1; RUN: llc < %s -mtriple=arm-apple-darwin | FileCheck %s 2; RUN: llc < %s -mtriple=arm-apple-darwin | FileCheck %s --check-prefix=V7 3; RUN: llc < %s -mtriple=armv8-none-linux-gnueabi | FileCheck %s -check-prefix=V8 4 5 6define i32 @f(i32 %a, i32 %b) nounwind ssp { 7entry: 8; CHECK-LABEL: f: 9; CHECK: subs 10; CHECK-NOT: cmp 11 %cmp = icmp sgt i32 %a, %b 12 %sub = sub nsw i32 %a, %b 13 %sub. = select i1 %cmp, i32 %sub, i32 0 14 ret i32 %sub. 15} 16 17define i32 @g(i32 %a, i32 %b) nounwind ssp { 18entry: 19; CHECK-LABEL: g: 20; CHECK: subs 21; CHECK-NOT: cmp 22 %cmp = icmp slt i32 %a, %b 23 %sub = sub nsw i32 %b, %a 24 %sub. = select i1 %cmp, i32 %sub, i32 0 25 ret i32 %sub. 26} 27 28define i32 @h(i32 %a, i32 %b) nounwind ssp { 29entry: 30; CHECK-LABEL: h: 31; CHECK: subs 32; CHECK-NOT: cmp 33 %cmp = icmp sgt i32 %a, 3 34 %sub = sub nsw i32 %a, 3 35 %sub. = select i1 %cmp, i32 %sub, i32 %b 36 ret i32 %sub. 37} 38 39; rdar://11725965 40define i32 @i(i32 %a, i32 %b) nounwind readnone ssp { 41entry: 42; CHECK-LABEL: i: 43; CHECK: subs 44; CHECK-NOT: cmp 45 %cmp = icmp ult i32 %a, %b 46 %sub = sub i32 %b, %a 47 %sub. = select i1 %cmp, i32 %sub, i32 0 48 ret i32 %sub. 49} 50; If CPSR is live-out, we can't remove cmp if there exists 51; a swapped sub. 52define i32 @j(i32 %a, i32 %b) nounwind { 53entry: 54; CHECK-LABEL: j: 55; CHECK: sub 56; CHECK: cmp 57 %cmp = icmp eq i32 %b, %a 58 %sub = sub nsw i32 %a, %b 59 br i1 %cmp, label %if.then, label %if.else 60 61if.then: 62 %cmp2 = icmp sgt i32 %b, %a 63 %sel = select i1 %cmp2, i32 %sub, i32 %a 64 ret i32 %sel 65 66if.else: 67 ret i32 %sub 68} 69 70; If the sub/rsb instruction is predicated, we can't use the flags. 71; <rdar://problem/12263428> 72; Test case from MultiSource/Benchmarks/Ptrdist/bc/number.s 73; CHECK: bc_raise 74; CHECK: rsbeq 75; CHECK: cmp 76define i32 @bc_raise() nounwind ssp { 77entry: 78 %val.2.i = select i1 undef, i32 0, i32 undef 79 %sub.i = sub nsw i32 0, %val.2.i 80 %retval.0.i = select i1 undef, i32 %val.2.i, i32 %sub.i 81 %cmp1 = icmp eq i32 %retval.0.i, 0 82 br i1 %cmp1, label %land.lhs.true, label %if.end11 83 84land.lhs.true: ; preds = %num2long.exit 85 ret i32 17 86 87if.end11: ; preds = %num2long.exit 88 ret i32 23 89} 90 91define float @float_sel(i32 %a, i32 %b, float %x, float %y) { 92entry: 93; CHECK-LABEL: float_sel: 94; CHECK-NOT: cmp 95; V8-LABEL: float_sel: 96; V8-NOT: cmp 97; V8: vseleq.f32 98 %sub = sub i32 %a, %b 99 %cmp = icmp eq i32 %sub, 0 100 %ret = select i1 %cmp, float %x, float %y 101 ret float %ret 102} 103 104define double @double_sel(i32 %a, i32 %b, double %x, double %y) { 105entry: 106; CHECK-LABEL: double_sel: 107; CHECK-NOT: cmp 108; V8-LABEL: double_sel: 109; V8-NOT: cmp 110; V8: vseleq.f64 111 %sub = sub i32 %a, %b 112 %cmp = icmp eq i32 %sub, 0 113 %ret = select i1 %cmp, double %x, double %y 114 ret double %ret 115} 116 117@t = common global i32 0 118define double @double_sub(i32 %a, i32 %b, double %x, double %y) { 119entry: 120; CHECK-LABEL: double_sub: 121; CHECK: subs 122; CHECK-NOT: cmp 123; V8-LABEL: double_sub: 124; V8: vsel 125 %cmp = icmp sgt i32 %a, %b 126 %sub = sub i32 %a, %b 127 store i32 %sub, i32* @t 128 %ret = select i1 %cmp, double %x, double %y 129 ret double %ret 130} 131 132define double @double_sub_swap(i32 %a, i32 %b, double %x, double %y) { 133entry: 134; V7-LABEL: double_sub_swap: 135; V7-NOT: cmp 136; V7: subs 137; V8-LABEL: double_sub_swap: 138; V8-NOT: subs 139; V8: cmp 140; V8: vsel 141 %cmp = icmp sgt i32 %a, %b 142 %sub = sub i32 %b, %a 143 %ret = select i1 %cmp, double %x, double %y 144 store i32 %sub, i32* @t 145 ret double %ret 146} 147