323 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 22; RUN: llc < %s -mtriple=armv7-none-linux-gnueabi | FileCheck %s --check-prefixes=CHECK,CHECK-V73; RUN: llc < %s -mtriple=armv8-none-linux-gnueabi | FileCheck %s -check-prefixes=CHECK,CHECK-V84 5 6define i32 @f(i32 %a, i32 %b) nounwind ssp {7; CHECK-LABEL: f:8; CHECK: @ %bb.0: @ %entry9; CHECK-NEXT: subs r0, r0, r110; CHECK-NEXT: movle r0, #011; CHECK-NEXT: bx lr12entry:13 %cmp = icmp sgt i32 %a, %b14 %sub = sub nsw i32 %a, %b15 %sub. = select i1 %cmp, i32 %sub, i32 016 ret i32 %sub.17}18 19define i32 @g(i32 %a, i32 %b) nounwind ssp {20; CHECK-LABEL: g:21; CHECK: @ %bb.0: @ %entry22; CHECK-NEXT: subs r0, r1, r023; CHECK-NEXT: movle r0, #024; CHECK-NEXT: bx lr25entry:26 %cmp = icmp slt i32 %a, %b27 %sub = sub nsw i32 %b, %a28 %sub. = select i1 %cmp, i32 %sub, i32 029 ret i32 %sub.30}31 32define i32 @h(i32 %a, i32 %b) nounwind ssp {33; CHECK-LABEL: h:34; CHECK: @ %bb.0: @ %entry35; CHECK-NEXT: subs r0, r0, #336; CHECK-NEXT: movle r0, r137; CHECK-NEXT: bx lr38entry:39 %cmp = icmp sgt i32 %a, 340 %sub = sub nsw i32 %a, 341 %sub. = select i1 %cmp, i32 %sub, i32 %b42 ret i32 %sub.43}44 45; rdar://1172596546define i32 @i(i32 %a, i32 %b) nounwind readnone ssp {47; CHECK-LABEL: i:48; CHECK: @ %bb.0: @ %entry49; CHECK-NEXT: subs r0, r1, r050; CHECK-NEXT: movls r0, #051; CHECK-NEXT: bx lr52entry:53 %cmp = icmp ult i32 %a, %b54 %sub = sub i32 %b, %a55 %sub. = select i1 %cmp, i32 %sub, i32 056 ret i32 %sub.57}58 59; If CPSR is live-out, we can't remove cmp if there exists60; a swapped sub.61define i32 @j(i32 %a, i32 %b) nounwind {62; CHECK-LABEL: j:63; CHECK: @ %bb.0: @ %entry64; CHECK-NEXT: subs r1, r0, r165; CHECK-NEXT: movlt r0, r166; CHECK-NEXT: movne r0, r167; CHECK-NEXT: bx lr68entry:69 %cmp = icmp eq i32 %b, %a70 %sub = sub nsw i32 %a, %b71 br i1 %cmp, label %if.then, label %if.else72 73if.then:74 %cmp2 = icmp sgt i32 %b, %a75 %sel = select i1 %cmp2, i32 %sub, i32 %a76 ret i32 %sel77 78if.else:79 ret i32 %sub80}81 82; If the sub/rsb instruction is predicated, we can't use the flags.83; <rdar://problem/12263428>84; Test case from MultiSource/Benchmarks/Ptrdist/bc/number.s85define i32 @bc_raise(i1 %cond) nounwind ssp {86; CHECK-LABEL: bc_raise:87; CHECK: @ %bb.0: @ %entry88; CHECK-NEXT: mov r1, #189; CHECK-NEXT: tst r0, #190; CHECK-NEXT: bic r1, r1, r091; CHECK-NEXT: mov r0, #2392; CHECK-NEXT: rsbeq r1, r1, #093; CHECK-NEXT: cmp r1, #094; CHECK-NEXT: movweq r0, #1795; CHECK-NEXT: bx lr96entry:97 %val.2.i = select i1 %cond, i32 0, i32 198 %sub.i = sub nsw i32 0, %val.2.i99 %retval.0.i = select i1 %cond, i32 %val.2.i, i32 %sub.i100 %cmp1 = icmp eq i32 %retval.0.i, 0101 br i1 %cmp1, label %land.lhs.true, label %if.end11102 103land.lhs.true: ; preds = %num2long.exit104 ret i32 17105 106if.end11: ; preds = %num2long.exit107 ret i32 23108}109 110; When considering the producer of cmp's src as the subsuming instruction,111; only consider that when the comparison is to 0.112define i32 @cmp_src_nonzero(i32 %a, i32 %b, i32 %x, i32 %y) {113; CHECK-LABEL: cmp_src_nonzero:114; CHECK: @ %bb.0: @ %entry115; CHECK-NEXT: sub r0, r0, r1116; CHECK-NEXT: cmp r0, #17117; CHECK-NEXT: movne r2, r3118; CHECK-NEXT: mov r0, r2119; CHECK-NEXT: bx lr120entry:121 %sub = sub i32 %a, %b122 %cmp = icmp eq i32 %sub, 17123 %ret = select i1 %cmp, i32 %x, i32 %y124 ret i32 %ret125}126 127define float @float_sel(i32 %a, i32 %b, float %x, float %y) {128; CHECK-V7-LABEL: float_sel:129; CHECK-V7: @ %bb.0: @ %entry130; CHECK-V7-NEXT: vmov s2, r2131; CHECK-V7-NEXT: subs r0, r0, r1132; CHECK-V7-NEXT: vmov s0, r3133; CHECK-V7-NEXT: vmoveq.f32 s0, s2134; CHECK-V7-NEXT: vmov r0, s0135; CHECK-V7-NEXT: bx lr136;137; CHECK-V8-LABEL: float_sel:138; CHECK-V8: @ %bb.0: @ %entry139; CHECK-V8-NEXT: subs r0, r0, r1140; CHECK-V8-NEXT: vmov s0, r3141; CHECK-V8-NEXT: vmov s2, r2142; CHECK-V8-NEXT: vseleq.f32 s0, s2, s0143; CHECK-V8-NEXT: vmov r0, s0144; CHECK-V8-NEXT: bx lr145entry:146 %sub = sub i32 %a, %b147 %cmp = icmp eq i32 %sub, 0148 %ret = select i1 %cmp, float %x, float %y149 ret float %ret150}151 152define double @double_sel(i32 %a, i32 %b, double %x, double %y) {153; CHECK-V7-LABEL: double_sel:154; CHECK-V7: @ %bb.0: @ %entry155; CHECK-V7-NEXT: vmov d17, r2, r3156; CHECK-V7-NEXT: vldr d16, [sp]157; CHECK-V7-NEXT: subs r0, r0, r1158; CHECK-V7-NEXT: vmoveq.f64 d16, d17159; CHECK-V7-NEXT: vmov r0, r1, d16160; CHECK-V7-NEXT: bx lr161;162; CHECK-V8-LABEL: double_sel:163; CHECK-V8: @ %bb.0: @ %entry164; CHECK-V8-NEXT: vldr d16, [sp]165; CHECK-V8-NEXT: vmov d17, r2, r3166; CHECK-V8-NEXT: subs r0, r0, r1167; CHECK-V8-NEXT: vseleq.f64 d16, d17, d16168; CHECK-V8-NEXT: vmov r0, r1, d16169; CHECK-V8-NEXT: bx lr170entry:171 %sub = sub i32 %a, %b172 %cmp = icmp eq i32 %sub, 0173 %ret = select i1 %cmp, double %x, double %y174 ret double %ret175}176 177@t = common global i32 0178define double @double_sub(i32 %a, i32 %b, double %x, double %y) {179; CHECK-V7-LABEL: double_sub:180; CHECK-V7: @ %bb.0: @ %entry181; CHECK-V7-NEXT: vmov d17, r2, r3182; CHECK-V7-NEXT: cmp r0, r1183; CHECK-V7-NEXT: vldr d16, [sp]184; CHECK-V7-NEXT: sub r0, r0, r1185; CHECK-V7-NEXT: vmovgt.f64 d16, d17186; CHECK-V7-NEXT: movw r1, :lower16:t187; CHECK-V7-NEXT: movt r1, :upper16:t188; CHECK-V7-NEXT: str r0, [r1]189; CHECK-V7-NEXT: vmov r2, r3, d16190; CHECK-V7-NEXT: mov r0, r2191; CHECK-V7-NEXT: mov r1, r3192; CHECK-V7-NEXT: bx lr193;194; CHECK-V8-LABEL: double_sub:195; CHECK-V8: @ %bb.0: @ %entry196; CHECK-V8-NEXT: vldr d16, [sp]197; CHECK-V8-NEXT: cmp r0, r1198; CHECK-V8-NEXT: vmov d17, r2, r3199; CHECK-V8-NEXT: sub r0, r0, r1200; CHECK-V8-NEXT: vselgt.f64 d16, d17, d16201; CHECK-V8-NEXT: movw r1, :lower16:t202; CHECK-V8-NEXT: vmov r2, r3, d16203; CHECK-V8-NEXT: movt r1, :upper16:t204; CHECK-V8-NEXT: str r0, [r1]205; CHECK-V8-NEXT: mov r0, r2206; CHECK-V8-NEXT: mov r1, r3207; CHECK-V8-NEXT: bx lr208entry:209 %cmp = icmp sgt i32 %a, %b210 %sub = sub i32 %a, %b211 store i32 %sub, ptr @t212 %ret = select i1 %cmp, double %x, double %y213 ret double %ret214}215 216define double @double_sub_swap(i32 %a, i32 %b, double %x, double %y) {217; CHECK-V7-LABEL: double_sub_swap:218; CHECK-V7: @ %bb.0: @ %entry219; CHECK-V7-NEXT: vmov d17, r2, r3220; CHECK-V7-NEXT: cmp r1, r0221; CHECK-V7-NEXT: vldr d16, [sp]222; CHECK-V7-NEXT: sub r0, r1, r0223; CHECK-V7-NEXT: vmovlt.f64 d16, d17224; CHECK-V7-NEXT: movw r1, :lower16:t225; CHECK-V7-NEXT: movt r1, :upper16:t226; CHECK-V7-NEXT: str r0, [r1]227; CHECK-V7-NEXT: vmov r2, r3, d16228; CHECK-V7-NEXT: mov r0, r2229; CHECK-V7-NEXT: mov r1, r3230; CHECK-V7-NEXT: bx lr231;232; CHECK-V8-LABEL: double_sub_swap:233; CHECK-V8: @ %bb.0: @ %entry234; CHECK-V8-NEXT: vldr d16, [sp]235; CHECK-V8-NEXT: cmp r1, r0236; CHECK-V8-NEXT: vmov d17, r2, r3237; CHECK-V8-NEXT: sub r0, r1, r0238; CHECK-V8-NEXT: vselge.f64 d16, d16, d17239; CHECK-V8-NEXT: movw r1, :lower16:t240; CHECK-V8-NEXT: vmov r2, r3, d16241; CHECK-V8-NEXT: movt r1, :upper16:t242; CHECK-V8-NEXT: str r0, [r1]243; CHECK-V8-NEXT: mov r0, r2244; CHECK-V8-NEXT: mov r1, r3245; CHECK-V8-NEXT: bx lr246entry:247 %cmp = icmp sgt i32 %a, %b248 %sub = sub i32 %b, %a249 %ret = select i1 %cmp, double %x, double %y250 store i32 %sub, ptr @t251 ret double %ret252}253 254declare void @abort()255declare void @exit(i32)256 257; If the comparison uses the V bit (signed overflow/underflow), we can't258; omit the comparison.259define i32 @cmp_slt0(i32 %a, i32 %b, i32 %x, i32 %y) {260; CHECK-LABEL: cmp_slt0:261; CHECK: @ %bb.0: @ %entry262; CHECK-NEXT: .save {r11, lr}263; CHECK-NEXT: push {r11, lr}264; CHECK-NEXT: movw r0, :lower16:t265; CHECK-NEXT: movt r0, :upper16:t266; CHECK-NEXT: ldr r0, [r0]267; CHECK-NEXT: sub r0, r0, #17268; CHECK-NEXT: cmn r0, #1269; CHECK-NEXT: ble .LBB11_2270; CHECK-NEXT: @ %bb.1: @ %if.else271; CHECK-NEXT: mov r0, #0272; CHECK-NEXT: bl exit273; CHECK-NEXT: .LBB11_2: @ %if.then274; CHECK-NEXT: bl abort275entry:276 %load = load i32, ptr @t, align 4277 %sub = sub i32 %load, 17278 %cmp = icmp slt i32 %sub, 0279 br i1 %cmp, label %if.then, label %if.else280 281if.then:282 call void @abort()283 unreachable284 285if.else:286 call void @exit(i32 0)287 unreachable288}289 290; Same for the C bit. (Note the ult X, 0 is trivially291; false, so the DAG combiner may or may not optimize it).292define i32 @cmp_ult0(i32 %a, i32 %b, i32 %x, i32 %y) {293; CHECK-LABEL: cmp_ult0:294; CHECK: @ %bb.0: @ %entry295; CHECK-NEXT: .save {r11, lr}296; CHECK-NEXT: push {r11, lr}297; CHECK-NEXT: movw r0, :lower16:t298; CHECK-NEXT: movt r0, :upper16:t299; CHECK-NEXT: ldr r0, [r0]300; CHECK-NEXT: sub r0, r0, #17301; CHECK-NEXT: cmp r0, #0302; CHECK-NEXT: bhs .LBB12_2303; CHECK-NEXT: @ %bb.1: @ %if.then304; CHECK-NEXT: bl abort305; CHECK-NEXT: .LBB12_2: @ %if.else306; CHECK-NEXT: mov r0, #0307; CHECK-NEXT: bl exit308entry:309 %load = load i32, ptr @t, align 4310 %sub = sub i32 %load, 17311 %cmp = icmp ult i32 %sub, 0312 br i1 %cmp, label %if.then, label %if.else313 314if.then:315 call void @abort()316 unreachable317 318if.else:319 call void @exit(i32 0)320 unreachable321}322 323