[SelectionDAG] Force cycle detection in AssignTopologicalOrder before aborting
authorAdam Nemet <anemet@apple.com>
Sat, 31 May 2014 16:23:20 +0000 (16:23 +0000)
committerAdam Nemet <anemet@apple.com>
Sat, 31 May 2014 16:23:20 +0000 (16:23 +0000)
DAG cycle detection is only enabled with ENABLE_EXPENSIVE_CHECKS.  However we
can run it just before we would crash in order to provide more informative
diagnostics.

Now in addition to the "Overran sorted position" message we also get the Node
printed if a cycle was detected.

Tested by building several configs: Debug+Assert, Debug+Assert+Check (this is
ENABLE_EXPENSIVE_CHECKS), Release+Assert and Release.  Also tried that the
AssignTopologicalOrder assert produces the expected results.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@209977 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/CodeGen/SelectionDAG.h
include/llvm/CodeGen/SelectionDAGNodes.h
lib/CodeGen/SelectionDAG/SelectionDAG.cpp

index 66473554d03aab2efde9b46d039eb1475ed604d1..c6d716a5355be03d0d360e91321f2177a72b4a5d 100644 (file)
@@ -151,7 +151,7 @@ public:
 };
 
 class SelectionDAG;
 };
 
 class SelectionDAG;
-void checkForCycles(const SelectionDAG *DAG);
+void checkForCycles(const SelectionDAG *DAG, bool force = false);
 
 /// SelectionDAG class - This is used to represent a portion of an LLVM function
 /// in a low-level Data Dependence DAG representation suitable for instruction
 
 /// SelectionDAG class - This is used to represent a portion of an LLVM function
 /// in a low-level Data Dependence DAG representation suitable for instruction
index f281a069706720fd874843678ed56d326a132d5a..09cac4284182aa66dd386267a43cecb96b2ed423 100644 (file)
@@ -49,7 +49,8 @@ template <typename T> struct DenseMapInfo;
 template <typename T> struct simplify_type;
 template <typename T> struct ilist_traits;
 
 template <typename T> struct simplify_type;
 template <typename T> struct ilist_traits;
 
-void checkForCycles(const SDNode *N, const SelectionDAG *DAG = nullptr);
+void checkForCycles(const SDNode *N, const SelectionDAG *DAG = nullptr,
+                    bool force = false);
 
 /// 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
 
 /// 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
index 0f1d9758348c651425b0beb2be7082899da47b8d..b701add2de3f2039e1d53134b8d393c3b403c304 100644 (file)
@@ -6002,6 +6002,8 @@ unsigned SelectionDAG::AssignTopologicalOrder() {
       SDNode *S = ++I;
       dbgs() << "Overran sorted position:\n";
       S->dumprFull(this); dbgs() << "\n";
       SDNode *S = ++I;
       dbgs() << "Overran sorted position:\n";
       S->dumprFull(this); dbgs() << "\n";
+      dbgs() << "Checking if this is due to cycles\n";
+      checkForCycles(this, true);
 #endif
       llvm_unreachable(nullptr);
     }
 #endif
       llvm_unreachable(nullptr);
     }
@@ -6587,7 +6589,7 @@ bool ShuffleVectorSDNode::isSplatMask(const int *Mask, EVT VT) {
   return true;
 }
 
   return true;
 }
 
-#ifdef XDEBUG
+#ifndef NDEBUG
 static void checkForCyclesHelper(const SDNode *N,
                                  SmallPtrSet<const SDNode*, 32> &Visited,
                                  SmallPtrSet<const SDNode*, 32> &Checked,
 static void checkForCyclesHelper(const SDNode *N,
                                  SmallPtrSet<const SDNode*, 32> &Visited,
                                  SmallPtrSet<const SDNode*, 32> &Checked,
@@ -6614,15 +6616,22 @@ static void checkForCyclesHelper(const SDNode *N,
 #endif
 
 void llvm::checkForCycles(const llvm::SDNode *N,
 #endif
 
 void llvm::checkForCycles(const llvm::SDNode *N,
-                          const llvm::SelectionDAG *DAG) {
+                          const llvm::SelectionDAG *DAG,
+                          bool force) {
+#ifndef NDEBUG
+  bool check = force;
 #ifdef XDEBUG
 #ifdef XDEBUG
-  assert(N && "Checking nonexistent SDNode");
-  SmallPtrSet<const SDNode*, 32> visited;
-  SmallPtrSet<const SDNode*, 32> checked;
-  checkForCyclesHelper(N, visited, checked, DAG);
-#endif
+  check = true;
+#endif  // XDEBUG
+  if (check) {
+    assert(N && "Checking nonexistent SDNode");
+    SmallPtrSet<const SDNode*, 32> visited;
+    SmallPtrSet<const SDNode*, 32> checked;
+    checkForCyclesHelper(N, visited, checked, DAG);
+  }
+#endif  // !NDEBUG
 }
 
 }
 
-void llvm::checkForCycles(const llvm::SelectionDAG *DAG) {
-  checkForCycles(DAG->getRoot().getNode(), DAG);
+void llvm::checkForCycles(const llvm::SelectionDAG *DAG, bool force) {
+  checkForCycles(DAG->getRoot().getNode(), DAG, force);
 }
 }