Use isNull instead of getNode() to test for existence of a node, this is cheaper.
[oota-llvm.git] / tools / bugpoint / Miscompilation.cpp
index 89854f52c3feac705b16a2dbd392455c3677d698..98e299d76d82ddce5d5677e024ddf90ddf2ab21d 100644 (file)
@@ -1,58 +1,56 @@
 //===- 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"
-#include "Support/CommandLine.h"
-
-// Anonymous namespace to define command line options for miscompilation
-// debugging.
-//
-namespace {
-  // Output - The user can specify a file containing the expected output of the
-  // program.  If this filename is set, it is used as the reference diff source,
-  // otherwise the raw input run through an interpreter is used as the reference
-  // source.
-  //
-  cl::opt<std::string> 
-  Output("output", cl::desc("Specify a reference program output "
-                           "(for miscompilation detection)"));
-}
+#include "Support/FileUtilities.h"
+using namespace llvm;
 
-class ReduceMiscompilingPasses : public ListReducer<const PassInfo*> {
-  BugDriver &BD;
-public:
-  ReduceMiscompilingPasses(BugDriver &bd) : BD(bd) {}
+namespace llvm {
 
-  virtual TestResult doTest(const std::vector<const PassInfo*> &Prefix,
-                            const std::vector<const PassInfo*> &Kept);
-};
+  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(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*/)) {
-    std::cerr << BD.getToolName() << ": Error running this sequence of passes"
+  if (BD.runPasses(Suffix, BytecodeResult, false/*delete*/, true/*quiet*/)) {
+    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...
-  if (BD.diffProgram(Output, BytecodeResult, true /*delete bytecode*/)) {
+  if (BD.diffProgram(BytecodeResult, "", true /*delete bytecode*/)) {
     std::cout << "nope.\n";
     return KeepSuffix;        // Miscompilation detected!
   }
@@ -60,8 +58,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 separately run the "kept" passes.
   std::cout << "Checking to see if '" << getPassesString(Prefix)
             << "' compile correctly: ";
 
@@ -72,13 +70,15 @@ ReduceMiscompilingPasses::doTest(const 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!
-  if (BD.diffProgram(Output, BytecodeResult)) {
+  if (BD.diffProgram(BytecodeResult)) {
     std::cout << "nope.\n";
     removeFile(BytecodeResult);
     return KeepPrefix;
@@ -96,23 +96,25 @@ 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*/)) {
-    std::cerr << BD.getToolName() << ": Error running this sequence of passes"
+  if (BD.runPasses(Suffix, BytecodeResult, false/*delete*/, true/*quiet*/)) {
+    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...
-  if (BD.diffProgram(Output, BytecodeResult, true/*delete bytecode*/)) {
+  if (BD.diffProgram(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.
@@ -122,61 +124,42 @@ ReduceMiscompilingPasses::doTest(const std::vector<const PassInfo*> &Prefix,
   return NoFailure;
 }
 
-static void PrintFunctionList(const std::vector<Function*> &Funcs) {
-  for (unsigned i = 0, e = Funcs.size(); i != e; ++i) {
-    if (i) std::cout << ", ";
-    std::cout << Funcs[i]->getName();
-  }
-}
-
-
-class ReduceMiscompilingFunctions : public ListReducer<Function*> {
-  BugDriver &BD;
-public:
-  ReduceMiscompilingFunctions(BugDriver &bd) : BD(bd) {}
-
-  virtual TestResult doTest(const std::vector<Function*> &Prefix,
-                            const std::vector<Function*> &Kept) {
-    if (TestFuncs(Kept, false))
-      return KeepSuffix;
-    if (!Prefix.empty() && TestFuncs(Prefix, false))
-      return KeepPrefix;
-    return NoFailure;
-  }
-  
-  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!");
+namespace llvm {
+  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: ";
-    PrintFunctionList(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.PassesToRun.size() == 1 ? "" : "es") << ": ";
+    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);
+  Module *ToOptimize = CloneModule(BD.getProgram());
 
   // Second step: Make sure functions & globals are all external so that linkage
   // between the two modules will work.
@@ -239,15 +222,16 @@ bool ReduceMiscompilingFunctions::TestFuncs(const std::vector<Function*> &Funcs,
   std::string BytecodeResult;
   if (BD.runPasses(BD.PassesToRun, 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.EmitProgressBytecode("pass-error",  false);
+    exit(BD.debugOptimizerCrash());
   }
 
   if (!EmitBytecode)
     std::cout << "done.\n";
 
-  delete BD.Program;   // Delete the old "ToOptimize" module
+  delete BD.getProgram();   // Delete the old "ToOptimize" module
   BD.Program = BD.ParseInputFile(BytecodeResult);
 
   if (EmitBytecode) {
@@ -284,12 +268,12 @@ bool ReduceMiscompilingFunctions::TestFuncs(const std::vector<Function*> &Funcs,
 
   // Eighth step: Execute the program.  If it does not match the expected
   // output, then 'Funcs' are being misoptimized!
-  bool Broken = BD.diffProgram(Output);
+  bool Broken = BD.diffProgram();
 
-  delete BD.Program;  // Delete the hacked up program
+  delete BD.Program;         // Delete the hacked up program
   BD.Program = OldProgram;   // Restore the original
 
-  std::cout << (Broken ? "nope.\n" : "yup.\n");
+  std::cout << (Broken ? " nope.\n" : " yup.\n");
   return Broken;
 }
 
@@ -299,33 +283,8 @@ bool ReduceMiscompilingFunctions::TestFuncs(const std::vector<Function*> &Funcs,
 /// input.
 ///
 bool BugDriver::debugMiscompilation() {
-  std::cout << "*** Debugging miscompilation!\n";
-
-  // Set up the execution environment, selecting a method to run LLVM bytecode.
-  if (initializeExecutionEnvironment()) return true;
-
-  // Run the raw input to see where we are coming from.  If a reference output
-  // was specified, make sure that the raw output matches it.  If not, it's a
-  // problem in the front-end or whatever produced the input code.
-  //
-  bool CreatedOutput = false;
-  if (Output.empty()) {
-    std::cout << "Generating reference output from raw program...";
-    Output = executeProgram("bugpoint.reference.out");
-    CreatedOutput = true;
-    std::cout << " done! Reference output is: bugpoint.reference.out.\n";
-  } else if (diffProgram(Output)) {
-    std::cout << "\n*** Input program does not match reference diff!\n"
-             << "    Must be problem with input source!\n";
-    return false;  // Problem found
-  }
-
-  // Figure out which transformations miscompile the input program.
-  unsigned OldSize = PassesToRun.size();
-  ReduceMiscompilingPasses(*this).reduceList(PassesToRun);
-
   // Make sure something was miscompiled...
-  if (PassesToRun.size() == OldSize) {
+  if (!ReduceMiscompilingPasses(*this).reduceList(PassesToRun)) {
     std::cerr << "*** Optimized program matches reference output!  No problem "
              << "detected...\nbugpoint can't help you with your problem!\n";
     return false;
@@ -336,7 +295,6 @@ bool BugDriver::debugMiscompilation() {
             << getPassesString(PassesToRun) << "\n";
   EmitProgressBytecode("passinput");
 
-
   // Okay, now that we have reduced the list of passes which are causing the
   // failure, see if we can pin down which functions are being
   // miscompiled... first build a list of all of the non-external functions in
@@ -349,13 +307,15 @@ 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";
 
   // Output a bunch of bytecode files for the user...
   ReduceMiscompilingFunctions(*this).TestFuncs(MiscompiledFunctions, true);
 
-  if (CreatedOutput) removeFile(Output);
   return false;
 }
+