diff options
Diffstat (limited to 'llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp')
| -rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 68 |
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); } |
