#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"
#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"
#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;
StripDebug("strip-debug",
cl::desc("Strip debugger symbol info from translation unit"));
-static cl::opt<bool>
-StripValueNames("strip-value-names", cl::desc("Remove llvm value names"));
-
-static cl::opt<bool>
-NameValues("name-values", cl::desc("Give anonymous llvm values a name"));
-
static cl::opt<bool>
DisableInline("disable-inlining", cl::desc("Do not run the inliner pass"));
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);
GetCodeGenOptLevel());
}
-static void removeValueNames(Module &Mod) {
- for (Function &F : Mod) {
- for (BasicBlock &BB : F) {
- BB.setName("");
- for (Instruction &I : BB)
- I.setName("");
- }
- }
-}
-
-static void nameValuesInFunction(Function &F) {
- bool FirstBB = true;
- for (BasicBlock &BB : F) {
- if (!BB.hasName())
- BB.setName(FirstBB ? "entry" : "BB");
- FirstBB = false;
-
- for (Instruction &I : BB) {
- if (I.getType()->isVoidTy())
- continue;
- if (!I.hasName())
- I.setName("v");
- }
- }
-}
-
-static void nameValues(Module &Mod) {
- for (Function &F : Mod)
- nameValuesInFunction(F);
-}
-
#ifdef LINK_POLLY_INTO_TOOLS
namespace polly {
void initializePollyPasses(llvm::PassRegistry &Registry);
initializeVectorization(Registry);
initializeIPO(Registry);
initializeAnalysis(Registry);
- initializeIPA(Registry);
initializeTransformUtils(Registry);
initializeInstCombine(Registry);
initializeInstrumentation(Registry);
initializeRewriteSymbolsPass(Registry);
initializeWinEHPreparePass(Registry);
initializeDwarfEHPreparePass(Registry);
+ initializeSjLjEHPreparePass(Registry);
#ifdef LINK_POLLY_INTO_TOOLS
polly::initializePollyPasses(Registry);
if (StripDebug)
StripDebugInfo(*M);
- if (StripValueNames)
- removeValueNames(*M);
-
- if (NameValues)
- nameValues(*M);
-
// Immediately run the verifier to catch any problems before starting up the
// pass pipelines. Otherwise we can crash on broken code during
// doInitialization().
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 = nullptr;
+
// Write bitcode or assembly to the output as the last step...
if (!NoOutput && !AnalyzeOnly) {
+ assert(Out);
+ OS = &Out->os();
+ if (RunTwice) {
+ BOS = make_unique<raw_svector_ostream>(Buffer);
+ OS = BOS.get();
+ }
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.
cl::PrintOptionValues();
+ // If requested, run all passes again with the same pass manager to catch
+ // bugs caused by persistent state in the passes
+ if (RunTwice) {
+ std::unique_ptr<Module> M2(CloneModule(M.get()));
+ Passes.run(*M2);
+ CompileTwiceBuffer = Buffer;
+ Buffer.clear();
+ }
+
// Now that we have all of the passes ready, run them.
Passes.run(*M);
+ // Compare the two outputs and make sure they're the same
+ if (RunTwice) {
+ assert(Out);
+ 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() << BOS->str();
+ Out->keep();
+ return 1;
+ }
+ Out->os() << BOS->str();
+ }
+
// Declare success.
if (!NoOutput || PrintBreakpoints)
Out->keep();