summaryrefslogtreecommitdiffstats
path: root/llvm/lib/CodeGen
diff options
context:
space:
mode:
authorSimon Pilgrim <llvm-dev@redking.me.uk>2019-06-19 12:25:29 +0000
committerSimon Pilgrim <llvm-dev@redking.me.uk>2019-06-19 12:25:29 +0000
commit8c49366c9b9d02174c8e1821bbc319275d103fc5 (patch)
treeb03b74a97b76143769c1725004090b7e3e69e6a3 /llvm/lib/CodeGen
parent85f70baa230f25f965d7e324e7fadad2fe25c819 (diff)
downloadbcm5719-llvm-8c49366c9b9d02174c8e1821bbc319275d103fc5.tar.gz
bcm5719-llvm-8c49366c9b9d02174c8e1821bbc319275d103fc5.zip
[DAGCombiner] Support (shl (ext (shl x, c1)), c2) -> 0 non-uniform folds.
Use matchBinaryPredicate instead of isConstOrConstSplat to let us handle non-uniform shift cases. This requires us to tweak matchBinaryPredicate to allow it to (optionally) handle constants with different type widths. llvm-svn: 363792
Diffstat (limited to 'llvm/lib/CodeGen')
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp30
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp8
2 files changed, 27 insertions, 11 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 676cfbc859e..ae555ac0711 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -7210,19 +7210,35 @@ SDValue DAGCombiner::visitSHL(SDNode *N) {
// that are shifted out by the inner shift in the first form. This means
// the outer shift size must be >= the number of bits added by the ext.
// As a corollary, we don't care what kind of ext it is.
- if (N1C && (N0.getOpcode() == ISD::ZERO_EXTEND ||
- N0.getOpcode() == ISD::ANY_EXTEND ||
- N0.getOpcode() == ISD::SIGN_EXTEND) &&
+ if ((N0.getOpcode() == ISD::ZERO_EXTEND ||
+ N0.getOpcode() == ISD::ANY_EXTEND ||
+ N0.getOpcode() == ISD::SIGN_EXTEND) &&
N0.getOperand(0).getOpcode() == ISD::SHL) {
SDValue N0Op0 = N0.getOperand(0);
- if (ConstantSDNode *N0Op0C1 = isConstOrConstSplat(N0Op0.getOperand(1))) {
+ SDValue InnerShiftAmt = N0Op0.getOperand(1);
+ EVT InnerVT = N0Op0.getValueType();
+ uint64_t InnerBitwidth = InnerVT.getScalarSizeInBits();
+
+ auto MatchOutOfRange = [OpSizeInBits, InnerBitwidth](ConstantSDNode *LHS,
+ ConstantSDNode *RHS) {
+ APInt c1 = LHS->getAPIntValue();
+ APInt c2 = RHS->getAPIntValue();
+ zeroExtendToMatch(c1, c2, 1 /* Overflow Bit */);
+ return c2.uge(OpSizeInBits - InnerBitwidth) &&
+ (c1 + c2).uge(OpSizeInBits);
+ };
+ if (ISD::matchBinaryPredicate(InnerShiftAmt, N1, MatchOutOfRange,
+ /*AllowUndefs*/ false,
+ /*AllowTypeMismatch*/ true))
+ return DAG.getConstant(0, SDLoc(N), VT);
+
+ ConstantSDNode *N0Op0C1 = isConstOrConstSplat(InnerShiftAmt);
+ if (N1C && N0Op0C1) {
APInt c1 = N0Op0C1->getAPIntValue();
APInt c2 = N1C->getAPIntValue();
zeroExtendToMatch(c1, c2, 1 /* Overflow Bit */);
- EVT InnerShiftVT = N0Op0.getValueType();
- uint64_t InnerShiftSize = InnerShiftVT.getScalarSizeInBits();
- if (c2.uge(OpSizeInBits - InnerShiftSize)) {
+ if (c2.uge(OpSizeInBits - InnerBitwidth)) {
SDLoc DL(N0);
APInt Sum = c1 + c2;
if (Sum.uge(OpSizeInBits))
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index fea8d7ad894..a2eca91c67e 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -294,8 +294,8 @@ bool ISD::matchUnaryPredicate(SDValue Op,
bool ISD::matchBinaryPredicate(
SDValue LHS, SDValue RHS,
std::function<bool(ConstantSDNode *, ConstantSDNode *)> Match,
- bool AllowUndefs) {
- if (LHS.getValueType() != RHS.getValueType())
+ bool AllowUndefs, bool AllowTypeMismatch) {
+ if (!AllowTypeMismatch && LHS.getValueType() != RHS.getValueType())
return false;
// TODO: Add support for scalar UNDEF cases?
@@ -318,8 +318,8 @@ bool ISD::matchBinaryPredicate(
auto *RHSCst = dyn_cast<ConstantSDNode>(RHSOp);
if ((!LHSCst && !LHSUndef) || (!RHSCst && !RHSUndef))
return false;
- if (LHSOp.getValueType() != SVT ||
- LHSOp.getValueType() != RHSOp.getValueType())
+ if (!AllowTypeMismatch && (LHSOp.getValueType() != SVT ||
+ LHSOp.getValueType() != RHSOp.getValueType()))
return false;
if (!Match(LHSCst, RHSCst))
return false;
OpenPOWER on IntegriCloud