summaryrefslogtreecommitdiff
path: root/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp')
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp68
1 files changed, 56 insertions, 12 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 4fcbe08e4b2b..254d63abdf80 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -2575,13 +2575,13 @@ SDValue DAGCombiner::foldSubToAvg(SDNode *N, const SDLoc &DL) {
EVT VT = N0.getValueType();
SDValue A, B;
- if (hasOperation(ISD::AVGCEILU, VT) &&
+ if ((!LegalOperations || hasOperation(ISD::AVGCEILU, VT)) &&
sd_match(N, m_Sub(m_Or(m_Value(A), m_Value(B)),
m_Srl(m_Xor(m_Deferred(A), m_Deferred(B)),
m_SpecificInt(1))))) {
return DAG.getNode(ISD::AVGCEILU, DL, VT, A, B);
}
- if (hasOperation(ISD::AVGCEILS, VT) &&
+ if ((!LegalOperations || hasOperation(ISD::AVGCEILS, VT)) &&
sd_match(N, m_Sub(m_Or(m_Value(A), m_Value(B)),
m_Sra(m_Xor(m_Deferred(A), m_Deferred(B)),
m_SpecificInt(1))))) {
@@ -2947,13 +2947,13 @@ SDValue DAGCombiner::foldAddToAvg(SDNode *N, const SDLoc &DL) {
EVT VT = N0.getValueType();
SDValue A, B;
- if (hasOperation(ISD::AVGFLOORU, VT) &&
+ if ((!LegalOperations || hasOperation(ISD::AVGFLOORU, VT)) &&
sd_match(N, m_Add(m_And(m_Value(A), m_Value(B)),
m_Srl(m_Xor(m_Deferred(A), m_Deferred(B)),
m_SpecificInt(1))))) {
return DAG.getNode(ISD::AVGFLOORU, DL, VT, A, B);
}
- if (hasOperation(ISD::AVGFLOORS, VT) &&
+ if ((!LegalOperations || hasOperation(ISD::AVGFLOORS, VT)) &&
sd_match(N, m_Add(m_And(m_Value(A), m_Value(B)),
m_Sra(m_Xor(m_Deferred(A), m_Deferred(B)),
m_SpecificInt(1))))) {
@@ -4326,6 +4326,7 @@ template <class MatchContextClass> SDValue DAGCombiner::visitMUL(SDNode *N) {
SDValue N0 = N->getOperand(0);
SDValue N1 = N->getOperand(1);
EVT VT = N0.getValueType();
+ unsigned BitWidth = VT.getScalarSizeInBits();
SDLoc DL(N);
bool UseVP = std::is_same_v<MatchContextClass, VPMatchContext>;
MatchContextClass Matcher(DAG, TLI, N);
@@ -4355,8 +4356,7 @@ template <class MatchContextClass> SDValue DAGCombiner::visitMUL(SDNode *N) {
return FoldedVOp;
N1IsConst = ISD::isConstantSplatVector(N1.getNode(), ConstValue1);
- assert((!N1IsConst ||
- ConstValue1.getBitWidth() == VT.getScalarSizeInBits()) &&
+ assert((!N1IsConst || ConstValue1.getBitWidth() == BitWidth) &&
"Splat APInt should be element width");
} else {
N1IsConst = isa<ConstantSDNode>(N1);
@@ -4456,7 +4456,7 @@ template <class MatchContextClass> SDValue DAGCombiner::visitMUL(SDNode *N) {
unsigned ShAmt =
MathOp == ISD::ADD ? (MulC - 1).logBase2() : (MulC + 1).logBase2();
ShAmt += TZeros;
- assert(ShAmt < VT.getScalarSizeInBits() &&
+ assert(ShAmt < BitWidth &&
"multiply-by-constant generated out of bounds shift");
SDValue Shl =
DAG.getNode(ISD::SHL, DL, VT, N0, DAG.getConstant(ShAmt, DL, VT));
@@ -4525,6 +4525,16 @@ template <class MatchContextClass> SDValue DAGCombiner::visitMUL(SDNode *N) {
return DAG.getStepVector(DL, VT, NewStep);
}
+ // Fold Y = sra (X, size(X)-1); mul (or (Y, 1), X) -> (abs X)
+ SDValue X;
+ if (!UseVP && (!LegalOperations || hasOperation(ISD::ABS, VT)) &&
+ sd_context_match(
+ N, Matcher,
+ m_Mul(m_Or(m_Sra(m_Value(X), m_SpecificInt(BitWidth - 1)), m_One()),
+ m_Deferred(X)))) {
+ return Matcher.getNode(ISD::ABS, DL, VT, X);
+ }
+
// Fold ((mul x, 0/undef) -> 0,
// (mul x, 1) -> x) -> x)
// -> and(x, mask)
@@ -5203,6 +5213,7 @@ SDValue DAGCombiner::visitAVG(SDNode *N) {
SDValue N1 = N->getOperand(1);
EVT VT = N->getValueType(0);
SDLoc DL(N);
+ bool IsSigned = Opcode == ISD::AVGCEILS || Opcode == ISD::AVGFLOORS;
// fold (avg c1, c2)
if (SDValue C = DAG.FoldConstantArithmetic(Opcode, DL, VT, {N0, N1}))
@@ -5228,7 +5239,7 @@ SDValue DAGCombiner::visitAVG(SDNode *N) {
return N0;
// fold (avgfloor x, 0) -> x >> 1
- SDValue X;
+ SDValue X, Y;
if (sd_match(N, m_c_BinOp(ISD::AVGFLOORS, m_Value(X), m_Zero())))
return DAG.getNode(ISD::SRA, DL, VT, X,
DAG.getShiftAmountConstant(1, VT, DL));
@@ -5236,6 +5247,38 @@ SDValue DAGCombiner::visitAVG(SDNode *N) {
return DAG.getNode(ISD::SRL, DL, VT, X,
DAG.getShiftAmountConstant(1, VT, DL));
+ // fold avgu(zext(x), zext(y)) -> zext(avgu(x, y))
+ // fold avgs(sext(x), sext(y)) -> sext(avgs(x, y))
+ if (!IsSigned &&
+ sd_match(N, m_BinOp(Opcode, m_ZExt(m_Value(X)), m_ZExt(m_Value(Y)))) &&
+ X.getValueType() == Y.getValueType() &&
+ hasOperation(Opcode, X.getValueType())) {
+ SDValue AvgU = DAG.getNode(Opcode, DL, X.getValueType(), X, Y);
+ return DAG.getNode(ISD::ZERO_EXTEND, DL, VT, AvgU);
+ }
+ if (IsSigned &&
+ sd_match(N, m_BinOp(Opcode, m_SExt(m_Value(X)), m_SExt(m_Value(Y)))) &&
+ X.getValueType() == Y.getValueType() &&
+ hasOperation(Opcode, X.getValueType())) {
+ SDValue AvgS = DAG.getNode(Opcode, DL, X.getValueType(), X, Y);
+ return DAG.getNode(ISD::SIGN_EXTEND, DL, VT, AvgS);
+ }
+
+ // Fold avgflooru(x,y) -> avgceilu(x,y-1) iff y != 0
+ // Fold avgflooru(x,y) -> avgceilu(x-1,y) iff x != 0
+ // Check if avgflooru isn't legal/custom but avgceilu is.
+ if (Opcode == ISD::AVGFLOORU && !hasOperation(ISD::AVGFLOORU, VT) &&
+ (!LegalOperations || hasOperation(ISD::AVGCEILU, VT))) {
+ if (DAG.isKnownNeverZero(N1))
+ return DAG.getNode(
+ ISD::AVGCEILU, DL, VT, N0,
+ DAG.getNode(ISD::ADD, DL, VT, N1, DAG.getAllOnesConstant(DL, VT)));
+ if (DAG.isKnownNeverZero(N0))
+ return DAG.getNode(
+ ISD::AVGCEILU, DL, VT, N1,
+ DAG.getNode(ISD::ADD, DL, VT, N0, DAG.getAllOnesConstant(DL, VT)));
+ }
+
return SDValue();
}
@@ -26417,12 +26460,13 @@ SDValue DAGCombiner::visitINSERT_SUBVECTOR(SDNode *N) {
return N1.getOperand(0);
// TODO: To remove the zero check, need to adjust the offset to
// a multiple of the new src type.
- if (isNullConstant(N2) &&
- VT.isScalableVector() == SrcVT.isScalableVector()) {
- if (VT.getVectorMinNumElements() >= SrcVT.getVectorMinNumElements())
+ if (isNullConstant(N2)) {
+ if (VT.knownBitsGE(SrcVT) &&
+ !(VT.isFixedLengthVector() && SrcVT.isScalableVector()))
return DAG.getNode(ISD::INSERT_SUBVECTOR, SDLoc(N),
VT, N0, N1.getOperand(0), N2);
- else
+ else if (VT.knownBitsLE(SrcVT) &&
+ !(VT.isScalableVector() && SrcVT.isFixedLengthVector()))
return DAG.getNode(ISD::EXTRACT_SUBVECTOR, SDLoc(N),
VT, N1.getOperand(0), N2);
}