1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc < %s -mtriple=i686-unknown-unknown | FileCheck %s --check-prefixes=X86 3; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=-slow-incdec | FileCheck %s --check-prefixes=X64,X64-FASTINC 4; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+slow-incdec | FileCheck %s --check-prefixes=X64,X64-SLOWINC 5 6; Select of constants: control flow / conditional moves can always be replaced by logic+math (but may not be worth it?). 7; Test the zeroext/signext variants of each pattern to see if that makes a difference. 8 9; select Cond, 0, 1 --> zext (!Cond) 10 11define i32 @select_0_or_1(i1 %cond) { 12; X86-LABEL: select_0_or_1: 13; X86: # %bb.0: 14; X86-NEXT: movzbl {{[0-9]+}}(%esp), %eax 15; X86-NEXT: notb %al 16; X86-NEXT: movzbl %al, %eax 17; X86-NEXT: andl $1, %eax 18; X86-NEXT: retl 19; 20; X64-LABEL: select_0_or_1: 21; X64: # %bb.0: 22; X64-NEXT: notb %dil 23; X64-NEXT: movzbl %dil, %eax 24; X64-NEXT: andl $1, %eax 25; X64-NEXT: retq 26 %sel = select i1 %cond, i32 0, i32 1 27 ret i32 %sel 28} 29 30define i32 @select_0_or_1_zeroext(i1 zeroext %cond) { 31; X86-LABEL: select_0_or_1_zeroext: 32; X86: # %bb.0: 33; X86-NEXT: movzbl {{[0-9]+}}(%esp), %eax 34; X86-NEXT: xorb $1, %al 35; X86-NEXT: movzbl %al, %eax 36; X86-NEXT: retl 37; 38; X64-LABEL: select_0_or_1_zeroext: 39; X64: # %bb.0: 40; X64-NEXT: xorb $1, %dil 41; X64-NEXT: movzbl %dil, %eax 42; X64-NEXT: retq 43 %sel = select i1 %cond, i32 0, i32 1 44 ret i32 %sel 45} 46 47define i32 @select_0_or_1_signext(i1 signext %cond) { 48; X86-LABEL: select_0_or_1_signext: 49; X86: # %bb.0: 50; X86-NEXT: movzbl {{[0-9]+}}(%esp), %eax 51; X86-NEXT: notb %al 52; X86-NEXT: movzbl %al, %eax 53; X86-NEXT: andl $1, %eax 54; X86-NEXT: retl 55; 56; X64-LABEL: select_0_or_1_signext: 57; X64: # %bb.0: 58; X64-NEXT: notb %dil 59; X64-NEXT: movzbl %dil, %eax 60; X64-NEXT: andl $1, %eax 61; X64-NEXT: retq 62 %sel = select i1 %cond, i32 0, i32 1 63 ret i32 %sel 64} 65 66; select Cond, 1, 0 --> zext (Cond) 67 68define i32 @select_1_or_0(i1 %cond) { 69; X86-LABEL: select_1_or_0: 70; X86: # %bb.0: 71; X86-NEXT: movzbl {{[0-9]+}}(%esp), %eax 72; X86-NEXT: andl $1, %eax 73; X86-NEXT: retl 74; 75; X64-LABEL: select_1_or_0: 76; X64: # %bb.0: 77; X64-NEXT: movl %edi, %eax 78; X64-NEXT: andl $1, %eax 79; X64-NEXT: retq 80 %sel = select i1 %cond, i32 1, i32 0 81 ret i32 %sel 82} 83 84define i32 @select_1_or_0_zeroext(i1 zeroext %cond) { 85; X86-LABEL: select_1_or_0_zeroext: 86; X86: # %bb.0: 87; X86-NEXT: movzbl {{[0-9]+}}(%esp), %eax 88; X86-NEXT: retl 89; 90; X64-LABEL: select_1_or_0_zeroext: 91; X64: # %bb.0: 92; X64-NEXT: movl %edi, %eax 93; X64-NEXT: retq 94 %sel = select i1 %cond, i32 1, i32 0 95 ret i32 %sel 96} 97 98define i32 @select_1_or_0_signext(i1 signext %cond) { 99; X86-LABEL: select_1_or_0_signext: 100; X86: # %bb.0: 101; X86-NEXT: movzbl {{[0-9]+}}(%esp), %eax 102; X86-NEXT: andl $1, %eax 103; X86-NEXT: retl 104; 105; X64-LABEL: select_1_or_0_signext: 106; X64: # %bb.0: 107; X64-NEXT: movl %edi, %eax 108; X64-NEXT: andl $1, %eax 109; X64-NEXT: retq 110 %sel = select i1 %cond, i32 1, i32 0 111 ret i32 %sel 112} 113 114; select Cond, 0, -1 --> sext (!Cond) 115 116define i32 @select_0_or_neg1(i1 %cond) { 117; X86-LABEL: select_0_or_neg1: 118; X86: # %bb.0: 119; X86-NEXT: movzbl {{[0-9]+}}(%esp), %eax 120; X86-NEXT: andl $1, %eax 121; X86-NEXT: decl %eax 122; X86-NEXT: retl 123; 124; X64-LABEL: select_0_or_neg1: 125; X64: # %bb.0: 126; X64-NEXT: # kill: def $edi killed $edi def $rdi 127; X64-NEXT: andl $1, %edi 128; X64-NEXT: leal -1(%rdi), %eax 129; X64-NEXT: retq 130 %sel = select i1 %cond, i32 0, i32 -1 131 ret i32 %sel 132} 133 134define i32 @select_0_or_neg1_zeroext(i1 zeroext %cond) { 135; X86-LABEL: select_0_or_neg1_zeroext: 136; X86: # %bb.0: 137; X86-NEXT: movzbl {{[0-9]+}}(%esp), %eax 138; X86-NEXT: decl %eax 139; X86-NEXT: retl 140; 141; X64-LABEL: select_0_or_neg1_zeroext: 142; X64: # %bb.0: 143; X64-NEXT: # kill: def $edi killed $edi def $rdi 144; X64-NEXT: leal -1(%rdi), %eax 145; X64-NEXT: retq 146 %sel = select i1 %cond, i32 0, i32 -1 147 ret i32 %sel 148} 149 150define i32 @select_0_or_neg1_signext(i1 signext %cond) { 151; X86-LABEL: select_0_or_neg1_signext: 152; X86: # %bb.0: 153; X86-NEXT: movzbl {{[0-9]+}}(%esp), %eax 154; X86-NEXT: andl $1, %eax 155; X86-NEXT: decl %eax 156; X86-NEXT: retl 157; 158; X64-LABEL: select_0_or_neg1_signext: 159; X64: # %bb.0: 160; X64-NEXT: movl %edi, %eax 161; X64-NEXT: notl %eax 162; X64-NEXT: retq 163 %sel = select i1 %cond, i32 0, i32 -1 164 ret i32 %sel 165} 166 167; select Cond, -1, 0 --> sext (Cond) 168 169define i32 @select_neg1_or_0(i1 %cond) { 170; X86-LABEL: select_neg1_or_0: 171; X86: # %bb.0: 172; X86-NEXT: movzbl {{[0-9]+}}(%esp), %eax 173; X86-NEXT: andl $1, %eax 174; X86-NEXT: negl %eax 175; X86-NEXT: retl 176; 177; X64-LABEL: select_neg1_or_0: 178; X64: # %bb.0: 179; X64-NEXT: movl %edi, %eax 180; X64-NEXT: andl $1, %eax 181; X64-NEXT: negl %eax 182; X64-NEXT: retq 183 %sel = select i1 %cond, i32 -1, i32 0 184 ret i32 %sel 185} 186 187define i32 @select_neg1_or_0_zeroext(i1 zeroext %cond) { 188; X86-LABEL: select_neg1_or_0_zeroext: 189; X86: # %bb.0: 190; X86-NEXT: movzbl {{[0-9]+}}(%esp), %eax 191; X86-NEXT: negl %eax 192; X86-NEXT: retl 193; 194; X64-LABEL: select_neg1_or_0_zeroext: 195; X64: # %bb.0: 196; X64-NEXT: movl %edi, %eax 197; X64-NEXT: negl %eax 198; X64-NEXT: retq 199 %sel = select i1 %cond, i32 -1, i32 0 200 ret i32 %sel 201} 202 203define i32 @select_neg1_or_0_signext(i1 signext %cond) { 204; X86-LABEL: select_neg1_or_0_signext: 205; X86: # %bb.0: 206; X86-NEXT: movsbl {{[0-9]+}}(%esp), %eax 207; X86-NEXT: retl 208; 209; X64-LABEL: select_neg1_or_0_signext: 210; X64: # %bb.0: 211; X64-NEXT: movl %edi, %eax 212; X64-NEXT: retq 213 %sel = select i1 %cond, i32 -1, i32 0 214 ret i32 %sel 215} 216 217; select Cond, C+1, C --> add (zext Cond), C 218 219define i32 @select_Cplus1_C(i1 %cond) { 220; X86-LABEL: select_Cplus1_C: 221; X86: # %bb.0: 222; X86-NEXT: movzbl {{[0-9]+}}(%esp), %eax 223; X86-NEXT: andl $1, %eax 224; X86-NEXT: addl $41, %eax 225; X86-NEXT: retl 226; 227; X64-LABEL: select_Cplus1_C: 228; X64: # %bb.0: 229; X64-NEXT: # kill: def $edi killed $edi def $rdi 230; X64-NEXT: andl $1, %edi 231; X64-NEXT: leal 41(%rdi), %eax 232; X64-NEXT: retq 233 %sel = select i1 %cond, i32 42, i32 41 234 ret i32 %sel 235} 236 237define i32 @select_Cplus1_C_zeroext(i1 zeroext %cond) { 238; X86-LABEL: select_Cplus1_C_zeroext: 239; X86: # %bb.0: 240; X86-NEXT: movzbl {{[0-9]+}}(%esp), %eax 241; X86-NEXT: addl $41, %eax 242; X86-NEXT: retl 243; 244; X64-LABEL: select_Cplus1_C_zeroext: 245; X64: # %bb.0: 246; X64-NEXT: # kill: def $edi killed $edi def $rdi 247; X64-NEXT: leal 41(%rdi), %eax 248; X64-NEXT: retq 249 %sel = select i1 %cond, i32 42, i32 41 250 ret i32 %sel 251} 252 253define i32 @select_Cplus1_C_signext(i1 signext %cond) { 254; X86-LABEL: select_Cplus1_C_signext: 255; X86: # %bb.0: 256; X86-NEXT: movzbl {{[0-9]+}}(%esp), %eax 257; X86-NEXT: andl $1, %eax 258; X86-NEXT: addl $41, %eax 259; X86-NEXT: retl 260; 261; X64-LABEL: select_Cplus1_C_signext: 262; X64: # %bb.0: 263; X64-NEXT: movl $41, %eax 264; X64-NEXT: subl %edi, %eax 265; X64-NEXT: retq 266 %sel = select i1 %cond, i32 42, i32 41 267 ret i32 %sel 268} 269 270; select Cond, C, C+1 --> add (sext Cond), C 271 272define i32 @select_C_Cplus1(i1 %cond) { 273; X86-LABEL: select_C_Cplus1: 274; X86: # %bb.0: 275; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ecx 276; X86-NEXT: andl $1, %ecx 277; X86-NEXT: movl $42, %eax 278; X86-NEXT: subl %ecx, %eax 279; X86-NEXT: retl 280; 281; X64-LABEL: select_C_Cplus1: 282; X64: # %bb.0: 283; X64-NEXT: andl $1, %edi 284; X64-NEXT: movl $42, %eax 285; X64-NEXT: subl %edi, %eax 286; X64-NEXT: retq 287 %sel = select i1 %cond, i32 41, i32 42 288 ret i32 %sel 289} 290 291define i32 @select_C_Cplus1_zeroext(i1 zeroext %cond) { 292; X86-LABEL: select_C_Cplus1_zeroext: 293; X86: # %bb.0: 294; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ecx 295; X86-NEXT: movl $42, %eax 296; X86-NEXT: subl %ecx, %eax 297; X86-NEXT: retl 298; 299; X64-LABEL: select_C_Cplus1_zeroext: 300; X64: # %bb.0: 301; X64-NEXT: movl $42, %eax 302; X64-NEXT: subl %edi, %eax 303; X64-NEXT: retq 304 %sel = select i1 %cond, i32 41, i32 42 305 ret i32 %sel 306} 307 308define i32 @select_C_Cplus1_signext(i1 signext %cond) { 309; X86-LABEL: select_C_Cplus1_signext: 310; X86: # %bb.0: 311; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ecx 312; X86-NEXT: andl $1, %ecx 313; X86-NEXT: movl $42, %eax 314; X86-NEXT: subl %ecx, %eax 315; X86-NEXT: retl 316; 317; X64-LABEL: select_C_Cplus1_signext: 318; X64: # %bb.0: 319; X64-NEXT: # kill: def $edi killed $edi def $rdi 320; X64-NEXT: leal 42(%rdi), %eax 321; X64-NEXT: retq 322 %sel = select i1 %cond, i32 41, i32 42 323 ret i32 %sel 324} 325 326; If the constants differ by a small multiplier, use LEA. 327; select Cond, C1, C2 --> add (mul (zext Cond), C1-C2), C2 --> LEA C2(Cond * (C1-C2)) 328 329define i32 @select_lea_2(i1 zeroext %cond) { 330; X86-LABEL: select_lea_2: 331; X86: # %bb.0: 332; X86-NEXT: movzbl {{[0-9]+}}(%esp), %eax 333; X86-NEXT: negl %eax 334; X86-NEXT: orl $1, %eax 335; X86-NEXT: retl 336; 337; X64-LABEL: select_lea_2: 338; X64: # %bb.0: 339; X64-NEXT: movl %edi, %eax 340; X64-NEXT: negl %eax 341; X64-NEXT: orl $1, %eax 342; X64-NEXT: retq 343 %sel = select i1 %cond, i32 -1, i32 1 344 ret i32 %sel 345} 346 347define i64 @select_lea_3(i1 zeroext %cond) { 348; X86-LABEL: select_lea_3: 349; X86: # %bb.0: 350; X86-NEXT: cmpb $0, {{[0-9]+}}(%esp) 351; X86-NEXT: movl $-2, %eax 352; X86-NEXT: je .LBB19_1 353; X86-NEXT: # %bb.2: 354; X86-NEXT: movl $-1, %edx 355; X86-NEXT: je .LBB19_3 356; X86-NEXT: .LBB19_4: 357; X86-NEXT: retl 358; X86-NEXT: .LBB19_1: 359; X86-NEXT: movl $1, %eax 360; X86-NEXT: movl $-1, %edx 361; X86-NEXT: jne .LBB19_4 362; X86-NEXT: .LBB19_3: 363; X86-NEXT: xorl %edx, %edx 364; X86-NEXT: retl 365; 366; X64-LABEL: select_lea_3: 367; X64: # %bb.0: 368; X64-NEXT: xorb $1, %dil 369; X64-NEXT: movzbl %dil, %eax 370; X64-NEXT: leaq -2(%rax,%rax,2), %rax 371; X64-NEXT: retq 372 %sel = select i1 %cond, i64 -2, i64 1 373 ret i64 %sel 374} 375 376define i32 @select_lea_5(i1 zeroext %cond) { 377; X86-LABEL: select_lea_5: 378; X86: # %bb.0: 379; X86-NEXT: movzbl {{[0-9]+}}(%esp), %eax 380; X86-NEXT: xorb $1, %al 381; X86-NEXT: movzbl %al, %eax 382; X86-NEXT: leal -2(%eax,%eax,4), %eax 383; X86-NEXT: retl 384; 385; X64-LABEL: select_lea_5: 386; X64: # %bb.0: 387; X64-NEXT: xorb $1, %dil 388; X64-NEXT: movzbl %dil, %eax 389; X64-NEXT: leal -2(%rax,%rax,4), %eax 390; X64-NEXT: retq 391 %sel = select i1 %cond, i32 -2, i32 3 392 ret i32 %sel 393} 394 395define i64 @select_lea_9(i1 zeroext %cond) { 396; X86-LABEL: select_lea_9: 397; X86: # %bb.0: 398; X86-NEXT: cmpb $0, {{[0-9]+}}(%esp) 399; X86-NEXT: movl $-7, %eax 400; X86-NEXT: je .LBB21_1 401; X86-NEXT: # %bb.2: 402; X86-NEXT: movl $-1, %edx 403; X86-NEXT: je .LBB21_3 404; X86-NEXT: .LBB21_4: 405; X86-NEXT: retl 406; X86-NEXT: .LBB21_1: 407; X86-NEXT: movl $2, %eax 408; X86-NEXT: movl $-1, %edx 409; X86-NEXT: jne .LBB21_4 410; X86-NEXT: .LBB21_3: 411; X86-NEXT: xorl %edx, %edx 412; X86-NEXT: retl 413; 414; X64-LABEL: select_lea_9: 415; X64: # %bb.0: 416; X64-NEXT: xorb $1, %dil 417; X64-NEXT: movzbl %dil, %eax 418; X64-NEXT: leaq -7(%rax,%rax,8), %rax 419; X64-NEXT: retq 420 %sel = select i1 %cond, i64 -7, i64 2 421 ret i64 %sel 422} 423 424; Should this be 'sbb x,x' or 'sbb 0,x' with simpler LEA or add? 425 426define i64 @sel_1_2(i64 %x, i64 %y) { 427; X86-LABEL: sel_1_2: 428; X86: # %bb.0: 429; X86-NEXT: movl {{[0-9]+}}(%esp), %eax 430; X86-NEXT: movl {{[0-9]+}}(%esp), %edx 431; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx 432; X86-NEXT: cmpl $42, {{[0-9]+}}(%esp) 433; X86-NEXT: sbbl $0, %ecx 434; X86-NEXT: sbbl $0, %eax 435; X86-NEXT: sbbl $0, %edx 436; X86-NEXT: addl $2, %eax 437; X86-NEXT: adcl $0, %edx 438; X86-NEXT: retl 439; 440; X64-LABEL: sel_1_2: 441; X64: # %bb.0: 442; X64-NEXT: cmpq $42, %rdi 443; X64-NEXT: sbbq $0, %rsi 444; X64-NEXT: leaq 2(%rsi), %rax 445; X64-NEXT: retq 446 %cmp = icmp ult i64 %x, 42 447 %sel = select i1 %cmp, i64 1, i64 2 448 %sub = add i64 %sel, %y 449 ret i64 %sub 450} 451 452; No LEA with 8-bit, but this shouldn't need branches or cmov. 453 454define i8 @sel_1_neg1(i32 %x) { 455; X86-LABEL: sel_1_neg1: 456; X86: # %bb.0: 457; X86-NEXT: cmpl $43, {{[0-9]+}}(%esp) 458; X86-NEXT: setl %al 459; X86-NEXT: negb %al 460; X86-NEXT: orb $3, %al 461; X86-NEXT: retl 462; 463; X64-LABEL: sel_1_neg1: 464; X64: # %bb.0: 465; X64-NEXT: cmpl $43, %edi 466; X64-NEXT: setl %al 467; X64-NEXT: negb %al 468; X64-NEXT: orb $3, %al 469; X64-NEXT: retq 470 %cmp = icmp sgt i32 %x, 42 471 %sel = select i1 %cmp, i8 3, i8 -1 472 ret i8 %sel 473} 474 475; We get an LEA for 16-bit because we ignore the high-bits. 476 477define i16 @sel_neg1_1(i32 %x) { 478; X86-LABEL: sel_neg1_1: 479; X86: # %bb.0: 480; X86-NEXT: xorl %eax, %eax 481; X86-NEXT: cmpl $43, {{[0-9]+}}(%esp) 482; X86-NEXT: setl %al 483; X86-NEXT: leal -1(,%eax,4), %eax 484; X86-NEXT: # kill: def $ax killed $ax killed $eax 485; X86-NEXT: retl 486; 487; X64-LABEL: sel_neg1_1: 488; X64: # %bb.0: 489; X64-NEXT: xorl %eax, %eax 490; X64-NEXT: cmpl $43, %edi 491; X64-NEXT: setl %al 492; X64-NEXT: leal -1(,%rax,4), %eax 493; X64-NEXT: # kill: def $ax killed $ax killed $eax 494; X64-NEXT: retq 495 %cmp = icmp sgt i32 %x, 42 496 %sel = select i1 %cmp, i16 -1, i16 3 497 ret i16 %sel 498} 499 500; If the comparison is available, the predicate can be inverted. 501 502define i32 @sel_1_neg1_32(i32 %x) { 503; X86-LABEL: sel_1_neg1_32: 504; X86: # %bb.0: 505; X86-NEXT: xorl %eax, %eax 506; X86-NEXT: cmpl $43, {{[0-9]+}}(%esp) 507; X86-NEXT: setge %al 508; X86-NEXT: leal -1(%eax,%eax,8), %eax 509; X86-NEXT: retl 510; 511; X64-LABEL: sel_1_neg1_32: 512; X64: # %bb.0: 513; X64-NEXT: xorl %eax, %eax 514; X64-NEXT: cmpl $43, %edi 515; X64-NEXT: setge %al 516; X64-NEXT: leal -1(%rax,%rax,8), %eax 517; X64-NEXT: retq 518 %cmp = icmp sgt i32 %x, 42 519 %sel = select i1 %cmp, i32 8, i32 -1 520 ret i32 %sel 521} 522 523define i32 @sel_neg1_1_32(i32 %x) { 524; X86-LABEL: sel_neg1_1_32: 525; X86: # %bb.0: 526; X86-NEXT: xorl %eax, %eax 527; X86-NEXT: cmpl $43, {{[0-9]+}}(%esp) 528; X86-NEXT: setl %al 529; X86-NEXT: leal -7(%eax,%eax,8), %eax 530; X86-NEXT: retl 531; 532; X64-LABEL: sel_neg1_1_32: 533; X64: # %bb.0: 534; X64-NEXT: xorl %eax, %eax 535; X64-NEXT: cmpl $43, %edi 536; X64-NEXT: setl %al 537; X64-NEXT: leal -7(%rax,%rax,8), %eax 538; X64-NEXT: retq 539 %cmp = icmp sgt i32 %x, 42 540 %sel = select i1 %cmp, i32 -7, i32 2 541 ret i32 %sel 542} 543 544 545; If the constants differ by a large power-of-2, that can be a shift of the difference plus the smaller constant. 546; select Cond, C1, C2 --> add (mul (zext Cond), C1-C2), C2 547 548define i8 @select_pow2_diff(i1 zeroext %cond) { 549; X86-LABEL: select_pow2_diff: 550; X86: # %bb.0: 551; X86-NEXT: movzbl {{[0-9]+}}(%esp), %eax 552; X86-NEXT: shlb $4, %al 553; X86-NEXT: orb $3, %al 554; X86-NEXT: retl 555; 556; X64-LABEL: select_pow2_diff: 557; X64: # %bb.0: 558; X64-NEXT: # kill: def $edi killed $edi def $rdi 559; X64-NEXT: shlb $4, %dil 560; X64-NEXT: leal 3(%rdi), %eax 561; X64-NEXT: # kill: def $al killed $al killed $eax 562; X64-NEXT: retq 563 %sel = select i1 %cond, i8 19, i8 3 564 ret i8 %sel 565} 566 567define i16 @select_pow2_diff_invert(i1 zeroext %cond) { 568; X86-LABEL: select_pow2_diff_invert: 569; X86: # %bb.0: 570; X86-NEXT: movzbl {{[0-9]+}}(%esp), %eax 571; X86-NEXT: xorb $1, %al 572; X86-NEXT: movzbl %al, %eax 573; X86-NEXT: shll $6, %eax 574; X86-NEXT: orl $7, %eax 575; X86-NEXT: # kill: def $ax killed $ax killed $eax 576; X86-NEXT: retl 577; 578; X64-LABEL: select_pow2_diff_invert: 579; X64: # %bb.0: 580; X64-NEXT: xorb $1, %dil 581; X64-NEXT: movzbl %dil, %eax 582; X64-NEXT: shll $6, %eax 583; X64-NEXT: orl $7, %eax 584; X64-NEXT: # kill: def $ax killed $ax killed $eax 585; X64-NEXT: retq 586 %sel = select i1 %cond, i16 7, i16 71 587 ret i16 %sel 588} 589 590define i32 @select_pow2_diff_neg(i1 zeroext %cond) { 591; X86-LABEL: select_pow2_diff_neg: 592; X86: # %bb.0: 593; X86-NEXT: movzbl {{[0-9]+}}(%esp), %eax 594; X86-NEXT: shll $4, %eax 595; X86-NEXT: orl $-25, %eax 596; X86-NEXT: retl 597; 598; X64-LABEL: select_pow2_diff_neg: 599; X64: # %bb.0: 600; X64-NEXT: # kill: def $edi killed $edi def $rdi 601; X64-NEXT: shll $4, %edi 602; X64-NEXT: leal -25(%rdi), %eax 603; X64-NEXT: retq 604 %sel = select i1 %cond, i32 -9, i32 -25 605 ret i32 %sel 606} 607 608define i64 @select_pow2_diff_neg_invert(i1 zeroext %cond) { 609; X86-LABEL: select_pow2_diff_neg_invert: 610; X86: # %bb.0: 611; X86-NEXT: cmpb $0, {{[0-9]+}}(%esp) 612; X86-NEXT: movl $-99, %eax 613; X86-NEXT: je .LBB30_1 614; X86-NEXT: # %bb.2: 615; X86-NEXT: movl $-1, %edx 616; X86-NEXT: je .LBB30_3 617; X86-NEXT: .LBB30_4: 618; X86-NEXT: retl 619; X86-NEXT: .LBB30_1: 620; X86-NEXT: movl $29, %eax 621; X86-NEXT: movl $-1, %edx 622; X86-NEXT: jne .LBB30_4 623; X86-NEXT: .LBB30_3: 624; X86-NEXT: xorl %edx, %edx 625; X86-NEXT: retl 626; 627; X64-LABEL: select_pow2_diff_neg_invert: 628; X64: # %bb.0: 629; X64-NEXT: xorb $1, %dil 630; X64-NEXT: movzbl %dil, %eax 631; X64-NEXT: shll $7, %eax 632; X64-NEXT: addq $-99, %rax 633; X64-NEXT: retq 634 %sel = select i1 %cond, i64 -99, i64 29 635 ret i64 %sel 636} 637 638; This doesn't need a branch, but don't do the wrong thing if subtraction of the constants overflows. 639 640define i8 @sel_67_neg125(i32 %x) { 641; X86-LABEL: sel_67_neg125: 642; X86: # %bb.0: 643; X86-NEXT: cmpl $43, {{[0-9]+}}(%esp) 644; X86-NEXT: movb $67, %al 645; X86-NEXT: jge .LBB31_2 646; X86-NEXT: # %bb.1: 647; X86-NEXT: movb $-125, %al 648; X86-NEXT: .LBB31_2: 649; X86-NEXT: retl 650; 651; X64-LABEL: sel_67_neg125: 652; X64: # %bb.0: 653; X64-NEXT: cmpl $43, %edi 654; X64-NEXT: movl $67, %ecx 655; X64-NEXT: movl $131, %eax 656; X64-NEXT: cmovgel %ecx, %eax 657; X64-NEXT: # kill: def $al killed $al killed $eax 658; X64-NEXT: retq 659 %cmp = icmp sgt i32 %x, 42 660 %sel = select i1 %cmp, i8 67, i8 -125 661 ret i8 %sel 662} 663 664 665; In general, select of 2 constants could be: 666; select Cond, C1, C2 --> add (mul (zext Cond), C1-C2), C2 --> add (and (sext Cond), C1-C2), C2 667 668define i32 @select_C1_C2(i1 %cond) { 669; X86-LABEL: select_C1_C2: 670; X86: # %bb.0: 671; X86-NEXT: movzbl {{[0-9]+}}(%esp), %eax 672; X86-NEXT: andl $1, %eax 673; X86-NEXT: negl %eax 674; X86-NEXT: andl $399, %eax # imm = 0x18F 675; X86-NEXT: xorl $42, %eax 676; X86-NEXT: retl 677; 678; X64-LABEL: select_C1_C2: 679; X64: # %bb.0: 680; X64-NEXT: testb $1, %dil 681; X64-NEXT: movl $421, %ecx # imm = 0x1A5 682; X64-NEXT: movl $42, %eax 683; X64-NEXT: cmovnel %ecx, %eax 684; X64-NEXT: retq 685 %sel = select i1 %cond, i32 421, i32 42 686 ret i32 %sel 687} 688 689define i32 @select_C1_C2_zeroext(i1 zeroext %cond) { 690; X86-LABEL: select_C1_C2_zeroext: 691; X86: # %bb.0: 692; X86-NEXT: cmpb $0, {{[0-9]+}}(%esp) 693; X86-NEXT: movl $421, %eax # imm = 0x1A5 694; X86-NEXT: jne .LBB33_2 695; X86-NEXT: # %bb.1: 696; X86-NEXT: movl $42, %eax 697; X86-NEXT: .LBB33_2: 698; X86-NEXT: retl 699; 700; X64-LABEL: select_C1_C2_zeroext: 701; X64: # %bb.0: 702; X64-NEXT: testl %edi, %edi 703; X64-NEXT: movl $421, %ecx # imm = 0x1A5 704; X64-NEXT: movl $42, %eax 705; X64-NEXT: cmovnel %ecx, %eax 706; X64-NEXT: retq 707 %sel = select i1 %cond, i32 421, i32 42 708 ret i32 %sel 709} 710 711define i32 @select_C1_C2_signext(i1 signext %cond) { 712; X86-LABEL: select_C1_C2_signext: 713; X86: # %bb.0: 714; X86-NEXT: movzbl {{[0-9]+}}(%esp), %eax 715; X86-NEXT: andl $1, %eax 716; X86-NEXT: negl %eax 717; X86-NEXT: andl $399, %eax # imm = 0x18F 718; X86-NEXT: xorl $42, %eax 719; X86-NEXT: retl 720; 721; X64-LABEL: select_C1_C2_signext: 722; X64: # %bb.0: 723; X64-NEXT: testb $1, %dil 724; X64-NEXT: movl $421, %ecx # imm = 0x1A5 725; X64-NEXT: movl $42, %eax 726; X64-NEXT: cmovnel %ecx, %eax 727; X64-NEXT: retq 728 %sel = select i1 %cond, i32 421, i32 42 729 ret i32 %sel 730} 731 732define i32 @select_n_or_minus1(i1 signext %cond) { 733; X86-LABEL: select_n_or_minus1: 734; X86: # %bb.0: 735; X86-NEXT: movzbl {{[0-9]+}}(%esp), %eax 736; X86-NEXT: andl $1, %eax 737; X86-NEXT: decl %eax 738; X86-NEXT: orl $12414, %eax # imm = 0x307E 739; X86-NEXT: retl 740; 741; X64-LABEL: select_n_or_minus1: 742; X64: # %bb.0: 743; X64-NEXT: movl %edi, %eax 744; X64-NEXT: notl %eax 745; X64-NEXT: orl $12414, %eax # imm = 0x307E 746; X64-NEXT: retq 747 %sel = select i1 %cond, i32 12414, i32 -1 748 ret i32 %sel 749} 750 751; select (x == 2), 2, (x + 1) --> select (x == 2), x, (x + 1) 752 753define i64 @select_2_or_inc(i64 %x) { 754; X86-LABEL: select_2_or_inc: 755; X86: # %bb.0: 756; X86-NEXT: pushl %edi 757; X86-NEXT: .cfi_def_cfa_offset 8 758; X86-NEXT: pushl %esi 759; X86-NEXT: .cfi_def_cfa_offset 12 760; X86-NEXT: .cfi_offset %esi, -12 761; X86-NEXT: .cfi_offset %edi, -8 762; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx 763; X86-NEXT: movl {{[0-9]+}}(%esp), %esi 764; X86-NEXT: movl %ecx, %edi 765; X86-NEXT: xorl $2, %edi 766; X86-NEXT: addl $1, %ecx 767; X86-NEXT: movl %esi, %eax 768; X86-NEXT: adcl $0, %eax 769; X86-NEXT: xorl %edx, %edx 770; X86-NEXT: orl %esi, %edi 771; X86-NEXT: je .LBB36_2 772; X86-NEXT: # %bb.1: 773; X86-NEXT: movl %eax, %edx 774; X86-NEXT: .LBB36_2: 775; X86-NEXT: movl $2, %eax 776; X86-NEXT: je .LBB36_4 777; X86-NEXT: # %bb.3: 778; X86-NEXT: movl %ecx, %eax 779; X86-NEXT: .LBB36_4: 780; X86-NEXT: popl %esi 781; X86-NEXT: .cfi_def_cfa_offset 8 782; X86-NEXT: popl %edi 783; X86-NEXT: .cfi_def_cfa_offset 4 784; X86-NEXT: retl 785; 786; X64-LABEL: select_2_or_inc: 787; X64: # %bb.0: 788; X64-NEXT: leaq 1(%rdi), %rax 789; X64-NEXT: cmpq $2, %rdi 790; X64-NEXT: cmoveq %rdi, %rax 791; X64-NEXT: retq 792 %cmp = icmp eq i64 %x, 2 793 %add = add i64 %x, 1 794 %retval.0 = select i1 %cmp, i64 2, i64 %add 795 ret i64 %retval.0 796} 797 798define <4 x i32> @sel_constants_add_constant_vec(i1 %cond) { 799; X86-LABEL: sel_constants_add_constant_vec: 800; X86: # %bb.0: 801; X86-NEXT: pushl %edi 802; X86-NEXT: .cfi_def_cfa_offset 8 803; X86-NEXT: pushl %esi 804; X86-NEXT: .cfi_def_cfa_offset 12 805; X86-NEXT: .cfi_offset %esi, -12 806; X86-NEXT: .cfi_offset %edi, -8 807; X86-NEXT: movl {{[0-9]+}}(%esp), %eax 808; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ecx 809; X86-NEXT: andl $1, %ecx 810; X86-NEXT: negl %ecx 811; X86-NEXT: movl %ecx, %edx 812; X86-NEXT: andl $-15, %edx 813; X86-NEXT: orl $12, %edx 814; X86-NEXT: movl %ecx, %esi 815; X86-NEXT: andl $3, %esi 816; X86-NEXT: xorl $13, %esi 817; X86-NEXT: movl %ecx, %edi 818; X86-NEXT: andl $10, %edi 819; X86-NEXT: xorl $14, %edi 820; X86-NEXT: andl $11, %ecx 821; X86-NEXT: xorl $15, %ecx 822; X86-NEXT: movl %ecx, 12(%eax) 823; X86-NEXT: movl %edi, 8(%eax) 824; X86-NEXT: movl %esi, 4(%eax) 825; X86-NEXT: movl %edx, (%eax) 826; X86-NEXT: popl %esi 827; X86-NEXT: .cfi_def_cfa_offset 8 828; X86-NEXT: popl %edi 829; X86-NEXT: .cfi_def_cfa_offset 4 830; X86-NEXT: retl $4 831; 832; X64-LABEL: sel_constants_add_constant_vec: 833; X64: # %bb.0: 834; X64-NEXT: testb $1, %dil 835; X64-NEXT: jne .LBB37_1 836; X64-NEXT: # %bb.2: 837; X64-NEXT: movaps {{.*#+}} xmm0 = [12,13,14,15] 838; X64-NEXT: retq 839; X64-NEXT: .LBB37_1: 840; X64-NEXT: movaps {{.*#+}} xmm0 = [4294967293,14,4,4] 841; X64-NEXT: retq 842 %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> 843 %bo = add <4 x i32> %sel, <i32 1, i32 2, i32 3, i32 4> 844 ret <4 x i32> %bo 845} 846 847define <2 x double> @sel_constants_fmul_constant_vec(i1 %cond) { 848; X86-LABEL: sel_constants_fmul_constant_vec: 849; X86: # %bb.0: 850; X86-NEXT: testb $1, {{[0-9]+}}(%esp) 851; X86-NEXT: fldl {{\.?LCPI[0-9]+_[0-9]+}} 852; X86-NEXT: fldl {{\.?LCPI[0-9]+_[0-9]+}} 853; X86-NEXT: jne .LBB38_2 854; X86-NEXT: # %bb.1: 855; X86-NEXT: fstp %st(1) 856; X86-NEXT: fldz 857; X86-NEXT: .LBB38_2: 858; X86-NEXT: fstp %st(0) 859; X86-NEXT: fldl {{\.?LCPI[0-9]+_[0-9]+}} 860; X86-NEXT: fldl {{\.?LCPI[0-9]+_[0-9]+}} 861; X86-NEXT: jne .LBB38_4 862; X86-NEXT: # %bb.3: 863; X86-NEXT: fstp %st(1) 864; X86-NEXT: fldz 865; X86-NEXT: .LBB38_4: 866; X86-NEXT: fstp %st(0) 867; X86-NEXT: retl 868; 869; X64-LABEL: sel_constants_fmul_constant_vec: 870; X64: # %bb.0: 871; X64-NEXT: testb $1, %dil 872; X64-NEXT: jne .LBB38_1 873; X64-NEXT: # %bb.2: 874; X64-NEXT: movaps {{.*#+}} xmm0 = [1.1883E+2,3.4539999999999999E+1] 875; X64-NEXT: retq 876; X64-NEXT: .LBB38_1: 877; X64-NEXT: movaps {{.*#+}} xmm0 = [-2.0399999999999999E+1,3.768E+1] 878; X64-NEXT: retq 879 %sel = select i1 %cond, <2 x double> <double -4.0, double 12.0>, <2 x double> <double 23.3, double 11.0> 880 %bo = fmul <2 x double> %sel, <double 5.1, double 3.14> 881 ret <2 x double> %bo 882} 883 884; 4294967297 = 0x100000001. 885; This becomes an opaque constant via ConstantHoisting, so we don't fold it into the select. 886 887define i64 @opaque_constant(i1 %cond, i64 %x) { 888; X86-LABEL: opaque_constant: 889; X86: # %bb.0: 890; X86-NEXT: pushl %ebx 891; X86-NEXT: .cfi_def_cfa_offset 8 892; X86-NEXT: pushl %esi 893; X86-NEXT: .cfi_def_cfa_offset 12 894; X86-NEXT: .cfi_offset %esi, -12 895; X86-NEXT: .cfi_offset %ebx, -8 896; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx 897; X86-NEXT: movl {{[0-9]+}}(%esp), %esi 898; X86-NEXT: movzbl {{[0-9]+}}(%esp), %eax 899; X86-NEXT: movl %eax, %edx 900; X86-NEXT: andl $1, %edx 901; X86-NEXT: negl %edx 902; X86-NEXT: andl $1, %edx 903; X86-NEXT: decl %eax 904; X86-NEXT: andl $1, %eax 905; X86-NEXT: xorl $1, %esi 906; X86-NEXT: xorl $1, %ecx 907; X86-NEXT: xorl %ebx, %ebx 908; X86-NEXT: orl %esi, %ecx 909; X86-NEXT: sete %bl 910; X86-NEXT: subl %ebx, %eax 911; X86-NEXT: sbbl $0, %edx 912; X86-NEXT: popl %esi 913; X86-NEXT: .cfi_def_cfa_offset 8 914; X86-NEXT: popl %ebx 915; X86-NEXT: .cfi_def_cfa_offset 4 916; X86-NEXT: retl 917; 918; X64-LABEL: opaque_constant: 919; X64: # %bb.0: 920; X64-NEXT: testb $1, %dil 921; X64-NEXT: movq $-4, %rcx 922; X64-NEXT: movl $23, %eax 923; X64-NEXT: cmovneq %rcx, %rax 924; X64-NEXT: movabsq $4294967297, %rcx # imm = 0x100000001 925; X64-NEXT: andq %rcx, %rax 926; X64-NEXT: xorl %edx, %edx 927; X64-NEXT: cmpq %rcx, %rsi 928; X64-NEXT: sete %dl 929; X64-NEXT: subq %rdx, %rax 930; X64-NEXT: retq 931 %sel = select i1 %cond, i64 -4, i64 23 932 %bo = and i64 %sel, 4294967297 933 %cmp = icmp eq i64 %x, 4294967297 934 %sext = sext i1 %cmp to i64 935 %add = add i64 %bo, %sext 936 ret i64 %add 937} 938 939define float @select_undef_fp(float %x) { 940; X86-LABEL: select_undef_fp: 941; X86: # %bb.0: 942; X86-NEXT: flds {{\.?LCPI[0-9]+_[0-9]+}} 943; X86-NEXT: retl 944; 945; X64-LABEL: select_undef_fp: 946; X64: # %bb.0: 947; X64-NEXT: movss {{.*#+}} xmm0 = [4.0E+0,0.0E+0,0.0E+0,0.0E+0] 948; X64-NEXT: retq 949 %f = select i1 undef, float 4.0, float %x 950 ret float %f 951} 952 953define i32 @select_eq0_3_2(i32 %X) { 954; X86-LABEL: select_eq0_3_2: 955; X86: # %bb.0: 956; X86-NEXT: xorl %eax, %eax 957; X86-NEXT: cmpl $1, {{[0-9]+}}(%esp) 958; X86-NEXT: adcl $2, %eax 959; X86-NEXT: retl 960; 961; X64-LABEL: select_eq0_3_2: 962; X64: # %bb.0: 963; X64-NEXT: xorl %eax, %eax 964; X64-NEXT: cmpl $1, %edi 965; X64-NEXT: adcl $2, %eax 966; X64-NEXT: retq 967 %cmp = icmp eq i32 %X, 0 968 %sel = select i1 %cmp, i32 3, i32 2 969 ret i32 %sel 970} 971 972define i32 @select_ugt3_2_3(i32 %X) { 973; X86-LABEL: select_ugt3_2_3: 974; X86: # %bb.0: 975; X86-NEXT: xorl %eax, %eax 976; X86-NEXT: cmpl $4, {{[0-9]+}}(%esp) 977; X86-NEXT: adcl $2, %eax 978; X86-NEXT: retl 979; 980; X64-LABEL: select_ugt3_2_3: 981; X64: # %bb.0: 982; X64-NEXT: xorl %eax, %eax 983; X64-NEXT: cmpl $4, %edi 984; X64-NEXT: adcl $2, %eax 985; X64-NEXT: retq 986 %cmp = icmp ugt i32 %X, 3 987 %sel = select i1 %cmp, i32 2, i32 3 988 ret i32 %sel 989} 990 991define i32 @select_ult9_7_6(i32 %X) { 992; X86-LABEL: select_ult9_7_6: 993; X86: # %bb.0: 994; X86-NEXT: xorl %eax, %eax 995; X86-NEXT: cmpl $9, {{[0-9]+}}(%esp) 996; X86-NEXT: adcl $6, %eax 997; X86-NEXT: retl 998; 999; X64-LABEL: select_ult9_7_6: 1000; X64: # %bb.0: 1001; X64-NEXT: xorl %eax, %eax 1002; X64-NEXT: cmpl $9, %edi 1003; X64-NEXT: adcl $6, %eax 1004; X64-NEXT: retq 1005 %cmp = icmp ult i32 %X, 9 1006 %sel = select i1 %cmp, i32 7, i32 6 1007 ret i32 %sel 1008} 1009 1010define i32 @select_ult2_2_3(i32 %X) { 1011; X86-LABEL: select_ult2_2_3: 1012; X86: # %bb.0: 1013; X86-NEXT: cmpl $2, {{[0-9]+}}(%esp) 1014; X86-NEXT: movl $3, %eax 1015; X86-NEXT: sbbl $0, %eax 1016; X86-NEXT: retl 1017; 1018; X64-LABEL: select_ult2_2_3: 1019; X64: # %bb.0: 1020; X64-NEXT: cmpl $2, %edi 1021; X64-NEXT: movl $3, %eax 1022; X64-NEXT: sbbl $0, %eax 1023; X64-NEXT: retq 1024 %cmp = icmp ult i32 %X, 2 1025 %cond = select i1 %cmp, i32 2, i32 3 1026 ret i32 %cond 1027} 1028 1029define i32 @select_ugt3_3_2(i32 %X) { 1030; X86-LABEL: select_ugt3_3_2: 1031; X86: # %bb.0: 1032; X86-NEXT: cmpl $4, {{[0-9]+}}(%esp) 1033; X86-NEXT: movl $2, %eax 1034; X86-NEXT: sbbl $-1, %eax 1035; X86-NEXT: retl 1036; 1037; X64-LABEL: select_ugt3_3_2: 1038; X64: # %bb.0: 1039; X64-NEXT: cmpl $4, %edi 1040; X64-NEXT: movl $2, %eax 1041; X64-NEXT: sbbl $-1, %eax 1042; X64-NEXT: retq 1043 %cmp.inv = icmp ugt i32 %X, 3 1044 %cond = select i1 %cmp.inv, i32 3, i32 2 1045 ret i32 %cond 1046} 1047 1048define i32 @select_eq_1_2(i32 %a, i32 %b) { 1049; X86-LABEL: select_eq_1_2: 1050; X86: # %bb.0: 1051; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx 1052; X86-NEXT: xorl %eax, %eax 1053; X86-NEXT: cmpl {{[0-9]+}}(%esp), %ecx 1054; X86-NEXT: setne %al 1055; X86-NEXT: incl %eax 1056; X86-NEXT: retl 1057; 1058; X64-FASTINC-LABEL: select_eq_1_2: 1059; X64-FASTINC: # %bb.0: 1060; X64-FASTINC-NEXT: xorl %eax, %eax 1061; X64-FASTINC-NEXT: cmpl %esi, %edi 1062; X64-FASTINC-NEXT: setne %al 1063; X64-FASTINC-NEXT: incl %eax 1064; X64-FASTINC-NEXT: retq 1065; 1066; X64-SLOWINC-LABEL: select_eq_1_2: 1067; X64-SLOWINC: # %bb.0: 1068; X64-SLOWINC-NEXT: xorl %eax, %eax 1069; X64-SLOWINC-NEXT: cmpl %esi, %edi 1070; X64-SLOWINC-NEXT: setne %al 1071; X64-SLOWINC-NEXT: addl $1, %eax 1072; X64-SLOWINC-NEXT: retq 1073 1074 %cmp = icmp eq i32 %a, %b 1075 %cond = select i1 %cmp, i32 1, i32 2 1076 ret i32 %cond 1077} 1078