diff options
author | Erik Verbruggen <erik.verbruggen@digia.com> | 2012-11-13 09:54:24 +0100 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@digia.com> | 2012-11-14 08:40:37 +0100 |
commit | 2a8d0b894ba59c6e8966b39bf872ce081579f50d (patch) | |
tree | ac47b06da4b633317b989f4c34889c628044e1be /qv4isel_llvm.cpp | |
parent | c870a64bad28bc52e4bf7239a78e166804fd2124 (diff) |
Added different output types to LLVM backend to ease debugging.
While in that area of code, also throw in the pass-managers for
some extra optimisations during compilation.
Change-Id: I1239ab9d21fc50b2e65c2f9d77a03ae593b607bc
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Diffstat (limited to 'qv4isel_llvm.cpp')
-rw-r--r-- | qv4isel_llvm.cpp | 93 |
1 files changed, 63 insertions, 30 deletions
diff --git a/qv4isel_llvm.cpp b/qv4isel_llvm.cpp index c674377d6b..9b6907159f 100644 --- a/qv4isel_llvm.cpp +++ b/qv4isel_llvm.cpp @@ -82,9 +82,10 @@ namespace QQmlJS { -int compileWithLLVM(IR::Module *module, const QString &fileName, int (*exec)(void *)) +int compileWithLLVM(IR::Module *module, const QString &fileName, LLVMOutputType outputType, int (*exec)(void *)) { Q_ASSERT(module); + Q_ASSERT(exec || outputType != LLVMOutputJit); // TODO: should this be done here? LLVMInitializeX86TargetInfo(); @@ -103,44 +104,61 @@ int compileWithLLVM(IR::Module *module, const QString &fileName, int (*exec)(voi llvm::StringRef moduleId(moduleName.toUtf8().constData()); llvm::Module *llvmModule = new llvm::Module(moduleId, llvmIsel.getContext()); - if (exec) { + if (outputType == LLVMOutputJit) { // The execution engine takes ownership of the model. No need to delete it anymore. std::string errStr; llvm::ExecutionEngine *execEngine = llvm::EngineBuilder(llvmModule) - .setUseMCJIT(true) -// .setJITMemoryManager(llvm::JITMemoryManager::CreateDefaultMemManager()) +// .setUseMCJIT(true) .setErrorStr(&errStr).create(); if (!execEngine) { std::cerr << "Could not create LLVM JIT: " << errStr << std::endl; return EXIT_FAILURE; } - llvm::FunctionPassManager fpm(llvmModule); + llvm::FunctionPassManager functionPassManager(llvmModule); // Set up the optimizer pipeline. Start with registering info about how the // target lays out data structures. - fpm.add(new llvm::DataLayout(*execEngine->getDataLayout())); + functionPassManager.add(new llvm::DataLayout(*execEngine->getDataLayout())); + // Promote allocas to registers. + functionPassManager.add(llvm::createPromoteMemoryToRegisterPass()); // Provide basic AliasAnalysis support for GVN. - fpm.add(llvm::createBasicAliasAnalysisPass()); + functionPassManager.add(llvm::createBasicAliasAnalysisPass()); // Do simple "peephole" optimizations and bit-twiddling optzns. - fpm.add(llvm::createInstructionCombiningPass()); + functionPassManager.add(llvm::createInstructionCombiningPass()); // Reassociate expressions. - fpm.add(llvm::createReassociatePass()); + functionPassManager.add(llvm::createReassociatePass()); // Eliminate Common SubExpressions. - fpm.add(llvm::createGVNPass()); + functionPassManager.add(llvm::createGVNPass()); // Simplify the control flow graph (deleting unreachable blocks, etc). - fpm.add(llvm::createCFGSimplificationPass()); + functionPassManager.add(llvm::createCFGSimplificationPass()); - fpm.doInitialization(); + functionPassManager.doInitialization(); - llvmIsel.buildLLVMModule(module, llvmModule, &fpm); + llvmIsel.buildLLVMModule(module, llvmModule, &functionPassManager); llvm::Function *entryPoint = llvmModule->getFunction("%entry"); Q_ASSERT(entryPoint); void *funcPtr = execEngine->getPointerToFunction(entryPoint); return exec(funcPtr); } else { - // TODO: add a FunctionPassManager - llvmIsel.buildLLVMModule(module, llvmModule, 0); + llvm::FunctionPassManager functionPassManager(llvmModule); + // Set up the optimizer pipeline. + // Promote allocas to registers. + functionPassManager.add(llvm::createPromoteMemoryToRegisterPass()); + // Provide basic AliasAnalysis support for GVN. + functionPassManager.add(llvm::createBasicAliasAnalysisPass()); + // Do simple "peephole" optimizations and bit-twiddling optzns. + functionPassManager.add(llvm::createInstructionCombiningPass()); + // Reassociate expressions. + functionPassManager.add(llvm::createReassociatePass()); + // Eliminate Common SubExpressions. + functionPassManager.add(llvm::createGVNPass()); + // Simplify the control flow graph (deleting unreachable blocks, etc). + functionPassManager.add(llvm::createCFGSimplificationPass()); + + functionPassManager.doInitialization(); + + llvmIsel.buildLLVMModule(module, llvmModule, &functionPassManager); // TODO: if output type is .ll, print the module to file @@ -162,12 +180,16 @@ int compileWithLLVM(IR::Module *module, const QString &fileName, int (*exec)(voi llvm::TargetMachine::CodeGenFileType ft; QString ofName; - ft = llvm::TargetMachine::CGFT_ObjectFile; - ofName = fileName + QLatin1String(".o"); - - // TODO: - // ft = llvm::TargetMachine::CGFT_AssemblyFile; - // ofName = fileName + QLatin1String(".s"); + if (outputType == LLVMOutputObject) { + ft = llvm::TargetMachine::CGFT_ObjectFile; + ofName = fileName + QLatin1String(".o"); + } else if (outputType == LLVMOutputAssembler) { + ft = llvm::TargetMachine::CGFT_AssemblyFile; + ofName = fileName + QLatin1String(".s"); + } else { + // ft is not used. + ofName = fileName + QLatin1String(".ll"); + } llvm::raw_fd_ostream dest(ofName.toUtf8().constData(), err, llvm::raw_fd_ostream::F_Binary); llvm::formatted_raw_ostream destf(dest); @@ -176,15 +198,25 @@ int compileWithLLVM(IR::Module *module, const QString &fileName, int (*exec)(voi delete llvmModule; } - llvm::PassManager PM; - PM.add(llvm::createScalarReplAggregatesPass()); - PM.add(llvm::createInstructionCombiningPass()); - PM.add(llvm::createGlobalOptimizerPass()); - PM.add(llvm::createFunctionInliningPass(25)); - if (targetMachine->addPassesToEmitFile(PM, destf, ft)) { - std::cerr << err << " (probably no DataLayout in TargetMachine)" << std::endl; - } else { - PM.run(*llvmModule); + llvm::PassManager globalPassManager; + globalPassManager.add(llvm::createScalarReplAggregatesPass()); + globalPassManager.add(llvm::createInstructionCombiningPass()); + globalPassManager.add(llvm::createGlobalOptimizerPass()); + globalPassManager.add(llvm::createFunctionInliningPass(25)); +// globalPassManager.add(llvm::createFunctionInliningPass(125)); + + if (outputType == LLVMOutputObject || outputType == LLVMOutputAssembler) { + if (targetMachine->addPassesToEmitFile(globalPassManager, destf, ft)) { + std::cerr << err << " (probably no DataLayout in TargetMachine)" << std::endl; + } else { + globalPassManager.run(*llvmModule); + + destf.flush(); + dest.flush(); + } + } else { // .ll + globalPassManager.run(*llvmModule); + llvmModule->print(destf, 0); destf.flush(); dest.flush(); @@ -261,6 +293,7 @@ void LLVMInstructionSelection::buildLLVMModule(IR::Module *module, llvm::Module foreach (IR::Function *function, module->functions) (void) compileLLVMFunction(function); + qSwap(_fpm, fpm); qSwap(_llvmModule, llvmModule); } |