Change this DAGCombine to build AND of SHR instead of SHR of AND; this matches the ordering we prefer in instcombine. Part of rdar://9562809.

The potential DAGCombine which enforces this more generally messes up some other very fragile patterns, so I'm leaving that alone, at least for now.



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@132809 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Eli Friedman 2011-06-09 22:14:44 +00:00
parent a899b22310
commit 2a6d9eb10b
2 changed files with 27 additions and 15 deletions

View File

@ -3092,26 +3092,27 @@ SDValue DAGCombiner::visitSHL(SDNode *N) {
} }
} }
// fold (shl (srl x, c1), c2) -> (shl (and x, (shl -1, c1)), (sub c2, c1)) or // fold (shl (srl x, c1), c2) -> (and (shl x, (sub c2, c1), MASK) or
// (srl (and x, (shl -1, c1)), (sub c1, c2)) // (and (srl x, (sub c1, c2), MASK)
if (N1C && N0.getOpcode() == ISD::SRL && if (N1C && N0.getOpcode() == ISD::SRL &&
N0.getOperand(1).getOpcode() == ISD::Constant) { N0.getOperand(1).getOpcode() == ISD::Constant) {
uint64_t c1 = cast<ConstantSDNode>(N0.getOperand(1))->getZExtValue(); uint64_t c1 = cast<ConstantSDNode>(N0.getOperand(1))->getZExtValue();
if (c1 < VT.getSizeInBits()) { if (c1 < VT.getSizeInBits()) {
uint64_t c2 = N1C->getZExtValue(); uint64_t c2 = N1C->getZExtValue();
SDValue HiBitsMask = APInt Mask = APInt::getHighBitsSet(VT.getSizeInBits(),
DAG.getConstant(APInt::getHighBitsSet(VT.getSizeInBits(), VT.getSizeInBits() - c1);
VT.getSizeInBits() - c1), SDValue Shift;
VT); if (c2 > c1) {
SDValue Mask = DAG.getNode(ISD::AND, N0.getDebugLoc(), VT, Mask = Mask.shl(c2-c1);
N0.getOperand(0), Shift = DAG.getNode(ISD::SHL, N->getDebugLoc(), VT, N0.getOperand(0),
HiBitsMask); DAG.getConstant(c2-c1, N1.getValueType()));
if (c2 > c1) } else {
return DAG.getNode(ISD::SHL, N->getDebugLoc(), VT, Mask, Mask = Mask.lshr(c1-c2);
DAG.getConstant(c2-c1, N1.getValueType())); Shift = DAG.getNode(ISD::SRL, N->getDebugLoc(), VT, N0.getOperand(0),
else DAG.getConstant(c1-c2, N1.getValueType()));
return DAG.getNode(ISD::SRL, N->getDebugLoc(), VT, Mask, }
DAG.getConstant(c1-c2, N1.getValueType())); return DAG.getNode(ISD::AND, N0.getDebugLoc(), VT, Shift,
DAG.getConstant(Mask, VT));
} }
} }
// fold (shl (sra x, c1), c1) -> (and x, (shl -1, c1)) // fold (shl (sra x, c1), c1) -> (and x, (shl -1, c1))

View File

@ -0,0 +1,11 @@
; RUN: llc < %s -march=x86-64 | FileCheck %s
define i64 @test(i64 %A) {
; CHECK: @test
; CHECK: shrq $54
; CHECK: andq $1020
; CHECK: ret
%B = lshr i64 %A, 56
%C = shl i64 %B, 2
ret i64 %C
}