mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-10-05 11:17:53 +00:00
When XDEBUG is enabled, check for SelectionDAG cycles at some key
points. This will help us find future problems like the one described in PR6019. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@94019 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -63,6 +63,10 @@ enum CombineLevel {
|
|||||||
NoIllegalOperations // Combine may only create legal operations and types.
|
NoIllegalOperations // Combine may only create legal operations and types.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class SelectionDAG;
|
||||||
|
void checkForCycles(const SDNode *N);
|
||||||
|
void checkForCycles(const SelectionDAG *DAG);
|
||||||
|
|
||||||
/// SelectionDAG class - This is used to represent a portion of an LLVM function
|
/// SelectionDAG class - This is used to represent a portion of an LLVM function
|
||||||
/// in a low-level Data Dependence DAG representation suitable for instruction
|
/// in a low-level Data Dependence DAG representation suitable for instruction
|
||||||
/// selection. This DAG is constructed as the first step of instruction
|
/// selection. This DAG is constructed as the first step of instruction
|
||||||
@@ -204,7 +208,12 @@ public:
|
|||||||
const SDValue &setRoot(SDValue N) {
|
const SDValue &setRoot(SDValue N) {
|
||||||
assert((!N.getNode() || N.getValueType() == MVT::Other) &&
|
assert((!N.getNode() || N.getValueType() == MVT::Other) &&
|
||||||
"DAG root value is not a chain!");
|
"DAG root value is not a chain!");
|
||||||
return Root = N;
|
if (N.getNode())
|
||||||
|
checkForCycles(N.getNode());
|
||||||
|
Root = N;
|
||||||
|
if (N.getNode())
|
||||||
|
checkForCycles(this);
|
||||||
|
return Root;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Combine - This iterates over the nodes in the SelectionDAG, folding
|
/// Combine - This iterates over the nodes in the SelectionDAG, folding
|
||||||
|
@@ -44,6 +44,8 @@ template <typename T> struct DenseMapInfo;
|
|||||||
template <typename T> struct simplify_type;
|
template <typename T> struct simplify_type;
|
||||||
template <typename T> struct ilist_traits;
|
template <typename T> struct ilist_traits;
|
||||||
|
|
||||||
|
void checkForCycles(const SDNode *N);
|
||||||
|
|
||||||
/// SDVTList - This represents a list of ValueType's that has been intern'd by
|
/// SDVTList - This represents a list of ValueType's that has been intern'd by
|
||||||
/// a SelectionDAG. Instances of this simple value class are returned by
|
/// a SelectionDAG. Instances of this simple value class are returned by
|
||||||
/// SelectionDAG::getVTList(...).
|
/// SelectionDAG::getVTList(...).
|
||||||
@@ -1363,6 +1365,7 @@ protected:
|
|||||||
OperandList[i].setUser(this);
|
OperandList[i].setUser(this);
|
||||||
OperandList[i].setInitial(Ops[i]);
|
OperandList[i].setInitial(Ops[i]);
|
||||||
}
|
}
|
||||||
|
checkForCycles(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This constructor adds no operands itself; operands can be
|
/// This constructor adds no operands itself; operands can be
|
||||||
@@ -1379,6 +1382,7 @@ protected:
|
|||||||
Ops[0].setInitial(Op0);
|
Ops[0].setInitial(Op0);
|
||||||
NumOperands = 1;
|
NumOperands = 1;
|
||||||
OperandList = Ops;
|
OperandList = Ops;
|
||||||
|
checkForCycles(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// InitOperands - Initialize the operands list of this with 2 operands.
|
/// InitOperands - Initialize the operands list of this with 2 operands.
|
||||||
@@ -1389,6 +1393,7 @@ protected:
|
|||||||
Ops[1].setInitial(Op1);
|
Ops[1].setInitial(Op1);
|
||||||
NumOperands = 2;
|
NumOperands = 2;
|
||||||
OperandList = Ops;
|
OperandList = Ops;
|
||||||
|
checkForCycles(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// InitOperands - Initialize the operands list of this with 3 operands.
|
/// InitOperands - Initialize the operands list of this with 3 operands.
|
||||||
@@ -1402,6 +1407,7 @@ protected:
|
|||||||
Ops[2].setInitial(Op2);
|
Ops[2].setInitial(Op2);
|
||||||
NumOperands = 3;
|
NumOperands = 3;
|
||||||
OperandList = Ops;
|
OperandList = Ops;
|
||||||
|
checkForCycles(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// InitOperands - Initialize the operands list of this with 4 operands.
|
/// InitOperands - Initialize the operands list of this with 4 operands.
|
||||||
@@ -1417,6 +1423,7 @@ protected:
|
|||||||
Ops[3].setInitial(Op3);
|
Ops[3].setInitial(Op3);
|
||||||
NumOperands = 4;
|
NumOperands = 4;
|
||||||
OperandList = Ops;
|
OperandList = Ops;
|
||||||
|
checkForCycles(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// InitOperands - Initialize the operands list of this with N operands.
|
/// InitOperands - Initialize the operands list of this with N operands.
|
||||||
@@ -1427,6 +1434,7 @@ protected:
|
|||||||
}
|
}
|
||||||
NumOperands = N;
|
NumOperands = N;
|
||||||
OperandList = Ops;
|
OperandList = Ops;
|
||||||
|
checkForCycles(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// DropOperands - Release the operands and set this node to have
|
/// DropOperands - Release the operands and set this node to have
|
||||||
|
@@ -5172,6 +5172,7 @@ unsigned SelectionDAG::AssignTopologicalOrder() {
|
|||||||
// count of outstanding operands.
|
// count of outstanding operands.
|
||||||
for (allnodes_iterator I = allnodes_begin(),E = allnodes_end(); I != E; ) {
|
for (allnodes_iterator I = allnodes_begin(),E = allnodes_end(); I != E; ) {
|
||||||
SDNode *N = I++;
|
SDNode *N = I++;
|
||||||
|
checkForCycles(N);
|
||||||
unsigned Degree = N->getNumOperands();
|
unsigned Degree = N->getNumOperands();
|
||||||
if (Degree == 0) {
|
if (Degree == 0) {
|
||||||
// A node with no uses, add it to the result array immediately.
|
// A node with no uses, add it to the result array immediately.
|
||||||
@@ -5191,6 +5192,7 @@ unsigned SelectionDAG::AssignTopologicalOrder() {
|
|||||||
// such that by the time the end is reached all nodes will be sorted.
|
// such that by the time the end is reached all nodes will be sorted.
|
||||||
for (allnodes_iterator I = allnodes_begin(),E = allnodes_end(); I != E; ++I) {
|
for (allnodes_iterator I = allnodes_begin(),E = allnodes_end(); I != E; ++I) {
|
||||||
SDNode *N = I;
|
SDNode *N = I;
|
||||||
|
checkForCycles(N);
|
||||||
// N is in sorted position, so all its uses have one less operand
|
// N is in sorted position, so all its uses have one less operand
|
||||||
// that needs to be sorted.
|
// that needs to be sorted.
|
||||||
for (SDNode::use_iterator UI = N->use_begin(), UE = N->use_end();
|
for (SDNode::use_iterator UI = N->use_begin(), UE = N->use_end();
|
||||||
@@ -5216,7 +5218,7 @@ unsigned SelectionDAG::AssignTopologicalOrder() {
|
|||||||
SDNode *S = ++J;
|
SDNode *S = ++J;
|
||||||
dbgs() << "Offending node:\n";
|
dbgs() << "Offending node:\n";
|
||||||
S->dumprFull();
|
S->dumprFull();
|
||||||
assert(I != SortedPos && "Overran sorted position");
|
assert(0 && "Overran sorted position");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6279,3 +6281,35 @@ bool ShuffleVectorSDNode::isSplatMask(const int *Mask, EVT VT) {
|
|||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void checkForCyclesHelper(const SDNode *N,
|
||||||
|
std::set<const SDNode *> &visited) {
|
||||||
|
if (visited.find(N) != visited.end()) {
|
||||||
|
dbgs() << "Offending node:\n";
|
||||||
|
N->dumprFull();
|
||||||
|
assert(0 && "Detected cycle in SelectionDAG");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::set<const SDNode*>::iterator i;
|
||||||
|
bool inserted;
|
||||||
|
|
||||||
|
tie(i, inserted) = visited.insert(N);
|
||||||
|
assert(inserted && "Missed cycle");
|
||||||
|
|
||||||
|
for(unsigned i = 0; i < N->getNumOperands(); ++i) {
|
||||||
|
checkForCyclesHelper(N->getOperand(i).getNode(), visited);
|
||||||
|
}
|
||||||
|
visited.erase(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
void llvm::checkForCycles(const llvm::SDNode *N) {
|
||||||
|
#ifdef XDEBUG
|
||||||
|
assert(N && "Checking nonexistant SDNode");
|
||||||
|
std::set<const SDNode *> visited;
|
||||||
|
checkForCyclesHelper(N, visited);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void llvm::checkForCycles(const llvm::SelectionDAG *DAG) {
|
||||||
|
checkForCycles(DAG->getRoot().getNode());
|
||||||
|
}
|
||||||
|
@@ -598,6 +598,7 @@ void X86DAGToDAGISel::PreprocessForRMW() {
|
|||||||
if (RModW) {
|
if (RModW) {
|
||||||
MoveBelowTokenFactor(CurDAG, Load, SDValue(I, 0), Chain);
|
MoveBelowTokenFactor(CurDAG, Load, SDValue(I, 0), Chain);
|
||||||
++NumLoadMoved;
|
++NumLoadMoved;
|
||||||
|
checkForCycles(I);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user