From 998011927000c8150499bb887ca0d68bb1ff38c2 Mon Sep 17 00:00:00 2001 From: Nate Begeman Date: Wed, 7 Sep 2005 23:25:52 +0000 Subject: [PATCH] Another round of dag combiner changes. This fixes some missing XOR folds as well as fixing how we replace old values with new values. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23260 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 57 +++++++++++++++++------ lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 8 ++-- 2 files changed, 48 insertions(+), 17 deletions(-) diff --git a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index d5ace37f6dd..945c21fb615 100644 --- a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -223,11 +223,11 @@ static bool isSetCCEquivalent(SDOperand N, SDOperand &LHS, SDOperand &RHS, return false; } -// isInvertibleForFree - Return true if there is no cost to emitting the logical -// inverse of this node. -static bool isInvertibleForFree(SDOperand N) { +// isOneUseSetCC - Return true if this is a SetCC-equivalent operation with only +// one use. If this is true, it allows the users to invert the operation for +// free when it is profitable to do so. +static bool isOneUseSetCC(SDOperand N) { SDOperand N0, N1, N2; - if (isa(N.Val)) return true; if (isSetCCEquivalent(N, N0, N1, N2) && N.Val->hasOneUse()) return true; return false; @@ -270,7 +270,7 @@ void DAGCombiner::Run(bool RunningAfterLegalize) { DEBUG(std::cerr << "\nReplacing "; N->dump(); std::cerr << "\nWith: "; RV.Val->dump(); std::cerr << '\n'); - DAG.ReplaceAllUsesWith(SDOperand(N, 0), RV); + DAG.ReplaceAllUsesWith(N, std::vector(1, RV)); // Push the new node and any users onto the worklist WorkList.push_back(RV.Val); @@ -347,6 +347,11 @@ SDOperand DAGCombiner::visitADD(SDNode *N) { // fold (add c1, c2) -> c1+c2 if (N0C && N1C) return DAG.getConstant(N0C->getValue() + N1C->getValue(), VT); + // canonicalize constant to RHS + if (N0C && !N1C) { + std::swap(N0, N1); + std::swap(N0C, N1C); + } // fold (add x, 0) -> x if (N1C && N1C->isNullValue()) return N0; @@ -426,6 +431,11 @@ SDOperand DAGCombiner::visitMUL(SDNode *N) { if (N0C && N1C) return DAG.getConstant(N0C->getValue() * N1C->getValue(), N->getValueType(0)); + // canonicalize constant to RHS + if (N0C && !N1C) { + std::swap(N0, N1); + std::swap(N0C, N1C); + } // fold (mul x, 0) -> 0 if (N1C && N1C->isNullValue()) return N1; @@ -556,6 +566,11 @@ SDOperand DAGCombiner::visitAND(SDNode *N) { // fold (and c1, c2) -> c1&c2 if (N0C && N1C) return DAG.getConstant(N0C->getValue() & N1C->getValue(), VT); + // canonicalize constant to RHS + if (N0C && !N1C) { + std::swap(N0, N1); + std::swap(N0C, N1C); + } // fold (and x, -1) -> x if (N1C && N1C->isAllOnesValue()) return N0; @@ -593,6 +608,11 @@ SDOperand DAGCombiner::visitOR(SDNode *N) { if (N0C && N1C) return DAG.getConstant(N0C->getValue() | N1C->getValue(), N->getValueType(0)); + // canonicalize constant to RHS + if (N0C && !N1C) { + std::swap(N0, N1); + std::swap(N0C, N1C); + } // fold (or x, 0) -> x if (N1C && N1C->isNullValue()) return N0; @@ -617,6 +637,11 @@ SDOperand DAGCombiner::visitXOR(SDNode *N) { // fold (xor c1, c2) -> c1^c2 if (N0C && N1C) return DAG.getConstant(N0C->getValue() ^ N1C->getValue(), VT); + // canonicalize constant to RHS + if (N0C && !N1C) { + std::swap(N0, N1); + std::swap(N0C, N1C); + } // fold (xor x, 0) -> x if (N1C && N1C->isNullValue()) return N0; @@ -632,22 +657,28 @@ SDOperand DAGCombiner::visitXOR(SDNode *N) { assert(0 && "Unhandled SetCC Equivalent!"); abort(); } - // fold !(x or y) -> (!x and !y) iff x or y are freely invertible - if (N1C && N1C->isAllOnesValue() && N0.getOpcode() == ISD::OR) { + // fold !(x or y) -> (!x and !y) iff x or y are setcc + if (N1C && N1C->getValue() == 1 && + (N0.getOpcode() == ISD::OR || N0.getOpcode() == ISD::AND)) { SDOperand LHS = N0.getOperand(0), RHS = N0.getOperand(1); - if (isInvertibleForFree(RHS) || isInvertibleForFree(LHS)) { + if (isOneUseSetCC(RHS) || isOneUseSetCC(LHS)) { + unsigned NewOpcode = N0.getOpcode() == ISD::AND ? ISD::OR : ISD::AND; LHS = DAG.getNode(ISD::XOR, VT, LHS, N1); // RHS = ~LHS RHS = DAG.getNode(ISD::XOR, VT, RHS, N1); // RHS = ~RHS - return DAG.getNode(ISD::AND, VT, LHS, RHS); + WorkList.push_back(LHS.Val); WorkList.push_back(RHS.Val); + return DAG.getNode(NewOpcode, VT, LHS, RHS); } } - // fold !(x and y) -> (!x or !y) iff x or y are freely invertible - if (N1C && N1C->isAllOnesValue() && N0.getOpcode() == ISD::AND) { + // fold !(x or y) -> (!x and !y) iff x or y are constants + if (N1C && N1C->isAllOnesValue() && + (N0.getOpcode() == ISD::OR || N0.getOpcode() == ISD::AND)) { SDOperand LHS = N0.getOperand(0), RHS = N0.getOperand(1); - if (isInvertibleForFree(RHS) || isInvertibleForFree(LHS)) { + if (isa(RHS) || isa(LHS)) { + unsigned NewOpcode = N0.getOpcode() == ISD::AND ? ISD::OR : ISD::AND; LHS = DAG.getNode(ISD::XOR, VT, LHS, N1); // RHS = ~LHS RHS = DAG.getNode(ISD::XOR, VT, RHS, N1); // RHS = ~RHS - return DAG.getNode(ISD::OR, VT, LHS, RHS); + WorkList.push_back(LHS.Val); WorkList.push_back(RHS.Val); + return DAG.getNode(NewOpcode, VT, LHS, RHS); } } return SDOperand(); diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index 3aaf5c6043d..7d9f79fed3a 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -1256,7 +1256,6 @@ SDOperand SelectionDAG::getNode(unsigned Opcode, MVT::ValueType VT, ConstantSDNode *N2C = dyn_cast(N2.Val); if (N1C) { if (N2C) { - if (!CombinerEnabled) { uint64_t C1 = N1C->getValue(), C2 = N2C->getValue(); switch (Opcode) { case ISD::ADD: return getConstant(C1 + C2, VT); @@ -1284,7 +1283,6 @@ SDOperand SelectionDAG::getNode(unsigned Opcode, MVT::ValueType VT, case ISD::SRA : return getConstant(N1C->getSignExtended() >>(int)C2, VT); default: break; } - } } else { // Cannonicalize constant to RHS if commutative if (isCommutativeBinOp(Opcode)) { std::swap(N1C, N2C); @@ -1315,6 +1313,7 @@ SDOperand SelectionDAG::getNode(unsigned Opcode, MVT::ValueType VT, if (N2C) { uint64_t C2 = N2C->getValue(); + if (!CombinerEnabled) { switch (Opcode) { case ISD::ADD: if (!C2) return N1; // add X, 0 -> X @@ -1481,6 +1480,7 @@ SDOperand SelectionDAG::getNode(unsigned Opcode, MVT::ValueType VT, } break; } + } // Reassociate ((X op C1) op C2) if possible. if (N1.getOpcode() == Opcode && isAssociativeBinOp(Opcode)) @@ -1493,7 +1493,6 @@ SDOperand SelectionDAG::getNode(unsigned Opcode, MVT::ValueType VT, ConstantFPSDNode *N2CFP = dyn_cast(N2.Val); if (N1CFP) { if (N2CFP) { - if (!CombinerEnabled) { double C1 = N1CFP->getValue(), C2 = N2CFP->getValue(); switch (Opcode) { case ISD::ADD: return getConstantFP(C1 + C2, VT); @@ -1507,7 +1506,6 @@ SDOperand SelectionDAG::getNode(unsigned Opcode, MVT::ValueType VT, break; default: break; } - } } else { // Cannonicalize constant to RHS if commutative if (isCommutativeBinOp(Opcode)) { std::swap(N1CFP, N2CFP); @@ -1515,9 +1513,11 @@ SDOperand SelectionDAG::getNode(unsigned Opcode, MVT::ValueType VT, } } + if (!CombinerEnabled) { if (Opcode == ISD::FP_ROUND_INREG) return getNode(ISD::FP_EXTEND, VT, getNode(ISD::FP_ROUND, cast(N2)->getVT(), N1)); + } } // Finally, fold operations that do not require constants.