1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc < %s -mtriple=aarch64-- | FileCheck %s --check-prefixes=CHECK,SDISEL 3; RUN: llc < %s -mtriple=aarch64-- -global-isel | FileCheck %s --check-prefixes=CHECK,GISEL 4 5; Ensure chains of comparisons produce chains of `ccmp` 6 7; (x0 < x1) && (x2 > x3) 8define i32 @cmp_and2(i32 %0, i32 %1, i32 %2, i32 %3) { 9; SDISEL-LABEL: cmp_and2: 10; SDISEL: // %bb.0: 11; SDISEL-NEXT: cmp w0, w1 12; SDISEL-NEXT: ccmp w2, w3, #0, lo 13; SDISEL-NEXT: cset w0, hi 14; SDISEL-NEXT: ret 15; 16; GISEL-LABEL: cmp_and2: 17; GISEL: // %bb.0: 18; GISEL-NEXT: cmp w0, w1 19; GISEL-NEXT: cset w8, lo 20; GISEL-NEXT: cmp w2, w3 21; GISEL-NEXT: cset w9, hi 22; GISEL-NEXT: and w0, w8, w9 23; GISEL-NEXT: ret 24 %5 = icmp ult i32 %0, %1 25 %6 = icmp ugt i32 %2, %3 26 %7 = select i1 %5, i1 %6, i1 false 27 %8 = zext i1 %7 to i32 28 ret i32 %8 29} 30 31; (x0 < x1) && (x2 > x3) && (x4 != x5) 32define i32 @cmp_and3(i32 %0, i32 %1, i32 %2, i32 %3, i32 %4, i32 %5) { 33; SDISEL-LABEL: cmp_and3: 34; SDISEL: // %bb.0: 35; SDISEL-NEXT: cmp w0, w1 36; SDISEL-NEXT: ccmp w2, w3, #0, lo 37; SDISEL-NEXT: ccmp w4, w5, #4, hi 38; SDISEL-NEXT: cset w0, ne 39; SDISEL-NEXT: ret 40; 41; GISEL-LABEL: cmp_and3: 42; GISEL: // %bb.0: 43; GISEL-NEXT: cmp w0, w1 44; GISEL-NEXT: cset w8, lo 45; GISEL-NEXT: cmp w2, w3 46; GISEL-NEXT: cset w9, hi 47; GISEL-NEXT: cmp w4, w5 48; GISEL-NEXT: and w8, w8, w9 49; GISEL-NEXT: cset w9, ne 50; GISEL-NEXT: and w0, w8, w9 51; GISEL-NEXT: ret 52 %7 = icmp ult i32 %0, %1 53 %8 = icmp ugt i32 %2, %3 54 %9 = select i1 %7, i1 %8, i1 false 55 %10 = icmp ne i32 %4, %5 56 %11 = select i1 %9, i1 %10, i1 false 57 %12 = zext i1 %11 to i32 58 ret i32 %12 59} 60 61; (x0 < x1) && (x2 > x3) && (x4 != x5) && (x6 == x7) 62define i32 @cmp_and4(i32 %0, i32 %1, i32 %2, i32 %3, i32 %4, i32 %5, i32 %6, i32 %7) { 63; SDISEL-LABEL: cmp_and4: 64; SDISEL: // %bb.0: 65; SDISEL-NEXT: cmp w2, w3 66; SDISEL-NEXT: ccmp w0, w1, #2, hi 67; SDISEL-NEXT: ccmp w4, w5, #4, lo 68; SDISEL-NEXT: ccmp w6, w7, #0, ne 69; SDISEL-NEXT: cset w0, eq 70; SDISEL-NEXT: ret 71; 72; GISEL-LABEL: cmp_and4: 73; GISEL: // %bb.0: 74; GISEL-NEXT: cmp w2, w3 75; GISEL-NEXT: cset w8, hi 76; GISEL-NEXT: cmp w0, w1 77; GISEL-NEXT: cset w9, lo 78; GISEL-NEXT: cmp w4, w5 79; GISEL-NEXT: cset w10, ne 80; GISEL-NEXT: cmp w6, w7 81; GISEL-NEXT: and w8, w8, w9 82; GISEL-NEXT: cset w11, eq 83; GISEL-NEXT: and w9, w10, w11 84; GISEL-NEXT: and w0, w8, w9 85; GISEL-NEXT: ret 86 %9 = icmp ugt i32 %2, %3 87 %10 = icmp ult i32 %0, %1 88 %11 = select i1 %9, i1 %10, i1 false 89 %12 = icmp ne i32 %4, %5 90 %13 = select i1 %11, i1 %12, i1 false 91 %14 = icmp eq i32 %6, %7 92 %15 = select i1 %13, i1 %14, i1 false 93 %16 = zext i1 %15 to i32 94 ret i32 %16 95} 96 97; (x0 < x1) || (x2 > x3) 98define i32 @cmp_or2(i32 %0, i32 %1, i32 %2, i32 %3) { 99; SDISEL-LABEL: cmp_or2: 100; SDISEL: // %bb.0: 101; SDISEL-NEXT: cmp w0, w1 102; SDISEL-NEXT: ccmp w2, w3, #0, hs 103; SDISEL-NEXT: cset w0, ne 104; SDISEL-NEXT: ret 105; 106; GISEL-LABEL: cmp_or2: 107; GISEL: // %bb.0: 108; GISEL-NEXT: cmp w0, w1 109; GISEL-NEXT: cset w8, lo 110; GISEL-NEXT: cmp w2, w3 111; GISEL-NEXT: cset w9, ne 112; GISEL-NEXT: orr w8, w8, w9 113; GISEL-NEXT: and w0, w8, #0x1 114; GISEL-NEXT: ret 115 %5 = icmp ult i32 %0, %1 116 %6 = icmp ne i32 %2, %3 117 %7 = select i1 %5, i1 true, i1 %6 118 %8 = zext i1 %7 to i32 119 ret i32 %8 120} 121 122; (x0 < x1) || (x2 > x3) || (x4 != x5) 123define i32 @cmp_or3(i32 %0, i32 %1, i32 %2, i32 %3, i32 %4, i32 %5) { 124; SDISEL-LABEL: cmp_or3: 125; SDISEL: // %bb.0: 126; SDISEL-NEXT: cmp w0, w1 127; SDISEL-NEXT: ccmp w2, w3, #2, hs 128; SDISEL-NEXT: ccmp w4, w5, #0, ls 129; SDISEL-NEXT: cset w0, ne 130; SDISEL-NEXT: ret 131; 132; GISEL-LABEL: cmp_or3: 133; GISEL: // %bb.0: 134; GISEL-NEXT: cmp w0, w1 135; GISEL-NEXT: cset w8, lo 136; GISEL-NEXT: cmp w2, w3 137; GISEL-NEXT: cset w9, hi 138; GISEL-NEXT: cmp w4, w5 139; GISEL-NEXT: orr w8, w8, w9 140; GISEL-NEXT: cset w9, ne 141; GISEL-NEXT: orr w8, w8, w9 142; GISEL-NEXT: and w0, w8, #0x1 143; GISEL-NEXT: ret 144 %7 = icmp ult i32 %0, %1 145 %8 = icmp ugt i32 %2, %3 146 %9 = select i1 %7, i1 true, i1 %8 147 %10 = icmp ne i32 %4, %5 148 %11 = select i1 %9, i1 true, i1 %10 149 %12 = zext i1 %11 to i32 150 ret i32 %12 151} 152 153; (x0 < x1) || (x2 > x3) || (x4 != x5) || (x6 == x7) 154define i32 @cmp_or4(i32 %0, i32 %1, i32 %2, i32 %3, i32 %4, i32 %5, i32 %6, i32 %7) { 155; SDISEL-LABEL: cmp_or4: 156; SDISEL: // %bb.0: 157; SDISEL-NEXT: cmp w0, w1 158; SDISEL-NEXT: ccmp w2, w3, #2, hs 159; SDISEL-NEXT: ccmp w4, w5, #0, ls 160; SDISEL-NEXT: ccmp w6, w7, #4, eq 161; SDISEL-NEXT: cset w0, eq 162; SDISEL-NEXT: ret 163; 164; GISEL-LABEL: cmp_or4: 165; GISEL: // %bb.0: 166; GISEL-NEXT: cmp w0, w1 167; GISEL-NEXT: cset w8, lo 168; GISEL-NEXT: cmp w2, w3 169; GISEL-NEXT: cset w9, hi 170; GISEL-NEXT: cmp w4, w5 171; GISEL-NEXT: cset w10, ne 172; GISEL-NEXT: cmp w6, w7 173; GISEL-NEXT: orr w8, w8, w9 174; GISEL-NEXT: cset w11, eq 175; GISEL-NEXT: orr w9, w10, w11 176; GISEL-NEXT: orr w8, w8, w9 177; GISEL-NEXT: and w0, w8, #0x1 178; GISEL-NEXT: ret 179 %9 = icmp ult i32 %0, %1 180 %10 = icmp ugt i32 %2, %3 181 %11 = select i1 %9, i1 true, i1 %10 182 %12 = icmp ne i32 %4, %5 183 %13 = select i1 %11, i1 true, i1 %12 184 %14 = icmp eq i32 %6, %7 185 %15 = select i1 %13, i1 true, i1 %14 186 %16 = zext i1 %15 to i32 187 ret i32 %16 188} 189 190; (x0 != 0) || (x1 != 0) 191define i32 @true_or2(i32 %0, i32 %1) { 192; SDISEL-LABEL: true_or2: 193; SDISEL: // %bb.0: 194; SDISEL-NEXT: orr w8, w0, w1 195; SDISEL-NEXT: cmp w8, #0 196; SDISEL-NEXT: cset w0, ne 197; SDISEL-NEXT: ret 198; 199; GISEL-LABEL: true_or2: 200; GISEL: // %bb.0: 201; GISEL-NEXT: cmp w0, #0 202; GISEL-NEXT: cset w8, ne 203; GISEL-NEXT: cmp w1, #0 204; GISEL-NEXT: cset w9, ne 205; GISEL-NEXT: orr w8, w8, w9 206; GISEL-NEXT: and w0, w8, #0x1 207; GISEL-NEXT: ret 208 %3 = icmp ne i32 %0, 0 209 %4 = icmp ne i32 %1, 0 210 %5 = select i1 %3, i1 true, i1 %4 211 %6 = zext i1 %5 to i32 212 ret i32 %6 213} 214 215; (x0 != 0) || (x1 != 0) || (x2 != 0) 216define i32 @true_or3(i32 %0, i32 %1, i32 %2) { 217; SDISEL-LABEL: true_or3: 218; SDISEL: // %bb.0: 219; SDISEL-NEXT: orr w8, w0, w1 220; SDISEL-NEXT: orr w8, w8, w2 221; SDISEL-NEXT: cmp w8, #0 222; SDISEL-NEXT: cset w0, ne 223; SDISEL-NEXT: ret 224; 225; GISEL-LABEL: true_or3: 226; GISEL: // %bb.0: 227; GISEL-NEXT: cmp w0, #0 228; GISEL-NEXT: cset w8, ne 229; GISEL-NEXT: cmp w1, #0 230; GISEL-NEXT: cset w9, ne 231; GISEL-NEXT: cmp w2, #0 232; GISEL-NEXT: orr w8, w8, w9 233; GISEL-NEXT: cset w9, ne 234; GISEL-NEXT: orr w8, w8, w9 235; GISEL-NEXT: and w0, w8, #0x1 236; GISEL-NEXT: ret 237 %4 = icmp ne i32 %0, 0 238 %5 = icmp ne i32 %1, 0 239 %6 = select i1 %4, i1 true, i1 %5 240 %7 = icmp ne i32 %2, 0 241 %8 = select i1 %6, i1 true, i1 %7 242 %9 = zext i1 %8 to i32 243 ret i32 %9 244} 245 246; (b > -3 && a < c) 247define i32 @neg_range_int(i32 %a, i32 %b, i32 %c) { 248; CHECK-LABEL: neg_range_int: 249; CHECK: // %bb.0: 250; CHECK-NEXT: cmp w0, w2 251; CHECK-NEXT: ccmn w1, #3, #4, lt 252; CHECK-NEXT: csel w0, w1, w0, gt 253; CHECK-NEXT: ret 254 %cmp = icmp sgt i32 %b, -3 255 %cmp1 = icmp slt i32 %a, %c 256 %or.cond = and i1 %cmp, %cmp1 257 %retval.0 = select i1 %or.cond, i32 %b, i32 %a 258 ret i32 %retval.0 259} 260 261; (b > -(d | 1) && a < c) 262define i32 @neg_range_int_comp(i32 %a, i32 %b, i32 %c, i32 %d) { 263; SDISEL-LABEL: neg_range_int_comp: 264; SDISEL: // %bb.0: 265; SDISEL-NEXT: orr w8, w3, #0x1 266; SDISEL-NEXT: cmp w0, w2 267; SDISEL-NEXT: ccmn w1, w8, #4, lt 268; SDISEL-NEXT: csel w0, w1, w0, gt 269; SDISEL-NEXT: ret 270; 271; GISEL-LABEL: neg_range_int_comp: 272; GISEL: // %bb.0: 273; GISEL-NEXT: orr w8, w3, #0x1 274; GISEL-NEXT: cmp w0, w2 275; GISEL-NEXT: neg w8, w8 276; GISEL-NEXT: ccmp w1, w8, #4, lt 277; GISEL-NEXT: csel w0, w1, w0, gt 278; GISEL-NEXT: ret 279 %dor = or i32 %d, 1 280 %negd = sub i32 0, %dor 281 %cmp = icmp sgt i32 %b, %negd 282 %cmp1 = icmp slt i32 %a, %c 283 %or.cond = and i1 %cmp, %cmp1 284 %retval.0 = select i1 %or.cond, i32 %b, i32 %a 285 ret i32 %retval.0 286} 287 288; (b >u -(d | 1) && a < c) 289define i32 @neg_range_int_comp_u(i32 %a, i32 %b, i32 %c, i32 %d) { 290; SDISEL-LABEL: neg_range_int_comp_u: 291; SDISEL: // %bb.0: 292; SDISEL-NEXT: orr w8, w3, #0x1 293; SDISEL-NEXT: cmp w0, w2 294; SDISEL-NEXT: ccmn w1, w8, #0, lt 295; SDISEL-NEXT: csel w0, w1, w0, hi 296; SDISEL-NEXT: ret 297; 298; GISEL-LABEL: neg_range_int_comp_u: 299; GISEL: // %bb.0: 300; GISEL-NEXT: orr w8, w3, #0x1 301; GISEL-NEXT: cmp w0, w2 302; GISEL-NEXT: neg w8, w8 303; GISEL-NEXT: ccmp w1, w8, #0, lt 304; GISEL-NEXT: csel w0, w1, w0, hi 305; GISEL-NEXT: ret 306 %dor = or i32 %d, 1 307 %negd = sub i32 0, %dor 308 %cmp = icmp ugt i32 %b, %negd 309 %cmp1 = icmp slt i32 %a, %c 310 %or.cond = and i1 %cmp, %cmp1 311 %retval.0 = select i1 %or.cond, i32 %b, i32 %a 312 ret i32 %retval.0 313} 314 315; (b > -(d | 1) && a u < c) 316define i32 @neg_range_int_comp_ua(i32 %a, i32 %b, i32 %c, i32 %d) { 317; SDISEL-LABEL: neg_range_int_comp_ua: 318; SDISEL: // %bb.0: 319; SDISEL-NEXT: orr w8, w3, #0x1 320; SDISEL-NEXT: cmp w0, w2 321; SDISEL-NEXT: ccmn w1, w8, #4, lo 322; SDISEL-NEXT: csel w0, w1, w0, gt 323; SDISEL-NEXT: ret 324; 325; GISEL-LABEL: neg_range_int_comp_ua: 326; GISEL: // %bb.0: 327; GISEL-NEXT: orr w8, w3, #0x1 328; GISEL-NEXT: cmp w0, w2 329; GISEL-NEXT: neg w8, w8 330; GISEL-NEXT: ccmp w1, w8, #4, lo 331; GISEL-NEXT: csel w0, w1, w0, gt 332; GISEL-NEXT: ret 333 %dor = or i32 %d, 1 334 %negd = sub i32 0, %dor 335 %cmp = icmp sgt i32 %b, %negd 336 %cmp1 = icmp ult i32 %a, %c 337 %or.cond = and i1 %cmp, %cmp1 338 %retval.0 = select i1 %or.cond, i32 %b, i32 %a 339 ret i32 %retval.0 340} 341 342; (b <= -3 && a > c) 343define i32 @neg_range_int_2(i32 %a, i32 %b, i32 %c) { 344; SDISEL-LABEL: neg_range_int_2: 345; SDISEL: // %bb.0: 346; SDISEL-NEXT: cmp w0, w2 347; SDISEL-NEXT: ccmn w1, #4, #4, gt 348; SDISEL-NEXT: csel w0, w1, w0, gt 349; SDISEL-NEXT: ret 350; 351; GISEL-LABEL: neg_range_int_2: 352; GISEL: // %bb.0: 353; GISEL-NEXT: cmp w0, w2 354; GISEL-NEXT: ccmn w1, #3, #8, gt 355; GISEL-NEXT: csel w0, w1, w0, ge 356; GISEL-NEXT: ret 357 %cmp = icmp sge i32 %b, -3 358 %cmp1 = icmp sgt i32 %a, %c 359 %or.cond = and i1 %cmp, %cmp1 360 %retval.0 = select i1 %or.cond, i32 %b, i32 %a 361 ret i32 %retval.0 362} 363 364; (b < -(d | 1) && a >= c) 365define i32 @neg_range_int_comp2(i32 %a, i32 %b, i32 %c, i32 %d) { 366; SDISEL-LABEL: neg_range_int_comp2: 367; SDISEL: // %bb.0: 368; SDISEL-NEXT: orr w8, w3, #0x1 369; SDISEL-NEXT: cmp w0, w2 370; SDISEL-NEXT: ccmn w1, w8, #0, ge 371; SDISEL-NEXT: csel w0, w1, w0, lt 372; SDISEL-NEXT: ret 373; 374; GISEL-LABEL: neg_range_int_comp2: 375; GISEL: // %bb.0: 376; GISEL-NEXT: orr w8, w3, #0x1 377; GISEL-NEXT: cmp w0, w2 378; GISEL-NEXT: neg w8, w8 379; GISEL-NEXT: ccmp w1, w8, #0, ge 380; GISEL-NEXT: csel w0, w1, w0, lt 381; GISEL-NEXT: ret 382 %dor = or i32 %d, 1 383 %negd = sub i32 0, %dor 384 %cmp = icmp slt i32 %b, %negd 385 %cmp1 = icmp sge i32 %a, %c 386 %or.cond = and i1 %cmp, %cmp1 387 %retval.0 = select i1 %or.cond, i32 %b, i32 %a 388 ret i32 %retval.0 389} 390 391; (b <u -(d | 1) && a > c) 392define i32 @neg_range_int_comp_u2(i32 %a, i32 %b, i32 %c, i32 %d) { 393; SDISEL-LABEL: neg_range_int_comp_u2: 394; SDISEL: // %bb.0: 395; SDISEL-NEXT: orr w8, w3, #0x1 396; SDISEL-NEXT: cmp w0, w2 397; SDISEL-NEXT: ccmn w1, w8, #2, gt 398; SDISEL-NEXT: csel w0, w1, w0, lo 399; SDISEL-NEXT: ret 400; 401; GISEL-LABEL: neg_range_int_comp_u2: 402; GISEL: // %bb.0: 403; GISEL-NEXT: orr w8, w3, #0x1 404; GISEL-NEXT: cmp w0, w2 405; GISEL-NEXT: neg w8, w8 406; GISEL-NEXT: ccmp w1, w8, #2, gt 407; GISEL-NEXT: csel w0, w1, w0, lo 408; GISEL-NEXT: ret 409 %dor = or i32 %d, 1 410 %negd = sub i32 0, %dor 411 %cmp = icmp ult i32 %b, %negd 412 %cmp1 = icmp sgt i32 %a, %c 413 %or.cond = and i1 %cmp, %cmp1 414 %retval.0 = select i1 %or.cond, i32 %b, i32 %a 415 ret i32 %retval.0 416} 417 418; (b > -(d | 1) && a u > c) 419define i32 @neg_range_int_comp_ua2(i32 %a, i32 %b, i32 %c, i32 %d) { 420; SDISEL-LABEL: neg_range_int_comp_ua2: 421; SDISEL: // %bb.0: 422; SDISEL-NEXT: orr w8, w3, #0x1 423; SDISEL-NEXT: cmp w0, w2 424; SDISEL-NEXT: ccmn w1, w8, #4, hi 425; SDISEL-NEXT: csel w0, w1, w0, gt 426; SDISEL-NEXT: ret 427; 428; GISEL-LABEL: neg_range_int_comp_ua2: 429; GISEL: // %bb.0: 430; GISEL-NEXT: orr w8, w3, #0x1 431; GISEL-NEXT: cmp w0, w2 432; GISEL-NEXT: neg w8, w8 433; GISEL-NEXT: ccmp w1, w8, #4, hi 434; GISEL-NEXT: csel w0, w1, w0, gt 435; GISEL-NEXT: ret 436 %dor = or i32 %d, 1 437 %negd = sub i32 0, %dor 438 %cmp = icmp sgt i32 %b, %negd 439 %cmp1 = icmp ugt i32 %a, %c 440 %or.cond = and i1 %cmp, %cmp1 441 %retval.0 = select i1 %or.cond, i32 %b, i32 %a 442 ret i32 %retval.0 443} 444 445; (b > -(d | 1) && a u == c) 446define i32 @neg_range_int_comp_ua3(i32 %a, i32 %b, i32 %c, i32 %d) { 447; SDISEL-LABEL: neg_range_int_comp_ua3: 448; SDISEL: // %bb.0: 449; SDISEL-NEXT: orr w8, w3, #0x1 450; SDISEL-NEXT: cmp w0, w2 451; SDISEL-NEXT: ccmn w1, w8, #4, eq 452; SDISEL-NEXT: csel w0, w1, w0, gt 453; SDISEL-NEXT: ret 454; 455; GISEL-LABEL: neg_range_int_comp_ua3: 456; GISEL: // %bb.0: 457; GISEL-NEXT: orr w8, w3, #0x1 458; GISEL-NEXT: cmp w0, w2 459; GISEL-NEXT: neg w8, w8 460; GISEL-NEXT: ccmp w1, w8, #4, eq 461; GISEL-NEXT: csel w0, w1, w0, gt 462; GISEL-NEXT: ret 463 %dor = or i32 %d, 1 464 %negd = sub i32 0, %dor 465 %cmp = icmp sgt i32 %b, %negd 466 %cmp1 = icmp eq i32 %a, %c 467 %or.cond = and i1 %cmp, %cmp1 468 %retval.0 = select i1 %or.cond, i32 %b, i32 %a 469 ret i32 %retval.0 470} 471 472; -(a | 1) > (b | 3) && a < c 473define i32 @neg_range_int_c(i32 %a, i32 %b, i32 %c) { 474; SDISEL-LABEL: neg_range_int_c: 475; SDISEL: // %bb.0: // %entry 476; SDISEL-NEXT: orr w8, w0, #0x1 477; SDISEL-NEXT: orr w9, w1, #0x3 478; SDISEL-NEXT: cmn w9, w8 479; SDISEL-NEXT: ccmp w2, w0, #2, lo 480; SDISEL-NEXT: cset w0, lo 481; SDISEL-NEXT: ret 482; 483; GISEL-LABEL: neg_range_int_c: 484; GISEL: // %bb.0: // %entry 485; GISEL-NEXT: orr w8, w0, #0x1 486; GISEL-NEXT: orr w9, w1, #0x3 487; GISEL-NEXT: neg w8, w8 488; GISEL-NEXT: cmp w9, w8 489; GISEL-NEXT: cset w8, lo 490; GISEL-NEXT: cmp w2, w0 491; GISEL-NEXT: cset w9, lo 492; GISEL-NEXT: and w0, w8, w9 493; GISEL-NEXT: ret 494entry: 495 %or = or i32 %a, 1 496 %sub = sub i32 0, %or 497 %or1 = or i32 %b, 3 498 %cmp = icmp ult i32 %or1, %sub 499 %cmp2 = icmp ult i32 %c, %a 500 %0 = and i1 %cmp, %cmp2 501 %land.ext = zext i1 %0 to i32 502 ret i32 %land.ext 503} 504