Index: lib/Target/X86/X86InstrInfo.td =================================================================== --- lib/Target/X86/X86InstrInfo.td +++ lib/Target/X86/X86InstrInfo.td @@ -2429,6 +2429,7 @@ } let Predicates = [HasBMI2] in { + // x & ((1 << y) - 1) def : Pat<(and GR32:$src, (add (shl 1, GR8:$lz), -1)), (BZHI32rr GR32:$src, (INSERT_SUBREG (i32 (IMPLICIT_DEF)), GR8:$lz, sub_8bit))>; @@ -2445,6 +2446,23 @@ (BZHI64rm addr:$src, (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GR8:$lz, sub_8bit))>; + // x & ~(-1 << y) + def : Pat<(and GR32:$src, (xor (shl -1, GR8:$lz), -1)), + (BZHI32rr GR32:$src, + (INSERT_SUBREG (i32 (IMPLICIT_DEF)), GR8:$lz, sub_8bit))>; + + def : Pat<(and (loadi32 addr:$src), (xor (shl -1, GR8:$lz), -1)), + (BZHI32rm addr:$src, + (INSERT_SUBREG (i32 (IMPLICIT_DEF)), GR8:$lz, sub_8bit))>; + + def : Pat<(and GR64:$src, (xor (shl -1, GR8:$lz), -1)), + (BZHI64rr GR64:$src, + (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GR8:$lz, sub_8bit))>; + + def : Pat<(and (loadi64 addr:$src), (xor (shl -1, GR8:$lz), -1)), + (BZHI64rm addr:$src, + (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GR8:$lz, sub_8bit))>; + // x & (-1 >> (32 - y)) def : Pat<(and GR32:$src, (srl -1, (i8 (trunc (sub 32, GR32:$lz))))), (BZHI32rr GR32:$src, GR32:$lz)>; Index: test/CodeGen/X86/bmi-bzhi.ll =================================================================== --- test/CodeGen/X86/bmi-bzhi.ll +++ test/CodeGen/X86/bmi-bzhi.ll @@ -449,9 +449,7 @@ ; ; CHECK-BMI2-LABEL: bzhi32_b0: ; CHECK-BMI2: # %bb.0: -; CHECK-BMI2-NEXT: movl $-1, %eax -; CHECK-BMI2-NEXT: shlxl %esi, %eax, %eax -; CHECK-BMI2-NEXT: andnl %edi, %eax, %eax +; CHECK-BMI2-NEXT: bzhil %esi, %edi, %eax ; CHECK-BMI2-NEXT: retq %notmask = shl i32 -1, %numlowbits %mask = xor i32 %notmask, -1 @@ -479,9 +477,7 @@ ; ; CHECK-BMI2-LABEL: bzhi32_b1_indexzext: ; CHECK-BMI2: # %bb.0: -; CHECK-BMI2-NEXT: movl $-1, %eax -; CHECK-BMI2-NEXT: shlxl %esi, %eax, %eax -; CHECK-BMI2-NEXT: andnl %edi, %eax, %eax +; CHECK-BMI2-NEXT: bzhil %esi, %edi, %eax ; CHECK-BMI2-NEXT: retq %conv = zext i8 %numlowbits to i32 %notmask = shl i32 -1, %conv @@ -510,9 +506,7 @@ ; ; CHECK-BMI2-LABEL: bzhi32_b2_load: ; CHECK-BMI2: # %bb.0: -; CHECK-BMI2-NEXT: movl $-1, %eax -; CHECK-BMI2-NEXT: shlxl %esi, %eax, %eax -; CHECK-BMI2-NEXT: andnl (%rdi), %eax, %eax +; CHECK-BMI2-NEXT: bzhil %esi, (%rdi), %eax ; CHECK-BMI2-NEXT: retq %val = load i32, i32* %w %notmask = shl i32 -1, %numlowbits @@ -541,9 +535,7 @@ ; ; CHECK-BMI2-LABEL: bzhi32_b3_load_indexzext: ; CHECK-BMI2: # %bb.0: -; CHECK-BMI2-NEXT: movl $-1, %eax -; CHECK-BMI2-NEXT: shlxl %esi, %eax, %eax -; CHECK-BMI2-NEXT: andnl (%rdi), %eax, %eax +; CHECK-BMI2-NEXT: bzhil %esi, (%rdi), %eax ; CHECK-BMI2-NEXT: retq %val = load i32, i32* %w %conv = zext i8 %numlowbits to i32 @@ -573,9 +565,7 @@ ; ; CHECK-BMI2-LABEL: bzhi32_b4_commutative: ; CHECK-BMI2: # %bb.0: -; CHECK-BMI2-NEXT: movl $-1, %eax -; CHECK-BMI2-NEXT: shlxl %esi, %eax, %eax -; CHECK-BMI2-NEXT: andnl %edi, %eax, %eax +; CHECK-BMI2-NEXT: bzhil %esi, %edi, %eax ; CHECK-BMI2-NEXT: retq %notmask = shl i32 -1, %numlowbits %mask = xor i32 %notmask, -1 @@ -605,9 +595,7 @@ ; ; CHECK-BMI2-LABEL: bzhi32_b5_trunc16: ; CHECK-BMI2: # %bb.0: -; CHECK-BMI2-NEXT: movl $-1, %eax -; CHECK-BMI2-NEXT: shlxl %esi, %eax, %eax -; CHECK-BMI2-NEXT: andnl %edi, %eax, %eax +; CHECK-BMI2-NEXT: bzhil %esi, %edi, %eax ; CHECK-BMI2-NEXT: # kill: def $ax killed $ax killed $eax ; CHECK-BMI2-NEXT: retq %notmask = shl i32 -1, %numlowbits @@ -639,9 +627,7 @@ ; ; CHECK-BMI2-LABEL: bzhi64_b0: ; CHECK-BMI2: # %bb.0: -; CHECK-BMI2-NEXT: movq $-1, %rax -; CHECK-BMI2-NEXT: shlxq %rsi, %rax, %rax -; CHECK-BMI2-NEXT: andnq %rdi, %rax, %rax +; CHECK-BMI2-NEXT: bzhiq %rsi, %rdi, %rax ; CHECK-BMI2-NEXT: retq %notmask = shl i64 -1, %numlowbits %mask = xor i64 %notmask, -1 @@ -670,9 +656,7 @@ ; CHECK-BMI2-LABEL: bzhi64_b1_indexzext: ; CHECK-BMI2: # %bb.0: ; CHECK-BMI2-NEXT: # kill: def $esi killed $esi def $rsi -; CHECK-BMI2-NEXT: movq $-1, %rax -; CHECK-BMI2-NEXT: shlxq %rsi, %rax, %rax -; CHECK-BMI2-NEXT: andnq %rdi, %rax, %rax +; CHECK-BMI2-NEXT: bzhiq %rsi, %rdi, %rax ; CHECK-BMI2-NEXT: retq %conv = zext i8 %numlowbits to i64 %notmask = shl i64 -1, %conv @@ -701,9 +685,7 @@ ; ; CHECK-BMI2-LABEL: bzhi64_b2_load: ; CHECK-BMI2: # %bb.0: -; CHECK-BMI2-NEXT: movq $-1, %rax -; CHECK-BMI2-NEXT: shlxq %rsi, %rax, %rax -; CHECK-BMI2-NEXT: andnq (%rdi), %rax, %rax +; CHECK-BMI2-NEXT: bzhiq %rsi, (%rdi), %rax ; CHECK-BMI2-NEXT: retq %val = load i64, i64* %w %notmask = shl i64 -1, %numlowbits @@ -733,9 +715,7 @@ ; CHECK-BMI2-LABEL: bzhi64_b3_load_indexzext: ; CHECK-BMI2: # %bb.0: ; CHECK-BMI2-NEXT: # kill: def $esi killed $esi def $rsi -; CHECK-BMI2-NEXT: movq $-1, %rax -; CHECK-BMI2-NEXT: shlxq %rsi, %rax, %rax -; CHECK-BMI2-NEXT: andnq (%rdi), %rax, %rax +; CHECK-BMI2-NEXT: bzhiq %rsi, (%rdi), %rax ; CHECK-BMI2-NEXT: retq %val = load i64, i64* %w %conv = zext i8 %numlowbits to i64 @@ -765,9 +745,7 @@ ; ; CHECK-BMI2-LABEL: bzhi64_b4_commutative: ; CHECK-BMI2: # %bb.0: -; CHECK-BMI2-NEXT: movq $-1, %rax -; CHECK-BMI2-NEXT: shlxq %rsi, %rax, %rax -; CHECK-BMI2-NEXT: andnq %rdi, %rax, %rax +; CHECK-BMI2-NEXT: bzhiq %rsi, %rdi, %rax ; CHECK-BMI2-NEXT: retq %notmask = shl i64 -1, %numlowbits %mask = xor i64 %notmask, -1