1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc -debugify-and-strip-all-safe -O3 < %s | FileCheck %s 3target 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" 4target triple = "arm64-unknown-unknown" 5 6define i32 @foo1(i32 %b, i32 %c) nounwind readnone ssp { 7; CHECK-LABEL: foo1: 8; CHECK: // %bb.0: // %entry 9; CHECK-NEXT: cmp w1, #0 10; CHECK-NEXT: add w8, w1, w0 11; CHECK-NEXT: cinc w0, w8, ne 12; CHECK-NEXT: ret 13entry: 14 %not.tobool = icmp ne i32 %c, 0 15 %add = zext i1 %not.tobool to i32 16 %b.add = add i32 %c, %b 17 %add1 = add i32 %b.add, %add 18 ret i32 %add1 19} 20 21define i32 @foo2(i32 %b, i32 %c) nounwind readnone ssp { 22; CHECK-LABEL: foo2: 23; CHECK: // %bb.0: // %entry 24; CHECK-NEXT: cmp w1, #0 25; CHECK-NEXT: cneg w8, w0, ne 26; CHECK-NEXT: add w0, w8, w1 27; CHECK-NEXT: ret 28entry: 29 %mul = sub i32 0, %b 30 %tobool = icmp eq i32 %c, 0 31 %b.mul = select i1 %tobool, i32 %b, i32 %mul 32 %add = add nsw i32 %b.mul, %c 33 ret i32 %add 34} 35 36define i32 @foo3(i32 %b, i32 %c) nounwind readnone ssp { 37; CHECK-LABEL: foo3: 38; CHECK: // %bb.0: // %entry 39; CHECK-NEXT: cmp w1, #0 40; CHECK-NEXT: cinv w8, w0, ne 41; CHECK-NEXT: add w0, w8, w1 42; CHECK-NEXT: ret 43entry: 44 %not.tobool = icmp ne i32 %c, 0 45 %xor = sext i1 %not.tobool to i32 46 %b.xor = xor i32 %xor, %b 47 %add = add nsw i32 %b.xor, %c 48 ret i32 %add 49} 50 51; rdar://11632325 52define i32@foo4(i32 %a) nounwind ssp { 53; CHECK-LABEL: foo4: 54; CHECK: // %bb.0: 55; CHECK-NEXT: cmp w0, #0 56; CHECK-NEXT: cneg w0, w0, mi 57; CHECK-NEXT: ret 58 %cmp = icmp sgt i32 %a, -1 59 %neg = sub nsw i32 0, %a 60 %cond = select i1 %cmp, i32 %a, i32 %neg 61 ret i32 %cond 62} 63 64define i32@foo5(i32 %a, i32 %b) nounwind ssp { 65; CHECK-LABEL: foo5: 66; CHECK: // %bb.0: // %entry 67; CHECK-NEXT: subs w8, w0, w1 68; CHECK-NEXT: cneg w0, w8, mi 69; CHECK-NEXT: ret 70entry: 71 %sub = sub nsw i32 %a, %b 72 %cmp = icmp sgt i32 %sub, -1 73 %sub3 = sub nsw i32 0, %sub 74 %cond = select i1 %cmp, i32 %sub, i32 %sub3 75 ret i32 %cond 76} 77 78; make sure we can handle branch instruction in optimizeCompare. 79define i32@foo6(i32 %a, i32 %b) nounwind ssp { 80; CHECK-LABEL: foo6: 81; CHECK: // %bb.0: // %common.ret 82; CHECK-NEXT: subs w8, w0, w1 83; CHECK-NEXT: csinc w0, w8, wzr, le 84; CHECK-NEXT: ret 85 %sub = sub nsw i32 %a, %b 86 %cmp = icmp sgt i32 %sub, 0 87 br i1 %cmp, label %l.if, label %l.else 88 89l.if: 90 ret i32 1 91 92l.else: 93 ret i32 %sub 94} 95 96; If CPSR is used multiple times and V flag is used, we don't remove cmp. 97define i32 @foo7(i32 %a, i32 %b) nounwind { 98; CHECK-LABEL: foo7: 99; CHECK: // %bb.0: // %entry 100; CHECK-NEXT: subs w8, w0, w1 101; CHECK-NEXT: cneg w9, w8, mi 102; CHECK-NEXT: cmn w8, #1 103; CHECK-NEXT: csel w10, w9, w0, lt 104; CHECK-NEXT: cmp w8, #0 105; CHECK-NEXT: csel w0, w10, w9, ge 106; CHECK-NEXT: ret 107entry: 108 %sub = sub nsw i32 %a, %b 109 %cmp = icmp sgt i32 %sub, -1 110 %sub3 = sub nsw i32 0, %sub 111 %cond = select i1 %cmp, i32 %sub, i32 %sub3 112 br i1 %cmp, label %if.then, label %if.else 113 114if.then: 115 %cmp2 = icmp slt i32 %sub, -1 116 %sel = select i1 %cmp2, i32 %cond, i32 %a 117 ret i32 %sel 118 119if.else: 120 ret i32 %cond 121} 122 123define i32 @foo8(i32 %v, i32 %a, i32 %b) nounwind readnone ssp { 124; CHECK-LABEL: foo8: 125; CHECK: // %bb.0: // %entry 126; CHECK-NEXT: cmp w0, #0 127; CHECK-NEXT: csinv w0, w1, w2, ne 128; CHECK-NEXT: ret 129entry: 130 %tobool = icmp eq i32 %v, 0 131 %neg = xor i32 -1, %b 132 %cond = select i1 %tobool, i32 %neg, i32 %a 133 ret i32 %cond 134} 135 136define i32 @foo9(i32 %v) nounwind readnone optsize ssp { 137; CHECK-LABEL: foo9: 138; CHECK: // %bb.0: // %entry 139; CHECK-NEXT: mov w8, #4 // =0x4 140; CHECK-NEXT: cmp w0, #0 141; CHECK-NEXT: cinv w0, w8, eq 142; CHECK-NEXT: ret 143entry: 144 %tobool = icmp ne i32 %v, 0 145 %cond = select i1 %tobool, i32 4, i32 -5 146 ret i32 %cond 147} 148 149define i64 @foo10(i64 %v) nounwind readnone optsize ssp { 150; CHECK-LABEL: foo10: 151; CHECK: // %bb.0: // %entry 152; CHECK-NEXT: mov w8, #4 // =0x4 153; CHECK-NEXT: cmp x0, #0 154; CHECK-NEXT: cinv x0, x8, eq 155; CHECK-NEXT: ret 156entry: 157 %tobool = icmp ne i64 %v, 0 158 %cond = select i1 %tobool, i64 4, i64 -5 159 ret i64 %cond 160} 161 162define i32 @foo11(i32 %v) nounwind readnone optsize ssp { 163; CHECK-LABEL: foo11: 164; CHECK: // %bb.0: // %entry 165; CHECK-NEXT: mov w8, #4 // =0x4 166; CHECK-NEXT: cmp w0, #0 167; CHECK-NEXT: cneg w0, w8, eq 168; CHECK-NEXT: ret 169entry: 170 %tobool = icmp ne i32 %v, 0 171 %cond = select i1 %tobool, i32 4, i32 -4 172 ret i32 %cond 173} 174 175define i64 @foo12(i64 %v) nounwind readnone optsize ssp { 176; CHECK-LABEL: foo12: 177; CHECK: // %bb.0: // %entry 178; CHECK-NEXT: mov w8, #4 // =0x4 179; CHECK-NEXT: cmp x0, #0 180; CHECK-NEXT: cneg x0, x8, eq 181; CHECK-NEXT: ret 182entry: 183 %tobool = icmp ne i64 %v, 0 184 %cond = select i1 %tobool, i64 4, i64 -4 185 ret i64 %cond 186} 187 188define i32 @foo13(i32 %v, i32 %a, i32 %b) nounwind readnone optsize ssp { 189; CHECK-LABEL: foo13: 190; CHECK: // %bb.0: // %entry 191; CHECK-NEXT: cmp w0, #0 192; CHECK-NEXT: csneg w0, w1, w2, ne 193; CHECK-NEXT: ret 194entry: 195 %tobool = icmp eq i32 %v, 0 196 %sub = sub i32 0, %b 197 %cond = select i1 %tobool, i32 %sub, i32 %a 198 ret i32 %cond 199} 200 201define i64 @foo14(i64 %v, i64 %a, i64 %b) nounwind readnone optsize ssp { 202; CHECK-LABEL: foo14: 203; CHECK: // %bb.0: // %entry 204; CHECK-NEXT: cmp x0, #0 205; CHECK-NEXT: csneg x0, x1, x2, ne 206; CHECK-NEXT: ret 207entry: 208 %tobool = icmp eq i64 %v, 0 209 %sub = sub i64 0, %b 210 %cond = select i1 %tobool, i64 %sub, i64 %a 211 ret i64 %cond 212} 213 214define i32 @foo15(i32 %a, i32 %b) nounwind readnone optsize ssp { 215; CHECK-LABEL: foo15: 216; CHECK: // %bb.0: // %entry 217; CHECK-NEXT: mov w8, #1 // =0x1 218; CHECK-NEXT: cmp w0, w1 219; CHECK-NEXT: cinc w0, w8, gt 220; CHECK-NEXT: ret 221entry: 222 %cmp = icmp sgt i32 %a, %b 223 %. = select i1 %cmp, i32 2, i32 1 224 ret i32 %. 225} 226 227define i32 @foo16(i32 %a, i32 %b) nounwind readnone optsize ssp { 228; CHECK-LABEL: foo16: 229; CHECK: // %bb.0: // %entry 230; CHECK-NEXT: mov w8, #1 // =0x1 231; CHECK-NEXT: cmp w0, w1 232; CHECK-NEXT: cinc w0, w8, le 233; CHECK-NEXT: ret 234entry: 235 %cmp = icmp sgt i32 %a, %b 236 %. = select i1 %cmp, i32 1, i32 2 237 ret i32 %. 238} 239 240define i64 @foo17(i64 %a, i64 %b) nounwind readnone optsize ssp { 241; CHECK-LABEL: foo17: 242; CHECK: // %bb.0: // %entry 243; CHECK-NEXT: mov w8, #1 // =0x1 244; CHECK-NEXT: cmp x0, x1 245; CHECK-NEXT: cinc x0, x8, gt 246; CHECK-NEXT: ret 247entry: 248 %cmp = icmp sgt i64 %a, %b 249 %. = select i1 %cmp, i64 2, i64 1 250 ret i64 %. 251} 252 253define i64 @foo18(i64 %a, i64 %b) nounwind readnone optsize ssp { 254; CHECK-LABEL: foo18: 255; CHECK: // %bb.0: // %entry 256; CHECK-NEXT: mov w8, #1 // =0x1 257; CHECK-NEXT: cmp x0, x1 258; CHECK-NEXT: cinc x0, x8, le 259; CHECK-NEXT: ret 260entry: 261 %cmp = icmp sgt i64 %a, %b 262 %. = select i1 %cmp, i64 1, i64 2 263 ret i64 %. 264} 265 266; Regression test for TrueVal + 1 overflow 267define i64 @foo18_overflow1(i64 %a, i64 %b) nounwind readnone optsize ssp { 268; CHECK-LABEL: foo18_overflow1: 269; CHECK: // %bb.0: // %entry 270; CHECK-NEXT: mov x8, #9223372036854775807 // =0x7fffffffffffffff 271; CHECK-NEXT: cmp x0, x1 272; CHECK-NEXT: csel x0, x8, xzr, gt 273; CHECK-NEXT: ret 274entry: 275 %cmp = icmp sgt i64 %a, %b 276 %. = select i1 %cmp, i64 9223372036854775807, i64 0 277 ret i64 %. 278} 279 280; Regression test for FalseVal + 1 overflow 281define i64 @foo18_overflow2(i64 %a, i64 %b) nounwind readnone optsize ssp { 282; CHECK-LABEL: foo18_overflow2: 283; CHECK: // %bb.0: // %entry 284; CHECK-NEXT: mov x8, #9223372036854775807 // =0x7fffffffffffffff 285; CHECK-NEXT: cmp x0, x1 286; CHECK-NEXT: csel x0, xzr, x8, gt 287; CHECK-NEXT: ret 288entry: 289 %cmp = icmp sgt i64 %a, %b 290 %. = select i1 %cmp, i64 0, i64 9223372036854775807 291 ret i64 %. 292} 293 294; Regression test for FalseVal - TrueVal overflow 295define i64 @foo18_overflow3(i1 %cmp) nounwind readnone optsize ssp { 296; CHECK-LABEL: foo18_overflow3: 297; CHECK: // %bb.0: // %entry 298; CHECK-NEXT: mov x8, #-9223372036854775808 // =0x8000000000000000 299; CHECK-NEXT: tst w0, #0x1 300; CHECK-NEXT: csel x0, x8, xzr, ne 301; CHECK-NEXT: ret 302entry: 303 %. = select i1 %cmp, i64 -9223372036854775808, i64 0 304 ret i64 %. 305} 306 307; Regression test for TrueVal - FalseVal overflow 308define i64 @foo18_overflow4(i1 %cmp) nounwind readnone optsize ssp { 309; CHECK-LABEL: foo18_overflow4: 310; CHECK: // %bb.0: // %entry 311; CHECK-NEXT: mov x8, #-9223372036854775808 // =0x8000000000000000 312; CHECK-NEXT: tst w0, #0x1 313; CHECK-NEXT: csel x0, xzr, x8, ne 314; CHECK-NEXT: ret 315entry: 316 %. = select i1 %cmp, i64 0, i64 -9223372036854775808 317 ret i64 %. 318} 319 320define i64 @foo19(i64 %a, i64 %b, i64 %c) { 321; CHECK-LABEL: foo19: 322; CHECK: // %bb.0: // %entry 323; CHECK-NEXT: cmp x0, x1 324; CHECK-NEXT: cinc x0, x2, lo 325; CHECK-NEXT: ret 326entry: 327 %cmp = icmp ult i64 %a, %b 328 %inc = zext i1 %cmp to i64 329 %inc.c = add i64 %inc, %c 330 ret i64 %inc.c 331} 332 333define i32 @foo20(i32 %x) { 334; CHECK-LABEL: foo20: 335; CHECK: // %bb.0: 336; CHECK-NEXT: mov w8, #6 // =0x6 337; CHECK-NEXT: cmp w0, #5 338; CHECK-NEXT: csinc w0, w8, wzr, eq 339; CHECK-NEXT: ret 340 %cmp = icmp eq i32 %x, 5 341 %res = select i1 %cmp, i32 6, i32 1 342 ret i32 %res 343} 344 345define i64 @foo21(i64 %x) { 346; CHECK-LABEL: foo21: 347; CHECK: // %bb.0: 348; CHECK-NEXT: mov w8, #6 // =0x6 349; CHECK-NEXT: cmp x0, #5 350; CHECK-NEXT: csinc x0, x8, xzr, eq 351; CHECK-NEXT: ret 352 %cmp = icmp eq i64 %x, 5 353 %res = select i1 %cmp, i64 6, i64 1 354 ret i64 %res 355} 356 357define i32 @foo22(i32 %x) { 358; CHECK-LABEL: foo22: 359; CHECK: // %bb.0: 360; CHECK-NEXT: mov w8, #6 // =0x6 361; CHECK-NEXT: cmp w0, #5 362; CHECK-NEXT: csinc w0, w8, wzr, ne 363; CHECK-NEXT: ret 364 %cmp = icmp eq i32 %x, 5 365 %res = select i1 %cmp, i32 1, i32 6 366 ret i32 %res 367} 368 369define i64 @foo23(i64 %x) { 370; CHECK-LABEL: foo23: 371; CHECK: // %bb.0: 372; CHECK-NEXT: mov w8, #6 // =0x6 373; CHECK-NEXT: cmp x0, #5 374; CHECK-NEXT: csinc x0, x8, xzr, ne 375; CHECK-NEXT: ret 376 %cmp = icmp eq i64 %x, 5 377 %res = select i1 %cmp, i64 1, i64 6 378 ret i64 %res 379} 380 381define i16 @foo24(ptr nocapture readonly %A, ptr nocapture readonly %B) { 382; CHECK-LABEL: foo24: 383; CHECK: // %bb.0: // %entry 384; CHECK-NEXT: ldrb w8, [x0] 385; CHECK-NEXT: ldrb w9, [x1] 386; CHECK-NEXT: cmp w8, #3 387; CHECK-NEXT: cset w8, hi 388; CHECK-NEXT: cmp w9, #33 389; CHECK-NEXT: cinc w0, w8, hi 390; CHECK-NEXT: ret 391entry: 392 %0 = load i8, ptr %A, align 1 393 %cmp = icmp ugt i8 %0, 3 394 %conv1 = zext i1 %cmp to i16 395 %1 = load i8, ptr %B, align 1 396 %cmp4 = icmp ugt i8 %1, 33 397 %conv5 = zext i1 %cmp4 to i16 398 %add = add nuw nsw i16 %conv5, %conv1 399 ret i16 %add 400} 401 402define i64 @foo25(ptr nocapture readonly %A, ptr nocapture readonly %B) { 403; CHECK-LABEL: foo25: 404; CHECK: // %bb.0: // %entry 405; CHECK-NEXT: ldr x8, [x1] 406; CHECK-NEXT: ldr x9, [x0] 407; CHECK-NEXT: cmp x8, #33 408; CHECK-NEXT: cset w8, hi 409; CHECK-NEXT: cmp x9, #3 410; CHECK-NEXT: cinc x0, x8, hi 411; CHECK-NEXT: ret 412entry: 413 %0 = load i64, ptr %A, align 1 414 %cmp = icmp ugt i64 %0, 3 415 %conv1 = zext i1 %cmp to i64 416 %1 = load i64, ptr %B, align 1 417 %cmp4 = icmp ugt i64 %1, 33 418 %conv5 = zext i1 %cmp4 to i64 419 %add = add nuw nsw i64 %conv5, %conv1 420 ret i64 %add 421} 422 423define i32 @or(i32 %num, i32 %x) { 424; CHECK-LABEL: or: 425; CHECK: // %bb.0: // %entry 426; CHECK-NEXT: and w8, w0, #0xff00 427; CHECK-NEXT: cmp w1, #0 428; CHECK-NEXT: cinc w0, w8, ne 429; CHECK-NEXT: ret 430entry: 431 %and = and i32 %num, 65280 432 %tobool.not = icmp ne i32 %x, 0 433 %cond = zext i1 %tobool.not to i32 434 %or = or disjoint i32 %and, %cond 435 ret i32 %or 436} 437 438define i64 @or64(i64 %num, i64 %x) { 439; CHECK-LABEL: or64: 440; CHECK: // %bb.0: // %entry 441; CHECK-NEXT: and x8, x0, #0xff00 442; CHECK-NEXT: cmp x1, #0 443; CHECK-NEXT: cinc x0, x8, ne 444; CHECK-NEXT: ret 445entry: 446 %and = and i64 %num, 65280 447 %tobool.not = icmp ne i64 %x, 0 448 %conv = zext i1 %tobool.not to i64 449 %or = or disjoint i64 %and, %conv 450 ret i64 %or 451} 452 453define i32 @selor32(i32 %num, i32 %x) { 454; CHECK-LABEL: selor32: 455; CHECK: // %bb.0: // %entry 456; CHECK-NEXT: and w8, w0, #0xff00 457; CHECK-NEXT: cmp w1, #0 458; CHECK-NEXT: cinc w0, w8, ne 459; CHECK-NEXT: ret 460entry: 461 %and = and i32 %num, 65280 462 %tobool.not = icmp ne i32 %x, 0 463 %or = or disjoint i32 %and, 1 464 %sel = select i1 %tobool.not, i32 %or, i32 %and 465 ret i32 %sel 466} 467 468define i32 @selor32_2(i32 %num, i32 %x) { 469; CHECK-LABEL: selor32_2: 470; CHECK: // %bb.0: // %entry 471; CHECK-NEXT: and w8, w0, #0xff00 472; CHECK-NEXT: cmp w1, #0 473; CHECK-NEXT: orr w9, w8, #0x2 474; CHECK-NEXT: csel w0, w9, w8, ne 475; CHECK-NEXT: ret 476entry: 477 %and = and i32 %num, 65280 478 %tobool.not = icmp ne i32 %x, 0 479 %or = or disjoint i32 %and, 2 480 %sel = select i1 %tobool.not, i32 %or, i32 %and 481 ret i32 %sel 482} 483 484define i64 @selor64(i64 %num, i64 %x) { 485; CHECK-LABEL: selor64: 486; CHECK: // %bb.0: // %entry 487; CHECK-NEXT: and x8, x0, #0xff00 488; CHECK-NEXT: cmp x1, #0 489; CHECK-NEXT: cinc x0, x8, ne 490; CHECK-NEXT: ret 491entry: 492 %and = and i64 %num, 65280 493 %tobool.not = icmp ne i64 %x, 0 494 %or = or disjoint i64 %and, 1 495 %sel = select i1 %tobool.not, i64 %or, i64 %and 496 ret i64 %sel 497} 498 499; Same as above with disjoint but without knowing haveNoCommonBitsSet. 500define i64 @selor64_disjoint(i64 %num, i64 %x) { 501; CHECK-LABEL: selor64_disjoint: 502; CHECK: // %bb.0: // %entry 503; CHECK-NEXT: cmp x1, #0 504; CHECK-NEXT: cinc x0, x0, ne 505; CHECK-NEXT: ret 506entry: 507 %tobool.not = icmp ne i64 %x, 0 508 %or = or disjoint i64 %num, 1 509 %sel = select i1 %tobool.not, i64 %or, i64 %num 510 ret i64 %sel 511} 512