forked from OSchip/llvm-project
[X86] Teach X86DAGToDAGISel::shrinkAndImmediate to preserve upper 32 zeroes of a 64 bit mask.
If the upper 32 bits of a 64 bit mask are all zeros, we have special isel patterns to use a 32-bit and instead of a 64-bit and by relying on the impliciting zeroing of 32 bit ops. This patch teachs shrinkAndImmediate not to break that optimization. Differential Revision: https://reviews.llvm.org/D42899 llvm-svn: 324249
This commit is contained in:
parent
22db17cf43
commit
57e0643160
|
@ -2486,14 +2486,24 @@ bool X86DAGToDAGISel::shrinkAndImmediate(SDNode *And) {
|
|||
if (!And1C)
|
||||
return false;
|
||||
|
||||
// Bail out if the mask constant is already negative. It can't shrink more.
|
||||
// Bail out if the mask constant is already negative. It's can't shrink more.
|
||||
// If the upper 32 bits of a 64 bit mask are all zeros, we have special isel
|
||||
// patterns to use a 32-bit and instead of a 64-bit and by relying on the
|
||||
// implicit zeroing of 32 bit ops. So we should check if the lower 32 bits
|
||||
// are negative too.
|
||||
APInt MaskVal = And1C->getAPIntValue();
|
||||
unsigned MaskLZ = MaskVal.countLeadingZeros();
|
||||
if (!MaskLZ)
|
||||
if (!MaskLZ || (VT == MVT::i64 && MaskLZ == 32))
|
||||
return false;
|
||||
|
||||
// Don't extend into the upper 32 bits of a 64 bit mask.
|
||||
if (VT == MVT::i64 && MaskLZ >= 32) {
|
||||
MaskLZ -= 32;
|
||||
MaskVal = MaskVal.trunc(32);
|
||||
}
|
||||
|
||||
SDValue And0 = And->getOperand(0);
|
||||
APInt HighZeros = APInt::getHighBitsSet(VT.getSizeInBits(), MaskLZ);
|
||||
APInt HighZeros = APInt::getHighBitsSet(MaskVal.getBitWidth(), MaskLZ);
|
||||
APInt NegMaskVal = MaskVal | HighZeros;
|
||||
|
||||
// If a negative constant would not allow a smaller encoding, there's no need
|
||||
|
@ -2502,6 +2512,12 @@ bool X86DAGToDAGISel::shrinkAndImmediate(SDNode *And) {
|
|||
if (MinWidth > 32 || (MinWidth > 8 && MaskVal.getMinSignedBits() <= 32))
|
||||
return false;
|
||||
|
||||
// Extend masks if we truncated above.
|
||||
if (VT == MVT::i64 && MaskVal.getBitWidth() < 64) {
|
||||
NegMaskVal = NegMaskVal.zext(64);
|
||||
HighZeros = HighZeros.zext(64);
|
||||
}
|
||||
|
||||
// The variable operand must be all zeros in the top bits to allow using the
|
||||
// new, negative constant as the mask.
|
||||
if (!CurDAG->MaskedValueIsZero(And0, HighZeros))
|
||||
|
|
|
@ -61,7 +61,7 @@ define i64 @lopped64_32to8(i64 %x) {
|
|||
; CHECK-LABEL: lopped64_32to8:
|
||||
; CHECK: # %bb.0:
|
||||
; CHECK-NEXT: shrq $36, %rdi # encoding: [0x48,0xc1,0xef,0x24]
|
||||
; CHECK-NEXT: andq $-16, %rdi # encoding: [0x48,0x83,0xe7,0xf0]
|
||||
; CHECK-NEXT: andl $-16, %edi # encoding: [0x83,0xe7,0xf0]
|
||||
; CHECK-NEXT: movq %rdi, %rax # encoding: [0x48,0x89,0xf8]
|
||||
; CHECK-NEXT: retq # encoding: [0xc3]
|
||||
%shr = lshr i64 %x, 36
|
||||
|
|
|
@ -5,7 +5,7 @@ define i64 @test(i64 %A) {
|
|||
; CHECK-LABEL: test:
|
||||
; CHECK: # %bb.0:
|
||||
; CHECK-NEXT: shrq $54, %rdi
|
||||
; CHECK-NEXT: andq $-4, %rdi
|
||||
; CHECK-NEXT: andl $-4, %edi
|
||||
; CHECK-NEXT: movq %rdi, %rax
|
||||
; CHECK-NEXT: retq
|
||||
%B = lshr i64 %A, 56
|
||||
|
|
Loading…
Reference in New Issue