[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:
Craig Topper 2018-02-05 16:54:07 +00:00
parent 22db17cf43
commit 57e0643160
3 changed files with 21 additions and 5 deletions

View File

@ -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))

View File

@ -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

View File

@ -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