diff --git a/llvm/test/CodeGen/X86/const-shift-with-and.ll b/llvm/test/CodeGen/X86/const-shift-with-and.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/X86/const-shift-with-and.ll @@ -0,0 +1,549 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple=i686-unknown-unknown | FileCheck %s --check-prefix=X86 +; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s --check-prefix=X64 + +define i64 @and_shr_from_mask_i64(i64 %x) nounwind { +; X86-LABEL: and_shr_from_mask_i64: +; X86: # %bb.0: +; X86-NEXT: movzbl {{[0-9]+}}(%esp), %eax +; X86-NEXT: shrl $4, %eax +; X86-NEXT: xorl %edx, %edx +; X86-NEXT: retl +; +; X64-LABEL: and_shr_from_mask_i64: +; X64: # %bb.0: +; X64-NEXT: movzbl %dil, %eax +; X64-NEXT: shrq $4, %rax +; X64-NEXT: retq + %and = and i64 %x, 255 + %shr = lshr i64 %and, 4 + ret i64 %shr +} + +define i32 @shr_and_from_mask_i32(i32 %x) nounwind { +; X86-LABEL: shr_and_from_mask_i32: +; X86: # %bb.0: +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: shrl $6, %eax +; X86-NEXT: movzwl %ax, %eax +; X86-NEXT: retl +; +; X64-LABEL: shr_and_from_mask_i32: +; X64: # %bb.0: +; X64-NEXT: shrl $6, %edi +; X64-NEXT: movzwl %di, %eax +; X64-NEXT: retq + %shr = lshr i32 %x, 6 + %and = and i32 %shr, 65535 + ret i32 %and +} + +define i64 @and_shl_from_mask_i64(i64 %x) nounwind { +; X86-LABEL: and_shl_from_mask_i64: +; X86: # %bb.0: +; X86-NEXT: movzwl {{[0-9]+}}(%esp), %eax +; X86-NEXT: shll $8, %eax +; X86-NEXT: xorl %edx, %edx +; X86-NEXT: retl +; +; X64-LABEL: and_shl_from_mask_i64: +; X64: # %bb.0: +; X64-NEXT: movzwl %di, %eax +; X64-NEXT: shlq $8, %rax +; X64-NEXT: retq + %and = and i64 %x, 65535 + %shl = shl i64 %and, 8 + ret i64 %shl +} + +define i16 @shl_and_from_mask_i16(i16 %x) nounwind { +; X86-LABEL: shl_and_from_mask_i16: +; X86: # %bb.0: +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: shll $3, %eax +; X86-NEXT: movzbl %al, %eax +; X86-NEXT: # kill: def $ax killed $ax killed $eax +; X86-NEXT: retl +; +; X64-LABEL: shl_and_from_mask_i16: +; X64: # %bb.0: +; X64-NEXT: shll $3, %edi +; X64-NEXT: movzbl %dil, %eax +; X64-NEXT: # kill: def $ax killed $ax killed $eax +; X64-NEXT: retq + %shl = shl i16 %x, 3 + %and = and i16 %shl, 255 + ret i16 %and +} + +define i64 @and_shr_to_mask_i64(i64 %x) nounwind { +; X86-LABEL: and_shr_to_mask_i64: +; X86: # %bb.0: +; X86-NEXT: movzbl {{[0-9]+}}(%esp), %eax +; X86-NEXT: shrl $4, %eax +; X86-NEXT: xorl %edx, %edx +; X86-NEXT: retl +; +; X64-LABEL: and_shr_to_mask_i64: +; X64: # %bb.0: +; X64-NEXT: movzbl %dil, %eax +; X64-NEXT: shrq $4, %rax +; X64-NEXT: retq + %and = and i64 %x, 240 + %shr = lshr i64 %and, 4 + ret i64 %shr +} + +define i32 @shr_and_to_mask_i32(i32 %x) nounwind { +; X86-LABEL: shr_and_to_mask_i32: +; X86: # %bb.0: +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: shrl $6, %eax +; X86-NEXT: andl $1023, %eax # imm = 0x3FF +; X86-NEXT: retl +; +; X64-LABEL: shr_and_to_mask_i32: +; X64: # %bb.0: +; X64-NEXT: movl %edi, %eax +; X64-NEXT: shrl $6, %eax +; X64-NEXT: andl $1023, %eax # imm = 0x3FF +; X64-NEXT: retq + %shr = lshr i32 %x, 6 + %and = and i32 %shr, 1023 + ret i32 %and +} + +define i64 @and_shl_to_mask_i64(i64 %x) nounwind { +; X86-LABEL: and_shl_to_mask_i64: +; X86: # %bb.0: +; X86-NEXT: movl $511, %eax # imm = 0x1FF +; X86-NEXT: andl {{[0-9]+}}(%esp), %eax +; X86-NEXT: shll $7, %eax +; X86-NEXT: xorl %edx, %edx +; X86-NEXT: retl +; +; X64-LABEL: and_shl_to_mask_i64: +; X64: # %bb.0: +; X64-NEXT: movq %rdi, %rax +; X64-NEXT: andl $511, %eax # imm = 0x1FF +; X64-NEXT: shlq $7, %rax +; X64-NEXT: retq + %and = and i64 %x, 511 + %shl = shl i64 %and, 7 + ret i64 %shl +} + +define i16 @shl_and_to_mask_i16(i16 %x) nounwind { +; X86-LABEL: shl_and_to_mask_i16: +; X86: # %bb.0: +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: addl %eax, %eax +; X86-NEXT: movzbl %al, %eax +; X86-NEXT: # kill: def $ax killed $ax killed $eax +; X86-NEXT: retl +; +; X64-LABEL: shl_and_to_mask_i16: +; X64: # %bb.0: +; X64-NEXT: addl %edi, %edi +; X64-NEXT: movzbl %dil, %eax +; X64-NEXT: # kill: def $ax killed $ax killed $eax +; X64-NEXT: retq + %shl = shl i16 %x, 1 + %and = and i16 %shl, 254 + ret i16 %and +} + +define i64 @shr_and_from_shrink_i64(i64 %x) nounwind { +; X86-LABEL: shr_and_from_shrink_i64: +; X86: # %bb.0: +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: shrl $6, %eax +; X86-NEXT: andl $511, %eax # imm = 0x1FF +; X86-NEXT: xorl %edx, %edx +; X86-NEXT: retl +; +; X64-LABEL: shr_and_from_shrink_i64: +; X64: # %bb.0: +; X64-NEXT: movq %rdi, %rax +; X64-NEXT: shrl $6, %eax +; X64-NEXT: andl $511, %eax # imm = 0x1FF +; X64-NEXT: retq + %shr = lshr i64 %x, 6 + %and = and i64 %shr, 511 + ret i64 %and +} + +define i32 @and_shl_from_shrink_i32(i32 %x) nounwind { +; X86-LABEL: and_shl_from_shrink_i32: +; X86: # %bb.0: +; X86-NEXT: movl $511, %eax # imm = 0x1FF +; X86-NEXT: andl {{[0-9]+}}(%esp), %eax +; X86-NEXT: shll $8, %eax +; X86-NEXT: retl +; +; X64-LABEL: and_shl_from_shrink_i32: +; X64: # %bb.0: +; X64-NEXT: movl %edi, %eax +; X64-NEXT: andl $511, %eax # imm = 0x1FF +; X64-NEXT: shll $8, %eax +; X64-NEXT: retq + %and = and i32 %x, 511 + %shl = shl i32 %and, 8 + ret i32 %shl +} + +define i64 @and_shr_to_shrink_i64(i64 %x) nounwind { +; X86-LABEL: and_shr_to_shrink_i64: +; X86: # %bb.0: +; X86-NEXT: movl $64704, %eax # imm = 0xFCC0 +; X86-NEXT: andl {{[0-9]+}}(%esp), %eax +; X86-NEXT: shrl $6, %eax +; X86-NEXT: xorl %edx, %edx +; X86-NEXT: retl +; +; X64-LABEL: and_shr_to_shrink_i64: +; X64: # %bb.0: +; X64-NEXT: movq %rdi, %rax +; X64-NEXT: andl $64704, %eax # imm = 0xFCC0 +; X64-NEXT: shrq $6, %rax +; X64-NEXT: retq + %and = and i64 %x, 64704 + %shr = lshr i64 %and, 6 + ret i64 %shr +} + +define i32 @shl_and_to_shrink_i32(i32 %x) nounwind { +; X86-LABEL: shl_and_to_shrink_i32: +; X86: # %bb.0: +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: shll $8, %eax +; X86-NEXT: andl $130816, %eax # imm = 0x1FF00 +; X86-NEXT: retl +; +; X64-LABEL: shl_and_to_shrink_i32: +; X64: # %bb.0: +; X64-NEXT: movl %edi, %eax +; X64-NEXT: shll $8, %eax +; X64-NEXT: andl $130816, %eax # imm = 0x1FF00 +; X64-NEXT: retq + %shl = shl i32 %x, 8 + %and = and i32 %shl, 131071 + ret i32 %and +} + +define i64 @shr_and_from_shrink8_i64(i64 %x) nounwind { +; X86-LABEL: shr_and_from_shrink8_i64: +; X86: # %bb.0: +; X86-NEXT: movzwl {{[0-9]+}}(%esp), %eax +; X86-NEXT: andl $63, %eax +; X86-NEXT: xorl %edx, %edx +; X86-NEXT: retl +; +; X64-LABEL: shr_and_from_shrink8_i64: +; X64: # %bb.0: +; X64-NEXT: movq %rdi, %rax +; X64-NEXT: shrl $16, %eax +; X64-NEXT: andl $63, %eax +; X64-NEXT: retq + %shr = lshr i64 %x, 16 + %and = and i64 %shr, 63 + ret i64 %and +} + +define i16 @and_shl_from_shrink8_i16(i16 %x) nounwind { +; X86-LABEL: and_shl_from_shrink8_i16: +; X86: # %bb.0: +; X86-NEXT: movzwl {{[0-9]+}}(%esp), %eax +; X86-NEXT: andl $63, %eax +; X86-NEXT: shll $5, %eax +; X86-NEXT: # kill: def $ax killed $ax killed $eax +; X86-NEXT: retl +; +; X64-LABEL: and_shl_from_shrink8_i16: +; X64: # %bb.0: +; X64-NEXT: movl %edi, %eax +; X64-NEXT: andl $63, %eax +; X64-NEXT: shll $5, %eax +; X64-NEXT: # kill: def $ax killed $ax killed $eax +; X64-NEXT: retq + %and = and i16 %x, 63 + %shl = shl i16 %and, 5 + ret i16 %shl +} + +define i64 @and_shr_to_shrink8_i64(i64 %x) nounwind { +; X86-LABEL: and_shr_to_shrink8_i64: +; X86: # %bb.0: +; X86-NEXT: movzwl {{[0-9]+}}(%esp), %eax +; X86-NEXT: andl $63, %eax +; X86-NEXT: xorl %edx, %edx +; X86-NEXT: retl +; +; X64-LABEL: and_shr_to_shrink8_i64: +; X64: # %bb.0: +; X64-NEXT: movq %rdi, %rax +; X64-NEXT: shrl $16, %eax +; X64-NEXT: andl $63, %eax +; X64-NEXT: retq + %and = and i64 %x, 4128768 + %shr = lshr i64 %and, 16 + ret i64 %shr +} + +define i32 @shl_and_to_shrink8_i32(i32 %x) nounwind { +; X86-LABEL: shl_and_to_shrink8_i32: +; X86: # %bb.0: +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: andl $63, %eax +; X86-NEXT: shll $5, %eax +; X86-NEXT: retl +; +; X64-LABEL: shl_and_to_shrink8_i32: +; X64: # %bb.0: +; X64-NEXT: movl %edi, %eax +; X64-NEXT: andl $63, %eax +; X64-NEXT: shll $5, %eax +; X64-NEXT: retq + %shl = shl i32 %x, 5 + %and = and i32 %shl, 2016 + ret i32 %and +} + +define i64 @shr_and_from_shrink32_i64(i64 %x) nounwind { +; X86-LABEL: shr_and_from_shrink32_i64: +; X86: # %bb.0: +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: shll $16, %eax +; X86-NEXT: andl $536870912, %eax # imm = 0x20000000 +; X86-NEXT: xorl %edx, %edx +; X86-NEXT: retl +; +; X64-LABEL: shr_and_from_shrink32_i64: +; X64: # %bb.0: +; X64-NEXT: movq %rdi, %rax +; X64-NEXT: shrq $16, %rax +; X64-NEXT: andl $536870912, %eax # imm = 0x20000000 +; X64-NEXT: retq + %shr = lshr i64 %x, 16 + %and = and i64 %shr, 536870912 + ret i64 %and +} + +define i64 @and_shl_from_shrink32_i64(i64 %x) nounwind { +; X86-LABEL: and_shl_from_shrink32_i64: +; X86: # %bb.0: +; X86-NEXT: movl $-447369324, %edx # imm = 0xE555AF94 +; X86-NEXT: andl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl %edx, %eax +; X86-NEXT: shll $5, %eax +; X86-NEXT: shrl $27, %edx +; X86-NEXT: retl +; +; X64-LABEL: and_shl_from_shrink32_i64: +; X64: # %bb.0: +; X64-NEXT: movq %rdi, %rax +; X64-NEXT: andl $-447369324, %eax # imm = 0xE555AF94 +; X64-NEXT: shlq $5, %rax +; X64-NEXT: retq + %and = and i64 %x, 3847597972 + %shl = shl i64 %and, 5 + ret i64 %shl +} + +define i64 @and_shr_to_shrink32_i64(i64 %x) nounwind { +; X86-LABEL: and_shr_to_shrink32_i64: +; X86: # %bb.0: +; X86-NEXT: movl $8192, %eax # imm = 0x2000 +; X86-NEXT: andl {{[0-9]+}}(%esp), %eax +; X86-NEXT: shll $16, %eax +; X86-NEXT: xorl %edx, %edx +; X86-NEXT: retl +; +; X64-LABEL: and_shr_to_shrink32_i64: +; X64: # %bb.0: +; X64-NEXT: movq %rdi, %rax +; X64-NEXT: shrq $16, %rax +; X64-NEXT: andl $536870912, %eax # imm = 0x20000000 +; X64-NEXT: retq + %and = and i64 %x, 35184372088832 + %shr = lshr i64 %and, 16 + ret i64 %shr +} + +define i64 @shl_and_to_shrink32_i64(i64 %x) nounwind { +; X86-LABEL: shl_and_to_shrink32_i64: +; X86: # %bb.0: +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, %edx +; X86-NEXT: shrl $27, %edx +; X86-NEXT: shll $5, %eax +; X86-NEXT: andl $-1430916480, %eax # imm = 0xAAB5F280 +; X86-NEXT: andl $-4, %edx +; X86-NEXT: retl +; +; X64-LABEL: shl_and_to_shrink32_i64: +; X64: # %bb.0: +; X64-NEXT: movq %rdi, %rax +; X64-NEXT: andl $-447369324, %eax # imm = 0xE555AF94 +; X64-NEXT: shlq $5, %rax +; X64-NEXT: retq + %shl = shl i64 %x, 5 + %and = and i64 %shl, 123123135124 + ret i64 %and +} + +define i64 @shr_and_fail0_i64(i64 %x) nounwind { +; X86-LABEL: shr_and_fail0_i64: +; X86: # %bb.0: +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: shrl $6, %eax +; X86-NEXT: andl $240, %eax +; X86-NEXT: xorl %edx, %edx +; X86-NEXT: retl +; +; X64-LABEL: shr_and_fail0_i64: +; X64: # %bb.0: +; X64-NEXT: movq %rdi, %rax +; X64-NEXT: shrq $6, %rax +; X64-NEXT: andl $240, %eax +; X64-NEXT: retq + %shr = lshr i64 %x, 6 + %and = and i64 %shr, 240 + ret i64 %and +} + +define i32 @shr_and_fail1_i32(i32 %x) nounwind { +; X86-LABEL: shr_and_fail1_i32: +; X86: # %bb.0: +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: shrl $4, %eax +; X86-NEXT: andl $112, %eax +; X86-NEXT: retl +; +; X64-LABEL: shr_and_fail1_i32: +; X64: # %bb.0: +; X64-NEXT: movl %edi, %eax +; X64-NEXT: shrl $4, %eax +; X64-NEXT: andl $112, %eax +; X64-NEXT: retq + %shr = lshr i32 %x, 4 + %and = and i32 %shr, 112 + ret i32 %and +} + +define i64 @shr_and_fail2_i64(i64 %x) nounwind { +; X86-LABEL: shr_and_fail2_i64: +; X86: # %bb.0: +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: shrl $5, %eax +; X86-NEXT: andl $1231231, %eax # imm = 0x12C97F +; X86-NEXT: xorl %edx, %edx +; X86-NEXT: retl +; +; X64-LABEL: shr_and_fail2_i64: +; X64: # %bb.0: +; X64-NEXT: movq %rdi, %rax +; X64-NEXT: shrq $5, %rax +; X64-NEXT: andl $1231231, %eax # imm = 0x12C97F +; X64-NEXT: retq + %shr = lshr i64 %x, 5 + %and = and i64 %shr, 1231231 + ret i64 %and +} + +define i32 @shr_and_fail3_i32(i32 %x) nounwind { +; X86-LABEL: shr_and_fail3_i32: +; X86: # %bb.0: +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: shrl $7, %eax +; X86-NEXT: andl $91238, %eax # imm = 0x16466 +; X86-NEXT: retl +; +; X64-LABEL: shr_and_fail3_i32: +; X64: # %bb.0: +; X64-NEXT: movl %edi, %eax +; X64-NEXT: shrl $7, %eax +; X64-NEXT: andl $91238, %eax # imm = 0x16466 +; X64-NEXT: retq + %shr = lshr i32 %x, 7 + %and = and i32 %shr, 91238 + ret i32 %and +} + +define i64 @and_shl_fail0_i64(i64 %x) nounwind { +; X86-LABEL: and_shl_fail0_i64: +; X86: # %bb.0: +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: andl $1, %eax +; X86-NEXT: shll $5, %eax +; X86-NEXT: xorl %edx, %edx +; X86-NEXT: retl +; +; X64-LABEL: and_shl_fail0_i64: +; X64: # %bb.0: +; X64-NEXT: movq %rdi, %rax +; X64-NEXT: andl $1, %eax +; X64-NEXT: shlq $5, %rax +; X64-NEXT: retq + %and = and i64 %x, 1 + %shl = shl i64 %and, 5 + ret i64 %shl +} + +define i32 @and_shl_fail1_i32(i32 %x) nounwind { +; X86-LABEL: and_shl_fail1_i32: +; X86: # %bb.0: +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: andl $111, %eax +; X86-NEXT: shll $5, %eax +; X86-NEXT: retl +; +; X64-LABEL: and_shl_fail1_i32: +; X64: # %bb.0: +; X64-NEXT: movl %edi, %eax +; X64-NEXT: andl $111, %eax +; X64-NEXT: shll $5, %eax +; X64-NEXT: retq + %and = and i32 %x, 111 + %shl = shl i32 %and, 5 + ret i32 %shl +} + +define i64 @and_shl_fail2_i64(i64 %x) nounwind { +; X86-LABEL: and_shl_fail2_i64: +; X86: # %bb.0: +; X86-NEXT: movl $242641, %eax # imm = 0x3B3D1 +; X86-NEXT: andl {{[0-9]+}}(%esp), %eax +; X86-NEXT: shll $5, %eax +; X86-NEXT: xorl %edx, %edx +; X86-NEXT: retl +; +; X64-LABEL: and_shl_fail2_i64: +; X64: # %bb.0: +; X64-NEXT: movq %rdi, %rax +; X64-NEXT: andl $242641, %eax # imm = 0x3B3D1 +; X64-NEXT: shlq $5, %rax +; X64-NEXT: retq + %and = and i64 %x, 242641 + %shl = shl i64 %and, 5 + ret i64 %shl +} + +define i32 @and_shl_fail3_i32(i32 %x) nounwind { +; X86-LABEL: and_shl_fail3_i32: +; X86: # %bb.0: +; X86-NEXT: movl $2423211, %eax # imm = 0x24F9AB +; X86-NEXT: andl {{[0-9]+}}(%esp), %eax +; X86-NEXT: shll $5, %eax +; X86-NEXT: retl +; +; X64-LABEL: and_shl_fail3_i32: +; X64: # %bb.0: +; X64-NEXT: movl %edi, %eax +; X64-NEXT: andl $2423211, %eax # imm = 0x24F9AB +; X64-NEXT: shll $5, %eax +; X64-NEXT: retq + %and = and i32 %x, 2423211 + %shl = shl i32 %and, 5 + ret i32 %shl +}