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 6 define i32 @f(i32 %a, i32 %b) nounwind ssp { 7 entry: 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 17 define i32 @g(i32 %a, i32 %b) nounwind ssp { 18 entry: 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 28 define i32 @h(i32 %a, i32 %b) nounwind ssp { 29 entry: 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 40 define i32 @i(i32 %a, i32 %b) nounwind readnone ssp { 41 entry: 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. 52 define i32 @j(i32 %a, i32 %b) nounwind { 53 entry: 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 61 if.then: 62 %cmp2 = icmp sgt i32 %b, %a 63 %sel = select i1 %cmp2, i32 %sub, i32 %a 64 ret i32 %sel 65 66 if.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 76 define i32 @bc_raise() nounwind ssp { 77 entry: 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 84 land.lhs.true: ; preds = %num2long.exit 85 ret i32 17 86 87 if.end11: ; preds = %num2long.exit 88 ret i32 23 89 } 90 91 ; When considering the producer of cmp's src as the subsuming instruction, 92 ; only consider that when the comparison is to 0. 93 define i32 @cmp_src_nonzero(i32 %a, i32 %b, i32 %x, i32 %y) { 94 entry: 95 ; CHECK-LABEL: cmp_src_nonzero: 96 ; CHECK: sub 97 ; CHECK: cmp 98 %sub = sub i32 %a, %b 99 %cmp = icmp eq i32 %sub, 17 100 %ret = select i1 %cmp, i32 %x, i32 %y 101 ret i32 %ret 102 } 103 104 define float @float_sel(i32 %a, i32 %b, float %x, float %y) { 105 entry: 106 ; CHECK-LABEL: float_sel: 107 ; CHECK-NOT: cmp 108 ; V8-LABEL: float_sel: 109 ; V8-NOT: cmp 110 ; V8: vseleq.f32 111 %sub = sub i32 %a, %b 112 %cmp = icmp eq i32 %sub, 0 113 %ret = select i1 %cmp, float %x, float %y 114 ret float %ret 115 } 116 117 define double @double_sel(i32 %a, i32 %b, double %x, double %y) { 118 entry: 119 ; CHECK-LABEL: double_sel: 120 ; CHECK-NOT: cmp 121 ; V8-LABEL: double_sel: 122 ; V8-NOT: cmp 123 ; V8: vseleq.f64 124 %sub = sub i32 %a, %b 125 %cmp = icmp eq i32 %sub, 0 126 %ret = select i1 %cmp, double %x, double %y 127 ret double %ret 128 } 129 130 @t = common global i32 0 131 define double @double_sub(i32 %a, i32 %b, double %x, double %y) { 132 entry: 133 ; CHECK-LABEL: double_sub: 134 ; CHECK: subs 135 ; CHECK-NOT: cmp 136 ; V8-LABEL: double_sub: 137 ; V8: vsel 138 %cmp = icmp sgt i32 %a, %b 139 %sub = sub i32 %a, %b 140 store i32 %sub, i32* @t 141 %ret = select i1 %cmp, double %x, double %y 142 ret double %ret 143 } 144 145 define double @double_sub_swap(i32 %a, i32 %b, double %x, double %y) { 146 entry: 147 ; V7-LABEL: double_sub_swap: 148 ; V7-NOT: cmp 149 ; V7: subs 150 ; V8-LABEL: double_sub_swap: 151 ; V8-NOT: subs 152 ; V8: cmp 153 ; V8: vsel 154 %cmp = icmp sgt i32 %a, %b 155 %sub = sub i32 %b, %a 156 %ret = select i1 %cmp, double %x, double %y 157 store i32 %sub, i32* @t 158 ret double %ret 159 } 160 161 declare void @abort() 162 declare void @exit(i32) 163 164 ; If the comparison uses the V bit (signed overflow/underflow), we can't 165 ; omit the comparison. 166 define i32 @cmp_slt0(i32 %a, i32 %b, i32 %x, i32 %y) { 167 entry: 168 ; CHECK-LABEL: cmp_slt0 169 ; CHECK: sub 170 ; CHECK: cmp 171 ; CHECK: bge 172 %load = load i32, i32* @t, align 4 173 %sub = sub i32 %load, 17 174 %cmp = icmp slt i32 %sub, 0 175 br i1 %cmp, label %if.then, label %if.else 176 177 if.then: 178 call void @abort() 179 unreachable 180 181 if.else: 182 call void @exit(i32 0) 183 unreachable 184 } 185 186 ; Same for the C bit. (Note the ult X, 0 is trivially 187 ; false, so the DAG combiner may or may not optimize it). 188 define i32 @cmp_ult0(i32 %a, i32 %b, i32 %x, i32 %y) { 189 entry: 190 ; CHECK-LABEL: cmp_ult0 191 ; CHECK: sub 192 ; CHECK: cmp 193 ; CHECK: bhs 194 %load = load i32, i32* @t, align 4 195 %sub = sub i32 %load, 17 196 %cmp = icmp ult i32 %sub, 0 197 br i1 %cmp, label %if.then, label %if.else 198 199 if.then: 200 call void @abort() 201 unreachable 202 203 if.else: 204 call void @exit(i32 0) 205 unreachable 206 } 207