/* * Copyright © 2012 Intel Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . * * Author: Benjamin Segovia */ /** * \file llvm_to_gen.cpp * \author Benjamin Segovia */ #include "llvm/Config/llvm-config.h" #if LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR <= 2 #include "llvm/LLVMContext.h" #include "llvm/Module.h" #include "llvm/DataLayout.h" #else #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/IR/DataLayout.h" #endif /* LLVM_VERSION_MINOR <= 2 */ #include "llvm/PassManager.h" #include "llvm/Pass.h" #include "llvm/Analysis/Passes.h" #include "llvm/Transforms/IPO.h" #include "llvm/Target/TargetLibraryInfo.h" #include "llvm/ADT/Triple.h" #if LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR <= 2 #include "llvm/Support/IRReader.h" #else #include "llvm/IRReader/IRReader.h" #include "llvm/Support/SourceMgr.h" #endif /* LLVM_VERSION_MINOR <= 2 */ #include "llvm/Support/raw_ostream.h" #include "llvm/Transforms/Scalar.h" #if LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >=5 #include "llvm/IR/IRPrintingPasses.h" #include "llvm/IR/Verifier.h" #else #include "llvm/Analysis/Verifier.h" #include "llvm/Assembly/PrintModulePass.h" #endif #include "llvm/Analysis/CFGPrinter.h" #include "llvm/llvm_gen_backend.hpp" #include "llvm/llvm_to_gen.hpp" #include "sys/cvar.hpp" #include "sys/platform.hpp" #include #include #include #include #include namespace gbe { BVAR(OCL_OUTPUT_LLVM, false); BVAR(OCL_OUTPUT_CFG, false); BVAR(OCL_OUTPUT_CFG_ONLY, false); BVAR(OCL_OUTPUT_LLVM_BEFORE_EXTRA_PASS, false); using namespace llvm; void runFuntionPass(Module &mod, TargetLibraryInfo *libraryInfo, DataLayout &DL) { FunctionPassManager FPM(&mod); #if LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 5 FPM.add(new DataLayoutPass(DL)); #else FPM.add(&DL); #endif #if LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >=5 FPM.add(createVerifierPass(true)); #else FPM.add(createVerifierPass()); #endif FPM.add(new TargetLibraryInfo(*libraryInfo)); FPM.add(createTypeBasedAliasAnalysisPass()); FPM.add(createBasicAliasAnalysisPass()); FPM.add(createCFGSimplificationPass()); FPM.add(createSROAPass()); FPM.add(createEarlyCSEPass()); FPM.add(createLowerExpectIntrinsicPass()); FPM.doInitialization(); for (Module::iterator I = mod.begin(), E = mod.end(); I != E; ++I) if (!I->isDeclaration()) FPM.run(*I); FPM.doFinalization(); } void runModulePass(Module &mod, TargetLibraryInfo *libraryInfo, DataLayout &DL, int optLevel) { llvm::PassManager MPM; #if LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 5 MPM.add(new DataLayoutPass(DL)); #else MPM.add(&DL); #endif MPM.add(new TargetLibraryInfo(*libraryInfo)); MPM.add(createTypeBasedAliasAnalysisPass()); MPM.add(createBasicAliasAnalysisPass()); MPM.add(createGlobalOptimizerPass()); // Optimize out global vars MPM.add(createIPSCCPPass()); // IP SCCP MPM.add(createDeadArgEliminationPass()); // Dead argument elimination MPM.add(createInstructionCombiningPass());// Clean up after IPCP & DAE MPM.add(createCFGSimplificationPass()); // Clean up after IPCP & DAE MPM.add(createPruneEHPass()); // Remove dead EH info MPM.add(createBarrierNodupPass(false)); // remove noduplicate fnAttr before inlining. MPM.add(createFunctionInliningPass(200000)); MPM.add(createBarrierNodupPass(true)); // restore noduplicate fnAttr after inlining. MPM.add(createFunctionAttrsPass()); // Set readonly/readnone attrs //MPM.add(createScalarReplAggregatesPass(64, true, -1, -1, 64)) if(optLevel > 0) MPM.add(createSROAPass(/*RequiresDomTree*/ false)); MPM.add(createEarlyCSEPass()); // Catch trivial redundancies MPM.add(createJumpThreadingPass()); // Thread jumps. MPM.add(createCorrelatedValuePropagationPass()); // Propagate conditionals MPM.add(createCFGSimplificationPass()); // Merge & remove BBs MPM.add(createInstructionCombiningPass()); // Combine silly seq's MPM.add(createTailCallEliminationPass()); // Eliminate tail calls MPM.add(createCFGSimplificationPass()); // Merge & remove BBs MPM.add(createReassociatePass()); // Reassociate expressions MPM.add(createLoopRotatePass()); // Rotate Loop MPM.add(createLICMPass()); // Hoist loop invariants MPM.add(createLoopUnswitchPass(true)); MPM.add(createInstructionCombiningPass()); MPM.add(createIndVarSimplifyPass()); // Canonicalize indvars MPM.add(createLoopIdiomPass()); // Recognize idioms like memset. MPM.add(createLoopDeletionPass()); // Delete dead loops MPM.add(createLoopUnrollPass()); // Unroll small loops if(optLevel > 0) MPM.add(createGVNPass()); // Remove redundancies MPM.add(createMemCpyOptPass()); // Remove memcpy / form memset MPM.add(createSCCPPass()); // Constant prop with SCCP // Run instcombine after redundancy elimination to exploit opportunities // opened up by them. MPM.add(createInstructionCombiningPass()); MPM.add(createJumpThreadingPass()); // Thread jumps MPM.add(createCorrelatedValuePropagationPass()); MPM.add(createDeadStoreEliminationPass()); // Delete dead stores MPM.add(createAggressiveDCEPass()); // Delete dead instructions MPM.add(createCFGSimplificationPass()); // Merge & remove BBs MPM.add(createInstructionCombiningPass()); // Clean up after everything. MPM.add(createStripDeadPrototypesPass()); // Get rid of dead prototypes if(optLevel > 0) { MPM.add(createGlobalDCEPass()); // Remove dead fns and globals. MPM.add(createConstantMergePass()); // Merge dup global constants } MPM.run(mod); } bool llvmToGen(ir::Unit &unit, const char *fileName,const void* module, int optLevel) { std::string errInfo; std::unique_ptr o = NULL; if (OCL_OUTPUT_LLVM_BEFORE_EXTRA_PASS || OCL_OUTPUT_LLVM) o = std::unique_ptr(new llvm::raw_fd_ostream(fileno(stdout), false)); // Get the module from its file llvm::SMDiagnostic Err; std::auto_ptr M; if(fileName){ // only when module is null, Get the global LLVM context llvm::LLVMContext& c = llvm::getGlobalContext(); M.reset(ParseIRFile(fileName, Err, c)); if (M.get() == 0) return false; } Module &mod = (module!=NULL)?*(llvm::Module*)module:*M.get(); DataLayout DL(&mod); Triple TargetTriple(mod.getTargetTriple()); TargetLibraryInfo *libraryInfo = new TargetLibraryInfo(TargetTriple); libraryInfo->disableAllFunctions(); runFuntionPass(mod, libraryInfo, DL); runModulePass(mod, libraryInfo, DL, optLevel); llvm::PassManager passes; #if LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 5 passes.add(new DataLayoutPass(DL)); #else passes.add(&DL); #endif // Print the code before further optimizations if (OCL_OUTPUT_LLVM_BEFORE_EXTRA_PASS) #if LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 5 passes.add(createPrintModulePass(*o)); #else passes.add(createPrintModulePass(&*o)); #endif passes.add(createIntrinsicLoweringPass()); passes.add(createFunctionInliningPass(200000)); passes.add(createScalarReplAggregatesPass(64, true, -1, -1, 64)); passes.add(createLoadStoreOptimizationPass()); passes.add(createRemoveGEPPass(unit)); passes.add(createConstantPropagationPass()); passes.add(createLowerSwitchPass()); passes.add(createPromoteMemoryToRegisterPass()); if(optLevel > 0) passes.add(createGVNPass()); // Remove redundancies passes.add(createPrintfParserPass()); passes.add(createScalarizePass()); // Expand all vector ops passes.add(createDeadInstEliminationPass()); // Remove simplified instructions passes.add(createCFGSimplificationPass()); // Merge & remove BBs passes.add(createScalarizePass()); // Expand all vector ops if(OCL_OUTPUT_CFG) passes.add(createCFGPrinterPass()); if(OCL_OUTPUT_CFG_ONLY) passes.add(createCFGOnlyPrinterPass()); passes.add(createGenPass(unit)); // Print the code extra optimization passes if (OCL_OUTPUT_LLVM) #if LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 5 passes.add(createPrintModulePass(*o)); #else passes.add(createPrintModulePass(&*o)); #endif passes.run(mod); return true; } } /* namespace gbe */