mirror of
https://github.com/RPCS3/llvm.git
synced 2024-12-23 12:40:17 +00:00
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:
parent
dc6e2e0a5f
commit
9980119270
@ -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();
|
||||
|
@ -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,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<VTSDNode>(N2)->getVT(), N1));
|
||||
}
|
||||
}
|
||||
|
||||
// Finally, fold operations that do not require constants.
|
||||
|
Loading…
Reference in New Issue
Block a user