1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc -mtriple=arm64-apple-iphoneos -aarch64-enable-sink-fold=true -o - %s | FileCheck %s 3 4define i3 @sign_i3(i3 %a) { 5; CHECK-LABEL: sign_i3: 6; CHECK: // %bb.0: 7; CHECK-NEXT: sbfx w8, w0, #2, #1 8; CHECK-NEXT: orr w0, w8, #0x1 9; CHECK-NEXT: ret 10 %c = icmp sgt i3 %a, -1 11 %res = select i1 %c, i3 1, i3 -1 12 ret i3 %res 13} 14 15define i4 @sign_i4(i4 %a) { 16; CHECK-LABEL: sign_i4: 17; CHECK: // %bb.0: 18; CHECK-NEXT: sbfx w8, w0, #3, #1 19; CHECK-NEXT: orr w0, w8, #0x1 20; CHECK-NEXT: ret 21 %c = icmp sgt i4 %a, -1 22 %res = select i1 %c, i4 1, i4 -1 23 ret i4 %res 24} 25 26define i8 @sign_i8(i8 %a) { 27; CHECK-LABEL: sign_i8: 28; CHECK: // %bb.0: 29; CHECK-NEXT: sbfx w8, w0, #7, #1 30; CHECK-NEXT: orr w0, w8, #0x1 31; CHECK-NEXT: ret 32 %c = icmp sgt i8 %a, -1 33 %res = select i1 %c, i8 1, i8 -1 34 ret i8 %res 35} 36 37define i16 @sign_i16(i16 %a) { 38; CHECK-LABEL: sign_i16: 39; CHECK: // %bb.0: 40; CHECK-NEXT: sbfx w8, w0, #15, #1 41; CHECK-NEXT: orr w0, w8, #0x1 42; CHECK-NEXT: ret 43 %c = icmp sgt i16 %a, -1 44 %res = select i1 %c, i16 1, i16 -1 45 ret i16 %res 46} 47 48define i32 @sign_i32(i32 %a) { 49; CHECK-LABEL: sign_i32: 50; CHECK: // %bb.0: 51; CHECK-NEXT: asr w8, w0, #31 52; CHECK-NEXT: orr w0, w8, #0x1 53; CHECK-NEXT: ret 54 %c = icmp sgt i32 %a, -1 55 %res = select i1 %c, i32 1, i32 -1 56 ret i32 %res 57} 58 59define i64 @sign_i64(i64 %a) { 60; CHECK-LABEL: sign_i64: 61; CHECK: // %bb.0: 62; CHECK-NEXT: asr x8, x0, #63 63; CHECK-NEXT: orr x0, x8, #0x1 64; CHECK-NEXT: ret 65 %c = icmp sgt i64 %a, -1 66 %res = select i1 %c, i64 1, i64 -1 67 ret i64 %res 68} 69 70 71define i64 @not_sign_i64(i64 %a) { 72; CHECK-LABEL: not_sign_i64: 73; CHECK: // %bb.0: 74; CHECK-NEXT: mov w8, #1 // =0x1 75; CHECK-NEXT: cmp x0, #0 76; CHECK-NEXT: cneg x0, x8, le 77; CHECK-NEXT: ret 78 %c = icmp sgt i64 %a, 0 79 %res = select i1 %c, i64 1, i64 -1 80 ret i64 %res 81} 82 83define i64 @not_sign_i64_2(i64 %a) { 84; CHECK-LABEL: not_sign_i64_2: 85; CHECK: // %bb.0: 86; CHECK-NEXT: asr x0, x0, #63 87; CHECK-NEXT: ret 88 %c = icmp sgt i64 %a, -1 89 %res = select i1 %c, i64 0, i64 -1 90 ret i64 %res 91} 92 93define i64 @not_sign_i64_3(i64 %a) { 94; CHECK-LABEL: not_sign_i64_3: 95; CHECK: // %bb.0: 96; CHECK-NEXT: mvn x8, x0 97; CHECK-NEXT: lsr x0, x8, #63 98; CHECK-NEXT: ret 99 %c = icmp sgt i64 %a, -1 100 %res = select i1 %c, i64 1, i64 0 101 ret i64 %res 102} 103 104define i64 @not_sign_i64_4(i64 %a) { 105; CHECK-LABEL: not_sign_i64_4: 106; CHECK: // %bb.0: 107; CHECK-NEXT: mov x0, #-1 // =0xffffffffffffffff 108; CHECK-NEXT: ret 109 %c = icmp ugt i64 %a, -1 110 %res = select i1 %c, i64 1, i64 -1 111 ret i64 %res 112} 113 114define <7 x i8> @sign_7xi8(<7 x i8> %a) { 115; CHECK-LABEL: sign_7xi8: 116; CHECK: // %bb.0: 117; CHECK-NEXT: movi v1.8b, #1 118; CHECK-NEXT: cmlt v0.8b, v0.8b, #0 119; CHECK-NEXT: orr v0.8b, v0.8b, v1.8b 120; CHECK-NEXT: ret 121 %c = icmp sgt <7 x i8> %a, <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1> 122 %res = select <7 x i1> %c, <7 x i8> <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1>, <7 x i8> <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1> 123 ret <7 x i8> %res 124} 125 126define <8 x i8> @sign_8xi8(<8 x i8> %a) { 127; CHECK-LABEL: sign_8xi8: 128; CHECK: // %bb.0: 129; CHECK-NEXT: movi v1.8b, #1 130; CHECK-NEXT: cmlt v0.8b, v0.8b, #0 131; CHECK-NEXT: orr v0.8b, v0.8b, v1.8b 132; CHECK-NEXT: ret 133 %c = icmp sgt <8 x i8> %a, <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1> 134 %res = select <8 x i1> %c, <8 x i8> <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1>, <8 x i8> <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1> 135 ret <8 x i8> %res 136} 137 138define <16 x i8> @sign_16xi8(<16 x i8> %a) { 139; CHECK-LABEL: sign_16xi8: 140; CHECK: // %bb.0: 141; CHECK-NEXT: movi v1.16b, #1 142; CHECK-NEXT: cmlt v0.16b, v0.16b, #0 143; CHECK-NEXT: orr v0.16b, v0.16b, v1.16b 144; CHECK-NEXT: ret 145 %c = icmp sgt <16 x i8> %a, <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1> 146 %res = select <16 x i1> %c, <16 x i8> <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1>, <16 x i8> <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1> 147 ret <16 x i8> %res 148} 149 150define <3 x i32> @sign_3xi32(<3 x i32> %a) { 151; CHECK-LABEL: sign_3xi32: 152; CHECK: // %bb.0: 153; CHECK-NEXT: cmlt v0.4s, v0.4s, #0 154; CHECK-NEXT: orr v0.4s, #1 155; CHECK-NEXT: ret 156 %c = icmp sgt <3 x i32> %a, <i32 -1, i32 -1, i32 -1> 157 %res = select <3 x i1> %c, <3 x i32> <i32 1, i32 1, i32 1>, <3 x i32> <i32 -1, i32 -1, i32 -1> 158 ret <3 x i32> %res 159} 160 161define <4 x i32> @sign_4xi32(<4 x i32> %a) { 162; CHECK-LABEL: sign_4xi32: 163; CHECK: // %bb.0: 164; CHECK-NEXT: cmlt v0.4s, v0.4s, #0 165; CHECK-NEXT: orr v0.4s, #1 166; CHECK-NEXT: ret 167 %c = icmp sgt <4 x i32> %a, <i32 -1, i32 -1, i32 -1, i32 -1> 168 %res = select <4 x i1> %c, <4 x i32> <i32 1, i32 1, i32 1, i32 1>, <4 x i32> <i32 -1, i32 -1, i32 -1, i32 -1> 169 ret <4 x i32> %res 170} 171 172define <4 x i32> @sign_4xi32_multi_use(<4 x i32> %a) { 173; CHECK-LABEL: sign_4xi32_multi_use: 174; CHECK: // %bb.0: 175; CHECK-NEXT: sub sp, sp, #32 176; CHECK-NEXT: str x30, [sp, #16] // 8-byte Folded Spill 177; CHECK-NEXT: .cfi_def_cfa_offset 32 178; CHECK-NEXT: .cfi_offset w30, -16 179; CHECK-NEXT: cmlt v1.4s, v0.4s, #0 180; CHECK-NEXT: cmge v0.4s, v0.4s, #0 181; CHECK-NEXT: xtn v0.4h, v0.4s 182; CHECK-NEXT: orr v1.4s, #1 183; CHECK-NEXT: str q1, [sp] // 16-byte Folded Spill 184; CHECK-NEXT: bl use_4xi1 185; CHECK-NEXT: ldr q0, [sp] // 16-byte Folded Reload 186; CHECK-NEXT: ldr x30, [sp, #16] // 8-byte Folded Reload 187; CHECK-NEXT: add sp, sp, #32 188; CHECK-NEXT: ret 189 %c = icmp sgt <4 x i32> %a, <i32 -1, i32 -1, i32 -1, i32 -1> 190 %res = select <4 x i1> %c, <4 x i32> <i32 1, i32 1, i32 1, i32 1>, <4 x i32> <i32 -1, i32 -1, i32 -1, i32 -1> 191 call void @use_4xi1(<4 x i1> %c) 192 ret <4 x i32> %res 193} 194 195; Second icmp operand breaks sign pattern. 196define <4 x i32> @not_sign_4xi32(<4 x i32> %a) { 197; CHECK-LABEL: not_sign_4xi32: 198; CHECK: // %bb.0: 199; CHECK-NEXT: adrp x8, .LCPI16_0 200; CHECK-NEXT: movi v2.4s, #1 201; CHECK-NEXT: ldr q1, [x8, :lo12:.LCPI16_0] 202; CHECK-NEXT: cmgt v0.4s, v0.4s, v1.4s 203; CHECK-NEXT: and v1.16b, v0.16b, v2.16b 204; CHECK-NEXT: orn v0.16b, v1.16b, v0.16b 205; CHECK-NEXT: ret 206 %c = icmp sgt <4 x i32> %a, <i32 1, i32 -1, i32 -1, i32 -1> 207 %res = select <4 x i1> %c, <4 x i32> <i32 1, i32 1, i32 1, i32 1>, <4 x i32> <i32 -1, i32 -1, i32 -1, i32 -1> 208 ret <4 x i32> %res 209} 210 211; First select operand breaks sign pattern. 212define <4 x i32> @not_sign_4xi32_2(<4 x i32> %a) { 213; CHECK-LABEL: not_sign_4xi32_2: 214; CHECK: // %bb.0: 215; CHECK-NEXT: adrp x8, .LCPI17_0 216; CHECK-NEXT: cmlt v0.4s, v0.4s, #0 217; CHECK-NEXT: ldr q1, [x8, :lo12:.LCPI17_0] 218; CHECK-NEXT: orr v0.16b, v0.16b, v1.16b 219; CHECK-NEXT: ret 220 %c = icmp sgt <4 x i32> %a, <i32 -1, i32 -1, i32 -1, i32 -1> 221 %res = select <4 x i1> %c, <4 x i32> <i32 1, i32 1, i32 -1, i32 1>, <4 x i32> <i32 -1, i32 -1, i32 -1, i32 -1> 222 ret <4 x i32> %res 223} 224 225; Second select operand breaks sign pattern. 226define <4 x i32> @not_sign_4xi32_3(<4 x i32> %a) { 227; CHECK-LABEL: not_sign_4xi32_3: 228; CHECK: // %bb.0: 229; CHECK-NEXT: adrp x8, .LCPI18_0 230; CHECK-NEXT: cmge v0.4s, v0.4s, #0 231; CHECK-NEXT: ldr q1, [x8, :lo12:.LCPI18_0] 232; CHECK-NEXT: bic v1.16b, v1.16b, v0.16b 233; CHECK-NEXT: sub v0.4s, v1.4s, v0.4s 234; CHECK-NEXT: ret 235 %c = icmp sgt <4 x i32> %a, <i32 -1, i32 -1, i32 -1, i32 -1> 236 %res = select <4 x i1> %c, <4 x i32> <i32 1, i32 1, i32 1, i32 1>, <4 x i32> <i32 -1, i32 -1, i32 -1, i32 1> 237 ret <4 x i32> %res 238} 239 240; i65 is not legal. 241define <4 x i65> @sign_4xi65(<4 x i65> %a) { 242; CHECK-LABEL: sign_4xi65: 243; CHECK: // %bb.0: 244; CHECK-NEXT: sbfx x8, x5, #0, #1 245; CHECK-NEXT: sbfx x9, x3, #0, #1 246; CHECK-NEXT: sbfx x10, x1, #0, #1 247; CHECK-NEXT: sbfx x11, x7, #0, #1 248; CHECK-NEXT: lsr x1, x10, #63 249; CHECK-NEXT: lsr x3, x9, #63 250; CHECK-NEXT: lsr x5, x8, #63 251; CHECK-NEXT: lsr x7, x11, #63 252; CHECK-NEXT: orr x0, x10, #0x1 253; CHECK-NEXT: orr x2, x9, #0x1 254; CHECK-NEXT: orr x4, x8, #0x1 255; CHECK-NEXT: orr x6, x11, #0x1 256; CHECK-NEXT: ret 257 %c = icmp sgt <4 x i65> %a, <i65 -1, i65 -1, i65 -1, i65 -1> 258 %res = select <4 x i1> %c, <4 x i65> <i65 1, i65 1, i65 1, i65 1>, <4 x i65 > <i65 -1, i65 -1, i65 -1, i65 -1> 259 ret <4 x i65> %res 260} 261 262define i32 @or_neg(i32 %x, i32 %y) { 263; CHECK-LABEL: or_neg: 264; CHECK: // %bb.0: 265; CHECK-NEXT: orr w8, w0, #0x1 266; CHECK-NEXT: cmn w1, w8 267; CHECK-NEXT: cset w0, lt 268; CHECK-NEXT: ret 269 %3 = or i32 %x, 1 270 %4 = sub i32 0, %3 271 %5 = icmp sgt i32 %4, %y 272 %6 = zext i1 %5 to i32 273 ret i32 %6 274} 275 276define i32 @or_neg_ugt(i32 %x, i32 %y) { 277; CHECK-LABEL: or_neg_ugt: 278; CHECK: // %bb.0: 279; CHECK-NEXT: orr w8, w0, #0x1 280; CHECK-NEXT: cmn w1, w8 281; CHECK-NEXT: cset w0, lo 282; CHECK-NEXT: ret 283 %3 = or i32 %x, 1 284 %4 = sub i32 0, %3 285 %5 = icmp ugt i32 %4, %y 286 %6 = zext i1 %5 to i32 287 ret i32 %6 288} 289 290; Negative test 291 292define i32 @or_neg_no_smin(i32 %x, i32 %y) { 293; CHECK-LABEL: or_neg_no_smin: 294; CHECK: // %bb.0: 295; CHECK-NEXT: neg w8, w0 296; CHECK-NEXT: cmp w8, w1 297; CHECK-NEXT: cset w0, gt 298; CHECK-NEXT: ret 299 %4 = sub i32 0, %x 300 %5 = icmp sgt i32 %4, %y 301 %6 = zext i1 %5 to i32 302 ret i32 %6 303} 304 305; Negative test 306 307define i32 @or_neg_ult_no_zero(i32 %x, i32 %y) { 308; CHECK-LABEL: or_neg_ult_no_zero: 309; CHECK: // %bb.0: 310; CHECK-NEXT: neg w8, w0 311; CHECK-NEXT: cmp w8, w1 312; CHECK-NEXT: cset w0, lo 313; CHECK-NEXT: ret 314 %4 = sub i32 0, %x 315 %5 = icmp ult i32 %4, %y 316 %6 = zext i1 %5 to i32 317 ret i32 %6 318} 319 320define i32 @or_neg_no_smin_but_zero(i32 %x, i32 %y) { 321; CHECK-LABEL: or_neg_no_smin_but_zero: 322; CHECK: // %bb.0: 323; CHECK-NEXT: bic w8, w0, w0, asr #31 324; CHECK-NEXT: cmn w1, w8 325; CHECK-NEXT: cset w0, lt 326; CHECK-NEXT: ret 327 %3 = call i32 @llvm.smax.i32(i32 %x, i32 0) 328 %4 = sub i32 0, %3 329 %5 = icmp sgt i32 %4, %y 330 %6 = zext i1 %5 to i32 331 ret i32 %6 332} 333 334define i32 @or_neg_slt_zero_but_no_smin(i32 %x, i32 %y) { 335; CHECK-LABEL: or_neg_slt_zero_but_no_smin: 336; CHECK: // %bb.0: 337; CHECK-NEXT: mov w8, #9 // =0x9 338; CHECK-NEXT: cmp w0, #9 339; CHECK-NEXT: csel w8, w0, w8, lo 340; CHECK-NEXT: neg w8, w8 341; CHECK-NEXT: cmp w8, w1 342; CHECK-NEXT: cset w0, hi 343; CHECK-NEXT: ret 344 %3 = call i32 @llvm.umin.i32(i32 %x, i32 9) 345 %4 = sub i32 0, %3 346 %5 = icmp ugt i32 %4, %y 347 %6 = zext i1 %5 to i32 348 ret i32 %6 349} 350 351define i32 @or_neg2(i32 %x, i32 %y) { 352; CHECK-LABEL: or_neg2: 353; CHECK: // %bb.0: 354; CHECK-NEXT: orr w8, w0, #0x1 355; CHECK-NEXT: cmn w1, w8 356; CHECK-NEXT: cset w0, le 357; CHECK-NEXT: ret 358 %3 = or i32 %x, 1 359 %4 = sub i32 0, %3 360 %5 = icmp sge i32 %4, %y 361 %6 = zext i1 %5 to i32 362 ret i32 %6 363} 364 365define i32 @or_neg3(i32 %x, i32 %y) { 366; CHECK-LABEL: or_neg3: 367; CHECK: // %bb.0: 368; CHECK-NEXT: orr w8, w0, #0x1 369; CHECK-NEXT: cmn w1, w8 370; CHECK-NEXT: cset w0, gt 371; CHECK-NEXT: ret 372 %3 = or i32 %x, 1 373 %4 = sub i32 0, %3 374 %5 = icmp slt i32 %4, %y 375 %6 = zext i1 %5 to i32 376 ret i32 %6 377} 378 379define i32 @or_neg4(i32 %x, i32 %y) { 380; CHECK-LABEL: or_neg4: 381; CHECK: // %bb.0: 382; CHECK-NEXT: orr w8, w0, #0x1 383; CHECK-NEXT: cmn w1, w8 384; CHECK-NEXT: cset w0, ge 385; CHECK-NEXT: ret 386 %3 = or i32 %x, 1 387 %4 = sub i32 0, %3 388 %5 = icmp sle i32 %4, %y 389 %6 = zext i1 %5 to i32 390 ret i32 %6 391} 392 393define i32 @or_neg_ult(i32 %x, i32 %y) { 394; CHECK-LABEL: or_neg_ult: 395; CHECK: // %bb.0: 396; CHECK-NEXT: orr w8, w0, #0x1 397; CHECK-NEXT: cmn w1, w8 398; CHECK-NEXT: cset w0, lo 399; CHECK-NEXT: ret 400 %3 = or i32 %x, 1 401 %4 = sub i32 0, %3 402 %5 = icmp ugt i32 %4, %y 403 %6 = zext i1 %5 to i32 404 ret i32 %6 405} 406 407define i32 @or_neg_no_smin2(i32 %x, i32 %y) { 408; CHECK-LABEL: or_neg_no_smin2: 409; CHECK: // %bb.0: 410; CHECK-NEXT: neg w8, w0 411; CHECK-NEXT: cmp w8, w1 412; CHECK-NEXT: cset w0, ge 413; CHECK-NEXT: ret 414 %4 = sub i32 0, %x 415 %5 = icmp sge i32 %4, %y 416 %6 = zext i1 %5 to i32 417 ret i32 %6 418} 419 420; Negative test 421 422define i32 @or_neg_ult_no_zero2(i32 %x, i32 %y) { 423; CHECK-LABEL: or_neg_ult_no_zero2: 424; CHECK: // %bb.0: 425; CHECK-NEXT: neg w8, w0 426; CHECK-NEXT: cmp w8, w1 427; CHECK-NEXT: cset w0, lo 428; CHECK-NEXT: ret 429 %4 = sub i32 0, %x 430 %5 = icmp ult i32 %4, %y 431 %6 = zext i1 %5 to i32 432 ret i32 %6 433} 434 435define i32 @or_neg_no_smin_but_zero2(i32 %x, i32 %y) { 436; CHECK-LABEL: or_neg_no_smin_but_zero2: 437; CHECK: // %bb.0: 438; CHECK-NEXT: bic w8, w0, w0, asr #31 439; CHECK-NEXT: cmn w1, w8 440; CHECK-NEXT: cset w0, ge 441; CHECK-NEXT: ret 442 %3 = call i32 @llvm.smax.i32(i32 %x, i32 0) 443 %4 = sub i32 0, %3 444 %5 = icmp sle i32 %4, %y 445 %6 = zext i1 %5 to i32 446 ret i32 %6 447} 448 449define i32 @or_neg_slt_zero_but_no_smin2(i32 %x, i32 %y) { 450; CHECK-LABEL: or_neg_slt_zero_but_no_smin2: 451; CHECK: // %bb.0: 452; CHECK-NEXT: mov w8, #9 // =0x9 453; CHECK-NEXT: cmp w0, #9 454; CHECK-NEXT: csel w8, w0, w8, lo 455; CHECK-NEXT: neg w8, w8 456; CHECK-NEXT: cmp w8, w1 457; CHECK-NEXT: cset w0, hs 458; CHECK-NEXT: ret 459 %3 = call i32 @llvm.umin.i32(i32 %x, i32 9) 460 %4 = sub i32 0, %3 461 %5 = icmp uge i32 %4, %y 462 %6 = zext i1 %5 to i32 463 ret i32 %6 464} 465 466declare i32 @llvm.smax.i32(i32, i32) 467declare i32 @llvm.umax.i32(i32, i32) 468declare void @use_4xi1(<4 x i1>) 469