1; RUN: llc -O3 < %s | FileCheck %s 2target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-n32:64" 3target triple = "arm64-unknown-unknown" 4 5; CHECK-LABEL: foo1 6; CHECK: cinc w{{[0-9]+}}, w{{[0-9]+}}, ne 7define i32 @foo1(i32 %b, i32 %c) nounwind readnone ssp { 8entry: 9 %not.tobool = icmp ne i32 %c, 0 10 %add = zext i1 %not.tobool to i32 11 %b.add = add i32 %c, %b 12 %add1 = add i32 %b.add, %add 13 ret i32 %add1 14} 15 16; CHECK-LABEL: foo2 17; CHECK: cneg w{{[0-9]+}}, w{{[0-9]+}}, ne 18define i32 @foo2(i32 %b, i32 %c) nounwind readnone ssp { 19entry: 20 %mul = sub i32 0, %b 21 %tobool = icmp eq i32 %c, 0 22 %b.mul = select i1 %tobool, i32 %b, i32 %mul 23 %add = add nsw i32 %b.mul, %c 24 ret i32 %add 25} 26 27; CHECK-LABEL: foo3 28; CHECK: cinv w{{[0-9]+}}, w{{[0-9]+}}, ne 29define i32 @foo3(i32 %b, i32 %c) nounwind readnone ssp { 30entry: 31 %not.tobool = icmp ne i32 %c, 0 32 %xor = sext i1 %not.tobool to i32 33 %b.xor = xor i32 %xor, %b 34 %add = add nsw i32 %b.xor, %c 35 ret i32 %add 36} 37 38; rdar://11632325 39define i32@foo4(i32 %a) nounwind ssp { 40; CHECK-LABEL: foo4 41; CHECK: cneg 42; CHECK-NEXT: ret 43 %cmp = icmp sgt i32 %a, -1 44 %neg = sub nsw i32 0, %a 45 %cond = select i1 %cmp, i32 %a, i32 %neg 46 ret i32 %cond 47} 48 49define i32@foo5(i32 %a, i32 %b) nounwind ssp { 50entry: 51; CHECK-LABEL: foo5 52; CHECK: subs 53; CHECK-NEXT: cneg 54; CHECK-NEXT: ret 55 %sub = sub nsw i32 %a, %b 56 %cmp = icmp sgt i32 %sub, -1 57 %sub3 = sub nsw i32 0, %sub 58 %cond = select i1 %cmp, i32 %sub, i32 %sub3 59 ret i32 %cond 60} 61 62; make sure we can handle branch instruction in optimizeCompare. 63define i32@foo6(i32 %a, i32 %b) nounwind ssp { 64; CHECK-LABEL: foo6 65; CHECK: b 66 %sub = sub nsw i32 %a, %b 67 %cmp = icmp sgt i32 %sub, 0 68 br i1 %cmp, label %l.if, label %l.else 69 70l.if: 71 ret i32 1 72 73l.else: 74 ret i32 %sub 75} 76 77; If CPSR is used multiple times and V flag is used, we don't remove cmp. 78define i32 @foo7(i32 %a, i32 %b) nounwind { 79entry: 80; CHECK-LABEL: foo7: 81; CHECK: sub 82; CHECK-next: adds 83; CHECK-next: csneg 84; CHECK-next: b 85 %sub = sub nsw i32 %a, %b 86 %cmp = icmp sgt i32 %sub, -1 87 %sub3 = sub nsw i32 0, %sub 88 %cond = select i1 %cmp, i32 %sub, i32 %sub3 89 br i1 %cmp, label %if.then, label %if.else 90 91if.then: 92 %cmp2 = icmp slt i32 %sub, -1 93 %sel = select i1 %cmp2, i32 %cond, i32 %a 94 ret i32 %sel 95 96if.else: 97 ret i32 %cond 98} 99 100define i32 @foo8(i32 %v, i32 %a, i32 %b) nounwind readnone ssp { 101entry: 102; CHECK-LABEL: foo8: 103; CHECK: cmp w0, #0 104; CHECK: csinv w0, w1, w2, ne 105 %tobool = icmp eq i32 %v, 0 106 %neg = xor i32 -1, %b 107 %cond = select i1 %tobool, i32 %neg, i32 %a 108 ret i32 %cond 109} 110 111define i32 @foo9(i32 %v) nounwind readnone optsize ssp { 112entry: 113; CHECK-LABEL: foo9: 114; CHECK: cmp w0, #0 115; CHECK: orr w[[REG:[0-9]+]], wzr, #0x4 116; CHECK: cinv w0, w[[REG]], eq 117 %tobool = icmp ne i32 %v, 0 118 %cond = select i1 %tobool, i32 4, i32 -5 119 ret i32 %cond 120} 121 122define i64 @foo10(i64 %v) nounwind readnone optsize ssp { 123entry: 124; CHECK-LABEL: foo10: 125; CHECK: cmp x0, #0 126; CHECK: orr w[[REG:[0-9]+]], wzr, #0x4 127; CHECK: cinv x0, x[[REG]], eq 128 %tobool = icmp ne i64 %v, 0 129 %cond = select i1 %tobool, i64 4, i64 -5 130 ret i64 %cond 131} 132 133define i32 @foo11(i32 %v) nounwind readnone optsize ssp { 134entry: 135; CHECK-LABEL: foo11: 136; CHECK: cmp w0, #0 137; CHECK: orr w[[REG:[0-9]+]], wzr, #0x4 138; CHECK: cneg w0, w[[REG]], eq 139 %tobool = icmp ne i32 %v, 0 140 %cond = select i1 %tobool, i32 4, i32 -4 141 ret i32 %cond 142} 143 144define i64 @foo12(i64 %v) nounwind readnone optsize ssp { 145entry: 146; CHECK-LABEL: foo12: 147; CHECK: cmp x0, #0 148; CHECK: orr w[[REG:[0-9]+]], wzr, #0x4 149; CHECK: cneg x0, x[[REG]], eq 150 %tobool = icmp ne i64 %v, 0 151 %cond = select i1 %tobool, i64 4, i64 -4 152 ret i64 %cond 153} 154 155define i32 @foo13(i32 %v, i32 %a, i32 %b) nounwind readnone optsize ssp { 156entry: 157; CHECK-LABEL: foo13: 158; CHECK: cmp w0, #0 159; CHECK: csneg w0, w1, w2, ne 160 %tobool = icmp eq i32 %v, 0 161 %sub = sub i32 0, %b 162 %cond = select i1 %tobool, i32 %sub, i32 %a 163 ret i32 %cond 164} 165 166define i64 @foo14(i64 %v, i64 %a, i64 %b) nounwind readnone optsize ssp { 167entry: 168; CHECK-LABEL: foo14: 169; CHECK: cmp x0, #0 170; CHECK: csneg x0, x1, x2, ne 171 %tobool = icmp eq i64 %v, 0 172 %sub = sub i64 0, %b 173 %cond = select i1 %tobool, i64 %sub, i64 %a 174 ret i64 %cond 175} 176 177define i32 @foo15(i32 %a, i32 %b) nounwind readnone optsize ssp { 178entry: 179; CHECK-LABEL: foo15: 180; CHECK: cmp w0, w1 181; CHECK: orr w[[REG:[0-9]+]], wzr, #0x1 182; CHECK: cinc w0, w[[REG]], gt 183 %cmp = icmp sgt i32 %a, %b 184 %. = select i1 %cmp, i32 2, i32 1 185 ret i32 %. 186} 187 188define i32 @foo16(i32 %a, i32 %b) nounwind readnone optsize ssp { 189entry: 190; CHECK-LABEL: foo16: 191; CHECK: cmp w0, w1 192; CHECK: orr w[[REG:[0-9]+]], wzr, #0x1 193; CHECK: cinc w0, w[[REG]], le 194 %cmp = icmp sgt i32 %a, %b 195 %. = select i1 %cmp, i32 1, i32 2 196 ret i32 %. 197} 198 199define i64 @foo17(i64 %a, i64 %b) nounwind readnone optsize ssp { 200entry: 201; CHECK-LABEL: foo17: 202; CHECK: cmp x0, x1 203; CHECK: orr w[[REG:[0-9]+]], wzr, #0x1 204; CHECK: cinc x0, x[[REG]], gt 205 %cmp = icmp sgt i64 %a, %b 206 %. = select i1 %cmp, i64 2, i64 1 207 ret i64 %. 208} 209 210define i64 @foo18(i64 %a, i64 %b) nounwind readnone optsize ssp { 211entry: 212; CHECK-LABEL: foo18: 213; CHECK: cmp x0, x1 214; CHECK: orr w[[REG:[0-9]+]], wzr, #0x1 215; CHECK: cinc x0, x[[REG]], le 216 %cmp = icmp sgt i64 %a, %b 217 %. = select i1 %cmp, i64 1, i64 2 218 ret i64 %. 219} 220 221define i64 @foo19(i64 %a, i64 %b, i64 %c) { 222entry: 223; CHECK-LABEL: foo19: 224; CHECK: cinc x0, x2 225; CHECK-NOT: add 226 %cmp = icmp ult i64 %a, %b 227 %inc = zext i1 %cmp to i64 228 %inc.c = add i64 %inc, %c 229 ret i64 %inc.c 230} 231