1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc -mtriple=x86_64-unknown-linux-gnu -mattr=-bmi < %s | FileCheck %s --check-prefix=CHECK-NOBMI 3; RUN: llc -mtriple=x86_64-unknown-linux-gnu -mattr=+bmi < %s | FileCheck %s --check-prefix=CHECK-BMI 4 5; https://bugs.llvm.org/show_bug.cgi?id=37104 6 7; X: [byte1][byte0] 8; Y: [byte3][byte2] 9 10define i8 @out8_constmask(i8 %x, i8 %y) { 11; CHECK-NOBMI-LABEL: out8_constmask: 12; CHECK-NOBMI: # %bb.0: 13; CHECK-NOBMI-NEXT: # kill: def $esi killed $esi def $rsi 14; CHECK-NOBMI-NEXT: # kill: def $edi killed $edi def $rdi 15; CHECK-NOBMI-NEXT: andb $15, %dil 16; CHECK-NOBMI-NEXT: andb $-16, %sil 17; CHECK-NOBMI-NEXT: leal (%rsi,%rdi), %eax 18; CHECK-NOBMI-NEXT: # kill: def $al killed $al killed $eax 19; CHECK-NOBMI-NEXT: retq 20; 21; CHECK-BMI-LABEL: out8_constmask: 22; CHECK-BMI: # %bb.0: 23; CHECK-BMI-NEXT: # kill: def $esi killed $esi def $rsi 24; CHECK-BMI-NEXT: # kill: def $edi killed $edi def $rdi 25; CHECK-BMI-NEXT: andb $15, %dil 26; CHECK-BMI-NEXT: andb $-16, %sil 27; CHECK-BMI-NEXT: leal (%rsi,%rdi), %eax 28; CHECK-BMI-NEXT: # kill: def $al killed $al killed $eax 29; CHECK-BMI-NEXT: retq 30 %mx = and i8 %x, 15 31 %my = and i8 %y, -16 32 %r = or i8 %mx, %my 33 ret i8 %r 34} 35 36define i16 @out16_constmask(i16 %x, i16 %y) { 37; CHECK-NOBMI-LABEL: out16_constmask: 38; CHECK-NOBMI: # %bb.0: 39; CHECK-NOBMI-NEXT: movzbl %dil, %eax 40; CHECK-NOBMI-NEXT: andl $-256, %esi 41; CHECK-NOBMI-NEXT: orl %esi, %eax 42; CHECK-NOBMI-NEXT: # kill: def $ax killed $ax killed $eax 43; CHECK-NOBMI-NEXT: retq 44; 45; CHECK-BMI-LABEL: out16_constmask: 46; CHECK-BMI: # %bb.0: 47; CHECK-BMI-NEXT: movzbl %dil, %eax 48; CHECK-BMI-NEXT: andl $-256, %esi 49; CHECK-BMI-NEXT: orl %esi, %eax 50; CHECK-BMI-NEXT: # kill: def $ax killed $ax killed $eax 51; CHECK-BMI-NEXT: retq 52 %mx = and i16 %x, 255 53 %my = and i16 %y, -256 54 %r = or i16 %mx, %my 55 ret i16 %r 56} 57 58define i32 @out32_constmask(i32 %x, i32 %y) { 59; CHECK-NOBMI-LABEL: out32_constmask: 60; CHECK-NOBMI: # %bb.0: 61; CHECK-NOBMI-NEXT: movzwl %di, %eax 62; CHECK-NOBMI-NEXT: andl $-65536, %esi # imm = 0xFFFF0000 63; CHECK-NOBMI-NEXT: orl %esi, %eax 64; CHECK-NOBMI-NEXT: retq 65; 66; CHECK-BMI-LABEL: out32_constmask: 67; CHECK-BMI: # %bb.0: 68; CHECK-BMI-NEXT: movzwl %di, %eax 69; CHECK-BMI-NEXT: andl $-65536, %esi # imm = 0xFFFF0000 70; CHECK-BMI-NEXT: orl %esi, %eax 71; CHECK-BMI-NEXT: retq 72 %mx = and i32 %x, 65535 73 %my = and i32 %y, -65536 74 %r = or i32 %mx, %my 75 ret i32 %r 76} 77 78define i64 @out64_constmask(i64 %x, i64 %y) { 79; CHECK-NOBMI-LABEL: out64_constmask: 80; CHECK-NOBMI: # %bb.0: 81; CHECK-NOBMI-NEXT: movl %edi, %ecx 82; CHECK-NOBMI-NEXT: movabsq $-4294967296, %rax # imm = 0xFFFFFFFF00000000 83; CHECK-NOBMI-NEXT: andq %rsi, %rax 84; CHECK-NOBMI-NEXT: orq %rcx, %rax 85; CHECK-NOBMI-NEXT: retq 86; 87; CHECK-BMI-LABEL: out64_constmask: 88; CHECK-BMI: # %bb.0: 89; CHECK-BMI-NEXT: movl %edi, %ecx 90; CHECK-BMI-NEXT: movabsq $-4294967296, %rax # imm = 0xFFFFFFFF00000000 91; CHECK-BMI-NEXT: andq %rsi, %rax 92; CHECK-BMI-NEXT: orq %rcx, %rax 93; CHECK-BMI-NEXT: retq 94 %mx = and i64 %x, 4294967295 95 %my = and i64 %y, -4294967296 96 %r = or i64 %mx, %my 97 ret i64 %r 98} 99 100;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 101; Should be the same as the previous one. 102;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 103 104define i8 @in8_constmask(i8 %x, i8 %y) { 105; CHECK-NOBMI-LABEL: in8_constmask: 106; CHECK-NOBMI: # %bb.0: 107; CHECK-NOBMI-NEXT: movl %esi, %eax 108; CHECK-NOBMI-NEXT: xorl %esi, %edi 109; CHECK-NOBMI-NEXT: andb $15, %dil 110; CHECK-NOBMI-NEXT: xorb %dil, %al 111; CHECK-NOBMI-NEXT: # kill: def $al killed $al killed $eax 112; CHECK-NOBMI-NEXT: retq 113; 114; CHECK-BMI-LABEL: in8_constmask: 115; CHECK-BMI: # %bb.0: 116; CHECK-BMI-NEXT: movl %esi, %eax 117; CHECK-BMI-NEXT: xorl %esi, %edi 118; CHECK-BMI-NEXT: andb $15, %dil 119; CHECK-BMI-NEXT: xorb %dil, %al 120; CHECK-BMI-NEXT: # kill: def $al killed $al killed $eax 121; CHECK-BMI-NEXT: retq 122 %n0 = xor i8 %x, %y 123 %n1 = and i8 %n0, 15 124 %r = xor i8 %n1, %y 125 ret i8 %r 126} 127 128define i16 @in16_constmask(i16 %x, i16 %y) { 129; CHECK-NOBMI-LABEL: in16_constmask: 130; CHECK-NOBMI: # %bb.0: 131; CHECK-NOBMI-NEXT: xorl %esi, %edi 132; CHECK-NOBMI-NEXT: movzbl %dil, %eax 133; CHECK-NOBMI-NEXT: xorl %esi, %eax 134; CHECK-NOBMI-NEXT: # kill: def $ax killed $ax killed $eax 135; CHECK-NOBMI-NEXT: retq 136; 137; CHECK-BMI-LABEL: in16_constmask: 138; CHECK-BMI: # %bb.0: 139; CHECK-BMI-NEXT: xorl %esi, %edi 140; CHECK-BMI-NEXT: movzbl %dil, %eax 141; CHECK-BMI-NEXT: xorl %esi, %eax 142; CHECK-BMI-NEXT: # kill: def $ax killed $ax killed $eax 143; CHECK-BMI-NEXT: retq 144 %n0 = xor i16 %x, %y 145 %n1 = and i16 %n0, 255 146 %r = xor i16 %n1, %y 147 ret i16 %r 148} 149 150define i32 @in32_constmask(i32 %x, i32 %y) { 151; CHECK-NOBMI-LABEL: in32_constmask: 152; CHECK-NOBMI: # %bb.0: 153; CHECK-NOBMI-NEXT: xorl %esi, %edi 154; CHECK-NOBMI-NEXT: movzwl %di, %eax 155; CHECK-NOBMI-NEXT: xorl %esi, %eax 156; CHECK-NOBMI-NEXT: retq 157; 158; CHECK-BMI-LABEL: in32_constmask: 159; CHECK-BMI: # %bb.0: 160; CHECK-BMI-NEXT: xorl %esi, %edi 161; CHECK-BMI-NEXT: movzwl %di, %eax 162; CHECK-BMI-NEXT: xorl %esi, %eax 163; CHECK-BMI-NEXT: retq 164 %n0 = xor i32 %x, %y 165 %n1 = and i32 %n0, 65535 166 %r = xor i32 %n1, %y 167 ret i32 %r 168} 169 170define i64 @in64_constmask(i64 %x, i64 %y) { 171; CHECK-NOBMI-LABEL: in64_constmask: 172; CHECK-NOBMI: # %bb.0: 173; CHECK-NOBMI-NEXT: movl %esi, %eax 174; CHECK-NOBMI-NEXT: xorl %edi, %eax 175; CHECK-NOBMI-NEXT: xorq %rsi, %rax 176; CHECK-NOBMI-NEXT: retq 177; 178; CHECK-BMI-LABEL: in64_constmask: 179; CHECK-BMI: # %bb.0: 180; CHECK-BMI-NEXT: movl %esi, %eax 181; CHECK-BMI-NEXT: xorl %edi, %eax 182; CHECK-BMI-NEXT: xorq %rsi, %rax 183; CHECK-BMI-NEXT: retq 184 %n0 = xor i64 %x, %y 185 %n1 = and i64 %n0, 4294967295 186 %r = xor i64 %n1, %y 187 ret i64 %r 188} 189 190; ============================================================================ ; 191; Constant Commutativity tests. 192; ============================================================================ ; 193 194define i32 @in_constmask_commutativity_0_1(i32 %x, i32 %y) { 195; CHECK-NOBMI-LABEL: in_constmask_commutativity_0_1: 196; CHECK-NOBMI: # %bb.0: 197; CHECK-NOBMI-NEXT: xorl %esi, %edi 198; CHECK-NOBMI-NEXT: movzwl %di, %eax 199; CHECK-NOBMI-NEXT: xorl %esi, %eax 200; CHECK-NOBMI-NEXT: retq 201; 202; CHECK-BMI-LABEL: in_constmask_commutativity_0_1: 203; CHECK-BMI: # %bb.0: 204; CHECK-BMI-NEXT: xorl %esi, %edi 205; CHECK-BMI-NEXT: movzwl %di, %eax 206; CHECK-BMI-NEXT: xorl %esi, %eax 207; CHECK-BMI-NEXT: retq 208 %n0 = xor i32 %x, %y 209 %n1 = and i32 %n0, 65535 210 %r = xor i32 %y, %n1 ; swapped 211 ret i32 %r 212} 213 214define i32 @in_constmask_commutativity_1_0(i32 %x, i32 %y) { 215; CHECK-NOBMI-LABEL: in_constmask_commutativity_1_0: 216; CHECK-NOBMI: # %bb.0: 217; CHECK-NOBMI-NEXT: xorl %edi, %esi 218; CHECK-NOBMI-NEXT: movzwl %si, %eax 219; CHECK-NOBMI-NEXT: xorl %edi, %eax 220; CHECK-NOBMI-NEXT: retq 221; 222; CHECK-BMI-LABEL: in_constmask_commutativity_1_0: 223; CHECK-BMI: # %bb.0: 224; CHECK-BMI-NEXT: xorl %edi, %esi 225; CHECK-BMI-NEXT: movzwl %si, %eax 226; CHECK-BMI-NEXT: xorl %edi, %eax 227; CHECK-BMI-NEXT: retq 228 %n0 = xor i32 %x, %y 229 %n1 = and i32 %n0, 65535 230 %r = xor i32 %n1, %x ; %x instead of %y 231 ret i32 %r 232} 233 234define i32 @in_constmask_commutativity_1_1(i32 %x, i32 %y) { 235; CHECK-NOBMI-LABEL: in_constmask_commutativity_1_1: 236; CHECK-NOBMI: # %bb.0: 237; CHECK-NOBMI-NEXT: xorl %edi, %esi 238; CHECK-NOBMI-NEXT: movzwl %si, %eax 239; CHECK-NOBMI-NEXT: xorl %edi, %eax 240; CHECK-NOBMI-NEXT: retq 241; 242; CHECK-BMI-LABEL: in_constmask_commutativity_1_1: 243; CHECK-BMI: # %bb.0: 244; CHECK-BMI-NEXT: xorl %edi, %esi 245; CHECK-BMI-NEXT: movzwl %si, %eax 246; CHECK-BMI-NEXT: xorl %edi, %eax 247; CHECK-BMI-NEXT: retq 248 %n0 = xor i32 %x, %y 249 %n1 = and i32 %n0, 65535 250 %r = xor i32 %x, %n1 ; swapped, %x instead of %y 251 ret i32 %r 252} 253 254; ============================================================================ ; 255; Y is an 'and' too. 256; ============================================================================ ; 257 258define i32 @in_complex_y0_constmask(i32 %x, i32 %y_hi, i32 %y_low) { 259; CHECK-NOBMI-LABEL: in_complex_y0_constmask: 260; CHECK-NOBMI: # %bb.0: 261; CHECK-NOBMI-NEXT: andl %edx, %esi 262; CHECK-NOBMI-NEXT: xorl %esi, %edi 263; CHECK-NOBMI-NEXT: movzwl %di, %eax 264; CHECK-NOBMI-NEXT: xorl %esi, %eax 265; CHECK-NOBMI-NEXT: retq 266; 267; CHECK-BMI-LABEL: in_complex_y0_constmask: 268; CHECK-BMI: # %bb.0: 269; CHECK-BMI-NEXT: andl %edx, %esi 270; CHECK-BMI-NEXT: xorl %esi, %edi 271; CHECK-BMI-NEXT: movzwl %di, %eax 272; CHECK-BMI-NEXT: xorl %esi, %eax 273; CHECK-BMI-NEXT: retq 274 %y = and i32 %y_hi, %y_low 275 %n0 = xor i32 %x, %y 276 %n1 = and i32 %n0, 65535 277 %r = xor i32 %n1, %y 278 ret i32 %r 279} 280 281define i32 @in_complex_y1_constmask(i32 %x, i32 %y_hi, i32 %y_low) { 282; CHECK-NOBMI-LABEL: in_complex_y1_constmask: 283; CHECK-NOBMI: # %bb.0: 284; CHECK-NOBMI-NEXT: andl %edx, %esi 285; CHECK-NOBMI-NEXT: xorl %esi, %edi 286; CHECK-NOBMI-NEXT: movzwl %di, %eax 287; CHECK-NOBMI-NEXT: xorl %esi, %eax 288; CHECK-NOBMI-NEXT: retq 289; 290; CHECK-BMI-LABEL: in_complex_y1_constmask: 291; CHECK-BMI: # %bb.0: 292; CHECK-BMI-NEXT: andl %edx, %esi 293; CHECK-BMI-NEXT: xorl %esi, %edi 294; CHECK-BMI-NEXT: movzwl %di, %eax 295; CHECK-BMI-NEXT: xorl %esi, %eax 296; CHECK-BMI-NEXT: retq 297 %y = and i32 %y_hi, %y_low 298 %n0 = xor i32 %x, %y 299 %n1 = and i32 %n0, 65535 300 %r = xor i32 %y, %n1 301 ret i32 %r 302} 303 304; ============================================================================ ; 305; Negative tests. Should not be folded. 306; ============================================================================ ; 307 308; Multi-use tests. 309 310declare void @use32(i32) nounwind 311 312define i32 @in_multiuse_A_constmask(i32 %x, i32 %y, i32 %z) nounwind { 313; CHECK-NOBMI-LABEL: in_multiuse_A_constmask: 314; CHECK-NOBMI: # %bb.0: 315; CHECK-NOBMI-NEXT: pushq %rbp 316; CHECK-NOBMI-NEXT: pushq %rbx 317; CHECK-NOBMI-NEXT: pushq %rax 318; CHECK-NOBMI-NEXT: movl %esi, %ebx 319; CHECK-NOBMI-NEXT: xorl %esi, %edi 320; CHECK-NOBMI-NEXT: movzwl %di, %ebp 321; CHECK-NOBMI-NEXT: movl %ebp, %edi 322; CHECK-NOBMI-NEXT: callq use32 323; CHECK-NOBMI-NEXT: xorl %ebx, %ebp 324; CHECK-NOBMI-NEXT: movl %ebp, %eax 325; CHECK-NOBMI-NEXT: addq $8, %rsp 326; CHECK-NOBMI-NEXT: popq %rbx 327; CHECK-NOBMI-NEXT: popq %rbp 328; CHECK-NOBMI-NEXT: retq 329; 330; CHECK-BMI-LABEL: in_multiuse_A_constmask: 331; CHECK-BMI: # %bb.0: 332; CHECK-BMI-NEXT: pushq %rbp 333; CHECK-BMI-NEXT: pushq %rbx 334; CHECK-BMI-NEXT: pushq %rax 335; CHECK-BMI-NEXT: movl %esi, %ebx 336; CHECK-BMI-NEXT: xorl %esi, %edi 337; CHECK-BMI-NEXT: movzwl %di, %ebp 338; CHECK-BMI-NEXT: movl %ebp, %edi 339; CHECK-BMI-NEXT: callq use32 340; CHECK-BMI-NEXT: xorl %ebx, %ebp 341; CHECK-BMI-NEXT: movl %ebp, %eax 342; CHECK-BMI-NEXT: addq $8, %rsp 343; CHECK-BMI-NEXT: popq %rbx 344; CHECK-BMI-NEXT: popq %rbp 345; CHECK-BMI-NEXT: retq 346 %n0 = xor i32 %x, %y 347 %n1 = and i32 %n0, 65535 348 call void @use32(i32 %n1) 349 %r = xor i32 %n1, %y 350 ret i32 %r 351} 352 353define i32 @in_multiuse_B_constmask(i32 %x, i32 %y, i32 %z) nounwind { 354; CHECK-NOBMI-LABEL: in_multiuse_B_constmask: 355; CHECK-NOBMI: # %bb.0: 356; CHECK-NOBMI-NEXT: pushq %rbp 357; CHECK-NOBMI-NEXT: pushq %rbx 358; CHECK-NOBMI-NEXT: pushq %rax 359; CHECK-NOBMI-NEXT: movl %esi, %ebx 360; CHECK-NOBMI-NEXT: xorl %esi, %edi 361; CHECK-NOBMI-NEXT: movzwl %di, %ebp 362; CHECK-NOBMI-NEXT: callq use32 363; CHECK-NOBMI-NEXT: xorl %ebx, %ebp 364; CHECK-NOBMI-NEXT: movl %ebp, %eax 365; CHECK-NOBMI-NEXT: addq $8, %rsp 366; CHECK-NOBMI-NEXT: popq %rbx 367; CHECK-NOBMI-NEXT: popq %rbp 368; CHECK-NOBMI-NEXT: retq 369; 370; CHECK-BMI-LABEL: in_multiuse_B_constmask: 371; CHECK-BMI: # %bb.0: 372; CHECK-BMI-NEXT: pushq %rbp 373; CHECK-BMI-NEXT: pushq %rbx 374; CHECK-BMI-NEXT: pushq %rax 375; CHECK-BMI-NEXT: movl %esi, %ebx 376; CHECK-BMI-NEXT: xorl %esi, %edi 377; CHECK-BMI-NEXT: movzwl %di, %ebp 378; CHECK-BMI-NEXT: callq use32 379; CHECK-BMI-NEXT: xorl %ebx, %ebp 380; CHECK-BMI-NEXT: movl %ebp, %eax 381; CHECK-BMI-NEXT: addq $8, %rsp 382; CHECK-BMI-NEXT: popq %rbx 383; CHECK-BMI-NEXT: popq %rbp 384; CHECK-BMI-NEXT: retq 385 %n0 = xor i32 %x, %y 386 %n1 = and i32 %n0, 65535 387 call void @use32(i32 %n0) 388 %r = xor i32 %n1, %y 389 ret i32 %r 390} 391 392; Various bad variants 393 394define i32 @n0_badconstmask(i32 %x, i32 %y) { 395; CHECK-NOBMI-LABEL: n0_badconstmask: 396; CHECK-NOBMI: # %bb.0: 397; CHECK-NOBMI-NEXT: movzwl %di, %eax 398; CHECK-NOBMI-NEXT: andl $-65535, %esi # imm = 0xFFFF0001 399; CHECK-NOBMI-NEXT: orl %esi, %eax 400; CHECK-NOBMI-NEXT: retq 401; 402; CHECK-BMI-LABEL: n0_badconstmask: 403; CHECK-BMI: # %bb.0: 404; CHECK-BMI-NEXT: movzwl %di, %eax 405; CHECK-BMI-NEXT: andl $-65535, %esi # imm = 0xFFFF0001 406; CHECK-BMI-NEXT: orl %esi, %eax 407; CHECK-BMI-NEXT: retq 408 %mx = and i32 %x, 65535 409 %my = and i32 %y, -65535 ; instead of -65536 410 %r = or i32 %mx, %my 411 ret i32 %r 412} 413 414define i32 @n1_thirdvar_constmask(i32 %x, i32 %y, i32 %z) { 415; CHECK-NOBMI-LABEL: n1_thirdvar_constmask: 416; CHECK-NOBMI: # %bb.0: 417; CHECK-NOBMI-NEXT: xorl %esi, %edi 418; CHECK-NOBMI-NEXT: movzwl %di, %eax 419; CHECK-NOBMI-NEXT: xorl %edx, %eax 420; CHECK-NOBMI-NEXT: retq 421; 422; CHECK-BMI-LABEL: n1_thirdvar_constmask: 423; CHECK-BMI: # %bb.0: 424; CHECK-BMI-NEXT: xorl %esi, %edi 425; CHECK-BMI-NEXT: movzwl %di, %eax 426; CHECK-BMI-NEXT: xorl %edx, %eax 427; CHECK-BMI-NEXT: retq 428 %n0 = xor i32 %x, %y 429 %n1 = and i32 %n0, 65535 430 %r = xor i32 %n1, %z ; instead of %y 431 ret i32 %r 432} 433