X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=blobdiff_plain;f=tools%2Fllc%2Fllc.cpp;h=531aba1f64bf9e071dcf0b2e750ad19966a5762a;hp=e33cd795d3ae2d01b2fe708ad6e8c70d6779d16a;hb=6f41c1352b5e860ce6fd737f1d69a13f810c0311;hpb=26be2142324893e254ec9ba91da3a54694936498 diff --git a/tools/llc/llc.cpp b/tools/llc/llc.cpp index e33cd795d3a..531aba1f64b 100644 --- a/tools/llc/llc.cpp +++ b/tools/llc/llc.cpp @@ -45,6 +45,7 @@ #include "llvm/Support/ToolOutputFile.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetSubtargetInfo.h" +#include "llvm/Transforms/Utils/Cloning.h" #include using namespace llvm; @@ -96,6 +97,12 @@ static cl::opt AsmVerbose("asm-verbose", cl::desc("Add comments to directives."), cl::init(true)); +static cl::opt + CompileTwice("compile-twice", cl::Hidden, + cl::desc("Run everything twice, re-using the same pass " + "manager and verify the the result is the same."), + cl::init(false)); + static int compileModule(char **, LLVMContext &); static std::unique_ptr @@ -312,8 +319,7 @@ static int compileModule(char **argv, LLVMContext &Context) { PM.add(new TargetLibraryInfoWrapperPass(TLII)); // Add the target data from the target machine, if it exists, or the module. - if (const DataLayout *DL = Target->getDataLayout()) - M->setDataLayout(*DL); + M->setDataLayout(Target->createDataLayout()); // Override function attributes based on CPUStr, FeaturesStr, and command line // flags. @@ -326,10 +332,15 @@ static int compileModule(char **argv, LLVMContext &Context) { { raw_pwrite_stream *OS = &Out->os(); - std::unique_ptr BOS; - if (FileType != TargetMachine::CGFT_AssemblyFile && - !Out->os().supportsSeeking()) { - BOS = make_unique(*OS); + + // Manually do the buffering rather than using buffer_ostream, + // so we can memcmp the contents in CompileTwice mode + SmallVector Buffer; + std::unique_ptr BOS; + if ((FileType != TargetMachine::CGFT_AssemblyFile && + !Out->os().supportsSeeking()) || + CompileTwice) { + BOS = make_unique(Buffer); OS = BOS.get(); } @@ -379,7 +390,39 @@ static int compileModule(char **argv, LLVMContext &Context) { // Before executing passes, print the final values of the LLVM options. cl::PrintOptionValues(); + // If requested, run the pass manager over the same module again, + // to catch any bugs due to persistent state in the passes. Note that + // opt has the same functionality, so it may be worth abstracting this out + // in the future. + SmallVector CompileTwiceBuffer; + if (CompileTwice) { + std::unique_ptr M2(llvm::CloneModule(M.get())); + PM.run(*M2); + CompileTwiceBuffer = Buffer; + Buffer.clear(); + } + PM.run(*M); + + // Compare the two outputs and make sure they're the same + if (CompileTwice) { + 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\n" + "To generate the one-run comparison binary, just run without\n" + "the compile-twice option\n"; + Out->os() << Buffer; + Out->keep(); + return 1; + } + } + + if (BOS) { + Out->os() << Buffer; + } } // Declare success.