Rename Kept -> Suffix
[oota-llvm.git] / tools / bugpoint / Miscompilation.cpp
index d382c06c83444795e05f9e34dfd01586d186511b..01d46aa7c4bfcc141f1305b15ca42f69be9b57ec 100644 (file)
@@ -6,6 +6,7 @@
 
 #include "BugDriver.h"
 #include "SystemUtils.h"
+#include "ListReducer.h"
 #include "llvm/Pass.h"
 #include "llvm/Module.h"
 #include "llvm/Transforms/Utils/Cloning.h"
@@ -26,74 +27,25 @@ namespace {
                            "(for miscompilation detection)"));
 }
 
-template<typename ElTy>
-struct ListReducer {
-  enum TestResult {
-    NoFailure,         // No failure of the predicate was detected
-    KeepSuffix,        // The suffix alone satisfies the predicate
-    KeepPrefix,        // The prefix alone satisfies the predicate
-  };
-
-  // doTest - This virtual function should be overriden by subclasses to
-  // implement the test desired.  The testcase is only required to test to see
-  // if the Kept list still satisfies the property, but if it is going to check
-  // the prefix anyway, it can.
-  //
-  virtual TestResult doTest(const std::vector<ElTy> &Prefix,
-                            const std::vector<ElTy> &Kept) = 0;
-
-  // reduceList - This function attempts to reduce the length of the specified
-  // list while still maintaining the "test" property.  This is the core of the
-  // "work" that bugpoint does.
-  //
-  void reduceList(std::vector<ElTy> &TheList) {
-    unsigned MidTop = TheList.size();
-    while (MidTop > 1) {
-      unsigned Mid = MidTop / 2;
-      std::vector<ElTy> Prefix(TheList.begin()+Mid, TheList.end());
-      std::vector<ElTy> Kept  (TheList.begin(), TheList.begin()+Mid);
-
-      switch (doTest(Prefix, Kept)) {
-      case KeepSuffix:
-        // The property still holds.  We can just drop the prefix elements, and
-        // shorten the list to the "kept" elements.
-        TheList.swap(Kept);
-        MidTop = TheList.size();
-        break;
-      case KeepPrefix:
-        // The predicate still holds, shorten the list to the prefix elements.
-        TheList.swap(Prefix);
-        MidTop = TheList.size();
-        break;
-      case NoFailure:
-        // Otherwise the property doesn't hold.  Some of the elements we removed
-        // must be neccesary to maintain the property.
-        MidTop = Mid;
-        break;
-      }
-    }
-  }
-};
-
 class ReduceMiscompilingPasses : public ListReducer<const PassInfo*> {
   BugDriver &BD;
 public:
   ReduceMiscompilingPasses(BugDriver &bd) : BD(bd) {}
 
-  virtual TestResult doTest(const std::vector<const PassInfo*> &Prefix,
-                            const std::vector<const PassInfo*> &Kept);
+  virtual TestResult doTest(std::vector<const PassInfo*> &Prefix,
+                            std::vector<const PassInfo*> &Kept);
 };
 
 ReduceMiscompilingPasses::TestResult
-ReduceMiscompilingPasses::doTest(const std::vector<const PassInfo*> &Prefix,
-                                 const std::vector<const PassInfo*> &Kept) {
-  // First, run the program with just the Kept passes.  If it is still broken
+ReduceMiscompilingPasses::doTest(std::vector<const PassInfo*> &Prefix,
+                                 std::vector<const PassInfo*> &Suffix) {
+  // First, run the program with just the Suffix passes.  If it is still broken
   // with JUST the kept passes, discard the prefix passes.
-  std::cout << "Checking to see if '" << getPassesString(Kept)
+  std::cout << "Checking to see if '" << getPassesString(Suffix)
             << "' compile correctly: ";
 
   std::string BytecodeResult;
-  if (BD.runPasses(Kept, BytecodeResult, false/*delete*/, true/*quiet*/)) {
+  if (BD.runPasses(Suffix, BytecodeResult, false/*delete*/, true/*quiet*/)) {
     std::cerr << BD.getToolName() << ": Error running this sequence of passes"
               << " on the input program!\n";
     exit(1);
@@ -108,8 +60,8 @@ ReduceMiscompilingPasses::doTest(const std::vector<const PassInfo*> &Prefix,
 
   if (Prefix.empty()) return NoFailure;
 
-  // First, run the program with just the Kept passes.  If it is still broken
-  // with JUST the kept passes, discard the prefix passes.
+  // Next, see if the program is broken if we run the "prefix" passes first,
+  // then seperately run the "kept" passes.
   std::cout << "Checking to see if '" << getPassesString(Prefix)
             << "' compile correctly: ";
 
@@ -144,13 +96,13 @@ ReduceMiscompilingPasses::doTest(const std::vector<const PassInfo*> &Prefix,
   }
   removeFile(BytecodeResult);  // No longer need the file on disk
     
-  std::cout << "Checking to see if '" << getPassesString(Kept)
+  std::cout << "Checking to see if '" << getPassesString(Suffix)
             << "' passes compile correctly after the '"
             << getPassesString(Prefix) << "' passes: ";
 
   Module *OriginalInput = BD.Program;
   BD.Program = PrefixOutput;
-  if (BD.runPasses(Kept, BytecodeResult, false/*delete*/, true/*quiet*/)) {
+  if (BD.runPasses(Suffix, BytecodeResult, false/*delete*/, true/*quiet*/)) {
     std::cerr << BD.getToolName() << ": Error running this sequence of passes"
               << " on the input program!\n";
     exit(1);
@@ -160,7 +112,7 @@ ReduceMiscompilingPasses::doTest(const std::vector<const PassInfo*> &Prefix,
   if (BD.diffProgram(Output, BytecodeResult, true/*delete bytecode*/)) {
     std::cout << "nope.\n";
     delete OriginalInput;     // We pruned down the original input...
-    return KeepPrefix;
+    return KeepSuffix;
   }
 
   // Otherwise, we must not be running the bad pass anymore.
@@ -183,11 +135,11 @@ class ReduceMiscompilingFunctions : public ListReducer<Function*> {
 public:
   ReduceMiscompilingFunctions(BugDriver &bd) : BD(bd) {}
 
-  virtual TestResult doTest(const std::vector<Function*> &Prefix,
-                            const std::vector<Function*> &Kept) {
-    if (TestFuncs(Kept, false))
+  virtual TestResult doTest(std::vector<Function*> &Prefix,
+                            std::vector<Function*> &Suffix) {
+    if (TestFuncs(Suffix, false))
       return KeepSuffix;
-    if (TestFuncs(Prefix, false))
+    if (!Prefix.empty() && TestFuncs(Prefix, false))
       return KeepPrefix;
     return NoFailure;
   }
@@ -195,21 +147,6 @@ public:
   bool TestFuncs(const std::vector<Function*> &Prefix, bool EmitBytecode);
 };
 
-// DeleteFunctionBody - "Remove" the function by deleting all of it's basic
-// blocks, making it external.
-//
-static void DeleteFunctionBody(Function *F) {
-  // First, break circular use/def chain references...
-  for (Function::iterator I = F->begin(), E = F->end(); I != E; ++I)
-    I->dropAllReferences();
-
-  // Next, delete all of the basic blocks.
-  F->getBasicBlockList().clear();
-
-  assert(F->isExternal() && "This didn't make the function external!");
-}
-
-
 bool ReduceMiscompilingFunctions::TestFuncs(const std::vector<Function*> &Funcs,
                                             bool EmitBytecode) {
   // Test to see if the function is misoptimized if we ONLY run it on the