1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc < %s -mtriple=x86_64-unknown-unknown -verify-machineinstrs | FileCheck %s --check-prefixes=CHECK,NOBMI -enable-var-scope 3; RUN: llc < %s -mtriple=x86_64-unknown-unknown -verify-machineinstrs -mattr=+bmi | FileCheck %s -check-prefixes=CHECK,BMI -enable-var-scope 4 5define i32 @select_and1(i32 %x, i32 %y) { 6; CHECK-LABEL: select_and1: 7; CHECK: # %bb.0: 8; CHECK-NEXT: xorl %eax, %eax 9; CHECK-NEXT: cmpl $11, %edi 10; CHECK-NEXT: cmovgel %esi, %eax 11; CHECK-NEXT: retq 12 %c = icmp slt i32 %x, 11 13 %s = select i1 %c, i32 0, i32 -1 14 %a = and i32 %y, %s 15 ret i32 %a 16} 17 18define i32 @select_and2(i32 %x, i32 %y) { 19; CHECK-LABEL: select_and2: 20; CHECK: # %bb.0: 21; CHECK-NEXT: xorl %eax, %eax 22; CHECK-NEXT: cmpl $11, %edi 23; CHECK-NEXT: cmovgel %esi, %eax 24; CHECK-NEXT: retq 25 %c = icmp slt i32 %x, 11 26 %s = select i1 %c, i32 0, i32 -1 27 %a = and i32 %s, %y 28 ret i32 %a 29} 30 31define i32 @select_and3(i32 %x, i32 %y) { 32; CHECK-LABEL: select_and3: 33; CHECK: # %bb.0: 34; CHECK-NEXT: xorl %eax, %eax 35; CHECK-NEXT: cmpl $11, %edi 36; CHECK-NEXT: cmovll %esi, %eax 37; CHECK-NEXT: retq 38 %c = icmp slt i32 %x, 11 39 %s = select i1 %c, i32 -1, i32 0 40 %a = and i32 %y, %s 41 ret i32 %a 42} 43 44define <4 x i32> @select_and_v4(i32 %x, <4 x i32> %y) { 45; CHECK-LABEL: select_and_v4: 46; CHECK: # %bb.0: 47; CHECK-NEXT: cmpl $11, %edi 48; CHECK-NEXT: xorps %xmm1, %xmm1 49; CHECK-NEXT: jl .LBB3_2 50; CHECK-NEXT: # %bb.1: 51; CHECK-NEXT: movaps %xmm0, %xmm1 52; CHECK-NEXT: .LBB3_2: 53; CHECK-NEXT: movaps %xmm1, %xmm0 54; CHECK-NEXT: retq 55 %c = icmp slt i32 %x, 11 56 %s = select i1 %c, <4 x i32> zeroinitializer, <4 x i32><i32 -1, i32 -1, i32 -1, i32 -1> 57 %a = and <4 x i32> %s, %y 58 ret <4 x i32> %a 59} 60 61define i32 @select_or1(i32 %x, i32 %y) { 62; CHECK-LABEL: select_or1: 63; CHECK: # %bb.0: 64; CHECK-NEXT: cmpl $11, %edi 65; CHECK-NEXT: movl $-1, %eax 66; CHECK-NEXT: cmovll %esi, %eax 67; CHECK-NEXT: retq 68 %c = icmp slt i32 %x, 11 69 %s = select i1 %c, i32 0, i32 -1 70 %a = or i32 %y, %s 71 ret i32 %a 72} 73 74define i32 @select_or2(i32 %x, i32 %y) { 75; CHECK-LABEL: select_or2: 76; CHECK: # %bb.0: 77; CHECK-NEXT: cmpl $11, %edi 78; CHECK-NEXT: movl $-1, %eax 79; CHECK-NEXT: cmovll %esi, %eax 80; CHECK-NEXT: retq 81 %c = icmp slt i32 %x, 11 82 %s = select i1 %c, i32 0, i32 -1 83 %a = or i32 %s, %y 84 ret i32 %a 85} 86 87define i32 @select_or3(i32 %x, i32 %y) { 88; CHECK-LABEL: select_or3: 89; CHECK: # %bb.0: 90; CHECK-NEXT: cmpl $11, %edi 91; CHECK-NEXT: movl $-1, %eax 92; CHECK-NEXT: cmovgel %esi, %eax 93; CHECK-NEXT: retq 94 %c = icmp slt i32 %x, 11 95 %s = select i1 %c, i32 -1, i32 0 96 %a = or i32 %y, %s 97 ret i32 %a 98} 99 100define <4 x i32> @select_or_v4(i32 %x, <4 x i32> %y) { 101; CHECK-LABEL: select_or_v4: 102; CHECK: # %bb.0: 103; CHECK-NEXT: cmpl $11, %edi 104; CHECK-NEXT: jl .LBB7_2 105; CHECK-NEXT: # %bb.1: 106; CHECK-NEXT: pcmpeqd %xmm0, %xmm0 107; CHECK-NEXT: .LBB7_2: 108; CHECK-NEXT: retq 109 %c = icmp slt i32 %x, 11 110 %s = select i1 %c, <4 x i32> zeroinitializer, <4 x i32><i32 -1, i32 -1, i32 -1, i32 -1> 111 %a = or <4 x i32> %s, %y 112 ret <4 x i32> %a 113} 114 115define i32 @sel_constants_sub_constant_sel_constants(i1 %cond) { 116; CHECK-LABEL: sel_constants_sub_constant_sel_constants: 117; CHECK: # %bb.0: 118; CHECK-NEXT: testb $1, %dil 119; CHECK-NEXT: movl $9, %ecx 120; CHECK-NEXT: movl $2, %eax 121; CHECK-NEXT: cmovnel %ecx, %eax 122; CHECK-NEXT: retq 123 %sel = select i1 %cond, i32 -4, i32 3 124 %bo = sub i32 5, %sel 125 ret i32 %bo 126} 127 128define i32 @sdiv_constant_sel_constants(i1 %cond) { 129; CHECK-LABEL: sdiv_constant_sel_constants: 130; CHECK: # %bb.0: 131; CHECK-NEXT: notb %dil 132; CHECK-NEXT: movzbl %dil, %eax 133; CHECK-NEXT: andl $1, %eax 134; CHECK-NEXT: leal (%rax,%rax,4), %eax 135; CHECK-NEXT: retq 136 %sel = select i1 %cond, i32 121, i32 23 137 %bo = sdiv i32 120, %sel 138 ret i32 %bo 139} 140 141define i32 @udiv_constant_sel_constants(i1 %cond) { 142; CHECK-LABEL: udiv_constant_sel_constants: 143; CHECK: # %bb.0: 144; CHECK-NEXT: notb %dil 145; CHECK-NEXT: movzbl %dil, %eax 146; CHECK-NEXT: andl $1, %eax 147; CHECK-NEXT: leal (%rax,%rax,4), %eax 148; CHECK-NEXT: retq 149 %sel = select i1 %cond, i32 -4, i32 23 150 %bo = udiv i32 120, %sel 151 ret i32 %bo 152} 153 154define i32 @srem_constant_sel_constants(i1 %cond) { 155; CHECK-LABEL: srem_constant_sel_constants: 156; CHECK: # %bb.0: 157; CHECK-NEXT: testb $1, %dil 158; CHECK-NEXT: movl $120, %ecx 159; CHECK-NEXT: movl $5, %eax 160; CHECK-NEXT: cmovnel %ecx, %eax 161; CHECK-NEXT: retq 162 %sel = select i1 %cond, i32 121, i32 23 163 %bo = srem i32 120, %sel 164 ret i32 %bo 165} 166 167define i32 @urem_constant_sel_constants(i1 %cond) { 168; CHECK-LABEL: urem_constant_sel_constants: 169; CHECK: # %bb.0: 170; CHECK-NEXT: testb $1, %dil 171; CHECK-NEXT: movl $120, %ecx 172; CHECK-NEXT: movl $5, %eax 173; CHECK-NEXT: cmovnel %ecx, %eax 174; CHECK-NEXT: retq 175 %sel = select i1 %cond, i32 -4, i32 23 176 %bo = urem i32 120, %sel 177 ret i32 %bo 178} 179 180define i32 @sel_constants_shl_constant(i1 %cond) { 181; CHECK-LABEL: sel_constants_shl_constant: 182; CHECK: # %bb.0: 183; CHECK-NEXT: notb %dil 184; CHECK-NEXT: movzbl %dil, %eax 185; CHECK-NEXT: andl $1, %eax 186; CHECK-NEXT: orl $2, %eax 187; CHECK-NEXT: shll $8, %eax 188; CHECK-NEXT: retq 189 %sel = select i1 %cond, i32 2, i32 3 190 %bo = shl i32 %sel, 8 191 ret i32 %bo 192} 193 194define i32 @shl_constant_sel_constants(i1 %cond) { 195; CHECK-LABEL: shl_constant_sel_constants: 196; CHECK: # %bb.0: 197; CHECK-NEXT: notb %dil 198; CHECK-NEXT: movzbl %dil, %eax 199; CHECK-NEXT: andl $1, %eax 200; CHECK-NEXT: leal 4(,%rax,4), %eax 201; CHECK-NEXT: retq 202 %sel = select i1 %cond, i32 2, i32 3 203 %bo = shl i32 1, %sel 204 ret i32 %bo 205} 206 207define i32 @shl_constant_sel_setcc(i32 %a) { 208; CHECK-LABEL: shl_constant_sel_setcc: 209; CHECK: # %bb.0: 210; CHECK-NEXT: xorl %eax, %eax 211; CHECK-NEXT: testb $1, %dil 212; CHECK-NEXT: sete %al 213; CHECK-NEXT: leal 4(,%rax,4), %eax 214; CHECK-NEXT: retq 215 %m = and i32 %a, 1 216 %cond = icmp ne i32 %m, 0 217 %sel = select i1 %cond, i32 2, i32 3 218 %bo = shl i32 1, %sel 219 ret i32 %bo 220} 221 222define i32 @lshr_constant_sel_constants(i1 %cond) { 223; CHECK-LABEL: lshr_constant_sel_constants: 224; CHECK: # %bb.0: 225; CHECK-NEXT: # kill: def $edi killed $edi def $rdi 226; CHECK-NEXT: andl $1, %edi 227; CHECK-NEXT: leal 8(,%rdi,8), %eax 228; CHECK-NEXT: retq 229 %sel = select i1 %cond, i32 2, i32 3 230 %bo = lshr i32 64, %sel 231 ret i32 %bo 232} 233 234define i32 @lshr_constant_sel_setcc(i32 %a) { 235; CHECK-LABEL: lshr_constant_sel_setcc: 236; CHECK: # %bb.0: 237; CHECK-NEXT: # kill: def $edi killed $edi def $rdi 238; CHECK-NEXT: andl $1, %edi 239; CHECK-NEXT: leal 8(,%rdi,8), %eax 240; CHECK-NEXT: retq 241 %m = and i32 %a, 1 242 %cond = icmp ne i32 %m, 0 243 %sel = select i1 %cond, i32 2, i32 3 244 %bo = lshr i32 64, %sel 245 ret i32 %bo 246} 247 248define i32 @ashr_constant_sel_constants(i1 %cond) { 249; CHECK-LABEL: ashr_constant_sel_constants: 250; CHECK: # %bb.0: 251; CHECK-NEXT: # kill: def $edi killed $edi def $rdi 252; CHECK-NEXT: andl $1, %edi 253; CHECK-NEXT: shll $4, %edi 254; CHECK-NEXT: leal 16(%rdi), %eax 255; CHECK-NEXT: retq 256 %sel = select i1 %cond, i32 2, i32 3 257 %bo = ashr i32 128, %sel 258 ret i32 %bo 259} 260 261define i32 @ashr_constant_sel_setcc(i32 %a) { 262; CHECK-LABEL: ashr_constant_sel_setcc: 263; CHECK: # %bb.0: 264; CHECK-NEXT: # kill: def $edi killed $edi def $rdi 265; CHECK-NEXT: andl $1, %edi 266; CHECK-NEXT: shll $4, %edi 267; CHECK-NEXT: leal 16(%rdi), %eax 268; CHECK-NEXT: retq 269 %m = and i32 %a, 1 270 %cond = icmp ne i32 %m, 0 271 %sel = select i1 %cond, i32 2, i32 3 272 %bo = ashr i32 128, %sel 273 ret i32 %bo 274} 275 276define double @fsub_constant_sel_constants(i1 %cond) { 277; CHECK-LABEL: fsub_constant_sel_constants: 278; CHECK: # %bb.0: 279; CHECK-NEXT: testb $1, %dil 280; CHECK-NEXT: jne .LBB20_1 281; CHECK-NEXT: # %bb.2: 282; CHECK-NEXT: movsd {{.*#+}} xmm0 = [-1.8200000000000003E+1,0.0E+0] 283; CHECK-NEXT: retq 284; CHECK-NEXT: .LBB20_1: 285; CHECK-NEXT: movsd {{.*#+}} xmm0 = [9.0999999999999996E+0,0.0E+0] 286; CHECK-NEXT: retq 287 %sel = select i1 %cond, double -4.0, double 23.3 288 %bo = fsub double 5.1, %sel 289 ret double %bo 290} 291 292define double @fdiv_constant_sel_constants(i1 %cond) { 293; CHECK-LABEL: fdiv_constant_sel_constants: 294; CHECK: # %bb.0: 295; CHECK-NEXT: testb $1, %dil 296; CHECK-NEXT: jne .LBB21_1 297; CHECK-NEXT: # %bb.2: 298; CHECK-NEXT: movsd {{.*#+}} xmm0 = [2.188841201716738E-1,0.0E+0] 299; CHECK-NEXT: retq 300; CHECK-NEXT: .LBB21_1: 301; CHECK-NEXT: movsd {{.*#+}} xmm0 = [-1.2749999999999999E+0,0.0E+0] 302; CHECK-NEXT: retq 303 %sel = select i1 %cond, double -4.0, double 23.3 304 %bo = fdiv double 5.1, %sel 305 ret double %bo 306} 307 308define double @frem_constant_sel_constants(i1 %cond) { 309; CHECK-LABEL: frem_constant_sel_constants: 310; CHECK: # %bb.0: 311; CHECK-NEXT: testb $1, %dil 312; CHECK-NEXT: jne .LBB22_1 313; CHECK-NEXT: # %bb.2: 314; CHECK-NEXT: movsd {{.*#+}} xmm0 = [5.0999999999999996E+0,0.0E+0] 315; CHECK-NEXT: retq 316; CHECK-NEXT: .LBB22_1: 317; CHECK-NEXT: movsd {{.*#+}} xmm0 = [1.0999999999999996E+0,0.0E+0] 318; CHECK-NEXT: retq 319 %sel = select i1 %cond, double -4.0, double 23.3 320 %bo = frem double 5.1, %sel 321 ret double %bo 322} 323 324declare i64 @llvm.cttz.i64(i64, i1) 325define i64 @cttz_64_eq_select(i64 %v) nounwind { 326; NOBMI-LABEL: cttz_64_eq_select: 327; NOBMI: # %bb.0: 328; NOBMI-NEXT: bsfq %rdi, %rcx 329; NOBMI-NEXT: movq $-1, %rax 330; NOBMI-NEXT: cmovneq %rcx, %rax 331; NOBMI-NEXT: addq $6, %rax 332; NOBMI-NEXT: retq 333; 334; BMI-LABEL: cttz_64_eq_select: 335; BMI: # %bb.0: 336; BMI-NEXT: tzcntq %rdi, %rcx 337; BMI-NEXT: movq $-1, %rax 338; BMI-NEXT: cmovaeq %rcx, %rax 339; BMI-NEXT: addq $6, %rax 340; BMI-NEXT: retq 341 342 %cnt = tail call i64 @llvm.cttz.i64(i64 %v, i1 true) 343 %tobool = icmp eq i64 %v, 0 344 %.op = add nuw nsw i64 %cnt, 6 345 %add = select i1 %tobool, i64 5, i64 %.op 346 ret i64 %add 347} 348 349define i64 @cttz_64_ne_select(i64 %v) nounwind { 350; NOBMI-LABEL: cttz_64_ne_select: 351; NOBMI: # %bb.0: 352; NOBMI-NEXT: bsfq %rdi, %rcx 353; NOBMI-NEXT: movq $-1, %rax 354; NOBMI-NEXT: cmovneq %rcx, %rax 355; NOBMI-NEXT: addq $6, %rax 356; NOBMI-NEXT: retq 357; 358; BMI-LABEL: cttz_64_ne_select: 359; BMI: # %bb.0: 360; BMI-NEXT: tzcntq %rdi, %rcx 361; BMI-NEXT: movq $-1, %rax 362; BMI-NEXT: cmovaeq %rcx, %rax 363; BMI-NEXT: addq $6, %rax 364; BMI-NEXT: retq 365 366 %cnt = tail call i64 @llvm.cttz.i64(i64 %v, i1 true) 367 %tobool = icmp ne i64 %v, 0 368 %.op = add nuw nsw i64 %cnt, 6 369 %add = select i1 %tobool, i64 %.op, i64 5 370 ret i64 %add 371} 372 373declare i32 @llvm.cttz.i32(i32, i1) 374define i32 @cttz_32_eq_select(i32 %v) nounwind { 375; NOBMI-LABEL: cttz_32_eq_select: 376; NOBMI: # %bb.0: 377; NOBMI-NEXT: bsfl %edi, %ecx 378; NOBMI-NEXT: movl $-1, %eax 379; NOBMI-NEXT: cmovnel %ecx, %eax 380; NOBMI-NEXT: addl $6, %eax 381; NOBMI-NEXT: retq 382; 383; BMI-LABEL: cttz_32_eq_select: 384; BMI: # %bb.0: 385; BMI-NEXT: tzcntl %edi, %ecx 386; BMI-NEXT: movl $-1, %eax 387; BMI-NEXT: cmovael %ecx, %eax 388; BMI-NEXT: addl $6, %eax 389; BMI-NEXT: retq 390 391 %cnt = tail call i32 @llvm.cttz.i32(i32 %v, i1 true) 392 %tobool = icmp eq i32 %v, 0 393 %.op = add nuw nsw i32 %cnt, 6 394 %add = select i1 %tobool, i32 5, i32 %.op 395 ret i32 %add 396} 397 398define i32 @cttz_32_ne_select(i32 %v) nounwind { 399; NOBMI-LABEL: cttz_32_ne_select: 400; NOBMI: # %bb.0: 401; NOBMI-NEXT: bsfl %edi, %ecx 402; NOBMI-NEXT: movl $-1, %eax 403; NOBMI-NEXT: cmovnel %ecx, %eax 404; NOBMI-NEXT: addl $6, %eax 405; NOBMI-NEXT: retq 406; 407; BMI-LABEL: cttz_32_ne_select: 408; BMI: # %bb.0: 409; BMI-NEXT: tzcntl %edi, %ecx 410; BMI-NEXT: movl $-1, %eax 411; BMI-NEXT: cmovael %ecx, %eax 412; BMI-NEXT: addl $6, %eax 413; BMI-NEXT: retq 414 415 %cnt = tail call i32 @llvm.cttz.i32(i32 %v, i1 true) 416 %tobool = icmp ne i32 %v, 0 417 %.op = add nuw nsw i32 %cnt, 6 418 %add = select i1 %tobool, i32 %.op, i32 5 419 ret i32 %add 420} 421 422; This matches the pattern emitted for __builtin_ffs 423define i32 @cttz_32_eq_select_ffs(i32 %v) nounwind { 424; NOBMI-LABEL: cttz_32_eq_select_ffs: 425; NOBMI: # %bb.0: 426; NOBMI-NEXT: bsfl %edi, %ecx 427; NOBMI-NEXT: movl $-1, %eax 428; NOBMI-NEXT: cmovnel %ecx, %eax 429; NOBMI-NEXT: incl %eax 430; NOBMI-NEXT: retq 431; 432; BMI-LABEL: cttz_32_eq_select_ffs: 433; BMI: # %bb.0: 434; BMI-NEXT: tzcntl %edi, %ecx 435; BMI-NEXT: movl $-1, %eax 436; BMI-NEXT: cmovael %ecx, %eax 437; BMI-NEXT: incl %eax 438; BMI-NEXT: retq 439 440 %cnt = tail call i32 @llvm.cttz.i32(i32 %v, i1 true) 441 %tobool = icmp eq i32 %v, 0 442 %.op = add nuw nsw i32 %cnt, 1 443 %add = select i1 %tobool, i32 0, i32 %.op 444 ret i32 %add 445} 446 447define i32 @cttz_32_ne_select_ffs(i32 %v) nounwind { 448; NOBMI-LABEL: cttz_32_ne_select_ffs: 449; NOBMI: # %bb.0: 450; NOBMI-NEXT: bsfl %edi, %ecx 451; NOBMI-NEXT: movl $-1, %eax 452; NOBMI-NEXT: cmovnel %ecx, %eax 453; NOBMI-NEXT: incl %eax 454; NOBMI-NEXT: retq 455; 456; BMI-LABEL: cttz_32_ne_select_ffs: 457; BMI: # %bb.0: 458; BMI-NEXT: tzcntl %edi, %ecx 459; BMI-NEXT: movl $-1, %eax 460; BMI-NEXT: cmovael %ecx, %eax 461; BMI-NEXT: incl %eax 462; BMI-NEXT: retq 463 464 %cnt = tail call i32 @llvm.cttz.i32(i32 %v, i1 true) 465 %tobool = icmp ne i32 %v, 0 466 %.op = add nuw nsw i32 %cnt, 1 467 %add = select i1 %tobool, i32 %.op, i32 0 468 ret i32 %add 469} 470 471; This matches the pattern emitted for __builtin_ffs - 1 472define i32 @cttz_32_eq_select_ffs_m1(i32 %v) nounwind { 473; NOBMI-LABEL: cttz_32_eq_select_ffs_m1: 474; NOBMI: # %bb.0: 475; NOBMI-NEXT: bsfl %edi, %ecx 476; NOBMI-NEXT: movl $-1, %eax 477; NOBMI-NEXT: cmovnel %ecx, %eax 478; NOBMI-NEXT: retq 479; 480; BMI-LABEL: cttz_32_eq_select_ffs_m1: 481; BMI: # %bb.0: 482; BMI-NEXT: tzcntl %edi, %ecx 483; BMI-NEXT: movl $-1, %eax 484; BMI-NEXT: cmovael %ecx, %eax 485; BMI-NEXT: retq 486 487 %cnt = tail call i32 @llvm.cttz.i32(i32 %v, i1 true) 488 %tobool = icmp eq i32 %v, 0 489 %sel = select i1 %tobool, i32 -1, i32 %cnt 490 ret i32 %sel 491} 492 493define i32 @cttz_32_ne_select_ffs_m1(i32 %v) nounwind { 494; NOBMI-LABEL: cttz_32_ne_select_ffs_m1: 495; NOBMI: # %bb.0: 496; NOBMI-NEXT: bsfl %edi, %ecx 497; NOBMI-NEXT: movl $-1, %eax 498; NOBMI-NEXT: cmovnel %ecx, %eax 499; NOBMI-NEXT: retq 500; 501; BMI-LABEL: cttz_32_ne_select_ffs_m1: 502; BMI: # %bb.0: 503; BMI-NEXT: tzcntl %edi, %ecx 504; BMI-NEXT: movl $-1, %eax 505; BMI-NEXT: cmovael %ecx, %eax 506; BMI-NEXT: retq 507 508 %cnt = tail call i32 @llvm.cttz.i32(i32 %v, i1 true) 509 %tobool = icmp ne i32 %v, 0 510 %sel = select i1 %tobool, i32 %cnt, i32 -1 511 ret i32 %sel 512} 513