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