Clone and restore the module being reduced in
authorRafael Espindola <rafael.espindola@gmail.com>
Mon, 26 Jul 2010 00:07:51 +0000 (00:07 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Mon, 26 Jul 2010 00:07:51 +0000 (00:07 +0000)
ReduceMiscompilingFunctions::TestFuncs. This makes the test functional
(i.e., no side effects).

Before we would end up using dead functions if a pass decided to remove them
(inline for example) and we would also keep broken functions and conclude that
that a single function was enough to reproduce the bug.

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

tools/bugpoint/Miscompilation.cpp

index 47ac3c5c4d3a71dcce68d77fab3497492b43d23a..3ceb573d60db2b8e196754e18276ce71766e36a9 100644 (file)
@@ -198,7 +198,7 @@ namespace {
       return NoFailure;
     }
 
-    int TestFuncs(const std::vector<Function*> &Prefix, std::string &Error);
+    bool TestFuncs(const std::vector<Function*> &Prefix, std::string &Error);
   };
 }
 
@@ -239,8 +239,8 @@ static bool TestMergedProgram(BugDriver &BD, Module *M1, Module *M2,
 /// under consideration for miscompilation vs. those that are not, and test
 /// accordingly. Each group of functions becomes a separate Module.
 ///
-int ReduceMiscompilingFunctions::TestFuncs(const std::vector<Function*> &Funcs,
-                                           std::string &Error) {
+bool ReduceMiscompilingFunctions::TestFuncs(const std::vector<Function*> &Funcs,
+                                            std::string &Error) {
   // Test to see if the function is misoptimized if we ONLY run it on the
   // functions listed in Funcs.
   outs() << "Checking to see if the program is misoptimized when "
@@ -250,14 +250,35 @@ int ReduceMiscompilingFunctions::TestFuncs(const std::vector<Function*> &Funcs,
   PrintFunctionList(Funcs);
   outs() << '\n';
 
-  // Split the module into the two halves of the program we want.
+  // Create a clone for two reasons:
+  // * If the optimization passes delete any function, the deleted function
+  //   will be in the clone and Funcs will still point to valid memory
+  // * If the optimization passes use interprocedural information to break
+  //   a function, we want to continue with the original function. Otherwise
+  //   we can conclude that a function triggers the bug when in fact one
+  //   needs a larger set of original functions to do so.
   ValueMap<const Value*, Value*> VMap;
+  Module *Clone = CloneModule(BD.getProgram(), VMap);
+  Module *Orig = BD.swapProgramIn(Clone);
+
+  std::vector<Function*> FuncsOnClone;
+  for (unsigned i = 0, e = Funcs.size(); i != e; ++i) {
+    Function *F = cast<Function>(VMap[Funcs[i]]);
+    FuncsOnClone.push_back(F);
+  }
+
+  // Split the module into the two halves of the program we want.
+  VMap.clear();
   Module *ToNotOptimize = CloneModule(BD.getProgram(), VMap);
-  Module *ToOptimize = SplitFunctionsOutOfModule(ToNotOptimize, Funcs,
+  Module *ToOptimize = SplitFunctionsOutOfModule(ToNotOptimize, FuncsOnClone,
                                                  VMap);
 
   // Run the predicate, note that the predicate will delete both input modules.
-  return TestFn(BD, ToOptimize, ToNotOptimize, Error);
+  bool Broken = TestFn(BD, ToOptimize, ToNotOptimize, Error);
+
+  delete BD.swapProgramIn(Orig);
+
+  return Broken;
 }
 
 /// DisambiguateGlobalSymbols - Give anonymous global values names.