1#ifndef PROTEUS_CORE_LLVM_H
2#define PROTEUS_CORE_LLVM_H
4static_assert(__cplusplus >= 201703L,
5 "This header requires C++17 or later due to LLVM.");
12#include <llvm/CodeGen/CommandFlags.h>
13#include <llvm/IR/DebugInfo.h>
14#include <llvm/IR/Module.h>
15#include <llvm/IR/PassManager.h>
16#include <llvm/Linker/Linker.h>
17#include <llvm/MC/TargetRegistry.h>
18#include <llvm/Passes/PassBuilder.h>
19#include <llvm/Support/TargetSelect.h>
20#include <llvm/Target/TargetMachine.h>
21#include <llvm/Transforms/IPO/MergeFunctions.h>
23#if LLVM_VERSION_MAJOR >= 18
24#include <llvm/TargetParser/SubtargetFeature.h>
29#elif LLVM_VERSION_MAJOR == 17
30#if defined(__HIP_PLATFORM_HCC__) || defined(HIP_VERSION_MAJOR)
31#include <llvm/MC/SubtargetFeature.h>
33#include <llvm/TargetParser/SubtargetFeature.h>
36#define STRINGIFY_HELPER(x) #x
37#define STRINGIFY(x) STRINGIFY_HELPER(x)
38#error "Unsupported LLVM version " STRINGIFY(LLVM_VERSION_MAJOR)
40#include <llvm/Transforms/IPO/GlobalDCE.h>
41#include <llvm/Transforms/IPO/Internalize.h>
42#include <llvm/Transforms/IPO/StripDeadPrototypes.h>
43#include <llvm/Transforms/IPO/StripSymbols.h>
44#include <llvm/Transforms/Utils/ModuleUtils.h>
51inline Expected<std::unique_ptr<TargetMachine>>
53 Triple TT(M.getTargetTriple());
54 auto CGOptLevel = CodeGenOpt::getLevel(OptLevel);
55 if (CGOptLevel == std::nullopt)
59 const Target *T = TargetRegistry::lookupTarget(M.getTargetTriple(), Msg);
61 return make_error<StringError>(Msg, inconvertibleErrorCode());
63 SubtargetFeatures Features;
64 Features.getDefaultSubtargetFeatures(TT);
66 std::optional<Reloc::Model> RelocModel;
67 if (M.getModuleFlag(
"PIC Level"))
69 M.getPICLevel() == PICLevel::NotPIC ? Reloc::Static : Reloc::PIC_;
71 std::optional<CodeModel::Model> CodeModel = M.getCodeModel();
76 TargetOptions Options;
77 std::unique_ptr<TargetMachine> TM(T->createTargetMachine(
78 M.getTargetTriple(), Arch, Features.getString(), Options, RelocModel,
79 CodeModel, CGOptLevel.value()));
81 return make_error<StringError>(
"Failed to create target machine",
82 inconvertibleErrorCode());
87 const std::string &PassPipeline,
88 unsigned CodegenOptLevel = 3) {
89 PipelineTuningOptions PTO;
91 std::optional<PGOOptions> PGOOpt;
93 if (
auto Err = TM.takeError())
94 report_fatal_error(std::move(Err));
95 TargetLibraryInfoImpl TLII(Triple(M.getTargetTriple()));
97 PassBuilder PB(TM->get(), PTO, PGOOpt,
nullptr);
98 LoopAnalysisManager LAM;
99 FunctionAnalysisManager FAM;
100 CGSCCAnalysisManager CGAM;
101 ModuleAnalysisManager MAM;
103 FAM.registerPass([&] {
return TargetLibraryAnalysis(TLII); });
105 PB.registerModuleAnalyses(MAM);
106 PB.registerCGSCCAnalyses(CGAM);
107 PB.registerFunctionAnalyses(FAM);
108 PB.registerLoopAnalyses(LAM);
109 PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
110 ModulePassManager Passes;
111 if (
auto E = PB.parsePassPipeline(Passes, PassPipeline))
119 unsigned CodegenOptLevel = 3) {
120 PipelineTuningOptions PTO;
122 std::optional<PGOOptions> PGOOpt;
124 if (
auto Err = TM.takeError())
125 report_fatal_error(std::move(Err));
126 TargetLibraryInfoImpl TLII(Triple(M.getTargetTriple()));
128 PassBuilder PB(TM->get(), PTO, PGOOpt,
nullptr);
129 LoopAnalysisManager LAM;
130 FunctionAnalysisManager FAM;
131 CGSCCAnalysisManager CGAM;
132 ModuleAnalysisManager MAM;
134 FAM.registerPass([&] {
return TargetLibraryAnalysis(TLII); });
136 PB.registerModuleAnalyses(MAM);
137 PB.registerCGSCCAnalyses(CGAM);
138 PB.registerFunctionAnalyses(FAM);
139 PB.registerLoopAnalyses(LAM);
140 PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
142 OptimizationLevel OptSetting;
145 OptSetting = OptimizationLevel::O0;
148 OptSetting = OptimizationLevel::O1;
151 OptSetting = OptimizationLevel::O2;
154 OptSetting = OptimizationLevel::O3;
157 OptSetting = OptimizationLevel::Os;
160 OptSetting = OptimizationLevel::Oz;
163 reportFatalError(std::string(
"Unsupported optimization level ") + OptLevel);
166 ModulePassManager Passes = PB.buildPerModuleDefaultPipeline(OptSetting);
174 InitializeAllTargetInfos();
175 InitializeAllTargets();
176 InitializeAllTargetMCs();
177 InitializeAllAsmParsers();
178 InitializeAllAsmPrinters();
182inline void optimizeIR(Module &M, StringRef Arch,
char OptLevel,
183 unsigned CodegenOptLevel) {
187 <<
"optimizeIR optlevel " << OptLevel <<
" codegenopt "
188 << CodegenOptLevel <<
" " << T.
elapsed() <<
" ms\n");
192 const std::string &PassPipeline,
193 unsigned CodegenOptLevel) {
195 auto TraceOut = [](
const std::string &PassPipeline) {
197 raw_svector_ostream OS(S);
198 OS <<
"[CustomPipeline] " << PassPipeline <<
"\n";
207 <<
"optimizeIR optlevel " << PassPipeline
208 <<
" codegenopt " << CodegenOptLevel <<
" "
212inline std::unique_ptr<Module>
214 SmallVector<std::unique_ptr<Module>> LinkedModules) {
215 if (LinkedModules.empty())
218 auto LinkedModule = std::make_unique<llvm::Module>(
"JitModule", Ctx);
219 Linker IRLinker(*LinkedModule);
221 for (
auto &LinkedM : LinkedModules) {
223 if (IRLinker.linkInModule(std::move(LinkedM)))
232 LoopAnalysisManager LAM;
233 FunctionAnalysisManager FAM;
234 CGSCCAnalysisManager CGAM;
235 ModuleAnalysisManager MAM;
237 PB.registerModuleAnalyses(MAM);
238 PB.registerCGSCCAnalyses(CGAM);
239 PB.registerFunctionAnalyses(FAM);
240 PB.registerLoopAnalyses(LAM);
241 PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
243 ModulePassManager Passes;
244 Passes.addPass(GlobalDCEPass());
246 Passes.addPass(StripDeadPrototypesPass());
253inline void pruneIR(Module &M,
bool UnsetExternallyInitialized =
true) {
255 if (
auto *GlobalAnnotations = M.getGlobalVariable(
"llvm.global.annotations"))
256 M.eraseGlobalVariable(GlobalAnnotations);
259 if (
auto *CompilerUsed = M.getGlobalVariable(
"llvm.compiler.used"))
260 M.eraseGlobalVariable(CompilerUsed);
264 SmallVector<GlobalVariable *> GlobalsToErase;
265 for (
auto &GV : M.globals()) {
266 auto Name = GV.getName();
267 if (Name.starts_with(
"__clang_gpu_used_external") ||
268 Name.starts_with(
"_jit_bitcode") || Name.starts_with(
"__hip_cuid")) {
269 GlobalsToErase.push_back(&GV);
270 removeFromUsedLists(M, [&GV](Constant *C) {
271 if (
auto *Global = dyn_cast<GlobalVariable>(C))
272 return Global == &GV;
277 for (
auto *GV : GlobalsToErase) {
278 M.eraseGlobalVariable(GV);
282 if (UnsetExternallyInitialized)
283 for (
auto &GV : M.globals())
284 if (GV.isExternallyInitialized())
285 GV.setExternallyInitialized(
false);
288inline void internalize(Module &M, StringRef PreserveFunctionName) {
289 auto *F = M.getFunction(PreserveFunctionName);
291 internalizeModule(M, [&F](
const GlobalValue &GV) {
#define PROTEUS_TIMER_OUTPUT(x)
Definition TimeTracing.h:54
static Config & get()
Definition Config.h:334
static llvm::raw_ostream & outs(const std::string &Name)
Definition Logger.h:25
static void trace(llvm::StringRef Msg)
Definition Logger.h:30
Definition TimeTracing.h:40
uint64_t elapsed()
Definition TimeTracing.cpp:51
Definition CompiledLibrary.h:7
void runOptimizationPassPipeline(Module &M, StringRef Arch, const std::string &PassPipeline, unsigned CodegenOptLevel=3)
Definition CoreLLVM.h:86
Expected< std::unique_ptr< TargetMachine > > createTargetMachine(Module &M, StringRef Arch, unsigned OptLevel=3)
Definition CoreLLVM.h:52
Definition MemoryCache.h:26
void optimizeIR(Module &M, StringRef Arch, char OptLevel, unsigned CodegenOptLevel)
Definition CoreLLVM.h:182
void reportFatalError(const llvm::Twine &Reason, const char *FILE, unsigned Line)
Definition Error.cpp:14
void pruneIR(Module &M, bool UnsetExternallyInitialized=true)
Definition CoreLLVM.h:253
std::string toString(CodegenOption Option)
Definition Config.h:28
void internalize(Module &M, StringRef PreserveFunctionName)
Definition CoreLLVM.h:288
void runCleanupPassPipeline(Module &M)
Definition CoreLLVM.h:230
std::unique_ptr< Module > linkModules(LLVMContext &Ctx, SmallVector< std::unique_ptr< Module > > LinkedModules)
Definition CoreLLVM.h:213
Definition CoreLLVM.h:172
InitLLVMTargets()
Definition CoreLLVM.h:173