1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc < %s -debugify-and-strip-all-safe -mcpu=cyclone -verify-machineinstrs -aarch64-enable-ccmp -aarch64-stress-ccmp | FileCheck %s --check-prefixes=CHECK,SDISEL 3; RUN: llc < %s -debugify-and-strip-all-safe -mcpu=cyclone -verify-machineinstrs -aarch64-enable-ccmp -aarch64-stress-ccmp -global-isel | FileCheck %s --check-prefixes=CHECK,GISEL 4target triple = "arm64-apple-ios" 5 6define i32 @single_same(i32 %a, i32 %b) nounwind ssp { 7; CHECK-LABEL: single_same: 8; CHECK: ; %bb.0: ; %entry 9; CHECK-NEXT: cmp w0, #5 10; CHECK-NEXT: ccmp w1, #17, #4, ne 11; CHECK-NEXT: b.ne LBB0_2 12; CHECK-NEXT: ; %bb.1: ; %if.then 13; CHECK-NEXT: stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill 14; CHECK-NEXT: bl _foo 15; CHECK-NEXT: ldp x29, x30, [sp], #16 ; 16-byte Folded Reload 16; CHECK-NEXT: LBB0_2: ; %if.end 17; CHECK-NEXT: mov w0, #7 ; =0x7 18; CHECK-NEXT: ret 19entry: 20 %cmp = icmp eq i32 %a, 5 21 %cmp1 = icmp eq i32 %b, 17 22 %or.cond = or i1 %cmp, %cmp1 23 br i1 %or.cond, label %if.then, label %if.end 24 25if.then: 26 %call = tail call i32 @foo() nounwind 27 br label %if.end 28 29if.end: 30 ret i32 7 31} 32 33; Different condition codes for the two compares. 34define i32 @single_different(i32 %a, i32 %b) nounwind ssp { 35; SDISEL-LABEL: single_different: 36; SDISEL: ; %bb.0: ; %entry 37; SDISEL-NEXT: cmp w0, #6 38; SDISEL-NEXT: ccmp w1, #17, #0, ge 39; SDISEL-NEXT: b.eq LBB1_2 40; SDISEL-NEXT: ; %bb.1: ; %if.then 41; SDISEL-NEXT: stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill 42; SDISEL-NEXT: bl _foo 43; SDISEL-NEXT: ldp x29, x30, [sp], #16 ; 16-byte Folded Reload 44; SDISEL-NEXT: LBB1_2: ; %if.end 45; SDISEL-NEXT: mov w0, #7 ; =0x7 46; SDISEL-NEXT: ret 47; 48; GISEL-LABEL: single_different: 49; GISEL: ; %bb.0: ; %entry 50; GISEL-NEXT: cmp w0, #5 51; GISEL-NEXT: ccmp w1, #17, #0, gt 52; GISEL-NEXT: b.eq LBB1_2 53; GISEL-NEXT: ; %bb.1: ; %if.then 54; GISEL-NEXT: stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill 55; GISEL-NEXT: bl _foo 56; GISEL-NEXT: ldp x29, x30, [sp], #16 ; 16-byte Folded Reload 57; GISEL-NEXT: LBB1_2: ; %if.end 58; GISEL-NEXT: mov w0, #7 ; =0x7 59; GISEL-NEXT: ret 60entry: 61 %cmp = icmp sle i32 %a, 5 62 %cmp1 = icmp ne i32 %b, 17 63 %or.cond = or i1 %cmp, %cmp1 64 br i1 %or.cond, label %if.then, label %if.end 65 66if.then: 67 %call = tail call i32 @foo() nounwind 68 br label %if.end 69 70if.end: 71 ret i32 7 72} 73 74; Second block clobbers the flags, can't convert (easily). 75define i32 @single_flagclobber(i32 %a, i32 %b) nounwind ssp { 76; SDISEL-LABEL: single_flagclobber: 77; SDISEL: ; %bb.0: ; %entry 78; SDISEL-NEXT: cmp w0, #5 79; SDISEL-NEXT: b.eq LBB2_2 80; SDISEL-NEXT: ; %bb.1: ; %lor.lhs.false 81; SDISEL-NEXT: lsl w8, w1, #1 82; SDISEL-NEXT: cmp w1, #7 83; SDISEL-NEXT: csinc w8, w8, w1, lt 84; SDISEL-NEXT: cmp w8, #16 85; SDISEL-NEXT: b.gt LBB2_3 86; SDISEL-NEXT: LBB2_2: ; %if.then 87; SDISEL-NEXT: stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill 88; SDISEL-NEXT: bl _foo 89; SDISEL-NEXT: ldp x29, x30, [sp], #16 ; 16-byte Folded Reload 90; SDISEL-NEXT: LBB2_3: ; %if.end 91; SDISEL-NEXT: mov w0, #7 ; =0x7 92; SDISEL-NEXT: ret 93; 94; GISEL-LABEL: single_flagclobber: 95; GISEL: ; %bb.0: ; %entry 96; GISEL-NEXT: cmp w0, #5 97; GISEL-NEXT: b.eq LBB2_2 98; GISEL-NEXT: ; %bb.1: ; %lor.lhs.false 99; GISEL-NEXT: lsl w8, w1, #1 100; GISEL-NEXT: cmp w1, #7 101; GISEL-NEXT: csinc w8, w8, w1, lt 102; GISEL-NEXT: cmp w8, #17 103; GISEL-NEXT: b.ge LBB2_3 104; GISEL-NEXT: LBB2_2: ; %if.then 105; GISEL-NEXT: stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill 106; GISEL-NEXT: bl _foo 107; GISEL-NEXT: ldp x29, x30, [sp], #16 ; 16-byte Folded Reload 108; GISEL-NEXT: LBB2_3: ; %if.end 109; GISEL-NEXT: mov w0, #7 ; =0x7 110; GISEL-NEXT: ret 111entry: 112 %cmp = icmp eq i32 %a, 5 113 br i1 %cmp, label %if.then, label %lor.lhs.false 114 115lor.lhs.false: ; preds = %entry 116 %cmp1 = icmp slt i32 %b, 7 117 %mul = shl nsw i32 %b, 1 118 %add = add nsw i32 %b, 1 119 %cond = select i1 %cmp1, i32 %mul, i32 %add 120 %cmp2 = icmp slt i32 %cond, 17 121 br i1 %cmp2, label %if.then, label %if.end 122 123if.then: ; preds = %lor.lhs.false, %entry 124 %call = tail call i32 @foo() nounwind 125 br label %if.end 126 127if.end: ; preds = %if.then, %lor.lhs.false 128 ret i32 7 129} 130 131; Second block clobbers the flags and ends with a tbz terminator. 132define i32 @single_flagclobber_tbz(i32 %a, i32 %b) nounwind ssp { 133; CHECK-LABEL: single_flagclobber_tbz: 134; CHECK: ; %bb.0: ; %entry 135; CHECK-NEXT: cmp w0, #5 136; CHECK-NEXT: b.eq LBB3_2 137; CHECK-NEXT: ; %bb.1: ; %lor.lhs.false 138; CHECK-NEXT: lsl w8, w1, #1 139; CHECK-NEXT: cmp w1, #7 140; CHECK-NEXT: csinc w8, w8, w1, lt 141; CHECK-NEXT: tbz w8, #3, LBB3_3 142; CHECK-NEXT: LBB3_2: ; %if.then 143; CHECK-NEXT: stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill 144; CHECK-NEXT: bl _foo 145; CHECK-NEXT: ldp x29, x30, [sp], #16 ; 16-byte Folded Reload 146; CHECK-NEXT: LBB3_3: ; %if.end 147; CHECK-NEXT: mov w0, #7 ; =0x7 148; CHECK-NEXT: ret 149entry: 150 %cmp = icmp eq i32 %a, 5 151 br i1 %cmp, label %if.then, label %lor.lhs.false 152 153lor.lhs.false: ; preds = %entry 154 %cmp1 = icmp slt i32 %b, 7 155 %mul = shl nsw i32 %b, 1 156 %add = add nsw i32 %b, 1 157 %cond = select i1 %cmp1, i32 %mul, i32 %add 158 %and = and i32 %cond, 8 159 %cmp2 = icmp ne i32 %and, 0 160 br i1 %cmp2, label %if.then, label %if.end 161 162if.then: ; preds = %lor.lhs.false, %entry 163 %call = tail call i32 @foo() nounwind 164 br label %if.end 165 166if.end: ; preds = %if.then, %lor.lhs.false 167 ret i32 7 168} 169 170; Speculatively execute division by zero. 171; The sdiv/udiv instructions do not trap when the divisor is zero, so they are 172; safe to speculate. 173define i32 @speculate_division(i32 %a, i32 %b) nounwind ssp { 174; SDISEL-LABEL: speculate_division: 175; SDISEL: ; %bb.0: ; %entry 176; SDISEL-NEXT: cmp w0, #1 177; SDISEL-NEXT: sdiv w8, w1, w0 178; SDISEL-NEXT: ccmp w8, #16, #0, ge 179; SDISEL-NEXT: b.le LBB4_2 180; SDISEL-NEXT: ; %bb.1: ; %if.end 181; SDISEL-NEXT: mov w0, #7 ; =0x7 182; SDISEL-NEXT: ret 183; SDISEL-NEXT: LBB4_2: ; %if.then 184; SDISEL-NEXT: stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill 185; SDISEL-NEXT: bl _foo 186; SDISEL-NEXT: ldp x29, x30, [sp], #16 ; 16-byte Folded Reload 187; SDISEL-NEXT: mov w0, #7 ; =0x7 188; SDISEL-NEXT: ret 189; 190; GISEL-LABEL: speculate_division: 191; GISEL: ; %bb.0: ; %entry 192; GISEL-NEXT: cmp w0, #0 193; GISEL-NEXT: sdiv w8, w1, w0 194; GISEL-NEXT: ccmp w8, #17, #0, gt 195; GISEL-NEXT: b.lt LBB4_2 196; GISEL-NEXT: ; %bb.1: ; %if.end 197; GISEL-NEXT: mov w0, #7 ; =0x7 198; GISEL-NEXT: ret 199; GISEL-NEXT: LBB4_2: ; %if.then 200; GISEL-NEXT: stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill 201; GISEL-NEXT: bl _foo 202; GISEL-NEXT: ldp x29, x30, [sp], #16 ; 16-byte Folded Reload 203; GISEL-NEXT: mov w0, #7 ; =0x7 204; GISEL-NEXT: ret 205entry: 206 %cmp = icmp sgt i32 %a, 0 207 br i1 %cmp, label %land.lhs.true, label %if.end 208 209land.lhs.true: 210 %div = sdiv i32 %b, %a 211 %cmp1 = icmp slt i32 %div, 17 212 br i1 %cmp1, label %if.then, label %if.end 213 214if.then: 215 %call = tail call i32 @foo() nounwind 216 br label %if.end 217 218if.end: 219 ret i32 7 220} 221 222; Floating point compare. 223define i32 @single_fcmp(i32 %a, float %b) nounwind ssp { 224; SDISEL-LABEL: single_fcmp: 225; SDISEL: ; %bb.0: ; %entry 226; SDISEL-NEXT: cmp w0, #1 227; SDISEL-NEXT: scvtf s1, w0 228; SDISEL-NEXT: fdiv s0, s0, s1 229; SDISEL-NEXT: fmov s1, #17.00000000 230; SDISEL-NEXT: fccmp s0, s1, #8, ge 231; SDISEL-NEXT: b.ge LBB5_2 232; SDISEL-NEXT: ; %bb.1: ; %if.end 233; SDISEL-NEXT: mov w0, #7 ; =0x7 234; SDISEL-NEXT: ret 235; SDISEL-NEXT: LBB5_2: ; %if.then 236; SDISEL-NEXT: stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill 237; SDISEL-NEXT: bl _foo 238; SDISEL-NEXT: ldp x29, x30, [sp], #16 ; 16-byte Folded Reload 239; SDISEL-NEXT: mov w0, #7 ; =0x7 240; SDISEL-NEXT: ret 241; 242; GISEL-LABEL: single_fcmp: 243; GISEL: ; %bb.0: ; %entry 244; GISEL-NEXT: cmp w0, #0 245; GISEL-NEXT: scvtf s1, w0 246; GISEL-NEXT: fdiv s0, s0, s1 247; GISEL-NEXT: fmov s1, #17.00000000 248; GISEL-NEXT: fccmp s0, s1, #8, gt 249; GISEL-NEXT: b.ge LBB5_2 250; GISEL-NEXT: ; %bb.1: ; %if.end 251; GISEL-NEXT: mov w0, #7 ; =0x7 252; GISEL-NEXT: ret 253; GISEL-NEXT: LBB5_2: ; %if.then 254; GISEL-NEXT: stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill 255; GISEL-NEXT: bl _foo 256; GISEL-NEXT: ldp x29, x30, [sp], #16 ; 16-byte Folded Reload 257; GISEL-NEXT: mov w0, #7 ; =0x7 258; GISEL-NEXT: ret 259entry: 260 %cmp = icmp sgt i32 %a, 0 261 br i1 %cmp, label %land.lhs.true, label %if.end 262 263land.lhs.true: 264 %conv = sitofp i32 %a to float 265 %div = fdiv float %b, %conv 266 %cmp1 = fcmp oge float %div, 1.700000e+01 267 br i1 %cmp1, label %if.then, label %if.end 268 269if.then: 270 %call = tail call i32 @foo() nounwind 271 br label %if.end 272 273if.end: 274 ret i32 7 275} 276 277; Chain multiple compares. 278define void @multi_different(i32 %a, i32 %b, i32 %c) nounwind ssp { 279; CHECK-LABEL: multi_different: 280; CHECK: ; %bb.0: ; %entry 281; CHECK-NEXT: cmp w0, w1 282; CHECK-NEXT: sdiv w8, w1, w0 283; CHECK-NEXT: ccmp w8, #5, #0, gt 284; CHECK-NEXT: ccmp w8, w2, #4, eq 285; CHECK-NEXT: b.gt LBB6_2 286; CHECK-NEXT: ; %bb.1: ; %if.end 287; CHECK-NEXT: ret 288; CHECK-NEXT: LBB6_2: ; %if.then 289; CHECK-NEXT: b _foo 290entry: 291 %cmp = icmp sgt i32 %a, %b 292 br i1 %cmp, label %land.lhs.true, label %if.end 293 294land.lhs.true: 295 %div = sdiv i32 %b, %a 296 %cmp1 = icmp eq i32 %div, 5 297 %cmp4 = icmp sgt i32 %div, %c 298 %or.cond = and i1 %cmp1, %cmp4 299 br i1 %or.cond, label %if.then, label %if.end 300 301if.then: 302 %call = tail call i32 @foo() nounwind 303 br label %if.end 304 305if.end: 306 ret void 307} 308 309; Convert a cbz in the head block. 310define i32 @cbz_head(i32 %a, i32 %b) nounwind ssp { 311; CHECK-LABEL: cbz_head: 312; CHECK: ; %bb.0: ; %entry 313; CHECK-NEXT: cmp w0, #0 314; CHECK-NEXT: ccmp w1, #17, #0, ne 315; CHECK-NEXT: b.eq LBB7_2 316; CHECK-NEXT: ; %bb.1: ; %if.then 317; CHECK-NEXT: stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill 318; CHECK-NEXT: bl _foo 319; CHECK-NEXT: ldp x29, x30, [sp], #16 ; 16-byte Folded Reload 320; CHECK-NEXT: LBB7_2: ; %if.end 321; CHECK-NEXT: mov w0, #7 ; =0x7 322; CHECK-NEXT: ret 323entry: 324 %cmp = icmp eq i32 %a, 0 325 %cmp1 = icmp ne i32 %b, 17 326 %or.cond = or i1 %cmp, %cmp1 327 br i1 %or.cond, label %if.then, label %if.end 328 329if.then: 330 %call = tail call i32 @foo() nounwind 331 br label %if.end 332 333if.end: 334 ret i32 7 335} 336 337; Check that the immediate operand is in range. The ccmp instruction encodes a 338; smaller range of immediates than subs/adds. 339; The ccmp immediates must be in the range 0-31. 340define i32 @immediate_range(i32 %a, i32 %b) nounwind ssp { 341; CHECK-LABEL: immediate_range: 342; CHECK: ; %bb.0: ; %entry 343; CHECK-NEXT: cmp w0, #5 344; CHECK-NEXT: b.eq LBB8_3 345; CHECK-NEXT: ; %bb.1: ; %entry 346; CHECK-NEXT: cmp w1, #32 347; CHECK-NEXT: b.eq LBB8_3 348; CHECK-NEXT: ; %bb.2: ; %if.end 349; CHECK-NEXT: mov w0, #7 ; =0x7 350; CHECK-NEXT: ret 351; CHECK-NEXT: LBB8_3: ; %if.then 352; CHECK-NEXT: stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill 353; CHECK-NEXT: bl _foo 354; CHECK-NEXT: ldp x29, x30, [sp], #16 ; 16-byte Folded Reload 355; CHECK-NEXT: mov w0, #7 ; =0x7 356; CHECK-NEXT: ret 357entry: 358 %cmp = icmp eq i32 %a, 5 359 %cmp1 = icmp eq i32 %b, 32 360 %or.cond = or i1 %cmp, %cmp1 361 br i1 %or.cond, label %if.then, label %if.end 362 363if.then: 364 %call = tail call i32 @foo() nounwind 365 br label %if.end 366 367if.end: 368 ret i32 7 369} 370 371; Convert a cbz in the second block. 372define i32 @cbz_second(i32 %a, i32 %b) nounwind ssp { 373; CHECK-LABEL: cbz_second: 374; CHECK: ; %bb.0: ; %entry 375; CHECK-NEXT: cmp w0, #0 376; CHECK-NEXT: ccmp w1, #0, #0, ne 377; CHECK-NEXT: b.eq LBB9_2 378; CHECK-NEXT: ; %bb.1: ; %if.then 379; CHECK-NEXT: stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill 380; CHECK-NEXT: bl _foo 381; CHECK-NEXT: ldp x29, x30, [sp], #16 ; 16-byte Folded Reload 382; CHECK-NEXT: LBB9_2: ; %if.end 383; CHECK-NEXT: mov w0, #7 ; =0x7 384; CHECK-NEXT: ret 385entry: 386 %cmp = icmp eq i32 %a, 0 387 %cmp1 = icmp ne i32 %b, 0 388 %or.cond = or i1 %cmp, %cmp1 389 br i1 %or.cond, label %if.then, label %if.end 390 391if.then: 392 %call = tail call i32 @foo() nounwind 393 br label %if.end 394 395if.end: 396 ret i32 7 397} 398 399; Convert a cbnz in the second block. 400define i32 @cbnz_second(i32 %a, i32 %b) nounwind ssp { 401; CHECK-LABEL: cbnz_second: 402; CHECK: ; %bb.0: ; %entry 403; CHECK-NEXT: cmp w0, #0 404; CHECK-NEXT: ccmp w1, #0, #4, ne 405; CHECK-NEXT: b.ne LBB10_2 406; CHECK-NEXT: ; %bb.1: ; %if.then 407; CHECK-NEXT: stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill 408; CHECK-NEXT: bl _foo 409; CHECK-NEXT: ldp x29, x30, [sp], #16 ; 16-byte Folded Reload 410; CHECK-NEXT: LBB10_2: ; %if.end 411; CHECK-NEXT: mov w0, #7 ; =0x7 412; CHECK-NEXT: ret 413entry: 414 %cmp = icmp eq i32 %a, 0 415 %cmp1 = icmp eq i32 %b, 0 416 %or.cond = or i1 %cmp, %cmp1 417 br i1 %or.cond, label %if.then, label %if.end 418 419if.then: 420 %call = tail call i32 @foo() nounwind 421 br label %if.end 422 423if.end: 424 ret i32 7 425} 426declare i32 @foo() 427 428%str1 = type { %str2 } 429%str2 = type { [24 x i8], ptr, i32, ptr, i32, [4 x i8], ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, i8, ptr, ptr, ptr } 430 431; Test case distilled from 126.gcc. 432; The phi in sw.bb.i.i gets multiple operands for the %entry predecessor. 433define void @build_modify_expr() nounwind ssp { 434; CHECK-LABEL: build_modify_expr: 435; CHECK: ; %bb.0: ; %entry 436; CHECK-NEXT: ret 437entry: 438 switch i32 undef, label %sw.bb.i.i [ 439 i32 69, label %if.end85 440 i32 70, label %if.end85 441 i32 71, label %if.end85 442 i32 72, label %if.end85 443 i32 73, label %if.end85 444 i32 105, label %if.end85 445 i32 106, label %if.end85 446 ] 447 448if.end85: 449 ret void 450 451sw.bb.i.i: 452 %ref.tr.i.i = phi ptr [ %0, %sw.bb.i.i ], [ undef, %entry ] 453 %operands.i.i = getelementptr inbounds %str1, ptr %ref.tr.i.i, i64 0, i32 0, i32 2 454 %0 = load ptr, ptr %operands.i.i, align 8 455 %code1.i.i.phi.trans.insert = getelementptr inbounds %str1, ptr %0, i64 0, i32 0, i32 0, i64 16 456 br label %sw.bb.i.i 457} 458 459define i64 @select_and(i32 %w0, i32 %w1, i64 %x2, i64 %x3) { 460; CHECK-LABEL: select_and: 461; CHECK: ; %bb.0: 462; CHECK-NEXT: cmp w1, #5 463; CHECK-NEXT: ccmp w0, w1, #0, ne 464; CHECK-NEXT: csel x0, x2, x3, lt 465; CHECK-NEXT: ret 466 %1 = icmp slt i32 %w0, %w1 467 %2 = icmp ne i32 5, %w1 468 %3 = and i1 %1, %2 469 %sel = select i1 %3, i64 %x2, i64 %x3 470 ret i64 %sel 471} 472 473define i64 @select_or(i32 %w0, i32 %w1, i64 %x2, i64 %x3) { 474; CHECK-LABEL: select_or: 475; CHECK: ; %bb.0: 476; CHECK-NEXT: cmp w1, #5 477; CHECK-NEXT: ccmp w0, w1, #8, eq 478; CHECK-NEXT: csel x0, x2, x3, lt 479; CHECK-NEXT: ret 480 %1 = icmp slt i32 %w0, %w1 481 %2 = icmp ne i32 5, %w1 482 %3 = or i1 %1, %2 483 %sel = select i1 %3, i64 %x2, i64 %x3 484 ret i64 %sel 485} 486 487define float @select_or_float(i32 %w0, i32 %w1, float %x2, float %x3) { 488; CHECK-LABEL: select_or_float: 489; CHECK: ; %bb.0: 490; CHECK-NEXT: cmp w1, #5 491; CHECK-NEXT: ccmp w0, w1, #8, eq 492; CHECK-NEXT: fcsel s0, s0, s1, lt 493; CHECK-NEXT: ret 494 %1 = icmp slt i32 %w0, %w1 495 %2 = icmp ne i32 5, %w1 496 %3 = or i1 %1, %2 497 %sel = select i1 %3, float %x2,float %x3 498 ret float %sel 499} 500 501define i64 @gccbug(i64 %x0, i64 %x1) { 502; SDISEL-LABEL: gccbug: 503; SDISEL: ; %bb.0: 504; SDISEL-NEXT: cmp x0, #2 505; SDISEL-NEXT: ccmp x0, #4, #4, ne 506; SDISEL-NEXT: ccmp x1, #0, #0, eq 507; SDISEL-NEXT: mov w8, #1 ; =0x1 508; SDISEL-NEXT: cinc x0, x8, eq 509; SDISEL-NEXT: ret 510; 511; GISEL-LABEL: gccbug: 512; GISEL: ; %bb.0: 513; GISEL-NEXT: cmp x1, #0 514; GISEL-NEXT: cset w8, eq 515; GISEL-NEXT: cmp x0, #2 516; GISEL-NEXT: cset w9, eq 517; GISEL-NEXT: cmp x0, #4 518; GISEL-NEXT: cset w10, eq 519; GISEL-NEXT: orr w9, w10, w9 520; GISEL-NEXT: and w8, w9, w8 521; GISEL-NEXT: and x8, x8, #0x1 522; GISEL-NEXT: add x0, x8, #1 523; GISEL-NEXT: ret 524 %cmp0 = icmp eq i64 %x1, 0 525 %cmp1 = icmp eq i64 %x0, 2 526 %cmp2 = icmp eq i64 %x0, 4 527 528 %or = or i1 %cmp2, %cmp1 529 %and = and i1 %or, %cmp0 530 531 %sel = select i1 %and, i64 2, i64 1 532 ret i64 %sel 533} 534 535define i32 @select_ororand(i32 %w0, i32 %w1, i32 %w2, i32 %w3) { 536; CHECK-LABEL: select_ororand: 537; CHECK: ; %bb.0: 538; CHECK-NEXT: cmp w3, #4 539; CHECK-NEXT: ccmp w2, #2, #0, gt 540; CHECK-NEXT: ccmp w1, #13, #2, ge 541; CHECK-NEXT: ccmp w0, #0, #4, ls 542; CHECK-NEXT: csel w0, w3, wzr, eq 543; CHECK-NEXT: ret 544 %c0 = icmp eq i32 %w0, 0 545 %c1 = icmp ugt i32 %w1, 13 546 %c2 = icmp slt i32 %w2, 2 547 %c4 = icmp sgt i32 %w3, 4 548 %or = or i1 %c0, %c1 549 %and = and i1 %c2, %c4 550 %or1 = or i1 %or, %and 551 %sel = select i1 %or1, i32 %w3, i32 0 552 ret i32 %sel 553} 554 555define i32 @select_andor(i32 %v1, i32 %v2, i32 %v3) { 556; CHECK-LABEL: select_andor: 557; CHECK: ; %bb.0: 558; CHECK-NEXT: cmp w1, w2 559; CHECK-NEXT: ccmp w0, #0, #4, lt 560; CHECK-NEXT: ccmp w0, w1, #0, eq 561; CHECK-NEXT: csel w0, w0, w1, eq 562; CHECK-NEXT: ret 563 %c0 = icmp eq i32 %v1, %v2 564 %c1 = icmp sge i32 %v2, %v3 565 %c2 = icmp eq i32 %v1, 0 566 %or = or i1 %c2, %c1 567 %and = and i1 %or, %c0 568 %sel = select i1 %and, i32 %v1, i32 %v2 569 ret i32 %sel 570} 571 572define i32 @select_andor32(i32 %v1, i32 %v2, i32 %v3) { 573; SDISEL-LABEL: select_andor32: 574; SDISEL: ; %bb.0: 575; SDISEL-NEXT: cmp w1, w2 576; SDISEL-NEXT: mov w8, #32 ; =0x20 577; SDISEL-NEXT: ccmp w0, w8, #4, lt 578; SDISEL-NEXT: ccmp w0, w1, #0, eq 579; SDISEL-NEXT: csel w0, w0, w1, eq 580; SDISEL-NEXT: ret 581; 582; GISEL-LABEL: select_andor32: 583; GISEL: ; %bb.0: 584; GISEL-NEXT: mov w8, #32 ; =0x20 585; GISEL-NEXT: cmp w1, w2 586; GISEL-NEXT: ccmp w0, w8, #4, lt 587; GISEL-NEXT: ccmp w0, w1, #0, eq 588; GISEL-NEXT: csel w0, w0, w1, eq 589; GISEL-NEXT: ret 590 %c0 = icmp eq i32 %v1, %v2 591 %c1 = icmp sge i32 %v2, %v3 592 %c2 = icmp eq i32 %v1, 32 593 %or = or i1 %c2, %c1 594 %and = and i1 %or, %c0 595 %sel = select i1 %and, i32 %v1, i32 %v2 596 ret i32 %sel 597} 598 599define i64 @select_noccmp1(i64 %v1, i64 %v2, i64 %v3, i64 %r) { 600; SDISEL-LABEL: select_noccmp1: 601; SDISEL: ; %bb.0: 602; SDISEL-NEXT: cmp x0, #0 603; SDISEL-NEXT: ccmp x0, #13, #4, lt 604; SDISEL-NEXT: cset w8, gt 605; SDISEL-NEXT: cmp x2, #2 606; SDISEL-NEXT: ccmp x2, #4, #4, lt 607; SDISEL-NEXT: csinc w8, w8, wzr, le 608; SDISEL-NEXT: cmp w8, #0 609; SDISEL-NEXT: csel x0, xzr, x3, ne 610; SDISEL-NEXT: ret 611; 612; GISEL-LABEL: select_noccmp1: 613; GISEL: ; %bb.0: 614; GISEL-NEXT: mov x0, x3 615; GISEL-NEXT: ret 616 %c0 = icmp slt i64 %v1, 0 617 %c1 = icmp sgt i64 %v1, 13 618 %c2 = icmp slt i64 %v3, 2 619 %c4 = icmp sgt i64 %v3, 4 620 %and0 = and i1 %c0, %c1 621 %and1 = and i1 %c2, %c4 622 %or = or i1 %and0, %and1 623 %sel = select i1 %or, i64 0, i64 %r 624 ret i64 %sel 625} 626 627@g = global i32 0 628 629define i64 @select_noccmp2(i64 %v1, i64 %v2, i64 %v3, i64 %r) { 630; SDISEL-LABEL: select_noccmp2: 631; SDISEL: ; %bb.0: 632; SDISEL-NEXT: cmp x0, #0 633; SDISEL-NEXT: ccmp x0, #13, #0, ge 634; SDISEL-NEXT: cset w8, gt 635; SDISEL-NEXT: cmp w8, #0 636; SDISEL-NEXT: csel x0, xzr, x3, ne 637; SDISEL-NEXT: sbfx w8, w8, #0, #1 638; SDISEL-NEXT: adrp x9, _g@PAGE 639; SDISEL-NEXT: str w8, [x9, _g@PAGEOFF] 640; SDISEL-NEXT: ret 641; 642; GISEL-LABEL: select_noccmp2: 643; GISEL: ; %bb.0: 644; GISEL-NEXT: cmp x0, #14 645; GISEL-NEXT: cset w8, hs 646; GISEL-NEXT: tst w8, #0x1 647; GISEL-NEXT: csel x0, xzr, x3, ne 648; GISEL-NEXT: sbfx w8, w8, #0, #1 649; GISEL-NEXT: adrp x9, _g@PAGE 650; GISEL-NEXT: str w8, [x9, _g@PAGEOFF] 651; GISEL-NEXT: ret 652 %c0 = icmp slt i64 %v1, 0 653 %c1 = icmp sgt i64 %v1, 13 654 %or = or i1 %c0, %c1 655 %sel = select i1 %or, i64 0, i64 %r 656 %ext = sext i1 %or to i32 657 store volatile i32 %ext, ptr @g 658 ret i64 %sel 659} 660 661; The following is not possible to implement with a single cmp;ccmp;csel 662; sequence. 663define i32 @select_noccmp3(i32 %v0, i32 %v1, i32 %v2) { 664; SDISEL-LABEL: select_noccmp3: 665; SDISEL: ; %bb.0: 666; SDISEL-NEXT: cmp w0, #0 667; SDISEL-NEXT: ccmp w0, #13, #0, ge 668; SDISEL-NEXT: cset w8, gt 669; SDISEL-NEXT: cmp w0, #22 670; SDISEL-NEXT: mov w9, #44 ; =0x2c 671; SDISEL-NEXT: ccmp w0, w9, #0, ge 672; SDISEL-NEXT: csel w8, wzr, w8, le 673; SDISEL-NEXT: cmp w0, #99 674; SDISEL-NEXT: mov w9, #77 ; =0x4d 675; SDISEL-NEXT: ccmp w0, w9, #4, ne 676; SDISEL-NEXT: cset w9, eq 677; SDISEL-NEXT: tst w8, w9 678; SDISEL-NEXT: csel w0, w1, w2, ne 679; SDISEL-NEXT: ret 680; 681; GISEL-LABEL: select_noccmp3: 682; GISEL: ; %bb.0: 683; GISEL-NEXT: mov w8, #99 ; =0x63 684; GISEL-NEXT: sub w9, w0, #45 685; GISEL-NEXT: cmp w0, #77 686; GISEL-NEXT: ccmp w0, w8, #4, ne 687; GISEL-NEXT: ccmn w9, #23, #2, eq 688; GISEL-NEXT: ccmp w0, #14, #0, lo 689; GISEL-NEXT: csel w0, w1, w2, hs 690; GISEL-NEXT: ret 691 %c0 = icmp slt i32 %v0, 0 692 %c1 = icmp sgt i32 %v0, 13 693 %c2 = icmp slt i32 %v0, 22 694 %c3 = icmp sgt i32 %v0, 44 695 %c4 = icmp eq i32 %v0, 99 696 %c5 = icmp eq i32 %v0, 77 697 %or0 = or i1 %c0, %c1 698 %or1 = or i1 %c2, %c3 699 %and0 = and i1 %or0, %or1 700 %or2 = or i1 %c4, %c5 701 %and1 = and i1 %and0, %or2 702 %sel = select i1 %and1, i32 %v1, i32 %v2 703 ret i32 %sel 704} 705 706; Test the IR CCs that expand to two cond codes. 707 708define i32 @select_and_olt_one(double %v0, double %v1, double %v2, double %v3, i32 %a, i32 %b) #0 { 709; CHECK-LABEL: select_and_olt_one: 710; CHECK: ; %bb.0: 711; CHECK-NEXT: fcmp d0, d1 712; CHECK-NEXT: fccmp d2, d3, #4, mi 713; CHECK-NEXT: fccmp d2, d3, #1, ne 714; CHECK-NEXT: csel w0, w0, w1, vc 715; CHECK-NEXT: ret 716 %c0 = fcmp olt double %v0, %v1 717 %c1 = fcmp one double %v2, %v3 718 %cr = and i1 %c1, %c0 719 %sel = select i1 %cr, i32 %a, i32 %b 720 ret i32 %sel 721} 722 723define i32 @select_and_one_olt(double %v0, double %v1, double %v2, double %v3, i32 %a, i32 %b) #0 { 724; CHECK-LABEL: select_and_one_olt: 725; CHECK: ; %bb.0: 726; CHECK-NEXT: fcmp d0, d1 727; CHECK-NEXT: fccmp d0, d1, #1, ne 728; CHECK-NEXT: fccmp d2, d3, #0, vc 729; CHECK-NEXT: csel w0, w0, w1, mi 730; CHECK-NEXT: ret 731 %c0 = fcmp one double %v0, %v1 732 %c1 = fcmp olt double %v2, %v3 733 %cr = and i1 %c1, %c0 734 %sel = select i1 %cr, i32 %a, i32 %b 735 ret i32 %sel 736} 737 738define i32 @select_and_olt_ueq(double %v0, double %v1, double %v2, double %v3, i32 %a, i32 %b) #0 { 739; CHECK-LABEL: select_and_olt_ueq: 740; CHECK: ; %bb.0: 741; CHECK-NEXT: fcmp d0, d1 742; CHECK-NEXT: fccmp d2, d3, #0, mi 743; CHECK-NEXT: fccmp d2, d3, #8, le 744; CHECK-NEXT: csel w0, w0, w1, pl 745; CHECK-NEXT: ret 746 %c0 = fcmp olt double %v0, %v1 747 %c1 = fcmp ueq double %v2, %v3 748 %cr = and i1 %c1, %c0 749 %sel = select i1 %cr, i32 %a, i32 %b 750 ret i32 %sel 751} 752 753define i32 @select_and_ueq_olt(double %v0, double %v1, double %v2, double %v3, i32 %a, i32 %b) #0 { 754; CHECK-LABEL: select_and_ueq_olt: 755; CHECK: ; %bb.0: 756; CHECK-NEXT: fcmp d0, d1 757; CHECK-NEXT: fccmp d0, d1, #8, le 758; CHECK-NEXT: fccmp d2, d3, #0, pl 759; CHECK-NEXT: csel w0, w0, w1, mi 760; CHECK-NEXT: ret 761 %c0 = fcmp ueq double %v0, %v1 762 %c1 = fcmp olt double %v2, %v3 763 %cr = and i1 %c1, %c0 764 %sel = select i1 %cr, i32 %a, i32 %b 765 ret i32 %sel 766} 767 768define i32 @select_or_olt_one(double %v0, double %v1, double %v2, double %v3, i32 %a, i32 %b) #0 { 769; CHECK-LABEL: select_or_olt_one: 770; CHECK: ; %bb.0: 771; CHECK-NEXT: fcmp d0, d1 772; CHECK-NEXT: fccmp d2, d3, #0, pl 773; CHECK-NEXT: fccmp d2, d3, #8, le 774; CHECK-NEXT: csel w0, w0, w1, mi 775; CHECK-NEXT: ret 776 %c0 = fcmp olt double %v0, %v1 777 %c1 = fcmp one double %v2, %v3 778 %cr = or i1 %c1, %c0 779 %sel = select i1 %cr, i32 %a, i32 %b 780 ret i32 %sel 781} 782 783define i32 @select_or_one_olt(double %v0, double %v1, double %v2, double %v3, i32 %a, i32 %b) #0 { 784; CHECK-LABEL: select_or_one_olt: 785; CHECK: ; %bb.0: 786; CHECK-NEXT: fcmp d0, d1 787; CHECK-NEXT: fccmp d0, d1, #8, le 788; CHECK-NEXT: fccmp d2, d3, #8, pl 789; CHECK-NEXT: csel w0, w0, w1, mi 790; CHECK-NEXT: ret 791 %c0 = fcmp one double %v0, %v1 792 %c1 = fcmp olt double %v2, %v3 793 %cr = or i1 %c1, %c0 794 %sel = select i1 %cr, i32 %a, i32 %b 795 ret i32 %sel 796} 797 798define i32 @select_or_olt_ueq(double %v0, double %v1, double %v2, double %v3, i32 %a, i32 %b) #0 { 799; CHECK-LABEL: select_or_olt_ueq: 800; CHECK: ; %bb.0: 801; CHECK-NEXT: fcmp d0, d1 802; CHECK-NEXT: fccmp d2, d3, #4, pl 803; CHECK-NEXT: fccmp d2, d3, #1, ne 804; CHECK-NEXT: csel w0, w0, w1, vs 805; CHECK-NEXT: ret 806 %c0 = fcmp olt double %v0, %v1 807 %c1 = fcmp ueq double %v2, %v3 808 %cr = or i1 %c1, %c0 809 %sel = select i1 %cr, i32 %a, i32 %b 810 ret i32 %sel 811} 812 813define i32 @select_or_ueq_olt(double %v0, double %v1, double %v2, double %v3, i32 %a, i32 %b) #0 { 814; CHECK-LABEL: select_or_ueq_olt: 815; CHECK: ; %bb.0: 816; CHECK-NEXT: fcmp d0, d1 817; CHECK-NEXT: fccmp d0, d1, #1, ne 818; CHECK-NEXT: fccmp d2, d3, #8, vc 819; CHECK-NEXT: csel w0, w0, w1, mi 820; CHECK-NEXT: ret 821 %c0 = fcmp ueq double %v0, %v1 822 %c1 = fcmp olt double %v2, %v3 823 %cr = or i1 %c1, %c0 824 %sel = select i1 %cr, i32 %a, i32 %b 825 ret i32 %sel 826} 827 828define i32 @select_or_olt_ogt_ueq(double %v0, double %v1, double %v2, double %v3, double %v4, double %v5, i32 %a, i32 %b) #0 { 829; CHECK-LABEL: select_or_olt_ogt_ueq: 830; CHECK: ; %bb.0: 831; CHECK-NEXT: fcmp d0, d1 832; CHECK-NEXT: fccmp d2, d3, #0, pl 833; CHECK-NEXT: fccmp d4, d5, #4, le 834; CHECK-NEXT: fccmp d4, d5, #1, ne 835; CHECK-NEXT: csel w0, w0, w1, vs 836; CHECK-NEXT: ret 837 %c0 = fcmp olt double %v0, %v1 838 %c1 = fcmp ogt double %v2, %v3 839 %c2 = fcmp ueq double %v4, %v5 840 %c3 = or i1 %c1, %c0 841 %cr = or i1 %c2, %c3 842 %sel = select i1 %cr, i32 %a, i32 %b 843 ret i32 %sel 844} 845 846define i32 @select_or_olt_ueq_ogt(double %v0, double %v1, double %v2, double %v3, double %v4, double %v5, i32 %a, i32 %b) #0 { 847; CHECK-LABEL: select_or_olt_ueq_ogt: 848; CHECK: ; %bb.0: 849; CHECK-NEXT: fcmp d0, d1 850; CHECK-NEXT: fccmp d2, d3, #4, pl 851; CHECK-NEXT: fccmp d2, d3, #1, ne 852; CHECK-NEXT: fccmp d4, d5, #0, vc 853; CHECK-NEXT: csel w0, w0, w1, gt 854; CHECK-NEXT: ret 855 %c0 = fcmp olt double %v0, %v1 856 %c1 = fcmp ueq double %v2, %v3 857 %c2 = fcmp ogt double %v4, %v5 858 %c3 = or i1 %c1, %c0 859 %cr = or i1 %c2, %c3 860 %sel = select i1 %cr, i32 %a, i32 %b 861 ret i32 %sel 862} 863 864; Verify that we correctly promote f16. 865 866define i32 @half_select_and_olt_oge(half %v0, half %v1, half %v2, half %v3, i32 %a, i32 %b) #0 { 867; SDISEL-LABEL: half_select_and_olt_oge: 868; SDISEL: ; %bb.0: 869; SDISEL-NEXT: fcvt s1, h1 870; SDISEL-NEXT: fcvt s0, h0 871; SDISEL-NEXT: fcmp s0, s1 872; SDISEL-NEXT: fcvt s0, h3 873; SDISEL-NEXT: fcvt s1, h2 874; SDISEL-NEXT: fccmp s1, s0, #8, mi 875; SDISEL-NEXT: csel w0, w0, w1, ge 876; SDISEL-NEXT: ret 877; 878; GISEL-LABEL: half_select_and_olt_oge: 879; GISEL: ; %bb.0: 880; GISEL-NEXT: fcvt s0, h0 881; GISEL-NEXT: fcvt s1, h1 882; GISEL-NEXT: fcvt s2, h2 883; GISEL-NEXT: fcvt s3, h3 884; GISEL-NEXT: fcmp s0, s1 885; GISEL-NEXT: fccmp s2, s3, #8, mi 886; GISEL-NEXT: csel w0, w0, w1, ge 887; GISEL-NEXT: ret 888 %c0 = fcmp olt half %v0, %v1 889 %c1 = fcmp oge half %v2, %v3 890 %cr = and i1 %c1, %c0 891 %sel = select i1 %cr, i32 %a, i32 %b 892 ret i32 %sel 893} 894 895define i32 @half_select_and_olt_one(half %v0, half %v1, half %v2, half %v3, i32 %a, i32 %b) #0 { 896; SDISEL-LABEL: half_select_and_olt_one: 897; SDISEL: ; %bb.0: 898; SDISEL-NEXT: fcvt s1, h1 899; SDISEL-NEXT: fcvt s0, h0 900; SDISEL-NEXT: fcmp s0, s1 901; SDISEL-NEXT: fcvt s0, h3 902; SDISEL-NEXT: fcvt s1, h2 903; SDISEL-NEXT: fccmp s1, s0, #4, mi 904; SDISEL-NEXT: fccmp s1, s0, #1, ne 905; SDISEL-NEXT: csel w0, w0, w1, vc 906; SDISEL-NEXT: ret 907; 908; GISEL-LABEL: half_select_and_olt_one: 909; GISEL: ; %bb.0: 910; GISEL-NEXT: fcvt s0, h0 911; GISEL-NEXT: fcvt s1, h1 912; GISEL-NEXT: fcvt s2, h2 913; GISEL-NEXT: fcvt s3, h3 914; GISEL-NEXT: fcmp s0, s1 915; GISEL-NEXT: fccmp s2, s3, #4, mi 916; GISEL-NEXT: fccmp s2, s3, #1, ne 917; GISEL-NEXT: csel w0, w0, w1, vc 918; GISEL-NEXT: ret 919 %c0 = fcmp olt half %v0, %v1 920 %c1 = fcmp one half %v2, %v3 921 %cr = and i1 %c1, %c0 922 %sel = select i1 %cr, i32 %a, i32 %b 923 ret i32 %sel 924} 925 926; Also verify that we don't try to generate f128 FCCMPs, using RT calls instead. 927 928define i32 @f128_select_and_olt_oge(fp128 %v0, fp128 %v1, fp128 %v2, fp128 %v3, i32 %a, i32 %b) #0 { 929; SDISEL-LABEL: f128_select_and_olt_oge: 930; SDISEL: ; %bb.0: 931; SDISEL-NEXT: sub sp, sp, #80 932; SDISEL-NEXT: stp x22, x21, [sp, #32] ; 16-byte Folded Spill 933; SDISEL-NEXT: stp x20, x19, [sp, #48] ; 16-byte Folded Spill 934; SDISEL-NEXT: stp x29, x30, [sp, #64] ; 16-byte Folded Spill 935; SDISEL-NEXT: mov x19, x1 936; SDISEL-NEXT: mov x20, x0 937; SDISEL-NEXT: stp q2, q3, [sp] ; 32-byte Folded Spill 938; SDISEL-NEXT: bl ___lttf2 939; SDISEL-NEXT: cmp w0, #0 940; SDISEL-NEXT: cset w21, lt 941; SDISEL-NEXT: ldp q0, q1, [sp] ; 32-byte Folded Reload 942; SDISEL-NEXT: bl ___getf2 943; SDISEL-NEXT: cmp w0, #0 944; SDISEL-NEXT: cset w8, ge 945; SDISEL-NEXT: tst w8, w21 946; SDISEL-NEXT: csel w0, w20, w19, ne 947; SDISEL-NEXT: ldp x29, x30, [sp, #64] ; 16-byte Folded Reload 948; SDISEL-NEXT: ldp x20, x19, [sp, #48] ; 16-byte Folded Reload 949; SDISEL-NEXT: ldp x22, x21, [sp, #32] ; 16-byte Folded Reload 950; SDISEL-NEXT: add sp, sp, #80 951; SDISEL-NEXT: ret 952; 953; GISEL-LABEL: f128_select_and_olt_oge: 954; GISEL: ; %bb.0: 955; GISEL-NEXT: sub sp, sp, #80 956; GISEL-NEXT: stp x22, x21, [sp, #32] ; 16-byte Folded Spill 957; GISEL-NEXT: stp x20, x19, [sp, #48] ; 16-byte Folded Spill 958; GISEL-NEXT: stp x29, x30, [sp, #64] ; 16-byte Folded Spill 959; GISEL-NEXT: stp q3, q2, [sp] ; 32-byte Folded Spill 960; GISEL-NEXT: mov x19, x0 961; GISEL-NEXT: mov x20, x1 962; GISEL-NEXT: bl ___lttf2 963; GISEL-NEXT: mov x21, x0 964; GISEL-NEXT: ldp q1, q0, [sp] ; 32-byte Folded Reload 965; GISEL-NEXT: bl ___getf2 966; GISEL-NEXT: cmp w21, #0 967; GISEL-NEXT: ccmp w0, #0, #8, lt 968; GISEL-NEXT: csel w0, w19, w20, ge 969; GISEL-NEXT: ldp x29, x30, [sp, #64] ; 16-byte Folded Reload 970; GISEL-NEXT: ldp x20, x19, [sp, #48] ; 16-byte Folded Reload 971; GISEL-NEXT: ldp x22, x21, [sp, #32] ; 16-byte Folded Reload 972; GISEL-NEXT: add sp, sp, #80 973; GISEL-NEXT: ret 974 %c0 = fcmp olt fp128 %v0, %v1 975 %c1 = fcmp oge fp128 %v2, %v3 976 %cr = and i1 %c1, %c0 977 %sel = select i1 %cr, i32 %a, i32 %b 978 ret i32 %sel 979} 980 981; This testcase resembles the core problem of http://llvm.org/PR39550 982; (an OR operation is 2 levels deep but needs to be implemented first) 983define i32 @deep_or(i32 %a0, i32 %a1, i32 %a2, i32 %a3, i32 %x, i32 %y) { 984; CHECK-LABEL: deep_or: 985; CHECK: ; %bb.0: 986; CHECK-NEXT: cmp w2, #20 987; CHECK-NEXT: ccmp w2, #15, #4, ne 988; CHECK-NEXT: ccmp w1, #0, #4, eq 989; CHECK-NEXT: ccmp w0, #0, #4, ne 990; CHECK-NEXT: csel w0, w4, w5, ne 991; CHECK-NEXT: ret 992 %c0 = icmp ne i32 %a0, 0 993 %c1 = icmp ne i32 %a1, 0 994 %c2 = icmp eq i32 %a2, 15 995 %c3 = icmp eq i32 %a2, 20 996 997 %or = or i1 %c2, %c3 998 %and0 = and i1 %or, %c1 999 %and1 = and i1 %and0, %c0 1000 %sel = select i1 %and1, i32 %x, i32 %y 1001 ret i32 %sel 1002} 1003 1004; Variation of deep_or, we still need to implement the OR first though. 1005define i32 @deep_or1(i32 %a0, i32 %a1, i32 %a2, i32 %a3, i32 %x, i32 %y) { 1006; CHECK-LABEL: deep_or1: 1007; CHECK: ; %bb.0: 1008; CHECK-NEXT: cmp w2, #20 1009; CHECK-NEXT: ccmp w2, #15, #4, ne 1010; CHECK-NEXT: ccmp w0, #0, #4, eq 1011; CHECK-NEXT: ccmp w1, #0, #4, ne 1012; CHECK-NEXT: csel w0, w4, w5, ne 1013; CHECK-NEXT: ret 1014 %c0 = icmp ne i32 %a0, 0 1015 %c1 = icmp ne i32 %a1, 0 1016 %c2 = icmp eq i32 %a2, 15 1017 %c3 = icmp eq i32 %a2, 20 1018 1019 %or = or i1 %c2, %c3 1020 %and0 = and i1 %c0, %or 1021 %and1 = and i1 %and0, %c1 1022 %sel = select i1 %and1, i32 %x, i32 %y 1023 ret i32 %sel 1024} 1025 1026; Variation of deep_or, we still need to implement the OR first though. 1027define i32 @deep_or2(i32 %a0, i32 %a1, i32 %a2, i32 %a3, i32 %x, i32 %y) { 1028; CHECK-LABEL: deep_or2: 1029; CHECK: ; %bb.0: 1030; CHECK-NEXT: cmp w2, #20 1031; CHECK-NEXT: ccmp w2, #15, #4, ne 1032; CHECK-NEXT: ccmp w1, #0, #4, eq 1033; CHECK-NEXT: ccmp w0, #0, #4, ne 1034; CHECK-NEXT: csel w0, w4, w5, ne 1035; CHECK-NEXT: ret 1036 %c0 = icmp ne i32 %a0, 0 1037 %c1 = icmp ne i32 %a1, 0 1038 %c2 = icmp eq i32 %a2, 15 1039 %c3 = icmp eq i32 %a2, 20 1040 1041 %or = or i1 %c2, %c3 1042 %and0 = and i1 %c0, %c1 1043 %and1 = and i1 %and0, %or 1044 %sel = select i1 %and1, i32 %x, i32 %y 1045 ret i32 %sel 1046} 1047 1048; This test is trying to test that multiple ccmp's don't get created in a way 1049; that they would have multiple uses. It doesn't seem to. 1050define i32 @multiccmp(i32 %s0, i32 %s1, i32 %s2, i32 %s3, i32 %x, i32 %y) #0 { 1051; SDISEL-LABEL: multiccmp: 1052; SDISEL: ; %bb.0: ; %entry 1053; SDISEL-NEXT: stp x22, x21, [sp, #-48]! ; 16-byte Folded Spill 1054; SDISEL-NEXT: stp x20, x19, [sp, #16] ; 16-byte Folded Spill 1055; SDISEL-NEXT: stp x29, x30, [sp, #32] ; 16-byte Folded Spill 1056; SDISEL-NEXT: mov x19, x5 1057; SDISEL-NEXT: cmp w0, w1 1058; SDISEL-NEXT: cset w20, gt 1059; SDISEL-NEXT: cmp w2, w3 1060; SDISEL-NEXT: cset w21, ne 1061; SDISEL-NEXT: tst w20, w21 1062; SDISEL-NEXT: csel w0, w5, w4, ne 1063; SDISEL-NEXT: bl _callee 1064; SDISEL-NEXT: tst w20, w21 1065; SDISEL-NEXT: csel w0, w0, w19, ne 1066; SDISEL-NEXT: bl _callee 1067; SDISEL-NEXT: ldp x29, x30, [sp, #32] ; 16-byte Folded Reload 1068; SDISEL-NEXT: ldp x20, x19, [sp, #16] ; 16-byte Folded Reload 1069; SDISEL-NEXT: ldp x22, x21, [sp], #48 ; 16-byte Folded Reload 1070; SDISEL-NEXT: ret 1071; 1072; GISEL-LABEL: multiccmp: 1073; GISEL: ; %bb.0: ; %entry 1074; GISEL-NEXT: stp x20, x19, [sp, #-32]! ; 16-byte Folded Spill 1075; GISEL-NEXT: stp x29, x30, [sp, #16] ; 16-byte Folded Spill 1076; GISEL-NEXT: mov x19, x5 1077; GISEL-NEXT: cmp w0, w1 1078; GISEL-NEXT: cset w8, gt 1079; GISEL-NEXT: cmp w2, w3 1080; GISEL-NEXT: cset w9, ne 1081; GISEL-NEXT: and w20, w8, w9 1082; GISEL-NEXT: tst w20, #0x1 1083; GISEL-NEXT: csel w0, w5, w4, ne 1084; GISEL-NEXT: bl _callee 1085; GISEL-NEXT: tst w20, #0x1 1086; GISEL-NEXT: csel w0, w0, w19, ne 1087; GISEL-NEXT: bl _callee 1088; GISEL-NEXT: ldp x29, x30, [sp, #16] ; 16-byte Folded Reload 1089; GISEL-NEXT: ldp x20, x19, [sp], #32 ; 16-byte Folded Reload 1090; GISEL-NEXT: ret 1091entry: 1092 %c0 = icmp sgt i32 %s0, %s1 1093 %c1 = icmp ne i32 %s2, %s3 1094 %a = and i1 %c0, %c1 1095 %s = select i1 %a, i32 %y, i32 %x 1096 %o = call i32 @callee(i32 %s) 1097 %z1 = select i1 %a, i32 %o, i32 %y 1098 %p = call i32 @callee(i32 %z1) 1099 ret i32 %p 1100} 1101 1102define i32 @multiccmp2(i32 %s0, i32 %s1, i32 %s2, i32 %s3, i32 %x, i32 %y) #0 { 1103; SDISEL-LABEL: multiccmp2: 1104; SDISEL: ; %bb.0: ; %entry 1105; SDISEL-NEXT: stp x22, x21, [sp, #-48]! ; 16-byte Folded Spill 1106; SDISEL-NEXT: stp x20, x19, [sp, #16] ; 16-byte Folded Spill 1107; SDISEL-NEXT: stp x29, x30, [sp, #32] ; 16-byte Folded Spill 1108; SDISEL-NEXT: mov x19, x5 1109; SDISEL-NEXT: mov x20, x3 1110; SDISEL-NEXT: mov x21, x0 1111; SDISEL-NEXT: cmp w0, w1 1112; SDISEL-NEXT: cset w8, gt 1113; SDISEL-NEXT: cmp w2, w3 1114; SDISEL-NEXT: cset w22, ne 1115; SDISEL-NEXT: tst w8, w22 1116; SDISEL-NEXT: csel w0, w5, w4, ne 1117; SDISEL-NEXT: bl _callee 1118; SDISEL-NEXT: cmp w21, w20 1119; SDISEL-NEXT: cset w8, eq 1120; SDISEL-NEXT: tst w22, w8 1121; SDISEL-NEXT: csel w0, w0, w19, ne 1122; SDISEL-NEXT: bl _callee 1123; SDISEL-NEXT: ldp x29, x30, [sp, #32] ; 16-byte Folded Reload 1124; SDISEL-NEXT: ldp x20, x19, [sp, #16] ; 16-byte Folded Reload 1125; SDISEL-NEXT: ldp x22, x21, [sp], #48 ; 16-byte Folded Reload 1126; SDISEL-NEXT: ret 1127; 1128; GISEL-LABEL: multiccmp2: 1129; GISEL: ; %bb.0: ; %entry 1130; GISEL-NEXT: stp x22, x21, [sp, #-48]! ; 16-byte Folded Spill 1131; GISEL-NEXT: stp x20, x19, [sp, #16] ; 16-byte Folded Spill 1132; GISEL-NEXT: stp x29, x30, [sp, #32] ; 16-byte Folded Spill 1133; GISEL-NEXT: mov x19, x0 1134; GISEL-NEXT: mov x20, x3 1135; GISEL-NEXT: mov x21, x5 1136; GISEL-NEXT: cmp w0, w1 1137; GISEL-NEXT: cset w8, gt 1138; GISEL-NEXT: cmp w2, w3 1139; GISEL-NEXT: cset w22, ne 1140; GISEL-NEXT: and w8, w8, w22 1141; GISEL-NEXT: tst w8, #0x1 1142; GISEL-NEXT: csel w0, w5, w4, ne 1143; GISEL-NEXT: bl _callee 1144; GISEL-NEXT: cmp w19, w20 1145; GISEL-NEXT: cset w8, eq 1146; GISEL-NEXT: and w8, w22, w8 1147; GISEL-NEXT: tst w8, #0x1 1148; GISEL-NEXT: csel w0, w0, w21, ne 1149; GISEL-NEXT: bl _callee 1150; GISEL-NEXT: ldp x29, x30, [sp, #32] ; 16-byte Folded Reload 1151; GISEL-NEXT: ldp x20, x19, [sp, #16] ; 16-byte Folded Reload 1152; GISEL-NEXT: ldp x22, x21, [sp], #48 ; 16-byte Folded Reload 1153; GISEL-NEXT: ret 1154entry: 1155 %c0 = icmp sgt i32 %s0, %s1 1156 %c1 = icmp ne i32 %s2, %s3 1157 %a = and i1 %c0, %c1 1158 %z = zext i1 %a to i32 1159 %s = select i1 %a, i32 %y, i32 %x 1160 %o = call i32 @callee(i32 %s) 1161 1162 %c2 = icmp eq i32 %s0, %s3 1163 %a1 = and i1 %c1, %c2 1164 %z1 = select i1 %a1, i32 %o, i32 %y 1165 %p = call i32 @callee(i32 %z1) 1166 ret i32 %p 1167} 1168declare i32 @callee(i32) 1169 1170define i1 @cmp_and_negative_const(i32 %0, i32 %1) { 1171; SDISEL-LABEL: cmp_and_negative_const: 1172; SDISEL: ; %bb.0: 1173; SDISEL-NEXT: cmn w0, #1 1174; SDISEL-NEXT: ccmn w1, #2, #0, eq 1175; SDISEL-NEXT: cset w0, eq 1176; SDISEL-NEXT: ret 1177; 1178; GISEL-LABEL: cmp_and_negative_const: 1179; GISEL: ; %bb.0: 1180; GISEL-NEXT: cmn w0, #1 1181; GISEL-NEXT: cset w8, eq 1182; GISEL-NEXT: cmn w1, #2 1183; GISEL-NEXT: cset w9, eq 1184; GISEL-NEXT: and w0, w8, w9 1185; GISEL-NEXT: ret 1186 %3 = icmp eq i32 %0, -1 1187 %4 = icmp eq i32 %1, -2 1188 %5 = and i1 %3, %4 1189 ret i1 %5 1190} 1191 1192define i1 @cmp_or_negative_const(i32 %a, i32 %b) { 1193; SDISEL-LABEL: cmp_or_negative_const: 1194; SDISEL: ; %bb.0: 1195; SDISEL-NEXT: cmn w0, #1 1196; SDISEL-NEXT: ccmn w1, #2, #4, ne 1197; SDISEL-NEXT: cset w0, eq 1198; SDISEL-NEXT: ret 1199; 1200; GISEL-LABEL: cmp_or_negative_const: 1201; GISEL: ; %bb.0: 1202; GISEL-NEXT: cmn w0, #1 1203; GISEL-NEXT: cset w8, eq 1204; GISEL-NEXT: cmn w1, #2 1205; GISEL-NEXT: cset w9, eq 1206; GISEL-NEXT: orr w0, w8, w9 1207; GISEL-NEXT: ret 1208 %cmp = icmp eq i32 %a, -1 1209 %cmp1 = icmp eq i32 %b, -2 1210 %or.cond = or i1 %cmp, %cmp1 1211 ret i1 %or.cond 1212} 1213attributes #0 = { nounwind } 1214