| ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py | |
| ; RUN: llc -mtriple=i686-unknown-linux-gnu -mattr=-bmi,-tbm,-bmi2 < %s | FileCheck %s --check-prefixes=X86,X86-NOBMI | |
| ; RUN: llc -mtriple=i686-unknown-linux-gnu -mattr=+bmi,-tbm,-bmi2 < %s | FileCheck %s --check-prefixes=X86,X86-BMI1 | |
| ; RUN: llc -mtriple=i686-unknown-linux-gnu -mattr=+bmi,+tbm,-bmi2 < %s | FileCheck %s --check-prefixes=X86,X86-BMI1 | |
| ; RUN: llc -mtriple=i686-unknown-linux-gnu -mattr=+bmi,+tbm,+bmi2 < %s | FileCheck %s --check-prefixes=X86,X86-BMI2 | |
| ; RUN: llc -mtriple=i686-unknown-linux-gnu -mattr=+bmi,-tbm,+bmi2 < %s | FileCheck %s --check-prefixes=X86,X86-BMI2 | |
| ; RUN: llc -mtriple=x86_64-unknown-linux-gnu -mattr=-bmi,-tbm,-bmi2 < %s | FileCheck %s --check-prefixes=X64,X64-NOBMI | |
| ; RUN: llc -mtriple=x86_64-unknown-linux-gnu -mattr=+bmi,-tbm,-bmi2 < %s | FileCheck %s --check-prefixes=X64,X64-BMI1,X64-BMI1NOTBM | |
| ; RUN: llc -mtriple=x86_64-unknown-linux-gnu -mattr=+bmi,+tbm,-bmi2 < %s | FileCheck %s --check-prefixes=X64,X64-BMI1,X64-BMI1TBM | |
| ; RUN: llc -mtriple=x86_64-unknown-linux-gnu -mattr=+bmi,+tbm,+bmi2 < %s | FileCheck %s --check-prefixes=X64,X64-BMI2,X64-BMI2TBM | |
| ; RUN: llc -mtriple=x86_64-unknown-linux-gnu -mattr=+bmi,-tbm,+bmi2 < %s | FileCheck %s --check-prefixes=X64,X64-BMI2,X64-BMI2NOTBM | |
| ; *Please* keep in sync with test/CodeGen/AArch64/extract-lowbits.ll | |
| ; https://bugs.llvm.org/show_bug.cgi?id=36419 | |
| ; https://bugs.llvm.org/show_bug.cgi?id=37603 | |
| ; https://bugs.llvm.org/show_bug.cgi?id=37610 | |
| ; Patterns: | |
| ; a) x & (1 << nbits) - 1 | |
| ; b) x & ~(-1 << nbits) | |
| ; c) x & (-1 >> (32 - y)) | |
| ; d) x << (32 - y) >> (32 - y) | |
| ; are equivalent. | |
| ; ---------------------------------------------------------------------------- ; | |
| ; Pattern a. 32-bit | |
| ; ---------------------------------------------------------------------------- ; | |
| define i32 @bzhi32_a0(i32 %val, i32 %numlowbits) nounwind { | |
| ; X86-NOBMI-LABEL: bzhi32_a0: | |
| ; X86-NOBMI: # %bb.0: | |
| ; X86-NOBMI-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-NOBMI-NEXT: movl $1, %eax | |
| ; X86-NOBMI-NEXT: shll %cl, %eax | |
| ; X86-NOBMI-NEXT: decl %eax | |
| ; X86-NOBMI-NEXT: andl {{[0-9]+}}(%esp), %eax | |
| ; X86-NOBMI-NEXT: retl | |
| ; | |
| ; X86-BMI1-LABEL: bzhi32_a0: | |
| ; X86-BMI1: # %bb.0: | |
| ; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: shll $8, %eax | |
| ; X86-BMI1-NEXT: bextrl %eax, {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: retl | |
| ; | |
| ; X86-BMI2-LABEL: bzhi32_a0: | |
| ; X86-BMI2: # %bb.0: | |
| ; X86-BMI2-NEXT: movzbl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: bzhil %eax, {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: retl | |
| ; | |
| ; X64-NOBMI-LABEL: bzhi32_a0: | |
| ; X64-NOBMI: # %bb.0: | |
| ; X64-NOBMI-NEXT: movl %esi, %ecx | |
| ; X64-NOBMI-NEXT: movl $1, %eax | |
| ; X64-NOBMI-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X64-NOBMI-NEXT: shll %cl, %eax | |
| ; X64-NOBMI-NEXT: decl %eax | |
| ; X64-NOBMI-NEXT: andl %edi, %eax | |
| ; X64-NOBMI-NEXT: retq | |
| ; | |
| ; X64-BMI1-LABEL: bzhi32_a0: | |
| ; X64-BMI1: # %bb.0: | |
| ; X64-BMI1-NEXT: shll $8, %esi | |
| ; X64-BMI1-NEXT: bextrl %esi, %edi, %eax | |
| ; X64-BMI1-NEXT: retq | |
| ; | |
| ; X64-BMI2-LABEL: bzhi32_a0: | |
| ; X64-BMI2: # %bb.0: | |
| ; X64-BMI2-NEXT: bzhil %esi, %edi, %eax | |
| ; X64-BMI2-NEXT: retq | |
| %onebit = shl i32 1, %numlowbits | |
| %mask = add nsw i32 %onebit, -1 | |
| %masked = and i32 %mask, %val | |
| ret i32 %masked | |
| } | |
| define i32 @bzhi32_a1_indexzext(i32 %val, i8 zeroext %numlowbits) nounwind { | |
| ; X86-NOBMI-LABEL: bzhi32_a1_indexzext: | |
| ; X86-NOBMI: # %bb.0: | |
| ; X86-NOBMI-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-NOBMI-NEXT: movl $1, %eax | |
| ; X86-NOBMI-NEXT: shll %cl, %eax | |
| ; X86-NOBMI-NEXT: decl %eax | |
| ; X86-NOBMI-NEXT: andl {{[0-9]+}}(%esp), %eax | |
| ; X86-NOBMI-NEXT: retl | |
| ; | |
| ; X86-BMI1-LABEL: bzhi32_a1_indexzext: | |
| ; X86-BMI1: # %bb.0: | |
| ; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: shll $8, %eax | |
| ; X86-BMI1-NEXT: bextrl %eax, {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: retl | |
| ; | |
| ; X86-BMI2-LABEL: bzhi32_a1_indexzext: | |
| ; X86-BMI2: # %bb.0: | |
| ; X86-BMI2-NEXT: movzbl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: bzhil %eax, {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: retl | |
| ; | |
| ; X64-NOBMI-LABEL: bzhi32_a1_indexzext: | |
| ; X64-NOBMI: # %bb.0: | |
| ; X64-NOBMI-NEXT: movl %esi, %ecx | |
| ; X64-NOBMI-NEXT: movl $1, %eax | |
| ; X64-NOBMI-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X64-NOBMI-NEXT: shll %cl, %eax | |
| ; X64-NOBMI-NEXT: decl %eax | |
| ; X64-NOBMI-NEXT: andl %edi, %eax | |
| ; X64-NOBMI-NEXT: retq | |
| ; | |
| ; X64-BMI1-LABEL: bzhi32_a1_indexzext: | |
| ; X64-BMI1: # %bb.0: | |
| ; X64-BMI1-NEXT: shll $8, %esi | |
| ; X64-BMI1-NEXT: bextrl %esi, %edi, %eax | |
| ; X64-BMI1-NEXT: retq | |
| ; | |
| ; X64-BMI2-LABEL: bzhi32_a1_indexzext: | |
| ; X64-BMI2: # %bb.0: | |
| ; X64-BMI2-NEXT: bzhil %esi, %edi, %eax | |
| ; X64-BMI2-NEXT: retq | |
| %conv = zext i8 %numlowbits to i32 | |
| %onebit = shl i32 1, %conv | |
| %mask = add nsw i32 %onebit, -1 | |
| %masked = and i32 %mask, %val | |
| ret i32 %masked | |
| } | |
| define i32 @bzhi32_a2_load(ptr %w, i32 %numlowbits) nounwind { | |
| ; X86-NOBMI-LABEL: bzhi32_a2_load: | |
| ; X86-NOBMI: # %bb.0: | |
| ; X86-NOBMI-NEXT: movl {{[0-9]+}}(%esp), %edx | |
| ; X86-NOBMI-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-NOBMI-NEXT: movl $1, %eax | |
| ; X86-NOBMI-NEXT: shll %cl, %eax | |
| ; X86-NOBMI-NEXT: decl %eax | |
| ; X86-NOBMI-NEXT: andl (%edx), %eax | |
| ; X86-NOBMI-NEXT: retl | |
| ; | |
| ; X86-BMI1-LABEL: bzhi32_a2_load: | |
| ; X86-BMI1: # %bb.0: | |
| ; X86-BMI1-NEXT: movl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-BMI1-NEXT: shll $8, %ecx | |
| ; X86-BMI1-NEXT: bextrl %ecx, (%eax), %eax | |
| ; X86-BMI1-NEXT: retl | |
| ; | |
| ; X86-BMI2-LABEL: bzhi32_a2_load: | |
| ; X86-BMI2: # %bb.0: | |
| ; X86-BMI2-NEXT: movl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-BMI2-NEXT: bzhil %ecx, (%eax), %eax | |
| ; X86-BMI2-NEXT: retl | |
| ; | |
| ; X64-NOBMI-LABEL: bzhi32_a2_load: | |
| ; X64-NOBMI: # %bb.0: | |
| ; X64-NOBMI-NEXT: movl %esi, %ecx | |
| ; X64-NOBMI-NEXT: movl $1, %eax | |
| ; X64-NOBMI-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X64-NOBMI-NEXT: shll %cl, %eax | |
| ; X64-NOBMI-NEXT: decl %eax | |
| ; X64-NOBMI-NEXT: andl (%rdi), %eax | |
| ; X64-NOBMI-NEXT: retq | |
| ; | |
| ; X64-BMI1-LABEL: bzhi32_a2_load: | |
| ; X64-BMI1: # %bb.0: | |
| ; X64-BMI1-NEXT: shll $8, %esi | |
| ; X64-BMI1-NEXT: bextrl %esi, (%rdi), %eax | |
| ; X64-BMI1-NEXT: retq | |
| ; | |
| ; X64-BMI2-LABEL: bzhi32_a2_load: | |
| ; X64-BMI2: # %bb.0: | |
| ; X64-BMI2-NEXT: bzhil %esi, (%rdi), %eax | |
| ; X64-BMI2-NEXT: retq | |
| %val = load i32, ptr %w | |
| %onebit = shl i32 1, %numlowbits | |
| %mask = add nsw i32 %onebit, -1 | |
| %masked = and i32 %mask, %val | |
| ret i32 %masked | |
| } | |
| define i32 @bzhi32_a3_load_indexzext(ptr %w, i8 zeroext %numlowbits) nounwind { | |
| ; X86-NOBMI-LABEL: bzhi32_a3_load_indexzext: | |
| ; X86-NOBMI: # %bb.0: | |
| ; X86-NOBMI-NEXT: movl {{[0-9]+}}(%esp), %edx | |
| ; X86-NOBMI-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-NOBMI-NEXT: movl $1, %eax | |
| ; X86-NOBMI-NEXT: shll %cl, %eax | |
| ; X86-NOBMI-NEXT: decl %eax | |
| ; X86-NOBMI-NEXT: andl (%edx), %eax | |
| ; X86-NOBMI-NEXT: retl | |
| ; | |
| ; X86-BMI1-LABEL: bzhi32_a3_load_indexzext: | |
| ; X86-BMI1: # %bb.0: | |
| ; X86-BMI1-NEXT: movl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-BMI1-NEXT: shll $8, %ecx | |
| ; X86-BMI1-NEXT: bextrl %ecx, (%eax), %eax | |
| ; X86-BMI1-NEXT: retl | |
| ; | |
| ; X86-BMI2-LABEL: bzhi32_a3_load_indexzext: | |
| ; X86-BMI2: # %bb.0: | |
| ; X86-BMI2-NEXT: movl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-BMI2-NEXT: bzhil %ecx, (%eax), %eax | |
| ; X86-BMI2-NEXT: retl | |
| ; | |
| ; X64-NOBMI-LABEL: bzhi32_a3_load_indexzext: | |
| ; X64-NOBMI: # %bb.0: | |
| ; X64-NOBMI-NEXT: movl %esi, %ecx | |
| ; X64-NOBMI-NEXT: movl $1, %eax | |
| ; X64-NOBMI-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X64-NOBMI-NEXT: shll %cl, %eax | |
| ; X64-NOBMI-NEXT: decl %eax | |
| ; X64-NOBMI-NEXT: andl (%rdi), %eax | |
| ; X64-NOBMI-NEXT: retq | |
| ; | |
| ; X64-BMI1-LABEL: bzhi32_a3_load_indexzext: | |
| ; X64-BMI1: # %bb.0: | |
| ; X64-BMI1-NEXT: shll $8, %esi | |
| ; X64-BMI1-NEXT: bextrl %esi, (%rdi), %eax | |
| ; X64-BMI1-NEXT: retq | |
| ; | |
| ; X64-BMI2-LABEL: bzhi32_a3_load_indexzext: | |
| ; X64-BMI2: # %bb.0: | |
| ; X64-BMI2-NEXT: bzhil %esi, (%rdi), %eax | |
| ; X64-BMI2-NEXT: retq | |
| %val = load i32, ptr %w | |
| %conv = zext i8 %numlowbits to i32 | |
| %onebit = shl i32 1, %conv | |
| %mask = add nsw i32 %onebit, -1 | |
| %masked = and i32 %mask, %val | |
| ret i32 %masked | |
| } | |
| define i32 @bzhi32_a4_commutative(i32 %val, i32 %numlowbits) nounwind { | |
| ; X86-NOBMI-LABEL: bzhi32_a4_commutative: | |
| ; X86-NOBMI: # %bb.0: | |
| ; X86-NOBMI-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-NOBMI-NEXT: movl $1, %eax | |
| ; X86-NOBMI-NEXT: shll %cl, %eax | |
| ; X86-NOBMI-NEXT: decl %eax | |
| ; X86-NOBMI-NEXT: andl {{[0-9]+}}(%esp), %eax | |
| ; X86-NOBMI-NEXT: retl | |
| ; | |
| ; X86-BMI1-LABEL: bzhi32_a4_commutative: | |
| ; X86-BMI1: # %bb.0: | |
| ; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: shll $8, %eax | |
| ; X86-BMI1-NEXT: bextrl %eax, {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: retl | |
| ; | |
| ; X86-BMI2-LABEL: bzhi32_a4_commutative: | |
| ; X86-BMI2: # %bb.0: | |
| ; X86-BMI2-NEXT: movzbl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: bzhil %eax, {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: retl | |
| ; | |
| ; X64-NOBMI-LABEL: bzhi32_a4_commutative: | |
| ; X64-NOBMI: # %bb.0: | |
| ; X64-NOBMI-NEXT: movl %esi, %ecx | |
| ; X64-NOBMI-NEXT: movl $1, %eax | |
| ; X64-NOBMI-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X64-NOBMI-NEXT: shll %cl, %eax | |
| ; X64-NOBMI-NEXT: decl %eax | |
| ; X64-NOBMI-NEXT: andl %edi, %eax | |
| ; X64-NOBMI-NEXT: retq | |
| ; | |
| ; X64-BMI1-LABEL: bzhi32_a4_commutative: | |
| ; X64-BMI1: # %bb.0: | |
| ; X64-BMI1-NEXT: shll $8, %esi | |
| ; X64-BMI1-NEXT: bextrl %esi, %edi, %eax | |
| ; X64-BMI1-NEXT: retq | |
| ; | |
| ; X64-BMI2-LABEL: bzhi32_a4_commutative: | |
| ; X64-BMI2: # %bb.0: | |
| ; X64-BMI2-NEXT: bzhil %esi, %edi, %eax | |
| ; X64-BMI2-NEXT: retq | |
| %onebit = shl i32 1, %numlowbits | |
| %mask = add nsw i32 %onebit, -1 | |
| %masked = and i32 %val, %mask ; swapped order | |
| ret i32 %masked | |
| } | |
| ; 64-bit | |
| define i64 @bzhi64_a0(i64 %val, i64 %numlowbits) nounwind { | |
| ; X86-NOBMI-LABEL: bzhi64_a0: | |
| ; X86-NOBMI: # %bb.0: | |
| ; X86-NOBMI-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-NOBMI-NEXT: movl $1, %eax | |
| ; X86-NOBMI-NEXT: xorl %edx, %edx | |
| ; X86-NOBMI-NEXT: shldl %cl, %eax, %edx | |
| ; X86-NOBMI-NEXT: shll %cl, %eax | |
| ; X86-NOBMI-NEXT: testb $32, %cl | |
| ; X86-NOBMI-NEXT: je .LBB5_2 | |
| ; X86-NOBMI-NEXT: # %bb.1: | |
| ; X86-NOBMI-NEXT: movl %eax, %edx | |
| ; X86-NOBMI-NEXT: xorl %eax, %eax | |
| ; X86-NOBMI-NEXT: .LBB5_2: | |
| ; X86-NOBMI-NEXT: addl $-1, %eax | |
| ; X86-NOBMI-NEXT: adcl $-1, %edx | |
| ; X86-NOBMI-NEXT: andl {{[0-9]+}}(%esp), %edx | |
| ; X86-NOBMI-NEXT: andl {{[0-9]+}}(%esp), %eax | |
| ; X86-NOBMI-NEXT: retl | |
| ; | |
| ; X86-BMI1-LABEL: bzhi64_a0: | |
| ; X86-BMI1: # %bb.0: | |
| ; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-BMI1-NEXT: movl $1, %eax | |
| ; X86-BMI1-NEXT: xorl %edx, %edx | |
| ; X86-BMI1-NEXT: shldl %cl, %eax, %edx | |
| ; X86-BMI1-NEXT: shll %cl, %eax | |
| ; X86-BMI1-NEXT: testb $32, %cl | |
| ; X86-BMI1-NEXT: je .LBB5_2 | |
| ; X86-BMI1-NEXT: # %bb.1: | |
| ; X86-BMI1-NEXT: movl %eax, %edx | |
| ; X86-BMI1-NEXT: xorl %eax, %eax | |
| ; X86-BMI1-NEXT: .LBB5_2: | |
| ; X86-BMI1-NEXT: addl $-1, %eax | |
| ; X86-BMI1-NEXT: adcl $-1, %edx | |
| ; X86-BMI1-NEXT: andl {{[0-9]+}}(%esp), %edx | |
| ; X86-BMI1-NEXT: andl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: retl | |
| ; | |
| ; X86-BMI2-LABEL: bzhi64_a0: | |
| ; X86-BMI2: # %bb.0: | |
| ; X86-BMI2-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-BMI2-NEXT: movl $1, %eax | |
| ; X86-BMI2-NEXT: xorl %edx, %edx | |
| ; X86-BMI2-NEXT: shldl %cl, %eax, %edx | |
| ; X86-BMI2-NEXT: shlxl %ecx, %eax, %eax | |
| ; X86-BMI2-NEXT: testb $32, %cl | |
| ; X86-BMI2-NEXT: je .LBB5_2 | |
| ; X86-BMI2-NEXT: # %bb.1: | |
| ; X86-BMI2-NEXT: movl %eax, %edx | |
| ; X86-BMI2-NEXT: xorl %eax, %eax | |
| ; X86-BMI2-NEXT: .LBB5_2: | |
| ; X86-BMI2-NEXT: addl $-1, %eax | |
| ; X86-BMI2-NEXT: adcl $-1, %edx | |
| ; X86-BMI2-NEXT: andl {{[0-9]+}}(%esp), %edx | |
| ; X86-BMI2-NEXT: andl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: retl | |
| ; | |
| ; X64-NOBMI-LABEL: bzhi64_a0: | |
| ; X64-NOBMI: # %bb.0: | |
| ; X64-NOBMI-NEXT: movq %rsi, %rcx | |
| ; X64-NOBMI-NEXT: movl $1, %eax | |
| ; X64-NOBMI-NEXT: # kill: def $cl killed $cl killed $rcx | |
| ; X64-NOBMI-NEXT: shlq %cl, %rax | |
| ; X64-NOBMI-NEXT: decq %rax | |
| ; X64-NOBMI-NEXT: andq %rdi, %rax | |
| ; X64-NOBMI-NEXT: retq | |
| ; | |
| ; X64-BMI1-LABEL: bzhi64_a0: | |
| ; X64-BMI1: # %bb.0: | |
| ; X64-BMI1-NEXT: shll $8, %esi | |
| ; X64-BMI1-NEXT: bextrq %rsi, %rdi, %rax | |
| ; X64-BMI1-NEXT: retq | |
| ; | |
| ; X64-BMI2-LABEL: bzhi64_a0: | |
| ; X64-BMI2: # %bb.0: | |
| ; X64-BMI2-NEXT: bzhiq %rsi, %rdi, %rax | |
| ; X64-BMI2-NEXT: retq | |
| %onebit = shl i64 1, %numlowbits | |
| %mask = add nsw i64 %onebit, -1 | |
| %masked = and i64 %mask, %val | |
| ret i64 %masked | |
| } | |
| ; Check that we don't throw away the vreg_width-1 mask if not using shifts | |
| define i64 @bzhi64_a0_masked(i64 %val, i64 %numlowbits) nounwind { | |
| ; X86-NOBMI-LABEL: bzhi64_a0_masked: | |
| ; X86-NOBMI: # %bb.0: | |
| ; X86-NOBMI-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-NOBMI-NEXT: movl $1, %eax | |
| ; X86-NOBMI-NEXT: xorl %edx, %edx | |
| ; X86-NOBMI-NEXT: shldl %cl, %eax, %edx | |
| ; X86-NOBMI-NEXT: shll %cl, %eax | |
| ; X86-NOBMI-NEXT: testb $32, %cl | |
| ; X86-NOBMI-NEXT: je .LBB6_2 | |
| ; X86-NOBMI-NEXT: # %bb.1: | |
| ; X86-NOBMI-NEXT: movl %eax, %edx | |
| ; X86-NOBMI-NEXT: xorl %eax, %eax | |
| ; X86-NOBMI-NEXT: .LBB6_2: | |
| ; X86-NOBMI-NEXT: addl $-1, %eax | |
| ; X86-NOBMI-NEXT: adcl $-1, %edx | |
| ; X86-NOBMI-NEXT: andl {{[0-9]+}}(%esp), %edx | |
| ; X86-NOBMI-NEXT: andl {{[0-9]+}}(%esp), %eax | |
| ; X86-NOBMI-NEXT: retl | |
| ; | |
| ; X86-BMI1-LABEL: bzhi64_a0_masked: | |
| ; X86-BMI1: # %bb.0: | |
| ; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-BMI1-NEXT: movl $1, %eax | |
| ; X86-BMI1-NEXT: xorl %edx, %edx | |
| ; X86-BMI1-NEXT: shldl %cl, %eax, %edx | |
| ; X86-BMI1-NEXT: shll %cl, %eax | |
| ; X86-BMI1-NEXT: testb $32, %cl | |
| ; X86-BMI1-NEXT: je .LBB6_2 | |
| ; X86-BMI1-NEXT: # %bb.1: | |
| ; X86-BMI1-NEXT: movl %eax, %edx | |
| ; X86-BMI1-NEXT: xorl %eax, %eax | |
| ; X86-BMI1-NEXT: .LBB6_2: | |
| ; X86-BMI1-NEXT: addl $-1, %eax | |
| ; X86-BMI1-NEXT: adcl $-1, %edx | |
| ; X86-BMI1-NEXT: andl {{[0-9]+}}(%esp), %edx | |
| ; X86-BMI1-NEXT: andl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: retl | |
| ; | |
| ; X86-BMI2-LABEL: bzhi64_a0_masked: | |
| ; X86-BMI2: # %bb.0: | |
| ; X86-BMI2-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-BMI2-NEXT: movl $1, %eax | |
| ; X86-BMI2-NEXT: xorl %edx, %edx | |
| ; X86-BMI2-NEXT: shldl %cl, %eax, %edx | |
| ; X86-BMI2-NEXT: shlxl %ecx, %eax, %eax | |
| ; X86-BMI2-NEXT: testb $32, %cl | |
| ; X86-BMI2-NEXT: je .LBB6_2 | |
| ; X86-BMI2-NEXT: # %bb.1: | |
| ; X86-BMI2-NEXT: movl %eax, %edx | |
| ; X86-BMI2-NEXT: xorl %eax, %eax | |
| ; X86-BMI2-NEXT: .LBB6_2: | |
| ; X86-BMI2-NEXT: addl $-1, %eax | |
| ; X86-BMI2-NEXT: adcl $-1, %edx | |
| ; X86-BMI2-NEXT: andl {{[0-9]+}}(%esp), %edx | |
| ; X86-BMI2-NEXT: andl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: retl | |
| ; | |
| ; X64-NOBMI-LABEL: bzhi64_a0_masked: | |
| ; X64-NOBMI: # %bb.0: | |
| ; X64-NOBMI-NEXT: movq %rsi, %rcx | |
| ; X64-NOBMI-NEXT: movl $1, %eax | |
| ; X64-NOBMI-NEXT: # kill: def $cl killed $cl killed $rcx | |
| ; X64-NOBMI-NEXT: shlq %cl, %rax | |
| ; X64-NOBMI-NEXT: decq %rax | |
| ; X64-NOBMI-NEXT: andq %rdi, %rax | |
| ; X64-NOBMI-NEXT: retq | |
| ; | |
| ; X64-BMI1-LABEL: bzhi64_a0_masked: | |
| ; X64-BMI1: # %bb.0: | |
| ; X64-BMI1-NEXT: andl $63, %esi | |
| ; X64-BMI1-NEXT: shll $8, %esi | |
| ; X64-BMI1-NEXT: bextrq %rsi, %rdi, %rax | |
| ; X64-BMI1-NEXT: retq | |
| ; | |
| ; X64-BMI2-LABEL: bzhi64_a0_masked: | |
| ; X64-BMI2: # %bb.0: | |
| ; X64-BMI2-NEXT: andl $63, %esi | |
| ; X64-BMI2-NEXT: bzhiq %rsi, %rdi, %rax | |
| ; X64-BMI2-NEXT: retq | |
| %numlowbits.masked = and i64 %numlowbits, 63 | |
| %onebit = shl i64 1, %numlowbits.masked | |
| %mask = add nsw i64 %onebit, -1 | |
| %masked = and i64 %mask, %val | |
| ret i64 %masked | |
| } | |
| define i64 @bzhi64_a1_indexzext(i64 %val, i8 zeroext %numlowbits) nounwind { | |
| ; X86-NOBMI-LABEL: bzhi64_a1_indexzext: | |
| ; X86-NOBMI: # %bb.0: | |
| ; X86-NOBMI-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-NOBMI-NEXT: movl $1, %eax | |
| ; X86-NOBMI-NEXT: xorl %edx, %edx | |
| ; X86-NOBMI-NEXT: shldl %cl, %eax, %edx | |
| ; X86-NOBMI-NEXT: shll %cl, %eax | |
| ; X86-NOBMI-NEXT: testb $32, %cl | |
| ; X86-NOBMI-NEXT: je .LBB7_2 | |
| ; X86-NOBMI-NEXT: # %bb.1: | |
| ; X86-NOBMI-NEXT: movl %eax, %edx | |
| ; X86-NOBMI-NEXT: xorl %eax, %eax | |
| ; X86-NOBMI-NEXT: .LBB7_2: | |
| ; X86-NOBMI-NEXT: addl $-1, %eax | |
| ; X86-NOBMI-NEXT: adcl $-1, %edx | |
| ; X86-NOBMI-NEXT: andl {{[0-9]+}}(%esp), %edx | |
| ; X86-NOBMI-NEXT: andl {{[0-9]+}}(%esp), %eax | |
| ; X86-NOBMI-NEXT: retl | |
| ; | |
| ; X86-BMI1-LABEL: bzhi64_a1_indexzext: | |
| ; X86-BMI1: # %bb.0: | |
| ; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-BMI1-NEXT: movl $1, %eax | |
| ; X86-BMI1-NEXT: xorl %edx, %edx | |
| ; X86-BMI1-NEXT: shldl %cl, %eax, %edx | |
| ; X86-BMI1-NEXT: shll %cl, %eax | |
| ; X86-BMI1-NEXT: testb $32, %cl | |
| ; X86-BMI1-NEXT: je .LBB7_2 | |
| ; X86-BMI1-NEXT: # %bb.1: | |
| ; X86-BMI1-NEXT: movl %eax, %edx | |
| ; X86-BMI1-NEXT: xorl %eax, %eax | |
| ; X86-BMI1-NEXT: .LBB7_2: | |
| ; X86-BMI1-NEXT: addl $-1, %eax | |
| ; X86-BMI1-NEXT: adcl $-1, %edx | |
| ; X86-BMI1-NEXT: andl {{[0-9]+}}(%esp), %edx | |
| ; X86-BMI1-NEXT: andl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: retl | |
| ; | |
| ; X86-BMI2-LABEL: bzhi64_a1_indexzext: | |
| ; X86-BMI2: # %bb.0: | |
| ; X86-BMI2-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-BMI2-NEXT: movl $1, %eax | |
| ; X86-BMI2-NEXT: xorl %edx, %edx | |
| ; X86-BMI2-NEXT: shldl %cl, %eax, %edx | |
| ; X86-BMI2-NEXT: shlxl %ecx, %eax, %eax | |
| ; X86-BMI2-NEXT: testb $32, %cl | |
| ; X86-BMI2-NEXT: je .LBB7_2 | |
| ; X86-BMI2-NEXT: # %bb.1: | |
| ; X86-BMI2-NEXT: movl %eax, %edx | |
| ; X86-BMI2-NEXT: xorl %eax, %eax | |
| ; X86-BMI2-NEXT: .LBB7_2: | |
| ; X86-BMI2-NEXT: addl $-1, %eax | |
| ; X86-BMI2-NEXT: adcl $-1, %edx | |
| ; X86-BMI2-NEXT: andl {{[0-9]+}}(%esp), %edx | |
| ; X86-BMI2-NEXT: andl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: retl | |
| ; | |
| ; X64-NOBMI-LABEL: bzhi64_a1_indexzext: | |
| ; X64-NOBMI: # %bb.0: | |
| ; X64-NOBMI-NEXT: movl %esi, %ecx | |
| ; X64-NOBMI-NEXT: movl $1, %eax | |
| ; X64-NOBMI-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X64-NOBMI-NEXT: shlq %cl, %rax | |
| ; X64-NOBMI-NEXT: decq %rax | |
| ; X64-NOBMI-NEXT: andq %rdi, %rax | |
| ; X64-NOBMI-NEXT: retq | |
| ; | |
| ; X64-BMI1-LABEL: bzhi64_a1_indexzext: | |
| ; X64-BMI1: # %bb.0: | |
| ; X64-BMI1-NEXT: # kill: def $esi killed $esi def $rsi | |
| ; X64-BMI1-NEXT: shll $8, %esi | |
| ; X64-BMI1-NEXT: bextrq %rsi, %rdi, %rax | |
| ; X64-BMI1-NEXT: retq | |
| ; | |
| ; X64-BMI2-LABEL: bzhi64_a1_indexzext: | |
| ; X64-BMI2: # %bb.0: | |
| ; X64-BMI2-NEXT: # kill: def $esi killed $esi def $rsi | |
| ; X64-BMI2-NEXT: bzhiq %rsi, %rdi, %rax | |
| ; X64-BMI2-NEXT: retq | |
| %conv = zext i8 %numlowbits to i64 | |
| %onebit = shl i64 1, %conv | |
| %mask = add nsw i64 %onebit, -1 | |
| %masked = and i64 %mask, %val | |
| ret i64 %masked | |
| } | |
| define i64 @bzhi64_a2_load(ptr %w, i64 %numlowbits) nounwind { | |
| ; X86-NOBMI-LABEL: bzhi64_a2_load: | |
| ; X86-NOBMI: # %bb.0: | |
| ; X86-NOBMI-NEXT: pushl %esi | |
| ; X86-NOBMI-NEXT: movl {{[0-9]+}}(%esp), %esi | |
| ; X86-NOBMI-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-NOBMI-NEXT: movl $1, %eax | |
| ; X86-NOBMI-NEXT: xorl %edx, %edx | |
| ; X86-NOBMI-NEXT: shldl %cl, %eax, %edx | |
| ; X86-NOBMI-NEXT: shll %cl, %eax | |
| ; X86-NOBMI-NEXT: testb $32, %cl | |
| ; X86-NOBMI-NEXT: je .LBB8_2 | |
| ; X86-NOBMI-NEXT: # %bb.1: | |
| ; X86-NOBMI-NEXT: movl %eax, %edx | |
| ; X86-NOBMI-NEXT: xorl %eax, %eax | |
| ; X86-NOBMI-NEXT: .LBB8_2: | |
| ; X86-NOBMI-NEXT: addl $-1, %eax | |
| ; X86-NOBMI-NEXT: adcl $-1, %edx | |
| ; X86-NOBMI-NEXT: andl 4(%esi), %edx | |
| ; X86-NOBMI-NEXT: andl (%esi), %eax | |
| ; X86-NOBMI-NEXT: popl %esi | |
| ; X86-NOBMI-NEXT: retl | |
| ; | |
| ; X86-BMI1-LABEL: bzhi64_a2_load: | |
| ; X86-BMI1: # %bb.0: | |
| ; X86-BMI1-NEXT: pushl %esi | |
| ; X86-BMI1-NEXT: movl {{[0-9]+}}(%esp), %esi | |
| ; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-BMI1-NEXT: movl $1, %eax | |
| ; X86-BMI1-NEXT: xorl %edx, %edx | |
| ; X86-BMI1-NEXT: shldl %cl, %eax, %edx | |
| ; X86-BMI1-NEXT: shll %cl, %eax | |
| ; X86-BMI1-NEXT: testb $32, %cl | |
| ; X86-BMI1-NEXT: je .LBB8_2 | |
| ; X86-BMI1-NEXT: # %bb.1: | |
| ; X86-BMI1-NEXT: movl %eax, %edx | |
| ; X86-BMI1-NEXT: xorl %eax, %eax | |
| ; X86-BMI1-NEXT: .LBB8_2: | |
| ; X86-BMI1-NEXT: addl $-1, %eax | |
| ; X86-BMI1-NEXT: adcl $-1, %edx | |
| ; X86-BMI1-NEXT: andl 4(%esi), %edx | |
| ; X86-BMI1-NEXT: andl (%esi), %eax | |
| ; X86-BMI1-NEXT: popl %esi | |
| ; X86-BMI1-NEXT: retl | |
| ; | |
| ; X86-BMI2-LABEL: bzhi64_a2_load: | |
| ; X86-BMI2: # %bb.0: | |
| ; X86-BMI2-NEXT: pushl %esi | |
| ; X86-BMI2-NEXT: movl {{[0-9]+}}(%esp), %esi | |
| ; X86-BMI2-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-BMI2-NEXT: movl $1, %eax | |
| ; X86-BMI2-NEXT: xorl %edx, %edx | |
| ; X86-BMI2-NEXT: shldl %cl, %eax, %edx | |
| ; X86-BMI2-NEXT: shlxl %ecx, %eax, %eax | |
| ; X86-BMI2-NEXT: testb $32, %cl | |
| ; X86-BMI2-NEXT: je .LBB8_2 | |
| ; X86-BMI2-NEXT: # %bb.1: | |
| ; X86-BMI2-NEXT: movl %eax, %edx | |
| ; X86-BMI2-NEXT: xorl %eax, %eax | |
| ; X86-BMI2-NEXT: .LBB8_2: | |
| ; X86-BMI2-NEXT: addl $-1, %eax | |
| ; X86-BMI2-NEXT: adcl $-1, %edx | |
| ; X86-BMI2-NEXT: andl 4(%esi), %edx | |
| ; X86-BMI2-NEXT: andl (%esi), %eax | |
| ; X86-BMI2-NEXT: popl %esi | |
| ; X86-BMI2-NEXT: retl | |
| ; | |
| ; X64-NOBMI-LABEL: bzhi64_a2_load: | |
| ; X64-NOBMI: # %bb.0: | |
| ; X64-NOBMI-NEXT: movq %rsi, %rcx | |
| ; X64-NOBMI-NEXT: movl $1, %eax | |
| ; X64-NOBMI-NEXT: # kill: def $cl killed $cl killed $rcx | |
| ; X64-NOBMI-NEXT: shlq %cl, %rax | |
| ; X64-NOBMI-NEXT: decq %rax | |
| ; X64-NOBMI-NEXT: andq (%rdi), %rax | |
| ; X64-NOBMI-NEXT: retq | |
| ; | |
| ; X64-BMI1-LABEL: bzhi64_a2_load: | |
| ; X64-BMI1: # %bb.0: | |
| ; X64-BMI1-NEXT: shll $8, %esi | |
| ; X64-BMI1-NEXT: bextrq %rsi, (%rdi), %rax | |
| ; X64-BMI1-NEXT: retq | |
| ; | |
| ; X64-BMI2-LABEL: bzhi64_a2_load: | |
| ; X64-BMI2: # %bb.0: | |
| ; X64-BMI2-NEXT: bzhiq %rsi, (%rdi), %rax | |
| ; X64-BMI2-NEXT: retq | |
| %val = load i64, ptr %w | |
| %onebit = shl i64 1, %numlowbits | |
| %mask = add nsw i64 %onebit, -1 | |
| %masked = and i64 %mask, %val | |
| ret i64 %masked | |
| } | |
| define i64 @bzhi64_a3_load_indexzext(ptr %w, i8 zeroext %numlowbits) nounwind { | |
| ; X86-NOBMI-LABEL: bzhi64_a3_load_indexzext: | |
| ; X86-NOBMI: # %bb.0: | |
| ; X86-NOBMI-NEXT: pushl %esi | |
| ; X86-NOBMI-NEXT: movl {{[0-9]+}}(%esp), %esi | |
| ; X86-NOBMI-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-NOBMI-NEXT: movl $1, %eax | |
| ; X86-NOBMI-NEXT: xorl %edx, %edx | |
| ; X86-NOBMI-NEXT: shldl %cl, %eax, %edx | |
| ; X86-NOBMI-NEXT: shll %cl, %eax | |
| ; X86-NOBMI-NEXT: testb $32, %cl | |
| ; X86-NOBMI-NEXT: je .LBB9_2 | |
| ; X86-NOBMI-NEXT: # %bb.1: | |
| ; X86-NOBMI-NEXT: movl %eax, %edx | |
| ; X86-NOBMI-NEXT: xorl %eax, %eax | |
| ; X86-NOBMI-NEXT: .LBB9_2: | |
| ; X86-NOBMI-NEXT: addl $-1, %eax | |
| ; X86-NOBMI-NEXT: adcl $-1, %edx | |
| ; X86-NOBMI-NEXT: andl 4(%esi), %edx | |
| ; X86-NOBMI-NEXT: andl (%esi), %eax | |
| ; X86-NOBMI-NEXT: popl %esi | |
| ; X86-NOBMI-NEXT: retl | |
| ; | |
| ; X86-BMI1-LABEL: bzhi64_a3_load_indexzext: | |
| ; X86-BMI1: # %bb.0: | |
| ; X86-BMI1-NEXT: pushl %esi | |
| ; X86-BMI1-NEXT: movl {{[0-9]+}}(%esp), %esi | |
| ; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-BMI1-NEXT: movl $1, %eax | |
| ; X86-BMI1-NEXT: xorl %edx, %edx | |
| ; X86-BMI1-NEXT: shldl %cl, %eax, %edx | |
| ; X86-BMI1-NEXT: shll %cl, %eax | |
| ; X86-BMI1-NEXT: testb $32, %cl | |
| ; X86-BMI1-NEXT: je .LBB9_2 | |
| ; X86-BMI1-NEXT: # %bb.1: | |
| ; X86-BMI1-NEXT: movl %eax, %edx | |
| ; X86-BMI1-NEXT: xorl %eax, %eax | |
| ; X86-BMI1-NEXT: .LBB9_2: | |
| ; X86-BMI1-NEXT: addl $-1, %eax | |
| ; X86-BMI1-NEXT: adcl $-1, %edx | |
| ; X86-BMI1-NEXT: andl 4(%esi), %edx | |
| ; X86-BMI1-NEXT: andl (%esi), %eax | |
| ; X86-BMI1-NEXT: popl %esi | |
| ; X86-BMI1-NEXT: retl | |
| ; | |
| ; X86-BMI2-LABEL: bzhi64_a3_load_indexzext: | |
| ; X86-BMI2: # %bb.0: | |
| ; X86-BMI2-NEXT: pushl %esi | |
| ; X86-BMI2-NEXT: movl {{[0-9]+}}(%esp), %esi | |
| ; X86-BMI2-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-BMI2-NEXT: movl $1, %eax | |
| ; X86-BMI2-NEXT: xorl %edx, %edx | |
| ; X86-BMI2-NEXT: shldl %cl, %eax, %edx | |
| ; X86-BMI2-NEXT: shlxl %ecx, %eax, %eax | |
| ; X86-BMI2-NEXT: testb $32, %cl | |
| ; X86-BMI2-NEXT: je .LBB9_2 | |
| ; X86-BMI2-NEXT: # %bb.1: | |
| ; X86-BMI2-NEXT: movl %eax, %edx | |
| ; X86-BMI2-NEXT: xorl %eax, %eax | |
| ; X86-BMI2-NEXT: .LBB9_2: | |
| ; X86-BMI2-NEXT: addl $-1, %eax | |
| ; X86-BMI2-NEXT: adcl $-1, %edx | |
| ; X86-BMI2-NEXT: andl 4(%esi), %edx | |
| ; X86-BMI2-NEXT: andl (%esi), %eax | |
| ; X86-BMI2-NEXT: popl %esi | |
| ; X86-BMI2-NEXT: retl | |
| ; | |
| ; X64-NOBMI-LABEL: bzhi64_a3_load_indexzext: | |
| ; X64-NOBMI: # %bb.0: | |
| ; X64-NOBMI-NEXT: movl %esi, %ecx | |
| ; X64-NOBMI-NEXT: movl $1, %eax | |
| ; X64-NOBMI-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X64-NOBMI-NEXT: shlq %cl, %rax | |
| ; X64-NOBMI-NEXT: decq %rax | |
| ; X64-NOBMI-NEXT: andq (%rdi), %rax | |
| ; X64-NOBMI-NEXT: retq | |
| ; | |
| ; X64-BMI1-LABEL: bzhi64_a3_load_indexzext: | |
| ; X64-BMI1: # %bb.0: | |
| ; X64-BMI1-NEXT: # kill: def $esi killed $esi def $rsi | |
| ; X64-BMI1-NEXT: shll $8, %esi | |
| ; X64-BMI1-NEXT: bextrq %rsi, (%rdi), %rax | |
| ; X64-BMI1-NEXT: retq | |
| ; | |
| ; X64-BMI2-LABEL: bzhi64_a3_load_indexzext: | |
| ; X64-BMI2: # %bb.0: | |
| ; X64-BMI2-NEXT: # kill: def $esi killed $esi def $rsi | |
| ; X64-BMI2-NEXT: bzhiq %rsi, (%rdi), %rax | |
| ; X64-BMI2-NEXT: retq | |
| %val = load i64, ptr %w | |
| %conv = zext i8 %numlowbits to i64 | |
| %onebit = shl i64 1, %conv | |
| %mask = add nsw i64 %onebit, -1 | |
| %masked = and i64 %mask, %val | |
| ret i64 %masked | |
| } | |
| define i64 @bzhi64_a4_commutative(i64 %val, i64 %numlowbits) nounwind { | |
| ; X86-NOBMI-LABEL: bzhi64_a4_commutative: | |
| ; X86-NOBMI: # %bb.0: | |
| ; X86-NOBMI-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-NOBMI-NEXT: movl $1, %eax | |
| ; X86-NOBMI-NEXT: xorl %edx, %edx | |
| ; X86-NOBMI-NEXT: shldl %cl, %eax, %edx | |
| ; X86-NOBMI-NEXT: shll %cl, %eax | |
| ; X86-NOBMI-NEXT: testb $32, %cl | |
| ; X86-NOBMI-NEXT: je .LBB10_2 | |
| ; X86-NOBMI-NEXT: # %bb.1: | |
| ; X86-NOBMI-NEXT: movl %eax, %edx | |
| ; X86-NOBMI-NEXT: xorl %eax, %eax | |
| ; X86-NOBMI-NEXT: .LBB10_2: | |
| ; X86-NOBMI-NEXT: addl $-1, %eax | |
| ; X86-NOBMI-NEXT: adcl $-1, %edx | |
| ; X86-NOBMI-NEXT: andl {{[0-9]+}}(%esp), %edx | |
| ; X86-NOBMI-NEXT: andl {{[0-9]+}}(%esp), %eax | |
| ; X86-NOBMI-NEXT: retl | |
| ; | |
| ; X86-BMI1-LABEL: bzhi64_a4_commutative: | |
| ; X86-BMI1: # %bb.0: | |
| ; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-BMI1-NEXT: movl $1, %eax | |
| ; X86-BMI1-NEXT: xorl %edx, %edx | |
| ; X86-BMI1-NEXT: shldl %cl, %eax, %edx | |
| ; X86-BMI1-NEXT: shll %cl, %eax | |
| ; X86-BMI1-NEXT: testb $32, %cl | |
| ; X86-BMI1-NEXT: je .LBB10_2 | |
| ; X86-BMI1-NEXT: # %bb.1: | |
| ; X86-BMI1-NEXT: movl %eax, %edx | |
| ; X86-BMI1-NEXT: xorl %eax, %eax | |
| ; X86-BMI1-NEXT: .LBB10_2: | |
| ; X86-BMI1-NEXT: addl $-1, %eax | |
| ; X86-BMI1-NEXT: adcl $-1, %edx | |
| ; X86-BMI1-NEXT: andl {{[0-9]+}}(%esp), %edx | |
| ; X86-BMI1-NEXT: andl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: retl | |
| ; | |
| ; X86-BMI2-LABEL: bzhi64_a4_commutative: | |
| ; X86-BMI2: # %bb.0: | |
| ; X86-BMI2-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-BMI2-NEXT: movl $1, %eax | |
| ; X86-BMI2-NEXT: xorl %edx, %edx | |
| ; X86-BMI2-NEXT: shldl %cl, %eax, %edx | |
| ; X86-BMI2-NEXT: shlxl %ecx, %eax, %eax | |
| ; X86-BMI2-NEXT: testb $32, %cl | |
| ; X86-BMI2-NEXT: je .LBB10_2 | |
| ; X86-BMI2-NEXT: # %bb.1: | |
| ; X86-BMI2-NEXT: movl %eax, %edx | |
| ; X86-BMI2-NEXT: xorl %eax, %eax | |
| ; X86-BMI2-NEXT: .LBB10_2: | |
| ; X86-BMI2-NEXT: addl $-1, %eax | |
| ; X86-BMI2-NEXT: adcl $-1, %edx | |
| ; X86-BMI2-NEXT: andl {{[0-9]+}}(%esp), %edx | |
| ; X86-BMI2-NEXT: andl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: retl | |
| ; | |
| ; X64-NOBMI-LABEL: bzhi64_a4_commutative: | |
| ; X64-NOBMI: # %bb.0: | |
| ; X64-NOBMI-NEXT: movq %rsi, %rcx | |
| ; X64-NOBMI-NEXT: movl $1, %eax | |
| ; X64-NOBMI-NEXT: # kill: def $cl killed $cl killed $rcx | |
| ; X64-NOBMI-NEXT: shlq %cl, %rax | |
| ; X64-NOBMI-NEXT: decq %rax | |
| ; X64-NOBMI-NEXT: andq %rdi, %rax | |
| ; X64-NOBMI-NEXT: retq | |
| ; | |
| ; X64-BMI1-LABEL: bzhi64_a4_commutative: | |
| ; X64-BMI1: # %bb.0: | |
| ; X64-BMI1-NEXT: shll $8, %esi | |
| ; X64-BMI1-NEXT: bextrq %rsi, %rdi, %rax | |
| ; X64-BMI1-NEXT: retq | |
| ; | |
| ; X64-BMI2-LABEL: bzhi64_a4_commutative: | |
| ; X64-BMI2: # %bb.0: | |
| ; X64-BMI2-NEXT: bzhiq %rsi, %rdi, %rax | |
| ; X64-BMI2-NEXT: retq | |
| %onebit = shl i64 1, %numlowbits | |
| %mask = add nsw i64 %onebit, -1 | |
| %masked = and i64 %val, %mask ; swapped order | |
| ret i64 %masked | |
| } | |
| ; 64-bit, but with 32-bit output | |
| ; Everything done in 64-bit, truncation happens last. | |
| define i32 @bzhi64_32_a0(i64 %val, i64 %numlowbits) nounwind { | |
| ; X86-NOBMI-LABEL: bzhi64_32_a0: | |
| ; X86-NOBMI: # %bb.0: | |
| ; X86-NOBMI-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-NOBMI-NEXT: movl $1, %edx | |
| ; X86-NOBMI-NEXT: shll %cl, %edx | |
| ; X86-NOBMI-NEXT: xorl %eax, %eax | |
| ; X86-NOBMI-NEXT: testb $32, %cl | |
| ; X86-NOBMI-NEXT: jne .LBB11_2 | |
| ; X86-NOBMI-NEXT: # %bb.1: | |
| ; X86-NOBMI-NEXT: movl %edx, %eax | |
| ; X86-NOBMI-NEXT: .LBB11_2: | |
| ; X86-NOBMI-NEXT: decl %eax | |
| ; X86-NOBMI-NEXT: andl {{[0-9]+}}(%esp), %eax | |
| ; X86-NOBMI-NEXT: retl | |
| ; | |
| ; X86-BMI1-LABEL: bzhi64_32_a0: | |
| ; X86-BMI1: # %bb.0: | |
| ; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-BMI1-NEXT: movl $1, %edx | |
| ; X86-BMI1-NEXT: shll %cl, %edx | |
| ; X86-BMI1-NEXT: xorl %eax, %eax | |
| ; X86-BMI1-NEXT: testb $32, %cl | |
| ; X86-BMI1-NEXT: jne .LBB11_2 | |
| ; X86-BMI1-NEXT: # %bb.1: | |
| ; X86-BMI1-NEXT: movl %edx, %eax | |
| ; X86-BMI1-NEXT: .LBB11_2: | |
| ; X86-BMI1-NEXT: decl %eax | |
| ; X86-BMI1-NEXT: andl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: retl | |
| ; | |
| ; X86-BMI2-LABEL: bzhi64_32_a0: | |
| ; X86-BMI2: # %bb.0: | |
| ; X86-BMI2-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-BMI2-NEXT: xorl %eax, %eax | |
| ; X86-BMI2-NEXT: testb $32, %cl | |
| ; X86-BMI2-NEXT: jne .LBB11_2 | |
| ; X86-BMI2-NEXT: # %bb.1: | |
| ; X86-BMI2-NEXT: movl $1, %eax | |
| ; X86-BMI2-NEXT: shlxl %ecx, %eax, %eax | |
| ; X86-BMI2-NEXT: .LBB11_2: | |
| ; X86-BMI2-NEXT: decl %eax | |
| ; X86-BMI2-NEXT: andl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: retl | |
| ; | |
| ; X64-NOBMI-LABEL: bzhi64_32_a0: | |
| ; X64-NOBMI: # %bb.0: | |
| ; X64-NOBMI-NEXT: movq %rsi, %rcx | |
| ; X64-NOBMI-NEXT: movl $1, %eax | |
| ; X64-NOBMI-NEXT: # kill: def $cl killed $cl killed $rcx | |
| ; X64-NOBMI-NEXT: shlq %cl, %rax | |
| ; X64-NOBMI-NEXT: decl %eax | |
| ; X64-NOBMI-NEXT: andl %edi, %eax | |
| ; X64-NOBMI-NEXT: # kill: def $eax killed $eax killed $rax | |
| ; X64-NOBMI-NEXT: retq | |
| ; | |
| ; X64-BMI1-LABEL: bzhi64_32_a0: | |
| ; X64-BMI1: # %bb.0: | |
| ; X64-BMI1-NEXT: shll $8, %esi | |
| ; X64-BMI1-NEXT: bextrl %esi, %edi, %eax | |
| ; X64-BMI1-NEXT: retq | |
| ; | |
| ; X64-BMI2-LABEL: bzhi64_32_a0: | |
| ; X64-BMI2: # %bb.0: | |
| ; X64-BMI2-NEXT: bzhil %esi, %edi, %eax | |
| ; X64-BMI2-NEXT: retq | |
| %onebit = shl i64 1, %numlowbits | |
| %mask = add nsw i64 %onebit, -1 | |
| %masked = and i64 %mask, %val | |
| %res = trunc i64 %masked to i32 | |
| ret i32 %res | |
| } | |
| ; Shifting happens in 64-bit, then truncation. Masking is 32-bit. | |
| define i32 @bzhi64_32_a1(i64 %val, i32 %numlowbits) nounwind { | |
| ; X86-NOBMI-LABEL: bzhi64_32_a1: | |
| ; X86-NOBMI: # %bb.0: | |
| ; X86-NOBMI-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-NOBMI-NEXT: movl $1, %eax | |
| ; X86-NOBMI-NEXT: shll %cl, %eax | |
| ; X86-NOBMI-NEXT: decl %eax | |
| ; X86-NOBMI-NEXT: andl {{[0-9]+}}(%esp), %eax | |
| ; X86-NOBMI-NEXT: retl | |
| ; | |
| ; X86-BMI1-LABEL: bzhi64_32_a1: | |
| ; X86-BMI1: # %bb.0: | |
| ; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: shll $8, %eax | |
| ; X86-BMI1-NEXT: bextrl %eax, {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: retl | |
| ; | |
| ; X86-BMI2-LABEL: bzhi64_32_a1: | |
| ; X86-BMI2: # %bb.0: | |
| ; X86-BMI2-NEXT: movzbl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: bzhil %eax, {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: retl | |
| ; | |
| ; X64-NOBMI-LABEL: bzhi64_32_a1: | |
| ; X64-NOBMI: # %bb.0: | |
| ; X64-NOBMI-NEXT: movl %esi, %ecx | |
| ; X64-NOBMI-NEXT: movl $1, %eax | |
| ; X64-NOBMI-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X64-NOBMI-NEXT: shll %cl, %eax | |
| ; X64-NOBMI-NEXT: decl %eax | |
| ; X64-NOBMI-NEXT: andl %edi, %eax | |
| ; X64-NOBMI-NEXT: retq | |
| ; | |
| ; X64-BMI1-LABEL: bzhi64_32_a1: | |
| ; X64-BMI1: # %bb.0: | |
| ; X64-BMI1-NEXT: shll $8, %esi | |
| ; X64-BMI1-NEXT: bextrl %esi, %edi, %eax | |
| ; X64-BMI1-NEXT: retq | |
| ; | |
| ; X64-BMI2-LABEL: bzhi64_32_a1: | |
| ; X64-BMI2: # %bb.0: | |
| ; X64-BMI2-NEXT: bzhil %esi, %edi, %eax | |
| ; X64-BMI2-NEXT: retq | |
| %truncval = trunc i64 %val to i32 | |
| %onebit = shl i32 1, %numlowbits | |
| %mask = add nsw i32 %onebit, -1 | |
| %masked = and i32 %mask, %truncval | |
| ret i32 %masked | |
| } | |
| ; Shifting happens in 64-bit, then truncation (with extra use). | |
| ; Masking is 32-bit. | |
| define i32 @bzhi64_32_a1_trunc_extrause(i64 %val, i32 %numlowbits, ptr %escape) nounwind { | |
| ; X86-NOBMI-LABEL: bzhi64_32_a1_trunc_extrause: | |
| ; X86-NOBMI: # %bb.0: | |
| ; X86-NOBMI-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-NOBMI-NEXT: movl {{[0-9]+}}(%esp), %edx | |
| ; X86-NOBMI-NEXT: movl {{[0-9]+}}(%esp), %eax | |
| ; X86-NOBMI-NEXT: movl %edx, (%eax) | |
| ; X86-NOBMI-NEXT: movl $1, %eax | |
| ; X86-NOBMI-NEXT: shll %cl, %eax | |
| ; X86-NOBMI-NEXT: decl %eax | |
| ; X86-NOBMI-NEXT: andl %edx, %eax | |
| ; X86-NOBMI-NEXT: retl | |
| ; | |
| ; X86-BMI1-LABEL: bzhi64_32_a1_trunc_extrause: | |
| ; X86-BMI1: # %bb.0: | |
| ; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: movl {{[0-9]+}}(%esp), %ecx | |
| ; X86-BMI1-NEXT: movl {{[0-9]+}}(%esp), %edx | |
| ; X86-BMI1-NEXT: movl %ecx, (%edx) | |
| ; X86-BMI1-NEXT: shll $8, %eax | |
| ; X86-BMI1-NEXT: bextrl %eax, %ecx, %eax | |
| ; X86-BMI1-NEXT: retl | |
| ; | |
| ; X86-BMI2-LABEL: bzhi64_32_a1_trunc_extrause: | |
| ; X86-BMI2: # %bb.0: | |
| ; X86-BMI2-NEXT: movzbl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: movl {{[0-9]+}}(%esp), %ecx | |
| ; X86-BMI2-NEXT: movl {{[0-9]+}}(%esp), %edx | |
| ; X86-BMI2-NEXT: movl %ecx, (%edx) | |
| ; X86-BMI2-NEXT: bzhil %eax, %ecx, %eax | |
| ; X86-BMI2-NEXT: retl | |
| ; | |
| ; X64-NOBMI-LABEL: bzhi64_32_a1_trunc_extrause: | |
| ; X64-NOBMI: # %bb.0: | |
| ; X64-NOBMI-NEXT: movl %esi, %ecx | |
| ; X64-NOBMI-NEXT: movl %edi, (%rdx) | |
| ; X64-NOBMI-NEXT: movl $1, %eax | |
| ; X64-NOBMI-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X64-NOBMI-NEXT: shll %cl, %eax | |
| ; X64-NOBMI-NEXT: decl %eax | |
| ; X64-NOBMI-NEXT: andl %edi, %eax | |
| ; X64-NOBMI-NEXT: retq | |
| ; | |
| ; X64-BMI1-LABEL: bzhi64_32_a1_trunc_extrause: | |
| ; X64-BMI1: # %bb.0: | |
| ; X64-BMI1-NEXT: movl %edi, (%rdx) | |
| ; X64-BMI1-NEXT: shll $8, %esi | |
| ; X64-BMI1-NEXT: bextrl %esi, %edi, %eax | |
| ; X64-BMI1-NEXT: retq | |
| ; | |
| ; X64-BMI2-LABEL: bzhi64_32_a1_trunc_extrause: | |
| ; X64-BMI2: # %bb.0: | |
| ; X64-BMI2-NEXT: movl %edi, (%rdx) | |
| ; X64-BMI2-NEXT: bzhil %esi, %edi, %eax | |
| ; X64-BMI2-NEXT: retq | |
| %truncval = trunc i64 %val to i32 | |
| store i32 %truncval, ptr %escape | |
| %onebit = shl i32 1, %numlowbits | |
| %mask = add nsw i32 %onebit, -1 | |
| %masked = and i32 %mask, %truncval | |
| ret i32 %masked | |
| } | |
| ; Shifting happens in 64-bit. Mask is 32-bit, but extended to 64-bit. | |
| ; Masking is 64-bit. Then truncation. | |
| define i32 @bzhi64_32_a2(i64 %val, i32 %numlowbits) nounwind { | |
| ; X86-NOBMI-LABEL: bzhi64_32_a2: | |
| ; X86-NOBMI: # %bb.0: | |
| ; X86-NOBMI-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-NOBMI-NEXT: movl $1, %eax | |
| ; X86-NOBMI-NEXT: shll %cl, %eax | |
| ; X86-NOBMI-NEXT: decl %eax | |
| ; X86-NOBMI-NEXT: andl {{[0-9]+}}(%esp), %eax | |
| ; X86-NOBMI-NEXT: retl | |
| ; | |
| ; X86-BMI1-LABEL: bzhi64_32_a2: | |
| ; X86-BMI1: # %bb.0: | |
| ; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: shll $8, %eax | |
| ; X86-BMI1-NEXT: bextrl %eax, {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: retl | |
| ; | |
| ; X86-BMI2-LABEL: bzhi64_32_a2: | |
| ; X86-BMI2: # %bb.0: | |
| ; X86-BMI2-NEXT: movzbl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: bzhil %eax, {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: retl | |
| ; | |
| ; X64-NOBMI-LABEL: bzhi64_32_a2: | |
| ; X64-NOBMI: # %bb.0: | |
| ; X64-NOBMI-NEXT: movl %esi, %ecx | |
| ; X64-NOBMI-NEXT: movl $1, %eax | |
| ; X64-NOBMI-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X64-NOBMI-NEXT: shll %cl, %eax | |
| ; X64-NOBMI-NEXT: decl %eax | |
| ; X64-NOBMI-NEXT: andl %edi, %eax | |
| ; X64-NOBMI-NEXT: retq | |
| ; | |
| ; X64-BMI1-LABEL: bzhi64_32_a2: | |
| ; X64-BMI1: # %bb.0: | |
| ; X64-BMI1-NEXT: shll $8, %esi | |
| ; X64-BMI1-NEXT: bextrl %esi, %edi, %eax | |
| ; X64-BMI1-NEXT: retq | |
| ; | |
| ; X64-BMI2-LABEL: bzhi64_32_a2: | |
| ; X64-BMI2: # %bb.0: | |
| ; X64-BMI2-NEXT: bzhil %esi, %edi, %eax | |
| ; X64-BMI2-NEXT: retq | |
| %onebit = shl i32 1, %numlowbits | |
| %mask = add nsw i32 %onebit, -1 | |
| %zextmask = zext i32 %mask to i64 | |
| %masked = and i64 %zextmask, %val | |
| %truncmasked = trunc i64 %masked to i32 | |
| ret i32 %truncmasked | |
| } | |
| ; Shifting happens in 64-bit. Mask is 32-bit, but calculated in 64-bit. | |
| ; Masking is 64-bit. Then truncation. | |
| define i32 @bzhi64_32_a3(i64 %val, i64 %numlowbits) nounwind { | |
| ; X86-NOBMI-LABEL: bzhi64_32_a3: | |
| ; X86-NOBMI: # %bb.0: | |
| ; X86-NOBMI-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-NOBMI-NEXT: movl $1, %edx | |
| ; X86-NOBMI-NEXT: shll %cl, %edx | |
| ; X86-NOBMI-NEXT: xorl %eax, %eax | |
| ; X86-NOBMI-NEXT: testb $32, %cl | |
| ; X86-NOBMI-NEXT: jne .LBB15_2 | |
| ; X86-NOBMI-NEXT: # %bb.1: | |
| ; X86-NOBMI-NEXT: movl %edx, %eax | |
| ; X86-NOBMI-NEXT: .LBB15_2: | |
| ; X86-NOBMI-NEXT: decl %eax | |
| ; X86-NOBMI-NEXT: andl {{[0-9]+}}(%esp), %eax | |
| ; X86-NOBMI-NEXT: retl | |
| ; | |
| ; X86-BMI1-LABEL: bzhi64_32_a3: | |
| ; X86-BMI1: # %bb.0: | |
| ; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-BMI1-NEXT: movl $1, %edx | |
| ; X86-BMI1-NEXT: shll %cl, %edx | |
| ; X86-BMI1-NEXT: xorl %eax, %eax | |
| ; X86-BMI1-NEXT: testb $32, %cl | |
| ; X86-BMI1-NEXT: jne .LBB15_2 | |
| ; X86-BMI1-NEXT: # %bb.1: | |
| ; X86-BMI1-NEXT: movl %edx, %eax | |
| ; X86-BMI1-NEXT: .LBB15_2: | |
| ; X86-BMI1-NEXT: decl %eax | |
| ; X86-BMI1-NEXT: andl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: retl | |
| ; | |
| ; X86-BMI2-LABEL: bzhi64_32_a3: | |
| ; X86-BMI2: # %bb.0: | |
| ; X86-BMI2-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-BMI2-NEXT: xorl %eax, %eax | |
| ; X86-BMI2-NEXT: testb $32, %cl | |
| ; X86-BMI2-NEXT: jne .LBB15_2 | |
| ; X86-BMI2-NEXT: # %bb.1: | |
| ; X86-BMI2-NEXT: movl $1, %eax | |
| ; X86-BMI2-NEXT: shlxl %ecx, %eax, %eax | |
| ; X86-BMI2-NEXT: .LBB15_2: | |
| ; X86-BMI2-NEXT: decl %eax | |
| ; X86-BMI2-NEXT: andl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: retl | |
| ; | |
| ; X64-NOBMI-LABEL: bzhi64_32_a3: | |
| ; X64-NOBMI: # %bb.0: | |
| ; X64-NOBMI-NEXT: movq %rsi, %rcx | |
| ; X64-NOBMI-NEXT: movl $1, %eax | |
| ; X64-NOBMI-NEXT: # kill: def $cl killed $cl killed $rcx | |
| ; X64-NOBMI-NEXT: shlq %cl, %rax | |
| ; X64-NOBMI-NEXT: decl %eax | |
| ; X64-NOBMI-NEXT: andl %edi, %eax | |
| ; X64-NOBMI-NEXT: # kill: def $eax killed $eax killed $rax | |
| ; X64-NOBMI-NEXT: retq | |
| ; | |
| ; X64-BMI1-LABEL: bzhi64_32_a3: | |
| ; X64-BMI1: # %bb.0: | |
| ; X64-BMI1-NEXT: shll $8, %esi | |
| ; X64-BMI1-NEXT: bextrl %esi, %edi, %eax | |
| ; X64-BMI1-NEXT: retq | |
| ; | |
| ; X64-BMI2-LABEL: bzhi64_32_a3: | |
| ; X64-BMI2: # %bb.0: | |
| ; X64-BMI2-NEXT: bzhil %esi, %edi, %eax | |
| ; X64-BMI2-NEXT: retq | |
| %onebit = shl i64 1, %numlowbits | |
| %mask = add nsw i64 %onebit, 4294967295 | |
| %masked = and i64 %mask, %val | |
| %truncmasked = trunc i64 %masked to i32 | |
| ret i32 %truncmasked | |
| } | |
| ; ---------------------------------------------------------------------------- ; | |
| ; Pattern b. 32-bit | |
| ; ---------------------------------------------------------------------------- ; | |
| define i32 @bzhi32_b0(i32 %val, i32 %numlowbits) nounwind { | |
| ; X86-NOBMI-LABEL: bzhi32_b0: | |
| ; X86-NOBMI: # %bb.0: | |
| ; X86-NOBMI-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-NOBMI-NEXT: movl $-1, %eax | |
| ; X86-NOBMI-NEXT: shll %cl, %eax | |
| ; X86-NOBMI-NEXT: notl %eax | |
| ; X86-NOBMI-NEXT: andl {{[0-9]+}}(%esp), %eax | |
| ; X86-NOBMI-NEXT: retl | |
| ; | |
| ; X86-BMI1-LABEL: bzhi32_b0: | |
| ; X86-BMI1: # %bb.0: | |
| ; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: shll $8, %eax | |
| ; X86-BMI1-NEXT: bextrl %eax, {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: retl | |
| ; | |
| ; X86-BMI2-LABEL: bzhi32_b0: | |
| ; X86-BMI2: # %bb.0: | |
| ; X86-BMI2-NEXT: movzbl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: bzhil %eax, {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: retl | |
| ; | |
| ; X64-NOBMI-LABEL: bzhi32_b0: | |
| ; X64-NOBMI: # %bb.0: | |
| ; X64-NOBMI-NEXT: movl %esi, %ecx | |
| ; X64-NOBMI-NEXT: movl $-1, %eax | |
| ; X64-NOBMI-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X64-NOBMI-NEXT: shll %cl, %eax | |
| ; X64-NOBMI-NEXT: notl %eax | |
| ; X64-NOBMI-NEXT: andl %edi, %eax | |
| ; X64-NOBMI-NEXT: retq | |
| ; | |
| ; X64-BMI1-LABEL: bzhi32_b0: | |
| ; X64-BMI1: # %bb.0: | |
| ; X64-BMI1-NEXT: shll $8, %esi | |
| ; X64-BMI1-NEXT: bextrl %esi, %edi, %eax | |
| ; X64-BMI1-NEXT: retq | |
| ; | |
| ; X64-BMI2-LABEL: bzhi32_b0: | |
| ; X64-BMI2: # %bb.0: | |
| ; X64-BMI2-NEXT: bzhil %esi, %edi, %eax | |
| ; X64-BMI2-NEXT: retq | |
| %notmask = shl i32 -1, %numlowbits | |
| %mask = xor i32 %notmask, -1 | |
| %masked = and i32 %mask, %val | |
| ret i32 %masked | |
| } | |
| define i32 @bzhi32_b1_indexzext(i32 %val, i8 zeroext %numlowbits) nounwind { | |
| ; X86-NOBMI-LABEL: bzhi32_b1_indexzext: | |
| ; X86-NOBMI: # %bb.0: | |
| ; X86-NOBMI-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-NOBMI-NEXT: movl $-1, %eax | |
| ; X86-NOBMI-NEXT: shll %cl, %eax | |
| ; X86-NOBMI-NEXT: notl %eax | |
| ; X86-NOBMI-NEXT: andl {{[0-9]+}}(%esp), %eax | |
| ; X86-NOBMI-NEXT: retl | |
| ; | |
| ; X86-BMI1-LABEL: bzhi32_b1_indexzext: | |
| ; X86-BMI1: # %bb.0: | |
| ; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: shll $8, %eax | |
| ; X86-BMI1-NEXT: bextrl %eax, {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: retl | |
| ; | |
| ; X86-BMI2-LABEL: bzhi32_b1_indexzext: | |
| ; X86-BMI2: # %bb.0: | |
| ; X86-BMI2-NEXT: movzbl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: bzhil %eax, {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: retl | |
| ; | |
| ; X64-NOBMI-LABEL: bzhi32_b1_indexzext: | |
| ; X64-NOBMI: # %bb.0: | |
| ; X64-NOBMI-NEXT: movl %esi, %ecx | |
| ; X64-NOBMI-NEXT: movl $-1, %eax | |
| ; X64-NOBMI-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X64-NOBMI-NEXT: shll %cl, %eax | |
| ; X64-NOBMI-NEXT: notl %eax | |
| ; X64-NOBMI-NEXT: andl %edi, %eax | |
| ; X64-NOBMI-NEXT: retq | |
| ; | |
| ; X64-BMI1-LABEL: bzhi32_b1_indexzext: | |
| ; X64-BMI1: # %bb.0: | |
| ; X64-BMI1-NEXT: shll $8, %esi | |
| ; X64-BMI1-NEXT: bextrl %esi, %edi, %eax | |
| ; X64-BMI1-NEXT: retq | |
| ; | |
| ; X64-BMI2-LABEL: bzhi32_b1_indexzext: | |
| ; X64-BMI2: # %bb.0: | |
| ; X64-BMI2-NEXT: bzhil %esi, %edi, %eax | |
| ; X64-BMI2-NEXT: retq | |
| %conv = zext i8 %numlowbits to i32 | |
| %notmask = shl i32 -1, %conv | |
| %mask = xor i32 %notmask, -1 | |
| %masked = and i32 %mask, %val | |
| ret i32 %masked | |
| } | |
| define i32 @bzhi32_b2_load(ptr %w, i32 %numlowbits) nounwind { | |
| ; X86-NOBMI-LABEL: bzhi32_b2_load: | |
| ; X86-NOBMI: # %bb.0: | |
| ; X86-NOBMI-NEXT: movl {{[0-9]+}}(%esp), %edx | |
| ; X86-NOBMI-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-NOBMI-NEXT: movl $-1, %eax | |
| ; X86-NOBMI-NEXT: shll %cl, %eax | |
| ; X86-NOBMI-NEXT: notl %eax | |
| ; X86-NOBMI-NEXT: andl (%edx), %eax | |
| ; X86-NOBMI-NEXT: retl | |
| ; | |
| ; X86-BMI1-LABEL: bzhi32_b2_load: | |
| ; X86-BMI1: # %bb.0: | |
| ; X86-BMI1-NEXT: movl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-BMI1-NEXT: shll $8, %ecx | |
| ; X86-BMI1-NEXT: bextrl %ecx, (%eax), %eax | |
| ; X86-BMI1-NEXT: retl | |
| ; | |
| ; X86-BMI2-LABEL: bzhi32_b2_load: | |
| ; X86-BMI2: # %bb.0: | |
| ; X86-BMI2-NEXT: movl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-BMI2-NEXT: bzhil %ecx, (%eax), %eax | |
| ; X86-BMI2-NEXT: retl | |
| ; | |
| ; X64-NOBMI-LABEL: bzhi32_b2_load: | |
| ; X64-NOBMI: # %bb.0: | |
| ; X64-NOBMI-NEXT: movl %esi, %ecx | |
| ; X64-NOBMI-NEXT: movl $-1, %eax | |
| ; X64-NOBMI-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X64-NOBMI-NEXT: shll %cl, %eax | |
| ; X64-NOBMI-NEXT: notl %eax | |
| ; X64-NOBMI-NEXT: andl (%rdi), %eax | |
| ; X64-NOBMI-NEXT: retq | |
| ; | |
| ; X64-BMI1-LABEL: bzhi32_b2_load: | |
| ; X64-BMI1: # %bb.0: | |
| ; X64-BMI1-NEXT: shll $8, %esi | |
| ; X64-BMI1-NEXT: bextrl %esi, (%rdi), %eax | |
| ; X64-BMI1-NEXT: retq | |
| ; | |
| ; X64-BMI2-LABEL: bzhi32_b2_load: | |
| ; X64-BMI2: # %bb.0: | |
| ; X64-BMI2-NEXT: bzhil %esi, (%rdi), %eax | |
| ; X64-BMI2-NEXT: retq | |
| %val = load i32, ptr %w | |
| %notmask = shl i32 -1, %numlowbits | |
| %mask = xor i32 %notmask, -1 | |
| %masked = and i32 %mask, %val | |
| ret i32 %masked | |
| } | |
| define i32 @bzhi32_b3_load_indexzext(ptr %w, i8 zeroext %numlowbits) nounwind { | |
| ; X86-NOBMI-LABEL: bzhi32_b3_load_indexzext: | |
| ; X86-NOBMI: # %bb.0: | |
| ; X86-NOBMI-NEXT: movl {{[0-9]+}}(%esp), %edx | |
| ; X86-NOBMI-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-NOBMI-NEXT: movl $-1, %eax | |
| ; X86-NOBMI-NEXT: shll %cl, %eax | |
| ; X86-NOBMI-NEXT: notl %eax | |
| ; X86-NOBMI-NEXT: andl (%edx), %eax | |
| ; X86-NOBMI-NEXT: retl | |
| ; | |
| ; X86-BMI1-LABEL: bzhi32_b3_load_indexzext: | |
| ; X86-BMI1: # %bb.0: | |
| ; X86-BMI1-NEXT: movl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-BMI1-NEXT: shll $8, %ecx | |
| ; X86-BMI1-NEXT: bextrl %ecx, (%eax), %eax | |
| ; X86-BMI1-NEXT: retl | |
| ; | |
| ; X86-BMI2-LABEL: bzhi32_b3_load_indexzext: | |
| ; X86-BMI2: # %bb.0: | |
| ; X86-BMI2-NEXT: movl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-BMI2-NEXT: bzhil %ecx, (%eax), %eax | |
| ; X86-BMI2-NEXT: retl | |
| ; | |
| ; X64-NOBMI-LABEL: bzhi32_b3_load_indexzext: | |
| ; X64-NOBMI: # %bb.0: | |
| ; X64-NOBMI-NEXT: movl %esi, %ecx | |
| ; X64-NOBMI-NEXT: movl $-1, %eax | |
| ; X64-NOBMI-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X64-NOBMI-NEXT: shll %cl, %eax | |
| ; X64-NOBMI-NEXT: notl %eax | |
| ; X64-NOBMI-NEXT: andl (%rdi), %eax | |
| ; X64-NOBMI-NEXT: retq | |
| ; | |
| ; X64-BMI1-LABEL: bzhi32_b3_load_indexzext: | |
| ; X64-BMI1: # %bb.0: | |
| ; X64-BMI1-NEXT: shll $8, %esi | |
| ; X64-BMI1-NEXT: bextrl %esi, (%rdi), %eax | |
| ; X64-BMI1-NEXT: retq | |
| ; | |
| ; X64-BMI2-LABEL: bzhi32_b3_load_indexzext: | |
| ; X64-BMI2: # %bb.0: | |
| ; X64-BMI2-NEXT: bzhil %esi, (%rdi), %eax | |
| ; X64-BMI2-NEXT: retq | |
| %val = load i32, ptr %w | |
| %conv = zext i8 %numlowbits to i32 | |
| %notmask = shl i32 -1, %conv | |
| %mask = xor i32 %notmask, -1 | |
| %masked = and i32 %mask, %val | |
| ret i32 %masked | |
| } | |
| define i32 @bzhi32_b4_commutative(i32 %val, i32 %numlowbits) nounwind { | |
| ; X86-NOBMI-LABEL: bzhi32_b4_commutative: | |
| ; X86-NOBMI: # %bb.0: | |
| ; X86-NOBMI-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-NOBMI-NEXT: movl $-1, %eax | |
| ; X86-NOBMI-NEXT: shll %cl, %eax | |
| ; X86-NOBMI-NEXT: notl %eax | |
| ; X86-NOBMI-NEXT: andl {{[0-9]+}}(%esp), %eax | |
| ; X86-NOBMI-NEXT: retl | |
| ; | |
| ; X86-BMI1-LABEL: bzhi32_b4_commutative: | |
| ; X86-BMI1: # %bb.0: | |
| ; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: shll $8, %eax | |
| ; X86-BMI1-NEXT: bextrl %eax, {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: retl | |
| ; | |
| ; X86-BMI2-LABEL: bzhi32_b4_commutative: | |
| ; X86-BMI2: # %bb.0: | |
| ; X86-BMI2-NEXT: movzbl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: bzhil %eax, {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: retl | |
| ; | |
| ; X64-NOBMI-LABEL: bzhi32_b4_commutative: | |
| ; X64-NOBMI: # %bb.0: | |
| ; X64-NOBMI-NEXT: movl %esi, %ecx | |
| ; X64-NOBMI-NEXT: movl $-1, %eax | |
| ; X64-NOBMI-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X64-NOBMI-NEXT: shll %cl, %eax | |
| ; X64-NOBMI-NEXT: notl %eax | |
| ; X64-NOBMI-NEXT: andl %edi, %eax | |
| ; X64-NOBMI-NEXT: retq | |
| ; | |
| ; X64-BMI1-LABEL: bzhi32_b4_commutative: | |
| ; X64-BMI1: # %bb.0: | |
| ; X64-BMI1-NEXT: shll $8, %esi | |
| ; X64-BMI1-NEXT: bextrl %esi, %edi, %eax | |
| ; X64-BMI1-NEXT: retq | |
| ; | |
| ; X64-BMI2-LABEL: bzhi32_b4_commutative: | |
| ; X64-BMI2: # %bb.0: | |
| ; X64-BMI2-NEXT: bzhil %esi, %edi, %eax | |
| ; X64-BMI2-NEXT: retq | |
| %notmask = shl i32 -1, %numlowbits | |
| %mask = xor i32 %notmask, -1 | |
| %masked = and i32 %val, %mask ; swapped order | |
| ret i32 %masked | |
| } | |
| ; 64-bit | |
| define i64 @bzhi64_b0(i64 %val, i64 %numlowbits) nounwind { | |
| ; X86-NOBMI-LABEL: bzhi64_b0: | |
| ; X86-NOBMI: # %bb.0: | |
| ; X86-NOBMI-NEXT: pushl %esi | |
| ; X86-NOBMI-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-NOBMI-NEXT: movl $-1, %edx | |
| ; X86-NOBMI-NEXT: movl $-1, %esi | |
| ; X86-NOBMI-NEXT: shll %cl, %esi | |
| ; X86-NOBMI-NEXT: xorl %eax, %eax | |
| ; X86-NOBMI-NEXT: testb $32, %cl | |
| ; X86-NOBMI-NEXT: jne .LBB21_1 | |
| ; X86-NOBMI-NEXT: # %bb.2: | |
| ; X86-NOBMI-NEXT: movl %esi, %eax | |
| ; X86-NOBMI-NEXT: jmp .LBB21_3 | |
| ; X86-NOBMI-NEXT: .LBB21_1: | |
| ; X86-NOBMI-NEXT: movl %esi, %edx | |
| ; X86-NOBMI-NEXT: .LBB21_3: | |
| ; X86-NOBMI-NEXT: notl %edx | |
| ; X86-NOBMI-NEXT: notl %eax | |
| ; X86-NOBMI-NEXT: andl {{[0-9]+}}(%esp), %eax | |
| ; X86-NOBMI-NEXT: andl {{[0-9]+}}(%esp), %edx | |
| ; X86-NOBMI-NEXT: popl %esi | |
| ; X86-NOBMI-NEXT: retl | |
| ; | |
| ; X86-BMI1-LABEL: bzhi64_b0: | |
| ; X86-BMI1: # %bb.0: | |
| ; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-BMI1-NEXT: movl $-1, %edx | |
| ; X86-BMI1-NEXT: movl $-1, %eax | |
| ; X86-BMI1-NEXT: shll %cl, %eax | |
| ; X86-BMI1-NEXT: testb $32, %cl | |
| ; X86-BMI1-NEXT: je .LBB21_2 | |
| ; X86-BMI1-NEXT: # %bb.1: | |
| ; X86-BMI1-NEXT: movl %eax, %edx | |
| ; X86-BMI1-NEXT: xorl %eax, %eax | |
| ; X86-BMI1-NEXT: .LBB21_2: | |
| ; X86-BMI1-NEXT: andnl {{[0-9]+}}(%esp), %eax, %eax | |
| ; X86-BMI1-NEXT: andnl {{[0-9]+}}(%esp), %edx, %edx | |
| ; X86-BMI1-NEXT: retl | |
| ; | |
| ; X86-BMI2-LABEL: bzhi64_b0: | |
| ; X86-BMI2: # %bb.0: | |
| ; X86-BMI2-NEXT: movzbl {{[0-9]+}}(%esp), %edx | |
| ; X86-BMI2-NEXT: movl $-1, %ecx | |
| ; X86-BMI2-NEXT: shlxl %edx, %ecx, %eax | |
| ; X86-BMI2-NEXT: testb $32, %dl | |
| ; X86-BMI2-NEXT: je .LBB21_2 | |
| ; X86-BMI2-NEXT: # %bb.1: | |
| ; X86-BMI2-NEXT: movl %eax, %ecx | |
| ; X86-BMI2-NEXT: xorl %eax, %eax | |
| ; X86-BMI2-NEXT: .LBB21_2: | |
| ; X86-BMI2-NEXT: andnl {{[0-9]+}}(%esp), %eax, %eax | |
| ; X86-BMI2-NEXT: andnl {{[0-9]+}}(%esp), %ecx, %edx | |
| ; X86-BMI2-NEXT: retl | |
| ; | |
| ; X64-NOBMI-LABEL: bzhi64_b0: | |
| ; X64-NOBMI: # %bb.0: | |
| ; X64-NOBMI-NEXT: movq %rsi, %rcx | |
| ; X64-NOBMI-NEXT: movq $-1, %rax | |
| ; X64-NOBMI-NEXT: # kill: def $cl killed $cl killed $rcx | |
| ; X64-NOBMI-NEXT: shlq %cl, %rax | |
| ; X64-NOBMI-NEXT: notq %rax | |
| ; X64-NOBMI-NEXT: andq %rdi, %rax | |
| ; X64-NOBMI-NEXT: retq | |
| ; | |
| ; X64-BMI1-LABEL: bzhi64_b0: | |
| ; X64-BMI1: # %bb.0: | |
| ; X64-BMI1-NEXT: shll $8, %esi | |
| ; X64-BMI1-NEXT: bextrq %rsi, %rdi, %rax | |
| ; X64-BMI1-NEXT: retq | |
| ; | |
| ; X64-BMI2-LABEL: bzhi64_b0: | |
| ; X64-BMI2: # %bb.0: | |
| ; X64-BMI2-NEXT: bzhiq %rsi, %rdi, %rax | |
| ; X64-BMI2-NEXT: retq | |
| %notmask = shl i64 -1, %numlowbits | |
| %mask = xor i64 %notmask, -1 | |
| %masked = and i64 %mask, %val | |
| ret i64 %masked | |
| } | |
| define i64 @bzhi64_b1_indexzext(i64 %val, i8 zeroext %numlowbits) nounwind { | |
| ; X86-NOBMI-LABEL: bzhi64_b1_indexzext: | |
| ; X86-NOBMI: # %bb.0: | |
| ; X86-NOBMI-NEXT: pushl %esi | |
| ; X86-NOBMI-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-NOBMI-NEXT: movl $-1, %edx | |
| ; X86-NOBMI-NEXT: movl $-1, %esi | |
| ; X86-NOBMI-NEXT: shll %cl, %esi | |
| ; X86-NOBMI-NEXT: xorl %eax, %eax | |
| ; X86-NOBMI-NEXT: testb $32, %cl | |
| ; X86-NOBMI-NEXT: jne .LBB22_1 | |
| ; X86-NOBMI-NEXT: # %bb.2: | |
| ; X86-NOBMI-NEXT: movl %esi, %eax | |
| ; X86-NOBMI-NEXT: jmp .LBB22_3 | |
| ; X86-NOBMI-NEXT: .LBB22_1: | |
| ; X86-NOBMI-NEXT: movl %esi, %edx | |
| ; X86-NOBMI-NEXT: .LBB22_3: | |
| ; X86-NOBMI-NEXT: notl %edx | |
| ; X86-NOBMI-NEXT: notl %eax | |
| ; X86-NOBMI-NEXT: andl {{[0-9]+}}(%esp), %eax | |
| ; X86-NOBMI-NEXT: andl {{[0-9]+}}(%esp), %edx | |
| ; X86-NOBMI-NEXT: popl %esi | |
| ; X86-NOBMI-NEXT: retl | |
| ; | |
| ; X86-BMI1-LABEL: bzhi64_b1_indexzext: | |
| ; X86-BMI1: # %bb.0: | |
| ; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-BMI1-NEXT: movl $-1, %edx | |
| ; X86-BMI1-NEXT: movl $-1, %eax | |
| ; X86-BMI1-NEXT: shll %cl, %eax | |
| ; X86-BMI1-NEXT: testb $32, %cl | |
| ; X86-BMI1-NEXT: je .LBB22_2 | |
| ; X86-BMI1-NEXT: # %bb.1: | |
| ; X86-BMI1-NEXT: movl %eax, %edx | |
| ; X86-BMI1-NEXT: xorl %eax, %eax | |
| ; X86-BMI1-NEXT: .LBB22_2: | |
| ; X86-BMI1-NEXT: andnl {{[0-9]+}}(%esp), %eax, %eax | |
| ; X86-BMI1-NEXT: andnl {{[0-9]+}}(%esp), %edx, %edx | |
| ; X86-BMI1-NEXT: retl | |
| ; | |
| ; X86-BMI2-LABEL: bzhi64_b1_indexzext: | |
| ; X86-BMI2: # %bb.0: | |
| ; X86-BMI2-NEXT: movzbl {{[0-9]+}}(%esp), %edx | |
| ; X86-BMI2-NEXT: movl $-1, %ecx | |
| ; X86-BMI2-NEXT: shlxl %edx, %ecx, %eax | |
| ; X86-BMI2-NEXT: testb $32, %dl | |
| ; X86-BMI2-NEXT: je .LBB22_2 | |
| ; X86-BMI2-NEXT: # %bb.1: | |
| ; X86-BMI2-NEXT: movl %eax, %ecx | |
| ; X86-BMI2-NEXT: xorl %eax, %eax | |
| ; X86-BMI2-NEXT: .LBB22_2: | |
| ; X86-BMI2-NEXT: andnl {{[0-9]+}}(%esp), %eax, %eax | |
| ; X86-BMI2-NEXT: andnl {{[0-9]+}}(%esp), %ecx, %edx | |
| ; X86-BMI2-NEXT: retl | |
| ; | |
| ; X64-NOBMI-LABEL: bzhi64_b1_indexzext: | |
| ; X64-NOBMI: # %bb.0: | |
| ; X64-NOBMI-NEXT: movl %esi, %ecx | |
| ; X64-NOBMI-NEXT: movq $-1, %rax | |
| ; X64-NOBMI-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X64-NOBMI-NEXT: shlq %cl, %rax | |
| ; X64-NOBMI-NEXT: notq %rax | |
| ; X64-NOBMI-NEXT: andq %rdi, %rax | |
| ; X64-NOBMI-NEXT: retq | |
| ; | |
| ; X64-BMI1-LABEL: bzhi64_b1_indexzext: | |
| ; X64-BMI1: # %bb.0: | |
| ; X64-BMI1-NEXT: # kill: def $esi killed $esi def $rsi | |
| ; X64-BMI1-NEXT: shll $8, %esi | |
| ; X64-BMI1-NEXT: bextrq %rsi, %rdi, %rax | |
| ; X64-BMI1-NEXT: retq | |
| ; | |
| ; X64-BMI2-LABEL: bzhi64_b1_indexzext: | |
| ; X64-BMI2: # %bb.0: | |
| ; X64-BMI2-NEXT: # kill: def $esi killed $esi def $rsi | |
| ; X64-BMI2-NEXT: bzhiq %rsi, %rdi, %rax | |
| ; X64-BMI2-NEXT: retq | |
| %conv = zext i8 %numlowbits to i64 | |
| %notmask = shl i64 -1, %conv | |
| %mask = xor i64 %notmask, -1 | |
| %masked = and i64 %mask, %val | |
| ret i64 %masked | |
| } | |
| define i64 @bzhi64_b2_load(ptr %w, i64 %numlowbits) nounwind { | |
| ; X86-NOBMI-LABEL: bzhi64_b2_load: | |
| ; X86-NOBMI: # %bb.0: | |
| ; X86-NOBMI-NEXT: pushl %edi | |
| ; X86-NOBMI-NEXT: pushl %esi | |
| ; X86-NOBMI-NEXT: movl {{[0-9]+}}(%esp), %esi | |
| ; X86-NOBMI-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-NOBMI-NEXT: movl $-1, %edx | |
| ; X86-NOBMI-NEXT: movl $-1, %edi | |
| ; X86-NOBMI-NEXT: shll %cl, %edi | |
| ; X86-NOBMI-NEXT: xorl %eax, %eax | |
| ; X86-NOBMI-NEXT: testb $32, %cl | |
| ; X86-NOBMI-NEXT: jne .LBB23_1 | |
| ; X86-NOBMI-NEXT: # %bb.2: | |
| ; X86-NOBMI-NEXT: movl %edi, %eax | |
| ; X86-NOBMI-NEXT: jmp .LBB23_3 | |
| ; X86-NOBMI-NEXT: .LBB23_1: | |
| ; X86-NOBMI-NEXT: movl %edi, %edx | |
| ; X86-NOBMI-NEXT: .LBB23_3: | |
| ; X86-NOBMI-NEXT: notl %edx | |
| ; X86-NOBMI-NEXT: notl %eax | |
| ; X86-NOBMI-NEXT: andl (%esi), %eax | |
| ; X86-NOBMI-NEXT: andl 4(%esi), %edx | |
| ; X86-NOBMI-NEXT: popl %esi | |
| ; X86-NOBMI-NEXT: popl %edi | |
| ; X86-NOBMI-NEXT: retl | |
| ; | |
| ; X86-BMI1-LABEL: bzhi64_b2_load: | |
| ; X86-BMI1: # %bb.0: | |
| ; X86-BMI1-NEXT: pushl %esi | |
| ; X86-BMI1-NEXT: movl {{[0-9]+}}(%esp), %edx | |
| ; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-BMI1-NEXT: movl $-1, %esi | |
| ; X86-BMI1-NEXT: movl $-1, %eax | |
| ; X86-BMI1-NEXT: shll %cl, %eax | |
| ; X86-BMI1-NEXT: testb $32, %cl | |
| ; X86-BMI1-NEXT: je .LBB23_2 | |
| ; X86-BMI1-NEXT: # %bb.1: | |
| ; X86-BMI1-NEXT: movl %eax, %esi | |
| ; X86-BMI1-NEXT: xorl %eax, %eax | |
| ; X86-BMI1-NEXT: .LBB23_2: | |
| ; X86-BMI1-NEXT: andnl (%edx), %eax, %eax | |
| ; X86-BMI1-NEXT: andnl 4(%edx), %esi, %edx | |
| ; X86-BMI1-NEXT: popl %esi | |
| ; X86-BMI1-NEXT: retl | |
| ; | |
| ; X86-BMI2-LABEL: bzhi64_b2_load: | |
| ; X86-BMI2: # %bb.0: | |
| ; X86-BMI2-NEXT: pushl %ebx | |
| ; X86-BMI2-NEXT: movl {{[0-9]+}}(%esp), %ecx | |
| ; X86-BMI2-NEXT: movzbl {{[0-9]+}}(%esp), %ebx | |
| ; X86-BMI2-NEXT: movl $-1, %edx | |
| ; X86-BMI2-NEXT: shlxl %ebx, %edx, %eax | |
| ; X86-BMI2-NEXT: testb $32, %bl | |
| ; X86-BMI2-NEXT: je .LBB23_2 | |
| ; X86-BMI2-NEXT: # %bb.1: | |
| ; X86-BMI2-NEXT: movl %eax, %edx | |
| ; X86-BMI2-NEXT: xorl %eax, %eax | |
| ; X86-BMI2-NEXT: .LBB23_2: | |
| ; X86-BMI2-NEXT: andnl (%ecx), %eax, %eax | |
| ; X86-BMI2-NEXT: andnl 4(%ecx), %edx, %edx | |
| ; X86-BMI2-NEXT: popl %ebx | |
| ; X86-BMI2-NEXT: retl | |
| ; | |
| ; X64-NOBMI-LABEL: bzhi64_b2_load: | |
| ; X64-NOBMI: # %bb.0: | |
| ; X64-NOBMI-NEXT: movq %rsi, %rcx | |
| ; X64-NOBMI-NEXT: movq $-1, %rax | |
| ; X64-NOBMI-NEXT: # kill: def $cl killed $cl killed $rcx | |
| ; X64-NOBMI-NEXT: shlq %cl, %rax | |
| ; X64-NOBMI-NEXT: notq %rax | |
| ; X64-NOBMI-NEXT: andq (%rdi), %rax | |
| ; X64-NOBMI-NEXT: retq | |
| ; | |
| ; X64-BMI1-LABEL: bzhi64_b2_load: | |
| ; X64-BMI1: # %bb.0: | |
| ; X64-BMI1-NEXT: shll $8, %esi | |
| ; X64-BMI1-NEXT: bextrq %rsi, (%rdi), %rax | |
| ; X64-BMI1-NEXT: retq | |
| ; | |
| ; X64-BMI2-LABEL: bzhi64_b2_load: | |
| ; X64-BMI2: # %bb.0: | |
| ; X64-BMI2-NEXT: bzhiq %rsi, (%rdi), %rax | |
| ; X64-BMI2-NEXT: retq | |
| %val = load i64, ptr %w | |
| %notmask = shl i64 -1, %numlowbits | |
| %mask = xor i64 %notmask, -1 | |
| %masked = and i64 %mask, %val | |
| ret i64 %masked | |
| } | |
| define i64 @bzhi64_b3_load_indexzext(ptr %w, i8 zeroext %numlowbits) nounwind { | |
| ; X86-NOBMI-LABEL: bzhi64_b3_load_indexzext: | |
| ; X86-NOBMI: # %bb.0: | |
| ; X86-NOBMI-NEXT: pushl %edi | |
| ; X86-NOBMI-NEXT: pushl %esi | |
| ; X86-NOBMI-NEXT: movl {{[0-9]+}}(%esp), %esi | |
| ; X86-NOBMI-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-NOBMI-NEXT: movl $-1, %edx | |
| ; X86-NOBMI-NEXT: movl $-1, %edi | |
| ; X86-NOBMI-NEXT: shll %cl, %edi | |
| ; X86-NOBMI-NEXT: xorl %eax, %eax | |
| ; X86-NOBMI-NEXT: testb $32, %cl | |
| ; X86-NOBMI-NEXT: jne .LBB24_1 | |
| ; X86-NOBMI-NEXT: # %bb.2: | |
| ; X86-NOBMI-NEXT: movl %edi, %eax | |
| ; X86-NOBMI-NEXT: jmp .LBB24_3 | |
| ; X86-NOBMI-NEXT: .LBB24_1: | |
| ; X86-NOBMI-NEXT: movl %edi, %edx | |
| ; X86-NOBMI-NEXT: .LBB24_3: | |
| ; X86-NOBMI-NEXT: notl %edx | |
| ; X86-NOBMI-NEXT: notl %eax | |
| ; X86-NOBMI-NEXT: andl (%esi), %eax | |
| ; X86-NOBMI-NEXT: andl 4(%esi), %edx | |
| ; X86-NOBMI-NEXT: popl %esi | |
| ; X86-NOBMI-NEXT: popl %edi | |
| ; X86-NOBMI-NEXT: retl | |
| ; | |
| ; X86-BMI1-LABEL: bzhi64_b3_load_indexzext: | |
| ; X86-BMI1: # %bb.0: | |
| ; X86-BMI1-NEXT: pushl %esi | |
| ; X86-BMI1-NEXT: movl {{[0-9]+}}(%esp), %edx | |
| ; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-BMI1-NEXT: movl $-1, %esi | |
| ; X86-BMI1-NEXT: movl $-1, %eax | |
| ; X86-BMI1-NEXT: shll %cl, %eax | |
| ; X86-BMI1-NEXT: testb $32, %cl | |
| ; X86-BMI1-NEXT: je .LBB24_2 | |
| ; X86-BMI1-NEXT: # %bb.1: | |
| ; X86-BMI1-NEXT: movl %eax, %esi | |
| ; X86-BMI1-NEXT: xorl %eax, %eax | |
| ; X86-BMI1-NEXT: .LBB24_2: | |
| ; X86-BMI1-NEXT: andnl (%edx), %eax, %eax | |
| ; X86-BMI1-NEXT: andnl 4(%edx), %esi, %edx | |
| ; X86-BMI1-NEXT: popl %esi | |
| ; X86-BMI1-NEXT: retl | |
| ; | |
| ; X86-BMI2-LABEL: bzhi64_b3_load_indexzext: | |
| ; X86-BMI2: # %bb.0: | |
| ; X86-BMI2-NEXT: pushl %ebx | |
| ; X86-BMI2-NEXT: movl {{[0-9]+}}(%esp), %ecx | |
| ; X86-BMI2-NEXT: movzbl {{[0-9]+}}(%esp), %ebx | |
| ; X86-BMI2-NEXT: movl $-1, %edx | |
| ; X86-BMI2-NEXT: shlxl %ebx, %edx, %eax | |
| ; X86-BMI2-NEXT: testb $32, %bl | |
| ; X86-BMI2-NEXT: je .LBB24_2 | |
| ; X86-BMI2-NEXT: # %bb.1: | |
| ; X86-BMI2-NEXT: movl %eax, %edx | |
| ; X86-BMI2-NEXT: xorl %eax, %eax | |
| ; X86-BMI2-NEXT: .LBB24_2: | |
| ; X86-BMI2-NEXT: andnl (%ecx), %eax, %eax | |
| ; X86-BMI2-NEXT: andnl 4(%ecx), %edx, %edx | |
| ; X86-BMI2-NEXT: popl %ebx | |
| ; X86-BMI2-NEXT: retl | |
| ; | |
| ; X64-NOBMI-LABEL: bzhi64_b3_load_indexzext: | |
| ; X64-NOBMI: # %bb.0: | |
| ; X64-NOBMI-NEXT: movl %esi, %ecx | |
| ; X64-NOBMI-NEXT: movq $-1, %rax | |
| ; X64-NOBMI-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X64-NOBMI-NEXT: shlq %cl, %rax | |
| ; X64-NOBMI-NEXT: notq %rax | |
| ; X64-NOBMI-NEXT: andq (%rdi), %rax | |
| ; X64-NOBMI-NEXT: retq | |
| ; | |
| ; X64-BMI1-LABEL: bzhi64_b3_load_indexzext: | |
| ; X64-BMI1: # %bb.0: | |
| ; X64-BMI1-NEXT: # kill: def $esi killed $esi def $rsi | |
| ; X64-BMI1-NEXT: shll $8, %esi | |
| ; X64-BMI1-NEXT: bextrq %rsi, (%rdi), %rax | |
| ; X64-BMI1-NEXT: retq | |
| ; | |
| ; X64-BMI2-LABEL: bzhi64_b3_load_indexzext: | |
| ; X64-BMI2: # %bb.0: | |
| ; X64-BMI2-NEXT: # kill: def $esi killed $esi def $rsi | |
| ; X64-BMI2-NEXT: bzhiq %rsi, (%rdi), %rax | |
| ; X64-BMI2-NEXT: retq | |
| %val = load i64, ptr %w | |
| %conv = zext i8 %numlowbits to i64 | |
| %notmask = shl i64 -1, %conv | |
| %mask = xor i64 %notmask, -1 | |
| %masked = and i64 %mask, %val | |
| ret i64 %masked | |
| } | |
| define i64 @bzhi64_b4_commutative(i64 %val, i64 %numlowbits) nounwind { | |
| ; X86-NOBMI-LABEL: bzhi64_b4_commutative: | |
| ; X86-NOBMI: # %bb.0: | |
| ; X86-NOBMI-NEXT: pushl %esi | |
| ; X86-NOBMI-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-NOBMI-NEXT: movl $-1, %edx | |
| ; X86-NOBMI-NEXT: movl $-1, %esi | |
| ; X86-NOBMI-NEXT: shll %cl, %esi | |
| ; X86-NOBMI-NEXT: xorl %eax, %eax | |
| ; X86-NOBMI-NEXT: testb $32, %cl | |
| ; X86-NOBMI-NEXT: jne .LBB25_1 | |
| ; X86-NOBMI-NEXT: # %bb.2: | |
| ; X86-NOBMI-NEXT: movl %esi, %eax | |
| ; X86-NOBMI-NEXT: jmp .LBB25_3 | |
| ; X86-NOBMI-NEXT: .LBB25_1: | |
| ; X86-NOBMI-NEXT: movl %esi, %edx | |
| ; X86-NOBMI-NEXT: .LBB25_3: | |
| ; X86-NOBMI-NEXT: notl %edx | |
| ; X86-NOBMI-NEXT: notl %eax | |
| ; X86-NOBMI-NEXT: andl {{[0-9]+}}(%esp), %eax | |
| ; X86-NOBMI-NEXT: andl {{[0-9]+}}(%esp), %edx | |
| ; X86-NOBMI-NEXT: popl %esi | |
| ; X86-NOBMI-NEXT: retl | |
| ; | |
| ; X86-BMI1-LABEL: bzhi64_b4_commutative: | |
| ; X86-BMI1: # %bb.0: | |
| ; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-BMI1-NEXT: movl $-1, %edx | |
| ; X86-BMI1-NEXT: movl $-1, %eax | |
| ; X86-BMI1-NEXT: shll %cl, %eax | |
| ; X86-BMI1-NEXT: testb $32, %cl | |
| ; X86-BMI1-NEXT: je .LBB25_2 | |
| ; X86-BMI1-NEXT: # %bb.1: | |
| ; X86-BMI1-NEXT: movl %eax, %edx | |
| ; X86-BMI1-NEXT: xorl %eax, %eax | |
| ; X86-BMI1-NEXT: .LBB25_2: | |
| ; X86-BMI1-NEXT: andnl {{[0-9]+}}(%esp), %eax, %eax | |
| ; X86-BMI1-NEXT: andnl {{[0-9]+}}(%esp), %edx, %edx | |
| ; X86-BMI1-NEXT: retl | |
| ; | |
| ; X86-BMI2-LABEL: bzhi64_b4_commutative: | |
| ; X86-BMI2: # %bb.0: | |
| ; X86-BMI2-NEXT: movzbl {{[0-9]+}}(%esp), %edx | |
| ; X86-BMI2-NEXT: movl $-1, %ecx | |
| ; X86-BMI2-NEXT: shlxl %edx, %ecx, %eax | |
| ; X86-BMI2-NEXT: testb $32, %dl | |
| ; X86-BMI2-NEXT: je .LBB25_2 | |
| ; X86-BMI2-NEXT: # %bb.1: | |
| ; X86-BMI2-NEXT: movl %eax, %ecx | |
| ; X86-BMI2-NEXT: xorl %eax, %eax | |
| ; X86-BMI2-NEXT: .LBB25_2: | |
| ; X86-BMI2-NEXT: andnl {{[0-9]+}}(%esp), %eax, %eax | |
| ; X86-BMI2-NEXT: andnl {{[0-9]+}}(%esp), %ecx, %edx | |
| ; X86-BMI2-NEXT: retl | |
| ; | |
| ; X64-NOBMI-LABEL: bzhi64_b4_commutative: | |
| ; X64-NOBMI: # %bb.0: | |
| ; X64-NOBMI-NEXT: movq %rsi, %rcx | |
| ; X64-NOBMI-NEXT: movq $-1, %rax | |
| ; X64-NOBMI-NEXT: # kill: def $cl killed $cl killed $rcx | |
| ; X64-NOBMI-NEXT: shlq %cl, %rax | |
| ; X64-NOBMI-NEXT: notq %rax | |
| ; X64-NOBMI-NEXT: andq %rdi, %rax | |
| ; X64-NOBMI-NEXT: retq | |
| ; | |
| ; X64-BMI1-LABEL: bzhi64_b4_commutative: | |
| ; X64-BMI1: # %bb.0: | |
| ; X64-BMI1-NEXT: shll $8, %esi | |
| ; X64-BMI1-NEXT: bextrq %rsi, %rdi, %rax | |
| ; X64-BMI1-NEXT: retq | |
| ; | |
| ; X64-BMI2-LABEL: bzhi64_b4_commutative: | |
| ; X64-BMI2: # %bb.0: | |
| ; X64-BMI2-NEXT: bzhiq %rsi, %rdi, %rax | |
| ; X64-BMI2-NEXT: retq | |
| %notmask = shl i64 -1, %numlowbits | |
| %mask = xor i64 %notmask, -1 | |
| %masked = and i64 %val, %mask ; swapped order | |
| ret i64 %masked | |
| } | |
| ; 64-bit, but with 32-bit output | |
| ; Everything done in 64-bit, truncation happens last. | |
| define i32 @bzhi64_32_b0(i64 %val, i8 %numlowbits) nounwind { | |
| ; X86-NOBMI-LABEL: bzhi64_32_b0: | |
| ; X86-NOBMI: # %bb.0: | |
| ; X86-NOBMI-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-NOBMI-NEXT: movl $-1, %edx | |
| ; X86-NOBMI-NEXT: shll %cl, %edx | |
| ; X86-NOBMI-NEXT: xorl %eax, %eax | |
| ; X86-NOBMI-NEXT: testb $32, %cl | |
| ; X86-NOBMI-NEXT: jne .LBB26_2 | |
| ; X86-NOBMI-NEXT: # %bb.1: | |
| ; X86-NOBMI-NEXT: movl %edx, %eax | |
| ; X86-NOBMI-NEXT: .LBB26_2: | |
| ; X86-NOBMI-NEXT: notl %eax | |
| ; X86-NOBMI-NEXT: andl {{[0-9]+}}(%esp), %eax | |
| ; X86-NOBMI-NEXT: retl | |
| ; | |
| ; X86-BMI1-LABEL: bzhi64_32_b0: | |
| ; X86-BMI1: # %bb.0: | |
| ; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-BMI1-NEXT: movl $-1, %eax | |
| ; X86-BMI1-NEXT: shll %cl, %eax | |
| ; X86-BMI1-NEXT: xorl %edx, %edx | |
| ; X86-BMI1-NEXT: testb $32, %cl | |
| ; X86-BMI1-NEXT: jne .LBB26_2 | |
| ; X86-BMI1-NEXT: # %bb.1: | |
| ; X86-BMI1-NEXT: movl %eax, %edx | |
| ; X86-BMI1-NEXT: .LBB26_2: | |
| ; X86-BMI1-NEXT: andnl {{[0-9]+}}(%esp), %edx, %eax | |
| ; X86-BMI1-NEXT: retl | |
| ; | |
| ; X86-BMI2-LABEL: bzhi64_32_b0: | |
| ; X86-BMI2: # %bb.0: | |
| ; X86-BMI2-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-BMI2-NEXT: xorl %eax, %eax | |
| ; X86-BMI2-NEXT: testb $32, %cl | |
| ; X86-BMI2-NEXT: jne .LBB26_2 | |
| ; X86-BMI2-NEXT: # %bb.1: | |
| ; X86-BMI2-NEXT: movl $-1, %eax | |
| ; X86-BMI2-NEXT: shlxl %ecx, %eax, %eax | |
| ; X86-BMI2-NEXT: .LBB26_2: | |
| ; X86-BMI2-NEXT: andnl {{[0-9]+}}(%esp), %eax, %eax | |
| ; X86-BMI2-NEXT: retl | |
| ; | |
| ; X64-NOBMI-LABEL: bzhi64_32_b0: | |
| ; X64-NOBMI: # %bb.0: | |
| ; X64-NOBMI-NEXT: movl %esi, %ecx | |
| ; X64-NOBMI-NEXT: movq $-1, %rax | |
| ; X64-NOBMI-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X64-NOBMI-NEXT: shlq %cl, %rax | |
| ; X64-NOBMI-NEXT: notl %eax | |
| ; X64-NOBMI-NEXT: andl %edi, %eax | |
| ; X64-NOBMI-NEXT: # kill: def $eax killed $eax killed $rax | |
| ; X64-NOBMI-NEXT: retq | |
| ; | |
| ; X64-BMI1-LABEL: bzhi64_32_b0: | |
| ; X64-BMI1: # %bb.0: | |
| ; X64-BMI1-NEXT: shll $8, %esi | |
| ; X64-BMI1-NEXT: bextrl %esi, %edi, %eax | |
| ; X64-BMI1-NEXT: retq | |
| ; | |
| ; X64-BMI2-LABEL: bzhi64_32_b0: | |
| ; X64-BMI2: # %bb.0: | |
| ; X64-BMI2-NEXT: bzhil %esi, %edi, %eax | |
| ; X64-BMI2-NEXT: retq | |
| %widenumlowbits = zext i8 %numlowbits to i64 | |
| %notmask = shl nsw i64 -1, %widenumlowbits | |
| %mask = xor i64 %notmask, -1 | |
| %wideres = and i64 %val, %mask | |
| %res = trunc i64 %wideres to i32 | |
| ret i32 %res | |
| } | |
| ; Shifting happens in 64-bit, then truncation. Masking is 32-bit. | |
| define i32 @bzhi64_32_b1(i64 %val, i8 %numlowbits) nounwind { | |
| ; X86-NOBMI-LABEL: bzhi64_32_b1: | |
| ; X86-NOBMI: # %bb.0: | |
| ; X86-NOBMI-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-NOBMI-NEXT: movl $-1, %eax | |
| ; X86-NOBMI-NEXT: shll %cl, %eax | |
| ; X86-NOBMI-NEXT: notl %eax | |
| ; X86-NOBMI-NEXT: andl {{[0-9]+}}(%esp), %eax | |
| ; X86-NOBMI-NEXT: retl | |
| ; | |
| ; X86-BMI1-LABEL: bzhi64_32_b1: | |
| ; X86-BMI1: # %bb.0: | |
| ; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: shll $8, %eax | |
| ; X86-BMI1-NEXT: bextrl %eax, {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: retl | |
| ; | |
| ; X86-BMI2-LABEL: bzhi64_32_b1: | |
| ; X86-BMI2: # %bb.0: | |
| ; X86-BMI2-NEXT: movzbl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: bzhil %eax, {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: retl | |
| ; | |
| ; X64-NOBMI-LABEL: bzhi64_32_b1: | |
| ; X64-NOBMI: # %bb.0: | |
| ; X64-NOBMI-NEXT: movl %esi, %ecx | |
| ; X64-NOBMI-NEXT: movl $-1, %eax | |
| ; X64-NOBMI-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X64-NOBMI-NEXT: shll %cl, %eax | |
| ; X64-NOBMI-NEXT: notl %eax | |
| ; X64-NOBMI-NEXT: andl %edi, %eax | |
| ; X64-NOBMI-NEXT: retq | |
| ; | |
| ; X64-BMI1-LABEL: bzhi64_32_b1: | |
| ; X64-BMI1: # %bb.0: | |
| ; X64-BMI1-NEXT: shll $8, %esi | |
| ; X64-BMI1-NEXT: bextrl %esi, %edi, %eax | |
| ; X64-BMI1-NEXT: retq | |
| ; | |
| ; X64-BMI2-LABEL: bzhi64_32_b1: | |
| ; X64-BMI2: # %bb.0: | |
| ; X64-BMI2-NEXT: bzhil %esi, %edi, %eax | |
| ; X64-BMI2-NEXT: retq | |
| %truncval = trunc i64 %val to i32 | |
| %widenumlowbits = zext i8 %numlowbits to i32 | |
| %notmask = shl nsw i32 -1, %widenumlowbits | |
| %mask = xor i32 %notmask, -1 | |
| %res = and i32 %truncval, %mask | |
| ret i32 %res | |
| } | |
| ; Shifting happens in 64-bit. Mask is 32-bit, but extended to 64-bit. | |
| ; Masking is 64-bit. Then truncation. | |
| define i32 @bzhi64_32_b2(i64 %val, i8 %numlowbits) nounwind { | |
| ; X86-NOBMI-LABEL: bzhi64_32_b2: | |
| ; X86-NOBMI: # %bb.0: | |
| ; X86-NOBMI-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-NOBMI-NEXT: movl $-1, %eax | |
| ; X86-NOBMI-NEXT: shll %cl, %eax | |
| ; X86-NOBMI-NEXT: notl %eax | |
| ; X86-NOBMI-NEXT: andl {{[0-9]+}}(%esp), %eax | |
| ; X86-NOBMI-NEXT: retl | |
| ; | |
| ; X86-BMI1-LABEL: bzhi64_32_b2: | |
| ; X86-BMI1: # %bb.0: | |
| ; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: shll $8, %eax | |
| ; X86-BMI1-NEXT: bextrl %eax, {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: retl | |
| ; | |
| ; X86-BMI2-LABEL: bzhi64_32_b2: | |
| ; X86-BMI2: # %bb.0: | |
| ; X86-BMI2-NEXT: movzbl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: bzhil %eax, {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: retl | |
| ; | |
| ; X64-NOBMI-LABEL: bzhi64_32_b2: | |
| ; X64-NOBMI: # %bb.0: | |
| ; X64-NOBMI-NEXT: movl %esi, %ecx | |
| ; X64-NOBMI-NEXT: movl $-1, %eax | |
| ; X64-NOBMI-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X64-NOBMI-NEXT: shll %cl, %eax | |
| ; X64-NOBMI-NEXT: notl %eax | |
| ; X64-NOBMI-NEXT: andl %edi, %eax | |
| ; X64-NOBMI-NEXT: retq | |
| ; | |
| ; X64-BMI1-LABEL: bzhi64_32_b2: | |
| ; X64-BMI1: # %bb.0: | |
| ; X64-BMI1-NEXT: shll $8, %esi | |
| ; X64-BMI1-NEXT: bextrl %esi, %edi, %eax | |
| ; X64-BMI1-NEXT: retq | |
| ; | |
| ; X64-BMI2-LABEL: bzhi64_32_b2: | |
| ; X64-BMI2: # %bb.0: | |
| ; X64-BMI2-NEXT: bzhil %esi, %edi, %eax | |
| ; X64-BMI2-NEXT: retq | |
| %widenumlowbits = zext i8 %numlowbits to i32 | |
| %notmask = shl nsw i32 -1, %widenumlowbits | |
| %mask = xor i32 %notmask, -1 | |
| %zextmask = zext i32 %mask to i64 | |
| %wideres = and i64 %val, %zextmask | |
| %res = trunc i64 %wideres to i32 | |
| ret i32 %res | |
| } | |
| ; Shifting happens in 64-bit. Mask is 32-bit, but calculated in 64-bit. | |
| ; Masking is 64-bit. Then truncation. | |
| define i32 @bzhi64_32_b3(i64 %val, i8 %numlowbits) nounwind { | |
| ; X86-NOBMI-LABEL: bzhi64_32_b3: | |
| ; X86-NOBMI: # %bb.0: | |
| ; X86-NOBMI-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-NOBMI-NEXT: movl $-1, %edx | |
| ; X86-NOBMI-NEXT: shll %cl, %edx | |
| ; X86-NOBMI-NEXT: xorl %eax, %eax | |
| ; X86-NOBMI-NEXT: testb $32, %cl | |
| ; X86-NOBMI-NEXT: jne .LBB29_2 | |
| ; X86-NOBMI-NEXT: # %bb.1: | |
| ; X86-NOBMI-NEXT: movl %edx, %eax | |
| ; X86-NOBMI-NEXT: .LBB29_2: | |
| ; X86-NOBMI-NEXT: notl %eax | |
| ; X86-NOBMI-NEXT: andl {{[0-9]+}}(%esp), %eax | |
| ; X86-NOBMI-NEXT: retl | |
| ; | |
| ; X86-BMI1-LABEL: bzhi64_32_b3: | |
| ; X86-BMI1: # %bb.0: | |
| ; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-BMI1-NEXT: movl $-1, %eax | |
| ; X86-BMI1-NEXT: shll %cl, %eax | |
| ; X86-BMI1-NEXT: xorl %edx, %edx | |
| ; X86-BMI1-NEXT: testb $32, %cl | |
| ; X86-BMI1-NEXT: jne .LBB29_2 | |
| ; X86-BMI1-NEXT: # %bb.1: | |
| ; X86-BMI1-NEXT: movl %eax, %edx | |
| ; X86-BMI1-NEXT: .LBB29_2: | |
| ; X86-BMI1-NEXT: andnl {{[0-9]+}}(%esp), %edx, %eax | |
| ; X86-BMI1-NEXT: retl | |
| ; | |
| ; X86-BMI2-LABEL: bzhi64_32_b3: | |
| ; X86-BMI2: # %bb.0: | |
| ; X86-BMI2-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-BMI2-NEXT: xorl %eax, %eax | |
| ; X86-BMI2-NEXT: testb $32, %cl | |
| ; X86-BMI2-NEXT: jne .LBB29_2 | |
| ; X86-BMI2-NEXT: # %bb.1: | |
| ; X86-BMI2-NEXT: movl $-1, %eax | |
| ; X86-BMI2-NEXT: shlxl %ecx, %eax, %eax | |
| ; X86-BMI2-NEXT: .LBB29_2: | |
| ; X86-BMI2-NEXT: andnl {{[0-9]+}}(%esp), %eax, %eax | |
| ; X86-BMI2-NEXT: retl | |
| ; | |
| ; X64-NOBMI-LABEL: bzhi64_32_b3: | |
| ; X64-NOBMI: # %bb.0: | |
| ; X64-NOBMI-NEXT: movl %esi, %ecx | |
| ; X64-NOBMI-NEXT: movl $4294967295, %eax # imm = 0xFFFFFFFF | |
| ; X64-NOBMI-NEXT: movl $4294967295, %edx # imm = 0xFFFFFFFF | |
| ; X64-NOBMI-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X64-NOBMI-NEXT: shlq %cl, %rdx | |
| ; X64-NOBMI-NEXT: xorl %edx, %eax | |
| ; X64-NOBMI-NEXT: andl %edi, %eax | |
| ; X64-NOBMI-NEXT: # kill: def $eax killed $eax killed $rax | |
| ; X64-NOBMI-NEXT: retq | |
| ; | |
| ; X64-BMI1-LABEL: bzhi64_32_b3: | |
| ; X64-BMI1: # %bb.0: | |
| ; X64-BMI1-NEXT: shll $8, %esi | |
| ; X64-BMI1-NEXT: bextrl %esi, %edi, %eax | |
| ; X64-BMI1-NEXT: retq | |
| ; | |
| ; X64-BMI2-LABEL: bzhi64_32_b3: | |
| ; X64-BMI2: # %bb.0: | |
| ; X64-BMI2-NEXT: bzhil %esi, %edi, %eax | |
| ; X64-BMI2-NEXT: retq | |
| %widenumlowbits = zext i8 %numlowbits to i64 | |
| %notmask = shl nsw i64 4294967295, %widenumlowbits | |
| %mask = xor i64 %notmask, 4294967295 | |
| %wideres = and i64 %val, %mask | |
| %res = trunc i64 %wideres to i32 | |
| ret i32 %res | |
| } | |
| ; ---------------------------------------------------------------------------- ; | |
| ; Pattern c. 32-bit | |
| ; ---------------------------------------------------------------------------- ; | |
| define i32 @bzhi32_c0(i32 %val, i32 %numlowbits, ptr %escape) nounwind { | |
| ; X86-NOBMI-LABEL: bzhi32_c0: | |
| ; X86-NOBMI: # %bb.0: | |
| ; X86-NOBMI-NEXT: movl {{[0-9]+}}(%esp), %edx | |
| ; X86-NOBMI-NEXT: xorl %ecx, %ecx | |
| ; X86-NOBMI-NEXT: subb {{[0-9]+}}(%esp), %cl | |
| ; X86-NOBMI-NEXT: movl $-1, %eax | |
| ; X86-NOBMI-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X86-NOBMI-NEXT: shrl %cl, %eax | |
| ; X86-NOBMI-NEXT: movl %eax, (%edx) | |
| ; X86-NOBMI-NEXT: andl {{[0-9]+}}(%esp), %eax | |
| ; X86-NOBMI-NEXT: retl | |
| ; | |
| ; X86-BMI1-LABEL: bzhi32_c0: | |
| ; X86-BMI1: # %bb.0: | |
| ; X86-BMI1-NEXT: movl {{[0-9]+}}(%esp), %edx | |
| ; X86-BMI1-NEXT: xorl %ecx, %ecx | |
| ; X86-BMI1-NEXT: subb {{[0-9]+}}(%esp), %cl | |
| ; X86-BMI1-NEXT: movl $-1, %eax | |
| ; X86-BMI1-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X86-BMI1-NEXT: shrl %cl, %eax | |
| ; X86-BMI1-NEXT: movl %eax, (%edx) | |
| ; X86-BMI1-NEXT: andl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: retl | |
| ; | |
| ; X86-BMI2-LABEL: bzhi32_c0: | |
| ; X86-BMI2: # %bb.0: | |
| ; X86-BMI2-NEXT: movl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-BMI2-NEXT: movl $-1, %edx | |
| ; X86-BMI2-NEXT: bzhil %ecx, %edx, %edx | |
| ; X86-BMI2-NEXT: movl %edx, (%eax) | |
| ; X86-BMI2-NEXT: bzhil %ecx, {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: retl | |
| ; | |
| ; X64-NOBMI-LABEL: bzhi32_c0: | |
| ; X64-NOBMI: # %bb.0: | |
| ; X64-NOBMI-NEXT: movl %esi, %ecx | |
| ; X64-NOBMI-NEXT: negb %cl | |
| ; X64-NOBMI-NEXT: movl $-1, %eax | |
| ; X64-NOBMI-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X64-NOBMI-NEXT: shrl %cl, %eax | |
| ; X64-NOBMI-NEXT: movl %eax, (%rdx) | |
| ; X64-NOBMI-NEXT: andl %edi, %eax | |
| ; X64-NOBMI-NEXT: retq | |
| ; | |
| ; X64-BMI1-LABEL: bzhi32_c0: | |
| ; X64-BMI1: # %bb.0: | |
| ; X64-BMI1-NEXT: movl %esi, %ecx | |
| ; X64-BMI1-NEXT: negb %cl | |
| ; X64-BMI1-NEXT: movl $-1, %eax | |
| ; X64-BMI1-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X64-BMI1-NEXT: shrl %cl, %eax | |
| ; X64-BMI1-NEXT: movl %eax, (%rdx) | |
| ; X64-BMI1-NEXT: andl %edi, %eax | |
| ; X64-BMI1-NEXT: retq | |
| ; | |
| ; X64-BMI2-LABEL: bzhi32_c0: | |
| ; X64-BMI2: # %bb.0: | |
| ; X64-BMI2-NEXT: movl $-1, %eax | |
| ; X64-BMI2-NEXT: bzhil %esi, %eax, %eax | |
| ; X64-BMI2-NEXT: movl %eax, (%rdx) | |
| ; X64-BMI2-NEXT: bzhil %esi, %edi, %eax | |
| ; X64-BMI2-NEXT: retq | |
| %numhighbits = sub i32 32, %numlowbits | |
| %mask = lshr i32 -1, %numhighbits | |
| store i32 %mask, ptr %escape | |
| %masked = and i32 %mask, %val | |
| ret i32 %masked | |
| } | |
| define i32 @bzhi32_c1_indexzext(i32 %val, i8 %numlowbits, ptr %escape) nounwind { | |
| ; X86-NOBMI-LABEL: bzhi32_c1_indexzext: | |
| ; X86-NOBMI: # %bb.0: | |
| ; X86-NOBMI-NEXT: movl {{[0-9]+}}(%esp), %edx | |
| ; X86-NOBMI-NEXT: xorl %ecx, %ecx | |
| ; X86-NOBMI-NEXT: subb {{[0-9]+}}(%esp), %cl | |
| ; X86-NOBMI-NEXT: movl $-1, %eax | |
| ; X86-NOBMI-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X86-NOBMI-NEXT: shrl %cl, %eax | |
| ; X86-NOBMI-NEXT: movl %eax, (%edx) | |
| ; X86-NOBMI-NEXT: andl {{[0-9]+}}(%esp), %eax | |
| ; X86-NOBMI-NEXT: retl | |
| ; | |
| ; X86-BMI1-LABEL: bzhi32_c1_indexzext: | |
| ; X86-BMI1: # %bb.0: | |
| ; X86-BMI1-NEXT: movl {{[0-9]+}}(%esp), %edx | |
| ; X86-BMI1-NEXT: xorl %ecx, %ecx | |
| ; X86-BMI1-NEXT: subb {{[0-9]+}}(%esp), %cl | |
| ; X86-BMI1-NEXT: movl $-1, %eax | |
| ; X86-BMI1-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X86-BMI1-NEXT: shrl %cl, %eax | |
| ; X86-BMI1-NEXT: movl %eax, (%edx) | |
| ; X86-BMI1-NEXT: andl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: retl | |
| ; | |
| ; X86-BMI2-LABEL: bzhi32_c1_indexzext: | |
| ; X86-BMI2: # %bb.0: | |
| ; X86-BMI2-NEXT: movl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-BMI2-NEXT: movl $-1, %edx | |
| ; X86-BMI2-NEXT: bzhil %ecx, %edx, %edx | |
| ; X86-BMI2-NEXT: movl %edx, (%eax) | |
| ; X86-BMI2-NEXT: bzhil %ecx, {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: retl | |
| ; | |
| ; X64-NOBMI-LABEL: bzhi32_c1_indexzext: | |
| ; X64-NOBMI: # %bb.0: | |
| ; X64-NOBMI-NEXT: movl %esi, %ecx | |
| ; X64-NOBMI-NEXT: negb %cl | |
| ; X64-NOBMI-NEXT: movl $-1, %eax | |
| ; X64-NOBMI-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X64-NOBMI-NEXT: shrl %cl, %eax | |
| ; X64-NOBMI-NEXT: movl %eax, (%rdx) | |
| ; X64-NOBMI-NEXT: andl %edi, %eax | |
| ; X64-NOBMI-NEXT: retq | |
| ; | |
| ; X64-BMI1-LABEL: bzhi32_c1_indexzext: | |
| ; X64-BMI1: # %bb.0: | |
| ; X64-BMI1-NEXT: movl %esi, %ecx | |
| ; X64-BMI1-NEXT: negb %cl | |
| ; X64-BMI1-NEXT: movl $-1, %eax | |
| ; X64-BMI1-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X64-BMI1-NEXT: shrl %cl, %eax | |
| ; X64-BMI1-NEXT: movl %eax, (%rdx) | |
| ; X64-BMI1-NEXT: andl %edi, %eax | |
| ; X64-BMI1-NEXT: retq | |
| ; | |
| ; X64-BMI2-LABEL: bzhi32_c1_indexzext: | |
| ; X64-BMI2: # %bb.0: | |
| ; X64-BMI2-NEXT: movl $-1, %eax | |
| ; X64-BMI2-NEXT: bzhil %esi, %eax, %eax | |
| ; X64-BMI2-NEXT: movl %eax, (%rdx) | |
| ; X64-BMI2-NEXT: bzhil %esi, %edi, %eax | |
| ; X64-BMI2-NEXT: retq | |
| %numhighbits = sub i8 32, %numlowbits | |
| %sh_prom = zext i8 %numhighbits to i32 | |
| %mask = lshr i32 -1, %sh_prom | |
| store i32 %mask, ptr %escape | |
| %masked = and i32 %mask, %val | |
| ret i32 %masked | |
| } | |
| define i32 @bzhi32_c2_load(ptr %w, i32 %numlowbits, ptr %escape) nounwind { | |
| ; X86-NOBMI-LABEL: bzhi32_c2_load: | |
| ; X86-NOBMI: # %bb.0: | |
| ; X86-NOBMI-NEXT: pushl %esi | |
| ; X86-NOBMI-NEXT: movl {{[0-9]+}}(%esp), %edx | |
| ; X86-NOBMI-NEXT: movl {{[0-9]+}}(%esp), %eax | |
| ; X86-NOBMI-NEXT: xorl %ecx, %ecx | |
| ; X86-NOBMI-NEXT: subb {{[0-9]+}}(%esp), %cl | |
| ; X86-NOBMI-NEXT: movl $-1, %esi | |
| ; X86-NOBMI-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X86-NOBMI-NEXT: shrl %cl, %esi | |
| ; X86-NOBMI-NEXT: movl (%eax), %eax | |
| ; X86-NOBMI-NEXT: andl %esi, %eax | |
| ; X86-NOBMI-NEXT: movl %esi, (%edx) | |
| ; X86-NOBMI-NEXT: popl %esi | |
| ; X86-NOBMI-NEXT: retl | |
| ; | |
| ; X86-BMI1-LABEL: bzhi32_c2_load: | |
| ; X86-BMI1: # %bb.0: | |
| ; X86-BMI1-NEXT: pushl %esi | |
| ; X86-BMI1-NEXT: movl {{[0-9]+}}(%esp), %edx | |
| ; X86-BMI1-NEXT: movl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: xorl %ecx, %ecx | |
| ; X86-BMI1-NEXT: subb {{[0-9]+}}(%esp), %cl | |
| ; X86-BMI1-NEXT: movl $-1, %esi | |
| ; X86-BMI1-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X86-BMI1-NEXT: shrl %cl, %esi | |
| ; X86-BMI1-NEXT: movl (%eax), %eax | |
| ; X86-BMI1-NEXT: andl %esi, %eax | |
| ; X86-BMI1-NEXT: movl %esi, (%edx) | |
| ; X86-BMI1-NEXT: popl %esi | |
| ; X86-BMI1-NEXT: retl | |
| ; | |
| ; X86-BMI2-LABEL: bzhi32_c2_load: | |
| ; X86-BMI2: # %bb.0: | |
| ; X86-BMI2-NEXT: pushl %esi | |
| ; X86-BMI2-NEXT: movl {{[0-9]+}}(%esp), %ecx | |
| ; X86-BMI2-NEXT: movl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: movzbl {{[0-9]+}}(%esp), %edx | |
| ; X86-BMI2-NEXT: movl $-1, %esi | |
| ; X86-BMI2-NEXT: bzhil %edx, %esi, %esi | |
| ; X86-BMI2-NEXT: bzhil %edx, (%eax), %eax | |
| ; X86-BMI2-NEXT: movl %esi, (%ecx) | |
| ; X86-BMI2-NEXT: popl %esi | |
| ; X86-BMI2-NEXT: retl | |
| ; | |
| ; X64-NOBMI-LABEL: bzhi32_c2_load: | |
| ; X64-NOBMI: # %bb.0: | |
| ; X64-NOBMI-NEXT: movl %esi, %ecx | |
| ; X64-NOBMI-NEXT: negb %cl | |
| ; X64-NOBMI-NEXT: movl $-1, %esi | |
| ; X64-NOBMI-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X64-NOBMI-NEXT: shrl %cl, %esi | |
| ; X64-NOBMI-NEXT: movl (%rdi), %eax | |
| ; X64-NOBMI-NEXT: andl %esi, %eax | |
| ; X64-NOBMI-NEXT: movl %esi, (%rdx) | |
| ; X64-NOBMI-NEXT: retq | |
| ; | |
| ; X64-BMI1-LABEL: bzhi32_c2_load: | |
| ; X64-BMI1: # %bb.0: | |
| ; X64-BMI1-NEXT: movl %esi, %ecx | |
| ; X64-BMI1-NEXT: negb %cl | |
| ; X64-BMI1-NEXT: movl $-1, %esi | |
| ; X64-BMI1-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X64-BMI1-NEXT: shrl %cl, %esi | |
| ; X64-BMI1-NEXT: movl (%rdi), %eax | |
| ; X64-BMI1-NEXT: andl %esi, %eax | |
| ; X64-BMI1-NEXT: movl %esi, (%rdx) | |
| ; X64-BMI1-NEXT: retq | |
| ; | |
| ; X64-BMI2-LABEL: bzhi32_c2_load: | |
| ; X64-BMI2: # %bb.0: | |
| ; X64-BMI2-NEXT: movl $-1, %eax | |
| ; X64-BMI2-NEXT: bzhil %esi, %eax, %ecx | |
| ; X64-BMI2-NEXT: bzhil %esi, (%rdi), %eax | |
| ; X64-BMI2-NEXT: movl %ecx, (%rdx) | |
| ; X64-BMI2-NEXT: retq | |
| %val = load i32, ptr %w | |
| %numhighbits = sub i32 32, %numlowbits | |
| %mask = lshr i32 -1, %numhighbits | |
| store i32 %mask, ptr %escape | |
| %masked = and i32 %mask, %val | |
| ret i32 %masked | |
| } | |
| define i32 @bzhi32_c3_load_indexzext(ptr %w, i8 %numlowbits, ptr %escape) nounwind { | |
| ; X86-NOBMI-LABEL: bzhi32_c3_load_indexzext: | |
| ; X86-NOBMI: # %bb.0: | |
| ; X86-NOBMI-NEXT: pushl %esi | |
| ; X86-NOBMI-NEXT: movl {{[0-9]+}}(%esp), %edx | |
| ; X86-NOBMI-NEXT: movl {{[0-9]+}}(%esp), %eax | |
| ; X86-NOBMI-NEXT: xorl %ecx, %ecx | |
| ; X86-NOBMI-NEXT: subb {{[0-9]+}}(%esp), %cl | |
| ; X86-NOBMI-NEXT: movl $-1, %esi | |
| ; X86-NOBMI-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X86-NOBMI-NEXT: shrl %cl, %esi | |
| ; X86-NOBMI-NEXT: movl (%eax), %eax | |
| ; X86-NOBMI-NEXT: andl %esi, %eax | |
| ; X86-NOBMI-NEXT: movl %esi, (%edx) | |
| ; X86-NOBMI-NEXT: popl %esi | |
| ; X86-NOBMI-NEXT: retl | |
| ; | |
| ; X86-BMI1-LABEL: bzhi32_c3_load_indexzext: | |
| ; X86-BMI1: # %bb.0: | |
| ; X86-BMI1-NEXT: pushl %esi | |
| ; X86-BMI1-NEXT: movl {{[0-9]+}}(%esp), %edx | |
| ; X86-BMI1-NEXT: movl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: xorl %ecx, %ecx | |
| ; X86-BMI1-NEXT: subb {{[0-9]+}}(%esp), %cl | |
| ; X86-BMI1-NEXT: movl $-1, %esi | |
| ; X86-BMI1-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X86-BMI1-NEXT: shrl %cl, %esi | |
| ; X86-BMI1-NEXT: movl (%eax), %eax | |
| ; X86-BMI1-NEXT: andl %esi, %eax | |
| ; X86-BMI1-NEXT: movl %esi, (%edx) | |
| ; X86-BMI1-NEXT: popl %esi | |
| ; X86-BMI1-NEXT: retl | |
| ; | |
| ; X86-BMI2-LABEL: bzhi32_c3_load_indexzext: | |
| ; X86-BMI2: # %bb.0: | |
| ; X86-BMI2-NEXT: pushl %esi | |
| ; X86-BMI2-NEXT: movl {{[0-9]+}}(%esp), %ecx | |
| ; X86-BMI2-NEXT: movl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: movzbl {{[0-9]+}}(%esp), %edx | |
| ; X86-BMI2-NEXT: movl $-1, %esi | |
| ; X86-BMI2-NEXT: bzhil %edx, %esi, %esi | |
| ; X86-BMI2-NEXT: bzhil %edx, (%eax), %eax | |
| ; X86-BMI2-NEXT: movl %esi, (%ecx) | |
| ; X86-BMI2-NEXT: popl %esi | |
| ; X86-BMI2-NEXT: retl | |
| ; | |
| ; X64-NOBMI-LABEL: bzhi32_c3_load_indexzext: | |
| ; X64-NOBMI: # %bb.0: | |
| ; X64-NOBMI-NEXT: movl %esi, %ecx | |
| ; X64-NOBMI-NEXT: negb %cl | |
| ; X64-NOBMI-NEXT: movl $-1, %esi | |
| ; X64-NOBMI-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X64-NOBMI-NEXT: shrl %cl, %esi | |
| ; X64-NOBMI-NEXT: movl (%rdi), %eax | |
| ; X64-NOBMI-NEXT: andl %esi, %eax | |
| ; X64-NOBMI-NEXT: movl %esi, (%rdx) | |
| ; X64-NOBMI-NEXT: retq | |
| ; | |
| ; X64-BMI1-LABEL: bzhi32_c3_load_indexzext: | |
| ; X64-BMI1: # %bb.0: | |
| ; X64-BMI1-NEXT: movl %esi, %ecx | |
| ; X64-BMI1-NEXT: negb %cl | |
| ; X64-BMI1-NEXT: movl $-1, %esi | |
| ; X64-BMI1-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X64-BMI1-NEXT: shrl %cl, %esi | |
| ; X64-BMI1-NEXT: movl (%rdi), %eax | |
| ; X64-BMI1-NEXT: andl %esi, %eax | |
| ; X64-BMI1-NEXT: movl %esi, (%rdx) | |
| ; X64-BMI1-NEXT: retq | |
| ; | |
| ; X64-BMI2-LABEL: bzhi32_c3_load_indexzext: | |
| ; X64-BMI2: # %bb.0: | |
| ; X64-BMI2-NEXT: movl $-1, %eax | |
| ; X64-BMI2-NEXT: bzhil %esi, %eax, %ecx | |
| ; X64-BMI2-NEXT: bzhil %esi, (%rdi), %eax | |
| ; X64-BMI2-NEXT: movl %ecx, (%rdx) | |
| ; X64-BMI2-NEXT: retq | |
| %val = load i32, ptr %w | |
| %numhighbits = sub i8 32, %numlowbits | |
| %sh_prom = zext i8 %numhighbits to i32 | |
| %mask = lshr i32 -1, %sh_prom | |
| store i32 %mask, ptr %escape | |
| %masked = and i32 %mask, %val | |
| ret i32 %masked | |
| } | |
| define i32 @bzhi32_c4_commutative(i32 %val, i32 %numlowbits, ptr %escape) nounwind { | |
| ; X86-NOBMI-LABEL: bzhi32_c4_commutative: | |
| ; X86-NOBMI: # %bb.0: | |
| ; X86-NOBMI-NEXT: movl {{[0-9]+}}(%esp), %edx | |
| ; X86-NOBMI-NEXT: xorl %ecx, %ecx | |
| ; X86-NOBMI-NEXT: subb {{[0-9]+}}(%esp), %cl | |
| ; X86-NOBMI-NEXT: movl $-1, %eax | |
| ; X86-NOBMI-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X86-NOBMI-NEXT: shrl %cl, %eax | |
| ; X86-NOBMI-NEXT: movl %eax, (%edx) | |
| ; X86-NOBMI-NEXT: andl {{[0-9]+}}(%esp), %eax | |
| ; X86-NOBMI-NEXT: retl | |
| ; | |
| ; X86-BMI1-LABEL: bzhi32_c4_commutative: | |
| ; X86-BMI1: # %bb.0: | |
| ; X86-BMI1-NEXT: movl {{[0-9]+}}(%esp), %edx | |
| ; X86-BMI1-NEXT: xorl %ecx, %ecx | |
| ; X86-BMI1-NEXT: subb {{[0-9]+}}(%esp), %cl | |
| ; X86-BMI1-NEXT: movl $-1, %eax | |
| ; X86-BMI1-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X86-BMI1-NEXT: shrl %cl, %eax | |
| ; X86-BMI1-NEXT: movl %eax, (%edx) | |
| ; X86-BMI1-NEXT: andl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: retl | |
| ; | |
| ; X86-BMI2-LABEL: bzhi32_c4_commutative: | |
| ; X86-BMI2: # %bb.0: | |
| ; X86-BMI2-NEXT: movl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-BMI2-NEXT: movl $-1, %edx | |
| ; X86-BMI2-NEXT: bzhil %ecx, %edx, %edx | |
| ; X86-BMI2-NEXT: movl %edx, (%eax) | |
| ; X86-BMI2-NEXT: bzhil %ecx, {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: retl | |
| ; | |
| ; X64-NOBMI-LABEL: bzhi32_c4_commutative: | |
| ; X64-NOBMI: # %bb.0: | |
| ; X64-NOBMI-NEXT: movl %esi, %ecx | |
| ; X64-NOBMI-NEXT: negb %cl | |
| ; X64-NOBMI-NEXT: movl $-1, %eax | |
| ; X64-NOBMI-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X64-NOBMI-NEXT: shrl %cl, %eax | |
| ; X64-NOBMI-NEXT: movl %eax, (%rdx) | |
| ; X64-NOBMI-NEXT: andl %edi, %eax | |
| ; X64-NOBMI-NEXT: retq | |
| ; | |
| ; X64-BMI1-LABEL: bzhi32_c4_commutative: | |
| ; X64-BMI1: # %bb.0: | |
| ; X64-BMI1-NEXT: movl %esi, %ecx | |
| ; X64-BMI1-NEXT: negb %cl | |
| ; X64-BMI1-NEXT: movl $-1, %eax | |
| ; X64-BMI1-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X64-BMI1-NEXT: shrl %cl, %eax | |
| ; X64-BMI1-NEXT: movl %eax, (%rdx) | |
| ; X64-BMI1-NEXT: andl %edi, %eax | |
| ; X64-BMI1-NEXT: retq | |
| ; | |
| ; X64-BMI2-LABEL: bzhi32_c4_commutative: | |
| ; X64-BMI2: # %bb.0: | |
| ; X64-BMI2-NEXT: movl $-1, %eax | |
| ; X64-BMI2-NEXT: bzhil %esi, %eax, %eax | |
| ; X64-BMI2-NEXT: movl %eax, (%rdx) | |
| ; X64-BMI2-NEXT: bzhil %esi, %edi, %eax | |
| ; X64-BMI2-NEXT: retq | |
| %numhighbits = sub i32 32, %numlowbits | |
| %mask = lshr i32 -1, %numhighbits | |
| store i32 %mask, ptr %escape | |
| %masked = and i32 %val, %mask ; swapped order | |
| ret i32 %masked | |
| } | |
| ; 64-bit | |
| define i64 @bzhi64_c0(i64 %val, i64 %numlowbits, ptr %escape) nounwind { | |
| ; X86-NOBMI-LABEL: bzhi64_c0: | |
| ; X86-NOBMI: # %bb.0: | |
| ; X86-NOBMI-NEXT: pushl %esi | |
| ; X86-NOBMI-NEXT: movl {{[0-9]+}}(%esp), %esi | |
| ; X86-NOBMI-NEXT: movb $64, %cl | |
| ; X86-NOBMI-NEXT: subb {{[0-9]+}}(%esp), %cl | |
| ; X86-NOBMI-NEXT: movl $-1, %eax | |
| ; X86-NOBMI-NEXT: movl $-1, %edx | |
| ; X86-NOBMI-NEXT: shrl %cl, %edx | |
| ; X86-NOBMI-NEXT: testb $32, %cl | |
| ; X86-NOBMI-NEXT: je .LBB35_2 | |
| ; X86-NOBMI-NEXT: # %bb.1: | |
| ; X86-NOBMI-NEXT: movl %edx, %eax | |
| ; X86-NOBMI-NEXT: xorl %edx, %edx | |
| ; X86-NOBMI-NEXT: .LBB35_2: | |
| ; X86-NOBMI-NEXT: movl %edx, 4(%esi) | |
| ; X86-NOBMI-NEXT: movl %eax, (%esi) | |
| ; X86-NOBMI-NEXT: andl {{[0-9]+}}(%esp), %eax | |
| ; X86-NOBMI-NEXT: andl {{[0-9]+}}(%esp), %edx | |
| ; X86-NOBMI-NEXT: popl %esi | |
| ; X86-NOBMI-NEXT: retl | |
| ; | |
| ; X86-BMI1-LABEL: bzhi64_c0: | |
| ; X86-BMI1: # %bb.0: | |
| ; X86-BMI1-NEXT: pushl %esi | |
| ; X86-BMI1-NEXT: movl {{[0-9]+}}(%esp), %esi | |
| ; X86-BMI1-NEXT: movb $64, %cl | |
| ; X86-BMI1-NEXT: subb {{[0-9]+}}(%esp), %cl | |
| ; X86-BMI1-NEXT: movl $-1, %eax | |
| ; X86-BMI1-NEXT: movl $-1, %edx | |
| ; X86-BMI1-NEXT: shrl %cl, %edx | |
| ; X86-BMI1-NEXT: testb $32, %cl | |
| ; X86-BMI1-NEXT: je .LBB35_2 | |
| ; X86-BMI1-NEXT: # %bb.1: | |
| ; X86-BMI1-NEXT: movl %edx, %eax | |
| ; X86-BMI1-NEXT: xorl %edx, %edx | |
| ; X86-BMI1-NEXT: .LBB35_2: | |
| ; X86-BMI1-NEXT: movl %edx, 4(%esi) | |
| ; X86-BMI1-NEXT: movl %eax, (%esi) | |
| ; X86-BMI1-NEXT: andl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: andl {{[0-9]+}}(%esp), %edx | |
| ; X86-BMI1-NEXT: popl %esi | |
| ; X86-BMI1-NEXT: retl | |
| ; | |
| ; X86-BMI2-LABEL: bzhi64_c0: | |
| ; X86-BMI2: # %bb.0: | |
| ; X86-BMI2-NEXT: pushl %ebx | |
| ; X86-BMI2-NEXT: movl {{[0-9]+}}(%esp), %ecx | |
| ; X86-BMI2-NEXT: movb $64, %bl | |
| ; X86-BMI2-NEXT: subb {{[0-9]+}}(%esp), %bl | |
| ; X86-BMI2-NEXT: movl $-1, %eax | |
| ; X86-BMI2-NEXT: shrxl %ebx, %eax, %edx | |
| ; X86-BMI2-NEXT: testb $32, %bl | |
| ; X86-BMI2-NEXT: je .LBB35_2 | |
| ; X86-BMI2-NEXT: # %bb.1: | |
| ; X86-BMI2-NEXT: movl %edx, %eax | |
| ; X86-BMI2-NEXT: xorl %edx, %edx | |
| ; X86-BMI2-NEXT: .LBB35_2: | |
| ; X86-BMI2-NEXT: movl %edx, 4(%ecx) | |
| ; X86-BMI2-NEXT: movl %eax, (%ecx) | |
| ; X86-BMI2-NEXT: andl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: andl {{[0-9]+}}(%esp), %edx | |
| ; X86-BMI2-NEXT: popl %ebx | |
| ; X86-BMI2-NEXT: retl | |
| ; | |
| ; X64-NOBMI-LABEL: bzhi64_c0: | |
| ; X64-NOBMI: # %bb.0: | |
| ; X64-NOBMI-NEXT: movq %rsi, %rcx | |
| ; X64-NOBMI-NEXT: negb %cl | |
| ; X64-NOBMI-NEXT: movq $-1, %rax | |
| ; X64-NOBMI-NEXT: # kill: def $cl killed $cl killed $rcx | |
| ; X64-NOBMI-NEXT: shrq %cl, %rax | |
| ; X64-NOBMI-NEXT: movq %rax, (%rdx) | |
| ; X64-NOBMI-NEXT: andq %rdi, %rax | |
| ; X64-NOBMI-NEXT: retq | |
| ; | |
| ; X64-BMI1-LABEL: bzhi64_c0: | |
| ; X64-BMI1: # %bb.0: | |
| ; X64-BMI1-NEXT: movq %rsi, %rcx | |
| ; X64-BMI1-NEXT: negb %cl | |
| ; X64-BMI1-NEXT: movq $-1, %rax | |
| ; X64-BMI1-NEXT: # kill: def $cl killed $cl killed $rcx | |
| ; X64-BMI1-NEXT: shrq %cl, %rax | |
| ; X64-BMI1-NEXT: movq %rax, (%rdx) | |
| ; X64-BMI1-NEXT: andq %rdi, %rax | |
| ; X64-BMI1-NEXT: retq | |
| ; | |
| ; X64-BMI2-LABEL: bzhi64_c0: | |
| ; X64-BMI2: # %bb.0: | |
| ; X64-BMI2-NEXT: movq $-1, %rax | |
| ; X64-BMI2-NEXT: bzhiq %rsi, %rax, %rax | |
| ; X64-BMI2-NEXT: movq %rax, (%rdx) | |
| ; X64-BMI2-NEXT: bzhiq %rsi, %rdi, %rax | |
| ; X64-BMI2-NEXT: retq | |
| %numhighbits = sub i64 64, %numlowbits | |
| %mask = lshr i64 -1, %numhighbits | |
| store i64 %mask, ptr %escape | |
| %masked = and i64 %mask, %val | |
| ret i64 %masked | |
| } | |
| define i64 @bzhi64_c1_indexzext(i64 %val, i8 %numlowbits, ptr %escape) nounwind { | |
| ; X86-NOBMI-LABEL: bzhi64_c1_indexzext: | |
| ; X86-NOBMI: # %bb.0: | |
| ; X86-NOBMI-NEXT: pushl %esi | |
| ; X86-NOBMI-NEXT: movl {{[0-9]+}}(%esp), %esi | |
| ; X86-NOBMI-NEXT: movb $64, %cl | |
| ; X86-NOBMI-NEXT: subb {{[0-9]+}}(%esp), %cl | |
| ; X86-NOBMI-NEXT: movl $-1, %eax | |
| ; X86-NOBMI-NEXT: movl $-1, %edx | |
| ; X86-NOBMI-NEXT: shrl %cl, %edx | |
| ; X86-NOBMI-NEXT: testb $32, %cl | |
| ; X86-NOBMI-NEXT: je .LBB36_2 | |
| ; X86-NOBMI-NEXT: # %bb.1: | |
| ; X86-NOBMI-NEXT: movl %edx, %eax | |
| ; X86-NOBMI-NEXT: xorl %edx, %edx | |
| ; X86-NOBMI-NEXT: .LBB36_2: | |
| ; X86-NOBMI-NEXT: movl %edx, 4(%esi) | |
| ; X86-NOBMI-NEXT: movl %eax, (%esi) | |
| ; X86-NOBMI-NEXT: andl {{[0-9]+}}(%esp), %eax | |
| ; X86-NOBMI-NEXT: andl {{[0-9]+}}(%esp), %edx | |
| ; X86-NOBMI-NEXT: popl %esi | |
| ; X86-NOBMI-NEXT: retl | |
| ; | |
| ; X86-BMI1-LABEL: bzhi64_c1_indexzext: | |
| ; X86-BMI1: # %bb.0: | |
| ; X86-BMI1-NEXT: pushl %esi | |
| ; X86-BMI1-NEXT: movl {{[0-9]+}}(%esp), %esi | |
| ; X86-BMI1-NEXT: movb $64, %cl | |
| ; X86-BMI1-NEXT: subb {{[0-9]+}}(%esp), %cl | |
| ; X86-BMI1-NEXT: movl $-1, %eax | |
| ; X86-BMI1-NEXT: movl $-1, %edx | |
| ; X86-BMI1-NEXT: shrl %cl, %edx | |
| ; X86-BMI1-NEXT: testb $32, %cl | |
| ; X86-BMI1-NEXT: je .LBB36_2 | |
| ; X86-BMI1-NEXT: # %bb.1: | |
| ; X86-BMI1-NEXT: movl %edx, %eax | |
| ; X86-BMI1-NEXT: xorl %edx, %edx | |
| ; X86-BMI1-NEXT: .LBB36_2: | |
| ; X86-BMI1-NEXT: movl %edx, 4(%esi) | |
| ; X86-BMI1-NEXT: movl %eax, (%esi) | |
| ; X86-BMI1-NEXT: andl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: andl {{[0-9]+}}(%esp), %edx | |
| ; X86-BMI1-NEXT: popl %esi | |
| ; X86-BMI1-NEXT: retl | |
| ; | |
| ; X86-BMI2-LABEL: bzhi64_c1_indexzext: | |
| ; X86-BMI2: # %bb.0: | |
| ; X86-BMI2-NEXT: pushl %ebx | |
| ; X86-BMI2-NEXT: movl {{[0-9]+}}(%esp), %ecx | |
| ; X86-BMI2-NEXT: movb $64, %bl | |
| ; X86-BMI2-NEXT: subb {{[0-9]+}}(%esp), %bl | |
| ; X86-BMI2-NEXT: movl $-1, %eax | |
| ; X86-BMI2-NEXT: shrxl %ebx, %eax, %edx | |
| ; X86-BMI2-NEXT: testb $32, %bl | |
| ; X86-BMI2-NEXT: je .LBB36_2 | |
| ; X86-BMI2-NEXT: # %bb.1: | |
| ; X86-BMI2-NEXT: movl %edx, %eax | |
| ; X86-BMI2-NEXT: xorl %edx, %edx | |
| ; X86-BMI2-NEXT: .LBB36_2: | |
| ; X86-BMI2-NEXT: movl %edx, 4(%ecx) | |
| ; X86-BMI2-NEXT: movl %eax, (%ecx) | |
| ; X86-BMI2-NEXT: andl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: andl {{[0-9]+}}(%esp), %edx | |
| ; X86-BMI2-NEXT: popl %ebx | |
| ; X86-BMI2-NEXT: retl | |
| ; | |
| ; X64-NOBMI-LABEL: bzhi64_c1_indexzext: | |
| ; X64-NOBMI: # %bb.0: | |
| ; X64-NOBMI-NEXT: movl %esi, %ecx | |
| ; X64-NOBMI-NEXT: negb %cl | |
| ; X64-NOBMI-NEXT: movq $-1, %rax | |
| ; X64-NOBMI-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X64-NOBMI-NEXT: shrq %cl, %rax | |
| ; X64-NOBMI-NEXT: movq %rax, (%rdx) | |
| ; X64-NOBMI-NEXT: andq %rdi, %rax | |
| ; X64-NOBMI-NEXT: retq | |
| ; | |
| ; X64-BMI1-LABEL: bzhi64_c1_indexzext: | |
| ; X64-BMI1: # %bb.0: | |
| ; X64-BMI1-NEXT: movl %esi, %ecx | |
| ; X64-BMI1-NEXT: negb %cl | |
| ; X64-BMI1-NEXT: movq $-1, %rax | |
| ; X64-BMI1-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X64-BMI1-NEXT: shrq %cl, %rax | |
| ; X64-BMI1-NEXT: movq %rax, (%rdx) | |
| ; X64-BMI1-NEXT: andq %rdi, %rax | |
| ; X64-BMI1-NEXT: retq | |
| ; | |
| ; X64-BMI2-LABEL: bzhi64_c1_indexzext: | |
| ; X64-BMI2: # %bb.0: | |
| ; X64-BMI2-NEXT: # kill: def $esi killed $esi def $rsi | |
| ; X64-BMI2-NEXT: movq $-1, %rax | |
| ; X64-BMI2-NEXT: bzhiq %rsi, %rax, %rax | |
| ; X64-BMI2-NEXT: movq %rax, (%rdx) | |
| ; X64-BMI2-NEXT: bzhiq %rsi, %rdi, %rax | |
| ; X64-BMI2-NEXT: retq | |
| %numhighbits = sub i8 64, %numlowbits | |
| %sh_prom = zext i8 %numhighbits to i64 | |
| %mask = lshr i64 -1, %sh_prom | |
| store i64 %mask, ptr %escape | |
| %masked = and i64 %mask, %val | |
| ret i64 %masked | |
| } | |
| define i64 @bzhi64_c2_load(ptr %w, i64 %numlowbits, ptr %escape) nounwind { | |
| ; X86-NOBMI-LABEL: bzhi64_c2_load: | |
| ; X86-NOBMI: # %bb.0: | |
| ; X86-NOBMI-NEXT: pushl %ebx | |
| ; X86-NOBMI-NEXT: pushl %edi | |
| ; X86-NOBMI-NEXT: pushl %esi | |
| ; X86-NOBMI-NEXT: movl {{[0-9]+}}(%esp), %esi | |
| ; X86-NOBMI-NEXT: movl {{[0-9]+}}(%esp), %eax | |
| ; X86-NOBMI-NEXT: movb $64, %cl | |
| ; X86-NOBMI-NEXT: subb {{[0-9]+}}(%esp), %cl | |
| ; X86-NOBMI-NEXT: movl $-1, %edi | |
| ; X86-NOBMI-NEXT: movl $-1, %ebx | |
| ; X86-NOBMI-NEXT: shrl %cl, %ebx | |
| ; X86-NOBMI-NEXT: testb $32, %cl | |
| ; X86-NOBMI-NEXT: je .LBB37_2 | |
| ; X86-NOBMI-NEXT: # %bb.1: | |
| ; X86-NOBMI-NEXT: movl %ebx, %edi | |
| ; X86-NOBMI-NEXT: xorl %ebx, %ebx | |
| ; X86-NOBMI-NEXT: .LBB37_2: | |
| ; X86-NOBMI-NEXT: movl 4(%eax), %edx | |
| ; X86-NOBMI-NEXT: andl %ebx, %edx | |
| ; X86-NOBMI-NEXT: movl (%eax), %eax | |
| ; X86-NOBMI-NEXT: andl %edi, %eax | |
| ; X86-NOBMI-NEXT: movl %ebx, 4(%esi) | |
| ; X86-NOBMI-NEXT: movl %edi, (%esi) | |
| ; X86-NOBMI-NEXT: popl %esi | |
| ; X86-NOBMI-NEXT: popl %edi | |
| ; X86-NOBMI-NEXT: popl %ebx | |
| ; X86-NOBMI-NEXT: retl | |
| ; | |
| ; X86-BMI1-LABEL: bzhi64_c2_load: | |
| ; X86-BMI1: # %bb.0: | |
| ; X86-BMI1-NEXT: pushl %ebx | |
| ; X86-BMI1-NEXT: pushl %edi | |
| ; X86-BMI1-NEXT: pushl %esi | |
| ; X86-BMI1-NEXT: movl {{[0-9]+}}(%esp), %esi | |
| ; X86-BMI1-NEXT: movl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: movb $64, %cl | |
| ; X86-BMI1-NEXT: subb {{[0-9]+}}(%esp), %cl | |
| ; X86-BMI1-NEXT: movl $-1, %edi | |
| ; X86-BMI1-NEXT: movl $-1, %ebx | |
| ; X86-BMI1-NEXT: shrl %cl, %ebx | |
| ; X86-BMI1-NEXT: testb $32, %cl | |
| ; X86-BMI1-NEXT: je .LBB37_2 | |
| ; X86-BMI1-NEXT: # %bb.1: | |
| ; X86-BMI1-NEXT: movl %ebx, %edi | |
| ; X86-BMI1-NEXT: xorl %ebx, %ebx | |
| ; X86-BMI1-NEXT: .LBB37_2: | |
| ; X86-BMI1-NEXT: movl 4(%eax), %edx | |
| ; X86-BMI1-NEXT: andl %ebx, %edx | |
| ; X86-BMI1-NEXT: movl (%eax), %eax | |
| ; X86-BMI1-NEXT: andl %edi, %eax | |
| ; X86-BMI1-NEXT: movl %ebx, 4(%esi) | |
| ; X86-BMI1-NEXT: movl %edi, (%esi) | |
| ; X86-BMI1-NEXT: popl %esi | |
| ; X86-BMI1-NEXT: popl %edi | |
| ; X86-BMI1-NEXT: popl %ebx | |
| ; X86-BMI1-NEXT: retl | |
| ; | |
| ; X86-BMI2-LABEL: bzhi64_c2_load: | |
| ; X86-BMI2: # %bb.0: | |
| ; X86-BMI2-NEXT: pushl %edi | |
| ; X86-BMI2-NEXT: pushl %esi | |
| ; X86-BMI2-NEXT: movl {{[0-9]+}}(%esp), %ecx | |
| ; X86-BMI2-NEXT: movl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: movb $64, %dl | |
| ; X86-BMI2-NEXT: subb {{[0-9]+}}(%esp), %dl | |
| ; X86-BMI2-NEXT: movl $-1, %esi | |
| ; X86-BMI2-NEXT: shrxl %edx, %esi, %edi | |
| ; X86-BMI2-NEXT: testb $32, %dl | |
| ; X86-BMI2-NEXT: je .LBB37_2 | |
| ; X86-BMI2-NEXT: # %bb.1: | |
| ; X86-BMI2-NEXT: movl %edi, %esi | |
| ; X86-BMI2-NEXT: xorl %edi, %edi | |
| ; X86-BMI2-NEXT: .LBB37_2: | |
| ; X86-BMI2-NEXT: movl 4(%eax), %edx | |
| ; X86-BMI2-NEXT: andl %edi, %edx | |
| ; X86-BMI2-NEXT: movl (%eax), %eax | |
| ; X86-BMI2-NEXT: andl %esi, %eax | |
| ; X86-BMI2-NEXT: movl %edi, 4(%ecx) | |
| ; X86-BMI2-NEXT: movl %esi, (%ecx) | |
| ; X86-BMI2-NEXT: popl %esi | |
| ; X86-BMI2-NEXT: popl %edi | |
| ; X86-BMI2-NEXT: retl | |
| ; | |
| ; X64-NOBMI-LABEL: bzhi64_c2_load: | |
| ; X64-NOBMI: # %bb.0: | |
| ; X64-NOBMI-NEXT: movq %rsi, %rcx | |
| ; X64-NOBMI-NEXT: negb %cl | |
| ; X64-NOBMI-NEXT: movq $-1, %rsi | |
| ; X64-NOBMI-NEXT: # kill: def $cl killed $cl killed $rcx | |
| ; X64-NOBMI-NEXT: shrq %cl, %rsi | |
| ; X64-NOBMI-NEXT: movq (%rdi), %rax | |
| ; X64-NOBMI-NEXT: andq %rsi, %rax | |
| ; X64-NOBMI-NEXT: movq %rsi, (%rdx) | |
| ; X64-NOBMI-NEXT: retq | |
| ; | |
| ; X64-BMI1-LABEL: bzhi64_c2_load: | |
| ; X64-BMI1: # %bb.0: | |
| ; X64-BMI1-NEXT: movq %rsi, %rcx | |
| ; X64-BMI1-NEXT: negb %cl | |
| ; X64-BMI1-NEXT: movq $-1, %rsi | |
| ; X64-BMI1-NEXT: # kill: def $cl killed $cl killed $rcx | |
| ; X64-BMI1-NEXT: shrq %cl, %rsi | |
| ; X64-BMI1-NEXT: movq (%rdi), %rax | |
| ; X64-BMI1-NEXT: andq %rsi, %rax | |
| ; X64-BMI1-NEXT: movq %rsi, (%rdx) | |
| ; X64-BMI1-NEXT: retq | |
| ; | |
| ; X64-BMI2-LABEL: bzhi64_c2_load: | |
| ; X64-BMI2: # %bb.0: | |
| ; X64-BMI2-NEXT: movq $-1, %rax | |
| ; X64-BMI2-NEXT: bzhiq %rsi, %rax, %rcx | |
| ; X64-BMI2-NEXT: bzhiq %rsi, (%rdi), %rax | |
| ; X64-BMI2-NEXT: movq %rcx, (%rdx) | |
| ; X64-BMI2-NEXT: retq | |
| %val = load i64, ptr %w | |
| %numhighbits = sub i64 64, %numlowbits | |
| %mask = lshr i64 -1, %numhighbits | |
| store i64 %mask, ptr %escape | |
| %masked = and i64 %mask, %val | |
| ret i64 %masked | |
| } | |
| define i64 @bzhi64_c3_load_indexzext(ptr %w, i8 %numlowbits, ptr %escape) nounwind { | |
| ; X86-NOBMI-LABEL: bzhi64_c3_load_indexzext: | |
| ; X86-NOBMI: # %bb.0: | |
| ; X86-NOBMI-NEXT: pushl %ebx | |
| ; X86-NOBMI-NEXT: pushl %edi | |
| ; X86-NOBMI-NEXT: pushl %esi | |
| ; X86-NOBMI-NEXT: movl {{[0-9]+}}(%esp), %esi | |
| ; X86-NOBMI-NEXT: movl {{[0-9]+}}(%esp), %eax | |
| ; X86-NOBMI-NEXT: movb $64, %cl | |
| ; X86-NOBMI-NEXT: subb {{[0-9]+}}(%esp), %cl | |
| ; X86-NOBMI-NEXT: movl $-1, %edi | |
| ; X86-NOBMI-NEXT: movl $-1, %ebx | |
| ; X86-NOBMI-NEXT: shrl %cl, %ebx | |
| ; X86-NOBMI-NEXT: testb $32, %cl | |
| ; X86-NOBMI-NEXT: je .LBB38_2 | |
| ; X86-NOBMI-NEXT: # %bb.1: | |
| ; X86-NOBMI-NEXT: movl %ebx, %edi | |
| ; X86-NOBMI-NEXT: xorl %ebx, %ebx | |
| ; X86-NOBMI-NEXT: .LBB38_2: | |
| ; X86-NOBMI-NEXT: movl 4(%eax), %edx | |
| ; X86-NOBMI-NEXT: andl %ebx, %edx | |
| ; X86-NOBMI-NEXT: movl (%eax), %eax | |
| ; X86-NOBMI-NEXT: andl %edi, %eax | |
| ; X86-NOBMI-NEXT: movl %ebx, 4(%esi) | |
| ; X86-NOBMI-NEXT: movl %edi, (%esi) | |
| ; X86-NOBMI-NEXT: popl %esi | |
| ; X86-NOBMI-NEXT: popl %edi | |
| ; X86-NOBMI-NEXT: popl %ebx | |
| ; X86-NOBMI-NEXT: retl | |
| ; | |
| ; X86-BMI1-LABEL: bzhi64_c3_load_indexzext: | |
| ; X86-BMI1: # %bb.0: | |
| ; X86-BMI1-NEXT: pushl %ebx | |
| ; X86-BMI1-NEXT: pushl %edi | |
| ; X86-BMI1-NEXT: pushl %esi | |
| ; X86-BMI1-NEXT: movl {{[0-9]+}}(%esp), %esi | |
| ; X86-BMI1-NEXT: movl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: movb $64, %cl | |
| ; X86-BMI1-NEXT: subb {{[0-9]+}}(%esp), %cl | |
| ; X86-BMI1-NEXT: movl $-1, %edi | |
| ; X86-BMI1-NEXT: movl $-1, %ebx | |
| ; X86-BMI1-NEXT: shrl %cl, %ebx | |
| ; X86-BMI1-NEXT: testb $32, %cl | |
| ; X86-BMI1-NEXT: je .LBB38_2 | |
| ; X86-BMI1-NEXT: # %bb.1: | |
| ; X86-BMI1-NEXT: movl %ebx, %edi | |
| ; X86-BMI1-NEXT: xorl %ebx, %ebx | |
| ; X86-BMI1-NEXT: .LBB38_2: | |
| ; X86-BMI1-NEXT: movl 4(%eax), %edx | |
| ; X86-BMI1-NEXT: andl %ebx, %edx | |
| ; X86-BMI1-NEXT: movl (%eax), %eax | |
| ; X86-BMI1-NEXT: andl %edi, %eax | |
| ; X86-BMI1-NEXT: movl %ebx, 4(%esi) | |
| ; X86-BMI1-NEXT: movl %edi, (%esi) | |
| ; X86-BMI1-NEXT: popl %esi | |
| ; X86-BMI1-NEXT: popl %edi | |
| ; X86-BMI1-NEXT: popl %ebx | |
| ; X86-BMI1-NEXT: retl | |
| ; | |
| ; X86-BMI2-LABEL: bzhi64_c3_load_indexzext: | |
| ; X86-BMI2: # %bb.0: | |
| ; X86-BMI2-NEXT: pushl %edi | |
| ; X86-BMI2-NEXT: pushl %esi | |
| ; X86-BMI2-NEXT: movl {{[0-9]+}}(%esp), %ecx | |
| ; X86-BMI2-NEXT: movl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: movb $64, %dl | |
| ; X86-BMI2-NEXT: subb {{[0-9]+}}(%esp), %dl | |
| ; X86-BMI2-NEXT: movl $-1, %esi | |
| ; X86-BMI2-NEXT: shrxl %edx, %esi, %edi | |
| ; X86-BMI2-NEXT: testb $32, %dl | |
| ; X86-BMI2-NEXT: je .LBB38_2 | |
| ; X86-BMI2-NEXT: # %bb.1: | |
| ; X86-BMI2-NEXT: movl %edi, %esi | |
| ; X86-BMI2-NEXT: xorl %edi, %edi | |
| ; X86-BMI2-NEXT: .LBB38_2: | |
| ; X86-BMI2-NEXT: movl 4(%eax), %edx | |
| ; X86-BMI2-NEXT: andl %edi, %edx | |
| ; X86-BMI2-NEXT: movl (%eax), %eax | |
| ; X86-BMI2-NEXT: andl %esi, %eax | |
| ; X86-BMI2-NEXT: movl %edi, 4(%ecx) | |
| ; X86-BMI2-NEXT: movl %esi, (%ecx) | |
| ; X86-BMI2-NEXT: popl %esi | |
| ; X86-BMI2-NEXT: popl %edi | |
| ; X86-BMI2-NEXT: retl | |
| ; | |
| ; X64-NOBMI-LABEL: bzhi64_c3_load_indexzext: | |
| ; X64-NOBMI: # %bb.0: | |
| ; X64-NOBMI-NEXT: movl %esi, %ecx | |
| ; X64-NOBMI-NEXT: negb %cl | |
| ; X64-NOBMI-NEXT: movq $-1, %rsi | |
| ; X64-NOBMI-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X64-NOBMI-NEXT: shrq %cl, %rsi | |
| ; X64-NOBMI-NEXT: movq (%rdi), %rax | |
| ; X64-NOBMI-NEXT: andq %rsi, %rax | |
| ; X64-NOBMI-NEXT: movq %rsi, (%rdx) | |
| ; X64-NOBMI-NEXT: retq | |
| ; | |
| ; X64-BMI1-LABEL: bzhi64_c3_load_indexzext: | |
| ; X64-BMI1: # %bb.0: | |
| ; X64-BMI1-NEXT: movl %esi, %ecx | |
| ; X64-BMI1-NEXT: negb %cl | |
| ; X64-BMI1-NEXT: movq $-1, %rsi | |
| ; X64-BMI1-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X64-BMI1-NEXT: shrq %cl, %rsi | |
| ; X64-BMI1-NEXT: movq (%rdi), %rax | |
| ; X64-BMI1-NEXT: andq %rsi, %rax | |
| ; X64-BMI1-NEXT: movq %rsi, (%rdx) | |
| ; X64-BMI1-NEXT: retq | |
| ; | |
| ; X64-BMI2-LABEL: bzhi64_c3_load_indexzext: | |
| ; X64-BMI2: # %bb.0: | |
| ; X64-BMI2-NEXT: # kill: def $esi killed $esi def $rsi | |
| ; X64-BMI2-NEXT: movq $-1, %rax | |
| ; X64-BMI2-NEXT: bzhiq %rsi, %rax, %rcx | |
| ; X64-BMI2-NEXT: bzhiq %rsi, (%rdi), %rax | |
| ; X64-BMI2-NEXT: movq %rcx, (%rdx) | |
| ; X64-BMI2-NEXT: retq | |
| %val = load i64, ptr %w | |
| %numhighbits = sub i8 64, %numlowbits | |
| %sh_prom = zext i8 %numhighbits to i64 | |
| %mask = lshr i64 -1, %sh_prom | |
| store i64 %mask, ptr %escape | |
| %masked = and i64 %mask, %val | |
| ret i64 %masked | |
| } | |
| define i64 @bzhi64_c4_commutative(i64 %val, i64 %numlowbits, ptr %escape) nounwind { | |
| ; X86-NOBMI-LABEL: bzhi64_c4_commutative: | |
| ; X86-NOBMI: # %bb.0: | |
| ; X86-NOBMI-NEXT: pushl %esi | |
| ; X86-NOBMI-NEXT: movl {{[0-9]+}}(%esp), %esi | |
| ; X86-NOBMI-NEXT: movb $64, %cl | |
| ; X86-NOBMI-NEXT: subb {{[0-9]+}}(%esp), %cl | |
| ; X86-NOBMI-NEXT: movl $-1, %eax | |
| ; X86-NOBMI-NEXT: movl $-1, %edx | |
| ; X86-NOBMI-NEXT: shrl %cl, %edx | |
| ; X86-NOBMI-NEXT: testb $32, %cl | |
| ; X86-NOBMI-NEXT: je .LBB39_2 | |
| ; X86-NOBMI-NEXT: # %bb.1: | |
| ; X86-NOBMI-NEXT: movl %edx, %eax | |
| ; X86-NOBMI-NEXT: xorl %edx, %edx | |
| ; X86-NOBMI-NEXT: .LBB39_2: | |
| ; X86-NOBMI-NEXT: movl %edx, 4(%esi) | |
| ; X86-NOBMI-NEXT: movl %eax, (%esi) | |
| ; X86-NOBMI-NEXT: andl {{[0-9]+}}(%esp), %eax | |
| ; X86-NOBMI-NEXT: andl {{[0-9]+}}(%esp), %edx | |
| ; X86-NOBMI-NEXT: popl %esi | |
| ; X86-NOBMI-NEXT: retl | |
| ; | |
| ; X86-BMI1-LABEL: bzhi64_c4_commutative: | |
| ; X86-BMI1: # %bb.0: | |
| ; X86-BMI1-NEXT: pushl %esi | |
| ; X86-BMI1-NEXT: movl {{[0-9]+}}(%esp), %esi | |
| ; X86-BMI1-NEXT: movb $64, %cl | |
| ; X86-BMI1-NEXT: subb {{[0-9]+}}(%esp), %cl | |
| ; X86-BMI1-NEXT: movl $-1, %eax | |
| ; X86-BMI1-NEXT: movl $-1, %edx | |
| ; X86-BMI1-NEXT: shrl %cl, %edx | |
| ; X86-BMI1-NEXT: testb $32, %cl | |
| ; X86-BMI1-NEXT: je .LBB39_2 | |
| ; X86-BMI1-NEXT: # %bb.1: | |
| ; X86-BMI1-NEXT: movl %edx, %eax | |
| ; X86-BMI1-NEXT: xorl %edx, %edx | |
| ; X86-BMI1-NEXT: .LBB39_2: | |
| ; X86-BMI1-NEXT: movl %edx, 4(%esi) | |
| ; X86-BMI1-NEXT: movl %eax, (%esi) | |
| ; X86-BMI1-NEXT: andl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: andl {{[0-9]+}}(%esp), %edx | |
| ; X86-BMI1-NEXT: popl %esi | |
| ; X86-BMI1-NEXT: retl | |
| ; | |
| ; X86-BMI2-LABEL: bzhi64_c4_commutative: | |
| ; X86-BMI2: # %bb.0: | |
| ; X86-BMI2-NEXT: pushl %ebx | |
| ; X86-BMI2-NEXT: movl {{[0-9]+}}(%esp), %ecx | |
| ; X86-BMI2-NEXT: movb $64, %bl | |
| ; X86-BMI2-NEXT: subb {{[0-9]+}}(%esp), %bl | |
| ; X86-BMI2-NEXT: movl $-1, %eax | |
| ; X86-BMI2-NEXT: shrxl %ebx, %eax, %edx | |
| ; X86-BMI2-NEXT: testb $32, %bl | |
| ; X86-BMI2-NEXT: je .LBB39_2 | |
| ; X86-BMI2-NEXT: # %bb.1: | |
| ; X86-BMI2-NEXT: movl %edx, %eax | |
| ; X86-BMI2-NEXT: xorl %edx, %edx | |
| ; X86-BMI2-NEXT: .LBB39_2: | |
| ; X86-BMI2-NEXT: movl %edx, 4(%ecx) | |
| ; X86-BMI2-NEXT: movl %eax, (%ecx) | |
| ; X86-BMI2-NEXT: andl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: andl {{[0-9]+}}(%esp), %edx | |
| ; X86-BMI2-NEXT: popl %ebx | |
| ; X86-BMI2-NEXT: retl | |
| ; | |
| ; X64-NOBMI-LABEL: bzhi64_c4_commutative: | |
| ; X64-NOBMI: # %bb.0: | |
| ; X64-NOBMI-NEXT: movq %rsi, %rcx | |
| ; X64-NOBMI-NEXT: negb %cl | |
| ; X64-NOBMI-NEXT: movq $-1, %rax | |
| ; X64-NOBMI-NEXT: # kill: def $cl killed $cl killed $rcx | |
| ; X64-NOBMI-NEXT: shrq %cl, %rax | |
| ; X64-NOBMI-NEXT: movq %rax, (%rdx) | |
| ; X64-NOBMI-NEXT: andq %rdi, %rax | |
| ; X64-NOBMI-NEXT: retq | |
| ; | |
| ; X64-BMI1-LABEL: bzhi64_c4_commutative: | |
| ; X64-BMI1: # %bb.0: | |
| ; X64-BMI1-NEXT: movq %rsi, %rcx | |
| ; X64-BMI1-NEXT: negb %cl | |
| ; X64-BMI1-NEXT: movq $-1, %rax | |
| ; X64-BMI1-NEXT: # kill: def $cl killed $cl killed $rcx | |
| ; X64-BMI1-NEXT: shrq %cl, %rax | |
| ; X64-BMI1-NEXT: movq %rax, (%rdx) | |
| ; X64-BMI1-NEXT: andq %rdi, %rax | |
| ; X64-BMI1-NEXT: retq | |
| ; | |
| ; X64-BMI2-LABEL: bzhi64_c4_commutative: | |
| ; X64-BMI2: # %bb.0: | |
| ; X64-BMI2-NEXT: movq $-1, %rax | |
| ; X64-BMI2-NEXT: bzhiq %rsi, %rax, %rax | |
| ; X64-BMI2-NEXT: movq %rax, (%rdx) | |
| ; X64-BMI2-NEXT: bzhiq %rsi, %rdi, %rax | |
| ; X64-BMI2-NEXT: retq | |
| %numhighbits = sub i64 64, %numlowbits | |
| %mask = lshr i64 -1, %numhighbits | |
| store i64 %mask, ptr %escape | |
| %masked = and i64 %val, %mask ; swapped order | |
| ret i64 %masked | |
| } | |
| ; 64-bit, but with 32-bit output | |
| ; Everything done in 64-bit, truncation happens last. | |
| define i32 @bzhi64_32_c0(i64 %val, i64 %numlowbits) nounwind { | |
| ; X86-NOBMI-LABEL: bzhi64_32_c0: | |
| ; X86-NOBMI: # %bb.0: | |
| ; X86-NOBMI-NEXT: movb $64, %cl | |
| ; X86-NOBMI-NEXT: subb {{[0-9]+}}(%esp), %cl | |
| ; X86-NOBMI-NEXT: movl $-1, %eax | |
| ; X86-NOBMI-NEXT: shrl %cl, %eax | |
| ; X86-NOBMI-NEXT: testb $32, %cl | |
| ; X86-NOBMI-NEXT: jne .LBB40_2 | |
| ; X86-NOBMI-NEXT: # %bb.1: | |
| ; X86-NOBMI-NEXT: movl $-1, %eax | |
| ; X86-NOBMI-NEXT: .LBB40_2: | |
| ; X86-NOBMI-NEXT: andl {{[0-9]+}}(%esp), %eax | |
| ; X86-NOBMI-NEXT: retl | |
| ; | |
| ; X86-BMI1-LABEL: bzhi64_32_c0: | |
| ; X86-BMI1: # %bb.0: | |
| ; X86-BMI1-NEXT: movb $64, %cl | |
| ; X86-BMI1-NEXT: subb {{[0-9]+}}(%esp), %cl | |
| ; X86-BMI1-NEXT: movl $-1, %eax | |
| ; X86-BMI1-NEXT: shrl %cl, %eax | |
| ; X86-BMI1-NEXT: testb $32, %cl | |
| ; X86-BMI1-NEXT: jne .LBB40_2 | |
| ; X86-BMI1-NEXT: # %bb.1: | |
| ; X86-BMI1-NEXT: movl $-1, %eax | |
| ; X86-BMI1-NEXT: .LBB40_2: | |
| ; X86-BMI1-NEXT: andl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: retl | |
| ; | |
| ; X86-BMI2-LABEL: bzhi64_32_c0: | |
| ; X86-BMI2: # %bb.0: | |
| ; X86-BMI2-NEXT: movb $64, %cl | |
| ; X86-BMI2-NEXT: subb {{[0-9]+}}(%esp), %cl | |
| ; X86-BMI2-NEXT: movl $-1, %eax | |
| ; X86-BMI2-NEXT: testb $32, %cl | |
| ; X86-BMI2-NEXT: je .LBB40_2 | |
| ; X86-BMI2-NEXT: # %bb.1: | |
| ; X86-BMI2-NEXT: shrxl %ecx, %eax, %eax | |
| ; X86-BMI2-NEXT: .LBB40_2: | |
| ; X86-BMI2-NEXT: andl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: retl | |
| ; | |
| ; X64-NOBMI-LABEL: bzhi64_32_c0: | |
| ; X64-NOBMI: # %bb.0: | |
| ; X64-NOBMI-NEXT: movq %rsi, %rcx | |
| ; X64-NOBMI-NEXT: negb %cl | |
| ; X64-NOBMI-NEXT: movq $-1, %rax | |
| ; X64-NOBMI-NEXT: # kill: def $cl killed $cl killed $rcx | |
| ; X64-NOBMI-NEXT: shrq %cl, %rax | |
| ; X64-NOBMI-NEXT: andl %edi, %eax | |
| ; X64-NOBMI-NEXT: # kill: def $eax killed $eax killed $rax | |
| ; X64-NOBMI-NEXT: retq | |
| ; | |
| ; X64-BMI1-LABEL: bzhi64_32_c0: | |
| ; X64-BMI1: # %bb.0: | |
| ; X64-BMI1-NEXT: shll $8, %esi | |
| ; X64-BMI1-NEXT: bextrl %esi, %edi, %eax | |
| ; X64-BMI1-NEXT: retq | |
| ; | |
| ; X64-BMI2-LABEL: bzhi64_32_c0: | |
| ; X64-BMI2: # %bb.0: | |
| ; X64-BMI2-NEXT: bzhil %esi, %edi, %eax | |
| ; X64-BMI2-NEXT: retq | |
| %numhighbits = sub i64 64, %numlowbits | |
| %mask = lshr i64 -1, %numhighbits | |
| %masked = and i64 %mask, %val | |
| %res = trunc i64 %masked to i32 | |
| ret i32 %res | |
| } | |
| ; Shifting happens in 64-bit, then truncation. Masking is 32-bit. | |
| define i32 @bzhi64_32_c1(i64 %val, i32 %numlowbits) nounwind { | |
| ; X86-NOBMI-LABEL: bzhi64_32_c1: | |
| ; X86-NOBMI: # %bb.0: | |
| ; X86-NOBMI-NEXT: movl {{[0-9]+}}(%esp), %eax | |
| ; X86-NOBMI-NEXT: xorl %ecx, %ecx | |
| ; X86-NOBMI-NEXT: subb {{[0-9]+}}(%esp), %cl | |
| ; X86-NOBMI-NEXT: shll %cl, %eax | |
| ; X86-NOBMI-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X86-NOBMI-NEXT: shrl %cl, %eax | |
| ; X86-NOBMI-NEXT: retl | |
| ; | |
| ; X86-BMI1-LABEL: bzhi64_32_c1: | |
| ; X86-BMI1: # %bb.0: | |
| ; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: shll $8, %eax | |
| ; X86-BMI1-NEXT: bextrl %eax, {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: retl | |
| ; | |
| ; X86-BMI2-LABEL: bzhi64_32_c1: | |
| ; X86-BMI2: # %bb.0: | |
| ; X86-BMI2-NEXT: movzbl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: bzhil %eax, {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: retl | |
| ; | |
| ; X64-NOBMI-LABEL: bzhi64_32_c1: | |
| ; X64-NOBMI: # %bb.0: | |
| ; X64-NOBMI-NEXT: movl %esi, %ecx | |
| ; X64-NOBMI-NEXT: movq %rdi, %rax | |
| ; X64-NOBMI-NEXT: negb %cl | |
| ; X64-NOBMI-NEXT: shll %cl, %eax | |
| ; X64-NOBMI-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X64-NOBMI-NEXT: shrl %cl, %eax | |
| ; X64-NOBMI-NEXT: # kill: def $eax killed $eax killed $rax | |
| ; X64-NOBMI-NEXT: retq | |
| ; | |
| ; X64-BMI1-LABEL: bzhi64_32_c1: | |
| ; X64-BMI1: # %bb.0: | |
| ; X64-BMI1-NEXT: shll $8, %esi | |
| ; X64-BMI1-NEXT: bextrl %esi, %edi, %eax | |
| ; X64-BMI1-NEXT: retq | |
| ; | |
| ; X64-BMI2-LABEL: bzhi64_32_c1: | |
| ; X64-BMI2: # %bb.0: | |
| ; X64-BMI2-NEXT: bzhil %esi, %edi, %eax | |
| ; X64-BMI2-NEXT: retq | |
| %truncval = trunc i64 %val to i32 | |
| %numhighbits = sub i32 32, %numlowbits | |
| %mask = lshr i32 -1, %numhighbits | |
| %masked = and i32 %mask, %truncval | |
| ret i32 %masked | |
| } | |
| ; Shifting happens in 64-bit. Mask is 32-bit, but extended to 64-bit. | |
| ; Masking is 64-bit. Then truncation. | |
| define i32 @bzhi64_32_c2(i64 %val, i32 %numlowbits) nounwind { | |
| ; X86-NOBMI-LABEL: bzhi64_32_c2: | |
| ; X86-NOBMI: # %bb.0: | |
| ; X86-NOBMI-NEXT: movl {{[0-9]+}}(%esp), %eax | |
| ; X86-NOBMI-NEXT: xorl %ecx, %ecx | |
| ; X86-NOBMI-NEXT: subb {{[0-9]+}}(%esp), %cl | |
| ; X86-NOBMI-NEXT: shll %cl, %eax | |
| ; X86-NOBMI-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X86-NOBMI-NEXT: shrl %cl, %eax | |
| ; X86-NOBMI-NEXT: retl | |
| ; | |
| ; X86-BMI1-LABEL: bzhi64_32_c2: | |
| ; X86-BMI1: # %bb.0: | |
| ; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: shll $8, %eax | |
| ; X86-BMI1-NEXT: bextrl %eax, {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: retl | |
| ; | |
| ; X86-BMI2-LABEL: bzhi64_32_c2: | |
| ; X86-BMI2: # %bb.0: | |
| ; X86-BMI2-NEXT: movzbl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: bzhil %eax, {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: retl | |
| ; | |
| ; X64-NOBMI-LABEL: bzhi64_32_c2: | |
| ; X64-NOBMI: # %bb.0: | |
| ; X64-NOBMI-NEXT: movl %esi, %ecx | |
| ; X64-NOBMI-NEXT: movq %rdi, %rax | |
| ; X64-NOBMI-NEXT: negb %cl | |
| ; X64-NOBMI-NEXT: shll %cl, %eax | |
| ; X64-NOBMI-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X64-NOBMI-NEXT: shrl %cl, %eax | |
| ; X64-NOBMI-NEXT: # kill: def $eax killed $eax killed $rax | |
| ; X64-NOBMI-NEXT: retq | |
| ; | |
| ; X64-BMI1-LABEL: bzhi64_32_c2: | |
| ; X64-BMI1: # %bb.0: | |
| ; X64-BMI1-NEXT: shll $8, %esi | |
| ; X64-BMI1-NEXT: bextrl %esi, %edi, %eax | |
| ; X64-BMI1-NEXT: retq | |
| ; | |
| ; X64-BMI2-LABEL: bzhi64_32_c2: | |
| ; X64-BMI2: # %bb.0: | |
| ; X64-BMI2-NEXT: bzhil %esi, %edi, %eax | |
| ; X64-BMI2-NEXT: retq | |
| %numhighbits = sub i32 32, %numlowbits | |
| %mask = lshr i32 -1, %numhighbits | |
| %zextmask = zext i32 %mask to i64 | |
| %masked = and i64 %zextmask, %val | |
| %truncmasked = trunc i64 %masked to i32 | |
| ret i32 %truncmasked | |
| } | |
| ; Shifting happens in 64-bit. Mask is 32-bit, but calculated in 64-bit. | |
| ; Masking is 64-bit. Then truncation. | |
| define i32 @bzhi64_32_c3(i64 %val, i64 %numlowbits) nounwind { | |
| ; X86-LABEL: bzhi64_32_c3: | |
| ; X86: # %bb.0: | |
| ; X86-NEXT: movb $64, %cl | |
| ; X86-NEXT: subb {{[0-9]+}}(%esp), %cl | |
| ; X86-NEXT: xorl %eax, %eax | |
| ; X86-NEXT: movl $-1, %edx | |
| ; X86-NEXT: shrdl %cl, %eax, %edx | |
| ; X86-NEXT: testb $32, %cl | |
| ; X86-NEXT: jne .LBB43_2 | |
| ; X86-NEXT: # %bb.1: | |
| ; X86-NEXT: movl %edx, %eax | |
| ; X86-NEXT: .LBB43_2: | |
| ; X86-NEXT: andl {{[0-9]+}}(%esp), %eax | |
| ; X86-NEXT: retl | |
| ; | |
| ; X64-NOBMI-LABEL: bzhi64_32_c3: | |
| ; X64-NOBMI: # %bb.0: | |
| ; X64-NOBMI-NEXT: movq %rsi, %rcx | |
| ; X64-NOBMI-NEXT: negb %cl | |
| ; X64-NOBMI-NEXT: movl $4294967295, %eax # imm = 0xFFFFFFFF | |
| ; X64-NOBMI-NEXT: # kill: def $cl killed $cl killed $rcx | |
| ; X64-NOBMI-NEXT: shrq %cl, %rax | |
| ; X64-NOBMI-NEXT: andl %edi, %eax | |
| ; X64-NOBMI-NEXT: # kill: def $eax killed $eax killed $rax | |
| ; X64-NOBMI-NEXT: retq | |
| ; | |
| ; X64-BMI1-LABEL: bzhi64_32_c3: | |
| ; X64-BMI1: # %bb.0: | |
| ; X64-BMI1-NEXT: movq %rsi, %rcx | |
| ; X64-BMI1-NEXT: negb %cl | |
| ; X64-BMI1-NEXT: movl $4294967295, %eax # imm = 0xFFFFFFFF | |
| ; X64-BMI1-NEXT: # kill: def $cl killed $cl killed $rcx | |
| ; X64-BMI1-NEXT: shrq %cl, %rax | |
| ; X64-BMI1-NEXT: andl %edi, %eax | |
| ; X64-BMI1-NEXT: # kill: def $eax killed $eax killed $rax | |
| ; X64-BMI1-NEXT: retq | |
| ; | |
| ; X64-BMI2-LABEL: bzhi64_32_c3: | |
| ; X64-BMI2: # %bb.0: | |
| ; X64-BMI2-NEXT: negb %sil | |
| ; X64-BMI2-NEXT: movl $4294967295, %eax # imm = 0xFFFFFFFF | |
| ; X64-BMI2-NEXT: shrxq %rsi, %rax, %rax | |
| ; X64-BMI2-NEXT: andl %edi, %eax | |
| ; X64-BMI2-NEXT: # kill: def $eax killed $eax killed $rax | |
| ; X64-BMI2-NEXT: retq | |
| %numhighbits = sub i64 64, %numlowbits | |
| %mask = lshr i64 4294967295, %numhighbits | |
| %masked = and i64 %mask, %val | |
| %truncmasked = trunc i64 %masked to i32 | |
| ret i32 %truncmasked | |
| } | |
| ; ---------------------------------------------------------------------------- ; | |
| ; Pattern d. 32-bit. | |
| ; ---------------------------------------------------------------------------- ; | |
| define i32 @bzhi32_d0(i32 %val, i32 %numlowbits) nounwind { | |
| ; X86-NOBMI-LABEL: bzhi32_d0: | |
| ; X86-NOBMI: # %bb.0: | |
| ; X86-NOBMI-NEXT: movl {{[0-9]+}}(%esp), %eax | |
| ; X86-NOBMI-NEXT: xorl %ecx, %ecx | |
| ; X86-NOBMI-NEXT: subb {{[0-9]+}}(%esp), %cl | |
| ; X86-NOBMI-NEXT: shll %cl, %eax | |
| ; X86-NOBMI-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X86-NOBMI-NEXT: shrl %cl, %eax | |
| ; X86-NOBMI-NEXT: retl | |
| ; | |
| ; X86-BMI1-LABEL: bzhi32_d0: | |
| ; X86-BMI1: # %bb.0: | |
| ; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: shll $8, %eax | |
| ; X86-BMI1-NEXT: bextrl %eax, {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: retl | |
| ; | |
| ; X86-BMI2-LABEL: bzhi32_d0: | |
| ; X86-BMI2: # %bb.0: | |
| ; X86-BMI2-NEXT: movzbl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: bzhil %eax, {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: retl | |
| ; | |
| ; X64-NOBMI-LABEL: bzhi32_d0: | |
| ; X64-NOBMI: # %bb.0: | |
| ; X64-NOBMI-NEXT: movl %esi, %ecx | |
| ; X64-NOBMI-NEXT: movl %edi, %eax | |
| ; X64-NOBMI-NEXT: negb %cl | |
| ; X64-NOBMI-NEXT: shll %cl, %eax | |
| ; X64-NOBMI-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X64-NOBMI-NEXT: shrl %cl, %eax | |
| ; X64-NOBMI-NEXT: retq | |
| ; | |
| ; X64-BMI1-LABEL: bzhi32_d0: | |
| ; X64-BMI1: # %bb.0: | |
| ; X64-BMI1-NEXT: shll $8, %esi | |
| ; X64-BMI1-NEXT: bextrl %esi, %edi, %eax | |
| ; X64-BMI1-NEXT: retq | |
| ; | |
| ; X64-BMI2-LABEL: bzhi32_d0: | |
| ; X64-BMI2: # %bb.0: | |
| ; X64-BMI2-NEXT: bzhil %esi, %edi, %eax | |
| ; X64-BMI2-NEXT: retq | |
| %numhighbits = sub i32 32, %numlowbits | |
| %highbitscleared = shl i32 %val, %numhighbits | |
| %masked = lshr i32 %highbitscleared, %numhighbits | |
| ret i32 %masked | |
| } | |
| define i32 @bzhi32_d1_indexzext(i32 %val, i8 %numlowbits) nounwind { | |
| ; X86-NOBMI-LABEL: bzhi32_d1_indexzext: | |
| ; X86-NOBMI: # %bb.0: | |
| ; X86-NOBMI-NEXT: movl {{[0-9]+}}(%esp), %eax | |
| ; X86-NOBMI-NEXT: xorl %ecx, %ecx | |
| ; X86-NOBMI-NEXT: subb {{[0-9]+}}(%esp), %cl | |
| ; X86-NOBMI-NEXT: shll %cl, %eax | |
| ; X86-NOBMI-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X86-NOBMI-NEXT: shrl %cl, %eax | |
| ; X86-NOBMI-NEXT: retl | |
| ; | |
| ; X86-BMI1-LABEL: bzhi32_d1_indexzext: | |
| ; X86-BMI1: # %bb.0: | |
| ; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: shll $8, %eax | |
| ; X86-BMI1-NEXT: bextrl %eax, {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: retl | |
| ; | |
| ; X86-BMI2-LABEL: bzhi32_d1_indexzext: | |
| ; X86-BMI2: # %bb.0: | |
| ; X86-BMI2-NEXT: movzbl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: bzhil %eax, {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: retl | |
| ; | |
| ; X64-NOBMI-LABEL: bzhi32_d1_indexzext: | |
| ; X64-NOBMI: # %bb.0: | |
| ; X64-NOBMI-NEXT: movl %esi, %ecx | |
| ; X64-NOBMI-NEXT: movl %edi, %eax | |
| ; X64-NOBMI-NEXT: negb %cl | |
| ; X64-NOBMI-NEXT: shll %cl, %eax | |
| ; X64-NOBMI-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X64-NOBMI-NEXT: shrl %cl, %eax | |
| ; X64-NOBMI-NEXT: retq | |
| ; | |
| ; X64-BMI1-LABEL: bzhi32_d1_indexzext: | |
| ; X64-BMI1: # %bb.0: | |
| ; X64-BMI1-NEXT: shll $8, %esi | |
| ; X64-BMI1-NEXT: bextrl %esi, %edi, %eax | |
| ; X64-BMI1-NEXT: retq | |
| ; | |
| ; X64-BMI2-LABEL: bzhi32_d1_indexzext: | |
| ; X64-BMI2: # %bb.0: | |
| ; X64-BMI2-NEXT: bzhil %esi, %edi, %eax | |
| ; X64-BMI2-NEXT: retq | |
| %numhighbits = sub i8 32, %numlowbits | |
| %sh_prom = zext i8 %numhighbits to i32 | |
| %highbitscleared = shl i32 %val, %sh_prom | |
| %masked = lshr i32 %highbitscleared, %sh_prom | |
| ret i32 %masked | |
| } | |
| define i32 @bzhi32_d2_load(ptr %w, i32 %numlowbits) nounwind { | |
| ; X86-NOBMI-LABEL: bzhi32_d2_load: | |
| ; X86-NOBMI: # %bb.0: | |
| ; X86-NOBMI-NEXT: movl {{[0-9]+}}(%esp), %eax | |
| ; X86-NOBMI-NEXT: movl (%eax), %eax | |
| ; X86-NOBMI-NEXT: xorl %ecx, %ecx | |
| ; X86-NOBMI-NEXT: subb {{[0-9]+}}(%esp), %cl | |
| ; X86-NOBMI-NEXT: shll %cl, %eax | |
| ; X86-NOBMI-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X86-NOBMI-NEXT: shrl %cl, %eax | |
| ; X86-NOBMI-NEXT: retl | |
| ; | |
| ; X86-BMI1-LABEL: bzhi32_d2_load: | |
| ; X86-BMI1: # %bb.0: | |
| ; X86-BMI1-NEXT: movl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-BMI1-NEXT: shll $8, %ecx | |
| ; X86-BMI1-NEXT: bextrl %ecx, (%eax), %eax | |
| ; X86-BMI1-NEXT: retl | |
| ; | |
| ; X86-BMI2-LABEL: bzhi32_d2_load: | |
| ; X86-BMI2: # %bb.0: | |
| ; X86-BMI2-NEXT: movl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-BMI2-NEXT: bzhil %ecx, (%eax), %eax | |
| ; X86-BMI2-NEXT: retl | |
| ; | |
| ; X64-NOBMI-LABEL: bzhi32_d2_load: | |
| ; X64-NOBMI: # %bb.0: | |
| ; X64-NOBMI-NEXT: movl %esi, %ecx | |
| ; X64-NOBMI-NEXT: movl (%rdi), %eax | |
| ; X64-NOBMI-NEXT: negb %cl | |
| ; X64-NOBMI-NEXT: shll %cl, %eax | |
| ; X64-NOBMI-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X64-NOBMI-NEXT: shrl %cl, %eax | |
| ; X64-NOBMI-NEXT: retq | |
| ; | |
| ; X64-BMI1-LABEL: bzhi32_d2_load: | |
| ; X64-BMI1: # %bb.0: | |
| ; X64-BMI1-NEXT: shll $8, %esi | |
| ; X64-BMI1-NEXT: bextrl %esi, (%rdi), %eax | |
| ; X64-BMI1-NEXT: retq | |
| ; | |
| ; X64-BMI2-LABEL: bzhi32_d2_load: | |
| ; X64-BMI2: # %bb.0: | |
| ; X64-BMI2-NEXT: bzhil %esi, (%rdi), %eax | |
| ; X64-BMI2-NEXT: retq | |
| %val = load i32, ptr %w | |
| %numhighbits = sub i32 32, %numlowbits | |
| %highbitscleared = shl i32 %val, %numhighbits | |
| %masked = lshr i32 %highbitscleared, %numhighbits | |
| ret i32 %masked | |
| } | |
| define i32 @bzhi32_d3_load_indexzext(ptr %w, i8 %numlowbits) nounwind { | |
| ; X86-NOBMI-LABEL: bzhi32_d3_load_indexzext: | |
| ; X86-NOBMI: # %bb.0: | |
| ; X86-NOBMI-NEXT: movl {{[0-9]+}}(%esp), %eax | |
| ; X86-NOBMI-NEXT: movl (%eax), %eax | |
| ; X86-NOBMI-NEXT: xorl %ecx, %ecx | |
| ; X86-NOBMI-NEXT: subb {{[0-9]+}}(%esp), %cl | |
| ; X86-NOBMI-NEXT: shll %cl, %eax | |
| ; X86-NOBMI-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X86-NOBMI-NEXT: shrl %cl, %eax | |
| ; X86-NOBMI-NEXT: retl | |
| ; | |
| ; X86-BMI1-LABEL: bzhi32_d3_load_indexzext: | |
| ; X86-BMI1: # %bb.0: | |
| ; X86-BMI1-NEXT: movl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-BMI1-NEXT: shll $8, %ecx | |
| ; X86-BMI1-NEXT: bextrl %ecx, (%eax), %eax | |
| ; X86-BMI1-NEXT: retl | |
| ; | |
| ; X86-BMI2-LABEL: bzhi32_d3_load_indexzext: | |
| ; X86-BMI2: # %bb.0: | |
| ; X86-BMI2-NEXT: movl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-BMI2-NEXT: bzhil %ecx, (%eax), %eax | |
| ; X86-BMI2-NEXT: retl | |
| ; | |
| ; X64-NOBMI-LABEL: bzhi32_d3_load_indexzext: | |
| ; X64-NOBMI: # %bb.0: | |
| ; X64-NOBMI-NEXT: movl %esi, %ecx | |
| ; X64-NOBMI-NEXT: movl (%rdi), %eax | |
| ; X64-NOBMI-NEXT: negb %cl | |
| ; X64-NOBMI-NEXT: shll %cl, %eax | |
| ; X64-NOBMI-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X64-NOBMI-NEXT: shrl %cl, %eax | |
| ; X64-NOBMI-NEXT: retq | |
| ; | |
| ; X64-BMI1-LABEL: bzhi32_d3_load_indexzext: | |
| ; X64-BMI1: # %bb.0: | |
| ; X64-BMI1-NEXT: shll $8, %esi | |
| ; X64-BMI1-NEXT: bextrl %esi, (%rdi), %eax | |
| ; X64-BMI1-NEXT: retq | |
| ; | |
| ; X64-BMI2-LABEL: bzhi32_d3_load_indexzext: | |
| ; X64-BMI2: # %bb.0: | |
| ; X64-BMI2-NEXT: bzhil %esi, (%rdi), %eax | |
| ; X64-BMI2-NEXT: retq | |
| %val = load i32, ptr %w | |
| %numhighbits = sub i8 32, %numlowbits | |
| %sh_prom = zext i8 %numhighbits to i32 | |
| %highbitscleared = shl i32 %val, %sh_prom | |
| %masked = lshr i32 %highbitscleared, %sh_prom | |
| ret i32 %masked | |
| } | |
| ; 64-bit. | |
| define i64 @bzhi64_d0(i64 %val, i64 %numlowbits) nounwind { | |
| ; X86-NOBMI-LABEL: bzhi64_d0: | |
| ; X86-NOBMI: # %bb.0: | |
| ; X86-NOBMI-NEXT: pushl %ebx | |
| ; X86-NOBMI-NEXT: pushl %edi | |
| ; X86-NOBMI-NEXT: pushl %esi | |
| ; X86-NOBMI-NEXT: movl {{[0-9]+}}(%esp), %edx | |
| ; X86-NOBMI-NEXT: movl {{[0-9]+}}(%esp), %eax | |
| ; X86-NOBMI-NEXT: movb $64, %cl | |
| ; X86-NOBMI-NEXT: subb {{[0-9]+}}(%esp), %cl | |
| ; X86-NOBMI-NEXT: movl %edx, %edi | |
| ; X86-NOBMI-NEXT: shll %cl, %edi | |
| ; X86-NOBMI-NEXT: shldl %cl, %edx, %eax | |
| ; X86-NOBMI-NEXT: testb $32, %cl | |
| ; X86-NOBMI-NEXT: movl %edi, %esi | |
| ; X86-NOBMI-NEXT: jne .LBB48_2 | |
| ; X86-NOBMI-NEXT: # %bb.1: | |
| ; X86-NOBMI-NEXT: movl %eax, %esi | |
| ; X86-NOBMI-NEXT: .LBB48_2: | |
| ; X86-NOBMI-NEXT: movl %esi, %eax | |
| ; X86-NOBMI-NEXT: shrl %cl, %eax | |
| ; X86-NOBMI-NEXT: xorl %ebx, %ebx | |
| ; X86-NOBMI-NEXT: testb $32, %cl | |
| ; X86-NOBMI-NEXT: movl $0, %edx | |
| ; X86-NOBMI-NEXT: jne .LBB48_4 | |
| ; X86-NOBMI-NEXT: # %bb.3: | |
| ; X86-NOBMI-NEXT: movl %edi, %ebx | |
| ; X86-NOBMI-NEXT: movl %eax, %edx | |
| ; X86-NOBMI-NEXT: .LBB48_4: | |
| ; X86-NOBMI-NEXT: shrdl %cl, %esi, %ebx | |
| ; X86-NOBMI-NEXT: testb $32, %cl | |
| ; X86-NOBMI-NEXT: jne .LBB48_6 | |
| ; X86-NOBMI-NEXT: # %bb.5: | |
| ; X86-NOBMI-NEXT: movl %ebx, %eax | |
| ; X86-NOBMI-NEXT: .LBB48_6: | |
| ; X86-NOBMI-NEXT: popl %esi | |
| ; X86-NOBMI-NEXT: popl %edi | |
| ; X86-NOBMI-NEXT: popl %ebx | |
| ; X86-NOBMI-NEXT: retl | |
| ; | |
| ; X86-BMI1-LABEL: bzhi64_d0: | |
| ; X86-BMI1: # %bb.0: | |
| ; X86-BMI1-NEXT: pushl %ebx | |
| ; X86-BMI1-NEXT: pushl %edi | |
| ; X86-BMI1-NEXT: pushl %esi | |
| ; X86-BMI1-NEXT: movl {{[0-9]+}}(%esp), %edx | |
| ; X86-BMI1-NEXT: movl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: movb $64, %cl | |
| ; X86-BMI1-NEXT: subb {{[0-9]+}}(%esp), %cl | |
| ; X86-BMI1-NEXT: movl %edx, %edi | |
| ; X86-BMI1-NEXT: shll %cl, %edi | |
| ; X86-BMI1-NEXT: shldl %cl, %edx, %eax | |
| ; X86-BMI1-NEXT: testb $32, %cl | |
| ; X86-BMI1-NEXT: movl %edi, %esi | |
| ; X86-BMI1-NEXT: jne .LBB48_2 | |
| ; X86-BMI1-NEXT: # %bb.1: | |
| ; X86-BMI1-NEXT: movl %eax, %esi | |
| ; X86-BMI1-NEXT: .LBB48_2: | |
| ; X86-BMI1-NEXT: movl %esi, %eax | |
| ; X86-BMI1-NEXT: shrl %cl, %eax | |
| ; X86-BMI1-NEXT: xorl %ebx, %ebx | |
| ; X86-BMI1-NEXT: testb $32, %cl | |
| ; X86-BMI1-NEXT: movl $0, %edx | |
| ; X86-BMI1-NEXT: jne .LBB48_4 | |
| ; X86-BMI1-NEXT: # %bb.3: | |
| ; X86-BMI1-NEXT: movl %edi, %ebx | |
| ; X86-BMI1-NEXT: movl %eax, %edx | |
| ; X86-BMI1-NEXT: .LBB48_4: | |
| ; X86-BMI1-NEXT: shrdl %cl, %esi, %ebx | |
| ; X86-BMI1-NEXT: testb $32, %cl | |
| ; X86-BMI1-NEXT: jne .LBB48_6 | |
| ; X86-BMI1-NEXT: # %bb.5: | |
| ; X86-BMI1-NEXT: movl %ebx, %eax | |
| ; X86-BMI1-NEXT: .LBB48_6: | |
| ; X86-BMI1-NEXT: popl %esi | |
| ; X86-BMI1-NEXT: popl %edi | |
| ; X86-BMI1-NEXT: popl %ebx | |
| ; X86-BMI1-NEXT: retl | |
| ; | |
| ; X86-BMI2-LABEL: bzhi64_d0: | |
| ; X86-BMI2: # %bb.0: | |
| ; X86-BMI2-NEXT: pushl %edi | |
| ; X86-BMI2-NEXT: pushl %esi | |
| ; X86-BMI2-NEXT: movl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: movl {{[0-9]+}}(%esp), %esi | |
| ; X86-BMI2-NEXT: movb $64, %cl | |
| ; X86-BMI2-NEXT: subb {{[0-9]+}}(%esp), %cl | |
| ; X86-BMI2-NEXT: shldl %cl, %eax, %esi | |
| ; X86-BMI2-NEXT: shlxl %ecx, %eax, %edi | |
| ; X86-BMI2-NEXT: xorl %edx, %edx | |
| ; X86-BMI2-NEXT: testb $32, %cl | |
| ; X86-BMI2-NEXT: je .LBB48_2 | |
| ; X86-BMI2-NEXT: # %bb.1: | |
| ; X86-BMI2-NEXT: movl %edi, %esi | |
| ; X86-BMI2-NEXT: movl $0, %edi | |
| ; X86-BMI2-NEXT: .LBB48_2: | |
| ; X86-BMI2-NEXT: shrxl %ecx, %esi, %eax | |
| ; X86-BMI2-NEXT: jne .LBB48_4 | |
| ; X86-BMI2-NEXT: # %bb.3: | |
| ; X86-BMI2-NEXT: movl %eax, %edx | |
| ; X86-BMI2-NEXT: .LBB48_4: | |
| ; X86-BMI2-NEXT: shrdl %cl, %esi, %edi | |
| ; X86-BMI2-NEXT: testb $32, %cl | |
| ; X86-BMI2-NEXT: jne .LBB48_6 | |
| ; X86-BMI2-NEXT: # %bb.5: | |
| ; X86-BMI2-NEXT: movl %edi, %eax | |
| ; X86-BMI2-NEXT: .LBB48_6: | |
| ; X86-BMI2-NEXT: popl %esi | |
| ; X86-BMI2-NEXT: popl %edi | |
| ; X86-BMI2-NEXT: retl | |
| ; | |
| ; X64-NOBMI-LABEL: bzhi64_d0: | |
| ; X64-NOBMI: # %bb.0: | |
| ; X64-NOBMI-NEXT: movq %rsi, %rcx | |
| ; X64-NOBMI-NEXT: movq %rdi, %rax | |
| ; X64-NOBMI-NEXT: negb %cl | |
| ; X64-NOBMI-NEXT: shlq %cl, %rax | |
| ; X64-NOBMI-NEXT: # kill: def $cl killed $cl killed $rcx | |
| ; X64-NOBMI-NEXT: shrq %cl, %rax | |
| ; X64-NOBMI-NEXT: retq | |
| ; | |
| ; X64-BMI1-LABEL: bzhi64_d0: | |
| ; X64-BMI1: # %bb.0: | |
| ; X64-BMI1-NEXT: shll $8, %esi | |
| ; X64-BMI1-NEXT: bextrq %rsi, %rdi, %rax | |
| ; X64-BMI1-NEXT: retq | |
| ; | |
| ; X64-BMI2-LABEL: bzhi64_d0: | |
| ; X64-BMI2: # %bb.0: | |
| ; X64-BMI2-NEXT: bzhiq %rsi, %rdi, %rax | |
| ; X64-BMI2-NEXT: retq | |
| %numhighbits = sub i64 64, %numlowbits | |
| %highbitscleared = shl i64 %val, %numhighbits | |
| %masked = lshr i64 %highbitscleared, %numhighbits | |
| ret i64 %masked | |
| } | |
| define i64 @bzhi64_d1_indexzext(i64 %val, i8 %numlowbits) nounwind { | |
| ; X86-NOBMI-LABEL: bzhi64_d1_indexzext: | |
| ; X86-NOBMI: # %bb.0: | |
| ; X86-NOBMI-NEXT: pushl %ebx | |
| ; X86-NOBMI-NEXT: pushl %edi | |
| ; X86-NOBMI-NEXT: pushl %esi | |
| ; X86-NOBMI-NEXT: movl {{[0-9]+}}(%esp), %edx | |
| ; X86-NOBMI-NEXT: movl {{[0-9]+}}(%esp), %eax | |
| ; X86-NOBMI-NEXT: movb $64, %cl | |
| ; X86-NOBMI-NEXT: subb {{[0-9]+}}(%esp), %cl | |
| ; X86-NOBMI-NEXT: movl %edx, %edi | |
| ; X86-NOBMI-NEXT: shll %cl, %edi | |
| ; X86-NOBMI-NEXT: shldl %cl, %edx, %eax | |
| ; X86-NOBMI-NEXT: testb $32, %cl | |
| ; X86-NOBMI-NEXT: movl %edi, %esi | |
| ; X86-NOBMI-NEXT: jne .LBB49_2 | |
| ; X86-NOBMI-NEXT: # %bb.1: | |
| ; X86-NOBMI-NEXT: movl %eax, %esi | |
| ; X86-NOBMI-NEXT: .LBB49_2: | |
| ; X86-NOBMI-NEXT: movl %esi, %eax | |
| ; X86-NOBMI-NEXT: shrl %cl, %eax | |
| ; X86-NOBMI-NEXT: xorl %ebx, %ebx | |
| ; X86-NOBMI-NEXT: testb $32, %cl | |
| ; X86-NOBMI-NEXT: movl $0, %edx | |
| ; X86-NOBMI-NEXT: jne .LBB49_4 | |
| ; X86-NOBMI-NEXT: # %bb.3: | |
| ; X86-NOBMI-NEXT: movl %edi, %ebx | |
| ; X86-NOBMI-NEXT: movl %eax, %edx | |
| ; X86-NOBMI-NEXT: .LBB49_4: | |
| ; X86-NOBMI-NEXT: shrdl %cl, %esi, %ebx | |
| ; X86-NOBMI-NEXT: testb $32, %cl | |
| ; X86-NOBMI-NEXT: jne .LBB49_6 | |
| ; X86-NOBMI-NEXT: # %bb.5: | |
| ; X86-NOBMI-NEXT: movl %ebx, %eax | |
| ; X86-NOBMI-NEXT: .LBB49_6: | |
| ; X86-NOBMI-NEXT: popl %esi | |
| ; X86-NOBMI-NEXT: popl %edi | |
| ; X86-NOBMI-NEXT: popl %ebx | |
| ; X86-NOBMI-NEXT: retl | |
| ; | |
| ; X86-BMI1-LABEL: bzhi64_d1_indexzext: | |
| ; X86-BMI1: # %bb.0: | |
| ; X86-BMI1-NEXT: pushl %ebx | |
| ; X86-BMI1-NEXT: pushl %edi | |
| ; X86-BMI1-NEXT: pushl %esi | |
| ; X86-BMI1-NEXT: movl {{[0-9]+}}(%esp), %edx | |
| ; X86-BMI1-NEXT: movl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: movb $64, %cl | |
| ; X86-BMI1-NEXT: subb {{[0-9]+}}(%esp), %cl | |
| ; X86-BMI1-NEXT: movl %edx, %edi | |
| ; X86-BMI1-NEXT: shll %cl, %edi | |
| ; X86-BMI1-NEXT: shldl %cl, %edx, %eax | |
| ; X86-BMI1-NEXT: testb $32, %cl | |
| ; X86-BMI1-NEXT: movl %edi, %esi | |
| ; X86-BMI1-NEXT: jne .LBB49_2 | |
| ; X86-BMI1-NEXT: # %bb.1: | |
| ; X86-BMI1-NEXT: movl %eax, %esi | |
| ; X86-BMI1-NEXT: .LBB49_2: | |
| ; X86-BMI1-NEXT: movl %esi, %eax | |
| ; X86-BMI1-NEXT: shrl %cl, %eax | |
| ; X86-BMI1-NEXT: xorl %ebx, %ebx | |
| ; X86-BMI1-NEXT: testb $32, %cl | |
| ; X86-BMI1-NEXT: movl $0, %edx | |
| ; X86-BMI1-NEXT: jne .LBB49_4 | |
| ; X86-BMI1-NEXT: # %bb.3: | |
| ; X86-BMI1-NEXT: movl %edi, %ebx | |
| ; X86-BMI1-NEXT: movl %eax, %edx | |
| ; X86-BMI1-NEXT: .LBB49_4: | |
| ; X86-BMI1-NEXT: shrdl %cl, %esi, %ebx | |
| ; X86-BMI1-NEXT: testb $32, %cl | |
| ; X86-BMI1-NEXT: jne .LBB49_6 | |
| ; X86-BMI1-NEXT: # %bb.5: | |
| ; X86-BMI1-NEXT: movl %ebx, %eax | |
| ; X86-BMI1-NEXT: .LBB49_6: | |
| ; X86-BMI1-NEXT: popl %esi | |
| ; X86-BMI1-NEXT: popl %edi | |
| ; X86-BMI1-NEXT: popl %ebx | |
| ; X86-BMI1-NEXT: retl | |
| ; | |
| ; X86-BMI2-LABEL: bzhi64_d1_indexzext: | |
| ; X86-BMI2: # %bb.0: | |
| ; X86-BMI2-NEXT: pushl %edi | |
| ; X86-BMI2-NEXT: pushl %esi | |
| ; X86-BMI2-NEXT: movl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: movl {{[0-9]+}}(%esp), %esi | |
| ; X86-BMI2-NEXT: movb $64, %cl | |
| ; X86-BMI2-NEXT: subb {{[0-9]+}}(%esp), %cl | |
| ; X86-BMI2-NEXT: shldl %cl, %eax, %esi | |
| ; X86-BMI2-NEXT: shlxl %ecx, %eax, %edi | |
| ; X86-BMI2-NEXT: xorl %edx, %edx | |
| ; X86-BMI2-NEXT: testb $32, %cl | |
| ; X86-BMI2-NEXT: je .LBB49_2 | |
| ; X86-BMI2-NEXT: # %bb.1: | |
| ; X86-BMI2-NEXT: movl %edi, %esi | |
| ; X86-BMI2-NEXT: movl $0, %edi | |
| ; X86-BMI2-NEXT: .LBB49_2: | |
| ; X86-BMI2-NEXT: shrxl %ecx, %esi, %eax | |
| ; X86-BMI2-NEXT: jne .LBB49_4 | |
| ; X86-BMI2-NEXT: # %bb.3: | |
| ; X86-BMI2-NEXT: movl %eax, %edx | |
| ; X86-BMI2-NEXT: .LBB49_4: | |
| ; X86-BMI2-NEXT: shrdl %cl, %esi, %edi | |
| ; X86-BMI2-NEXT: testb $32, %cl | |
| ; X86-BMI2-NEXT: jne .LBB49_6 | |
| ; X86-BMI2-NEXT: # %bb.5: | |
| ; X86-BMI2-NEXT: movl %edi, %eax | |
| ; X86-BMI2-NEXT: .LBB49_6: | |
| ; X86-BMI2-NEXT: popl %esi | |
| ; X86-BMI2-NEXT: popl %edi | |
| ; X86-BMI2-NEXT: retl | |
| ; | |
| ; X64-NOBMI-LABEL: bzhi64_d1_indexzext: | |
| ; X64-NOBMI: # %bb.0: | |
| ; X64-NOBMI-NEXT: movl %esi, %ecx | |
| ; X64-NOBMI-NEXT: movq %rdi, %rax | |
| ; X64-NOBMI-NEXT: negb %cl | |
| ; X64-NOBMI-NEXT: shlq %cl, %rax | |
| ; X64-NOBMI-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X64-NOBMI-NEXT: shrq %cl, %rax | |
| ; X64-NOBMI-NEXT: retq | |
| ; | |
| ; X64-BMI1-LABEL: bzhi64_d1_indexzext: | |
| ; X64-BMI1: # %bb.0: | |
| ; X64-BMI1-NEXT: # kill: def $esi killed $esi def $rsi | |
| ; X64-BMI1-NEXT: shll $8, %esi | |
| ; X64-BMI1-NEXT: bextrq %rsi, %rdi, %rax | |
| ; X64-BMI1-NEXT: retq | |
| ; | |
| ; X64-BMI2-LABEL: bzhi64_d1_indexzext: | |
| ; X64-BMI2: # %bb.0: | |
| ; X64-BMI2-NEXT: # kill: def $esi killed $esi def $rsi | |
| ; X64-BMI2-NEXT: bzhiq %rsi, %rdi, %rax | |
| ; X64-BMI2-NEXT: retq | |
| %numhighbits = sub i8 64, %numlowbits | |
| %sh_prom = zext i8 %numhighbits to i64 | |
| %highbitscleared = shl i64 %val, %sh_prom | |
| %masked = lshr i64 %highbitscleared, %sh_prom | |
| ret i64 %masked | |
| } | |
| define i64 @bzhi64_d2_load(ptr %w, i64 %numlowbits) nounwind { | |
| ; X86-NOBMI-LABEL: bzhi64_d2_load: | |
| ; X86-NOBMI: # %bb.0: | |
| ; X86-NOBMI-NEXT: pushl %ebx | |
| ; X86-NOBMI-NEXT: pushl %edi | |
| ; X86-NOBMI-NEXT: pushl %esi | |
| ; X86-NOBMI-NEXT: movl {{[0-9]+}}(%esp), %eax | |
| ; X86-NOBMI-NEXT: movl (%eax), %edx | |
| ; X86-NOBMI-NEXT: movl 4(%eax), %eax | |
| ; X86-NOBMI-NEXT: movb $64, %cl | |
| ; X86-NOBMI-NEXT: subb {{[0-9]+}}(%esp), %cl | |
| ; X86-NOBMI-NEXT: movl %edx, %edi | |
| ; X86-NOBMI-NEXT: shll %cl, %edi | |
| ; X86-NOBMI-NEXT: shldl %cl, %edx, %eax | |
| ; X86-NOBMI-NEXT: testb $32, %cl | |
| ; X86-NOBMI-NEXT: movl %edi, %esi | |
| ; X86-NOBMI-NEXT: jne .LBB50_2 | |
| ; X86-NOBMI-NEXT: # %bb.1: | |
| ; X86-NOBMI-NEXT: movl %eax, %esi | |
| ; X86-NOBMI-NEXT: .LBB50_2: | |
| ; X86-NOBMI-NEXT: movl %esi, %eax | |
| ; X86-NOBMI-NEXT: shrl %cl, %eax | |
| ; X86-NOBMI-NEXT: xorl %ebx, %ebx | |
| ; X86-NOBMI-NEXT: testb $32, %cl | |
| ; X86-NOBMI-NEXT: movl $0, %edx | |
| ; X86-NOBMI-NEXT: jne .LBB50_4 | |
| ; X86-NOBMI-NEXT: # %bb.3: | |
| ; X86-NOBMI-NEXT: movl %edi, %ebx | |
| ; X86-NOBMI-NEXT: movl %eax, %edx | |
| ; X86-NOBMI-NEXT: .LBB50_4: | |
| ; X86-NOBMI-NEXT: shrdl %cl, %esi, %ebx | |
| ; X86-NOBMI-NEXT: testb $32, %cl | |
| ; X86-NOBMI-NEXT: jne .LBB50_6 | |
| ; X86-NOBMI-NEXT: # %bb.5: | |
| ; X86-NOBMI-NEXT: movl %ebx, %eax | |
| ; X86-NOBMI-NEXT: .LBB50_6: | |
| ; X86-NOBMI-NEXT: popl %esi | |
| ; X86-NOBMI-NEXT: popl %edi | |
| ; X86-NOBMI-NEXT: popl %ebx | |
| ; X86-NOBMI-NEXT: retl | |
| ; | |
| ; X86-BMI1-LABEL: bzhi64_d2_load: | |
| ; X86-BMI1: # %bb.0: | |
| ; X86-BMI1-NEXT: pushl %ebx | |
| ; X86-BMI1-NEXT: pushl %edi | |
| ; X86-BMI1-NEXT: pushl %esi | |
| ; X86-BMI1-NEXT: movl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: movl (%eax), %edx | |
| ; X86-BMI1-NEXT: movl 4(%eax), %eax | |
| ; X86-BMI1-NEXT: movb $64, %cl | |
| ; X86-BMI1-NEXT: subb {{[0-9]+}}(%esp), %cl | |
| ; X86-BMI1-NEXT: movl %edx, %edi | |
| ; X86-BMI1-NEXT: shll %cl, %edi | |
| ; X86-BMI1-NEXT: shldl %cl, %edx, %eax | |
| ; X86-BMI1-NEXT: testb $32, %cl | |
| ; X86-BMI1-NEXT: movl %edi, %esi | |
| ; X86-BMI1-NEXT: jne .LBB50_2 | |
| ; X86-BMI1-NEXT: # %bb.1: | |
| ; X86-BMI1-NEXT: movl %eax, %esi | |
| ; X86-BMI1-NEXT: .LBB50_2: | |
| ; X86-BMI1-NEXT: movl %esi, %eax | |
| ; X86-BMI1-NEXT: shrl %cl, %eax | |
| ; X86-BMI1-NEXT: xorl %ebx, %ebx | |
| ; X86-BMI1-NEXT: testb $32, %cl | |
| ; X86-BMI1-NEXT: movl $0, %edx | |
| ; X86-BMI1-NEXT: jne .LBB50_4 | |
| ; X86-BMI1-NEXT: # %bb.3: | |
| ; X86-BMI1-NEXT: movl %edi, %ebx | |
| ; X86-BMI1-NEXT: movl %eax, %edx | |
| ; X86-BMI1-NEXT: .LBB50_4: | |
| ; X86-BMI1-NEXT: shrdl %cl, %esi, %ebx | |
| ; X86-BMI1-NEXT: testb $32, %cl | |
| ; X86-BMI1-NEXT: jne .LBB50_6 | |
| ; X86-BMI1-NEXT: # %bb.5: | |
| ; X86-BMI1-NEXT: movl %ebx, %eax | |
| ; X86-BMI1-NEXT: .LBB50_6: | |
| ; X86-BMI1-NEXT: popl %esi | |
| ; X86-BMI1-NEXT: popl %edi | |
| ; X86-BMI1-NEXT: popl %ebx | |
| ; X86-BMI1-NEXT: retl | |
| ; | |
| ; X86-BMI2-LABEL: bzhi64_d2_load: | |
| ; X86-BMI2: # %bb.0: | |
| ; X86-BMI2-NEXT: pushl %edi | |
| ; X86-BMI2-NEXT: pushl %esi | |
| ; X86-BMI2-NEXT: movl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: movl (%eax), %edx | |
| ; X86-BMI2-NEXT: movl 4(%eax), %esi | |
| ; X86-BMI2-NEXT: movb $64, %cl | |
| ; X86-BMI2-NEXT: subb {{[0-9]+}}(%esp), %cl | |
| ; X86-BMI2-NEXT: shldl %cl, %edx, %esi | |
| ; X86-BMI2-NEXT: shlxl %ecx, %edx, %edi | |
| ; X86-BMI2-NEXT: xorl %edx, %edx | |
| ; X86-BMI2-NEXT: testb $32, %cl | |
| ; X86-BMI2-NEXT: je .LBB50_2 | |
| ; X86-BMI2-NEXT: # %bb.1: | |
| ; X86-BMI2-NEXT: movl %edi, %esi | |
| ; X86-BMI2-NEXT: movl $0, %edi | |
| ; X86-BMI2-NEXT: .LBB50_2: | |
| ; X86-BMI2-NEXT: shrxl %ecx, %esi, %eax | |
| ; X86-BMI2-NEXT: jne .LBB50_4 | |
| ; X86-BMI2-NEXT: # %bb.3: | |
| ; X86-BMI2-NEXT: movl %eax, %edx | |
| ; X86-BMI2-NEXT: .LBB50_4: | |
| ; X86-BMI2-NEXT: shrdl %cl, %esi, %edi | |
| ; X86-BMI2-NEXT: testb $32, %cl | |
| ; X86-BMI2-NEXT: jne .LBB50_6 | |
| ; X86-BMI2-NEXT: # %bb.5: | |
| ; X86-BMI2-NEXT: movl %edi, %eax | |
| ; X86-BMI2-NEXT: .LBB50_6: | |
| ; X86-BMI2-NEXT: popl %esi | |
| ; X86-BMI2-NEXT: popl %edi | |
| ; X86-BMI2-NEXT: retl | |
| ; | |
| ; X64-NOBMI-LABEL: bzhi64_d2_load: | |
| ; X64-NOBMI: # %bb.0: | |
| ; X64-NOBMI-NEXT: movq %rsi, %rcx | |
| ; X64-NOBMI-NEXT: movq (%rdi), %rax | |
| ; X64-NOBMI-NEXT: negb %cl | |
| ; X64-NOBMI-NEXT: shlq %cl, %rax | |
| ; X64-NOBMI-NEXT: # kill: def $cl killed $cl killed $rcx | |
| ; X64-NOBMI-NEXT: shrq %cl, %rax | |
| ; X64-NOBMI-NEXT: retq | |
| ; | |
| ; X64-BMI1-LABEL: bzhi64_d2_load: | |
| ; X64-BMI1: # %bb.0: | |
| ; X64-BMI1-NEXT: shll $8, %esi | |
| ; X64-BMI1-NEXT: bextrq %rsi, (%rdi), %rax | |
| ; X64-BMI1-NEXT: retq | |
| ; | |
| ; X64-BMI2-LABEL: bzhi64_d2_load: | |
| ; X64-BMI2: # %bb.0: | |
| ; X64-BMI2-NEXT: bzhiq %rsi, (%rdi), %rax | |
| ; X64-BMI2-NEXT: retq | |
| %val = load i64, ptr %w | |
| %numhighbits = sub i64 64, %numlowbits | |
| %highbitscleared = shl i64 %val, %numhighbits | |
| %masked = lshr i64 %highbitscleared, %numhighbits | |
| ret i64 %masked | |
| } | |
| define i64 @bzhi64_d3_load_indexzext(ptr %w, i8 %numlowbits) nounwind { | |
| ; X86-NOBMI-LABEL: bzhi64_d3_load_indexzext: | |
| ; X86-NOBMI: # %bb.0: | |
| ; X86-NOBMI-NEXT: pushl %ebx | |
| ; X86-NOBMI-NEXT: pushl %edi | |
| ; X86-NOBMI-NEXT: pushl %esi | |
| ; X86-NOBMI-NEXT: movl {{[0-9]+}}(%esp), %eax | |
| ; X86-NOBMI-NEXT: movl (%eax), %edx | |
| ; X86-NOBMI-NEXT: movl 4(%eax), %eax | |
| ; X86-NOBMI-NEXT: movb $64, %cl | |
| ; X86-NOBMI-NEXT: subb {{[0-9]+}}(%esp), %cl | |
| ; X86-NOBMI-NEXT: movl %edx, %edi | |
| ; X86-NOBMI-NEXT: shll %cl, %edi | |
| ; X86-NOBMI-NEXT: shldl %cl, %edx, %eax | |
| ; X86-NOBMI-NEXT: testb $32, %cl | |
| ; X86-NOBMI-NEXT: movl %edi, %esi | |
| ; X86-NOBMI-NEXT: jne .LBB51_2 | |
| ; X86-NOBMI-NEXT: # %bb.1: | |
| ; X86-NOBMI-NEXT: movl %eax, %esi | |
| ; X86-NOBMI-NEXT: .LBB51_2: | |
| ; X86-NOBMI-NEXT: movl %esi, %eax | |
| ; X86-NOBMI-NEXT: shrl %cl, %eax | |
| ; X86-NOBMI-NEXT: xorl %ebx, %ebx | |
| ; X86-NOBMI-NEXT: testb $32, %cl | |
| ; X86-NOBMI-NEXT: movl $0, %edx | |
| ; X86-NOBMI-NEXT: jne .LBB51_4 | |
| ; X86-NOBMI-NEXT: # %bb.3: | |
| ; X86-NOBMI-NEXT: movl %edi, %ebx | |
| ; X86-NOBMI-NEXT: movl %eax, %edx | |
| ; X86-NOBMI-NEXT: .LBB51_4: | |
| ; X86-NOBMI-NEXT: shrdl %cl, %esi, %ebx | |
| ; X86-NOBMI-NEXT: testb $32, %cl | |
| ; X86-NOBMI-NEXT: jne .LBB51_6 | |
| ; X86-NOBMI-NEXT: # %bb.5: | |
| ; X86-NOBMI-NEXT: movl %ebx, %eax | |
| ; X86-NOBMI-NEXT: .LBB51_6: | |
| ; X86-NOBMI-NEXT: popl %esi | |
| ; X86-NOBMI-NEXT: popl %edi | |
| ; X86-NOBMI-NEXT: popl %ebx | |
| ; X86-NOBMI-NEXT: retl | |
| ; | |
| ; X86-BMI1-LABEL: bzhi64_d3_load_indexzext: | |
| ; X86-BMI1: # %bb.0: | |
| ; X86-BMI1-NEXT: pushl %ebx | |
| ; X86-BMI1-NEXT: pushl %edi | |
| ; X86-BMI1-NEXT: pushl %esi | |
| ; X86-BMI1-NEXT: movl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: movl (%eax), %edx | |
| ; X86-BMI1-NEXT: movl 4(%eax), %eax | |
| ; X86-BMI1-NEXT: movb $64, %cl | |
| ; X86-BMI1-NEXT: subb {{[0-9]+}}(%esp), %cl | |
| ; X86-BMI1-NEXT: movl %edx, %edi | |
| ; X86-BMI1-NEXT: shll %cl, %edi | |
| ; X86-BMI1-NEXT: shldl %cl, %edx, %eax | |
| ; X86-BMI1-NEXT: testb $32, %cl | |
| ; X86-BMI1-NEXT: movl %edi, %esi | |
| ; X86-BMI1-NEXT: jne .LBB51_2 | |
| ; X86-BMI1-NEXT: # %bb.1: | |
| ; X86-BMI1-NEXT: movl %eax, %esi | |
| ; X86-BMI1-NEXT: .LBB51_2: | |
| ; X86-BMI1-NEXT: movl %esi, %eax | |
| ; X86-BMI1-NEXT: shrl %cl, %eax | |
| ; X86-BMI1-NEXT: xorl %ebx, %ebx | |
| ; X86-BMI1-NEXT: testb $32, %cl | |
| ; X86-BMI1-NEXT: movl $0, %edx | |
| ; X86-BMI1-NEXT: jne .LBB51_4 | |
| ; X86-BMI1-NEXT: # %bb.3: | |
| ; X86-BMI1-NEXT: movl %edi, %ebx | |
| ; X86-BMI1-NEXT: movl %eax, %edx | |
| ; X86-BMI1-NEXT: .LBB51_4: | |
| ; X86-BMI1-NEXT: shrdl %cl, %esi, %ebx | |
| ; X86-BMI1-NEXT: testb $32, %cl | |
| ; X86-BMI1-NEXT: jne .LBB51_6 | |
| ; X86-BMI1-NEXT: # %bb.5: | |
| ; X86-BMI1-NEXT: movl %ebx, %eax | |
| ; X86-BMI1-NEXT: .LBB51_6: | |
| ; X86-BMI1-NEXT: popl %esi | |
| ; X86-BMI1-NEXT: popl %edi | |
| ; X86-BMI1-NEXT: popl %ebx | |
| ; X86-BMI1-NEXT: retl | |
| ; | |
| ; X86-BMI2-LABEL: bzhi64_d3_load_indexzext: | |
| ; X86-BMI2: # %bb.0: | |
| ; X86-BMI2-NEXT: pushl %edi | |
| ; X86-BMI2-NEXT: pushl %esi | |
| ; X86-BMI2-NEXT: movl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: movl (%eax), %edx | |
| ; X86-BMI2-NEXT: movl 4(%eax), %esi | |
| ; X86-BMI2-NEXT: movb $64, %cl | |
| ; X86-BMI2-NEXT: subb {{[0-9]+}}(%esp), %cl | |
| ; X86-BMI2-NEXT: shldl %cl, %edx, %esi | |
| ; X86-BMI2-NEXT: shlxl %ecx, %edx, %edi | |
| ; X86-BMI2-NEXT: xorl %edx, %edx | |
| ; X86-BMI2-NEXT: testb $32, %cl | |
| ; X86-BMI2-NEXT: je .LBB51_2 | |
| ; X86-BMI2-NEXT: # %bb.1: | |
| ; X86-BMI2-NEXT: movl %edi, %esi | |
| ; X86-BMI2-NEXT: movl $0, %edi | |
| ; X86-BMI2-NEXT: .LBB51_2: | |
| ; X86-BMI2-NEXT: shrxl %ecx, %esi, %eax | |
| ; X86-BMI2-NEXT: jne .LBB51_4 | |
| ; X86-BMI2-NEXT: # %bb.3: | |
| ; X86-BMI2-NEXT: movl %eax, %edx | |
| ; X86-BMI2-NEXT: .LBB51_4: | |
| ; X86-BMI2-NEXT: shrdl %cl, %esi, %edi | |
| ; X86-BMI2-NEXT: testb $32, %cl | |
| ; X86-BMI2-NEXT: jne .LBB51_6 | |
| ; X86-BMI2-NEXT: # %bb.5: | |
| ; X86-BMI2-NEXT: movl %edi, %eax | |
| ; X86-BMI2-NEXT: .LBB51_6: | |
| ; X86-BMI2-NEXT: popl %esi | |
| ; X86-BMI2-NEXT: popl %edi | |
| ; X86-BMI2-NEXT: retl | |
| ; | |
| ; X64-NOBMI-LABEL: bzhi64_d3_load_indexzext: | |
| ; X64-NOBMI: # %bb.0: | |
| ; X64-NOBMI-NEXT: movl %esi, %ecx | |
| ; X64-NOBMI-NEXT: movq (%rdi), %rax | |
| ; X64-NOBMI-NEXT: negb %cl | |
| ; X64-NOBMI-NEXT: shlq %cl, %rax | |
| ; X64-NOBMI-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X64-NOBMI-NEXT: shrq %cl, %rax | |
| ; X64-NOBMI-NEXT: retq | |
| ; | |
| ; X64-BMI1-LABEL: bzhi64_d3_load_indexzext: | |
| ; X64-BMI1: # %bb.0: | |
| ; X64-BMI1-NEXT: # kill: def $esi killed $esi def $rsi | |
| ; X64-BMI1-NEXT: shll $8, %esi | |
| ; X64-BMI1-NEXT: bextrq %rsi, (%rdi), %rax | |
| ; X64-BMI1-NEXT: retq | |
| ; | |
| ; X64-BMI2-LABEL: bzhi64_d3_load_indexzext: | |
| ; X64-BMI2: # %bb.0: | |
| ; X64-BMI2-NEXT: # kill: def $esi killed $esi def $rsi | |
| ; X64-BMI2-NEXT: bzhiq %rsi, (%rdi), %rax | |
| ; X64-BMI2-NEXT: retq | |
| %val = load i64, ptr %w | |
| %numhighbits = sub i8 64, %numlowbits | |
| %sh_prom = zext i8 %numhighbits to i64 | |
| %highbitscleared = shl i64 %val, %sh_prom | |
| %masked = lshr i64 %highbitscleared, %sh_prom | |
| ret i64 %masked | |
| } | |
| ; 64-bit, but with 32-bit output | |
| ; Everything done in 64-bit, truncation happens last. | |
| define i32 @bzhi64_32_d0(i64 %val, i64 %numlowbits) nounwind { | |
| ; X86-NOBMI-LABEL: bzhi64_32_d0: | |
| ; X86-NOBMI: # %bb.0: | |
| ; X86-NOBMI-NEXT: pushl %esi | |
| ; X86-NOBMI-NEXT: movl {{[0-9]+}}(%esp), %esi | |
| ; X86-NOBMI-NEXT: movl {{[0-9]+}}(%esp), %eax | |
| ; X86-NOBMI-NEXT: movb $64, %cl | |
| ; X86-NOBMI-NEXT: subb {{[0-9]+}}(%esp), %cl | |
| ; X86-NOBMI-NEXT: movl %esi, %edx | |
| ; X86-NOBMI-NEXT: shll %cl, %edx | |
| ; X86-NOBMI-NEXT: shldl %cl, %esi, %eax | |
| ; X86-NOBMI-NEXT: testb $32, %cl | |
| ; X86-NOBMI-NEXT: je .LBB52_2 | |
| ; X86-NOBMI-NEXT: # %bb.1: | |
| ; X86-NOBMI-NEXT: movl %edx, %eax | |
| ; X86-NOBMI-NEXT: xorl %edx, %edx | |
| ; X86-NOBMI-NEXT: .LBB52_2: | |
| ; X86-NOBMI-NEXT: shrdl %cl, %eax, %edx | |
| ; X86-NOBMI-NEXT: shrl %cl, %eax | |
| ; X86-NOBMI-NEXT: testb $32, %cl | |
| ; X86-NOBMI-NEXT: jne .LBB52_4 | |
| ; X86-NOBMI-NEXT: # %bb.3: | |
| ; X86-NOBMI-NEXT: movl %edx, %eax | |
| ; X86-NOBMI-NEXT: .LBB52_4: | |
| ; X86-NOBMI-NEXT: popl %esi | |
| ; X86-NOBMI-NEXT: retl | |
| ; | |
| ; X86-BMI1-LABEL: bzhi64_32_d0: | |
| ; X86-BMI1: # %bb.0: | |
| ; X86-BMI1-NEXT: pushl %esi | |
| ; X86-BMI1-NEXT: movl {{[0-9]+}}(%esp), %esi | |
| ; X86-BMI1-NEXT: movl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: movb $64, %cl | |
| ; X86-BMI1-NEXT: subb {{[0-9]+}}(%esp), %cl | |
| ; X86-BMI1-NEXT: movl %esi, %edx | |
| ; X86-BMI1-NEXT: shll %cl, %edx | |
| ; X86-BMI1-NEXT: shldl %cl, %esi, %eax | |
| ; X86-BMI1-NEXT: testb $32, %cl | |
| ; X86-BMI1-NEXT: je .LBB52_2 | |
| ; X86-BMI1-NEXT: # %bb.1: | |
| ; X86-BMI1-NEXT: movl %edx, %eax | |
| ; X86-BMI1-NEXT: xorl %edx, %edx | |
| ; X86-BMI1-NEXT: .LBB52_2: | |
| ; X86-BMI1-NEXT: shrdl %cl, %eax, %edx | |
| ; X86-BMI1-NEXT: shrl %cl, %eax | |
| ; X86-BMI1-NEXT: testb $32, %cl | |
| ; X86-BMI1-NEXT: jne .LBB52_4 | |
| ; X86-BMI1-NEXT: # %bb.3: | |
| ; X86-BMI1-NEXT: movl %edx, %eax | |
| ; X86-BMI1-NEXT: .LBB52_4: | |
| ; X86-BMI1-NEXT: popl %esi | |
| ; X86-BMI1-NEXT: retl | |
| ; | |
| ; X86-BMI2-LABEL: bzhi64_32_d0: | |
| ; X86-BMI2: # %bb.0: | |
| ; X86-BMI2-NEXT: movl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: movl {{[0-9]+}}(%esp), %edx | |
| ; X86-BMI2-NEXT: movb $64, %cl | |
| ; X86-BMI2-NEXT: subb {{[0-9]+}}(%esp), %cl | |
| ; X86-BMI2-NEXT: shldl %cl, %eax, %edx | |
| ; X86-BMI2-NEXT: shlxl %ecx, %eax, %eax | |
| ; X86-BMI2-NEXT: testb $32, %cl | |
| ; X86-BMI2-NEXT: je .LBB52_2 | |
| ; X86-BMI2-NEXT: # %bb.1: | |
| ; X86-BMI2-NEXT: movl %eax, %edx | |
| ; X86-BMI2-NEXT: xorl %eax, %eax | |
| ; X86-BMI2-NEXT: .LBB52_2: | |
| ; X86-BMI2-NEXT: shrdl %cl, %edx, %eax | |
| ; X86-BMI2-NEXT: testb $32, %cl | |
| ; X86-BMI2-NEXT: je .LBB52_4 | |
| ; X86-BMI2-NEXT: # %bb.3: | |
| ; X86-BMI2-NEXT: shrxl %ecx, %edx, %eax | |
| ; X86-BMI2-NEXT: .LBB52_4: | |
| ; X86-BMI2-NEXT: retl | |
| ; | |
| ; X64-NOBMI-LABEL: bzhi64_32_d0: | |
| ; X64-NOBMI: # %bb.0: | |
| ; X64-NOBMI-NEXT: movq %rsi, %rcx | |
| ; X64-NOBMI-NEXT: movq %rdi, %rax | |
| ; X64-NOBMI-NEXT: negb %cl | |
| ; X64-NOBMI-NEXT: shlq %cl, %rax | |
| ; X64-NOBMI-NEXT: # kill: def $cl killed $cl killed $rcx | |
| ; X64-NOBMI-NEXT: shrq %cl, %rax | |
| ; X64-NOBMI-NEXT: # kill: def $eax killed $eax killed $rax | |
| ; X64-NOBMI-NEXT: retq | |
| ; | |
| ; X64-BMI1-LABEL: bzhi64_32_d0: | |
| ; X64-BMI1: # %bb.0: | |
| ; X64-BMI1-NEXT: shll $8, %esi | |
| ; X64-BMI1-NEXT: bextrq %rsi, %rdi, %rax | |
| ; X64-BMI1-NEXT: # kill: def $eax killed $eax killed $rax | |
| ; X64-BMI1-NEXT: retq | |
| ; | |
| ; X64-BMI2-LABEL: bzhi64_32_d0: | |
| ; X64-BMI2: # %bb.0: | |
| ; X64-BMI2-NEXT: bzhiq %rsi, %rdi, %rax | |
| ; X64-BMI2-NEXT: # kill: def $eax killed $eax killed $rax | |
| ; X64-BMI2-NEXT: retq | |
| %numhighbits = sub i64 64, %numlowbits | |
| %highbitscleared = shl i64 %val, %numhighbits | |
| %masked = lshr i64 %highbitscleared, %numhighbits | |
| %res = trunc i64 %masked to i32 | |
| ret i32 %res | |
| } | |
| ; Shifting happens in 64-bit, then truncation. Masking is 32-bit. | |
| define i32 @bzhi64_32_d1(i64 %val, i32 %numlowbits) nounwind { | |
| ; X86-NOBMI-LABEL: bzhi64_32_d1: | |
| ; X86-NOBMI: # %bb.0: | |
| ; X86-NOBMI-NEXT: movl {{[0-9]+}}(%esp), %eax | |
| ; X86-NOBMI-NEXT: xorl %ecx, %ecx | |
| ; X86-NOBMI-NEXT: subb {{[0-9]+}}(%esp), %cl | |
| ; X86-NOBMI-NEXT: shll %cl, %eax | |
| ; X86-NOBMI-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X86-NOBMI-NEXT: shrl %cl, %eax | |
| ; X86-NOBMI-NEXT: retl | |
| ; | |
| ; X86-BMI1-LABEL: bzhi64_32_d1: | |
| ; X86-BMI1: # %bb.0: | |
| ; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: shll $8, %eax | |
| ; X86-BMI1-NEXT: bextrl %eax, {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: retl | |
| ; | |
| ; X86-BMI2-LABEL: bzhi64_32_d1: | |
| ; X86-BMI2: # %bb.0: | |
| ; X86-BMI2-NEXT: movzbl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: bzhil %eax, {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: retl | |
| ; | |
| ; X64-NOBMI-LABEL: bzhi64_32_d1: | |
| ; X64-NOBMI: # %bb.0: | |
| ; X64-NOBMI-NEXT: movl %esi, %ecx | |
| ; X64-NOBMI-NEXT: movq %rdi, %rax | |
| ; X64-NOBMI-NEXT: negb %cl | |
| ; X64-NOBMI-NEXT: shll %cl, %eax | |
| ; X64-NOBMI-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X64-NOBMI-NEXT: shrl %cl, %eax | |
| ; X64-NOBMI-NEXT: # kill: def $eax killed $eax killed $rax | |
| ; X64-NOBMI-NEXT: retq | |
| ; | |
| ; X64-BMI1-LABEL: bzhi64_32_d1: | |
| ; X64-BMI1: # %bb.0: | |
| ; X64-BMI1-NEXT: shll $8, %esi | |
| ; X64-BMI1-NEXT: bextrl %esi, %edi, %eax | |
| ; X64-BMI1-NEXT: retq | |
| ; | |
| ; X64-BMI2-LABEL: bzhi64_32_d1: | |
| ; X64-BMI2: # %bb.0: | |
| ; X64-BMI2-NEXT: bzhil %esi, %edi, %eax | |
| ; X64-BMI2-NEXT: retq | |
| %truncval = trunc i64 %val to i32 | |
| %numhighbits = sub i32 32, %numlowbits | |
| %highbitscleared = shl i32 %truncval, %numhighbits | |
| %masked = lshr i32 %highbitscleared, %numhighbits | |
| ret i32 %masked | |
| } | |
| ; ---------------------------------------------------------------------------- ; | |
| ; Constant mask | |
| ; ---------------------------------------------------------------------------- ; | |
| ; 32-bit | |
| define i32 @bzhi32_constant_mask32(i32 %val) nounwind { | |
| ; X86-LABEL: bzhi32_constant_mask32: | |
| ; X86: # %bb.0: | |
| ; X86-NEXT: movl $2147483647, %eax # imm = 0x7FFFFFFF | |
| ; X86-NEXT: andl {{[0-9]+}}(%esp), %eax | |
| ; X86-NEXT: retl | |
| ; | |
| ; X64-LABEL: bzhi32_constant_mask32: | |
| ; X64: # %bb.0: | |
| ; X64-NEXT: movl %edi, %eax | |
| ; X64-NEXT: andl $2147483647, %eax # imm = 0x7FFFFFFF | |
| ; X64-NEXT: retq | |
| %masked = and i32 %val, 2147483647 | |
| ret i32 %masked | |
| } | |
| define i32 @bzhi32_constant_mask32_load(ptr %val) nounwind { | |
| ; X86-LABEL: bzhi32_constant_mask32_load: | |
| ; X86: # %bb.0: | |
| ; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx | |
| ; X86-NEXT: movl $2147483647, %eax # imm = 0x7FFFFFFF | |
| ; X86-NEXT: andl (%ecx), %eax | |
| ; X86-NEXT: retl | |
| ; | |
| ; X64-LABEL: bzhi32_constant_mask32_load: | |
| ; X64: # %bb.0: | |
| ; X64-NEXT: movl $2147483647, %eax # imm = 0x7FFFFFFF | |
| ; X64-NEXT: andl (%rdi), %eax | |
| ; X64-NEXT: retq | |
| %val1 = load i32, ptr %val | |
| %masked = and i32 %val1, 2147483647 | |
| ret i32 %masked | |
| } | |
| define i32 @bzhi32_constant_mask16(i32 %val) nounwind { | |
| ; X86-LABEL: bzhi32_constant_mask16: | |
| ; X86: # %bb.0: | |
| ; X86-NEXT: movl $32767, %eax # imm = 0x7FFF | |
| ; X86-NEXT: andl {{[0-9]+}}(%esp), %eax | |
| ; X86-NEXT: retl | |
| ; | |
| ; X64-LABEL: bzhi32_constant_mask16: | |
| ; X64: # %bb.0: | |
| ; X64-NEXT: movl %edi, %eax | |
| ; X64-NEXT: andl $32767, %eax # imm = 0x7FFF | |
| ; X64-NEXT: retq | |
| %masked = and i32 %val, 32767 | |
| ret i32 %masked | |
| } | |
| define i32 @bzhi32_constant_mask16_load(ptr %val) nounwind { | |
| ; X86-LABEL: bzhi32_constant_mask16_load: | |
| ; X86: # %bb.0: | |
| ; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx | |
| ; X86-NEXT: movl $32767, %eax # imm = 0x7FFF | |
| ; X86-NEXT: andl (%ecx), %eax | |
| ; X86-NEXT: retl | |
| ; | |
| ; X64-LABEL: bzhi32_constant_mask16_load: | |
| ; X64: # %bb.0: | |
| ; X64-NEXT: movl $32767, %eax # imm = 0x7FFF | |
| ; X64-NEXT: andl (%rdi), %eax | |
| ; X64-NEXT: retq | |
| %val1 = load i32, ptr %val | |
| %masked = and i32 %val1, 32767 | |
| ret i32 %masked | |
| } | |
| define i32 @bzhi32_constant_mask8(i32 %val) nounwind { | |
| ; X86-LABEL: bzhi32_constant_mask8: | |
| ; X86: # %bb.0: | |
| ; X86-NEXT: movl {{[0-9]+}}(%esp), %eax | |
| ; X86-NEXT: andl $127, %eax | |
| ; X86-NEXT: retl | |
| ; | |
| ; X64-LABEL: bzhi32_constant_mask8: | |
| ; X64: # %bb.0: | |
| ; X64-NEXT: movl %edi, %eax | |
| ; X64-NEXT: andl $127, %eax | |
| ; X64-NEXT: retq | |
| %masked = and i32 %val, 127 | |
| ret i32 %masked | |
| } | |
| define i32 @bzhi32_constant_mask8_load(ptr %val) nounwind { | |
| ; X86-LABEL: bzhi32_constant_mask8_load: | |
| ; X86: # %bb.0: | |
| ; X86-NEXT: movl {{[0-9]+}}(%esp), %eax | |
| ; X86-NEXT: movl (%eax), %eax | |
| ; X86-NEXT: andl $127, %eax | |
| ; X86-NEXT: retl | |
| ; | |
| ; X64-LABEL: bzhi32_constant_mask8_load: | |
| ; X64: # %bb.0: | |
| ; X64-NEXT: movl (%rdi), %eax | |
| ; X64-NEXT: andl $127, %eax | |
| ; X64-NEXT: retq | |
| %val1 = load i32, ptr %val | |
| %masked = and i32 %val1, 127 | |
| ret i32 %masked | |
| } | |
| ; 64-bit | |
| define i64 @bzhi64_constant_mask64(i64 %val) nounwind { | |
| ; X86-LABEL: bzhi64_constant_mask64: | |
| ; X86: # %bb.0: | |
| ; X86-NEXT: movl {{[0-9]+}}(%esp), %eax | |
| ; X86-NEXT: movl $1073741823, %edx # imm = 0x3FFFFFFF | |
| ; X86-NEXT: andl {{[0-9]+}}(%esp), %edx | |
| ; X86-NEXT: retl | |
| ; | |
| ; X64-NOBMI-LABEL: bzhi64_constant_mask64: | |
| ; X64-NOBMI: # %bb.0: | |
| ; X64-NOBMI-NEXT: movabsq $4611686018427387903, %rax # imm = 0x3FFFFFFFFFFFFFFF | |
| ; X64-NOBMI-NEXT: andq %rdi, %rax | |
| ; X64-NOBMI-NEXT: retq | |
| ; | |
| ; X64-BMI1NOTBM-LABEL: bzhi64_constant_mask64: | |
| ; X64-BMI1NOTBM: # %bb.0: | |
| ; X64-BMI1NOTBM-NEXT: movl $15872, %eax # imm = 0x3E00 | |
| ; X64-BMI1NOTBM-NEXT: bextrq %rax, %rdi, %rax | |
| ; X64-BMI1NOTBM-NEXT: retq | |
| ; | |
| ; X64-BMI1TBM-LABEL: bzhi64_constant_mask64: | |
| ; X64-BMI1TBM: # %bb.0: | |
| ; X64-BMI1TBM-NEXT: bextrq $15872, %rdi, %rax # imm = 0x3E00 | |
| ; X64-BMI1TBM-NEXT: retq | |
| ; | |
| ; X64-BMI2TBM-LABEL: bzhi64_constant_mask64: | |
| ; X64-BMI2TBM: # %bb.0: | |
| ; X64-BMI2TBM-NEXT: bextrq $15872, %rdi, %rax # imm = 0x3E00 | |
| ; X64-BMI2TBM-NEXT: retq | |
| ; | |
| ; X64-BMI2NOTBM-LABEL: bzhi64_constant_mask64: | |
| ; X64-BMI2NOTBM: # %bb.0: | |
| ; X64-BMI2NOTBM-NEXT: movb $62, %al | |
| ; X64-BMI2NOTBM-NEXT: bzhiq %rax, %rdi, %rax | |
| ; X64-BMI2NOTBM-NEXT: retq | |
| %masked = and i64 %val, 4611686018427387903 | |
| ret i64 %masked | |
| } | |
| define i64 @bzhi64_constant_mask64_load(ptr %val) nounwind { | |
| ; X86-LABEL: bzhi64_constant_mask64_load: | |
| ; X86: # %bb.0: | |
| ; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx | |
| ; X86-NEXT: movl (%ecx), %eax | |
| ; X86-NEXT: movl $1073741823, %edx # imm = 0x3FFFFFFF | |
| ; X86-NEXT: andl 4(%ecx), %edx | |
| ; X86-NEXT: retl | |
| ; | |
| ; X64-NOBMI-LABEL: bzhi64_constant_mask64_load: | |
| ; X64-NOBMI: # %bb.0: | |
| ; X64-NOBMI-NEXT: movabsq $4611686018427387903, %rax # imm = 0x3FFFFFFFFFFFFFFF | |
| ; X64-NOBMI-NEXT: andq (%rdi), %rax | |
| ; X64-NOBMI-NEXT: retq | |
| ; | |
| ; X64-BMI1NOTBM-LABEL: bzhi64_constant_mask64_load: | |
| ; X64-BMI1NOTBM: # %bb.0: | |
| ; X64-BMI1NOTBM-NEXT: movl $15872, %eax # imm = 0x3E00 | |
| ; X64-BMI1NOTBM-NEXT: bextrq %rax, (%rdi), %rax | |
| ; X64-BMI1NOTBM-NEXT: retq | |
| ; | |
| ; X64-BMI1TBM-LABEL: bzhi64_constant_mask64_load: | |
| ; X64-BMI1TBM: # %bb.0: | |
| ; X64-BMI1TBM-NEXT: bextrq $15872, (%rdi), %rax # imm = 0x3E00 | |
| ; X64-BMI1TBM-NEXT: retq | |
| ; | |
| ; X64-BMI2TBM-LABEL: bzhi64_constant_mask64_load: | |
| ; X64-BMI2TBM: # %bb.0: | |
| ; X64-BMI2TBM-NEXT: bextrq $15872, (%rdi), %rax # imm = 0x3E00 | |
| ; X64-BMI2TBM-NEXT: retq | |
| ; | |
| ; X64-BMI2NOTBM-LABEL: bzhi64_constant_mask64_load: | |
| ; X64-BMI2NOTBM: # %bb.0: | |
| ; X64-BMI2NOTBM-NEXT: movb $62, %al | |
| ; X64-BMI2NOTBM-NEXT: bzhiq %rax, (%rdi), %rax | |
| ; X64-BMI2NOTBM-NEXT: retq | |
| %val1 = load i64, ptr %val | |
| %masked = and i64 %val1, 4611686018427387903 | |
| ret i64 %masked | |
| } | |
| define i64 @bzhi64_constant_mask32(i64 %val) nounwind { | |
| ; X86-LABEL: bzhi64_constant_mask32: | |
| ; X86: # %bb.0: | |
| ; X86-NEXT: movl $2147483647, %eax # imm = 0x7FFFFFFF | |
| ; X86-NEXT: andl {{[0-9]+}}(%esp), %eax | |
| ; X86-NEXT: xorl %edx, %edx | |
| ; X86-NEXT: retl | |
| ; | |
| ; X64-LABEL: bzhi64_constant_mask32: | |
| ; X64: # %bb.0: | |
| ; X64-NEXT: movq %rdi, %rax | |
| ; X64-NEXT: andl $2147483647, %eax # imm = 0x7FFFFFFF | |
| ; X64-NEXT: retq | |
| %masked = and i64 %val, 2147483647 | |
| ret i64 %masked | |
| } | |
| define i64 @bzhi64_constant_mask32_load(ptr %val) nounwind { | |
| ; X86-LABEL: bzhi64_constant_mask32_load: | |
| ; X86: # %bb.0: | |
| ; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx | |
| ; X86-NEXT: movl $2147483647, %eax # imm = 0x7FFFFFFF | |
| ; X86-NEXT: andl (%ecx), %eax | |
| ; X86-NEXT: xorl %edx, %edx | |
| ; X86-NEXT: retl | |
| ; | |
| ; X64-LABEL: bzhi64_constant_mask32_load: | |
| ; X64: # %bb.0: | |
| ; X64-NEXT: movq (%rdi), %rax | |
| ; X64-NEXT: andl $2147483647, %eax # imm = 0x7FFFFFFF | |
| ; X64-NEXT: retq | |
| %val1 = load i64, ptr %val | |
| %masked = and i64 %val1, 2147483647 | |
| ret i64 %masked | |
| } | |
| define i64 @bzhi64_constant_mask16(i64 %val) nounwind { | |
| ; X86-LABEL: bzhi64_constant_mask16: | |
| ; X86: # %bb.0: | |
| ; X86-NEXT: movl $32767, %eax # imm = 0x7FFF | |
| ; X86-NEXT: andl {{[0-9]+}}(%esp), %eax | |
| ; X86-NEXT: xorl %edx, %edx | |
| ; X86-NEXT: retl | |
| ; | |
| ; X64-LABEL: bzhi64_constant_mask16: | |
| ; X64: # %bb.0: | |
| ; X64-NEXT: movq %rdi, %rax | |
| ; X64-NEXT: andl $32767, %eax # imm = 0x7FFF | |
| ; X64-NEXT: retq | |
| %masked = and i64 %val, 32767 | |
| ret i64 %masked | |
| } | |
| define i64 @bzhi64_constant_mask16_load(ptr %val) nounwind { | |
| ; X86-LABEL: bzhi64_constant_mask16_load: | |
| ; X86: # %bb.0: | |
| ; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx | |
| ; X86-NEXT: movl $32767, %eax # imm = 0x7FFF | |
| ; X86-NEXT: andl (%ecx), %eax | |
| ; X86-NEXT: xorl %edx, %edx | |
| ; X86-NEXT: retl | |
| ; | |
| ; X64-LABEL: bzhi64_constant_mask16_load: | |
| ; X64: # %bb.0: | |
| ; X64-NEXT: movq (%rdi), %rax | |
| ; X64-NEXT: andl $32767, %eax # imm = 0x7FFF | |
| ; X64-NEXT: retq | |
| %val1 = load i64, ptr %val | |
| %masked = and i64 %val1, 32767 | |
| ret i64 %masked | |
| } | |
| define i64 @bzhi64_constant_mask8(i64 %val) nounwind { | |
| ; X86-LABEL: bzhi64_constant_mask8: | |
| ; X86: # %bb.0: | |
| ; X86-NEXT: movl {{[0-9]+}}(%esp), %eax | |
| ; X86-NEXT: andl $127, %eax | |
| ; X86-NEXT: xorl %edx, %edx | |
| ; X86-NEXT: retl | |
| ; | |
| ; X64-LABEL: bzhi64_constant_mask8: | |
| ; X64: # %bb.0: | |
| ; X64-NEXT: movq %rdi, %rax | |
| ; X64-NEXT: andl $127, %eax | |
| ; X64-NEXT: retq | |
| %masked = and i64 %val, 127 | |
| ret i64 %masked | |
| } | |
| define i64 @bzhi64_constant_mask8_load(ptr %val) nounwind { | |
| ; X86-LABEL: bzhi64_constant_mask8_load: | |
| ; X86: # %bb.0: | |
| ; X86-NEXT: movl {{[0-9]+}}(%esp), %eax | |
| ; X86-NEXT: movl (%eax), %eax | |
| ; X86-NEXT: andl $127, %eax | |
| ; X86-NEXT: xorl %edx, %edx | |
| ; X86-NEXT: retl | |
| ; | |
| ; X64-LABEL: bzhi64_constant_mask8_load: | |
| ; X64: # %bb.0: | |
| ; X64-NEXT: movq (%rdi), %rax | |
| ; X64-NEXT: andl $127, %eax | |
| ; X64-NEXT: retq | |
| %val1 = load i64, ptr %val | |
| %masked = and i64 %val1, 127 | |
| ret i64 %masked | |
| } | |
| ; Ensure constant hoisting doesn't prevent BEXTR/BZHI instructions in both paths. | |
| define void @PR111323(ptr nocapture noundef writeonly %use, i64 noundef %x, i64 noundef %y) nounwind { | |
| ; X86-LABEL: PR111323: | |
| ; X86: # %bb.0: # %entry | |
| ; X86-NEXT: pushl %edi | |
| ; X86-NEXT: pushl %esi | |
| ; X86-NEXT: movl {{[0-9]+}}(%esp), %eax | |
| ; X86-NEXT: movl {{[0-9]+}}(%esp), %edx | |
| ; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx | |
| ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi | |
| ; X86-NEXT: movzwl {{[0-9]+}}(%esp), %edi | |
| ; X86-NEXT: movl %edi, 4(%ecx) | |
| ; X86-NEXT: movl %esi, (%ecx) | |
| ; X86-NEXT: movl %edx, %esi | |
| ; X86-NEXT: orl %eax, %esi | |
| ; X86-NEXT: je .LBB68_2 | |
| ; X86-NEXT: # %bb.1: # %if.end | |
| ; X86-NEXT: andl $65535, %eax # imm = 0xFFFF | |
| ; X86-NEXT: andl $-1, %edx | |
| ; X86-NEXT: movl %edx, 8(%ecx) | |
| ; X86-NEXT: movl %eax, 12(%ecx) | |
| ; X86-NEXT: .LBB68_2: # %return | |
| ; X86-NEXT: popl %esi | |
| ; X86-NEXT: popl %edi | |
| ; X86-NEXT: retl | |
| ; | |
| ; X64-NOBMI-LABEL: PR111323: | |
| ; X64-NOBMI: # %bb.0: # %entry | |
| ; X64-NOBMI-NEXT: movabsq $281474976710655, %rax # imm = 0xFFFFFFFFFFFF | |
| ; X64-NOBMI-NEXT: andq %rax, %rsi | |
| ; X64-NOBMI-NEXT: movq %rsi, (%rdi) | |
| ; X64-NOBMI-NEXT: testq %rdx, %rdx | |
| ; X64-NOBMI-NEXT: je .LBB68_2 | |
| ; X64-NOBMI-NEXT: # %bb.1: # %if.end | |
| ; X64-NOBMI-NEXT: andq %rax, %rdx | |
| ; X64-NOBMI-NEXT: movq %rdx, 8(%rdi) | |
| ; X64-NOBMI-NEXT: .LBB68_2: # %return | |
| ; X64-NOBMI-NEXT: retq | |
| ; | |
| ; X64-BMI1NOTBM-LABEL: PR111323: | |
| ; X64-BMI1NOTBM: # %bb.0: # %entry | |
| ; X64-BMI1NOTBM-NEXT: movl $12288, %eax # imm = 0x3000 | |
| ; X64-BMI1NOTBM-NEXT: bextrq %rax, %rsi, %rax | |
| ; X64-BMI1NOTBM-NEXT: movq %rax, (%rdi) | |
| ; X64-BMI1NOTBM-NEXT: testq %rdx, %rdx | |
| ; X64-BMI1NOTBM-NEXT: je .LBB68_2 | |
| ; X64-BMI1NOTBM-NEXT: # %bb.1: # %if.end | |
| ; X64-BMI1NOTBM-NEXT: movl $12288, %eax # imm = 0x3000 | |
| ; X64-BMI1NOTBM-NEXT: bextrq %rax, %rdx, %rax | |
| ; X64-BMI1NOTBM-NEXT: movq %rax, 8(%rdi) | |
| ; X64-BMI1NOTBM-NEXT: .LBB68_2: # %return | |
| ; X64-BMI1NOTBM-NEXT: retq | |
| ; | |
| ; X64-BMI1TBM-LABEL: PR111323: | |
| ; X64-BMI1TBM: # %bb.0: # %entry | |
| ; X64-BMI1TBM-NEXT: bextrq $12288, %rsi, %rax # imm = 0x3000 | |
| ; X64-BMI1TBM-NEXT: movq %rax, (%rdi) | |
| ; X64-BMI1TBM-NEXT: testq %rdx, %rdx | |
| ; X64-BMI1TBM-NEXT: je .LBB68_2 | |
| ; X64-BMI1TBM-NEXT: # %bb.1: # %if.end | |
| ; X64-BMI1TBM-NEXT: bextrq $12288, %rdx, %rax # imm = 0x3000 | |
| ; X64-BMI1TBM-NEXT: movq %rax, 8(%rdi) | |
| ; X64-BMI1TBM-NEXT: .LBB68_2: # %return | |
| ; X64-BMI1TBM-NEXT: retq | |
| ; | |
| ; X64-BMI2TBM-LABEL: PR111323: | |
| ; X64-BMI2TBM: # %bb.0: # %entry | |
| ; X64-BMI2TBM-NEXT: bextrq $12288, %rsi, %rax # imm = 0x3000 | |
| ; X64-BMI2TBM-NEXT: movq %rax, (%rdi) | |
| ; X64-BMI2TBM-NEXT: testq %rdx, %rdx | |
| ; X64-BMI2TBM-NEXT: je .LBB68_2 | |
| ; X64-BMI2TBM-NEXT: # %bb.1: # %if.end | |
| ; X64-BMI2TBM-NEXT: bextrq $12288, %rdx, %rax # imm = 0x3000 | |
| ; X64-BMI2TBM-NEXT: movq %rax, 8(%rdi) | |
| ; X64-BMI2TBM-NEXT: .LBB68_2: # %return | |
| ; X64-BMI2TBM-NEXT: retq | |
| ; | |
| ; X64-BMI2NOTBM-LABEL: PR111323: | |
| ; X64-BMI2NOTBM: # %bb.0: # %entry | |
| ; X64-BMI2NOTBM-NEXT: movb $48, %al | |
| ; X64-BMI2NOTBM-NEXT: bzhiq %rax, %rsi, %rcx | |
| ; X64-BMI2NOTBM-NEXT: movq %rcx, (%rdi) | |
| ; X64-BMI2NOTBM-NEXT: testq %rdx, %rdx | |
| ; X64-BMI2NOTBM-NEXT: je .LBB68_2 | |
| ; X64-BMI2NOTBM-NEXT: # %bb.1: # %if.end | |
| ; X64-BMI2NOTBM-NEXT: bzhiq %rax, %rdx, %rax | |
| ; X64-BMI2NOTBM-NEXT: movq %rax, 8(%rdi) | |
| ; X64-BMI2NOTBM-NEXT: .LBB68_2: # %return | |
| ; X64-BMI2NOTBM-NEXT: retq | |
| entry: | |
| %and = and i64 %x, 281474976710655 | |
| store i64 %and, ptr %use, align 8 | |
| %cmp = icmp eq i64 %y, 0 | |
| br i1 %cmp, label %return, label %if.end | |
| if.end: | |
| %and1 = and i64 %y, 281474976710655 | |
| %arrayidx2 = getelementptr inbounds i8, ptr %use, i64 8 | |
| store i64 %and1, ptr %arrayidx2, align 8 | |
| br label %return | |
| return: | |
| ret void | |
| } | |
| ; ---------------------------------------------------------------------------- ; | |
| ; Pattern e. 32-bit mask zero-extended into a 64-bit and | |
| ; ---------------------------------------------------------------------------- ; | |
| ; The mask is built in i32, as a 32-bit mask table or (1u << n) - 1 would be, | |
| ; and applied to a 64-bit value. The same mask built directly in i64 selects | |
| ; as a single and-not. | |
| define i64 @bzhi64_32_e0(i64 %val, i32 %numlowbits) nounwind { | |
| ; X86-NOBMI-LABEL: bzhi64_32_e0: | |
| ; X86-NOBMI: # %bb.0: | |
| ; X86-NOBMI-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-NOBMI-NEXT: movl $-1, %eax | |
| ; X86-NOBMI-NEXT: shll %cl, %eax | |
| ; X86-NOBMI-NEXT: notl %eax | |
| ; X86-NOBMI-NEXT: andl {{[0-9]+}}(%esp), %eax | |
| ; X86-NOBMI-NEXT: xorl %edx, %edx | |
| ; X86-NOBMI-NEXT: retl | |
| ; | |
| ; X86-BMI1-LABEL: bzhi64_32_e0: | |
| ; X86-BMI1: # %bb.0: | |
| ; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: shll $8, %eax | |
| ; X86-BMI1-NEXT: bextrl %eax, {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: xorl %edx, %edx | |
| ; X86-BMI1-NEXT: retl | |
| ; | |
| ; X86-BMI2-LABEL: bzhi64_32_e0: | |
| ; X86-BMI2: # %bb.0: | |
| ; X86-BMI2-NEXT: movzbl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: bzhil %eax, {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: xorl %edx, %edx | |
| ; X86-BMI2-NEXT: retl | |
| ; | |
| ; X64-NOBMI-LABEL: bzhi64_32_e0: | |
| ; X64-NOBMI: # %bb.0: | |
| ; X64-NOBMI-NEXT: movl %esi, %ecx | |
| ; X64-NOBMI-NEXT: movl $-1, %eax | |
| ; X64-NOBMI-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X64-NOBMI-NEXT: shll %cl, %eax | |
| ; X64-NOBMI-NEXT: notl %eax | |
| ; X64-NOBMI-NEXT: andl %edi, %eax | |
| ; X64-NOBMI-NEXT: retq | |
| ; | |
| ; X64-BMI1-LABEL: bzhi64_32_e0: | |
| ; X64-BMI1: # %bb.0: | |
| ; X64-BMI1-NEXT: shll $8, %esi | |
| ; X64-BMI1-NEXT: bextrl %esi, %edi, %eax | |
| ; X64-BMI1-NEXT: retq | |
| ; | |
| ; X64-BMI2-LABEL: bzhi64_32_e0: | |
| ; X64-BMI2: # %bb.0: | |
| ; X64-BMI2-NEXT: bzhil %esi, %edi, %eax | |
| ; X64-BMI2-NEXT: retq | |
| %notmask = shl i32 -1, %numlowbits | |
| %mask = xor i32 %notmask, -1 | |
| %zmask = zext i32 %mask to i64 | |
| %masked = and i64 %zmask, %val | |
| ret i64 %masked | |
| } | |
| define i64 @bzhi64_32_e1_indexzext(i64 %val, i8 zeroext %numlowbits) nounwind { | |
| ; X86-NOBMI-LABEL: bzhi64_32_e1_indexzext: | |
| ; X86-NOBMI: # %bb.0: | |
| ; X86-NOBMI-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-NOBMI-NEXT: movl $-1, %eax | |
| ; X86-NOBMI-NEXT: shll %cl, %eax | |
| ; X86-NOBMI-NEXT: notl %eax | |
| ; X86-NOBMI-NEXT: andl {{[0-9]+}}(%esp), %eax | |
| ; X86-NOBMI-NEXT: xorl %edx, %edx | |
| ; X86-NOBMI-NEXT: retl | |
| ; | |
| ; X86-BMI1-LABEL: bzhi64_32_e1_indexzext: | |
| ; X86-BMI1: # %bb.0: | |
| ; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: shll $8, %eax | |
| ; X86-BMI1-NEXT: bextrl %eax, {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: xorl %edx, %edx | |
| ; X86-BMI1-NEXT: retl | |
| ; | |
| ; X86-BMI2-LABEL: bzhi64_32_e1_indexzext: | |
| ; X86-BMI2: # %bb.0: | |
| ; X86-BMI2-NEXT: movzbl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: bzhil %eax, {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: xorl %edx, %edx | |
| ; X86-BMI2-NEXT: retl | |
| ; | |
| ; X64-NOBMI-LABEL: bzhi64_32_e1_indexzext: | |
| ; X64-NOBMI: # %bb.0: | |
| ; X64-NOBMI-NEXT: movl %esi, %ecx | |
| ; X64-NOBMI-NEXT: movl $-1, %eax | |
| ; X64-NOBMI-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X64-NOBMI-NEXT: shll %cl, %eax | |
| ; X64-NOBMI-NEXT: notl %eax | |
| ; X64-NOBMI-NEXT: andl %edi, %eax | |
| ; X64-NOBMI-NEXT: retq | |
| ; | |
| ; X64-BMI1-LABEL: bzhi64_32_e1_indexzext: | |
| ; X64-BMI1: # %bb.0: | |
| ; X64-BMI1-NEXT: shll $8, %esi | |
| ; X64-BMI1-NEXT: bextrl %esi, %edi, %eax | |
| ; X64-BMI1-NEXT: retq | |
| ; | |
| ; X64-BMI2-LABEL: bzhi64_32_e1_indexzext: | |
| ; X64-BMI2: # %bb.0: | |
| ; X64-BMI2-NEXT: bzhil %esi, %edi, %eax | |
| ; X64-BMI2-NEXT: retq | |
| %conv = zext i8 %numlowbits to i32 | |
| %notmask = shl i32 -1, %conv | |
| %mask = xor i32 %notmask, -1 | |
| %zmask = zext i32 %mask to i64 | |
| %masked = and i64 %zmask, %val | |
| ret i64 %masked | |
| } | |
| define i64 @bzhi64_32_e2_load(ptr %w, i32 %numlowbits) nounwind { | |
| ; X86-NOBMI-LABEL: bzhi64_32_e2_load: | |
| ; X86-NOBMI: # %bb.0: | |
| ; X86-NOBMI-NEXT: movl {{[0-9]+}}(%esp), %edx | |
| ; X86-NOBMI-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-NOBMI-NEXT: movl $-1, %eax | |
| ; X86-NOBMI-NEXT: shll %cl, %eax | |
| ; X86-NOBMI-NEXT: notl %eax | |
| ; X86-NOBMI-NEXT: andl (%edx), %eax | |
| ; X86-NOBMI-NEXT: xorl %edx, %edx | |
| ; X86-NOBMI-NEXT: retl | |
| ; | |
| ; X86-BMI1-LABEL: bzhi64_32_e2_load: | |
| ; X86-BMI1: # %bb.0: | |
| ; X86-BMI1-NEXT: movl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-BMI1-NEXT: shll $8, %ecx | |
| ; X86-BMI1-NEXT: bextrl %ecx, (%eax), %eax | |
| ; X86-BMI1-NEXT: xorl %edx, %edx | |
| ; X86-BMI1-NEXT: retl | |
| ; | |
| ; X86-BMI2-LABEL: bzhi64_32_e2_load: | |
| ; X86-BMI2: # %bb.0: | |
| ; X86-BMI2-NEXT: movl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-BMI2-NEXT: bzhil %ecx, (%eax), %eax | |
| ; X86-BMI2-NEXT: xorl %edx, %edx | |
| ; X86-BMI2-NEXT: retl | |
| ; | |
| ; X64-NOBMI-LABEL: bzhi64_32_e2_load: | |
| ; X64-NOBMI: # %bb.0: | |
| ; X64-NOBMI-NEXT: movl %esi, %ecx | |
| ; X64-NOBMI-NEXT: movl $-1, %eax | |
| ; X64-NOBMI-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X64-NOBMI-NEXT: shll %cl, %eax | |
| ; X64-NOBMI-NEXT: notl %eax | |
| ; X64-NOBMI-NEXT: andl (%rdi), %eax | |
| ; X64-NOBMI-NEXT: retq | |
| ; | |
| ; X64-BMI1-LABEL: bzhi64_32_e2_load: | |
| ; X64-BMI1: # %bb.0: | |
| ; X64-BMI1-NEXT: shll $8, %esi | |
| ; X64-BMI1-NEXT: bextrl %esi, (%rdi), %eax | |
| ; X64-BMI1-NEXT: retq | |
| ; | |
| ; X64-BMI2-LABEL: bzhi64_32_e2_load: | |
| ; X64-BMI2: # %bb.0: | |
| ; X64-BMI2-NEXT: bzhil %esi, (%rdi), %eax | |
| ; X64-BMI2-NEXT: retq | |
| %val = load i64, ptr %w | |
| %notmask = shl i32 -1, %numlowbits | |
| %mask = xor i32 %notmask, -1 | |
| %zmask = zext i32 %mask to i64 | |
| %masked = and i64 %zmask, %val | |
| ret i64 %masked | |
| } | |
| define i64 @bzhi64_32_e3_commutative(i64 %val, i32 %numlowbits) nounwind { | |
| ; X86-NOBMI-LABEL: bzhi64_32_e3_commutative: | |
| ; X86-NOBMI: # %bb.0: | |
| ; X86-NOBMI-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-NOBMI-NEXT: movl $-1, %eax | |
| ; X86-NOBMI-NEXT: shll %cl, %eax | |
| ; X86-NOBMI-NEXT: notl %eax | |
| ; X86-NOBMI-NEXT: andl {{[0-9]+}}(%esp), %eax | |
| ; X86-NOBMI-NEXT: xorl %edx, %edx | |
| ; X86-NOBMI-NEXT: retl | |
| ; | |
| ; X86-BMI1-LABEL: bzhi64_32_e3_commutative: | |
| ; X86-BMI1: # %bb.0: | |
| ; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: shll $8, %eax | |
| ; X86-BMI1-NEXT: bextrl %eax, {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: xorl %edx, %edx | |
| ; X86-BMI1-NEXT: retl | |
| ; | |
| ; X86-BMI2-LABEL: bzhi64_32_e3_commutative: | |
| ; X86-BMI2: # %bb.0: | |
| ; X86-BMI2-NEXT: movzbl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: bzhil %eax, {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: xorl %edx, %edx | |
| ; X86-BMI2-NEXT: retl | |
| ; | |
| ; X64-NOBMI-LABEL: bzhi64_32_e3_commutative: | |
| ; X64-NOBMI: # %bb.0: | |
| ; X64-NOBMI-NEXT: movl %esi, %ecx | |
| ; X64-NOBMI-NEXT: movl $-1, %eax | |
| ; X64-NOBMI-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X64-NOBMI-NEXT: shll %cl, %eax | |
| ; X64-NOBMI-NEXT: notl %eax | |
| ; X64-NOBMI-NEXT: andl %edi, %eax | |
| ; X64-NOBMI-NEXT: retq | |
| ; | |
| ; X64-BMI1-LABEL: bzhi64_32_e3_commutative: | |
| ; X64-BMI1: # %bb.0: | |
| ; X64-BMI1-NEXT: shll $8, %esi | |
| ; X64-BMI1-NEXT: bextrl %esi, %edi, %eax | |
| ; X64-BMI1-NEXT: retq | |
| ; | |
| ; X64-BMI2-LABEL: bzhi64_32_e3_commutative: | |
| ; X64-BMI2: # %bb.0: | |
| ; X64-BMI2-NEXT: bzhil %esi, %edi, %eax | |
| ; X64-BMI2-NEXT: retq | |
| %notmask = shl i32 -1, %numlowbits | |
| %mask = xor i32 %notmask, -1 | |
| %zmask = zext i32 %mask to i64 | |
| %masked = and i64 %val, %zmask ; swapped order | |
| ret i64 %masked | |
| } | |
| ; The value is a shifted operand: the and could absorb the shift, an and-not | |
| ; cannot, so the instruction count does not change here. | |
| define i64 @bzhi64_32_e4_shifted_val(i64 %val, i32 %numlowbits) nounwind { | |
| ; X86-NOBMI-LABEL: bzhi64_32_e4_shifted_val: | |
| ; X86-NOBMI: # %bb.0: | |
| ; X86-NOBMI-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-NOBMI-NEXT: movl {{[0-9]+}}(%esp), %edx | |
| ; X86-NOBMI-NEXT: shrl $8, %edx | |
| ; X86-NOBMI-NEXT: movl $-1, %eax | |
| ; X86-NOBMI-NEXT: shll %cl, %eax | |
| ; X86-NOBMI-NEXT: notl %eax | |
| ; X86-NOBMI-NEXT: andl %edx, %eax | |
| ; X86-NOBMI-NEXT: xorl %edx, %edx | |
| ; X86-NOBMI-NEXT: retl | |
| ; | |
| ; X86-BMI1-LABEL: bzhi64_32_e4_shifted_val: | |
| ; X86-BMI1: # %bb.0: | |
| ; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: shll $8, %eax | |
| ; X86-BMI1-NEXT: orl $8, %eax | |
| ; X86-BMI1-NEXT: bextrl %eax, {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: xorl %edx, %edx | |
| ; X86-BMI1-NEXT: retl | |
| ; | |
| ; X86-BMI2-LABEL: bzhi64_32_e4_shifted_val: | |
| ; X86-BMI2: # %bb.0: | |
| ; X86-BMI2-NEXT: movzbl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: movl {{[0-9]+}}(%esp), %ecx | |
| ; X86-BMI2-NEXT: shrl $8, %ecx | |
| ; X86-BMI2-NEXT: bzhil %eax, %ecx, %eax | |
| ; X86-BMI2-NEXT: xorl %edx, %edx | |
| ; X86-BMI2-NEXT: retl | |
| ; | |
| ; X64-NOBMI-LABEL: bzhi64_32_e4_shifted_val: | |
| ; X64-NOBMI: # %bb.0: | |
| ; X64-NOBMI-NEXT: movl %esi, %ecx | |
| ; X64-NOBMI-NEXT: shrq $40, %rdi | |
| ; X64-NOBMI-NEXT: movl $-1, %eax | |
| ; X64-NOBMI-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X64-NOBMI-NEXT: shll %cl, %eax | |
| ; X64-NOBMI-NEXT: notl %eax | |
| ; X64-NOBMI-NEXT: andl %edi, %eax | |
| ; X64-NOBMI-NEXT: retq | |
| ; | |
| ; X64-BMI1-LABEL: bzhi64_32_e4_shifted_val: | |
| ; X64-BMI1: # %bb.0: | |
| ; X64-BMI1-NEXT: # kill: def $esi killed $esi def $rsi | |
| ; X64-BMI1-NEXT: shll $8, %esi | |
| ; X64-BMI1-NEXT: orl $40, %esi | |
| ; X64-BMI1-NEXT: bextrq %rsi, %rdi, %rax | |
| ; X64-BMI1-NEXT: retq | |
| ; | |
| ; X64-BMI2-LABEL: bzhi64_32_e4_shifted_val: | |
| ; X64-BMI2: # %bb.0: | |
| ; X64-BMI2-NEXT: shrq $40, %rdi | |
| ; X64-BMI2-NEXT: bzhil %esi, %edi, %eax | |
| ; X64-BMI2-NEXT: retq | |
| %shifted = lshr i64 %val, 40 | |
| %notmask = shl i32 -1, %numlowbits | |
| %mask = xor i32 %notmask, -1 | |
| %zmask = zext i32 %mask to i64 | |
| %masked = and i64 %zmask, %shifted | |
| ret i64 %masked | |
| } | |
| define i64 @bzhi64_16_e0(i64 %val, i16 %numlowbits) nounwind { | |
| ; X86-NOBMI-LABEL: bzhi64_16_e0: | |
| ; X86-NOBMI: # %bb.0: | |
| ; X86-NOBMI-NEXT: movzwl {{[0-9]+}}(%esp), %edx | |
| ; X86-NOBMI-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-NOBMI-NEXT: movl $-1, %eax | |
| ; X86-NOBMI-NEXT: shll %cl, %eax | |
| ; X86-NOBMI-NEXT: notl %eax | |
| ; X86-NOBMI-NEXT: andl %edx, %eax | |
| ; X86-NOBMI-NEXT: xorl %edx, %edx | |
| ; X86-NOBMI-NEXT: retl | |
| ; | |
| ; X86-BMI1-LABEL: bzhi64_16_e0: | |
| ; X86-BMI1: # %bb.0: | |
| ; X86-BMI1-NEXT: movzwl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-BMI1-NEXT: shll $8, %ecx | |
| ; X86-BMI1-NEXT: bextrl %ecx, %eax, %eax | |
| ; X86-BMI1-NEXT: xorl %edx, %edx | |
| ; X86-BMI1-NEXT: retl | |
| ; | |
| ; X86-BMI2-LABEL: bzhi64_16_e0: | |
| ; X86-BMI2: # %bb.0: | |
| ; X86-BMI2-NEXT: movzwl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-BMI2-NEXT: bzhil %ecx, %eax, %eax | |
| ; X86-BMI2-NEXT: xorl %edx, %edx | |
| ; X86-BMI2-NEXT: retl | |
| ; | |
| ; X64-NOBMI-LABEL: bzhi64_16_e0: | |
| ; X64-NOBMI: # %bb.0: | |
| ; X64-NOBMI-NEXT: movl %esi, %ecx | |
| ; X64-NOBMI-NEXT: movl $-1, %eax | |
| ; X64-NOBMI-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X64-NOBMI-NEXT: shll %cl, %eax | |
| ; X64-NOBMI-NEXT: notl %eax | |
| ; X64-NOBMI-NEXT: andl %eax, %edi | |
| ; X64-NOBMI-NEXT: movzwl %di, %eax | |
| ; X64-NOBMI-NEXT: retq | |
| ; | |
| ; X64-BMI1-LABEL: bzhi64_16_e0: | |
| ; X64-BMI1: # %bb.0: | |
| ; X64-BMI1-NEXT: shll $8, %esi | |
| ; X64-BMI1-NEXT: bextrl %esi, %edi, %eax | |
| ; X64-BMI1-NEXT: movzwl %ax, %eax | |
| ; X64-BMI1-NEXT: retq | |
| ; | |
| ; X64-BMI2-LABEL: bzhi64_16_e0: | |
| ; X64-BMI2: # %bb.0: | |
| ; X64-BMI2-NEXT: bzhil %esi, %edi, %eax | |
| ; X64-BMI2-NEXT: movzwl %ax, %eax | |
| ; X64-BMI2-NEXT: retq | |
| %notmask = shl i16 -1, %numlowbits | |
| %mask = xor i16 %notmask, -1 | |
| %zmask = zext i16 %mask to i64 | |
| %masked = and i64 %zmask, %val | |
| ret i64 %masked | |
| } | |
| ; Negative: the narrow mask has another use. | |
| define i64 @bzhi64_32_e5_multiuse_mask(i64 %val, i32 %numlowbits, ptr %escape) nounwind { | |
| ; X86-NOBMI-LABEL: bzhi64_32_e5_multiuse_mask: | |
| ; X86-NOBMI: # %bb.0: | |
| ; X86-NOBMI-NEXT: movl {{[0-9]+}}(%esp), %edx | |
| ; X86-NOBMI-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-NOBMI-NEXT: movl $-1, %eax | |
| ; X86-NOBMI-NEXT: shll %cl, %eax | |
| ; X86-NOBMI-NEXT: notl %eax | |
| ; X86-NOBMI-NEXT: movl %eax, (%edx) | |
| ; X86-NOBMI-NEXT: andl {{[0-9]+}}(%esp), %eax | |
| ; X86-NOBMI-NEXT: xorl %edx, %edx | |
| ; X86-NOBMI-NEXT: retl | |
| ; | |
| ; X86-BMI1-LABEL: bzhi64_32_e5_multiuse_mask: | |
| ; X86-BMI1: # %bb.0: | |
| ; X86-BMI1-NEXT: pushl %esi | |
| ; X86-BMI1-NEXT: movl {{[0-9]+}}(%esp), %edx | |
| ; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-BMI1-NEXT: movl $-1, %esi | |
| ; X86-BMI1-NEXT: shll %cl, %esi | |
| ; X86-BMI1-NEXT: andnl {{[0-9]+}}(%esp), %esi, %eax | |
| ; X86-BMI1-NEXT: notl %esi | |
| ; X86-BMI1-NEXT: movl %esi, (%edx) | |
| ; X86-BMI1-NEXT: xorl %edx, %edx | |
| ; X86-BMI1-NEXT: popl %esi | |
| ; X86-BMI1-NEXT: retl | |
| ; | |
| ; X86-BMI2-LABEL: bzhi64_32_e5_multiuse_mask: | |
| ; X86-BMI2: # %bb.0: | |
| ; X86-BMI2-NEXT: movl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-BMI2-NEXT: movl $-1, %edx | |
| ; X86-BMI2-NEXT: bzhil %ecx, %edx, %edx | |
| ; X86-BMI2-NEXT: movl %edx, (%eax) | |
| ; X86-BMI2-NEXT: bzhil %ecx, {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: xorl %edx, %edx | |
| ; X86-BMI2-NEXT: retl | |
| ; | |
| ; X64-NOBMI-LABEL: bzhi64_32_e5_multiuse_mask: | |
| ; X64-NOBMI: # %bb.0: | |
| ; X64-NOBMI-NEXT: movl %esi, %ecx | |
| ; X64-NOBMI-NEXT: movl $-1, %eax | |
| ; X64-NOBMI-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X64-NOBMI-NEXT: shll %cl, %eax | |
| ; X64-NOBMI-NEXT: notl %eax | |
| ; X64-NOBMI-NEXT: movl %eax, (%rdx) | |
| ; X64-NOBMI-NEXT: andl %edi, %eax | |
| ; X64-NOBMI-NEXT: retq | |
| ; | |
| ; X64-BMI1-LABEL: bzhi64_32_e5_multiuse_mask: | |
| ; X64-BMI1: # %bb.0: | |
| ; X64-BMI1-NEXT: movl %esi, %ecx | |
| ; X64-BMI1-NEXT: movl $-1, %esi | |
| ; X64-BMI1-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X64-BMI1-NEXT: shll %cl, %esi | |
| ; X64-BMI1-NEXT: andnl %edi, %esi, %eax | |
| ; X64-BMI1-NEXT: notl %esi | |
| ; X64-BMI1-NEXT: movl %esi, (%rdx) | |
| ; X64-BMI1-NEXT: retq | |
| ; | |
| ; X64-BMI2-LABEL: bzhi64_32_e5_multiuse_mask: | |
| ; X64-BMI2: # %bb.0: | |
| ; X64-BMI2-NEXT: movl $-1, %eax | |
| ; X64-BMI2-NEXT: bzhil %esi, %eax, %eax | |
| ; X64-BMI2-NEXT: movl %eax, (%rdx) | |
| ; X64-BMI2-NEXT: bzhil %esi, %edi, %eax | |
| ; X64-BMI2-NEXT: retq | |
| %notmask = shl i32 -1, %numlowbits | |
| %mask = xor i32 %notmask, -1 | |
| store i32 %mask, ptr %escape | |
| %zmask = zext i32 %mask to i64 | |
| %masked = and i64 %zmask, %val | |
| ret i64 %masked | |
| } | |
| ; Negative: the zero-extended mask has another use. | |
| define i64 @bzhi64_32_e6_multiuse_zext(i64 %val, i32 %numlowbits, ptr %escape) nounwind { | |
| ; X86-NOBMI-LABEL: bzhi64_32_e6_multiuse_zext: | |
| ; X86-NOBMI: # %bb.0: | |
| ; X86-NOBMI-NEXT: movl {{[0-9]+}}(%esp), %edx | |
| ; X86-NOBMI-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-NOBMI-NEXT: movl $-1, %eax | |
| ; X86-NOBMI-NEXT: shll %cl, %eax | |
| ; X86-NOBMI-NEXT: notl %eax | |
| ; X86-NOBMI-NEXT: movl %eax, (%edx) | |
| ; X86-NOBMI-NEXT: movl $0, 4(%edx) | |
| ; X86-NOBMI-NEXT: andl {{[0-9]+}}(%esp), %eax | |
| ; X86-NOBMI-NEXT: xorl %edx, %edx | |
| ; X86-NOBMI-NEXT: retl | |
| ; | |
| ; X86-BMI1-LABEL: bzhi64_32_e6_multiuse_zext: | |
| ; X86-BMI1: # %bb.0: | |
| ; X86-BMI1-NEXT: pushl %esi | |
| ; X86-BMI1-NEXT: movl {{[0-9]+}}(%esp), %edx | |
| ; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-BMI1-NEXT: movl $-1, %esi | |
| ; X86-BMI1-NEXT: shll %cl, %esi | |
| ; X86-BMI1-NEXT: andnl {{[0-9]+}}(%esp), %esi, %eax | |
| ; X86-BMI1-NEXT: notl %esi | |
| ; X86-BMI1-NEXT: movl %esi, (%edx) | |
| ; X86-BMI1-NEXT: movl $0, 4(%edx) | |
| ; X86-BMI1-NEXT: xorl %edx, %edx | |
| ; X86-BMI1-NEXT: popl %esi | |
| ; X86-BMI1-NEXT: retl | |
| ; | |
| ; X86-BMI2-LABEL: bzhi64_32_e6_multiuse_zext: | |
| ; X86-BMI2: # %bb.0: | |
| ; X86-BMI2-NEXT: movl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-BMI2-NEXT: movl $-1, %edx | |
| ; X86-BMI2-NEXT: bzhil %ecx, %edx, %edx | |
| ; X86-BMI2-NEXT: movl %edx, (%eax) | |
| ; X86-BMI2-NEXT: movl $0, 4(%eax) | |
| ; X86-BMI2-NEXT: bzhil %ecx, {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: xorl %edx, %edx | |
| ; X86-BMI2-NEXT: retl | |
| ; | |
| ; X64-NOBMI-LABEL: bzhi64_32_e6_multiuse_zext: | |
| ; X64-NOBMI: # %bb.0: | |
| ; X64-NOBMI-NEXT: movl %esi, %ecx | |
| ; X64-NOBMI-NEXT: movl $-1, %eax | |
| ; X64-NOBMI-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X64-NOBMI-NEXT: shll %cl, %eax | |
| ; X64-NOBMI-NEXT: notl %eax | |
| ; X64-NOBMI-NEXT: movq %rax, (%rdx) | |
| ; X64-NOBMI-NEXT: andl %edi, %eax | |
| ; X64-NOBMI-NEXT: retq | |
| ; | |
| ; X64-BMI1-LABEL: bzhi64_32_e6_multiuse_zext: | |
| ; X64-BMI1: # %bb.0: | |
| ; X64-BMI1-NEXT: movl %esi, %ecx | |
| ; X64-BMI1-NEXT: movl $-1, %esi | |
| ; X64-BMI1-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X64-BMI1-NEXT: shll %cl, %esi | |
| ; X64-BMI1-NEXT: andnl %edi, %esi, %eax | |
| ; X64-BMI1-NEXT: movl %esi, %ecx | |
| ; X64-BMI1-NEXT: notl %ecx | |
| ; X64-BMI1-NEXT: movq %rcx, (%rdx) | |
| ; X64-BMI1-NEXT: retq | |
| ; | |
| ; X64-BMI2-LABEL: bzhi64_32_e6_multiuse_zext: | |
| ; X64-BMI2: # %bb.0: | |
| ; X64-BMI2-NEXT: movl $-1, %eax | |
| ; X64-BMI2-NEXT: bzhil %esi, %eax, %eax | |
| ; X64-BMI2-NEXT: movq %rax, (%rdx) | |
| ; X64-BMI2-NEXT: bzhil %esi, %edi, %eax | |
| ; X64-BMI2-NEXT: retq | |
| %notmask = shl i32 -1, %numlowbits | |
| %mask = xor i32 %notmask, -1 | |
| %zmask = zext i32 %mask to i64 | |
| store i64 %zmask, ptr %escape | |
| %masked = and i64 %zmask, %val | |
| ret i64 %masked | |
| } | |
| ; Not a low-bits mask. | |
| define i64 @bzhi64_32_e7_not_allones(i64 %val, i32 %numlowbits) nounwind { | |
| ; X86-NOBMI-LABEL: bzhi64_32_e7_not_allones: | |
| ; X86-NOBMI: # %bb.0: | |
| ; X86-NOBMI-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-NOBMI-NEXT: movl $3, %eax | |
| ; X86-NOBMI-NEXT: shll %cl, %eax | |
| ; X86-NOBMI-NEXT: notl %eax | |
| ; X86-NOBMI-NEXT: andl {{[0-9]+}}(%esp), %eax | |
| ; X86-NOBMI-NEXT: xorl %edx, %edx | |
| ; X86-NOBMI-NEXT: retl | |
| ; | |
| ; X86-BMI1-LABEL: bzhi64_32_e7_not_allones: | |
| ; X86-BMI1: # %bb.0: | |
| ; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-BMI1-NEXT: movl $3, %eax | |
| ; X86-BMI1-NEXT: shll %cl, %eax | |
| ; X86-BMI1-NEXT: andnl {{[0-9]+}}(%esp), %eax, %eax | |
| ; X86-BMI1-NEXT: xorl %edx, %edx | |
| ; X86-BMI1-NEXT: retl | |
| ; | |
| ; X86-BMI2-LABEL: bzhi64_32_e7_not_allones: | |
| ; X86-BMI2: # %bb.0: | |
| ; X86-BMI2-NEXT: movzbl {{[0-9]+}}(%esp), %eax | |
| ; X86-BMI2-NEXT: movl $3, %ecx | |
| ; X86-BMI2-NEXT: shlxl %eax, %ecx, %eax | |
| ; X86-BMI2-NEXT: andnl {{[0-9]+}}(%esp), %eax, %eax | |
| ; X86-BMI2-NEXT: xorl %edx, %edx | |
| ; X86-BMI2-NEXT: retl | |
| ; | |
| ; X64-NOBMI-LABEL: bzhi64_32_e7_not_allones: | |
| ; X64-NOBMI: # %bb.0: | |
| ; X64-NOBMI-NEXT: movl %esi, %ecx | |
| ; X64-NOBMI-NEXT: movl $3, %eax | |
| ; X64-NOBMI-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X64-NOBMI-NEXT: shll %cl, %eax | |
| ; X64-NOBMI-NEXT: notl %eax | |
| ; X64-NOBMI-NEXT: andl %edi, %eax | |
| ; X64-NOBMI-NEXT: retq | |
| ; | |
| ; X64-BMI1-LABEL: bzhi64_32_e7_not_allones: | |
| ; X64-BMI1: # %bb.0: | |
| ; X64-BMI1-NEXT: movl %esi, %ecx | |
| ; X64-BMI1-NEXT: movl $3, %eax | |
| ; X64-BMI1-NEXT: # kill: def $cl killed $cl killed $ecx | |
| ; X64-BMI1-NEXT: shll %cl, %eax | |
| ; X64-BMI1-NEXT: andnl %edi, %eax, %eax | |
| ; X64-BMI1-NEXT: retq | |
| ; | |
| ; X64-BMI2-LABEL: bzhi64_32_e7_not_allones: | |
| ; X64-BMI2: # %bb.0: | |
| ; X64-BMI2-NEXT: movl $3, %eax | |
| ; X64-BMI2-NEXT: shlxl %esi, %eax, %eax | |
| ; X64-BMI2-NEXT: andnl %edi, %eax, %eax | |
| ; X64-BMI2-NEXT: retq | |
| %notmask = shl i32 3, %numlowbits | |
| %mask = xor i32 %notmask, -1 | |
| %zmask = zext i32 %mask to i64 | |
| %masked = and i64 %zmask, %val | |
| ret i64 %masked | |
| } |