/// Optimize merged modules using various IPO passes bool LTOCodeGenerator::generateObjectFile(raw_ostream &out, std::string &errMsg) { // if options were requested, set them if (!_codegenOptions.empty()) cl::ParseCommandLineOptions(_codegenOptions.size(), const_cast<char **>(&_codegenOptions[0])); if (this->determineTarget(errMsg)) return true; Module* mergedModule = _linker.getModule(); // mark which symbols can not be internalized this->applyScopeRestrictions(); // Instantiate the pass manager to organize the passes. PassManager passes; // Start off with a verification pass. passes.add(createVerifierPass()); // Add an appropriate DataLayout instance for this module... passes.add(new DataLayout(*_target->getDataLayout())); passes.add(new TargetTransformInfo(_target->getScalarTargetTransformInfo(), _target->getVectorTargetTransformInfo())); // Enabling internalize here would use its AllButMain variant. It // keeps only main if it exists and does nothing for libraries. Instead // we create the pass ourselves with the symbol list provided by the linker. PassManagerBuilder().populateLTOPassManager(passes, /*Internalize=*/false, !DisableInline, DisableGVNLoadPRE); // Make sure everything is still good. passes.add(createVerifierPass()); FunctionPassManager *codeGenPasses = new FunctionPassManager(mergedModule); codeGenPasses->add(new DataLayout(*_target->getDataLayout())); formatted_raw_ostream Out(out); if (_target->addPassesToEmitFile(*codeGenPasses, Out, TargetMachine::CGFT_ObjectFile)) { errMsg = "target file type not supported"; return true; } // Run our queue of passes all at once now, efficiently. passes.run(*mergedModule); // Run the code generator, and write assembly file codeGenPasses->doInitialization(); for (Module::iterator it = mergedModule->begin(), e = mergedModule->end(); it != e; ++it) if (!it->isDeclaration()) codeGenPasses->run(*it); codeGenPasses->doFinalization(); delete codeGenPasses; return false; // success }
static int compileModule(char **argv, LLVMContext &Context) { // Load the module to be compiled... SMDiagnostic Err; OwningPtr<Module> M; Module *mod = 0; Triple TheTriple; bool SkipModule = MCPU == "help" || (!MAttrs.empty() && MAttrs.front() == "help"); // If user just wants to list available options, skip module loading if (!SkipModule) { M.reset(ParseIRFile(InputFilename, Err, Context)); mod = M.get(); if (mod == 0) { Err.print(argv[0], errs()); return 1; } // If we are supposed to override the target triple, do so now. if (!TargetTriple.empty()) mod->setTargetTriple(Triple::normalize(TargetTriple)); TheTriple = Triple(mod->getTargetTriple()); } else { TheTriple = Triple(Triple::normalize(TargetTriple)); } if (TheTriple.getTriple().empty()) TheTriple.setTriple(sys::getDefaultTargetTriple()); // Get the target specific parser. std::string Error; const Target *TheTarget = TargetRegistry::lookupTarget(MArch, TheTriple, Error); if (!TheTarget) { errs() << argv[0] << ": " << Error; return 1; } // Package up features to be passed to target/subtarget std::string FeaturesStr; if (MAttrs.size()) { SubtargetFeatures Features; for (unsigned i = 0; i != MAttrs.size(); ++i) Features.AddFeature(MAttrs[i]); FeaturesStr = Features.getString(); } CodeGenOpt::Level OLvl = CodeGenOpt::Default; switch (OptLevel) { default: errs() << argv[0] << ": invalid optimization level.\n"; return 1; case ' ': break; case '0': OLvl = CodeGenOpt::None; break; case '1': OLvl = CodeGenOpt::Less; break; case '2': OLvl = CodeGenOpt::Default; break; case '3': OLvl = CodeGenOpt::Aggressive; break; } TargetOptions Options; Options.LessPreciseFPMADOption = EnableFPMAD; Options.NoFramePointerElim = DisableFPElim; Options.AllowFPOpFusion = FuseFPOps; Options.UnsafeFPMath = EnableUnsafeFPMath; Options.NoInfsFPMath = EnableNoInfsFPMath; Options.NoNaNsFPMath = EnableNoNaNsFPMath; Options.HonorSignDependentRoundingFPMathOption = EnableHonorSignDependentRoundingFPMath; Options.UseSoftFloat = GenerateSoftFloatCalls; if (FloatABIForCalls != FloatABI::Default) Options.FloatABIType = FloatABIForCalls; Options.NoZerosInBSS = DontPlaceZerosInBSS; Options.GuaranteedTailCallOpt = EnableGuaranteedTailCallOpt; Options.DisableTailCalls = DisableTailCalls; Options.StackAlignmentOverride = OverrideStackAlignment; Options.TrapFuncName = TrapFuncName; Options.PositionIndependentExecutable = EnablePIE; Options.EnableSegmentedStacks = SegmentedStacks; Options.UseInitArray = UseInitArray; OwningPtr<TargetMachine> target(TheTarget->createTargetMachine(TheTriple.getTriple(), MCPU, FeaturesStr, Options, RelocModel, CMModel, OLvl)); assert(target.get() && "Could not allocate target machine!"); assert(mod && "Should have exited after outputting help!"); TargetMachine &Target = *target.get(); if (DisableDotLoc) Target.setMCUseLoc(false); if (DisableCFI) Target.setMCUseCFI(false); if (EnableDwarfDirectory) Target.setMCUseDwarfDirectory(true); if (GenerateSoftFloatCalls) FloatABIForCalls = FloatABI::Soft; // Disable .loc support for older OS X versions. if (TheTriple.isMacOSX() && TheTriple.isMacOSXVersionLT(10, 6)) Target.setMCUseLoc(false); // Figure out where we are going to send the output. OwningPtr<tool_output_file> Out (GetOutputStream(TheTarget->getName(), TheTriple.getOS(), argv[0])); if (!Out) return 1; // Build up all of the passes that we want to do to the module. PassManager PM; // Add an appropriate TargetLibraryInfo pass for the module's triple. TargetLibraryInfo *TLI = new TargetLibraryInfo(TheTriple); if (DisableSimplifyLibCalls) TLI->disableAllFunctions(); PM.add(TLI); // Add the target data from the target machine, if it exists, or the module. if (const DataLayout *TD = Target.getDataLayout()) PM.add(new DataLayout(*TD)); else PM.add(new DataLayout(mod)); // Override default to generate verbose assembly. Target.setAsmVerbosityDefault(true); if (RelaxAll) { if (FileType != TargetMachine::CGFT_ObjectFile) errs() << argv[0] << ": warning: ignoring -mc-relax-all because filetype != obj"; else Target.setMCRelaxAll(true); } { formatted_raw_ostream FOS(Out->os()); AnalysisID StartAfterID = 0; AnalysisID StopAfterID = 0; const PassRegistry *PR = PassRegistry::getPassRegistry(); if (!StartAfter.empty()) { const PassInfo *PI = PR->getPassInfo(StartAfter); if (!PI) { errs() << argv[0] << ": start-after pass is not registered.\n"; return 1; } StartAfterID = PI->getTypeInfo(); } if (!StopAfter.empty()) { const PassInfo *PI = PR->getPassInfo(StopAfter); if (!PI) { errs() << argv[0] << ": stop-after pass is not registered.\n"; return 1; } StopAfterID = PI->getTypeInfo(); } // Ask the target to add backend passes as necessary. if (Target.addPassesToEmitFile(PM, FOS, FileType, NoVerify, StartAfterID, StopAfterID)) { errs() << argv[0] << ": target does not support generation of this" << " file type!\n"; return 1; } // Before executing passes, print the final values of the LLVM options. cl::PrintOptionValues(); PM.run(*mod); } // Declare success. Out->keep(); return 0; }
//===----------------------------------------------------------------------===// // main for opt // int main(int argc, char **argv) { sys::PrintStackTraceOnErrorSignal(); llvm::PrettyStackTraceProgram X(argc, argv); // Enable debug stream buffering. EnableDebugBuffering = true; llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. LLVMContext &Context = getGlobalContext(); // Initialize passes PassRegistry &Registry = *PassRegistry::getPassRegistry(); initializeCore(Registry); initializeScalarOpts(Registry); initializeIPO(Registry); initializeAnalysis(Registry); initializeIPA(Registry); initializeTransformUtils(Registry); initializeInstCombine(Registry); initializeInstrumentation(Registry); initializeTarget(Registry); cl::ParseCommandLineOptions(argc, argv, "llvm .bc -> .bc modular optimizer and analysis printer\n"); if (AnalyzeOnly && NoOutput) { errs() << argv[0] << ": analyze mode conflicts with no-output mode.\n"; return 1; } // Allocate a full target machine description only if necessary. // FIXME: The choice of target should be controllable on the command line. std::auto_ptr<TargetMachine> target; SMDiagnostic Err; // Load the input module... std::auto_ptr<Module> M; M.reset(ParseIRFile(InputFilename, Err, Context)); if (M.get() == 0) { Err.print(argv[0], errs()); return 1; } // Figure out what stream we are supposed to write to... OwningPtr<tool_output_file> Out; if (NoOutput) { if (!OutputFilename.empty()) errs() << "WARNING: The -o (output filename) option is ignored when\n" "the --disable-output option is used.\n"; } else { // Default to standard output. if (OutputFilename.empty()) OutputFilename = "-"; std::string ErrorInfo; Out.reset(new tool_output_file(OutputFilename.c_str(), ErrorInfo, raw_fd_ostream::F_Binary)); if (!ErrorInfo.empty()) { errs() << ErrorInfo << '\n'; return 1; } } // If the output is set to be emitted to standard out, and standard out is a // console, print out a warning message and refuse to do it. We don't // impress anyone by spewing tons of binary goo to a terminal. if (!Force && !NoOutput && !AnalyzeOnly && !OutputAssembly) if (CheckBitcodeOutputToConsole(Out->os(), !Quiet)) NoOutput = true; // Create a PassManager to hold and optimize the collection of passes we are // about to build. // PassManager Passes; // Add an appropriate TargetLibraryInfo pass for the module's triple. TargetLibraryInfo *TLI = new TargetLibraryInfo(Triple(M->getTargetTriple())); // The -disable-simplify-libcalls flag actually disables all builtin optzns. if (DisableSimplifyLibCalls) TLI->disableAllFunctions(); Passes.add(TLI); // Add an appropriate TargetData instance for this module. TargetData *TD = 0; const std::string &ModuleDataLayout = M.get()->getDataLayout(); if (!ModuleDataLayout.empty()) TD = new TargetData(ModuleDataLayout); else if (!DefaultDataLayout.empty()) TD = new TargetData(DefaultDataLayout); if (TD) Passes.add(TD); OwningPtr<FunctionPassManager> FPasses; if (OptLevelO1 || OptLevelO2 || OptLevelO3) { FPasses.reset(new FunctionPassManager(M.get())); if (TD) FPasses->add(new TargetData(*TD)); } if (PrintBreakpoints) { // Default to standard output. if (!Out) { if (OutputFilename.empty()) OutputFilename = "-"; std::string ErrorInfo; Out.reset(new tool_output_file(OutputFilename.c_str(), ErrorInfo, raw_fd_ostream::F_Binary)); if (!ErrorInfo.empty()) { errs() << ErrorInfo << '\n'; return 1; } } Passes.add(new BreakpointPrinter(Out->os())); NoOutput = true; } // If the -strip-debug command line option was specified, add it. If // -std-compile-opts was also specified, it will handle StripDebug. if (StripDebug && !StandardCompileOpts) addPass(Passes, createStripSymbolsPass(true)); // Create a new optimization pass for each one specified on the command line for (unsigned i = 0; i < PassList.size(); ++i) { // Check to see if -std-compile-opts was specified before this option. If // so, handle it. if (StandardCompileOpts && StandardCompileOpts.getPosition() < PassList.getPosition(i)) { AddStandardCompilePasses(Passes); StandardCompileOpts = false; } if (StandardLinkOpts && StandardLinkOpts.getPosition() < PassList.getPosition(i)) { AddStandardLinkPasses(Passes); StandardLinkOpts = false; } if (OptLevelO1 && OptLevelO1.getPosition() < PassList.getPosition(i)) { AddOptimizationPasses(Passes, *FPasses, 1); OptLevelO1 = false; } if (OptLevelO2 && OptLevelO2.getPosition() < PassList.getPosition(i)) { AddOptimizationPasses(Passes, *FPasses, 2); OptLevelO2 = false; } if (OptLevelO3 && OptLevelO3.getPosition() < PassList.getPosition(i)) { AddOptimizationPasses(Passes, *FPasses, 3); OptLevelO3 = false; } const PassInfo *PassInf = PassList[i]; Pass *P = 0; if (PassInf->getNormalCtor()) P = PassInf->getNormalCtor()(); else errs() << argv[0] << ": cannot create pass: "******"\n"; if (P) { PassKind Kind = P->getPassKind(); addPass(Passes, P); if (AnalyzeOnly) { switch (Kind) { case PT_BasicBlock: Passes.add(new BasicBlockPassPrinter(PassInf, Out->os())); break; case PT_Region: Passes.add(new RegionPassPrinter(PassInf, Out->os())); break; case PT_Loop: Passes.add(new LoopPassPrinter(PassInf, Out->os())); break; case PT_Function: Passes.add(new FunctionPassPrinter(PassInf, Out->os())); break; case PT_CallGraphSCC: Passes.add(new CallGraphSCCPassPrinter(PassInf, Out->os())); break; default: Passes.add(new ModulePassPrinter(PassInf, Out->os())); break; } } } if (PrintEachXForm) Passes.add(createPrintModulePass(&errs())); } // If -std-compile-opts was specified at the end of the pass list, add them. if (StandardCompileOpts) { AddStandardCompilePasses(Passes); StandardCompileOpts = false; } if (StandardLinkOpts) { AddStandardLinkPasses(Passes); StandardLinkOpts = false; } if (OptLevelO1) AddOptimizationPasses(Passes, *FPasses, 1); if (OptLevelO2) AddOptimizationPasses(Passes, *FPasses, 2); if (OptLevelO3) AddOptimizationPasses(Passes, *FPasses, 3); if (OptLevelO1 || OptLevelO2 || OptLevelO3) { FPasses->doInitialization(); for (Module::iterator F = M->begin(), E = M->end(); F != E; ++F) FPasses->run(*F); FPasses->doFinalization(); } // Check that the module is well formed on completion of optimization if (!NoVerify && !VerifyEach) Passes.add(createVerifierPass()); // Write bitcode or assembly to the output as the last step... if (!NoOutput && !AnalyzeOnly) { if (OutputAssembly) Passes.add(createPrintModulePass(&Out->os())); else Passes.add(createBitcodeWriterPass(Out->os())); } // Before executing passes, print the final values of the LLVM options. cl::PrintOptionValues(); // Now that we have all of the passes ready, run them. Passes.run(*M.get()); // Declare success. if (!NoOutput || PrintBreakpoints) Out->keep(); return 0; }
int main(int argc, char **argv) { // Print a stack trace if we signal out. sys::PrintStackTraceOnErrorSignal(); PrettyStackTraceProgram X(argc, argv); LLVMContext &Context = getGlobalContext(); llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. cl::ParseCommandLineOptions(argc, argv, "llvm profile dump decoder\n"); // Read in the bitcode file... std::string ErrorMessage; error_code ec; Module *M = 0; if(DiffMode) { ProfileInfoLoader PIL1(argv[0], BitcodeFile); ProfileInfoLoader PIL2(argv[0], ProfileDataFile); ProfileInfoCompare Compare(PIL1,PIL2); Compare.run(); return 0; } if(Merge != MERGE_NONE) { /** argument alignment: * BitcodeFile ProfileDataFile MergeFile * output.out input1.out other-input.out **/ // Add the ProfileDataFile arg to MergeFile, it blongs to the MergeFile MergeFile.push_back(std::string(ProfileDataFile.getValue())); if(MergeFile.size()==0){ errs()<<"No merge file!"; return 0; } //Initialize the ProfileInfoMerge class using one of merge files ProfileInfoLoader AHS(argv[0], MergeFile.back()); ProfileInfoMerge MergeClass(std::string(argv[0]), BitcodeFile, AHS); for (std::vector<std::string>::iterator merIt = MergeFile.begin(), END = MergeFile.end() - 1; merIt != END; ++merIt) { //errs()<<*merIt<<"\n"; ProfileInfoLoader THS(argv[0], *merIt); MergeClass.addProfileInfo(THS); } if (Merge == MERGE_SUM) { MergeClass.writeTotalFile(); } else if (Merge == MERGE_AVG) { /** avg = sum/N **/ MergeClass.writeTotalFile( std::bind2nd(std::divides<unsigned>(), MergeFile.size())); } return 0; } #if LLVM_VERSION_MAJOR==3 && LLVM_VERSION_MINOR==4 OwningPtr<MemoryBuffer> Buffer; if (!(ec = MemoryBuffer::getFileOrSTDIN(BitcodeFile, Buffer.get()))) { M = ParseBitcodeFile(Buffer.get(), Context, &ErrorMessage); } else ErrorMessage = ec.message(); #else auto Buffer = MemoryBuffer::getFileOrSTDIN(BitcodeFile); if (!(ec = Buffer.getError())){ auto R = parseBitcodeFile(&**Buffer, Context); if(R.getError()){ M = NULL; ErrorMessage = R.getError().message(); }else M = R.get(); } else ErrorMessage = ec.message(); #endif if (M == 0) { errs() << argv[0] << ": " << BitcodeFile << ": " << ErrorMessage << "\n"; return 1; } // Run the printer pass. PassManager PassMgr; PassMgr.add(createProfileLoaderPass(ProfileDataFile)); if(CommMode) { PassMgr.add(new ProfileInfoComm()); PassMgr.run(*M); return 0; } if(Convert){ Require3rdArg("no output file"); ProfileInfoWriter PIW(argv[0], MergeFile.front()); PassMgr.add(new ProfileInfoConverter(PIW)); }else if(Timing.size() != 0){ Require3rdArg("no timing source file"); PassMgr.add(new ProfileTimingPrint(std::move(Timing.getValue()), MergeFile)); }else{ // Read the profiling information. This is redundant since we load it again // using the standard profile info provider pass, but for now this gives us // access to additional information not exposed via the ProfileInfo // interface. ProfileInfoLoader PIL(argv[0], ProfileDataFile); PassMgr.add(new ProfileInfoPrinterPass(PIL)); } PassMgr.run(*M); return 0; }
void LTOCodeGenerator::applyScopeRestrictions() { if (_scopeRestrictionsDone) return; Module *mergedModule = _linker.getModule(); // Start off with a verification pass. PassManager passes; passes.add(createVerifierPass()); // mark which symbols can not be internalized MCContext Context(*_target->getMCAsmInfo(), *_target->getRegisterInfo(),NULL); Mangler mangler(Context, *_target->getDataLayout()); std::vector<const char*> mustPreserveList; SmallPtrSet<GlobalValue*, 8> asmUsed; for (Module::iterator f = mergedModule->begin(), e = mergedModule->end(); f != e; ++f) applyRestriction(*f, mustPreserveList, asmUsed, mangler); for (Module::global_iterator v = mergedModule->global_begin(), e = mergedModule->global_end(); v != e; ++v) applyRestriction(*v, mustPreserveList, asmUsed, mangler); for (Module::alias_iterator a = mergedModule->alias_begin(), e = mergedModule->alias_end(); a != e; ++a) applyRestriction(*a, mustPreserveList, asmUsed, mangler); GlobalVariable *LLVMCompilerUsed = mergedModule->getGlobalVariable("llvm.compiler.used"); findUsedValues(LLVMCompilerUsed, asmUsed); if (LLVMCompilerUsed) LLVMCompilerUsed->eraseFromParent(); if (!asmUsed.empty()) { llvm::Type *i8PTy = llvm::Type::getInt8PtrTy(_context); std::vector<Constant*> asmUsed2; for (SmallPtrSet<GlobalValue*, 16>::const_iterator i = asmUsed.begin(), e = asmUsed.end(); i !=e; ++i) { GlobalValue *GV = *i; Constant *c = ConstantExpr::getBitCast(GV, i8PTy); asmUsed2.push_back(c); } llvm::ArrayType *ATy = llvm::ArrayType::get(i8PTy, asmUsed2.size()); LLVMCompilerUsed = new llvm::GlobalVariable(*mergedModule, ATy, false, llvm::GlobalValue::AppendingLinkage, llvm::ConstantArray::get(ATy, asmUsed2), "llvm.compiler.used"); LLVMCompilerUsed->setSection("llvm.metadata"); } // Add prerequisite passes needed by SAFECode PassManagerBuilder().populateLTOPassManager(passes, /*Internalize=*/ false, !DisableInline); passes.add(createInternalizePass(mustPreserveList)); // apply scope restrictions passes.run(*mergedModule); _scopeRestrictionsDone = true; }
/// Optimize merged modules using various IPO passes bool LTOCodeGenerator::generateObjectFile(raw_ostream &out, bool DisableOpt, bool DisableInline, bool DisableGVNLoadPRE, std::string &errMsg) { if (!this->determineTarget(errMsg)) return false; Module *mergedModule = IRLinker.getModule(); // Mark which symbols can not be internalized this->applyScopeRestrictions(); // Instantiate the pass manager to organize the passes. PassManager passes; // Start off with a verification pass. passes.add(createVerifierPass()); passes.add(createDebugInfoVerifierPass()); // Add an appropriate DataLayout instance for this module... mergedModule->setDataLayout(TargetMach->getDataLayout()); passes.add(new DataLayoutPass(mergedModule)); // Add appropriate TargetLibraryInfo for this module. passes.add(new TargetLibraryInfo(Triple(TargetMach->getTargetTriple()))); TargetMach->addAnalysisPasses(passes); // Enabling internalize here would use its AllButMain variant. It // keeps only main if it exists and does nothing for libraries. Instead // we create the pass ourselves with the symbol list provided by the linker. if (!DisableOpt) PassManagerBuilder().populateLTOPassManager(passes, /*Internalize=*/false, !DisableInline, DisableGVNLoadPRE); // Make sure everything is still good. passes.add(createVerifierPass()); passes.add(createDebugInfoVerifierPass()); PassManager codeGenPasses; codeGenPasses.add(new DataLayoutPass(mergedModule)); formatted_raw_ostream Out(out); // If the bitcode files contain ARC code and were compiled with optimization, // the ObjCARCContractPass must be run, so do it unconditionally here. codeGenPasses.add(createObjCARCContractPass()); if (TargetMach->addPassesToEmitFile(codeGenPasses, Out, TargetMachine::CGFT_ObjectFile)) { errMsg = "target file type not supported"; return false; } // Run our queue of passes all at once now, efficiently. passes.run(*mergedModule); // Run the code generator, and write assembly file codeGenPasses.run(*mergedModule); return true; }
// main - Entry point for the llc compiler. // int main(int argc, char **argv) { sys::PrintStackTraceOnErrorSignal(); PrettyStackTraceProgram X(argc, argv); // Enable debug stream buffering. EnableDebugBuffering = true; LLVMContext &Context = getGlobalContext(); llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. // Initialize targets first, so that --version shows registered targets. InitializeAllTargets(); InitializeAllTargetMCs(); InitializeAllAsmPrinters(); InitializeAllAsmParsers(); // Register the target printer for --version. cl::AddExtraVersionPrinter(TargetRegistry::printRegisteredTargetsForVersion); cl::ParseCommandLineOptions(argc, argv, "llvm system compiler\n"); // Load the module to be compiled... SMDiagnostic Err; std::auto_ptr<Module> M; M.reset(ParseIRFile(InputFilename, Err, Context)); if (M.get() == 0) { Err.print(argv[0], errs()); return 1; } Module &mod = *M.get(); // If we are supposed to override the target triple, do so now. if (!TargetTriple.empty()) mod.setTargetTriple(Triple::normalize(TargetTriple)); Triple TheTriple(mod.getTargetTriple()); if (TheTriple.getTriple().empty()) TheTriple.setTriple(sys::getDefaultTargetTriple()); // Allocate target machine. First, check whether the user has explicitly // specified an architecture to compile for. If so we have to look it up by // name, because it might be a backend that has no mapping to a target triple. const Target *TheTarget = 0; if (!MArch.empty()) { for (TargetRegistry::iterator it = TargetRegistry::begin(), ie = TargetRegistry::end(); it != ie; ++it) { if (MArch == it->getName()) { TheTarget = &*it; break; } } if (!TheTarget) { errs() << argv[0] << ": error: invalid target '" << MArch << "'.\n"; return 1; } // Adjust the triple to match (if known), otherwise stick with the // module/host triple. Triple::ArchType Type = Triple::getArchTypeForLLVMName(MArch); if (Type != Triple::UnknownArch) TheTriple.setArch(Type); } else { std::string Err; TheTarget = TargetRegistry::lookupTarget(TheTriple.getTriple(), Err); if (TheTarget == 0) { errs() << argv[0] << ": error auto-selecting target for module '" << Err << "'. Please use the -march option to explicitly " << "pick a target.\n"; return 1; } } // Package up features to be passed to target/subtarget std::string FeaturesStr; if (MAttrs.size()) { SubtargetFeatures Features; for (unsigned i = 0; i != MAttrs.size(); ++i) Features.AddFeature(MAttrs[i]); FeaturesStr = Features.getString(); } std::auto_ptr<TargetMachine> target(TheTarget->createTargetMachine(TheTriple.getTriple(), MCPU, FeaturesStr, RelocModel, CMModel)); assert(target.get() && "Could not allocate target machine!"); TargetMachine &Target = *target.get(); if (DisableDotLoc) Target.setMCUseLoc(false); if (DisableCFI) Target.setMCUseCFI(false); if (EnableDwarfDirectory) Target.setMCUseDwarfDirectory(true); // Disable .loc support for older OS X versions. if (TheTriple.isMacOSX() && TheTriple.isMacOSXVersionLT(10, 6)) Target.setMCUseLoc(false); // Figure out where we are going to send the output... OwningPtr<tool_output_file> Out (GetOutputStream(TheTarget->getName(), TheTriple.getOS(), argv[0])); if (!Out) return 1; CodeGenOpt::Level OLvl = CodeGenOpt::Default; switch (OptLevel) { default: errs() << argv[0] << ": invalid optimization level.\n"; return 1; case ' ': break; case '0': OLvl = CodeGenOpt::None; break; case '1': OLvl = CodeGenOpt::Less; break; case '2': OLvl = CodeGenOpt::Default; break; case '3': OLvl = CodeGenOpt::Aggressive; break; } // Build up all of the passes that we want to do to the module. PassManager PM; // Add the target data from the target machine, if it exists, or the module. if (const TargetData *TD = Target.getTargetData()) PM.add(new TargetData(*TD)); else PM.add(new TargetData(&mod)); // Override default to generate verbose assembly. Target.setAsmVerbosityDefault(true); if (RelaxAll) { if (FileType != TargetMachine::CGFT_ObjectFile) errs() << argv[0] << ": warning: ignoring -mc-relax-all because filetype != obj"; else Target.setMCRelaxAll(true); } { formatted_raw_ostream FOS(Out->os()); // Ask the target to add backend passes as necessary. if (Target.addPassesToEmitFile(PM, FOS, FileType, OLvl, NoVerify)) { errs() << argv[0] << ": target does not support generation of this" << " file type!\n"; return 1; } // Before executing passes, print the final values of the LLVM options. cl::PrintOptionValues(); PM.run(mod); } // Declare success. Out->keep(); return 0; }
static int compileModule(char **argv, LLVMContext &Context) { // Load the module to be compiled... SMDiagnostic Err; std::unique_ptr<Module> M; Triple TheTriple; bool SkipModule = MCPU == "help" || (!MAttrs.empty() && MAttrs.front() == "help"); // If user asked for the 'native' CPU, autodetect here. If autodection fails, // this will set the CPU to an empty string which tells the target to // pick a basic default. if (MCPU == "native") MCPU = sys::getHostCPUName(); // If user just wants to list available options, skip module loading if (!SkipModule) { M = parseIRFile(InputFilename, Err, Context); if (!M) { Err.print(argv[0], errs()); return 1; } // If we are supposed to override the target triple, do so now. if (!TargetTriple.empty()) M->setTargetTriple(Triple::normalize(TargetTriple)); TheTriple = Triple(M->getTargetTriple()); } else { TheTriple = Triple(Triple::normalize(TargetTriple)); } if (TheTriple.getTriple().empty()) TheTriple.setTriple(sys::getDefaultTargetTriple()); // Get the target specific parser. std::string Error; const Target *TheTarget = TargetRegistry::lookupTarget(MArch, TheTriple, Error); if (!TheTarget) { errs() << argv[0] << ": " << Error; return 1; } // Package up features to be passed to target/subtarget std::string FeaturesStr; if (MAttrs.size()) { SubtargetFeatures Features; for (unsigned i = 0; i != MAttrs.size(); ++i) Features.AddFeature(MAttrs[i]); FeaturesStr = Features.getString(); } CodeGenOpt::Level OLvl = CodeGenOpt::Default; switch (OptLevel) { default: errs() << argv[0] << ": invalid optimization level.\n"; return 1; case ' ': break; case '0': OLvl = CodeGenOpt::None; break; case '1': OLvl = CodeGenOpt::Less; break; case '2': OLvl = CodeGenOpt::Default; break; case '3': OLvl = CodeGenOpt::Aggressive; break; } TargetOptions Options = InitTargetOptionsFromCodeGenFlags(); Options.DisableIntegratedAS = NoIntegratedAssembler; Options.MCOptions.ShowMCEncoding = ShowMCEncoding; Options.MCOptions.MCUseDwarfDirectory = EnableDwarfDirectory; Options.MCOptions.AsmVerbose = AsmVerbose; std::unique_ptr<TargetMachine> Target( TheTarget->createTargetMachine(TheTriple.getTriple(), MCPU, FeaturesStr, Options, RelocModel, CMModel, OLvl)); assert(Target && "Could not allocate target machine!"); // If we don't have a module then just exit now. We do this down // here since the CPU/Feature help is underneath the target machine // creation. if (SkipModule) return 0; assert(M && "Should have exited if we didn't have a module!"); if (GenerateSoftFloatCalls) FloatABIForCalls = FloatABI::Soft; // Figure out where we are going to send the output. std::unique_ptr<tool_output_file> Out = GetOutputStream(TheTarget->getName(), TheTriple.getOS(), argv[0]); if (!Out) return 1; // Build up all of the passes that we want to do to the module. PassManager PM; // Add an appropriate TargetLibraryInfo pass for the module's triple. TargetLibraryInfo *TLI = new TargetLibraryInfo(TheTriple); if (DisableSimplifyLibCalls) TLI->disableAllFunctions(); PM.add(TLI); // Add the target data from the target machine, if it exists, or the module. if (const DataLayout *DL = Target->getSubtargetImpl()->getDataLayout()) M->setDataLayout(DL); PM.add(new DataLayoutPass()); if (RelaxAll.getNumOccurrences() > 0 && FileType != TargetMachine::CGFT_ObjectFile) errs() << argv[0] << ": warning: ignoring -mc-relax-all because filetype != obj"; { formatted_raw_ostream FOS(Out->os()); AnalysisID StartAfterID = nullptr; AnalysisID StopAfterID = nullptr; const PassRegistry *PR = PassRegistry::getPassRegistry(); if (!StartAfter.empty()) { const PassInfo *PI = PR->getPassInfo(StartAfter); if (!PI) { errs() << argv[0] << ": start-after pass is not registered.\n"; return 1; } StartAfterID = PI->getTypeInfo(); } if (!StopAfter.empty()) { const PassInfo *PI = PR->getPassInfo(StopAfter); if (!PI) { errs() << argv[0] << ": stop-after pass is not registered.\n"; return 1; } StopAfterID = PI->getTypeInfo(); } // Ask the target to add backend passes as necessary. if (Target->addPassesToEmitFile(PM, FOS, FileType, NoVerify, StartAfterID, StopAfterID)) { errs() << argv[0] << ": target does not support generation of this" << " file type!\n"; return 1; } // Before executing passes, print the final values of the LLVM options. cl::PrintOptionValues(); PM.run(*M); } // Declare success. Out->keep(); return 0; }
static int compileInternal(const char *input, int optimize, int optsize, const char *argv0, raw_fd_ostream *fd, CompilerInstance &Clang) { std::string ErrMsg; LLVMContext &Context = getGlobalContext(); std::auto_ptr<Module> M; MemoryBuffer *Buffer = MemoryBuffer::getFileOrSTDIN(input, &ErrMsg); if (!Buffer) { errs() << "Could not open temp input file '" << input << "'\n"; return 2; } M.reset(ParseBitcodeFile(Buffer, Context, &ErrMsg)); delete Buffer; if (M.get() == 0) { errs() << "Cannot parse temp input file '" << input << "'" << ErrMsg << "\n"; return 2; } // FIXME: Remove TargetData! //XXX M->setTargetTriple(""); //XXX M->setDataLayout(""); // TODO: let clang handle these PassManager Passes; FunctionPassManager *FPasses = NULL; if (optimize) { FPasses = new FunctionPassManager(M.get()); // FPasses->add(new TargetData(M.get()));//XXX createStandardFunctionPasses(FPasses, optimize); } // Passes.add(new TargetData(M.get()));//XXX unsigned threshold = optsize ? 75 : optimize > 2 ? 275 : 225; createStandardModulePasses(&Passes, optimize, optsize, true, optimize > 1 && !optsize, false, false, optimize > 1 ? createFunctionInliningPass(threshold) : createAlwaysInlinerPass()); if (optimize) { FPasses->doInitialization(); for (Module::iterator I = M.get()->begin(), E = M.get()->end(); I != E; ++I) FPasses->run(*I); Passes.add(createVerifierPass()); Passes.run(*M.get()); } std::string Err2; //TODO: directly construct our target const Target *TheTarget = TargetRegistry::lookupTarget("clambc-generic-generic", Err2); if (TheTarget == 0) { errs() << argv0 << ": error auto-selecting target for module '" << Err2 << "'. Please use the -march option to explicitly " << "pick a target.\n"; return 1; } std::auto_ptr<TargetMachine> Target(TheTarget->createTargetMachine("clambc-generic-generic", "")); //TODO: send it to the -o specified on cmdline // Figure out where we are going to send the output... formatted_raw_ostream *Out2 = new formatted_raw_ostream(*fd, formatted_raw_ostream::DELETE_STREAM); if (Out2 == 0) return 2; CodeGenOpt::Level OLvl = CodeGenOpt::Default; switch (optimize) { case 0: OLvl = CodeGenOpt::None; break; case 3: OLvl = CodeGenOpt::Aggressive; break; default: break; } PassManager PM; PM.add(new TargetData(M.get()));//XXX if (Target->addPassesToEmitWholeFile(PM, *Out2, TargetMachine::CGFT_AssemblyFile, OLvl)) { errs() << argv0<< ": target does not support generation of this" << " file type!\n"; if (Out2 != &fouts()) delete Out2; // And the Out file is empty and useless, so remove it now. // sys::Path(OutputFilename).eraseFromDisk(); return 2; } PM.run(*M.get()); delete Out2; return 0; }
void* MCJITHelper::dynamicInlinerForOpenOSR(Function* F1, Instruction* OSRSrc, void* extra, void* profDataAddr) { DynamicInlinerInfo* inlineInfo = (DynamicInlinerInfo*) extra; MCJITHelper* TheHelper = inlineInfo->TheHelper; bool verbose = TheHelper->verbose; assert(OSRSrc->getParent()->getParent() == F1 && "MCJIT messed up the objects"); if (verbose) { std::cerr << "Value for F1 is " << F1 << std::endl; std::cerr << "Value for OSRSrc is " << OSRSrc << std::endl; std::cerr << "Value for extra is " << extra << std::endl; std::cerr << "Value for profDataAddr is " << profDataAddr << std::endl; } std::pair<Function*, StateMap*> identityPair = StateMap::generateIdentityMapping(F1); Function* F2 = identityPair.first; StateMap* M = identityPair.second; Value* valToInlineInF2 = M->getCorrespondingOneToOneValue(inlineInfo->valToInline); Instruction* OSRSrcInF2 = cast<Instruction>(M->getCorrespondingOneToOneValue(OSRSrc)); assert (OSRSrcInF2 != nullptr && "TODO cannot find corresponding OSRSrc in temporary F2"); if (OSRLibrary::removeOSRPoint(*OSRSrcInF2) && verbose) { std::cerr << "OSR point removed after cloning F1" << std::endl; } Instruction* LPad = M->getLandingPad(OSRSrc); StateMap* M_F2toOSRContFun; LivenessAnalysis LA(F1); std::vector<Value*>* valuesToPass = OSRLibrary::getLiveValsVecAtInstr(OSRSrc, LA); std::string OSRDestFunName = (F2->getName().str()).append("OSRCont"); Function* OSRContFun = OSRLibrary::genContinuationFunc(TheHelper->Context, *F1, *F2, *OSRSrc, *LPad, *valuesToPass, *M, &OSRDestFunName, verbose, &M_F2toOSRContFun); Value* valToInline = M_F2toOSRContFun->getCorrespondingOneToOneValue(valToInlineInF2); assert (valToInline != nullptr && "broken state map for continuation function"); delete valuesToPass; delete F2; delete M; delete M_F2toOSRContFun; // create a module for generated code std::string modForJITName = "OpenOSRDynInline"; modForJITName.append(OSRDestFunName); std::unique_ptr<Module> modForJIT = llvm::make_unique<Module>(modForJITName, TheHelper->Context); Module* modForJIT_ptr = modForJIT.get(); // determine which function is called uint64_t calledFun = (uint64_t)profDataAddr; std::cerr << "Address of invoked function: " << calledFun << std::endl; Function* funToInline = nullptr; for (AddrSymPair &pair: TheHelper->CompiledFunAddrTable) { if (pair.first == calledFun) { std::string &FunName = pair.second; funToInline = TheHelper->getFunction(FunName); break; } } Function* myFunToInline = nullptr; if (funToInline == nullptr) { std::cerr << "Sorry, I could not determine which function was called!" << std::endl; } else { std::cerr << "Function being inlined: " << funToInline->getName().str() << std::endl; ValueToValueMapTy VMap; myFunToInline = CloneFunction(funToInline, VMap, false, nullptr); myFunToInline->addFnAttr(Attribute::AlwaysInline); myFunToInline->setLinkage(Function::LinkageTypes::PrivateLinkage); modForJIT_ptr->getFunctionList().push_back(myFunToInline); OSRLibrary::fixUsesOfFunctionsAndGlobals(funToInline, myFunToInline); for (Value::use_iterator UI = valToInline->use_begin(), UE = valToInline->use_end(); UI != UE; ) { Use &U = *(UI++); if (CallInst* CI = dyn_cast<CallInst>(U.getUser())) { if (CI->getParent()->getParent() != OSRContFun) continue; if (verbose) { raw_os_ostream errStream(std::cerr); std::cerr << "Updating instruction "; CI->print(errStream); std::cerr << std::endl; } U.set(myFunToInline); } } } modForJIT_ptr->getFunctionList().push_back(OSRContFun); verifyFunction(*OSRContFun, &outs()); // remove dead code & inline when possible FunctionPassManager FPM(modForJIT_ptr); FPM.add(createCFGSimplificationPass()); FPM.doInitialization(); FPM.run(*OSRContFun); if (funToInline != nullptr) { PassManager PM; PM.add(llvm::createAlwaysInlinerPass()); PM.run(*modForJIT_ptr); } // compile code TheHelper->addModule(std::move(modForJIT)); return (void*)TheHelper->JIT->getFunctionAddress(OSRDestFunName); }
// TODO: factor this into a C++ core function, and a thin OCaml C wrapper CAMLprim value compile_module_to_string(LLVMModuleRef modref) { #ifndef __arm__ Module &mod = *llvm::unwrap(modref); LLVMContext &ctx = mod.getContext(); // TODO: streamline this - don't initialize anything but PTX LLVMInitializeNVPTXTargetInfo(); LLVMInitializeNVPTXTarget(); LLVMInitializeNVPTXTargetMC(); LLVMInitializeNVPTXAsmPrinter(); // DISABLED - hooked in here to force PrintBeforeAll option - seems to be the only way? /*char* argv[] = { "llc", "-print-before-all" };*/ /*int argc = sizeof(argv)/sizeof(char*);*/ /*cl::ParseCommandLineOptions(argc, argv, "Halide PTX internal compiler\n");*/ // Set up TargetTriple mod.setTargetTriple(Triple::normalize("nvptx64--")); Triple TheTriple(mod.getTargetTriple()); // Allocate target machine const std::string MArch = "nvptx64"; const std::string MCPU = "sm_20"; const Target* TheTarget = 0; std::string errStr; TheTarget = TargetRegistry::lookupTarget(TheTriple.getTriple(), errStr); assert(TheTarget); TargetOptions Options; Options.LessPreciseFPMADOption = true; Options.PrintMachineCode = false; Options.NoFramePointerElim = false; Options.NoFramePointerElimNonLeaf = false; //Options.NoExcessFPPrecision = false; Options.AllowFPOpFusion = FPOpFusion::Fast; Options.UnsafeFPMath = true; Options.NoInfsFPMath = false; Options.NoNaNsFPMath = false; Options.HonorSignDependentRoundingFPMathOption = false; Options.UseSoftFloat = false; /* if (FloatABIForCalls != FloatABI::Default) */ /* Options.FloatABIType = FloatABIForCalls; */ Options.NoZerosInBSS = false; Options.JITExceptionHandling = false; Options.JITEmitDebugInfo = false; Options.JITEmitDebugInfoToDisk = false; Options.GuaranteedTailCallOpt = false; Options.StackAlignmentOverride = 0; Options.RealignStack = true; // Options.DisableJumpTables = false; Options.TrapFuncName = ""; Options.EnableSegmentedStacks = false; CodeGenOpt::Level OLvl = CodeGenOpt::Default; const std::string FeaturesStr = ""; std::auto_ptr<TargetMachine> target(TheTarget->createTargetMachine(TheTriple.getTriple(), MCPU, FeaturesStr, Options, llvm::Reloc::Default, llvm::CodeModel::Default, OLvl)); assert(target.get() && "Could not allocate target machine!"); TargetMachine &Target = *target.get(); // Set up passes PassManager PM; // Add the target data from the target machine PM.add(new TargetData(*Target.getTargetData())); // Inlining functions is essential to PTX PM.add(createAlwaysInlinerPass()); // Override default to generate verbose assembly. Target.setAsmVerbosityDefault(true); // Output string stream std::string outstr; raw_string_ostream outs(outstr); formatted_raw_ostream ostream(outs); // Ask the target to add backend passes as necessary. bool fail = Target.addPassesToEmitFile(PM, ostream, TargetMachine::CGFT_AssemblyFile, true); assert(!fail); PM.run(mod); ostream.flush(); std::string& out = outs.str(); return copy_string(out.c_str()); #else return caml_copy_string("NOT IMPLEMENTED ON ARM: compile_module_to_string"); #endif //disable on ARM }
// main - Entry point for the sc compiler. // int main(int argc, char **argv) { cl::ParseCommandLineOptions(argc, argv, " llvm system compiler\n"); sys::PrintStackTraceOnErrorSignal(); // Load the module to be compiled... std::auto_ptr<Module> M; std::string ErrorMessage; if (MemoryBuffer *Buffer = MemoryBuffer::getFileOrSTDIN(InputFilename, &ErrorMessage)) { M.reset(ParseBitcodeFile(Buffer, getGlobalContext(), &ErrorMessage)); delete Buffer; } if (M.get() == 0) { std::cerr << argv[0] << ": bytecode didn't read correctly.\n"; return 1; } // Build up all of the passes that we want to do to the module... PassManager Passes; Passes.add(new TargetData(M.get())); // Currently deactiviated Passes.add(new TypeChecks()); if(EnableTypeSafetyOpts) Passes.add(new TypeChecksOpt()); // Verify the final result Passes.add(createVerifierPass()); // Figure out where we are going to send the output... raw_fd_ostream *Out = 0; std::string error; if (OutputFilename != "") { if (OutputFilename != "-") { // Specified an output filename? if (!Force && std::ifstream(OutputFilename.c_str())) { // If force is not specified, make sure not to overwrite a file! std::cerr << argv[0] << ": error opening '" << OutputFilename << "': file exists!\n" << "Use -f command line argument to force output\n"; return 1; } Out = new raw_fd_ostream (OutputFilename.c_str(), error); // Make sure that the Out file gets unlinked from the disk if we get a // SIGINT sys::RemoveFileOnSignal(sys::Path(OutputFilename)); } else { Out = new raw_stdout_ostream(); } } else { if (InputFilename == "-") { OutputFilename = "-"; Out = new raw_stdout_ostream(); } else { OutputFilename = GetFileNameRoot(InputFilename); OutputFilename += ".abc.bc"; } if (!Force && std::ifstream(OutputFilename.c_str())) { // If force is not specified, make sure not to overwrite a file! std::cerr << argv[0] << ": error opening '" << OutputFilename << "': file exists!\n" << "Use -f command line argument to force output\n"; return 1; } Out = new raw_fd_ostream(OutputFilename.c_str(), error); if (error.length()) { std::cerr << argv[0] << ": error opening " << OutputFilename << "!\n"; delete Out; return 1; } // Make sure that the Out file gets unlinked from the disk if we get a // SIGINT sys::RemoveFileOnSignal(sys::Path(OutputFilename)); } // Add the writing of the output file to the list of passes Passes.add (createBitcodeWriterPass(*Out)); // Run our queue of passes all at once now, efficiently. Passes.run(*M.get()); // Delete the ostream delete Out; return 0; }
int main(int argc, char* argv[]) { if(argc < 2) { cerr << "Usage: " << argv[0] << " bf_file" << endl; return -1; } ifstream sourceFile(argv[1]); string line, source; while(getline(sourceFile, line)) source += line; // Setup a module and engine for JIT-ing std::string error; InitializeNativeTarget(); Module* module = new Module("bfcode", getGlobalContext()); InitializeNativeTarget(); LLVMLinkInJIT(); ExecutionEngine *engine = EngineBuilder(module) .setErrorStr(&error) .setOptLevel(CodeGenOpt::Aggressive) .create(); if(!engine) { cout << "No engine created: " << error << endl; return -1; } module->setDataLayout(engine->getTargetData()->getStringRepresentation()); // Compile the BF to IR cout << "Parsing… " << flush; Function* func = makeFunc(module, source.c_str()); cout << "done" << endl; { ofstream dst("out.ll"); raw_os_ostream rawdst(dst); rawdst << *module; } // Run optimization passes cout << "Optimizing… " << flush; PassManagerBuilder PMBuilder; FunctionPassManager pm(module); PMBuilder.populateFunctionPassManager(pm); pm.add(new TargetData(*(engine->getTargetData()))); pm.add(createVerifierPass()); // Eliminate simple loops such as [>>++<<-] pm.add(createInstructionCombiningPass()); // Cleanup for scalarrepl. pm.add(createLICMPass()); // Hoist loop invariants pm.add(createPromoteMemoryToRegisterPass()); pm.add(createIndVarSimplifyPass()); // Canonicalize indvars pm.add(createLoopDeletionPass()); // Delete dead loops pm.add(createConstantPropagationPass()); // Propagate constants pm.add(new CondProp); // Propagate conditionals // Simplify code for(int repeat=0; repeat < 3; repeat++) { pm.add(createPromoteMemoryToRegisterPass()); pm.add(createGVNPass()); // Remove redundancies pm.add(createSCCPPass()); // Constant prop with SCCP pm.add(createLoopDeletionPass()); pm.add(createLoopUnrollPass()); pm.add(createCFGSimplificationPass()); // Merge & remove BBs pm.add(createInstructionCombiningPass()); pm.add(createConstantPropagationPass()); // Propagate constants pm.add(createAggressiveDCEPass()); // Delete dead instructions pm.add(createCFGSimplificationPass()); // Merge & remove BBs pm.add(createDeadStoreEliminationPass()); // Delete dead stores pm.add(createMemCpyOptPass()); // Combine multiple stores into memset's //pm.add(new PutCharAggregatePass); } pm.add(createPromoteMemoryToRegisterPass()); // Process foreach (Function& f, *module) if (!f.isDeclaration) pm.run(f); PassManager pmm; PMBuilder.populateModulePassManager(pmm); pmm.add(createConstantMergePass()); pmm.add(createGlobalOptimizerPass()); pmm.add(createGlobalDCEPass()); pmm.add(createIPConstantPropagationPass()); pmm.run(*module); foreach (Function& f, *module) if (!f.isDeclaration) pm.run(f); pmm.run(*module); cout << "done" << endl; { ofstream dst("optout.ll"); raw_os_ostream rawdst(dst); rawdst << *module; } // Compile … cout << "Compiling…" << flush; int (*bf)() = (int (*)())engine->getPointerToFunction(func); cout << " done" << endl; // … and run! return bf(); }
//===----------------------------------------------------------------------===// // main for dppgen // int main(int argc, char **argv) { sys::PrintStackTraceOnErrorSignal(); llvm::PrettyStackTraceProgram X(argc, argv); // Enable debug stream buffering. EnableDebugBuffering = true; llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. LLVMContext &Context = getGlobalContext(); PassRegistry &Registry = *PassRegistry::getPassRegistry(); initializeInstructionGraphPass(Registry); INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) INITIALIZE_PASS_DEPENDENCY(PostDominatorTree) INITIALIZE_PASS_DEPENDENCY(LoopInfo) cl::ParseCommandLineOptions(argc, argv, "llvm .bc -> .cpp generate processing pipeline with decoupled memory access\n"); SMDiagnostic Err; // Load the input module... errs()<<"before parsing\n"; std::unique_ptr<Module> M = parseIRFile(InputFilename, Err, Context); errs()<<"after parsing\n"; //M.reset(ParseIRFile(InputFilename, Err, Context)); if (M.get() == 0) { Err.print(argv[0], errs()); return 1; } // Figure out what stream we are supposed to write to... std::unique_ptr<tool_output_file> Out; if (NoOutput) { if (!OutputFilename.empty()) errs() << "WARNING: The -o (output filename) option is ignored when\n" "the --disable-output option is used.\n"; } else { // Default to standard output. if (OutputFilename.empty()) OutputFilename = "-"; std::error_code EC; Out.reset(new tool_output_file(OutputFilename, EC, sys::fs::F_None)); if (EC) { errs() << EC.message() << '\n'; return 1; } } // a separate stream std::unique_ptr<tool_output_file> fdesOut; std::unique_ptr<tool_output_file> OutC; // do the samething for FIFO description if (NoOutput) { if (!OutputFIFOFilename.empty()) errs() << "WARNING: The -fdes (fifo des filename) option is ignored when\n" "the --disable-output option is used.\n"; if(!OutputCFileName.empty()) errs() << "WARNING: The -ocfile (synthesiziable c filename) option is ignored when\n" "the --disable-output option is used.\n"; } else { // Default to standard output. if (OutputFIFOFilename.empty()) OutputFIFOFilename = "-"; std::error_code EC; fdesOut.reset(new tool_output_file(OutputFIFOFilename, EC, sys::fs::F_None)); if (EC) { errs() << EC.message() << '\n'; return 1; } if(!OutputCFileName.empty()) { std::error_code EC_c; OutC.reset(new tool_output_file(OutputCFileName, EC_c, sys::fs::F_None)); if (EC_c) { errs() << EC_c.message() << '\n'; return 1; } } } PassManager Passes; // we will need two passes // the first pass is to generate multiple function from a single function // the second pass is to generate the synthesizable C version for each generated function Passes.add(llvm::createDecoupleInsSccPass(!NoControlFlowDup)); Passes.add(llvm::createDecoupleMemAccessPass(Burst)); Passes.add(createPrintModulePass(Out->os())); if(!OutputCFileName.empty()) { errs()<<"added cprint pass\n"; Passes.add(llvm::createGenSynthCPass(OutC->os(),GenerateCPUMode)); } //PartitionGen* pg = new PartitionGen(Out->os(),fdesOut->os(),NoControlFlowDup,GenerateCPUMode); //Passes.add(pg ); // Create a new optimization pass for each one specified on the command line /*for (unsigned i = 0; i < PassList.size(); ++i) { // Check to see if -std-compile-opts was specified before this option. If // so, handle it. const PassInfo *PassInf = PassList[i]; Pass *P = 0; if (PassInf->getNormalCtor()) P = PassInf->getNormalCtor()(); else errs() << argv[0] << ": cannot create pass: "******"\n"; if (P) { PassKind Kind = P->getPassKind(); addPass(Passes, P); } }*/ // Before executing passes, print the final values of the LLVM options. cl::PrintOptionValues(); // Now that we have all of the passes ready, run them. Passes.run(*M.get()); // Declare success. if (!NoOutput ) { Out->keep(); if (!OutputFIFOFilename.empty()) fdesOut->keep(); if(!OutputCFileName.empty()) OutC->keep(); } return 0; }
////////////////////////////////////////////////////////////////////////////////////////// // This function runs optimization passes based on command line arguments. // Returns true if any optimization passes were invoked. bool ldc_optimize_module(llvm::Module* m) { // Create a PassManager to hold and optimize the collection of // per-module passes we are about to build. PassManager mpm; // Add an appropriate TargetLibraryInfo pass for the module's triple. TargetLibraryInfo *tli = new TargetLibraryInfo(Triple(m->getTargetTriple())); // The -disable-simplify-libcalls flag actually disables all builtin optzns. if (disableSimplifyLibCalls) tli->disableAllFunctions(); mpm.add(tli); // Add an appropriate TargetData instance for this module. #if LDC_LLVM_VER >= 302 mpm.add(new DataLayout(m)); #else mpm.add(new TargetData(m)); #endif // Also set up a manager for the per-function passes. FunctionPassManager fpm(m); #if LDC_LLVM_VER >= 302 fpm.add(new DataLayout(m)); #else fpm.add(new TargetData(m)); #endif // If the -strip-debug command line option was specified, add it before // anything else. if (stripDebug) mpm.add(createStripSymbolsPass(true)); bool defaultsAdded = false; // Create a new optimization pass for each one specified on the command line for (unsigned i = 0; i < passList.size(); ++i) { if (optimizeLevel && optimizeLevel.getPosition() < passList.getPosition(i)) { addOptimizationPasses(mpm, fpm, optLevel(), sizeLevel()); defaultsAdded = true; } const PassInfo *passInf = passList[i]; Pass *pass = 0; if (passInf->getNormalCtor()) pass = passInf->getNormalCtor()(); else { const char* arg = passInf->getPassArgument(); // may return null if (arg) error("Can't create pass '-%s' (%s)", arg, pass->getPassName()); else error("Can't create pass (%s)", pass->getPassName()); llvm_unreachable("pass creation failed"); } if (pass) { addPass(mpm, pass); } } // Add the default passes for the specified optimization level. if (!defaultsAdded) addOptimizationPasses(mpm, fpm, optLevel(), sizeLevel()); // Run per-function passes. fpm.doInitialization(); for (llvm::Module::iterator F = m->begin(), E = m->end(); F != E; ++F) fpm.run(*F); fpm.doFinalization(); // Run per-module passes. mpm.run(*m); // Verify the resulting module. verifyModule(m); // Report that we run some passes. return true; }
int main(int argc, char **argv) { // Print a stack trace if we signal out. sys::PrintStackTraceOnErrorSignal(); PrettyStackTraceProgram X(argc, argv); LLVMContext &Context = getGlobalContext(); llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. cl::ParseCommandLineOptions(argc, argv, "llvm extractor\n"); // Use lazy loading, since we only care about selected global values. SMDiagnostic Err; std::unique_ptr<Module> M = getLazyIRFileModule(InputFilename, Err, Context); if (!M.get()) { Err.print(argv[0], errs()); return 1; } // Use SetVector to avoid duplicates. SetVector<GlobalValue *> GVs; // Figure out which aliases we should extract. for (size_t i = 0, e = ExtractAliases.size(); i != e; ++i) { GlobalAlias *GA = M->getNamedAlias(ExtractAliases[i]); if (!GA) { errs() << argv[0] << ": program doesn't contain alias named '" << ExtractAliases[i] << "'!\n"; return 1; } GVs.insert(GA); } // Extract aliases via regular expression matching. for (size_t i = 0, e = ExtractRegExpAliases.size(); i != e; ++i) { std::string Error; Regex RegEx(ExtractRegExpAliases[i]); if (!RegEx.isValid(Error)) { errs() << argv[0] << ": '" << ExtractRegExpAliases[i] << "' " "invalid regex: " << Error; } bool match = false; for (Module::alias_iterator GA = M->alias_begin(), E = M->alias_end(); GA != E; GA++) { if (RegEx.match(GA->getName())) { GVs.insert(&*GA); match = true; } } if (!match) { errs() << argv[0] << ": program doesn't contain global named '" << ExtractRegExpAliases[i] << "'!\n"; return 1; } } // Figure out which globals we should extract. for (size_t i = 0, e = ExtractGlobals.size(); i != e; ++i) { GlobalValue *GV = M->getNamedGlobal(ExtractGlobals[i]); if (!GV) { errs() << argv[0] << ": program doesn't contain global named '" << ExtractGlobals[i] << "'!\n"; return 1; } GVs.insert(GV); } // Extract globals via regular expression matching. for (size_t i = 0, e = ExtractRegExpGlobals.size(); i != e; ++i) { std::string Error; Regex RegEx(ExtractRegExpGlobals[i]); if (!RegEx.isValid(Error)) { errs() << argv[0] << ": '" << ExtractRegExpGlobals[i] << "' " "invalid regex: " << Error; } bool match = false; for (auto &GV : M->globals()) { if (RegEx.match(GV.getName())) { GVs.insert(&GV); match = true; } } if (!match) { errs() << argv[0] << ": program doesn't contain global named '" << ExtractRegExpGlobals[i] << "'!\n"; return 1; } } // Figure out which functions we should extract. for (size_t i = 0, e = ExtractFuncs.size(); i != e; ++i) { GlobalValue *GV = M->getFunction(ExtractFuncs[i]); if (!GV) { errs() << argv[0] << ": program doesn't contain function named '" << ExtractFuncs[i] << "'!\n"; return 1; } GVs.insert(GV); } // Extract functions via regular expression matching. for (size_t i = 0, e = ExtractRegExpFuncs.size(); i != e; ++i) { std::string Error; StringRef RegExStr = ExtractRegExpFuncs[i]; Regex RegEx(RegExStr); if (!RegEx.isValid(Error)) { errs() << argv[0] << ": '" << ExtractRegExpFuncs[i] << "' " "invalid regex: " << Error; } bool match = false; for (Module::iterator F = M->begin(), E = M->end(); F != E; F++) { if (RegEx.match(F->getName())) { GVs.insert(&*F); match = true; } } if (!match) { errs() << argv[0] << ": program doesn't contain global named '" << ExtractRegExpFuncs[i] << "'!\n"; return 1; } } // Materialize requisite global values. if (!DeleteFn) for (size_t i = 0, e = GVs.size(); i != e; ++i) { GlobalValue *GV = GVs[i]; if (GV->isMaterializable()) { std::string ErrInfo; if (GV->Materialize(&ErrInfo)) { errs() << argv[0] << ": error reading input: " << ErrInfo << "\n"; return 1; } } } else { // Deleting. Materialize every GV that's *not* in GVs. SmallPtrSet<GlobalValue *, 8> GVSet(GVs.begin(), GVs.end()); for (auto &G : M->globals()) { if (!GVSet.count(&G) && G.isMaterializable()) { std::string ErrInfo; if (G.Materialize(&ErrInfo)) { errs() << argv[0] << ": error reading input: " << ErrInfo << "\n"; return 1; } } } for (auto &F : *M) { if (!GVSet.count(&F) && F.isMaterializable()) { std::string ErrInfo; if (F.Materialize(&ErrInfo)) { errs() << argv[0] << ": error reading input: " << ErrInfo << "\n"; return 1; } } } } // In addition to deleting all other functions, we also want to spiff it // up a little bit. Do this now. PassManager Passes; Passes.add(new DataLayoutPass(M.get())); // Use correct DataLayout std::vector<GlobalValue*> Gvs(GVs.begin(), GVs.end()); Passes.add(createGVExtractionPass(Gvs, DeleteFn)); if (!DeleteFn) Passes.add(createGlobalDCEPass()); // Delete unreachable globals Passes.add(createStripDeadDebugInfoPass()); // Remove dead debug info Passes.add(createStripDeadPrototypesPass()); // Remove dead func decls std::error_code EC; tool_output_file Out(OutputFilename, EC, sys::fs::F_None); if (EC) { errs() << EC.message() << '\n'; return 1; } if (OutputAssembly) Passes.add(createPrintModulePass(Out.os())); else if (Force || !CheckBitcodeOutputToConsole(Out.os(), true)) Passes.add(createBitcodeWriterPass(Out.os())); Passes.run(*M.get()); // Declare success. Out.keep(); return 0; }
void LTOCodeGenerator::applyScopeRestrictions() { if (ScopeRestrictionsDone || !shouldInternalize()) return; Module *mergedModule = Linker.getModule(); // Start off with a verification pass. PassManager passes; passes.add(createVerifierPass()); // mark which symbols can not be internalized Mangler Mangler(TargetMach->getDataLayout()); std::vector<const char*> MustPreserveList; SmallPtrSet<GlobalValue*, 8> AsmUsed; std::vector<StringRef> Libcalls; TargetLibraryInfo TLI(Triple(TargetMach->getTargetTriple())); accumulateAndSortLibcalls(Libcalls, TLI, TargetMach->getTargetLowering()); for (Module::iterator f = mergedModule->begin(), e = mergedModule->end(); f != e; ++f) applyRestriction(*f, Libcalls, MustPreserveList, AsmUsed, Mangler); for (Module::global_iterator v = mergedModule->global_begin(), e = mergedModule->global_end(); v != e; ++v) applyRestriction(*v, Libcalls, MustPreserveList, AsmUsed, Mangler); for (Module::alias_iterator a = mergedModule->alias_begin(), e = mergedModule->alias_end(); a != e; ++a) applyRestriction(*a, Libcalls, MustPreserveList, AsmUsed, Mangler); GlobalVariable *LLVMCompilerUsed = mergedModule->getGlobalVariable("llvm.compiler.used"); findUsedValues(LLVMCompilerUsed, AsmUsed); if (LLVMCompilerUsed) LLVMCompilerUsed->eraseFromParent(); if (!AsmUsed.empty()) { llvm::Type *i8PTy = llvm::Type::getInt8PtrTy(Context); std::vector<Constant*> asmUsed2; for (SmallPtrSet<GlobalValue*, 16>::const_iterator i = AsmUsed.begin(), e = AsmUsed.end(); i !=e; ++i) { GlobalValue *GV = *i; Constant *c = ConstantExpr::getBitCast(GV, i8PTy); asmUsed2.push_back(c); } llvm::ArrayType *ATy = llvm::ArrayType::get(i8PTy, asmUsed2.size()); LLVMCompilerUsed = new llvm::GlobalVariable(*mergedModule, ATy, false, llvm::GlobalValue::AppendingLinkage, llvm::ConstantArray::get(ATy, asmUsed2), "llvm.compiler.used"); LLVMCompilerUsed->setSection("llvm.metadata"); } passes.add( createInternalizePass(MustPreserveList, shouldOnlyInternalizeHidden())); // apply scope restrictions passes.run(*mergedModule); ScopeRestrictionsDone = true; }
////////////////////////////////////////////////////////////////////////////////////////// // This function runs optimization passes based on command line arguments. // Returns true if any optimization passes were invoked. bool ldc_optimize_module(llvm::Module *M) { // Create a PassManager to hold and optimize the collection of // per-module passes we are about to build. #if LDC_LLVM_VER >= 307 legacy:: #endif PassManager mpm; #if LDC_LLVM_VER >= 307 // Add an appropriate TargetLibraryInfo pass for the module's triple. TargetLibraryInfoImpl *tlii = new TargetLibraryInfoImpl(Triple(M->getTargetTriple())); // The -disable-simplify-libcalls flag actually disables all builtin optzns. if (disableSimplifyLibCalls) tlii->disableAllFunctions(); mpm.add(new TargetLibraryInfoWrapperPass(*tlii)); #else // Add an appropriate TargetLibraryInfo pass for the module's triple. TargetLibraryInfo *tli = new TargetLibraryInfo(Triple(M->getTargetTriple())); // The -disable-simplify-libcalls flag actually disables all builtin optzns. if (disableSimplifyLibCalls) tli->disableAllFunctions(); mpm.add(tli); #endif // Add an appropriate DataLayout instance for this module. #if LDC_LLVM_VER >= 307 // The DataLayout is already set at the module (in module.cpp, // method Module::genLLVMModule()) // FIXME: Introduce new command line switch default-data-layout to // override the module data layout #elif LDC_LLVM_VER == 306 mpm.add(new DataLayoutPass()); #elif LDC_LLVM_VER == 305 const DataLayout *DL = M->getDataLayout(); assert(DL && "DataLayout not set at module"); mpm.add(new DataLayoutPass(*DL)); #elif LDC_LLVM_VER >= 302 mpm.add(new DataLayout(M)); #else mpm.add(new TargetData(M)); #endif #if LDC_LLVM_VER >= 307 // Add internal analysis passes from the target machine. mpm.add(createTargetTransformInfoWrapperPass(gTargetMachine->getTargetIRAnalysis())); #elif LDC_LLVM_VER >= 305 // Add internal analysis passes from the target machine. gTargetMachine->addAnalysisPasses(mpm); #endif // Also set up a manager for the per-function passes. #if LDC_LLVM_VER >= 307 legacy:: #endif FunctionPassManager fpm(M); #if LDC_LLVM_VER >= 307 // Add internal analysis passes from the target machine. fpm.add(createTargetTransformInfoWrapperPass(gTargetMachine->getTargetIRAnalysis())); #elif LDC_LLVM_VER >= 306 fpm.add(new DataLayoutPass()); gTargetMachine->addAnalysisPasses(fpm); #elif LDC_LLVM_VER == 305 fpm.add(new DataLayoutPass(M)); gTargetMachine->addAnalysisPasses(fpm); #elif LDC_LLVM_VER >= 302 fpm.add(new DataLayout(M)); #else fpm.add(new TargetData(M)); #endif // If the -strip-debug command line option was specified, add it before // anything else. if (stripDebug) mpm.add(createStripSymbolsPass(true)); bool defaultsAdded = false; // Create a new optimization pass for each one specified on the command line for (unsigned i = 0; i < passList.size(); ++i) { if (optimizeLevel && optimizeLevel.getPosition() < passList.getPosition(i)) { addOptimizationPasses(mpm, fpm, optLevel(), sizeLevel()); defaultsAdded = true; } const PassInfo *passInf = passList[i]; Pass *pass = 0; if (passInf->getNormalCtor()) pass = passInf->getNormalCtor()(); else { const char* arg = passInf->getPassArgument(); // may return null if (arg) error(Loc(), "Can't create pass '-%s' (%s)", arg, pass->getPassName()); else error(Loc(), "Can't create pass (%s)", pass->getPassName()); llvm_unreachable("pass creation failed"); } if (pass) { addPass(mpm, pass); } } // Add the default passes for the specified optimization level. if (!defaultsAdded) addOptimizationPasses(mpm, fpm, optLevel(), sizeLevel()); // Run per-function passes. fpm.doInitialization(); for (llvm::Module::iterator F = M->begin(), E = M->end(); F != E; ++F) fpm.run(*F); fpm.doFinalization(); // Run per-module passes. mpm.run(*M); // Verify the resulting module. verifyModule(M); // Report that we run some passes. return true; }
//===----------------------------------------------------------------------===// // main for dppgen // int main(int argc, char **argv) { sys::PrintStackTraceOnErrorSignal(); llvm::PrettyStackTraceProgram X(argc, argv); // Enable debug stream buffering. EnableDebugBuffering = true; llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. LLVMContext &Context = getGlobalContext(); PassRegistry &Registry = *PassRegistry::getPassRegistry(); initializeInstructionGraphPass(Registry); INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) INITIALIZE_PASS_DEPENDENCY(PostDominatorTree) INITIALIZE_PASS_DEPENDENCY(LoopInfo) cl::ParseCommandLineOptions(argc, argv, "llvm .bc -> .cpp generate decoupled processing pipeline\n"); SMDiagnostic Err; // Load the input module... std::unique_ptr<Module> M = parseIRFile(InputFilename, Err, Context); //M.reset(ParseIRFile(InputFilename, Err, Context)); if (M.get() == 0) { Err.print(argv[0], errs()); return 1; } // Figure out what stream we are supposed to write to... std::unique_ptr<tool_output_file> Out; if (NoOutput) { if (!OutputFilename.empty()) errs() << "WARNING: The -o (output filename) option is ignored when\n" "the --disable-output option is used.\n"; } else { // Default to standard output. if (OutputFilename.empty()) OutputFilename = "-"; std::error_code EC; Out.reset(new tool_output_file(OutputFilename, EC, sys::fs::F_None)); if (EC) { errs() << EC.message() << '\n'; return 1; } } PassManager Passes; // we will need two passes // the first pass is to generate multiple function from a single function // the second pass is to generate the synthesizable C version for each generated function Passes.add(llvm::createGenSynthCPass(Out->os(),GenerateCPUMode)); // Before executing passes, print the final values of the LLVM options. cl::PrintOptionValues(); // Now that we have all of the passes ready, run them. Passes.run(*M.get()); // Declare success. if (!NoOutput ) { Out->keep(); } return 0; }
/// Optimize module M using various IPO passes. Use exportList to /// internalize selected symbols. Target platform is selected /// based on information available to module M. No new target /// features are selected. enum LTOStatus LTO::optimize(Module *M, std::ostream &Out, std::vector<const char *> &exportList) { // Instantiate the pass manager to organize the passes. PassManager Passes; // Collect Target info getTarget(M); if (!Target) return LTO_NO_TARGET; // If target supports exception handling then enable it now. if (Target->getTargetAsmInfo()->doesSupportExceptionHandling()) ExceptionHandling = true; // Start off with a verification pass. Passes.add(createVerifierPass()); // Add an appropriate TargetData instance for this module... Passes.add(new TargetData(*Target->getTargetData())); // Internalize symbols if export list is nonemty if (!exportList.empty()) Passes.add(createInternalizePass(exportList)); // Now that we internalized some globals, see if we can hack on them! Passes.add(createGlobalOptimizerPass()); // Linking modules together can lead to duplicated global constants, only // keep one copy of each constant... Passes.add(createConstantMergePass()); // If the -s command line option was specified, strip the symbols out of the // resulting program to make it smaller. -s is a GLD option that we are // supporting. Passes.add(createStripSymbolsPass()); // Propagate constants at call sites into the functions they call. Passes.add(createIPConstantPropagationPass()); // Remove unused arguments from functions... Passes.add(createDeadArgEliminationPass()); Passes.add(createFunctionInliningPass()); // Inline small functions Passes.add(createPruneEHPass()); // Remove dead EH info Passes.add(createGlobalDCEPass()); // Remove dead functions // If we didn't decide to inline a function, check to see if we can // transform it to pass arguments by value instead of by reference. Passes.add(createArgumentPromotionPass()); // The IPO passes may leave cruft around. Clean up after them. Passes.add(createInstructionCombiningPass()); Passes.add(createScalarReplAggregatesPass()); // Break up allocas // Run a few AA driven optimizations here and now, to cleanup the code. Passes.add(createGlobalsModRefPass()); // IP alias analysis Passes.add(createLICMPass()); // Hoist loop invariants Passes.add(createGVNPass()); // Remove common subexprs Passed.add(createMemCpyOptPass()); // Remove dead memcpy's Passes.add(createDeadStoreEliminationPass()); // Nuke dead stores // Cleanup and simplify the code after the scalar optimizations. Passes.add(createInstructionCombiningPass()); // Delete basic blocks, which optimization passes may have killed... Passes.add(createCFGSimplificationPass()); // Now that we have optimized the program, discard unreachable functions... Passes.add(createGlobalDCEPass()); // Make sure everything is still good. Passes.add(createVerifierPass()); FunctionPassManager *CodeGenPasses = new FunctionPassManager(new ExistingModuleProvider(M)); CodeGenPasses->add(new TargetData(*Target->getTargetData())); MachineCodeEmitter *MCE = 0; switch (Target->addPassesToEmitFile(*CodeGenPasses, Out, TargetMachine::AssemblyFile, true)) { default: case FileModel::Error: return LTO_WRITE_FAILURE; case FileModel::AsmFile: break; case FileModel::MachOFile: MCE = AddMachOWriter(*CodeGenPasses, Out, *Target); break; case FileModel::ElfFile: MCE = AddELFWriter(*CodeGenPasses, Out, *Target); break; } if (Target->addPassesToEmitFileFinish(*CodeGenPasses, MCE, true)) return LTO_WRITE_FAILURE; // Run our queue of passes all at once now, efficiently. Passes.run(*M); // Run the code generator, if present. CodeGenPasses->doInitialization(); for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) { if (!I->isDeclaration()) CodeGenPasses->run(*I); } CodeGenPasses->doFinalization(); return LTO_OPT_SUCCESS; }
//===----------------------------------------------------------------------===// // main for opt // int main(int argc, char **argv) { sys::PrintStackTraceOnErrorSignal(); llvm::PrettyStackTraceProgram X(argc, argv); // Enable debug stream buffering. EnableDebugBuffering = true; llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. LLVMContext &Context = getGlobalContext(); InitializeAllTargets(); InitializeAllTargetMCs(); InitializeAllAsmPrinters(); // Initialize passes PassRegistry &Registry = *PassRegistry::getPassRegistry(); initializeCore(Registry); initializeScalarOpts(Registry); initializeObjCARCOpts(Registry); initializeVectorization(Registry); initializeIPO(Registry); initializeAnalysis(Registry); initializeIPA(Registry); initializeTransformUtils(Registry); initializeInstCombine(Registry); initializeInstrumentation(Registry); initializeTarget(Registry); initializeCheerpOpts(Registry); // For codegen passes, only passes that do IR to IR transformation are // supported. initializeCodeGenPreparePass(Registry); initializeAtomicExpandPass(Registry); initializeRewriteSymbolsPass(Registry); #ifdef LINK_POLLY_INTO_TOOLS polly::initializePollyPasses(Registry); #endif cl::ParseCommandLineOptions(argc, argv, "llvm .bc -> .bc modular optimizer and analysis printer\n"); if (AnalyzeOnly && NoOutput) { errs() << argv[0] << ": analyze mode conflicts with no-output mode.\n"; return 1; } SMDiagnostic Err; // Load the input module... std::unique_ptr<Module> M = parseIRFile(InputFilename, Err, Context); if (!M) { Err.print(argv[0], errs()); return 1; } // If we are supposed to override the target triple, do so now. if (!TargetTriple.empty()) M->setTargetTriple(Triple::normalize(TargetTriple)); // Figure out what stream we are supposed to write to... std::unique_ptr<tool_output_file> Out; if (NoOutput) { if (!OutputFilename.empty()) errs() << "WARNING: The -o (output filename) option is ignored when\n" "the --disable-output option is used.\n"; } else { // Default to standard output. if (OutputFilename.empty()) OutputFilename = "-"; std::error_code EC; Out.reset(new tool_output_file(OutputFilename, EC, sys::fs::F_None)); if (EC) { errs() << EC.message() << '\n'; return 1; } } // If the output is set to be emitted to standard out, and standard out is a // console, print out a warning message and refuse to do it. We don't // impress anyone by spewing tons of binary goo to a terminal. if (!Force && !NoOutput && !AnalyzeOnly && !OutputAssembly) if (CheckBitcodeOutputToConsole(Out->os(), !Quiet)) NoOutput = true; if (PassPipeline.getNumOccurrences() > 0) { OutputKind OK = OK_NoOutput; if (!NoOutput) OK = OutputAssembly ? OK_OutputAssembly : OK_OutputBitcode; VerifierKind VK = VK_VerifyInAndOut; if (NoVerify) VK = VK_NoVerifier; else if (VerifyEach) VK = VK_VerifyEachPass; // The user has asked to use the new pass manager and provided a pipeline // string. Hand off the rest of the functionality to the new code for that // layer. return runPassPipeline(argv[0], Context, *M, Out.get(), PassPipeline, OK, VK) ? 0 : 1; } // Create a PassManager to hold and optimize the collection of passes we are // about to build. // PassManager Passes; // Add an appropriate TargetLibraryInfo pass for the module's triple. TargetLibraryInfo *TLI = new TargetLibraryInfo(Triple(M->getTargetTriple())); // The -disable-simplify-libcalls flag actually disables all builtin optzns. if (DisableSimplifyLibCalls) TLI->disableAllFunctions(); Passes.add(TLI); // Add an appropriate DataLayout instance for this module. const DataLayout *DL = M->getDataLayout(); if (!DL && !DefaultDataLayout.empty()) { M->setDataLayout(DefaultDataLayout); DL = M->getDataLayout(); } if (DL) Passes.add(new DataLayoutPass()); Triple ModuleTriple(M->getTargetTriple()); TargetMachine *Machine = nullptr; if (ModuleTriple.getArch()) Machine = GetTargetMachine(Triple(ModuleTriple)); std::unique_ptr<TargetMachine> TM(Machine); // Add internal analysis passes from the target machine. if (TM) TM->addAnalysisPasses(Passes); std::unique_ptr<FunctionPassManager> FPasses; if (OptLevelO1 || OptLevelO2 || OptLevelOs || OptLevelOz || OptLevelO3) { FPasses.reset(new FunctionPassManager(M.get())); if (DL) FPasses->add(new DataLayoutPass()); if (TM) TM->addAnalysisPasses(*FPasses); } if (PrintBreakpoints) { // Default to standard output. if (!Out) { if (OutputFilename.empty()) OutputFilename = "-"; std::error_code EC; Out = llvm::make_unique<tool_output_file>(OutputFilename, EC, sys::fs::F_None); if (EC) { errs() << EC.message() << '\n'; return 1; } } Passes.add(createBreakpointPrinter(Out->os())); NoOutput = true; } // If the -strip-debug command line option was specified, add it. if (StripDebug) addPass(Passes, createStripSymbolsPass(true)); // Create a new optimization pass for each one specified on the command line for (unsigned i = 0; i < PassList.size(); ++i) { if (StandardLinkOpts && StandardLinkOpts.getPosition() < PassList.getPosition(i)) { AddStandardLinkPasses(Passes); StandardLinkOpts = false; } if (OptLevelO1 && OptLevelO1.getPosition() < PassList.getPosition(i)) { AddOptimizationPasses(Passes, *FPasses, 1, 0); OptLevelO1 = false; } if (OptLevelO2 && OptLevelO2.getPosition() < PassList.getPosition(i)) { AddOptimizationPasses(Passes, *FPasses, 2, 0); OptLevelO2 = false; } if (OptLevelOs && OptLevelOs.getPosition() < PassList.getPosition(i)) { AddOptimizationPasses(Passes, *FPasses, 2, 1); OptLevelOs = false; } if (OptLevelOz && OptLevelOz.getPosition() < PassList.getPosition(i)) { AddOptimizationPasses(Passes, *FPasses, 2, 2); OptLevelOz = false; } if (OptLevelO3 && OptLevelO3.getPosition() < PassList.getPosition(i)) { AddOptimizationPasses(Passes, *FPasses, 3, 0); OptLevelO3 = false; } const PassInfo *PassInf = PassList[i]; Pass *P = nullptr; if (PassInf->getTargetMachineCtor()) P = PassInf->getTargetMachineCtor()(TM.get()); else if (PassInf->getNormalCtor()) P = PassInf->getNormalCtor()(); else errs() << argv[0] << ": cannot create pass: "******"\n"; if (P) { PassKind Kind = P->getPassKind(); addPass(Passes, P); if (AnalyzeOnly) { switch (Kind) { case PT_BasicBlock: Passes.add(createBasicBlockPassPrinter(PassInf, Out->os(), Quiet)); break; case PT_Region: Passes.add(createRegionPassPrinter(PassInf, Out->os(), Quiet)); break; case PT_Loop: Passes.add(createLoopPassPrinter(PassInf, Out->os(), Quiet)); break; case PT_Function: Passes.add(createFunctionPassPrinter(PassInf, Out->os(), Quiet)); break; case PT_CallGraphSCC: Passes.add(createCallGraphPassPrinter(PassInf, Out->os(), Quiet)); break; default: Passes.add(createModulePassPrinter(PassInf, Out->os(), Quiet)); break; } } } if (PrintEachXForm) Passes.add(createPrintModulePass(errs())); } if (StandardLinkOpts) { AddStandardLinkPasses(Passes); StandardLinkOpts = false; } if (OptLevelO1) AddOptimizationPasses(Passes, *FPasses, 1, 0); if (OptLevelO2) AddOptimizationPasses(Passes, *FPasses, 2, 0); if (OptLevelOs) AddOptimizationPasses(Passes, *FPasses, 2, 1); if (OptLevelOz) AddOptimizationPasses(Passes, *FPasses, 2, 2); if (OptLevelO3) AddOptimizationPasses(Passes, *FPasses, 3, 0); if (OptLevelO1 || OptLevelO2 || OptLevelOs || OptLevelOz || OptLevelO3) { FPasses->doInitialization(); for (Function &F : *M) FPasses->run(F); FPasses->doFinalization(); } // Check that the module is well formed on completion of optimization if (!NoVerify && !VerifyEach) { Passes.add(createVerifierPass()); Passes.add(createDebugInfoVerifierPass()); } // Write bitcode or assembly to the output as the last step... if (!NoOutput && !AnalyzeOnly) { if (OutputAssembly) Passes.add(createPrintModulePass(Out->os())); else Passes.add(createBitcodeWriterPass(Out->os())); } // Before executing passes, print the final values of the LLVM options. cl::PrintOptionValues(); // Now that we have all of the passes ready, run them. Passes.run(*M); // Declare success. if (!NoOutput || PrintBreakpoints) Out->keep(); return 0; }
/** * Compile an LLVM module to machine code. * * @param bytes This function allocates memory for the byte stream, it is the * caller's responsibility to free it. */ extern "C" unsigned radeon_llvm_compile(LLVMModuleRef M, unsigned char ** bytes, unsigned * byte_count, const char * gpu_family, unsigned dump) { Triple AMDGPUTriple(sys::getDefaultTargetTriple()); #ifdef EXTERNAL_LLVM /* XXX: Can we just initialize the AMDGPU target here? */ InitializeAllTargets(); InitializeAllTargetMCs(); #else LLVMInitializeAMDGPUTargetInfo(); LLVMInitializeAMDGPUTarget(); LLVMInitializeAMDGPUTargetMC(); #endif std::string err; const Target * AMDGPUTarget = TargetRegistry::lookupTarget("r600", err); if(!AMDGPUTarget) { fprintf(stderr, "Can't find target: %s\n", err.c_str()); return 1; } Triple::ArchType Arch = Triple::getArchTypeForLLVMName("r600"); if (Arch == Triple::UnknownArch) { fprintf(stderr, "Unknown Arch\n"); } AMDGPUTriple.setArch(Arch); Module * mod = unwrap(M); std::string FS; TargetOptions TO; if (dump) { mod->dump(); FS += "+DumpCode"; } std::auto_ptr<TargetMachine> tm(AMDGPUTarget->createTargetMachine( AMDGPUTriple.getTriple(), gpu_family, FS, TO, Reloc::Default, CodeModel::Default, CodeGenOpt::Default )); TargetMachine &AMDGPUTargetMachine = *tm.get(); PassManager PM; PM.add(new TargetData(*AMDGPUTargetMachine.getTargetData())); PM.add(createPromoteMemoryToRegisterPass()); AMDGPUTargetMachine.setAsmVerbosityDefault(true); std::string CodeString; raw_string_ostream oStream(CodeString); formatted_raw_ostream out(oStream); /* Optional extra paramater true / false to disable verify */ if (AMDGPUTargetMachine.addPassesToEmitFile(PM, out, TargetMachine::CGFT_AssemblyFile, true)){ fprintf(stderr, "AddingPasses failed.\n"); return 1; } PM.run(*mod); out.flush(); std::string &data = oStream.str(); *bytes = (unsigned char*)malloc(data.length() * sizeof(unsigned char)); memcpy(*bytes, data.c_str(), data.length() * sizeof(unsigned char)); *byte_count = data.length(); return 0; }
//////////////////////////////////////////////////////////////////////////////// // This function runs optimization passes based on command line arguments. // Returns true if any optimization passes were invoked. bool ldc_optimize_module(llvm::Module *M) { // Create a PassManager to hold and optimize the collection of // per-module passes we are about to build. #if LDC_LLVM_VER >= 307 legacy:: #endif PassManager mpm; #if LDC_LLVM_VER >= 307 // Add an appropriate TargetLibraryInfo pass for the module's triple. TargetLibraryInfoImpl *tlii = new TargetLibraryInfoImpl(Triple(M->getTargetTriple())); // The -disable-simplify-libcalls flag actually disables all builtin optzns. if (disableSimplifyLibCalls) tlii->disableAllFunctions(); mpm.add(new TargetLibraryInfoWrapperPass(*tlii)); #else // Add an appropriate TargetLibraryInfo pass for the module's triple. TargetLibraryInfo *tli = new TargetLibraryInfo(Triple(M->getTargetTriple())); // The -disable-simplify-libcalls flag actually disables all builtin optzns. if (disableSimplifyLibCalls) { tli->disableAllFunctions(); } mpm.add(tli); #endif // Add an appropriate DataLayout instance for this module. #if LDC_LLVM_VER >= 307 // The DataLayout is already set at the module (in module.cpp, // method Module::genLLVMModule()) // FIXME: Introduce new command line switch default-data-layout to // override the module data layout #elif LDC_LLVM_VER == 306 mpm.add(new DataLayoutPass()); #else const DataLayout *DL = M->getDataLayout(); assert(DL && "DataLayout not set at module"); mpm.add(new DataLayoutPass(*DL)); #endif #if LDC_LLVM_VER >= 307 // Add internal analysis passes from the target machine. mpm.add(createTargetTransformInfoWrapperPass( gTargetMachine->getTargetIRAnalysis())); #else // Add internal analysis passes from the target machine. gTargetMachine->addAnalysisPasses(mpm); #endif // Also set up a manager for the per-function passes. #if LDC_LLVM_VER >= 307 legacy:: #endif FunctionPassManager fpm(M); #if LDC_LLVM_VER >= 307 // Add internal analysis passes from the target machine. fpm.add(createTargetTransformInfoWrapperPass( gTargetMachine->getTargetIRAnalysis())); #elif LDC_LLVM_VER >= 306 fpm.add(new DataLayoutPass()); gTargetMachine->addAnalysisPasses(fpm); #else fpm.add(new DataLayoutPass(M)); gTargetMachine->addAnalysisPasses(fpm); #endif // If the -strip-debug command line option was specified, add it before // anything else. if (stripDebug) { mpm.add(createStripSymbolsPass(true)); } addOptimizationPasses(mpm, fpm, optLevel(), sizeLevel()); // Run per-function passes. fpm.doInitialization(); for (auto &F : *M) { fpm.run(F); } fpm.doFinalization(); // Run per-module passes. mpm.run(*M); // Verify the resulting module. verifyModule(M); // Report that we run some passes. return true; }
int main (int argc, char ** argv) { cl::ParseCommandLineOptions(argc, argv, "llvm system compiler\n"); llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. LLVMContext &Context = getGlobalContext(); OwningPtr<tool_output_file> Out; std::string ErrorInfo; Out.reset(new tool_output_file(OutputFilename.c_str(), ErrorInfo, sys::fs::F_Binary)); SMDiagnostic Err; std::auto_ptr<Module> M; M.reset(ParseIRFile(InputFilename, Err, Context)); if (M.get() == 0) { Err.print(argv[0], errs()); return 1; } if (PreOpt) { PassManager Passes; Passes.add(createVerifierPass()); Passes.add(createPromoteMemoryToRegisterPass()); Passes.add(createDeadInstEliminationPass()); Passes.run(*M.get()); } if (CSE) { #ifdef UseC LLVMCommonSubexpressionElimination(wrap(M.get())); #else LLVMCommonSubexpressionElimination_Cpp(M.get()); #endif } if (DumpSummary) { char filename[1024]; sprintf(filename,"%s.stats",OutputFilename.c_str()); #ifdef UseC Summarize(wrap(M.get()),"preGCM",filename); #else Summarize_Cpp(M.get(),"preGCM",filename); #endif } if (!NoLICM) { #ifdef UseC LoopInvariantCodeMotion_C(wrap(M.get())); #else LoopInvariantCodeMotion_Cpp(M.get()); #endif if (Twice) { #ifdef UseC LoopInvariantCodeMotion_C(wrap(M.get())); #else LoopInvariantCodeMotion_Cpp(M.get()); #endif } } if (DumpSummary) { char filename[1024]; sprintf(filename,"%s.stats",OutputFilename.c_str()); #ifdef UseC Summarize(wrap(M.get()),"postGCM",filename); #else Summarize_Cpp(M.get(),"postGCM",filename); #endif } if (PostOpt) { PassManager Passes; Passes.add(createDeadCodeEliminationPass()); Passes.add(createCFGSimplificationPass()); Passes.run(*M.get()); } WriteBitcodeToFile(M.get(),Out->os()); Out->keep(); return 0; }
/// Optimize merged modules using various IPO passes bool LTOCodeGenerator::generateObjectFile(raw_ostream &out, std::string &errMsg) { if (this->determineTarget(errMsg)) return true; Module* mergedModule = _linker.getModule(); // if options were requested, set them if (!_codegenOptions.empty()) cl::ParseCommandLineOptions(_codegenOptions.size(), const_cast<char **>(&_codegenOptions[0])); // mark which symbols can not be internalized this->applyScopeRestrictions(); // Instantiate the pass manager to organize the passes. PassManager passes; // Start off with a verification pass. passes.add(createVerifierPass()); // Add an appropriate DataLayout instance for this module... passes.add(new DataLayout(*_target->getDataLayout())); _target->addAnalysisPasses(passes); // Enabling internalize here would use its AllButMain variant. It // keeps only main if it exists and does nothing for libraries. Instead // we create the pass ourselves with the symbol list provided by the linker. if (!DisableOpt) { PassManagerBuilder().populateLTOPassManager(passes, /*Internalize=*/false, !DisableInline, DisableGVNLoadPRE); } // Make sure everything is still good. passes.add(createVerifierPass()); PassManager codeGenPasses; codeGenPasses.add(new DataLayout(*_target->getDataLayout())); _target->addAnalysisPasses(codeGenPasses); formatted_raw_ostream Out(out); // If the bitcode files contain ARC code and were compiled with optimization, // the ObjCARCContractPass must be run, so do it unconditionally here. codeGenPasses.add(createObjCARCContractPass()); if (_target->addPassesToEmitFile(codeGenPasses, Out, TargetMachine::CGFT_ObjectFile)) { errMsg = "target file type not supported"; return true; } bool UsingSAFECode = false; // Add the SAFECode optimization/finalization passes. // Note that we only run these passes (which require DSA) if we detect // that run-time checks have been added to the code. for (unsigned index = 0; index < numChecks; ++index) { if (mergedModule->getFunction(RuntimeChecks[index].name)) { UsingSAFECode = true; break; } } // Do a check for some other SAFECode run-time checks. if (mergedModule->getFunction("poolcheck_freeui") || mergedModule->getFunction("poolcheck_freeui_debug") || mergedModule->getFunction("poolcheck_free") || mergedModule->getFunction("poolcheck_free_debug")) { UsingSAFECode = true; } if (UsingSAFECode) { passes.add(new DataLayout(*_target->getDataLayout())); passes.add(createSAFECodeMSCInfoPass()); #if 0 passes.add(createExactCheckOptPass()); #endif passes.add(new DominatorTree()); passes.add(new ScalarEvolution()); passes.add(createOptimizeImpliedFastLSChecksPass()); if (mergedModule->getFunction("main")) { passes.add(new CompleteChecks()); } #ifdef HAVE_POOLALLOC LowerSafecodeIntrinsic::IntrinsicMappingEntry *MapStart, *MapEnd; MapStart = RuntimeDebug; MapEnd = &RuntimeDebug[sizeof(RuntimeDebug) / sizeof(RuntimeDebug[0])]; // Add the automatic pool allocation passes passes.add(new OptimizeSafeLoadStore()); passes.add(new PA::AllNodesHeuristic()); //passes.add(new PoolAllocate()); passes.add(new PoolAllocateSimple()); // SAFECode's debug runtime needs to replace some of the poolalloc // intrinsics; LowerSafecodeIntrinsic handles the replacement. passes.add(new LowerSafecodeIntrinsic(MapStart, MapEnd)); #endif // Run our queue of passes all at once now, efficiently. passes.run(*mergedModule); #ifdef HAVE_POOLALLOC if (const char *OutFileName = getenv("PA_BITCODE_FILE")) { // Write out the pool allocated bitcode file for debugging purposes. std::cerr << "Writing out poolalloc bitcode file to " << OutFileName; std::cerr << std::endl; std::string error; tool_output_file PAFile(OutFileName, error, raw_fd_ostream::F_Binary); if (!error.empty()) { std::cerr << "Error writing out poolalloc bitcode file: " << error; std::cerr << std::endl; } else { WriteBitcodeToFile(mergedModule, PAFile.os()); PAFile.os().close(); PAFile.keep(); } } #endif } // Run the code generator, and write assembly file codeGenPasses.run(*mergedModule); return false; // success }
int compile(list<string> args, list<string> kgen_args, string merge, list<string> merge_args, string input, string output, int arch, string host_compiler, string fileprefix) { // // The LLVM compiler to emit IR. // const char* llvm_compiler = "kernelgen-gfortran"; // // Interpret kernelgen compile options. // for (list<string>::iterator iarg = kgen_args.begin(), iearg = kgen_args.end(); iarg != iearg; iarg++) { const char* arg = (*iarg).c_str(); if (!strncmp(arg, "-Wk,--llvm-compiler=", 20)) llvm_compiler = arg + 20; } // // Generate temporary output file. // Check if output file is specified in the command line. // Replace or add output to the temporary file. // cfiledesc tmp_output = cfiledesc::mktemp(fileprefix); bool output_specified = false; for (list<string>::iterator iarg = args.begin(), iearg = args.end(); iarg != iearg; iarg++) { const char* arg = (*iarg).c_str(); if (!strcmp(arg, "-o")) { iarg++; *iarg = tmp_output.getFilename(); output_specified = true; break; } } if (!output_specified) { args.push_back("-o"); args.push_back(tmp_output.getFilename()); } // // 1) Compile source code using regular host compiler. // { if (verbose) { cout << host_compiler; for (list<string>::iterator iarg = args.begin(), iearg = args.end(); iarg != iearg; iarg++) cout << " " << *iarg; cout << endl; } int status = execute(host_compiler, args, "", NULL, NULL); if (status) return status; } // // 2) Emit LLVM IR. // string out = ""; { list<string> emit_ir_args; for (list<string>::iterator iarg = args.begin(), iearg = args.end(); iarg != iearg; iarg++) { const char* arg = (*iarg).c_str(); if (!strcmp(arg, "-c") || !strcmp(arg, "-o")) { iarg++; continue; } if (!strcmp(arg, "-g")) { continue; } emit_ir_args.push_back(*iarg); } emit_ir_args.push_back("-fplugin=/opt/kernelgen/lib/dragonegg.so"); emit_ir_args.push_back("-fplugin-arg-dragonegg-emit-ir"); emit_ir_args.push_back("-S"); emit_ir_args.push_back(input); emit_ir_args.push_back("-o"); emit_ir_args.push_back("-"); if (verbose) { cout << llvm_compiler; for (list<string>::iterator iarg = emit_ir_args.begin(), iearg = emit_ir_args.end(); iarg != iearg; iarg++) cout << " " << *iarg; cout << endl; } int status = execute(llvm_compiler, emit_ir_args, "", &out, NULL); if (status) return status; } // // 3) Record existing module functions. // LLVMContext &context = getGlobalContext(); SMDiagnostic diag; MemoryBuffer* buffer1 = MemoryBuffer::getMemBuffer(out); auto_ptr<Module> m1; m1.reset(ParseIR(buffer1, diag, context)); //m1.get()->dump(); // // 4) Inline calls and extract loops into new functions. // MemoryBuffer* buffer2 = MemoryBuffer::getMemBuffer(out); auto_ptr<Module> m2; m2.reset(ParseIR(buffer2, diag, context)); { PassManager manager; manager.add(createInstructionCombiningPass()); manager.run(*m2.get()); } std::vector<CallInst *> LoopFuctionCalls; { PassManager manager; manager.add(createBranchedLoopExtractorPass(LoopFuctionCalls)); manager.run(*m2.get()); } //m2.get()->dump(); // // 5) Replace call to loop functions with call to launcher. // Append "always inline" attribute to all other functions. // Type* int32Ty = Type::getInt32Ty(context); Function* launch = Function::Create( TypeBuilder<types::i<32>(types::i<8>*, types::i<64>, types::i<32>*), true>::get(context), GlobalValue::ExternalLinkage, "kernelgen_launch", m2.get()); for (Module::iterator f1 = m2.get()->begin(), fe1 = m2.get()->end(); f1 != fe1; f1++) { Function* func = f1; if (func->isDeclaration()) continue; // Search for the current function in original module // functions list. // If function is not in list of original module, then // it is generated by the loop extractor. // Append "always inline" attribute to all other functions. if (m1.get()->getFunction(func->getName())) { const AttrListPtr attr = func->getAttributes(); const AttrListPtr attr_new = attr.addAttr(~0U, Attribute::AlwaysInline); func->setAttributes(attr_new); continue; } // Each such function must be extracted to the // standalone module and packed into resulting // object file data section. if (verbose) cout << "Preparing loop function " << func->getName().data() << " ..." << endl; // Reset to default visibility. func->setVisibility(GlobalValue::DefaultVisibility); // Reset to default linkage. func->setLinkage(GlobalValue::ExternalLinkage); // Replace call to this function in module with call to launcher. bool found = false; for (Module::iterator f2 = m2->begin(), fe2 = m2->end(); (f2 != fe2) && !found; f2++) for (Function::iterator bb = f2->begin(); (bb != f2->end()) && !found; bb++) for (BasicBlock::iterator i = bb->begin(); i != bb->end(); i++) { // Check if instruction in focus is a call. CallInst* call = dyn_cast<CallInst>(cast<Value>(i)); if (!call) continue; // Check if function is called (needs -instcombine pass). Function* callee = call->getCalledFunction(); if (!callee) continue; if (callee->isDeclaration()) continue; if (callee->getName() != func->getName()) continue; // Create a constant array holding original called // function name. Constant* name = ConstantArray::get( context, callee->getName(), true); // Create and initialize the memory buffer for name. ArrayType* nameTy = cast<ArrayType>(name->getType()); AllocaInst* nameAlloc = new AllocaInst(nameTy, "", call); StoreInst* nameInit = new StoreInst(name, nameAlloc, "", call); Value* Idx[2]; Idx[0] = Constant::getNullValue(Type::getInt32Ty(context)); Idx[1] = ConstantInt::get(Type::getInt32Ty(context), 0); GetElementPtrInst* namePtr = GetElementPtrInst::Create(nameAlloc, Idx, "", call); // Add pointer to the original function string name. SmallVector<Value*, 16> call_args; call_args.push_back(namePtr); // Add size of the aggregated arguments structure. { BitCastInst* BC = new BitCastInst( call->getArgOperand(0), Type::getInt64PtrTy(context), "", call); LoadInst* LI = new LoadInst(BC, "", call); call_args.push_back(LI); } // Add original aggregated structure argument. call_args.push_back(call->getArgOperand(0)); // Create new function call with new call arguments // and copy old call properties. CallInst* newcall = CallInst::Create(launch, call_args, "", call); //newcall->takeName(call); newcall->setCallingConv(call->getCallingConv()); newcall->setAttributes(call->getAttributes()); newcall->setDebugLoc(call->getDebugLoc()); // Replace old call with new one. call->replaceAllUsesWith(newcall); call->eraseFromParent(); found = true; break; } } //m2.get()->dump(); // // 6) Apply optimization passes to the resulting common // module. // { PassManager manager; manager.add(createLowerSetJmpPass()); PassManagerBuilder builder; builder.Inliner = createFunctionInliningPass(); builder.OptLevel = 3; builder.DisableSimplifyLibCalls = true; builder.populateModulePassManager(manager); manager.run(*m2.get()); } //m2.get()->dump(); // // 7) Embed the resulting module into object file. // { string ir_string; raw_string_ostream ir(ir_string); ir << (*m2.get()); celf e(tmp_output.getFilename(), output); e.getSection(".data")->addSymbol( "__kernelgen_" + string(input), ir_string.c_str(), ir_string.size() + 1); } return 0; }
//===----------------------------------------------------------------------===// // main for opt // int main(int argc, char **argv) { sys::PrintStackTraceOnErrorSignal(); llvm::PrettyStackTraceProgram X(argc, argv); // Enable debug stream buffering. EnableDebugBuffering = true; llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. LLVMContext &Context = getGlobalContext(); cl::ParseCommandLineOptions(argc, argv, "llvm .bc -> .bc modular optimizer and analysis printer\n"); // Allocate a full target machine description only if necessary. // FIXME: The choice of target should be controllable on the command line. std::auto_ptr<TargetMachine> target; SMDiagnostic Err; // Load the input module... std::auto_ptr<Module> M; M.reset(ParseIRFile(InputFilename, Err, Context)); if (M.get() == 0) { Err.Print(argv[0], errs()); return 1; } // Figure out what stream we are supposed to write to... raw_ostream *Out = 0; bool DeleteStream = false; if (!NoOutput && !AnalyzeOnly) { if (OutputFilename == "-") { // Print to stdout. Out = &outs(); // If we're printing a bitcode file, switch stdout to binary mode. // FIXME: This switches outs() globally, not just for the bitcode output. if (!OutputAssembly) sys::Program::ChangeStdoutToBinary(); } else { if (NoOutput || AnalyzeOnly) { errs() << "WARNING: The -o (output filename) option is ignored when\n" "the --disable-output or --analyze options are used.\n"; } else { // Make sure that the Output file gets unlinked from the disk if we get // a SIGINT. sys::RemoveFileOnSignal(sys::Path(OutputFilename)); std::string ErrorInfo; Out = new raw_fd_ostream(OutputFilename.c_str(), ErrorInfo, raw_fd_ostream::F_Binary); if (!ErrorInfo.empty()) { errs() << ErrorInfo << '\n'; delete Out; return 1; } DeleteStream = true; } } } // If the output is set to be emitted to standard out, and standard out is a // console, print out a warning message and refuse to do it. We don't // impress anyone by spewing tons of binary goo to a terminal. if (!Force && !NoOutput && !AnalyzeOnly && !OutputAssembly) if (CheckBitcodeOutputToConsole(*Out, !Quiet)) NoOutput = true; // Create a PassManager to hold and optimize the collection of passes we are // about to build... // PassManager Passes; // Add an appropriate TargetData instance for this module... TargetData *TD = 0; const std::string &ModuleDataLayout = M.get()->getDataLayout(); if (!ModuleDataLayout.empty()) TD = new TargetData(ModuleDataLayout); else if (!DefaultDataLayout.empty()) TD = new TargetData(DefaultDataLayout); if (TD) Passes.add(TD); OwningPtr<PassManager> FPasses; if (OptLevelO1 || OptLevelO2 || OptLevelO3) { FPasses.reset(new PassManager()); if (TD) FPasses->add(new TargetData(*TD)); } // If the -strip-debug command line option was specified, add it. If // -std-compile-opts was also specified, it will handle StripDebug. if (StripDebug && !StandardCompileOpts) addPass(Passes, createStripSymbolsPass(true)); // Create a new optimization pass for each one specified on the command line for (unsigned i = 0; i < PassList.size(); ++i) { // Check to see if -std-compile-opts was specified before this option. If // so, handle it. if (StandardCompileOpts && StandardCompileOpts.getPosition() < PassList.getPosition(i)) { AddStandardCompilePasses(Passes); StandardCompileOpts = false; } if (StandardLinkOpts && StandardLinkOpts.getPosition() < PassList.getPosition(i)) { AddStandardLinkPasses(Passes); StandardLinkOpts = false; } if (OptLevelO1 && OptLevelO1.getPosition() < PassList.getPosition(i)) { AddOptimizationPasses(Passes, *FPasses, 1); OptLevelO1 = false; } if (OptLevelO2 && OptLevelO2.getPosition() < PassList.getPosition(i)) { AddOptimizationPasses(Passes, *FPasses, 2); OptLevelO2 = false; } if (OptLevelO3 && OptLevelO3.getPosition() < PassList.getPosition(i)) { AddOptimizationPasses(Passes, *FPasses, 3); OptLevelO3 = false; } const PassInfo *PassInf = PassList[i]; Pass *P = 0; if (PassInf->getNormalCtor()) P = PassInf->getNormalCtor()(); else errs() << argv[0] << ": cannot create pass: "******"\n"; if (P) { PassKind Kind = P->getPassKind(); addPass(Passes, P); if (AnalyzeOnly) { switch (Kind) { case PT_BasicBlock: Passes.add(new BasicBlockPassPrinter(PassInf)); break; case PT_Loop: Passes.add(new LoopPassPrinter(PassInf)); break; case PT_Function: Passes.add(new FunctionPassPrinter(PassInf)); break; case PT_CallGraphSCC: Passes.add(new CallGraphSCCPassPrinter(PassInf)); break; default: Passes.add(new ModulePassPrinter(PassInf)); break; } } } if (PrintEachXForm) Passes.add(createPrintModulePass(&errs())); } // If -std-compile-opts was specified at the end of the pass list, add them. if (StandardCompileOpts) { AddStandardCompilePasses(Passes); StandardCompileOpts = false; } if (StandardLinkOpts) { AddStandardLinkPasses(Passes); StandardLinkOpts = false; } if (OptLevelO1) AddOptimizationPasses(Passes, *FPasses, 1); if (OptLevelO2) AddOptimizationPasses(Passes, *FPasses, 2); if (OptLevelO3) AddOptimizationPasses(Passes, *FPasses, 3); if (OptLevelO1 || OptLevelO2 || OptLevelO3) FPasses->run(*M.get()); // Check that the module is well formed on completion of optimization if (!NoVerify && !VerifyEach) Passes.add(createVerifierPass()); // Write bitcode or assembly out to disk or outs() as the last step... if (!NoOutput && !AnalyzeOnly) { if (OutputAssembly) Passes.add(createPrintModulePass(Out)); else Passes.add(createBitcodeWriterPass(*Out)); } // Now that we have all of the passes ready, run them. Passes.run(*M.get()); // Delete the raw_fd_ostream. if (DeleteStream) delete Out; return 0; }
void jl_dump_native(const char *bc_fname, const char *obj_fname, const char *sysimg_data, size_t sysimg_len) { assert(imaging_mode); // We don't want to use MCJIT's target machine because // it uses the large code model and we may potentially // want less optimizations there. Triple TheTriple = Triple(jl_TargetMachine->getTargetTriple()); // make sure to emit the native object format, even if FORCE_ELF was set in codegen #if defined(_OS_WINDOWS_) #ifdef LLVM35 TheTriple.setObjectFormat(Triple::COFF); #else TheTriple.setEnvironment(Triple::UnknownEnvironment); #endif #elif defined(_OS_DARWIN_) #ifdef LLVM35 TheTriple.setObjectFormat(Triple::MachO); #else TheTriple.setEnvironment(Triple::MachO); #endif #endif #ifdef LLVM35 std::unique_ptr<TargetMachine> #else OwningPtr<TargetMachine> #endif TM(jl_TargetMachine->getTarget().createTargetMachine( TheTriple.getTriple(), jl_TargetMachine->getTargetCPU(), jl_TargetMachine->getTargetFeatureString(), jl_TargetMachine->Options, #if defined(_OS_LINUX_) || defined(_OS_FREEBSD_) Reloc::PIC_, #elif defined(LLVM39) Optional<Reloc::Model>(), #else Reloc::Default, #endif CodeModel::Default, CodeGenOpt::Aggressive // -O3 TODO: respect command -O0 flag? )); #ifdef LLVM37 legacy::PassManager PM; #else PassManager PM; #endif #ifndef LLVM37 PM.add(new TargetLibraryInfo(Triple(TM->getTargetTriple()))); #else PM.add(new TargetLibraryInfoWrapperPass(Triple(TM->getTargetTriple()))); #endif // set up optimization passes #ifdef LLVM37 // No DataLayout pass needed anymore. #elif defined(LLVM36) PM.add(new DataLayoutPass()); #elif defined(LLVM35) PM.add(new DataLayoutPass(*jl_ExecutionEngine->getDataLayout())); #else PM.add(new DataLayout(*jl_ExecutionEngine->getDataLayout())); #endif addOptimizationPasses(&PM); std::unique_ptr<raw_fd_ostream> bc_OS; std::unique_ptr<raw_fd_ostream> obj_OS; #ifdef LLVM37 // 3.7 simplified formatted output; just use the raw stream alone std::unique_ptr<raw_fd_ostream> &bc_FOS = bc_OS; std::unique_ptr<raw_fd_ostream> &obj_FOS = obj_OS; #else std::unique_ptr<formatted_raw_ostream> bc_FOS; std::unique_ptr<formatted_raw_ostream> obj_FOS; #endif if (bc_fname) { #if defined(LLVM35) // call output handler directly to avoid special case handling of `-` filename int FD; std::error_code EC = sys::fs::openFileForWrite(bc_fname, FD, sys::fs::F_None); bc_OS.reset(new raw_fd_ostream(FD, true)); std::string err; if (EC) err = "ERROR: failed to open --output-bc file '" + std::string(bc_fname) + "': " + EC.message(); #else std::string err; bc_OS.reset(new raw_fd_ostream(bc_fname, err, raw_fd_ostream::F_Binary)); #endif if (!err.empty()) jl_safe_printf("%s\n", err.c_str()); else { #ifndef LLVM37 bc_FOS.reset(new formatted_raw_ostream(*bc_OS.get())); #endif PM.add(createBitcodeWriterPass(*bc_FOS.get())); // Unroll small loops } } if (obj_fname) { #if defined(LLVM35) // call output handler directly to avoid special case handling of `-` filename int FD; std::error_code EC = sys::fs::openFileForWrite(obj_fname, FD, sys::fs::F_None); obj_OS.reset(new raw_fd_ostream(FD, true)); std::string err; if (EC) err = "ERROR: failed to open --output-o file '" + std::string(obj_fname) + "': " + EC.message(); #else std::string err; obj_OS.reset(new raw_fd_ostream(obj_fname, err, raw_fd_ostream::F_Binary)); #endif if (!err.empty()) jl_safe_printf("%s\n", err.c_str()); else { #ifndef LLVM37 obj_FOS.reset(new formatted_raw_ostream(*obj_OS.get())); #endif if (TM->addPassesToEmitFile(PM, *obj_FOS.get(), TargetMachine::CGFT_ObjectFile, false)) { jl_safe_printf("ERROR: target does not support generation of object files\n"); } } } ValueToValueMapTy VMap; #if defined(USE_MCJIT) || defined(USE_ORCJIT) // now copy the module (if using the old JIT), since PM.run may modify it Module *clone = shadow_output; #else Module *clone = CloneModule(shadow_output, VMap); #endif #ifdef LLVM37 // Reset the target triple to make sure it matches the new target machine clone->setTargetTriple(TM->getTargetTriple().str()); #ifdef LLVM38 clone->setDataLayout(TM->createDataLayout()); #else clone->setDataLayout(TM->getDataLayout()->getStringRepresentation()); #endif #endif // add metadata information jl_gen_llvm_globaldata(clone, VMap, sysimg_data, sysimg_len); // do the actual work PM.run(*clone); #if !defined(USE_MCJIT) && !defined(USE_ORCJIT) delete clone; #endif imaging_mode = false; }
/// lintModule - Check a module for errors, printing messages on stderr. /// void llvm::lintModule(const Module &M) { PassManager PM; Lint *V = new Lint(); PM.add(V); PM.run(const_cast<Module&>(M)); }
/// Optimize merged modules using various IPO passes bool LTOCodeGenerator::generateAssemblyCode(formatted_raw_ostream& out, std::string& errMsg) { if ( this->determineTarget(errMsg) ) return true; // mark which symbols can not be internalized this->applyScopeRestrictions(); Module* mergedModule = _linker.getModule(); // If target supports exception handling then enable it now. switch (_target->getMCAsmInfo()->getExceptionHandlingType()) { case ExceptionHandling::Dwarf: llvm::DwarfExceptionHandling = true; break; case ExceptionHandling::SjLj: llvm::SjLjExceptionHandling = true; break; case ExceptionHandling::None: break; default: assert (0 && "Unknown exception handling model!"); } // if options were requested, set them if ( !_codegenOptions.empty() ) cl::ParseCommandLineOptions(_codegenOptions.size(), (char**)&_codegenOptions[0]); // Instantiate the pass manager to organize the passes. PassManager passes; // Start off with a verification pass. passes.add(createVerifierPass()); // Add an appropriate TargetData instance for this module... passes.add(new TargetData(*_target->getTargetData())); createStandardLTOPasses(&passes, /*Internalize=*/ false, !DisableInline, /*VerifyEach=*/ false); // Make sure everything is still good. passes.add(createVerifierPass()); FunctionPassManager* codeGenPasses = new FunctionPassManager(mergedModule); codeGenPasses->add(new TargetData(*_target->getTargetData())); if (_target->addPassesToEmitFile(*codeGenPasses, out, TargetMachine::CGFT_AssemblyFile, CodeGenOpt::Aggressive)) { errMsg = "target file type not supported"; return true; } // Run our queue of passes all at once now, efficiently. passes.run(*mergedModule); // Run the code generator, and write assembly file codeGenPasses->doInitialization(); for (Module::iterator it = mergedModule->begin(), e = mergedModule->end(); it != e; ++it) if (!it->isDeclaration()) codeGenPasses->run(*it); codeGenPasses->doFinalization(); return false; // success }