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.");
13#include <llvm/CodeGen/CommandFlags.h>
14#include <llvm/IR/DebugInfo.h>
15#include <llvm/IR/Module.h>
16#include <llvm/IR/PassManager.h>
17#include <llvm/Linker/Linker.h>
18#include <llvm/MC/TargetRegistry.h>
19#include <llvm/Passes/PassBuilder.h>
20#include <llvm/Support/TargetSelect.h>
21#include <llvm/Target/TargetMachine.h>
22#include <llvm/Transforms/IPO/MergeFunctions.h>
24#if LLVM_VERSION_MAJOR >= 18
25#include <llvm/TargetParser/SubtargetFeature.h>
30#elif LLVM_VERSION_MAJOR == 17
31#if defined(__HIP_PLATFORM_HCC__) || defined(HIP_VERSION_MAJOR)
32#include <llvm/MC/SubtargetFeature.h>
34#include <llvm/TargetParser/SubtargetFeature.h>
37#define STRINGIFY_HELPER(x) #x
38#define STRINGIFY(x) STRINGIFY_HELPER(x)
39#error "Unsupported LLVM version " STRINGIFY(LLVM_VERSION_MAJOR)
41#include <llvm/Transforms/IPO/GlobalDCE.h>
42#include <llvm/Transforms/IPO/Internalize.h>
43#include <llvm/Transforms/IPO/StripDeadPrototypes.h>
44#include <llvm/Transforms/IPO/StripSymbols.h>
45#include <llvm/Transforms/Utils/ModuleUtils.h>
56inline Expected<std::unique_ptr<TargetMachine>>
58 Triple TT(M.getTargetTriple());
59 auto CGOptLevel = CodeGenOpt::getLevel(OptLevel);
60 if (CGOptLevel == std::nullopt)
64 const Target *T = TargetRegistry::lookupTarget(M.getTargetTriple(), Msg);
66 return make_error<StringError>(Msg, inconvertibleErrorCode());
68 SubtargetFeatures Features;
69 Features.getDefaultSubtargetFeatures(TT);
71 std::optional<Reloc::Model> RelocModel;
72 if (M.getModuleFlag(
"PIC Level"))
74 M.getPICLevel() == PICLevel::NotPIC ? Reloc::Static : Reloc::PIC_;
76 std::optional<CodeModel::Model> CodeModel = M.getCodeModel();
81 TargetOptions Options;
82 std::unique_ptr<TargetMachine> TM(T->createTargetMachine(
83 M.getTargetTriple(), Arch, Features.getString(), Options, RelocModel,
84 CodeModel, CGOptLevel.value()));
86 return make_error<StringError>(
"Failed to create target machine",
87 inconvertibleErrorCode());
92 const std::string &PassPipeline,
93 unsigned CodegenOptLevel = 3) {
94 PipelineTuningOptions PTO;
96 std::optional<PGOOptions> PGOOpt;
98 if (
auto Err = TM.takeError())
99 report_fatal_error(std::move(Err));
100 TargetLibraryInfoImpl TLII(Triple(M.getTargetTriple()));
102 PassBuilder PB(TM->get(), PTO, PGOOpt,
nullptr);
103 LoopAnalysisManager LAM;
104 FunctionAnalysisManager FAM;
105 CGSCCAnalysisManager CGAM;
106 ModuleAnalysisManager MAM;
108 FAM.registerPass([&] {
return TargetLibraryAnalysis(TLII); });
110 PB.registerModuleAnalyses(MAM);
111 PB.registerCGSCCAnalyses(CGAM);
112 PB.registerFunctionAnalyses(FAM);
113 PB.registerLoopAnalyses(LAM);
114 PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
115 ModulePassManager Passes;
116 if (
auto E = PB.parsePassPipeline(Passes, PassPipeline))
124 unsigned CodegenOptLevel = 3) {
125 PipelineTuningOptions PTO;
127 std::optional<PGOOptions> PGOOpt;
129 if (
auto Err = TM.takeError())
130 report_fatal_error(std::move(Err));
131 TargetLibraryInfoImpl TLII(Triple(M.getTargetTriple()));
133 PassBuilder PB(TM->get(), PTO, PGOOpt,
nullptr);
134 LoopAnalysisManager LAM;
135 FunctionAnalysisManager FAM;
136 CGSCCAnalysisManager CGAM;
137 ModuleAnalysisManager MAM;
139 FAM.registerPass([&] {
return TargetLibraryAnalysis(TLII); });
141 PB.registerModuleAnalyses(MAM);
142 PB.registerCGSCCAnalyses(CGAM);
143 PB.registerFunctionAnalyses(FAM);
144 PB.registerLoopAnalyses(LAM);
145 PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
147 OptimizationLevel OptSetting;
150 OptSetting = OptimizationLevel::O0;
153 OptSetting = OptimizationLevel::O1;
156 OptSetting = OptimizationLevel::O2;
159 OptSetting = OptimizationLevel::O3;
162 OptSetting = OptimizationLevel::Os;
165 OptSetting = OptimizationLevel::Oz;
168 reportFatalError(std::string(
"Unsupported optimization level ") + OptLevel);
171 ModulePassManager Passes = PB.buildPerModuleDefaultPipeline(OptSetting);
179 InitializeAllTargetInfos();
180 InitializeAllTargets();
181 InitializeAllTargetMCs();
182 InitializeAllAsmParsers();
183 InitializeAllAsmPrinters();
211 auto TraceOut = [](
const std::string &PassPipeline) {
213 raw_svector_ostream OS(S);
214 OS <<
"[CustomPipeline] " << PassPipeline <<
"\n";
229 <<
"optimizeIR optlevel "
232 : StringRef(&OptConfig.
OptLevel, 1))
237inline std::unique_ptr<Module>
239 SmallVector<std::unique_ptr<Module>> LinkedModules) {
241 if (LinkedModules.empty())
244 auto LinkedModule = std::make_unique<llvm::Module>(
"JitModule", Ctx);
245 Linker IRLinker(*LinkedModule);
247 for (
auto &LinkedM : LinkedModules) {
249 if (IRLinker.linkInModule(std::move(LinkedM)))
257 TIMESCOPE(
"proteus::runCleanupPassPipeline");
259 LoopAnalysisManager LAM;
260 FunctionAnalysisManager FAM;
261 CGSCCAnalysisManager CGAM;
262 ModuleAnalysisManager MAM;
264 PB.registerModuleAnalyses(MAM);
265 PB.registerCGSCCAnalyses(CGAM);
266 PB.registerFunctionAnalyses(FAM);
267 PB.registerLoopAnalyses(LAM);
268 PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
270 ModulePassManager Passes;
271 Passes.addPass(GlobalDCEPass());
273 Passes.addPass(StripDeadPrototypesPass());
280inline void pruneIR(Module &M,
bool UnsetExternallyInitialized =
true) {
282 if (
auto *GlobalAnnotations = M.getGlobalVariable(
"llvm.global.annotations"))
283 M.eraseGlobalVariable(GlobalAnnotations);
286 if (
auto *CompilerUsed = M.getGlobalVariable(
"llvm.compiler.used"))
287 M.eraseGlobalVariable(CompilerUsed);
291 SmallVector<GlobalVariable *> GlobalsToErase;
292 for (
auto &GV : M.globals()) {
293 auto Name = GV.getName();
294 if (Name.starts_with(
"__clang_gpu_used_external") ||
295 Name.starts_with(
"_jit_bitcode") || Name.starts_with(
"__hip_cuid")) {
296 GlobalsToErase.push_back(&GV);
297 removeFromUsedLists(M, [&GV](Constant *C) {
298 if (
auto *Global = dyn_cast<GlobalVariable>(C))
299 return Global == &GV;
304 for (
auto *GV : GlobalsToErase) {
305 M.eraseGlobalVariable(GV);
309 if (UnsetExternallyInitialized)
310 for (
auto &GV : M.globals())
311 if (GV.isExternallyInitialized())
312 GV.setExternallyInitialized(
false);
315inline void internalize(Module &M, StringRef PreserveFunctionName) {
316 auto *F = M.getFunction(PreserveFunctionName);
318 internalizeModule(M, [&F](
const GlobalValue &GV) {
#define PROTEUS_TIMER_OUTPUT(x)
Definition Config.h:440
#define TIMESCOPE(...)
Definition TimeTracing.h:66
std::optional< const std::string > optPipeline() const
Definition Config.h:266
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:33
uint64_t elapsed()
Definition TimeTracing.cpp:66
Definition CompiledLibrary.h:7
void runOptimizationPassPipeline(Module &M, StringRef Arch, const std::string &PassPipeline, unsigned CodegenOptLevel=3)
Definition CoreLLVM.h:91
Expected< std::unique_ptr< TargetMachine > > createTargetMachine(Module &M, StringRef Arch, unsigned OptLevel=3)
Definition CoreLLVM.h:57
Definition MemoryCache.h:27
void optimizeIR(Module &M, StringRef Arch, const OptimizationPipelineConfig &OptConfig)
Definition CoreLLVM.h:205
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:280
std::string toString(CodegenOption Option)
Definition Config.h:28
void internalize(Module &M, StringRef PreserveFunctionName)
Definition CoreLLVM.h:315
void runCleanupPassPipeline(Module &M)
Definition CoreLLVM.h:256
std::unique_ptr< Module > linkModules(LLVMContext &Ctx, SmallVector< std::unique_ptr< Module > > LinkedModules)
Definition CoreLLVM.h:238
Definition CoreLLVM.h:177
InitLLVMTargets()
Definition CoreLLVM.h:178
Definition CoreLLVM.h:187
std::optional< std::string > PassPipeline
Definition CoreLLVM.h:188
OptimizationPipelineConfig(const CodeGenerationConfig &CGConfig)
Definition CoreLLVM.h:192
unsigned CodegenOptLevel
Definition CoreLLVM.h:190
OptimizationPipelineConfig(std::optional< std::string > PassPipeline, char OptLevel, unsigned CodegenOptLevel)
Definition CoreLLVM.h:199
char OptLevel
Definition CoreLLVM.h:189