https://github.com/vikramRH updated https://github.com/llvm/llvm-project/pull/210249
>From 1d61a4122d5d74d38f427a3d712f6f206455f8d8 Mon Sep 17 00:00:00 2001 From: vikhegde <[email protected]> Date: Thu, 16 Jul 2026 16:23:49 +0530 Subject: [PATCH] [CodeGen][LTO] Switch to runCodeGenPipeline abstraction --- clang/lib/CodeGen/BackendUtil.cpp | 10 ++-- llvm/include/llvm/Passes/RunCodeGen.h | 30 ++++++++--- llvm/lib/LTO/LTOBackend.cpp | 53 ++++++++---------- llvm/lib/Passes/RunCodeGen.cpp | 54 +++++++++++-------- .../CodeGen/AMDGPU/lto-lower-module-lds.ll | 49 +++++++++++++++++ 5 files changed, 134 insertions(+), 62 deletions(-) diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp index 5a01779613c8c..b71dfbdd133ca 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -1215,10 +1215,12 @@ void EmitAssemblyHelper::RunCodegenPipeline( } TimeCodegenPasses([&]() { - Error CodeGenError = runCodeGenPipeline( - *TM, *TheModule, *OS, DwoOS, CGFT, PrintPipelinePasses.has_value(), - !CodeGenOpts.VerifyModule, /*DisableSimplifyLibCalls=*/false, - CI.getVirtualFileSystemPtr()); + CodeGenPipelineConfig Config; + Config.PrintPipelinePasses = PrintPipelinePasses.has_value(); + Config.DisableVerify = !CodeGenOpts.VerifyModule; + Config.VFS = CI.getVirtualFileSystemPtr(); + Error CodeGenError = + runCodeGenPipeline(*TM, *TheModule, *OS, DwoOS, CGFT, Config); if (CodeGenError) Diags.Report(diag::err_fe_unable_to_interface_with_target); }); diff --git a/llvm/include/llvm/Passes/RunCodeGen.h b/llvm/include/llvm/Passes/RunCodeGen.h index b61e171363b7d..15aa926300aeb 100644 --- a/llvm/include/llvm/Passes/RunCodeGen.h +++ b/llvm/include/llvm/Passes/RunCodeGen.h @@ -16,12 +16,30 @@ namespace llvm { -LLVM_ABI Error runCodeGenPipeline( - TargetMachine &TM, Module &M, raw_pwrite_stream &OS, - std::unique_ptr<ToolOutputFile> &DwoOS, CodeGenFileType CGFT, - bool PrintPipelinePasses = false, bool DisableVerify = true, - bool DisableSimplifyLibCalls = false, - IntrusiveRefCntPtr<vfs::FileSystem> VFS = vfs::getRealFileSystem()); +class ModuleSummaryIndex; + +/// Options for runCodeGenPipeline(). +struct CodeGenPipelineConfig { + /// FIXME: Need to be implemented in runCodeGenPipeline(). + bool PrintPipelinePasses = false; + + bool DisableVerify = true; + bool DisableSimplifyLibCalls = false; + /// Log each pass as it runs. New pass manager only. + bool DebugPassManager = false; + /// Verify the IR between passes. New pass manager only. + bool VerifyEach = false; + /// LTO uses this to expose the combined summary index to summary-consuming + /// codegen passes. + const ModuleSummaryIndex *SummaryIndex = nullptr; + /// For passes needing file access. + IntrusiveRefCntPtr<vfs::FileSystem> VFS = nullptr; +}; + +Error runCodeGenPipeline(TargetMachine &TM, Module &M, raw_pwrite_stream &OS, + std::unique_ptr<ToolOutputFile> &DwoOS, + CodeGenFileType CGFT, + const CodeGenPipelineConfig &Config = {}); } // namespace llvm diff --git a/llvm/lib/LTO/LTOBackend.cpp b/llvm/lib/LTO/LTOBackend.cpp index d9a6551139d37..2b1d57d81f5ef 100644 --- a/llvm/lib/LTO/LTOBackend.cpp +++ b/llvm/lib/LTO/LTOBackend.cpp @@ -30,6 +30,7 @@ #include "llvm/MC/TargetRegistry.h" #include "llvm/Object/ModuleSymbolTable.h" #include "llvm/Passes/PassBuilder.h" +#include "llvm/Passes/RunCodeGen.h" #include "llvm/Passes/StandardInstrumentations.h" #include "llvm/Plugins/PassPlugin.h" #include "llvm/Support/Error.h" @@ -479,36 +480,28 @@ static void codegen(const Config &Conf, TargetMachine *TM, std::unique_ptr<CachedFileStream> &Stream = *StreamOrErr; TM->Options.ObjectFilenameForDebug = Stream->ObjectPathName; - // Create the codegen pipeline in its own scope so it gets deleted before - // Stream->commit() is called. The commit function of CacheStream deletes - // the raw stream, which is too early as streamers (e.g. MCAsmStreamer) - // keep the pointer and may use it until their destruction. See #138194. - { - legacy::PassManager CodeGenPasses; - TargetLibraryInfoImpl TLII(Mod.getTargetTriple(), TM->Options.VecLib); - CodeGenPasses.add(new TargetLibraryInfoWrapperPass(TLII)); - CodeGenPasses.add(new RuntimeLibraryInfoWrapper( - TM->Options.MCOptions.ABIName, TM->Options.VecLib)); - - // No need to make index available if the module is empty. - // In theory these passes should not use the index for an empty - // module, however, this guards against doing any unnecessary summary-based - // analysis in the case of a ThinLTO build where this might be an empty - // regular LTO combined module, with a large combined index from ThinLTO. - if (!isEmptyModule(Mod)) - CodeGenPasses.add( - createImmutableModuleSummaryIndexWrapperPass(&CombinedIndex)); - if (Conf.PreCodeGenPassesHook) - Conf.PreCodeGenPassesHook(CodeGenPasses); - if (TM->addPassesToEmitFile(CodeGenPasses, *Stream->OS, - DwoOut ? &DwoOut->os() : nullptr, - Conf.CGFileType)) - report_fatal_error("Failed to setup codegen"); - CodeGenPasses.run(Mod); - - if (DwoOut) - DwoOut->keep(); - } + CodeGenPipelineConfig CGConfig; + CGConfig.DebugPassManager = Conf.DebugPassManager; + CGConfig.VerifyEach = Conf.VerifyEach; + // No need to make index available if the module is empty. + // In theory these passes should not use the index for an empty + // module, however, this guards against doing any unnecessary summary-based + // analysis in the case of a ThinLTO build where this might be an empty + // regular LTO combined module, with a large combined index from ThinLTO. + if (!isEmptyModule(Mod)) + CGConfig.SummaryIndex = &CombinedIndex; + + // runCodeGenPipeline() keeps the pipeline local to itself so that it gets + // deleted before Stream->commit() is called below. The commit function of + // CacheStream deletes the raw stream, which is too early as streamers (e.g. + // MCAsmStreamer) keep the pointer and may use it until their destruction. + // See #138194. + if (Error Err = runCodeGenPipeline(*TM, Mod, *Stream->OS, DwoOut, + Conf.CGFileType, CGConfig)) + report_fatal_error(std::move(Err)); + + if (DwoOut) + DwoOut->keep(); if (Error Err = Stream->commit()) report_fatal_error(std::move(Err)); diff --git a/llvm/lib/Passes/RunCodeGen.cpp b/llvm/lib/Passes/RunCodeGen.cpp index fee9b8f4e00de..9112ad1df73df 100644 --- a/llvm/lib/Passes/RunCodeGen.cpp +++ b/llvm/lib/Passes/RunCodeGen.cpp @@ -9,6 +9,7 @@ #include "llvm/Passes/RunCodeGen.h" #include "llvm/Analysis/CGSCCPassManager.h" #include "llvm/Analysis/LoopAnalysisManager.h" +#include "llvm/Analysis/ModuleSummaryAnalysis.h" #include "llvm/Analysis/RuntimeLibcallInfo.h" #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/Analysis/TargetTransformInfo.h" @@ -32,17 +33,17 @@ static cl::opt<cl::boolOrDefault> "option will default to what the target prefers."), cl::init(cl::boolOrDefault::BOU_UNSET)); -static Error -runCodeGenPipelineLegacy(TargetMachine &TM, Module &M, raw_pwrite_stream &OS, - std::unique_ptr<ToolOutputFile> &DwoOS, - CodeGenFileType CGFT, bool PrintPipelinePasses, - bool DisableVerify, bool DisableSimplifyLibCalls) { +static Error runCodeGenPipelineLegacy(TargetMachine &TM, Module &M, + raw_pwrite_stream &OS, + std::unique_ptr<ToolOutputFile> &DwoOS, + CodeGenFileType CGFT, + const CodeGenPipelineConfig &Config) { legacy::PassManager CodeGenPasses; CodeGenPasses.add( createTargetTransformInfoWrapperPass(TM.getTargetIRAnalysis())); // Add LibraryInfo. TargetLibraryInfoImpl TLII(TM.getTargetTriple(), TM.Options.VecLib); - if (DisableSimplifyLibCalls) + if (Config.DisableSimplifyLibCalls) TLII.disableAllFunctions(); CodeGenPasses.add(new TargetLibraryInfoWrapperPass(TLII)); @@ -50,8 +51,12 @@ runCodeGenPipelineLegacy(TargetMachine &TM, Module &M, raw_pwrite_stream &OS, CodeGenPasses.add( new RuntimeLibraryInfoWrapper(Options.MCOptions.ABIName, Options.VecLib)); + if (Config.SummaryIndex) + CodeGenPasses.add( + createImmutableModuleSummaryIndexWrapperPass(Config.SummaryIndex)); + if (TM.addPassesToEmitFile(CodeGenPasses, OS, DwoOS ? &DwoOS->os() : nullptr, - CGFT, DisableVerify)) + CGFT, Config.DisableVerify)) return createStringError("Failed to construct CodeGen pipeline"); CodeGenPasses.run(M); @@ -61,8 +66,8 @@ runCodeGenPipelineLegacy(TargetMachine &TM, Module &M, raw_pwrite_stream &OS, static Error runCodeGenPipelineNewPM(TargetMachine &TM, Module &M, raw_pwrite_stream &OS, std::unique_ptr<ToolOutputFile> &DwoOS, - CodeGenFileType CGFT, bool DisableVerify, - IntrusiveRefCntPtr<vfs::FileSystem> VFS) { + CodeGenFileType CGFT, + const CodeGenPipelineConfig &Config) { ModulePassManager MPM; MachineFunctionAnalysisManager MFAM; LoopAnalysisManager LAM; @@ -70,17 +75,21 @@ static Error runCodeGenPipelineNewPM(TargetMachine &TM, Module &M, CGSCCAnalysisManager CGAM; ModuleAnalysisManager MAM; CGPassBuilderOption Opt = getCGPassBuilderOption(); - Opt.DisableVerify = DisableVerify; + Opt.DisableVerify = Config.DisableVerify; MachineModuleInfo MMI(&TM); PassInstrumentationCallbacks PIC; PipelineTuningOptions PTOptions; TargetMachine *TMPointer = &TM; - PassBuilder PB(TMPointer, PTOptions, std::nullopt, &PIC, VFS); + // Only resolve the fallback once we know we need one: under clang's IO + // sandbox, calling vfs::getRealFileSystem() at all is fatal. + PassBuilder PB(TMPointer, PTOptions, std::nullopt, &PIC, + Config.VFS ? Config.VFS : vfs::getRealFileSystem()); - StandardInstrumentations SI(M.getContext(), /*DebugLogging=*/false); + StandardInstrumentations SI(M.getContext(), Config.DebugPassManager, + Config.VerifyEach); SI.registerCallbacks(PIC, &MAM); - TargetLibraryInfoImpl TLII(M.getTargetTriple()); + TargetLibraryInfoImpl TLII(M.getTargetTriple(), TM.Options.VecLib); FAM.registerPass([&] { return TargetLibraryAnalysis(TLII); }); MAM.registerPass([&] { return MachineModuleAnalysis(MMI); }); MAM.registerPass([&] { @@ -88,6 +97,11 @@ static Error runCodeGenPipelineNewPM(TargetMachine &TM, Module &M, return RuntimeLibraryAnalysis(Options.MCOptions.ABIName, Options.VecLib); }); + if (Config.SummaryIndex) + MAM.registerPass([&] { + return ImmutableModuleSummaryIndexAnalysis(Config.SummaryIndex); + }); + PB.registerModuleAnalyses(MAM); PB.registerCGSCCAnalyses(CGAM); PB.registerFunctionAnalyses(FAM); @@ -108,15 +122,11 @@ static Error runCodeGenPipelineNewPM(TargetMachine &TM, Module &M, Error llvm::runCodeGenPipeline(TargetMachine &TM, Module &M, raw_pwrite_stream &OS, std::unique_ptr<ToolOutputFile> &DwoOS, - CodeGenFileType CGFT, bool PrintPipelinePasses, - bool DisableVerify, bool DisableSimplifyLibCalls, - IntrusiveRefCntPtr<vfs::FileSystem> VFS) { + CodeGenFileType CGFT, + const CodeGenPipelineConfig &Config) { if (ForceNewPM == cl::boolOrDefault::BOU_TRUE || - (TM.shouldDefaultToNewPM() && - ForceNewPM != cl::boolOrDefault::BOU_FALSE)) { - return runCodeGenPipelineNewPM(TM, M, OS, DwoOS, CGFT, DisableVerify, VFS); - } + (TM.shouldDefaultToNewPM() && ForceNewPM != cl::boolOrDefault::BOU_FALSE)) + return runCodeGenPipelineNewPM(TM, M, OS, DwoOS, CGFT, Config); - return runCodeGenPipelineLegacy(TM, M, OS, DwoOS, CGFT, PrintPipelinePasses, - DisableVerify, DisableSimplifyLibCalls); + return runCodeGenPipelineLegacy(TM, M, OS, DwoOS, CGFT, Config); } diff --git a/llvm/test/CodeGen/AMDGPU/lto-lower-module-lds.ll b/llvm/test/CodeGen/AMDGPU/lto-lower-module-lds.ll index a846a7cc12e49..b81cc4ef3c9c0 100644 --- a/llvm/test/CodeGen/AMDGPU/lto-lower-module-lds.ll +++ b/llvm/test/CodeGen/AMDGPU/lto-lower-module-lds.ll @@ -27,11 +27,60 @@ ; First print will be from the New PM during the full LTO pipeline. ; Second print will be from the legacy PM during the CG pipeline. +; These will be updated when NPM becomes default for AMDGPU CG pipeline. ; CHECK: Running pass: AMDGPULowerModuleLDSPass on [module] ; CHECK: ModulePass Manager ; CHECK: Lower uses of LDS variables from non-kernel functions +; Test -force-new-pm-codegen=true. + +; ENABLE-NPM Default O0 +; RUN: opt -mtriple=amdgpu10.30-- %s -o %t.bc +; RUN: llvm-lto2 run -O0 -cg-opt-level 0 %t.bc -o %t.s -r %t.bc,test,px -force-new-pm-codegen=true -debug-pass-manager 2>&1 | FileCheck --check-prefix=ENABLE-NPM %s + +; ENABLE-NPM Unified O0 +; RUN: opt -unified-lto -thinlto-split-lto-unit -thinlto-bc -mtriple=amdgpu10.30-- %s -o %t.bc +; RUN: llvm-lto2 run -unified-lto=full -O0 -cg-opt-level 0 %t.bc -o %t.s -r %t.bc,test,px -force-new-pm-codegen=true -debug-pass-manager 2>&1 | FileCheck --check-prefix=ENABLE-NPM %s + +; ENABLE-NPM Default O2 +; RUN: opt -mtriple=amdgpu10.30-- %s -o %t.bc +; RUN: llvm-lto2 run -O2 -cg-opt-level 2 %t.bc -o %t.s -r %t.bc,test,px -force-new-pm-codegen=true -debug-pass-manager 2>&1 | FileCheck --check-prefix=ENABLE-NPM %s + +; ENABLE-NPM Unified O2 +; RUN: opt -unified-lto -thinlto-split-lto-unit -thinlto-bc -mtriple=amdgpu10.30-- %s -o %t.bc +; RUN: llvm-lto2 run -unified-lto=full -O2 -cg-opt-level 2 %t.bc -o %t.s -r %t.bc,test,px -force-new-pm-codegen=true -debug-pass-manager 2>&1 | FileCheck --check-prefix=ENABLE-NPM %s + +; ENABLE-NPM-NOT: ModulePass Manager +; ENABLE-NPM: Running pass: AMDGPULowerModuleLDSPass on [module] +; ENABLE-NPM: Running pass: SelectionDAGISelPass on test +; ENABLE-NPM: Running pass: PrologEpilogInserterPass on test +; ENABLE-NPM: Running pass: AMDGPUAsmPrinterPass on test + +; Test -force-new-pm-codegen=false drives the CodeGen pipeline +; with the legacy PM, regardless of the target default. + +; DISABLE-NPM Default O0 +; RUN: opt -mtriple=amdgpu10.30-- %s -o %t.bc +; RUN: llvm-lto2 run -O0 -cg-opt-level 0 %t.bc -o %t.s -r %t.bc,test,px -force-new-pm-codegen=false -debug-pass-manager -debug-pass=Structure 2>&1 | FileCheck --check-prefix=DISABLE-NPM %s + +; DISABLE-NPM Unified O0 +; RUN: opt -unified-lto -thinlto-split-lto-unit -thinlto-bc -mtriple=amdgpu10.30-- %s -o %t.bc +; RUN: llvm-lto2 run -unified-lto=full -O0 -cg-opt-level 0 %t.bc -o %t.s -r %t.bc,test,px -force-new-pm-codegen=false -debug-pass-manager -debug-pass=Structure 2>&1 | FileCheck --check-prefix=DISABLE-NPM %s + +; DISABLE-NPM Default O2 +; RUN: opt -mtriple=amdgpu10.30-- %s -o %t.bc +; RUN: llvm-lto2 run -O2 -cg-opt-level 2 %t.bc -o %t.s -r %t.bc,test,px -force-new-pm-codegen=false -debug-pass-manager -debug-pass=Structure 2>&1 | FileCheck --check-prefix=DISABLE-NPM %s + +; DISABLE-NPM Unified O2 +; RUN: opt -unified-lto -thinlto-split-lto-unit -thinlto-bc -mtriple=amdgpu10.30-- %s -o %t.bc +; RUN: llvm-lto2 run -unified-lto=full -O2 -cg-opt-level 2 %t.bc -o %t.s -r %t.bc,test,px -force-new-pm-codegen=false -debug-pass-manager -debug-pass=Structure 2>&1 | FileCheck --check-prefix=DISABLE-NPM %s + +; DISABLE-NPM: Running pass: AMDGPULowerModuleLDSPass on [module] +; DISABLE-NPM: ModulePass Manager +; DISABLE-NPM: Lower uses of LDS variables from non-kernel functions +; DISABLE-NPM-NOT: Running pass: SelectionDAGISelPass + @lds = internal unnamed_addr addrspace(3) global i32 poison, align 4 define amdgpu_kernel void @test() { _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
