1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2 ; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s 3 4 ; Select of constants: control flow / conditional moves can always be replaced by logic+math (but may not be worth it?). 5 ; Test the zeroext/signext variants of each pattern to see if that makes a difference. 6 7 ; select Cond, 0, 1 --> zext (!Cond) 8 9 define i32 @select_0_or_1(i1 %cond) { 10 ; CHECK-LABEL: select_0_or_1: 11 ; CHECK: # %bb.0: 12 ; CHECK-NEXT: notb %dil 13 ; CHECK-NEXT: movzbl %dil, %eax 14 ; CHECK-NEXT: andl $1, %eax 15 ; CHECK-NEXT: retq 16 %sel = select i1 %cond, i32 0, i32 1 17 ret i32 %sel 18 } 19 20 define i32 @select_0_or_1_zeroext(i1 zeroext %cond) { 21 ; CHECK-LABEL: select_0_or_1_zeroext: 22 ; CHECK: # %bb.0: 23 ; CHECK-NEXT: xorb $1, %dil 24 ; CHECK-NEXT: movzbl %dil, %eax 25 ; CHECK-NEXT: retq 26 %sel = select i1 %cond, i32 0, i32 1 27 ret i32 %sel 28 } 29 30 define i32 @select_0_or_1_signext(i1 signext %cond) { 31 ; CHECK-LABEL: select_0_or_1_signext: 32 ; CHECK: # %bb.0: 33 ; CHECK-NEXT: notb %dil 34 ; CHECK-NEXT: movzbl %dil, %eax 35 ; CHECK-NEXT: andl $1, %eax 36 ; CHECK-NEXT: retq 37 %sel = select i1 %cond, i32 0, i32 1 38 ret i32 %sel 39 } 40 41 ; select Cond, 1, 0 --> zext (Cond) 42 43 define i32 @select_1_or_0(i1 %cond) { 44 ; CHECK-LABEL: select_1_or_0: 45 ; CHECK: # %bb.0: 46 ; CHECK-NEXT: andl $1, %edi 47 ; CHECK-NEXT: movl %edi, %eax 48 ; CHECK-NEXT: retq 49 %sel = select i1 %cond, i32 1, i32 0 50 ret i32 %sel 51 } 52 53 define i32 @select_1_or_0_zeroext(i1 zeroext %cond) { 54 ; CHECK-LABEL: select_1_or_0_zeroext: 55 ; CHECK: # %bb.0: 56 ; CHECK-NEXT: movl %edi, %eax 57 ; CHECK-NEXT: retq 58 %sel = select i1 %cond, i32 1, i32 0 59 ret i32 %sel 60 } 61 62 define i32 @select_1_or_0_signext(i1 signext %cond) { 63 ; CHECK-LABEL: select_1_or_0_signext: 64 ; CHECK: # %bb.0: 65 ; CHECK-NEXT: andl $1, %edi 66 ; CHECK-NEXT: movl %edi, %eax 67 ; CHECK-NEXT: retq 68 %sel = select i1 %cond, i32 1, i32 0 69 ret i32 %sel 70 } 71 72 ; select Cond, 0, -1 --> sext (!Cond) 73 74 define i32 @select_0_or_neg1(i1 %cond) { 75 ; CHECK-LABEL: select_0_or_neg1: 76 ; CHECK: # %bb.0: 77 ; CHECK-NEXT: # kill: def $edi killed $edi def $rdi 78 ; CHECK-NEXT: andl $1, %edi 79 ; CHECK-NEXT: leal -1(%rdi), %eax 80 ; CHECK-NEXT: retq 81 %sel = select i1 %cond, i32 0, i32 -1 82 ret i32 %sel 83 } 84 85 define i32 @select_0_or_neg1_zeroext(i1 zeroext %cond) { 86 ; CHECK-LABEL: select_0_or_neg1_zeroext: 87 ; CHECK: # %bb.0: 88 ; CHECK-NEXT: # kill: def $edi killed $edi def $rdi 89 ; CHECK-NEXT: leal -1(%rdi), %eax 90 ; CHECK-NEXT: retq 91 %sel = select i1 %cond, i32 0, i32 -1 92 ret i32 %sel 93 } 94 95 define i32 @select_0_or_neg1_signext(i1 signext %cond) { 96 ; CHECK-LABEL: select_0_or_neg1_signext: 97 ; CHECK: # %bb.0: 98 ; CHECK-NEXT: notl %edi 99 ; CHECK-NEXT: movl %edi, %eax 100 ; CHECK-NEXT: retq 101 %sel = select i1 %cond, i32 0, i32 -1 102 ret i32 %sel 103 } 104 105 ; select Cond, -1, 0 --> sext (Cond) 106 107 define i32 @select_neg1_or_0(i1 %cond) { 108 ; CHECK-LABEL: select_neg1_or_0: 109 ; CHECK: # %bb.0: 110 ; CHECK-NEXT: andl $1, %edi 111 ; CHECK-NEXT: negl %edi 112 ; CHECK-NEXT: movl %edi, %eax 113 ; CHECK-NEXT: retq 114 %sel = select i1 %cond, i32 -1, i32 0 115 ret i32 %sel 116 } 117 118 define i32 @select_neg1_or_0_zeroext(i1 zeroext %cond) { 119 ; CHECK-LABEL: select_neg1_or_0_zeroext: 120 ; CHECK: # %bb.0: 121 ; CHECK-NEXT: negl %edi 122 ; CHECK-NEXT: movl %edi, %eax 123 ; CHECK-NEXT: retq 124 %sel = select i1 %cond, i32 -1, i32 0 125 ret i32 %sel 126 } 127 128 define i32 @select_neg1_or_0_signext(i1 signext %cond) { 129 ; CHECK-LABEL: select_neg1_or_0_signext: 130 ; CHECK: # %bb.0: 131 ; CHECK-NEXT: movl %edi, %eax 132 ; CHECK-NEXT: retq 133 %sel = select i1 %cond, i32 -1, i32 0 134 ret i32 %sel 135 } 136 137 ; select Cond, C+1, C --> add (zext Cond), C 138 139 define i32 @select_Cplus1_C(i1 %cond) { 140 ; CHECK-LABEL: select_Cplus1_C: 141 ; CHECK: # %bb.0: 142 ; CHECK-NEXT: # kill: def $edi killed $edi def $rdi 143 ; CHECK-NEXT: andl $1, %edi 144 ; CHECK-NEXT: leal 41(%rdi), %eax 145 ; CHECK-NEXT: retq 146 %sel = select i1 %cond, i32 42, i32 41 147 ret i32 %sel 148 } 149 150 define i32 @select_Cplus1_C_zeroext(i1 zeroext %cond) { 151 ; CHECK-LABEL: select_Cplus1_C_zeroext: 152 ; CHECK: # %bb.0: 153 ; CHECK-NEXT: # kill: def $edi killed $edi def $rdi 154 ; CHECK-NEXT: leal 41(%rdi), %eax 155 ; CHECK-NEXT: retq 156 %sel = select i1 %cond, i32 42, i32 41 157 ret i32 %sel 158 } 159 160 define i32 @select_Cplus1_C_signext(i1 signext %cond) { 161 ; CHECK-LABEL: select_Cplus1_C_signext: 162 ; CHECK: # %bb.0: 163 ; CHECK-NEXT: movl $41, %eax 164 ; CHECK-NEXT: subl %edi, %eax 165 ; CHECK-NEXT: retq 166 %sel = select i1 %cond, i32 42, i32 41 167 ret i32 %sel 168 } 169 170 ; select Cond, C, C+1 --> add (sext Cond), C 171 172 define i32 @select_C_Cplus1(i1 %cond) { 173 ; CHECK-LABEL: select_C_Cplus1: 174 ; CHECK: # %bb.0: 175 ; CHECK-NEXT: andl $1, %edi 176 ; CHECK-NEXT: movl $42, %eax 177 ; CHECK-NEXT: subl %edi, %eax 178 ; CHECK-NEXT: retq 179 %sel = select i1 %cond, i32 41, i32 42 180 ret i32 %sel 181 } 182 183 define i32 @select_C_Cplus1_zeroext(i1 zeroext %cond) { 184 ; CHECK-LABEL: select_C_Cplus1_zeroext: 185 ; CHECK: # %bb.0: 186 ; CHECK-NEXT: movl $42, %eax 187 ; CHECK-NEXT: subl %edi, %eax 188 ; CHECK-NEXT: retq 189 %sel = select i1 %cond, i32 41, i32 42 190 ret i32 %sel 191 } 192 193 define i32 @select_C_Cplus1_signext(i1 signext %cond) { 194 ; CHECK-LABEL: select_C_Cplus1_signext: 195 ; CHECK: # %bb.0: 196 ; CHECK-NEXT: andl $1, %edi 197 ; CHECK-NEXT: movl $42, %eax 198 ; CHECK-NEXT: subl %edi, %eax 199 ; CHECK-NEXT: retq 200 %sel = select i1 %cond, i32 41, i32 42 201 ret i32 %sel 202 } 203 204 ; If the constants differ by a small multiplier, use LEA. 205 ; select Cond, C1, C2 --> add (mul (zext Cond), C1-C2), C2 --> LEA C2(Cond * (C1-C2)) 206 207 define i32 @select_lea_2(i1 zeroext %cond) { 208 ; CHECK-LABEL: select_lea_2: 209 ; CHECK: # %bb.0: 210 ; CHECK-NEXT: xorb $1, %dil 211 ; CHECK-NEXT: movzbl %dil, %eax 212 ; CHECK-NEXT: leal -1(%rax,%rax), %eax 213 ; CHECK-NEXT: retq 214 %sel = select i1 %cond, i32 -1, i32 1 215 ret i32 %sel 216 } 217 218 define i64 @select_lea_3(i1 zeroext %cond) { 219 ; CHECK-LABEL: select_lea_3: 220 ; CHECK: # %bb.0: 221 ; CHECK-NEXT: xorb $1, %dil 222 ; CHECK-NEXT: movzbl %dil, %eax 223 ; CHECK-NEXT: leaq -2(%rax,%rax,2), %rax 224 ; CHECK-NEXT: retq 225 %sel = select i1 %cond, i64 -2, i64 1 226 ret i64 %sel 227 } 228 229 define i32 @select_lea_5(i1 zeroext %cond) { 230 ; CHECK-LABEL: select_lea_5: 231 ; CHECK: # %bb.0: 232 ; CHECK-NEXT: xorb $1, %dil 233 ; CHECK-NEXT: movzbl %dil, %eax 234 ; CHECK-NEXT: leal -2(%rax,%rax,4), %eax 235 ; CHECK-NEXT: retq 236 %sel = select i1 %cond, i32 -2, i32 3 237 ret i32 %sel 238 } 239 240 define i64 @select_lea_9(i1 zeroext %cond) { 241 ; CHECK-LABEL: select_lea_9: 242 ; CHECK: # %bb.0: 243 ; CHECK-NEXT: xorb $1, %dil 244 ; CHECK-NEXT: movzbl %dil, %eax 245 ; CHECK-NEXT: leaq -7(%rax,%rax,8), %rax 246 ; CHECK-NEXT: retq 247 %sel = select i1 %cond, i64 -7, i64 2 248 ret i64 %sel 249 } 250 251 ; Should this be 'sbb x,x' or 'sbb 0,x' with simpler LEA or add? 252 253 define i64 @sel_1_2(i64 %x, i64 %y) { 254 ; CHECK-LABEL: sel_1_2: 255 ; CHECK: # %bb.0: 256 ; CHECK-NEXT: cmpq $42, %rdi 257 ; CHECK-NEXT: sbbq $0, %rsi 258 ; CHECK-NEXT: leaq 2(%rsi), %rax 259 ; CHECK-NEXT: retq 260 %cmp = icmp ult i64 %x, 42 261 %sel = select i1 %cmp, i64 1, i64 2 262 %sub = add i64 %sel, %y 263 ret i64 %sub 264 } 265 266 ; No LEA with 8-bit, but this shouldn't need branches or cmov. 267 268 define i8 @sel_1_neg1(i32 %x) { 269 ; CHECK-LABEL: sel_1_neg1: 270 ; CHECK: # %bb.0: 271 ; CHECK-NEXT: cmpl $42, %edi 272 ; CHECK-NEXT: setg %al 273 ; CHECK-NEXT: shlb $2, %al 274 ; CHECK-NEXT: decb %al 275 ; CHECK-NEXT: retq 276 %cmp = icmp sgt i32 %x, 42 277 %sel = select i1 %cmp, i8 3, i8 -1 278 ret i8 %sel 279 } 280 281 ; We get an LEA for 16-bit because we ignore the high-bits. 282 283 define i16 @sel_neg1_1(i32 %x) { 284 ; CHECK-LABEL: sel_neg1_1: 285 ; CHECK: # %bb.0: 286 ; CHECK-NEXT: xorl %eax, %eax 287 ; CHECK-NEXT: cmpl $43, %edi 288 ; CHECK-NEXT: setl %al 289 ; CHECK-NEXT: leal -1(,%rax,4), %eax 290 ; CHECK-NEXT: # kill: def $ax killed $ax killed $eax 291 ; CHECK-NEXT: retq 292 %cmp = icmp sgt i32 %x, 42 293 %sel = select i1 %cmp, i16 -1, i16 3 294 ret i16 %sel 295 } 296 297 ; If the comparison is available, the predicate can be inverted. 298 299 define i32 @sel_1_neg1_32(i32 %x) { 300 ; CHECK-LABEL: sel_1_neg1_32: 301 ; CHECK: # %bb.0: 302 ; CHECK-NEXT: xorl %eax, %eax 303 ; CHECK-NEXT: cmpl $42, %edi 304 ; CHECK-NEXT: setg %al 305 ; CHECK-NEXT: leal -1(%rax,%rax,8), %eax 306 ; CHECK-NEXT: retq 307 %cmp = icmp sgt i32 %x, 42 308 %sel = select i1 %cmp, i32 8, i32 -1 309 ret i32 %sel 310 } 311 312 define i32 @sel_neg1_1_32(i32 %x) { 313 ; CHECK-LABEL: sel_neg1_1_32: 314 ; CHECK: # %bb.0: 315 ; CHECK-NEXT: xorl %eax, %eax 316 ; CHECK-NEXT: cmpl $43, %edi 317 ; CHECK-NEXT: setl %al 318 ; CHECK-NEXT: leal -7(%rax,%rax,8), %eax 319 ; CHECK-NEXT: retq 320 %cmp = icmp sgt i32 %x, 42 321 %sel = select i1 %cmp, i32 -7, i32 2 322 ret i32 %sel 323 } 324 325 326 ; If the constants differ by a large power-of-2, that can be a shift of the difference plus the smaller constant. 327 ; select Cond, C1, C2 --> add (mul (zext Cond), C1-C2), C2 328 329 define i8 @select_pow2_diff(i1 zeroext %cond) { 330 ; CHECK-LABEL: select_pow2_diff: 331 ; CHECK: # %bb.0: 332 ; CHECK-NEXT: shlb $4, %dil 333 ; CHECK-NEXT: orb $3, %dil 334 ; CHECK-NEXT: movl %edi, %eax 335 ; CHECK-NEXT: retq 336 %sel = select i1 %cond, i8 19, i8 3 337 ret i8 %sel 338 } 339 340 define i16 @select_pow2_diff_invert(i1 zeroext %cond) { 341 ; CHECK-LABEL: select_pow2_diff_invert: 342 ; CHECK: # %bb.0: 343 ; CHECK-NEXT: xorb $1, %dil 344 ; CHECK-NEXT: movzbl %dil, %eax 345 ; CHECK-NEXT: shll $6, %eax 346 ; CHECK-NEXT: orl $7, %eax 347 ; CHECK-NEXT: # kill: def $ax killed $ax killed $eax 348 ; CHECK-NEXT: retq 349 %sel = select i1 %cond, i16 7, i16 71 350 ret i16 %sel 351 } 352 353 define i32 @select_pow2_diff_neg(i1 zeroext %cond) { 354 ; CHECK-LABEL: select_pow2_diff_neg: 355 ; CHECK: # %bb.0: 356 ; CHECK-NEXT: shlb $4, %dil 357 ; CHECK-NEXT: movzbl %dil, %eax 358 ; CHECK-NEXT: orl $-25, %eax 359 ; CHECK-NEXT: retq 360 %sel = select i1 %cond, i32 -9, i32 -25 361 ret i32 %sel 362 } 363 364 define i64 @select_pow2_diff_neg_invert(i1 zeroext %cond) { 365 ; CHECK-LABEL: select_pow2_diff_neg_invert: 366 ; CHECK: # %bb.0: 367 ; CHECK-NEXT: xorb $1, %dil 368 ; CHECK-NEXT: movzbl %dil, %eax 369 ; CHECK-NEXT: shlq $7, %rax 370 ; CHECK-NEXT: addq $-99, %rax 371 ; CHECK-NEXT: retq 372 %sel = select i1 %cond, i64 -99, i64 29 373 ret i64 %sel 374 } 375 376 ; This doesn't need a branch, but don't do the wrong thing if subtraction of the constants overflows. 377 378 define i8 @sel_67_neg125(i32 %x) { 379 ; CHECK-LABEL: sel_67_neg125: 380 ; CHECK: # %bb.0: 381 ; CHECK-NEXT: cmpl $42, %edi 382 ; CHECK-NEXT: movb $67, %al 383 ; CHECK-NEXT: jg .LBB31_2 384 ; CHECK-NEXT: # %bb.1: 385 ; CHECK-NEXT: movb $-125, %al 386 ; CHECK-NEXT: .LBB31_2: 387 ; CHECK-NEXT: retq 388 %cmp = icmp sgt i32 %x, 42 389 %sel = select i1 %cmp, i8 67, i8 -125 390 ret i8 %sel 391 } 392 393 394 ; In general, select of 2 constants could be: 395 ; select Cond, C1, C2 --> add (mul (zext Cond), C1-C2), C2 --> add (and (sext Cond), C1-C2), C2 396 397 define i32 @select_C1_C2(i1 %cond) { 398 ; CHECK-LABEL: select_C1_C2: 399 ; CHECK: # %bb.0: 400 ; CHECK-NEXT: testb $1, %dil 401 ; CHECK-NEXT: movl $421, %ecx # imm = 0x1A5 402 ; CHECK-NEXT: movl $42, %eax 403 ; CHECK-NEXT: cmovnel %ecx, %eax 404 ; CHECK-NEXT: retq 405 %sel = select i1 %cond, i32 421, i32 42 406 ret i32 %sel 407 } 408 409 define i32 @select_C1_C2_zeroext(i1 zeroext %cond) { 410 ; CHECK-LABEL: select_C1_C2_zeroext: 411 ; CHECK: # %bb.0: 412 ; CHECK-NEXT: testl %edi, %edi 413 ; CHECK-NEXT: movl $421, %ecx # imm = 0x1A5 414 ; CHECK-NEXT: movl $42, %eax 415 ; CHECK-NEXT: cmovnel %ecx, %eax 416 ; CHECK-NEXT: retq 417 %sel = select i1 %cond, i32 421, i32 42 418 ret i32 %sel 419 } 420 421 define i32 @select_C1_C2_signext(i1 signext %cond) { 422 ; CHECK-LABEL: select_C1_C2_signext: 423 ; CHECK: # %bb.0: 424 ; CHECK-NEXT: testb $1, %dil 425 ; CHECK-NEXT: movl $421, %ecx # imm = 0x1A5 426 ; CHECK-NEXT: movl $42, %eax 427 ; CHECK-NEXT: cmovnel %ecx, %eax 428 ; CHECK-NEXT: retq 429 %sel = select i1 %cond, i32 421, i32 42 430 ret i32 %sel 431 } 432 433 ; select (x == 2), 2, (x + 1) --> select (x == 2), x, (x + 1) 434 435 define i64 @select_2_or_inc(i64 %x) { 436 ; CHECK-LABEL: select_2_or_inc: 437 ; CHECK: # %bb.0: 438 ; CHECK-NEXT: leaq 1(%rdi), %rax 439 ; CHECK-NEXT: cmpq $2, %rdi 440 ; CHECK-NEXT: cmoveq %rdi, %rax 441 ; CHECK-NEXT: retq 442 %cmp = icmp eq i64 %x, 2 443 %add = add i64 %x, 1 444 %retval.0 = select i1 %cmp, i64 2, i64 %add 445 ret i64 %retval.0 446 } 447 448 define <4 x i32> @sel_constants_add_constant_vec(i1 %cond) { 449 ; CHECK-LABEL: sel_constants_add_constant_vec: 450 ; CHECK: # %bb.0: 451 ; CHECK-NEXT: testb $1, %dil 452 ; CHECK-NEXT: jne .LBB36_1 453 ; CHECK-NEXT: # %bb.2: 454 ; CHECK-NEXT: movaps {{.*#+}} xmm0 = [12,13,14,15] 455 ; CHECK-NEXT: retq 456 ; CHECK-NEXT: .LBB36_1: 457 ; CHECK-NEXT: movaps {{.*#+}} xmm0 = [4294967293,14,4,4] 458 ; CHECK-NEXT: retq 459 %sel = select i1 %cond, <4 x i32> <i32 -4, i32 12, i32 1, i32 0>, <4 x i32> <i32 11, i32 11, i32 11, i32 11> 460 %bo = add <4 x i32> %sel, <i32 1, i32 2, i32 3, i32 4> 461 ret <4 x i32> %bo 462 } 463 464 define <2 x double> @sel_constants_fmul_constant_vec(i1 %cond) { 465 ; CHECK-LABEL: sel_constants_fmul_constant_vec: 466 ; CHECK: # %bb.0: 467 ; CHECK-NEXT: testb $1, %dil 468 ; CHECK-NEXT: jne .LBB37_1 469 ; CHECK-NEXT: # %bb.2: 470 ; CHECK-NEXT: movaps {{.*#+}} xmm0 = [1.188300e+02,3.454000e+01] 471 ; CHECK-NEXT: retq 472 ; CHECK-NEXT: .LBB37_1: 473 ; CHECK-NEXT: movaps {{.*#+}} xmm0 = [-2.040000e+01,3.768000e+01] 474 ; CHECK-NEXT: retq 475 %sel = select i1 %cond, <2 x double> <double -4.0, double 12.0>, <2 x double> <double 23.3, double 11.0> 476 %bo = fmul <2 x double> %sel, <double 5.1, double 3.14> 477 ret <2 x double> %bo 478 } 479 480 ; 4294967297 = 0x100000001. 481 ; This becomes an opaque constant via ConstantHoisting, so we don't fold it into the select. 482 483 define i64 @opaque_constant(i1 %cond, i64 %x) { 484 ; CHECK-LABEL: opaque_constant: 485 ; CHECK: # %bb.0: 486 ; CHECK-NEXT: testb $1, %dil 487 ; CHECK-NEXT: movl $23, %ecx 488 ; CHECK-NEXT: movq $-4, %rax 489 ; CHECK-NEXT: cmoveq %rcx, %rax 490 ; CHECK-NEXT: movabsq $4294967297, %rcx # imm = 0x100000001 491 ; CHECK-NEXT: andq %rcx, %rax 492 ; CHECK-NEXT: xorl %edx, %edx 493 ; CHECK-NEXT: cmpq %rcx, %rsi 494 ; CHECK-NEXT: sete %dl 495 ; CHECK-NEXT: subq %rdx, %rax 496 ; CHECK-NEXT: retq 497 %sel = select i1 %cond, i64 -4, i64 23 498 %bo = and i64 %sel, 4294967297 499 %cmp = icmp eq i64 %x, 4294967297 500 %sext = sext i1 %cmp to i64 501 %add = add i64 %bo, %sext 502 ret i64 %add 503 } 504 505