diff options
Diffstat (limited to 'llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp')
| -rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 43 |
1 files changed, 25 insertions, 18 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index d14615dcbc5e..701a76c4cc6b 100644 --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -7206,24 +7206,29 @@ static SDValue foldLogicTreeOfShifts(SDNode *N, SDValue LeftHand, return DAG.getNode(LogicOpcode, DL, VT, CombinedShifts, W); } -/// Fold "masked merge" expressions like `(m & x) | (~m & y)` into the -/// equivalent `((x ^ y) & m) ^ y)` pattern. -/// This is typically a better representation for targets without a fused -/// "and-not" operation. +/// Fold "masked merge" expressions like `(m & x) | (~m & y)` and its DeMorgan +/// variant `(~m | x) & (m | y)` into the equivalent `((x ^ y) & m) ^ y)` +/// pattern. This is typically a better representation for targets without a +/// fused "and-not" operation. static SDValue foldMaskedMerge(SDNode *Node, SelectionDAG &DAG, const TargetLowering &TLI, const SDLoc &DL) { // Note that masked-merge variants using XOR or ADD expressions are - // normalized to OR by InstCombine so we only check for OR. - assert(Node->getOpcode() == ISD::OR && "Must be called with ISD::OR node"); + // normalized to OR by InstCombine so we only check for OR or AND. + assert((Node->getOpcode() == ISD::OR || Node->getOpcode() == ISD::AND) && + "Must be called with ISD::OR or ISD::AND node"); // If the target supports and-not, don't fold this. if (TLI.hasAndNot(SDValue(Node, 0))) return SDValue(); SDValue M, X, Y; + if (sd_match(Node, m_Or(m_OneUse(m_And(m_OneUse(m_Not(m_Value(M))), m_Value(Y))), - m_OneUse(m_And(m_Deferred(M), m_Value(X)))))) { + m_OneUse(m_And(m_Deferred(M), m_Value(X))))) || + sd_match(Node, + m_And(m_OneUse(m_Or(m_OneUse(m_Not(m_Value(M))), m_Value(X))), + m_OneUse(m_Or(m_Deferred(M), m_Value(Y)))))) { EVT VT = M.getValueType(); SDValue Xor = DAG.getNode(ISD::XOR, DL, VT, X, Y); SDValue And = DAG.getNode(ISD::AND, DL, VT, Xor, M); @@ -7678,6 +7683,10 @@ SDValue DAGCombiner::visitAND(SDNode *N) { if (SDValue R = foldLogicTreeOfShifts(N, N0, N1, DAG)) return R; + if (VT.isScalarInteger() && VT != MVT::i1) + if (SDValue R = foldMaskedMerge(N, DAG, TLI, DL)) + return R; + return SDValue(); } @@ -11260,19 +11269,13 @@ SDValue DAGCombiner::foldABSToABD(SDNode *N, const SDLoc &DL) { if (N->getOpcode() == ISD::TRUNCATE) N = N->getOperand(0).getNode(); - if (N->getOpcode() != ISD::ABS) - return SDValue(); - EVT VT = N->getValueType(0); - SDValue AbsOp1 = N->getOperand(0); SDValue Op0, Op1; - if (AbsOp1.getOpcode() != ISD::SUB) + if (!sd_match(N, m_Abs(m_Sub(m_Value(Op0), m_Value(Op1))))) return SDValue(); - Op0 = AbsOp1.getOperand(0); - Op1 = AbsOp1.getOperand(1); - + SDValue AbsOp0 = N->getOperand(0); unsigned Opc0 = Op0.getOpcode(); // Check if the operands of the sub are (zero|sign)-extended. @@ -11282,7 +11285,7 @@ SDValue DAGCombiner::foldABSToABD(SDNode *N, const SDLoc &DL) { Opc0 != ISD::SIGN_EXTEND_INREG)) { // fold (abs (sub nsw x, y)) -> abds(x, y) // Don't fold this for unsupported types as we lose the NSW handling. - if (AbsOp1->getFlags().hasNoSignedWrap() && hasOperation(ISD::ABDS, VT) && + if (AbsOp0->getFlags().hasNoSignedWrap() && hasOperation(ISD::ABDS, VT) && TLI.preferABDSToABSWithNSW(VT)) { SDValue ABD = DAG.getNode(ISD::ABDS, DL, VT, Op0, Op1); return DAG.getZExtOrTrunc(ABD, DL, SrcVT); @@ -15736,8 +15739,12 @@ SDValue DAGCombiner::visitTRUNCATE(SDNode *N) { N0.getOpcode() == ISD::SIGN_EXTEND || N0.getOpcode() == ISD::ANY_EXTEND) { // if the source is smaller than the dest, we still need an extend. - if (N0.getOperand(0).getValueType().bitsLT(VT)) - return DAG.getNode(N0.getOpcode(), DL, VT, N0.getOperand(0)); + if (N0.getOperand(0).getValueType().bitsLT(VT)) { + SDNodeFlags Flags; + if (N0.getOpcode() == ISD::ZERO_EXTEND) + Flags.setNonNeg(N0->getFlags().hasNonNeg()); + return DAG.getNode(N0.getOpcode(), DL, VT, N0.getOperand(0), Flags); + } // if the source is larger than the dest, than we just need the truncate. if (N0.getOperand(0).getValueType().bitsGT(VT)) return DAG.getNode(ISD::TRUNCATE, DL, VT, N0.getOperand(0)); |
