Index: llvm/trunk/lib/Target/X86/X86InstrInfo.td =================================================================== --- llvm/trunk/lib/Target/X86/X86InstrInfo.td +++ llvm/trunk/lib/Target/X86/X86InstrInfo.td @@ -844,6 +844,7 @@ def HasFMA4 : Predicate<"Subtarget->hasFMA4()">; def HasXOP : Predicate<"Subtarget->hasXOP()">; def HasTBM : Predicate<"Subtarget->hasTBM()">; +def NoTBM : Predicate<"!Subtarget->hasTBM()">; def HasLWP : Predicate<"Subtarget->hasLWP()">; def HasMOVBE : Predicate<"Subtarget->hasMOVBE()">; def HasRDRAND : Predicate<"Subtarget->hasRDRAND()">; @@ -853,6 +854,7 @@ def HasLZCNT : Predicate<"Subtarget->hasLZCNT()">; def HasBMI : Predicate<"Subtarget->hasBMI()">; def HasBMI2 : Predicate<"Subtarget->hasBMI2()">; +def NoBMI2 : Predicate<"!Subtarget->hasBMI2()">; def HasVBMI : Predicate<"Subtarget->hasVBMI()">, AssemblerPredicate<"FeatureVBMI", "AVX-512 VBMI ISA">; def HasIFMA : Predicate<"Subtarget->hasIFMA()">, @@ -2352,20 +2354,40 @@ return getI8Imm(countTrailingOnes(N->getZExtValue()), SDLoc(N)); }]>; -def BZHIMask : ImmLeaf(Imm) > 32); -}]>; - -let Predicates = [HasBMI2] in { - def : Pat<(and GR64:$src, BZHIMask:$mask), +def BEXTRMaskXForm : SDNodeXFormgetZExtValue()); + return getI32Imm(Length << 8, SDLoc(N)); +}]>; + +def AndMask64 : ImmLeaf UINT32_MAX; +}]>; + +// Use BEXTR for 64-bit 'and' with large immediate 'mask'. +let Predicates = [HasBMI, NoBMI2, NoTBM] in { + def : Pat<(and GR64:$src, AndMask64:$mask), + (BEXTR64rr GR64:$src, + (SUBREG_TO_REG (i64 0), + (MOV32ri (BEXTRMaskXForm imm:$mask)), sub_32bit))>; + def : Pat<(and (loadi64 addr:$src), AndMask64:$mask), + (BEXTR64rm addr:$src, + (SUBREG_TO_REG (i64 0), + (MOV32ri (BEXTRMaskXForm imm:$mask)), sub_32bit))>; +} + +// Use BZHI for 64-bit 'and' with large immediate 'mask'. +let Predicates = [HasBMI2, NoTBM] in { + def : Pat<(and GR64:$src, AndMask64:$mask), (BZHI64rr GR64:$src, (INSERT_SUBREG (i64 (IMPLICIT_DEF)), (MOV8ri (CountTrailingOnes imm:$mask)), sub_8bit))>; - def : Pat<(and (loadi64 addr:$src), BZHIMask:$mask), + def : Pat<(and (loadi64 addr:$src), AndMask64:$mask), (BZHI64rm addr:$src, (INSERT_SUBREG (i64 (IMPLICIT_DEF)), (MOV8ri (CountTrailingOnes imm:$mask)), sub_8bit))>; +} +let Predicates = [HasBMI2] in { def : Pat<(and GR32:$src, (add (shl 1, GR8:$lz), -1)), (BZHI32rr GR32:$src, (INSERT_SUBREG (i32 (IMPLICIT_DEF)), GR8:$lz, sub_8bit))>; @@ -2511,6 +2533,15 @@ defm TZMSK : tbm_binary_intr<0x01, "tzmsk", MRM4r, MRM4m>; } // HasTBM, EFLAGS +// Use BEXTRI for 64-bit 'and' with large immediate 'mask'. +let Predicates = [HasTBM] in { + def : Pat<(and GR64:$src, AndMask64:$mask), + (BEXTRI64ri GR64:$src, (BEXTRMaskXForm imm:$mask))>; + + def : Pat<(and (loadi64 addr:$src), AndMask64:$mask), + (BEXTRI64mi addr:$src, (BEXTRMaskXForm imm:$mask))>; +} + //===----------------------------------------------------------------------===// // Lightweight Profiling Instructions Index: llvm/trunk/test/CodeGen/X86/bmi.ll =================================================================== --- llvm/trunk/test/CodeGen/X86/bmi.ll +++ llvm/trunk/test/CodeGen/X86/bmi.ll @@ -612,8 +612,8 @@ define i64 @bzhi64_constant_mask(i64 %x) { ; BMI1-LABEL: bzhi64_constant_mask: ; BMI1: # BB#0: # %entry -; BMI1-NEXT: movabsq $4611686018427387903, %rax # imm = 0x3FFFFFFFFFFFFFFF -; BMI1-NEXT: andq %rdi, %rax +; BMI1-NEXT: movl $15872, %eax # imm = 0x3E00 +; BMI1-NEXT: bextrq %rax, %rdi, %rax ; BMI1-NEXT: retq ; ; BMI2-LABEL: bzhi64_constant_mask: @@ -629,8 +629,8 @@ define i64 @bzhi64_constant_mask_load(i64* %x) { ; BMI1-LABEL: bzhi64_constant_mask_load: ; BMI1: # BB#0: # %entry -; BMI1-NEXT: movabsq $4611686018427387903, %rax # imm = 0x3FFFFFFFFFFFFFFF -; BMI1-NEXT: andq (%rdi), %rax +; BMI1-NEXT: movl $15872, %eax # imm = 0x3E00 +; BMI1-NEXT: bextrq %rax, (%rdi), %rax ; BMI1-NEXT: retq ; ; BMI2-LABEL: bzhi64_constant_mask_load: Index: llvm/trunk/test/CodeGen/X86/tbm_patterns.ll =================================================================== --- llvm/trunk/test/CodeGen/X86/tbm_patterns.ll +++ llvm/trunk/test/CodeGen/X86/tbm_patterns.ll @@ -253,3 +253,23 @@ ret i64 %t2 } +define i64 @test_and_large_constant_mask(i64 %x) { +; CHECK-LABEL: test_and_large_constant_mask: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: bextr $15872, %rdi, %rax # imm = 0x3E00 +; CHECK-NEXT: retq +entry: + %and = and i64 %x, 4611686018427387903 + ret i64 %and +} + +define i64 @test_and_large_constant_mask_load(i64* %x) { +; CHECK-LABEL: test_and_large_constant_mask_load: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: bextr $15872, (%rdi), %rax # imm = 0x3E00 +; CHECK-NEXT: retq +entry: + %x1 = load i64, i64* %x + %and = and i64 %x1, 4611686018427387903 + ret i64 %and +}