2015-02-11 23:58:21 +03:00
//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// author: Vassil Vassilev <vvasilev@cern.ch>
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------
# include "BackendPasses.h"
2021-08-05 17:57:09 +03:00
# include "IncrementalJIT.h"
2022-09-15 18:48:32 +03:00
# include "cling/Utils/Platform.h"
2015-02-12 17:14:00 +03:00
# include "llvm/Analysis/InlineCost.h"
2016-11-15 17:17:01 +03:00
# include "llvm/Analysis/TargetLibraryInfo.h"
# include "llvm/Analysis/TargetTransformInfo.h"
2016-04-22 16:10:49 +03:00
# include "llvm/IR/LegacyPassManager.h"
2015-02-11 23:58:21 +03:00
# include "llvm/IR/Module.h"
# include "llvm/IR/Verifier.h"
2016-11-15 17:17:01 +03:00
# include "llvm/Target/TargetMachine.h"
2015-02-11 23:58:21 +03:00
# include "llvm/Transforms/IPO.h"
2017-05-18 16:16:30 +03:00
# include "llvm/Transforms/IPO/AlwaysInliner.h"
# include "llvm/Transforms/IPO/Inliner.h"
2015-02-11 23:58:21 +03:00
# include "llvm/Transforms/IPO/PassManagerBuilder.h"
2016-11-15 17:17:01 +03:00
# include "llvm/Transforms/Scalar.h"
2020-03-09 11:51:11 +03:00
# include "llvm/Transforms/Utils.h"
2015-02-11 23:58:21 +03:00
2016-12-01 12:03:22 +03:00
//#include "clang/Basic/LangOptions.h"
//#include "clang/Basic/TargetOptions.h"
2018-05-18 12:07:36 +03:00
# include "clang/Basic/CharInfo.h"
2020-03-07 21:28:19 +03:00
# include "clang/Basic/CodeGenOptions.h"
2015-02-11 23:58:21 +03:00
using namespace cling ;
using namespace clang ;
using namespace llvm ;
2016-04-22 16:10:49 +03:00
using namespace llvm : : legacy ;
2015-02-11 23:58:21 +03:00
2017-03-29 18:51:12 +03:00
namespace {
2017-04-03 16:08:26 +03:00
class KeepLocalGVPass : public ModulePass {
2017-03-29 18:51:12 +03:00
static char ID ;
2017-04-03 16:08:26 +03:00
bool runOnGlobal ( GlobalValue & GV ) {
if ( GV . isDeclaration ( ) )
2017-03-29 18:51:12 +03:00
return false ; // no change.
2022-04-08 16:52:08 +03:00
// GV is a definition.
// It doesn't make sense to keep unnamed constants, we wouldn't know how
// to reference them anyway.
if ( ! GV . hasName ( ) )
return false ;
2022-03-19 20:57:47 +03:00
if ( GV . getName ( ) . startswith ( " .str " ) )
return false ;
2017-03-29 18:51:12 +03:00
2017-04-03 16:08:26 +03:00
llvm : : GlobalValue : : LinkageTypes LT = GV . getLinkage ( ) ;
if ( ! GV . isDiscardableIfUnused ( LT ) )
2017-03-29 18:51:12 +03:00
return false ;
2023-01-31 17:31:27 +03:00
if ( LT = = llvm : : GlobalValue : : InternalLinkage ) {
2022-05-23 09:53:31 +03:00
// We want to keep this GlobalValue around, but have to tell the JIT
// linker that it should not error on duplicate symbols.
// FIXME: Ideally the frontend would never emit duplicate symbols and
// we could just use the old version of saying:
// GV.setLinkage(llvm::GlobalValue::ExternalLinkage);
GV . setLinkage ( llvm : : GlobalValue : : WeakAnyLinkage ) ;
2017-03-29 18:51:12 +03:00
return true ; // a change!
}
return false ;
}
2017-04-03 16:08:26 +03:00
public :
KeepLocalGVPass ( ) : ModulePass ( ID ) { }
bool runOnModule ( Module & M ) override {
bool ret = false ;
for ( auto & & F : M )
ret | = runOnGlobal ( F ) ;
for ( auto & & G : M . globals ( ) )
ret | = runOnGlobal ( G ) ;
return ret ;
}
2017-03-29 18:51:12 +03:00
} ;
}
2017-04-03 16:08:26 +03:00
char KeepLocalGVPass : : ID = 0 ;
2017-03-29 18:51:12 +03:00
Mark __dso_handle a "far" pointer:
The relocation needs to allow for long offsets, as for the JIT, __dso_handle
might be outside the shared library. Fixes
```
cling JIT session error: In graph cling-module-10-jitted-objectbuffer, section __TEXT,__StaticInit: relocation target "___dso_handle" at address 0x7fe1ee5052e0 is out of range of Delta32 fixup at 0x108c410bd (___cxx_global_var_initcling_module_10_, 0x108c41090 + 0x2d)
[runStaticInitializersOnce]: Failed to materialize symbols: { (main, { $.cling-module-10.__inits.0, __ZN12IncidentTypeL2m1E, __ZN6MarkerD2Ev, __ZN6MarkerD1Ev, ___cxx_global_var_initcling_module_10_.1, __GLOBAL__sub_I_cling_module_10, __ZN6MarkerC2EPKc, ___cxx_global_var_initcling_module_10_.3, __ZN12IncidentTypeL2m3E, __ZN6MarkerC1EPKc, __ZN12IncidentTypeL2m2E, ____orc_init_func.cling-module-10, ___cxx_global_var_initcling_module_10_ }) }
```
as seen no RISC-V and macOS, i.e. with the JITLinker.
2022-11-18 12:15:00 +03:00
namespace {
class PreventLocalOptPass : public ModulePass {
static char ID ;
bool runOnGlobal ( GlobalValue & GV ) {
if ( ! GV . isDeclaration ( ) )
return false ; // no change.
// GV is a declaration with no definition. Make sure to prevent any
// optimization that tries to take advantage of the actual definition
// being "local" because we have no influence on the memory layout of
// data sections and how "close" they are to the code.
bool changed = false ;
if ( GV . hasLocalLinkage ( ) ) {
GV . setLinkage ( llvm : : GlobalValue : : ExternalLinkage ) ;
changed = true ;
}
if ( ! GV . hasDefaultVisibility ( ) ) {
GV . setVisibility ( llvm : : GlobalValue : : DefaultVisibility ) ;
changed = true ;
}
// Set DSO locality last because setLinkage() and setVisibility() check
// isImplicitDSOLocal().
if ( GV . isDSOLocal ( ) ) {
GV . setDSOLocal ( false ) ;
changed = true ;
}
return changed ;
}
public :
PreventLocalOptPass ( ) : ModulePass ( ID ) { }
bool runOnModule ( Module & M ) override {
bool ret = false ;
for ( auto & & F : M )
ret | = runOnGlobal ( F ) ;
for ( auto & & G : M . globals ( ) )
ret | = runOnGlobal ( G ) ;
return ret ;
}
} ;
}
char PreventLocalOptPass : : ID = 0 ;
2022-05-31 18:57:29 +03:00
namespace {
class WeakTypeinfoVTablePass : public ModulePass {
static char ID ;
bool runOnGlobalVariable ( GlobalVariable & GV ) {
// Only need to consider symbols with external linkage because only
// these could be reported as duplicate.
if ( GV . getLinkage ( ) ! = llvm : : GlobalValue : : ExternalLinkage )
return false ;
if ( GV . getName ( ) . startswith ( " _ZT " ) ) {
// Currently, if Cling sees the "key function" of a virtual class, it
// emits typeinfo and vtable variables in every transaction llvm::Module
// that reference them. Turn them into weak linkage to avoid duplicate
// symbol errors from the JIT linker.
// FIXME: This is a hack, we should teach the frontend to emit these
// only once, or mark all duplicates as available_externally (if that
// improves performance due to optimizations).
GV . setLinkage ( llvm : : GlobalValue : : WeakAnyLinkage ) ;
return true ; // a change!
}
return false ;
}
public :
WeakTypeinfoVTablePass ( ) : ModulePass ( ID ) { }
bool runOnModule ( Module & M ) override {
bool ret = false ;
for ( auto & & GV : M . globals ( ) )
ret | = runOnGlobalVariable ( GV ) ;
return ret ;
}
} ;
}
char WeakTypeinfoVTablePass : : ID = 0 ;
2018-05-18 12:07:36 +03:00
namespace {
2022-07-27 14:23:42 +03:00
// Add a suffix to the CUDA module ctor/dtor, CUDA specific functions and
// variables to generate a unique name. This is necessary for lazy
// compilation. Without suffix, cling cannot distinguish ctor/dtor, register
// function and and ptx code string of subsequent modules.
2018-05-18 12:07:36 +03:00
class UniqueCUDAStructorName : public ModulePass {
static char ID ;
2022-07-27 14:23:42 +03:00
// append a suffix to a symbol to make it unique
// the suffix is "_cling_module_<module number>"
llvm : : SmallString < 128 > add_module_suffix ( const StringRef SymbolName ,
const StringRef ModuleName ) {
llvm : : SmallString < 128 > NewFunctionName ;
NewFunctionName . append ( SymbolName ) ;
NewFunctionName . append ( " _ " ) ;
NewFunctionName . append ( ModuleName ) ;
for ( size_t i = 0 ; i < NewFunctionName . size ( ) ; + + i ) {
// Replace everything that is not [a-zA-Z0-9._] with a _. This set
// happens to be the set of C preprocessing numbers.
if ( ! isPreprocessingNumberBody ( NewFunctionName [ i ] ) )
NewFunctionName [ i ] = ' _ ' ;
}
return NewFunctionName ;
}
// make CUDA specific variables unique
bool runOnGlobal ( GlobalValue & GV , const StringRef ModuleName ) {
if ( GV . isDeclaration ( ) )
return false ; // no change.
if ( ! GV . hasName ( ) )
return false ;
2018-05-18 12:07:36 +03:00
2022-07-27 14:23:42 +03:00
if ( GV . getName ( ) . equals ( " __cuda_fatbin_wrapper " ) | |
GV . getName ( ) . equals ( " __cuda_gpubin_handle " ) ) {
GV . setName ( add_module_suffix ( GV . getName ( ) , ModuleName ) ) ;
return true ;
}
2018-05-18 12:07:36 +03:00
2022-07-27 14:23:42 +03:00
return false ;
}
2018-05-18 12:07:36 +03:00
2022-07-27 14:23:42 +03:00
// make CUDA specific functions unique
bool runOnFunction ( Function & F , const StringRef ModuleName ) {
if ( F . hasName ( ) & & ( F . getName ( ) . equals ( " __cuda_module_ctor " ) | |
F . getName ( ) . equals ( " __cuda_module_dtor " ) | |
F . getName ( ) . equals ( " __cuda_register_globals " ) ) ) {
F . setName ( add_module_suffix ( F . getName ( ) , ModuleName ) ) ;
2018-05-18 12:07:36 +03:00
return true ;
}
return false ;
}
public :
UniqueCUDAStructorName ( ) : ModulePass ( ID ) { }
2022-07-27 14:23:42 +03:00
bool runOnModule ( Module & M ) override {
2018-05-18 12:07:36 +03:00
bool ret = false ;
const StringRef ModuleName = M . getName ( ) ;
2022-07-27 14:23:42 +03:00
for ( auto & & F : M )
2018-05-18 12:07:36 +03:00
ret | = runOnFunction ( F , ModuleName ) ;
2022-07-27 14:23:42 +03:00
for ( auto & & G : M . globals ( ) )
ret | = runOnGlobal ( G , ModuleName ) ;
2018-05-18 12:07:36 +03:00
return ret ;
}
} ;
2022-07-27 14:23:42 +03:00
} // namespace
2018-05-18 12:07:36 +03:00
char UniqueCUDAStructorName : : ID = 0 ;
2017-03-29 18:51:12 +03:00
2021-08-05 17:57:09 +03:00
namespace {
// Replace definitions of weak symbols for which symbols already exist by
// declarations. This reduces the amount of emitted symbols.
class ReuseExistingWeakSymbols : public ModulePass {
static char ID ;
2023-01-12 15:54:23 +03:00
cling : : IncrementalJIT & m_JIT ;
2021-08-05 17:57:09 +03:00
2023-01-12 17:35:04 +03:00
bool shouldRemoveGlobalDefinition ( GlobalValue & GV ) {
// Existing *weak* symbols can be re-used thanks to ODR.
2021-08-05 17:57:09 +03:00
llvm : : GlobalValue : : LinkageTypes LT = GV . getLinkage ( ) ;
if ( ! GV . isDiscardableIfUnused ( LT ) | | ! GV . isWeakForLinker ( LT ) )
return false ;
2023-01-12 18:20:40 +03:00
// Find the symbol as existing, previously compiled symbol in the JIT...
if ( m_JIT . doesSymbolAlreadyExist ( GV . getName ( ) ) )
return true ;
// ...or in shared libraries (without auto-loading).
std : : string Name = GV . getName ( ) . str ( ) ;
# if !defined(_WIN32)
return llvm : : sys : : DynamicLibrary : : SearchForAddressOfSymbol ( Name ) ;
# else
return platform : : DLSym ( Name ) ;
# endif
2023-01-12 17:35:04 +03:00
}
bool runOnVar ( GlobalVariable & GV ) {
2021-08-09 18:13:55 +03:00
# if !defined(_WIN32)
2023-01-12 17:35:04 +03:00
// Heuristically, Windows cannot handle cross-library variables; they
// must be library-local.
if ( GV . isDeclaration ( ) )
return false ; // no change.
if ( shouldRemoveGlobalDefinition ( GV ) ) {
GV . setInitializer ( nullptr ) ; // make this a declaration
return true ; // a change!
}
2021-08-09 18:13:55 +03:00
# endif
2023-01-12 17:35:04 +03:00
return false ; // no change.
}
bool runOnFunc ( Function & Func ) {
if ( Func . isDeclaration ( ) )
return false ; // no change.
2023-01-17 14:56:34 +03:00
# ifndef _WIN32
// MSVC's stdlib gets symbol issues; i.e. apparently: JIT all or none.
2023-01-12 17:35:04 +03:00
if ( Func . getInstructionCount ( ) < 50 ) {
// This is a small function. Keep its definition to retain it for
// inlining: the cost for JITting it is small, and the likelihood
// that the call will be inlined is high.
return false ;
}
2023-01-17 14:56:34 +03:00
# endif
2023-01-12 17:35:04 +03:00
if ( shouldRemoveGlobalDefinition ( Func ) ) {
Func . deleteBody ( ) ; // make this a declaration
2021-08-05 17:57:09 +03:00
return true ; // a change!
}
2023-01-12 17:35:04 +03:00
return false ; // no change.
2021-08-05 17:57:09 +03:00
}
public :
2023-01-12 15:54:23 +03:00
ReuseExistingWeakSymbols ( IncrementalJIT & JIT ) :
ModulePass ( ID ) , m_JIT ( JIT ) { }
2021-08-05 17:57:09 +03:00
bool runOnModule ( Module & M ) override {
bool ret = false ;
2023-01-12 18:20:40 +03:00
// FIXME: use SymbolLookupSet, rather than looking up symbol by symbol.
2021-08-05 17:57:09 +03:00
for ( auto & & F : M )
2023-01-12 17:35:04 +03:00
ret | = runOnFunc ( F ) ;
2021-08-05 17:57:09 +03:00
for ( auto & & G : M . globals ( ) )
2023-01-12 17:35:04 +03:00
ret | = runOnVar ( G ) ;
2021-08-05 17:57:09 +03:00
return ret ;
}
} ;
}
char ReuseExistingWeakSymbols : : ID = 0 ;
2020-10-10 21:34:55 +03:00
BackendPasses : : BackendPasses ( const clang : : CodeGenOptions & CGOpts ,
2023-01-12 15:54:23 +03:00
IncrementalJIT & JIT , llvm : : TargetMachine & TM ) :
2020-10-10 21:34:55 +03:00
m_TM ( TM ) ,
2023-01-12 15:54:23 +03:00
m_JIT ( JIT ) ,
2022-09-20 17:06:12 +03:00
m_CGOpts ( CGOpts )
2020-10-10 21:34:55 +03:00
{ }
2015-05-27 18:35:57 +03:00
BackendPasses : : ~ BackendPasses ( ) {
2016-11-15 17:17:01 +03:00
//delete m_PMBuilder->Inliner;
2015-05-27 18:35:57 +03:00
}
2015-02-11 23:58:21 +03:00
2017-04-07 17:56:07 +03:00
void BackendPasses : : CreatePasses ( llvm : : Module & M , int OptLevel )
2015-02-11 23:58:21 +03:00
{
// From BackEndUtil's clang::EmitAssemblyHelper::CreatePasses().
2017-04-11 09:52:29 +03:00
#if 0
2017-06-14 19:22:17 +03:00
CodeGenOptions : : InliningMethod Inlining = m_CGOpts . getInlining ( ) ;
2016-11-15 17:17:01 +03:00
CodeGenOptions & CGOpts_ = const_cast < CodeGenOptions & > ( m_CGOpts ) ;
// DON'T: we will not find our symbols...
//CGOpts_.CXXCtorDtorAliases = 1;
2017-03-27 17:18:15 +03:00
// Default clang -O2 on Linux 64bit also has the following, but see
// CIFactory.cpp.
2016-11-15 17:17:01 +03:00
CGOpts_ . DisableFPElim = 0 ;
CGOpts_ . DiscardValueNames = 1 ;
CGOpts_ . OmitLeafFramePointer = 1 ;
CGOpts_ . OptimizationLevel = 2 ;
CGOpts_ . RelaxAll = 0 ;
CGOpts_ . UnrollLoops = 1 ;
CGOpts_ . VectorizeLoop = 1 ;
CGOpts_ . VectorizeSLP = 1 ;
# endif
2017-03-27 17:17:22 +03:00
2017-05-04 11:02:24 +03:00
#if 0 // def __GNUC__
2017-03-27 17:17:22 +03:00
// Better inlining is pending https://bugs.llvm.org//show_bug.cgi?id=19668
// and its consequence https://sft.its.cern.ch/jira/browse/ROOT-7111
// shown e.g. by roottest/cling/stl/map/badstringMap
2017-04-11 09:53:24 +03:00
if ( Inlining > CodeGenOptions : : NormalInlining )
Inlining = CodeGenOptions : : NormalInlining ;
# endif
2015-02-11 23:58:21 +03:00
2017-10-19 21:55:41 +03:00
// Handle disabling of LLVM optimization, where we want to preserve the
// internal module before any optimization.
if ( m_CGOpts . DisableLLVMPasses ) {
OptLevel = 0 ;
// Always keep at least ForceInline - NoInlining is deadly for libc++.
// Inlining = CGOpts.NoInlining;
}
2015-02-11 23:58:21 +03:00
2016-11-15 17:17:01 +03:00
llvm : : PassManagerBuilder PMBuilder ;
PMBuilder . OptLevel = OptLevel ;
2016-11-15 18:41:14 +03:00
PMBuilder . SizeLevel = m_CGOpts . OptimizeSize ;
2017-04-07 17:56:07 +03:00
PMBuilder . SLPVectorize = OptLevel > 1 ? 1 : 0 ; // m_CGOpts.VectorizeSLP
PMBuilder . LoopVectorize = OptLevel > 1 ? 1 : 0 ; // m_CGOpts.VectorizeLoop
2016-11-15 17:17:01 +03:00
2016-11-15 18:41:14 +03:00
PMBuilder . DisableTailCalls = m_CGOpts . DisableTailCalls ;
PMBuilder . DisableUnrollLoops = ! m_CGOpts . UnrollLoops ;
PMBuilder . MergeFunctions = m_CGOpts . MergeFunctions ;
PMBuilder . RerollLoops = m_CGOpts . RerollLoops ;
2015-02-11 23:58:21 +03:00
2016-11-15 18:41:14 +03:00
PMBuilder . LibraryInfo = new TargetLibraryInfoImpl ( m_TM . getTargetTriple ( ) ) ;
2015-02-11 23:58:21 +03:00
2017-05-18 16:16:30 +03:00
// At O0 and O1 we only run the always inliner which is more efficient. At
// higher optimization levels we run the normal inliner.
2018-07-25 11:36:29 +03:00
// See also call to `CGOpts.setInlining()` in CIFactory!
2019-01-09 20:48:18 +03:00
if ( PMBuilder . OptLevel < = 1 ) {
bool InsertLifetimeIntrinsics = PMBuilder . OptLevel ! = 0 ;
2017-05-18 16:16:30 +03:00
PMBuilder . Inliner = createAlwaysInlinerLegacyPass ( InsertLifetimeIntrinsics ) ;
} else {
2019-01-09 20:48:18 +03:00
PMBuilder . Inliner = createFunctionInliningPass ( OptLevel ,
PMBuilder . SizeLevel ,
2020-03-09 11:51:42 +03:00
( ! m_CGOpts . SampleProfileFile . empty ( ) & & m_CGOpts . PrepareForThinLTO ) ) ;
2015-02-11 23:58:21 +03:00
}
// Set up the per-module pass manager.
2017-04-07 17:56:07 +03:00
m_MPM [ OptLevel ] . reset ( new legacy : : PassManager ( ) ) ;
2016-11-15 17:17:01 +03:00
2017-04-07 17:56:07 +03:00
m_MPM [ OptLevel ] - > add ( new KeepLocalGVPass ( ) ) ;
Mark __dso_handle a "far" pointer:
The relocation needs to allow for long offsets, as for the JIT, __dso_handle
might be outside the shared library. Fixes
```
cling JIT session error: In graph cling-module-10-jitted-objectbuffer, section __TEXT,__StaticInit: relocation target "___dso_handle" at address 0x7fe1ee5052e0 is out of range of Delta32 fixup at 0x108c410bd (___cxx_global_var_initcling_module_10_, 0x108c41090 + 0x2d)
[runStaticInitializersOnce]: Failed to materialize symbols: { (main, { $.cling-module-10.__inits.0, __ZN12IncidentTypeL2m1E, __ZN6MarkerD2Ev, __ZN6MarkerD1Ev, ___cxx_global_var_initcling_module_10_.1, __GLOBAL__sub_I_cling_module_10, __ZN6MarkerC2EPKc, ___cxx_global_var_initcling_module_10_.3, __ZN12IncidentTypeL2m3E, __ZN6MarkerC1EPKc, __ZN12IncidentTypeL2m2E, ____orc_init_func.cling-module-10, ___cxx_global_var_initcling_module_10_ }) }
```
as seen no RISC-V and macOS, i.e. with the JITLinker.
2022-11-18 12:15:00 +03:00
m_MPM [ OptLevel ] - > add ( new PreventLocalOptPass ( ) ) ;
2022-05-31 18:57:29 +03:00
m_MPM [ OptLevel ] - > add ( new WeakTypeinfoVTablePass ( ) ) ;
2023-01-12 15:54:23 +03:00
m_MPM [ OptLevel ] - > add ( new ReuseExistingWeakSymbols ( m_JIT ) ) ;
2021-08-05 17:57:09 +03:00
2018-05-18 12:07:36 +03:00
// The function __cuda_module_ctor and __cuda_module_dtor will just generated,
// if a CUDA fatbinary file exist. Without file path there is no need for the
// function pass.
2020-03-09 11:54:08 +03:00
if ( ! m_CGOpts . CudaGpuBinaryFileName . empty ( ) )
2018-05-18 12:07:36 +03:00
m_MPM [ OptLevel ] - > add ( new UniqueCUDAStructorName ( ) ) ;
2017-04-07 17:56:07 +03:00
m_MPM [ OptLevel ] - > add ( createTargetTransformInfoWrapperPass (
m_TM . getTargetIRAnalysis ( ) ) ) ;
2016-11-15 17:17:01 +03:00
2017-05-18 16:16:30 +03:00
m_TM . adjustPassManager ( PMBuilder ) ;
2016-11-15 18:41:14 +03:00
PMBuilder . addExtension ( PassManagerBuilder : : EP_EarlyAsPossible ,
[ & ] ( const PassManagerBuilder & ,
legacy : : PassManagerBase & PM ) {
2016-11-15 17:17:01 +03:00
PM . add ( createAddDiscriminatorsPass ( ) ) ;
} ) ;
2015-02-11 23:58:21 +03:00
//if (!CGOpts.RewriteMapFiles.empty())
// addSymbolRewriterPass(CGOpts, m_MPM);
2017-04-07 17:56:07 +03:00
PMBuilder . populateModulePassManager ( * m_MPM [ OptLevel ] ) ;
2016-11-15 17:17:01 +03:00
2017-04-07 17:56:07 +03:00
m_FPM [ OptLevel ] . reset ( new legacy : : FunctionPassManager ( & M ) ) ;
m_FPM [ OptLevel ] - > add ( createTargetTransformInfoWrapperPass (
m_TM . getTargetIRAnalysis ( ) ) ) ;
2016-11-15 17:17:01 +03:00
if ( m_CGOpts . VerifyModule )
2017-04-07 17:56:07 +03:00
m_FPM [ OptLevel ] - > add ( createVerifierPass ( ) ) ;
PMBuilder . populateFunctionPassManager ( * m_FPM [ OptLevel ] ) ;
2015-02-11 23:58:21 +03:00
}
2017-04-07 17:56:07 +03:00
void BackendPasses : : runOnModule ( Module & M , int OptLevel ) {
2015-02-11 23:58:21 +03:00
2017-04-07 17:56:07 +03:00
if ( OptLevel < 0 )
OptLevel = 0 ;
if ( OptLevel > 3 )
OptLevel = 3 ;
if ( ! m_MPM [ OptLevel ] )
CreatePasses ( M , OptLevel ) ;
2017-06-23 12:33:23 +03:00
static constexpr std : : array < llvm : : CodeGenOpt : : Level , 4 > CGOptLevel { {
2017-04-07 17:56:07 +03:00
llvm : : CodeGenOpt : : None ,
llvm : : CodeGenOpt : : Less ,
llvm : : CodeGenOpt : : Default ,
llvm : : CodeGenOpt : : Aggressive
2017-06-23 12:33:23 +03:00
} } ;
2017-04-07 17:56:07 +03:00
// TM's OptLevel is used to build orc::SimpleCompiler passes for every Module.
m_TM . setOptLevel ( CGOptLevel [ OptLevel ] ) ;
2015-02-11 23:58:21 +03:00
// Run the per-function passes on the module.
2017-04-07 17:56:07 +03:00
m_FPM [ OptLevel ] - > doInitialization ( ) ;
2015-02-11 23:58:21 +03:00
for ( auto & & I : M . functions ( ) )
if ( ! I . isDeclaration ( ) )
2017-04-07 17:56:07 +03:00
m_FPM [ OptLevel ] - > run ( I ) ;
m_FPM [ OptLevel ] - > doFinalization ( ) ;
2015-02-11 23:58:21 +03:00
2017-04-07 17:56:07 +03:00
m_MPM [ OptLevel ] - > run ( M ) ;
2015-02-11 23:58:21 +03:00
}