llvm.org GIT mirror llvm / 6f41c13
[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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@254774 91177308-0d34-0410-b5e6-96231b3b80d8 Keno Fischer 3 years ago
4 changed file(s) with 111 addition(s) and 9 deletion(s). Raw diff Collapse all Expand all
0 ; Check that there is no persistent state in the ELF emitter that crashes us
1 ; when we try to reuse the pass manager
2 ; RUN: llc -compile-twice -filetype=obj %s -o -
3
4 target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32"
5 target triple = "i386-pc-linux-gnu"
0 ; The pass here doesn't matter (we use deadargelim), but test
1 ; that the -run-twice options exists, generates output, and
2 ; doesn't crash
3 ; RUN: opt -run-twice -deadargelim -S < %s | FileCheck %s
4
5 ; CHECK: define internal void @test
6 define internal {} @test() {
7 ret {} undef
8 }
9
10 define void @caller() {
11 call {} @test()
12 ret void
13 }
4444 #include "llvm/Support/ToolOutputFile.h"
4545 #include "llvm/Target/TargetMachine.h"
4646 #include "llvm/Target/TargetSubtargetInfo.h"
47 #include "llvm/Transforms/Utils/Cloning.h"
4748 #include
4849 using namespace llvm;
4950
9495 static cl::opt AsmVerbose("asm-verbose",
9596 cl::desc("Add comments to directives."),
9697 cl::init(true));
98
99 static cl::opt
100 CompileTwice("compile-twice", cl::Hidden,
101 cl::desc("Run everything twice, re-using the same pass "
102 "manager and verify the the result is the same."),
103 cl::init(false));
97104
98105 static int compileModule(char **, LLVMContext &);
99106
324331
325332 {
326333 raw_pwrite_stream *OS = &Out->os();
327 std::unique_ptr BOS;
328 if (FileType != TargetMachine::CGFT_AssemblyFile &&
329 !Out->os().supportsSeeking()) {
330 BOS = make_unique(*OS);
334
335 // Manually do the buffering rather than using buffer_ostream,
336 // so we can memcmp the contents in CompileTwice mode
337 SmallVector Buffer;
338 std::unique_ptr BOS;
339 if ((FileType != TargetMachine::CGFT_AssemblyFile &&
340 !Out->os().supportsSeeking()) ||
341 CompileTwice) {
342 BOS = make_unique(Buffer);
331343 OS = BOS.get();
332344 }
333345
377389 // Before executing passes, print the final values of the LLVM options.
378390 cl::PrintOptionValues();
379391
392 // If requested, run the pass manager over the same module again,
393 // to catch any bugs due to persistent state in the passes. Note that
394 // opt has the same functionality, so it may be worth abstracting this out
395 // in the future.
396 SmallVector CompileTwiceBuffer;
397 if (CompileTwice) {
398 std::unique_ptr M2(llvm::CloneModule(M.get()));
399 PM.run(*M2);
400 CompileTwiceBuffer = Buffer;
401 Buffer.clear();
402 }
403
380404 PM.run(*M);
405
406 // Compare the two outputs and make sure they're the same
407 if (CompileTwice) {
408 if (Buffer.size() != CompileTwiceBuffer.size() ||
409 (memcmp(Buffer.data(), CompileTwiceBuffer.data(), Buffer.size()) !=
410 0)) {
411 errs()
412 << "Running the pass manager twice changed the output.\n"
413 "Writing the result of the second run to the specified output\n"
414 "To generate the one-run comparison binary, just run without\n"
415 "the compile-twice option\n";
416 Out->os() << Buffer;
417 Out->keep();
418 return 1;
419 }
420 }
421
422 if (BOS) {
423 Out->os() << Buffer;
424 }
381425 }
382426
383427 // Declare success.
2727 #include "llvm/IR/DebugInfo.h"
2828 #include "llvm/IR/IRPrintingPasses.h"
2929 #include "llvm/IR/LLVMContext.h"
30 #include "llvm/IR/LegacyPassManager.h"
3031 #include "llvm/IR/LegacyPassNameParser.h"
3132 #include "llvm/IR/Module.h"
3233 #include "llvm/IR/Verifier.h"
3536 #include "llvm/LinkAllIR.h"
3637 #include "llvm/LinkAllPasses.h"
3738 #include "llvm/MC/SubtargetFeature.h"
38 #include "llvm/IR/LegacyPassManager.h"
3939 #include "llvm/Support/Debug.h"
4040 #include "llvm/Support/FileSystem.h"
4141 #include "llvm/Support/Host.h"
5050 #include "llvm/Support/ToolOutputFile.h"
5151 #include "llvm/Target/TargetMachine.h"
5252 #include "llvm/Transforms/IPO/PassManagerBuilder.h"
53 #include "llvm/Transforms/Utils/Cloning.h"
5354 #include
5455 #include
5556 using namespace llvm;
188189 "preserve-ll-uselistorder",
189190 cl::desc("Preserve use-list order when writing LLVM assembly."),
190191 cl::init(false), cl::Hidden);
192
193 static cl::opt
194 RunTwice("run-twice",
195 cl::desc("Run all passes twice, re-using the same pass manager."),
196 cl::init(false), cl::Hidden);
191197
192198 static inline void addPass(legacy::PassManagerBase &PM, Pass *P) {
193199 // Add the pass to the pass manager...
581587 if (!NoVerify && !VerifyEach)
582588 Passes.add(createVerifierPass());
583589
590 // In run twice mode, we want to make sure the output is bit-by-bit
591 // equivalent if we run the pass manager again, so setup two buffers and
592 // a stream to write to them. Note that llc does something similar and it
593 // may be worth to abstract this out in the future.
594 SmallVector Buffer;
595 SmallVector CompileTwiceBuffer;
596 std::unique_ptr BOS;
597 raw_ostream *OS = &Out->os();
598 if (RunTwice) {
599 BOS = make_unique(Buffer);
600 OS = BOS.get();
601 }
602
584603 // Write bitcode or assembly to the output as the last step...
585604 if (!NoOutput && !AnalyzeOnly) {
586605 if (OutputAssembly)
587 Passes.add(
588 createPrintModulePass(Out->os(), "", PreserveAssemblyUseListOrder));
606 Passes.add(createPrintModulePass(*OS, "", PreserveAssemblyUseListOrder));
589607 else
590 Passes.add(
591 createBitcodeWriterPass(Out->os(), PreserveBitcodeUseListOrder));
608 Passes.add(createBitcodeWriterPass(*OS, PreserveBitcodeUseListOrder));
592609 }
593610
594611 // Before executing passes, print the final values of the LLVM options.
596613
597614 // Now that we have all of the passes ready, run them.
598615 Passes.run(*M);
616
617 // If requested, run all passes again with the same pass manager to catch
618 // bugs caused by persistent state in the passes
619 if (RunTwice) {
620 CompileTwiceBuffer = Buffer;
621 Buffer.clear();
622 std::unique_ptr M2(CloneModule(M.get()));
623 Passes.run(*M2);
624 if (Buffer.size() != CompileTwiceBuffer.size() ||
625 (memcmp(Buffer.data(), CompileTwiceBuffer.data(), Buffer.size()) !=
626 0)) {
627 errs() << "Running the pass manager twice changed the output.\n"
628 "Writing the result of the second run to the specified output."
629 "To generate the one-run comparison binary, just run without\n"
630 "the compile-twice option\n";
631 Out->os() << BOS->str();
632 Out->keep();
633 return 1;
634 }
635 Out->os() << BOS->str();
636 }
599637
600638 // Declare success.
601639 if (!NoOutput || PrintBreakpoints)