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
This commit is contained in:
Nate Begeman 2005-09-07 23:25:52 +00:00
parent dc6e2e0a5f
commit 9980119270
2 changed files with 48 additions and 17 deletions

View File

@ -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<ConstantSDNode>(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<SDOperand>(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<ConstantSDNode>(RHS) || isa<ConstantSDNode>(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();

View File

@ -1256,7 +1256,6 @@ SDOperand SelectionDAG::getNode(unsigned Opcode, MVT::ValueType VT,
ConstantSDNode *N2C = dyn_cast<ConstantSDNode>(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<ConstantFPSDNode>(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,10 +1513,12 @@ 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<VTSDNode>(N2)->getVT(), N1));
}
}
// Finally, fold operations that do not require constants.
switch (Opcode) {