minor formatting change
[oota-llvm.git] / tools / bugpoint / Miscompilation.cpp
index 968a34e6c9f20f4460e98c288cf7c42999129b29..0913caeb3660f963dec622143300406dc6545af1 100644 (file)
@@ -1,25 +1,35 @@
 //===- Miscompilation.cpp - Debug program miscompilations -----------------===//
+// 
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// 
+//===----------------------------------------------------------------------===//
 //
 // This file implements program miscompilation debugging support.
 //
 //===----------------------------------------------------------------------===//
 
 #include "BugDriver.h"
-#include "SystemUtils.h"
 #include "ListReducer.h"
-#include "llvm/Pass.h"
 #include "llvm/Module.h"
+#include "llvm/Pass.h"
 #include "llvm/Transforms/Utils/Cloning.h"
 #include "llvm/Transforms/Utils/Linker.h"
-
-class ReduceMiscompilingPasses : public ListReducer<const PassInfo*> {
-  BugDriver &BD;
-public:
-  ReduceMiscompilingPasses(BugDriver &bd) : BD(bd) {}
-
-  virtual TestResult doTest(std::vector<const PassInfo*> &Prefix,
-                            std::vector<const PassInfo*> &Suffix);
-};
+#include "Support/FileUtilities.h"
+using namespace llvm;
+
+namespace {
+  class ReduceMiscompilingPasses : public ListReducer<const PassInfo*> {
+    BugDriver &BD;
+  public:
+    ReduceMiscompilingPasses(BugDriver &bd) : BD(bd) {}
+    
+    virtual TestResult doTest(std::vector<const PassInfo*> &Prefix,
+                              std::vector<const PassInfo*> &Suffix);
+  };
+}
 
 ReduceMiscompilingPasses::TestResult
 ReduceMiscompilingPasses::doTest(std::vector<const PassInfo*> &Prefix,
@@ -31,9 +41,11 @@ ReduceMiscompilingPasses::doTest(std::vector<const PassInfo*> &Prefix,
 
   std::string BytecodeResult;
   if (BD.runPasses(Suffix, BytecodeResult, false/*delete*/, true/*quiet*/)) {
-    std::cerr << BD.getToolName() << ": Error running this sequence of passes"
+    std::cerr << " Error running this sequence of passes" 
               << " on the input program!\n";
-    exit(1);
+    BD.setPassesToRun(Suffix);
+    BD.EmitProgressBytecode("pass-error",  false);
+    exit(BD.debugOptimizerCrash());
   }
 
   // Check to see if the finished program matches the reference output...
@@ -57,9 +69,11 @@ ReduceMiscompilingPasses::doTest(std::vector<const PassInfo*> &Prefix,
   // prefix passes, then discard the prefix passes.
   //
   if (BD.runPasses(Prefix, BytecodeResult, false/*delete*/, true/*quiet*/)) {
-    std::cerr << BD.getToolName() << ": Error running this sequence of passes"
+    std::cerr << " Error running this sequence of passes" 
               << " on the input program!\n";
-    exit(1);
+    BD.setPassesToRun(Prefix);
+    BD.EmitProgressBytecode("pass-error",  false);
+    exit(BD.debugOptimizerCrash());
   }
 
   // If the prefix maintains the predicate by itself, only keep the prefix!
@@ -73,7 +87,7 @@ ReduceMiscompilingPasses::doTest(std::vector<const PassInfo*> &Prefix,
   // Ok, so now we know that the prefix passes work, try running the suffix
   // passes on the result of the prefix passes.
   //
-  Module *PrefixOutput = BD.ParseInputFile(BytecodeResult);
+  Module *PrefixOutput = ParseInputFile(BytecodeResult);
   if (PrefixOutput == 0) {
     std::cerr << BD.getToolName() << ": Error reading bytecode file '"
               << BytecodeResult << "'!\n";
@@ -85,12 +99,13 @@ ReduceMiscompilingPasses::doTest(std::vector<const PassInfo*> &Prefix,
             << "' passes compile correctly after the '"
             << getPassesString(Prefix) << "' passes: ";
 
-  Module *OriginalInput = BD.Program;
-  BD.Program = PrefixOutput;
+  Module *OriginalInput = BD.swapProgramIn(PrefixOutput);
   if (BD.runPasses(Suffix, BytecodeResult, false/*delete*/, true/*quiet*/)) {
-    std::cerr << BD.getToolName() << ": Error running this sequence of passes"
+    std::cerr << " Error running this sequence of passes" 
               << " on the input program!\n";
-    exit(1);
+    BD.setPassesToRun(Suffix);
+    BD.EmitProgressBytecode("pass-error",  false);
+    exit(BD.debugOptimizerCrash());
   }
 
   // Run the result...
@@ -102,172 +117,182 @@ ReduceMiscompilingPasses::doTest(std::vector<const PassInfo*> &Prefix,
 
   // Otherwise, we must not be running the bad pass anymore.
   std::cout << "yup.\n";      // No miscompilation!
-  BD.Program = OriginalInput; // Restore original program
-  delete PrefixOutput;        // Free experiment
+  delete BD.swapProgramIn(OriginalInput); // Restore orig program & free test
   return NoFailure;
 }
 
-class ReduceMiscompilingFunctions : public ListReducer<Function*> {
-  BugDriver &BD;
-public:
-  ReduceMiscompilingFunctions(BugDriver &bd) : BD(bd) {}
-
-  virtual TestResult doTest(std::vector<Function*> &Prefix,
-                            std::vector<Function*> &Suffix) {
-    if (!Suffix.empty() && TestFuncs(Suffix, false))
-      return KeepSuffix;
-    if (!Prefix.empty() && TestFuncs(Prefix, false))
-      return KeepPrefix;
-    return NoFailure;
-  }
-  
-  bool TestFuncs(const std::vector<Function*> &Prefix, bool EmitBytecode);
-};
-
-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
-  // functions listed in Funcs.
-  if (!EmitBytecode) {
-    std::cout << "Checking to see if the program is misoptimized when these "
-              << "functions are run\nthrough the passes: ";
-    BD.PrintFunctionList(Funcs);
-    std::cout << "\n";
-  } else {
-    std::cout <<"Outputting reduced bytecode files which expose the problem:\n";
-  }
-
-  // First step: clone the module for the two halves of the program we want.
-  Module *ToOptimize = CloneModule(BD.Program);
-
-  // Second step: Make sure functions & globals are all external so that linkage
-  // between the two modules will work.
-  for (Module::iterator I = ToOptimize->begin(), E = ToOptimize->end();I!=E;++I)
-    I->setLinkage(GlobalValue::ExternalLinkage);
-  for (Module::giterator I = ToOptimize->gbegin(), E = ToOptimize->gend();
-       I != E; ++I)
-    I->setLinkage(GlobalValue::ExternalLinkage);
-
-  // Third step: make a clone of the externalized program for the non-optimized
-  // part.
-  Module *ToNotOptimize = CloneModule(ToOptimize);
-
-  // Fourth step: Remove the test functions from the ToNotOptimize module, and
-  // all of the global variables.
-  for (unsigned i = 0, e = Funcs.size(); i != e; ++i) {
-    Function *TNOF = ToNotOptimize->getFunction(Funcs[i]->getName(),
-                                                Funcs[i]->getFunctionType());
-    assert(TNOF && "Function doesn't exist in module!");
-    DeleteFunctionBody(TNOF);       // Function is now external in this module!
-  }
-  for (Module::giterator I = ToNotOptimize->gbegin(), E = ToNotOptimize->gend();
-       I != E; ++I)
-    I->setInitializer(0);  // Delete the initializer to make it external
-
-  if (EmitBytecode) {
-    std::cout << "  Non-optimized portion: ";
-    std::swap(BD.Program, ToNotOptimize);
-    BD.EmitProgressBytecode("tonotoptimize", true);
-    std::swap(BD.Program, ToNotOptimize);
-  }
-
-  // Fifth step: Remove all functions from the ToOptimize module EXCEPT for the
-  // ones specified in Funcs.  We know which ones these are because they are
-  // non-external in ToOptimize, but external in ToNotOptimize.
-  //
-  for (Module::iterator I = ToOptimize->begin(), E = ToOptimize->end();I!=E;++I)
-    if (!I->isExternal()) {
-      Function *TNOF = ToNotOptimize->getFunction(I->getName(),
-                                                  I->getFunctionType());
-      assert(TNOF && "Function doesn't exist in ToNotOptimize module??");
-      if (!TNOF->isExternal())
-        DeleteFunctionBody(I);
+namespace {
+  class ReduceMiscompilingFunctions : public ListReducer<Function*> {
+    BugDriver &BD;
+  public:
+    ReduceMiscompilingFunctions(BugDriver &bd) : BD(bd) {}
+    
+    virtual TestResult doTest(std::vector<Function*> &Prefix,
+                              std::vector<Function*> &Suffix) {
+      if (!Suffix.empty() && TestFuncs(Suffix))
+        return KeepSuffix;
+      if (!Prefix.empty() && TestFuncs(Prefix))
+        return KeepPrefix;
+      return NoFailure;
     }
+    
+    bool TestFuncs(const std::vector<Function*> &Prefix);
+  };
+}
 
-  if (EmitBytecode) {
-    std::cout << "  Portion that is input to optimizer: ";
-    std::swap(BD.Program, ToOptimize);
-    BD.EmitProgressBytecode("tooptimize");
-    std::swap(BD.Program, ToOptimize);
+/// TestMergedProgram - Given two modules, link them together and run the
+/// program, checking to see if the program matches the diff.  If the diff
+/// matches, return false, otherwise return true.  If the DeleteInputs argument
+/// is set to true then this function deletes both input modules before it
+/// returns.
+static bool TestMergedProgram(BugDriver &BD, Module *M1, Module *M2,
+                              bool DeleteInputs) {
+  // Link the two portions of the program back to together.
+  std::string ErrorMsg;
+  if (!DeleteInputs) M1 = CloneModule(M1);
+  if (LinkModules(M1, M2, &ErrorMsg)) {
+    std::cerr << BD.getToolName() << ": Error linking modules together:"
+              << ErrorMsg << "\n";
+    exit(1);
   }
+  if (DeleteInputs) delete M2;  // We are done with this module...
 
-  // Sixth step: Run the optimization passes on ToOptimize, producing a
-  // transformed version of the functions being tested.
-  Module *OldProgram = BD.Program;
-  BD.Program = ToOptimize;
+  Module *OldProgram = BD.swapProgramIn(M1);
 
-  if (!EmitBytecode)
-    std::cout << "  Optimizing functions being tested: ";
-  std::string BytecodeResult;
-  if (BD.runPasses(BD.PassesToRun, BytecodeResult, false/*delete*/,
-                   true/*quiet*/)) {
-    std::cerr << BD.getToolName() << ": Error running this sequence of passes"
-              << " on the input program!\n";
-    exit(1);
-  }
+  // Execute the program.  If it does not match the expected output, we must
+  // return true.
+  bool Broken = BD.diffProgram();
 
-  if (!EmitBytecode)
-    std::cout << "done.\n";
+  // Delete the linked module & restore the original
+  BD.swapProgramIn(OldProgram);
+  delete M1;
+  return Broken;
+}
 
-  delete BD.Program;   // Delete the old "ToOptimize" module
-  BD.Program = BD.ParseInputFile(BytecodeResult);
+bool ReduceMiscompilingFunctions::TestFuncs(const std::vector<Function*>&Funcs){
+  // Test to see if the function is misoptimized if we ONLY run it on the
+  // functions listed in Funcs.
+  std::cout << "Checking to see if the program is misoptimized when "
+            << (Funcs.size()==1 ? "this function is" : "these functions are")
+            << " run through the pass"
+            << (BD.getPassesToRun().size() == 1 ? "" : "es") << ":";
+  PrintFunctionList(Funcs);
+  std::cout << "\n";
 
-  if (EmitBytecode) {
-    std::cout << "  'tooptimize' after being optimized: ";
-    BD.EmitProgressBytecode("optimized", true);
-  }
+  // Split the module into the two halves of the program we want.
+  Module *ToNotOptimize = CloneModule(BD.getProgram());
+  Module *ToOptimize = SplitFunctionsOutOfModule(ToNotOptimize, Funcs);
 
-  if (BD.Program == 0) {
-    std::cerr << BD.getToolName() << ": Error reading bytecode file '"
-              << BytecodeResult << "'!\n";
-    exit(1);
-  }
-  removeFile(BytecodeResult);  // No longer need the file on disk
+  // Run the optimization passes on ToOptimize, producing a transformed version
+  // of the functions being tested.
+  std::cout << "  Optimizing functions being tested: ";
+  Module *Optimized = BD.runPassesOn(ToOptimize, BD.getPassesToRun(),
+                                     /*AutoDebugCrashes*/true);
+  std::cout << "done.\n";
+  delete ToOptimize;
 
-  // Seventh step: Link the optimized part of the program back to the
-  // unoptimized part of the program.
-  //
-  if (LinkModules(BD.Program, ToNotOptimize, &BytecodeResult)) {
-    std::cerr << BD.getToolName() << ": Error linking modules together:"
-              << BytecodeResult << "\n";
-    exit(1);
-  }
-  delete ToNotOptimize;  // We are done with this module...
-
-  if (EmitBytecode) {
-    std::cout << "  Program as tested: ";
-    BD.EmitProgressBytecode("linked", true);
-    delete BD.Program;
-    BD.Program = OldProgram;
-    return false;   // We don't need to actually execute the program here.
-  }
 
   std::cout << "  Checking to see if the merged program executes correctly: ";
+  bool Broken = TestMergedProgram(BD, Optimized, ToNotOptimize, true);
+  std::cout << (Broken ? " nope.\n" : " yup.\n");
+  return Broken;
+}
 
-  // Eighth step: Execute the program.  If it does not match the expected
-  // output, then 'Funcs' are being misoptimized!
-  bool Broken = BD.diffProgram();
+/// ExtractLoops - Given a reduced list of functions that still exposed the bug,
+/// check to see if we can extract the loops in the region without obscuring the
+/// bug.  If so, it reduces the amount of code identified.
+static bool ExtractLoops(BugDriver &BD, 
+                         std::vector<Function*> &MiscompiledFunctions) {
+  bool MadeChange = false;
+  while (1) {
+    Module *ToNotOptimize = CloneModule(BD.getProgram());
+    Module *ToOptimize = SplitFunctionsOutOfModule(ToNotOptimize,
+                                                   MiscompiledFunctions);
+    Module *ToOptimizeLoopExtracted = BD.ExtractLoop(ToOptimize);
+    if (!ToOptimizeLoopExtracted) {
+      // If the loop extractor crashed or if there were no extractible loops,
+      // then this chapter of our odyssey is over with.
+      delete ToNotOptimize;
+      delete ToOptimize;
+      return MadeChange;
+    }
 
-  delete BD.Program;  // Delete the hacked up program
-  BD.Program = OldProgram;   // Restore the original
+    std::cerr << "Extracted a loop from the breaking portion of the program.\n";
+    delete ToOptimize;
+
+    // Bugpoint is intentionally not very trusting of LLVM transformations.  In
+    // particular, we're not going to assume that the loop extractor works, so
+    // we're going to test the newly loop extracted program to make sure nothing
+    // has broken.  If something broke, then we'll inform the user and stop
+    // extraction.
+    if (TestMergedProgram(BD, ToOptimizeLoopExtracted, ToNotOptimize, false)) {
+      // Merged program doesn't work anymore!
+      std::cerr << "  *** ERROR: Loop extraction broke the program. :("
+                << " Please report a bug!\n";
+      std::cerr << "      Continuing on with un-loop-extracted version.\n";
+      delete ToNotOptimize;
+      delete ToOptimizeLoopExtracted;
+      return MadeChange;
+    }
+    
+    // Okay, the loop extractor didn't break the program.  Run the series of
+    // optimizations on the loop extracted portion and see if THEY still break
+    // the program.  If so, it was safe to extract these loops!
+    std::cout << "  Running optimizations on loop extracted portion: ";
+    Module *Optimized = BD.runPassesOn(ToOptimizeLoopExtracted,
+                                       BD.getPassesToRun(),
+                                       /*AutoDebugCrashes*/true);
+    std::cout << "done.\n";
 
-  std::cout << (Broken ? "nope.\n" : "yup.\n");
-  return Broken;
-}
+    std::cout << "  Checking to see if the merged program executes correctly: ";
+    bool Broken = TestMergedProgram(BD, Optimized, ToNotOptimize, false);
+    delete Optimized;
+    if (!Broken) {
+      std::cout << "yup: loop extraction masked the problem.  Undoing.\n";
+      // If the program is not still broken, then loop extraction did something
+      // that masked the error.  Stop loop extraction now.
+      delete ToNotOptimize;
+      delete ToOptimizeLoopExtracted;
+      return MadeChange;
+    }
+    std::cout << "nope: loop extraction successful!\n";
+
+    // Okay, great!  Now we know that we extracted a loop and that loop
+    // extraction both didn't break the program, and didn't mask the problem.
+    // Replace the current program with the loop extracted version, and try to
+    // extract another loop.
+    std::string ErrorMsg;
+    if (LinkModules(ToNotOptimize, ToOptimizeLoopExtracted, &ErrorMsg)) {
+      std::cerr << BD.getToolName() << ": Error linking modules together:"
+                << ErrorMsg << "\n";
+      exit(1);
+    }
 
+    // All of the Function*'s in the MiscompiledFunctions list are in the old
+    // module.  Update this list to include all of the functions in the
+    // optimized and loop extracted module.
+    MiscompiledFunctions.clear();
+    for (Module::iterator I = ToOptimizeLoopExtracted->begin(),
+           E = ToOptimizeLoopExtracted->end(); I != E; ++I) {
+      if (!I->isExternal()) {
+        Function *NewF = ToNotOptimize->getFunction(I->getName(),
+                                                    I->getFunctionType());
+        assert(NewF && "Function not found??");
+        MiscompiledFunctions.push_back(NewF);
+      }
+    }
+    delete ToOptimizeLoopExtracted;
+
+    BD.setNewProgram(ToNotOptimize);
+    MadeChange = true;
+  }
+}
 
 /// debugMiscompilation - This method is used when the passes selected are not
 /// crashing, but the generated output is semantically different from the
 /// input.
 ///
 bool BugDriver::debugMiscompilation() {
-
-  if (diffProgram()) {
-    std::cout << "\n*** Input program does not match reference diff!\n"
-              << "    Must be problem with input source!\n";
-    return false;  // Problem found
-  }
-
   // Make sure something was miscompiled...
   if (!ReduceMiscompilingPasses(*this).reduceList(PassesToRun)) {
     std::cerr << "*** Optimized program matches reference output!  No problem "
@@ -276,8 +301,8 @@ bool BugDriver::debugMiscompilation() {
   }
 
   std::cout << "\n*** Found miscompiling pass"
-            << (PassesToRun.size() == 1 ? "" : "es") << ": "
-            << getPassesString(PassesToRun) << "\n";
+            << (getPassesToRun().size() == 1 ? "" : "es") << ": "
+            << getPassesString(getPassesToRun()) << "\n";
   EmitProgressBytecode("passinput");
 
   // Okay, now that we have reduced the list of passes which are causing the
@@ -292,12 +317,44 @@ bool BugDriver::debugMiscompilation() {
   // Do the reduction...
   ReduceMiscompilingFunctions(*this).reduceList(MiscompiledFunctions);
 
-  std::cout << "\n*** The following functions are being miscompiled: ";
+  std::cout << "\n*** The following function"
+            << (MiscompiledFunctions.size() == 1 ? " is" : "s are")
+            << " being miscompiled: ";
   PrintFunctionList(MiscompiledFunctions);
   std::cout << "\n";
 
+  // See if we can rip any loops out of the miscompiled functions and still
+  // trigger the problem.
+  if (ExtractLoops(*this, MiscompiledFunctions)) {
+    // Okay, we extracted some loops and the problem still appears.  See if we
+    // can eliminate some of the created functions from being candidates.
+
+    // Do the reduction...
+    ReduceMiscompilingFunctions(*this).reduceList(MiscompiledFunctions);
+    
+    std::cout << "\n*** The following function"
+              << (MiscompiledFunctions.size() == 1 ? " is" : "s are")
+              << " being miscompiled: ";
+    PrintFunctionList(MiscompiledFunctions);
+    std::cout << "\n";
+  }
+
   // Output a bunch of bytecode files for the user...
-  ReduceMiscompilingFunctions(*this).TestFuncs(MiscompiledFunctions, true);
+  std::cout << "Outputting reduced bytecode files which expose the problem:\n";
+  Module *ToNotOptimize = CloneModule(getProgram());
+  Module *ToOptimize = SplitFunctionsOutOfModule(ToNotOptimize,
+                                                 MiscompiledFunctions);
+
+  std::cout << "  Non-optimized portion: ";
+  std::swap(Program, ToNotOptimize);
+  EmitProgressBytecode("tonotoptimize", true);
+  setNewProgram(ToNotOptimize);   // Delete hacked module.
+  
+  std::cout << "  Portion that is input to optimizer: ";
+  std::swap(Program, ToOptimize);
+  EmitProgressBytecode("tooptimize");
+  setNewProgram(ToOptimize);      // Delete hacked module.
 
   return false;
 }
+