diff options
author | Keno Fischer <kfischer@college.harvard.edu> | 2015-12-04 21:56:46 +0000 |
---|---|---|
committer | Keno Fischer <kfischer@college.harvard.edu> | 2015-12-04 21:56:46 +0000 |
commit | 04464cf7313a7c2873f2b8a9011a19f1685b44c1 (patch) | |
tree | 4406bbc91a7f670202224b5fba05e4de166b5ba8 /llvm/tools/opt/opt.cpp | |
parent | f3491496dcbaa236943c6a167399e85335acdc4d (diff) | |
download | bcm5719-llvm-04464cf7313a7c2873f2b8a9011a19f1685b44c1.tar.gz bcm5719-llvm-04464cf7313a7c2873f2b8a9011a19f1685b44c1.zip |
[llc/opt] Add an option to run all passes twice
Summary: Lately, I have submitted a number of patches to fix bugs that
only occurred when using the same pass manager to compile multiple
modules (generally these bugs are failure to reset some persistent
state). Unfortunately I don't think there is currently a way to test
that from the command line. This adds a very simple flag to both llc
and opt, under which the tools will simply re-run their respective
pass pipelines using the same pass manager on (a clone of the same
module). Additionally, we verify that both outputs are bitwise the
same.
Reviewers: yaron.keren
Subscribers: loladiro, yaron.keren, kcc, llvm-commits
Differential Revision: http://reviews.llvm.org/D14965
llvm-svn: 254774
Diffstat (limited to 'llvm/tools/opt/opt.cpp')
-rw-r--r-- | llvm/tools/opt/opt.cpp | 48 |
1 files changed, 43 insertions, 5 deletions
diff --git a/llvm/tools/opt/opt.cpp b/llvm/tools/opt/opt.cpp index 5fe2f034c6e..c1510a7fb25 100644 --- a/llvm/tools/opt/opt.cpp +++ b/llvm/tools/opt/opt.cpp @@ -28,6 +28,7 @@ #include "llvm/IR/DebugInfo.h" #include "llvm/IR/IRPrintingPasses.h" #include "llvm/IR/LLVMContext.h" +#include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/LegacyPassNameParser.h" #include "llvm/IR/Module.h" #include "llvm/IR/Verifier.h" @@ -36,7 +37,6 @@ #include "llvm/LinkAllIR.h" #include "llvm/LinkAllPasses.h" #include "llvm/MC/SubtargetFeature.h" -#include "llvm/IR/LegacyPassManager.h" #include "llvm/Support/Debug.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Host.h" @@ -51,6 +51,7 @@ #include "llvm/Support/ToolOutputFile.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Transforms/IPO/PassManagerBuilder.h" +#include "llvm/Transforms/Utils/Cloning.h" #include <algorithm> #include <memory> using namespace llvm; @@ -190,6 +191,11 @@ static cl::opt<bool> PreserveAssemblyUseListOrder( cl::desc("Preserve use-list order when writing LLVM assembly."), cl::init(false), cl::Hidden); +static cl::opt<bool> + RunTwice("run-twice", + cl::desc("Run all passes twice, re-using the same pass manager."), + cl::init(false), cl::Hidden); + static inline void addPass(legacy::PassManagerBase &PM, Pass *P) { // Add the pass to the pass manager... PM.add(P); @@ -582,14 +588,25 @@ int main(int argc, char **argv) { if (!NoVerify && !VerifyEach) Passes.add(createVerifierPass()); + // In run twice mode, we want to make sure the output is bit-by-bit + // equivalent if we run the pass manager again, so setup two buffers and + // a stream to write to them. Note that llc does something similar and it + // may be worth to abstract this out in the future. + SmallVector<char, 0> Buffer; + SmallVector<char, 0> CompileTwiceBuffer; + std::unique_ptr<raw_svector_ostream> BOS; + raw_ostream *OS = &Out->os(); + if (RunTwice) { + BOS = make_unique<raw_svector_ostream>(Buffer); + OS = BOS.get(); + } + // Write bitcode or assembly to the output as the last step... if (!NoOutput && !AnalyzeOnly) { if (OutputAssembly) - Passes.add( - createPrintModulePass(Out->os(), "", PreserveAssemblyUseListOrder)); + Passes.add(createPrintModulePass(*OS, "", PreserveAssemblyUseListOrder)); else - Passes.add( - createBitcodeWriterPass(Out->os(), PreserveBitcodeUseListOrder)); + Passes.add(createBitcodeWriterPass(*OS, PreserveBitcodeUseListOrder)); } // Before executing passes, print the final values of the LLVM options. @@ -598,6 +615,27 @@ int main(int argc, char **argv) { // Now that we have all of the passes ready, run them. Passes.run(*M); + // If requested, run all passes again with the same pass manager to catch + // bugs caused by persistent state in the passes + if (RunTwice) { + CompileTwiceBuffer = Buffer; + Buffer.clear(); + std::unique_ptr<Module> M2(CloneModule(M.get())); + Passes.run(*M2); + if (Buffer.size() != CompileTwiceBuffer.size() || + (memcmp(Buffer.data(), CompileTwiceBuffer.data(), Buffer.size()) != + 0)) { + errs() << "Running the pass manager twice changed the output.\n" + "Writing the result of the second run to the specified output." + "To generate the one-run comparison binary, just run without\n" + "the compile-twice option\n"; + Out->os() << BOS->str(); + Out->keep(); + return 1; + } + Out->os() << BOS->str(); + } + // Declare success. if (!NoOutput || PrintBreakpoints) Out->keep(); |