Index: llvm/lib/Target/AMDGPU/AMDGPU.h =================================================================== --- llvm/lib/Target/AMDGPU/AMDGPU.h +++ llvm/lib/Target/AMDGPU/AMDGPU.h @@ -91,9 +91,9 @@ void initializeAMDGPULowerIntrinsicsPass(PassRegistry &); extern char &AMDGPULowerIntrinsicsID; -ModulePass *createAMDGPUCtorDtorLoweringPass(); -void initializeAMDGPUCtorDtorLoweringPass(PassRegistry &); -extern char &AMDGPUCtorDtorLoweringID; +ModulePass *createAMDGPUCtorDtorLoweringLegacyPass(); +void initializeAMDGPUCtorDtorLoweringLegacyPass(PassRegistry &); +extern char &AMDGPUCtorDtorLoweringLegacyPassID; FunctionPass *createAMDGPULowerKernelArgumentsPass(); void initializeAMDGPULowerKernelArgumentsPass(PassRegistry &); Index: llvm/lib/Target/AMDGPU/AMDGPUCtorDtorLowering.h =================================================================== --- /dev/null +++ llvm/lib/Target/AMDGPU/AMDGPUCtorDtorLowering.h @@ -0,0 +1,26 @@ +//===-- AMDGPUCtorDtorLowering.h --------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_AMDGPU_AMDGPUCTORDTORLOWERING_H +#define LLVM_LIB_TARGET_AMDGPU_AMDGPUCTORDTORLOWERING_H + +#include "llvm/IR/PassManager.h" + +namespace llvm { +class Module; + +/// Lower llvm.global_ctors and llvm.global_dtors to special kernels. +class AMDGPUCtorDtorLoweringPass + : public PassInfoMixin { +public: + PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); +}; + +} // namespace llvm + +#endif // LLVM_LIB_TARGET_AMDGPU_AMDGPUCTORDTORLOWERING_H Index: llvm/lib/Target/AMDGPU/AMDGPUCtorDtorLowering.cpp =================================================================== --- llvm/lib/Target/AMDGPU/AMDGPUCtorDtorLowering.cpp +++ llvm/lib/Target/AMDGPU/AMDGPUCtorDtorLowering.cpp @@ -10,6 +10,7 @@ /// This pass creates a unified init and fini kernel with the required metadata //===----------------------------------------------------------------------===// +#include "AMDGPUCtorDtorLowering.h" #include "AMDGPU.h" #include "llvm/IR/Constants.h" #include "llvm/IR/Function.h" @@ -25,69 +26,80 @@ #define DEBUG_TYPE "amdgpu-lower-ctor-dtor" namespace { -class AMDGPUCtorDtorLowering final : public ModulePass { - bool runOnModule(Module &M) override; -public: - Function *createInitOrFiniKernelFunction(Module &M, bool IsCtor) { - StringRef InitOrFiniKernelName = "amdgcn.device.init"; - if (!IsCtor) - InitOrFiniKernelName = "amdgcn.device.fini"; - - Function *InitOrFiniKernel = Function::createWithDefaultAttr( - FunctionType::get(Type::getVoidTy(M.getContext()), false), - GlobalValue::ExternalLinkage, 0, InitOrFiniKernelName, &M); - BasicBlock *InitOrFiniKernelBB = - BasicBlock::Create(M.getContext(), "", InitOrFiniKernel); - ReturnInst::Create(M.getContext(), InitOrFiniKernelBB); - - InitOrFiniKernel->setCallingConv(CallingConv::AMDGPU_KERNEL); - if (IsCtor) - InitOrFiniKernel->addFnAttr("device-init"); - else - InitOrFiniKernel->addFnAttr("device-fini"); - return InitOrFiniKernel; - } - - bool createInitOrFiniKernel(Module &M, StringRef GlobalName, bool IsCtor) { - GlobalVariable *GV = M.getGlobalVariable(GlobalName); - if (!GV || !GV->hasInitializer()) - return false; - ConstantArray *GA = dyn_cast(GV->getInitializer()); - if (!GA || GA->getNumOperands() == 0) - return false; +static Function *createInitOrFiniKernelFunction(Module &M, bool IsCtor) { + StringRef InitOrFiniKernelName = "amdgcn.device.init"; + if (!IsCtor) + InitOrFiniKernelName = "amdgcn.device.fini"; + + Function *InitOrFiniKernel = Function::createWithDefaultAttr( + FunctionType::get(Type::getVoidTy(M.getContext()), false), + GlobalValue::ExternalLinkage, 0, InitOrFiniKernelName, &M); + BasicBlock *InitOrFiniKernelBB = + BasicBlock::Create(M.getContext(), "", InitOrFiniKernel); + ReturnInst::Create(M.getContext(), InitOrFiniKernelBB); + + InitOrFiniKernel->setCallingConv(CallingConv::AMDGPU_KERNEL); + if (IsCtor) + InitOrFiniKernel->addFnAttr("device-init"); + else + InitOrFiniKernel->addFnAttr("device-fini"); + return InitOrFiniKernel; +} - Function *InitOrFiniKernel = createInitOrFiniKernelFunction(M, IsCtor); - IRBuilder<> IRB(InitOrFiniKernel->getEntryBlock().getTerminator()); +static bool createInitOrFiniKernel(Module &M, StringRef GlobalName, + bool IsCtor) { + GlobalVariable *GV = M.getGlobalVariable(GlobalName); + if (!GV || !GV->hasInitializer()) + return false; + ConstantArray *GA = dyn_cast(GV->getInitializer()); + if (!GA || GA->getNumOperands() == 0) + return false; - FunctionType *ConstructorTy = InitOrFiniKernel->getFunctionType(); + Function *InitOrFiniKernel = createInitOrFiniKernelFunction(M, IsCtor); + IRBuilder<> IRB(InitOrFiniKernel->getEntryBlock().getTerminator()); - for (Value *V : GA->operands()) { - auto *CS = cast(V); - IRB.CreateCall(ConstructorTy, CS->getOperand(1)); - } + FunctionType *ConstructorTy = InitOrFiniKernel->getFunctionType(); - appendToUsed(M, {InitOrFiniKernel}); - return true; + for (Value *V : GA->operands()) { + auto *CS = cast(V); + IRB.CreateCall(ConstructorTy, CS->getOperand(1)); } - static char ID; - AMDGPUCtorDtorLowering() : ModulePass(ID) {} -}; -} // End anonymous namespace - -char AMDGPUCtorDtorLowering::ID = 0; -char &llvm::AMDGPUCtorDtorLoweringID = AMDGPUCtorDtorLowering::ID; -INITIALIZE_PASS(AMDGPUCtorDtorLowering, DEBUG_TYPE, - "Lower ctors and dtors for AMDGPU", false, false) - -ModulePass *llvm::createAMDGPUCtorDtorLoweringPass() { - return new AMDGPUCtorDtorLowering(); + appendToUsed(M, {InitOrFiniKernel}); + return true; } -bool AMDGPUCtorDtorLowering::runOnModule(Module &M) { +static bool lowerCtorsAndDtors(Module &M) { bool Modified = false; Modified |= createInitOrFiniKernel(M, "llvm.global_ctors", /*IsCtor =*/true); Modified |= createInitOrFiniKernel(M, "llvm.global_dtors", /*IsCtor =*/false); return Modified; } + +class AMDGPUCtorDtorLoweringLegacy final : public ModulePass { +public: + static char ID; + AMDGPUCtorDtorLoweringLegacy() : ModulePass(ID) {} + bool runOnModule(Module &M) override { + return lowerCtorsAndDtors(M); + } +}; + +} // End anonymous namespace + +PreservedAnalyses AMDGPUCtorDtorLoweringPass::run(Module &M, + ModuleAnalysisManager &AM) { + lowerCtorsAndDtors(M); + return PreservedAnalyses::all(); +} + +char AMDGPUCtorDtorLoweringLegacy::ID = 0; +char &llvm::AMDGPUCtorDtorLoweringLegacyPassID = + AMDGPUCtorDtorLoweringLegacy::ID; +INITIALIZE_PASS(AMDGPUCtorDtorLoweringLegacy, DEBUG_TYPE, + "Lower ctors and dtors for AMDGPU", false, false) + +ModulePass *llvm::createAMDGPUCtorDtorLoweringLegacyPass() { + return new AMDGPUCtorDtorLoweringLegacy(); +} Index: llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp =================================================================== --- llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp +++ llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp @@ -15,6 +15,7 @@ #include "AMDGPUTargetMachine.h" #include "AMDGPU.h" #include "AMDGPUAliasAnalysis.h" +#include "AMDGPUCtorDtorLowering.h" #include "AMDGPUExportClustering.h" #include "AMDGPUIGroupLP.h" #include "AMDGPUMacroFusion.h" @@ -355,7 +356,7 @@ initializeSIOptimizeExecMaskingPreRAPass(*PR); initializeSIOptimizeVGPRLiveRangePass(*PR); initializeSILoadStoreOptimizerPass(*PR); - initializeAMDGPUCtorDtorLoweringPass(*PR); + initializeAMDGPUCtorDtorLoweringLegacyPass(*PR); initializeAMDGPUAlwaysInlinePass(*PR); initializeAMDGPUAttributorPass(*PR); initializeAMDGPUAnnotateKernelFeaturesPass(*PR); @@ -607,6 +608,10 @@ PM.addPass(AMDGPULowerModuleLDSPass()); return true; } + if (PassName == "amdgpu-lower-ctor-dtor") { + PM.addPass(AMDGPUCtorDtorLoweringPass()); + return true; + } return false; }); PB.registerPipelineParsingCallback( @@ -950,7 +955,7 @@ disablePass(&PatchableFunctionID); addPass(createAMDGPUPrintfRuntimeBinding()); - addPass(createAMDGPUCtorDtorLoweringPass()); + addPass(createAMDGPUCtorDtorLoweringLegacyPass()); // A call to propagate attributes pass in the backend in case opt was not run. addPass(createAMDGPUPropagateAttributesEarlyPass(&TM)); Index: llvm/test/CodeGen/AMDGPU/lower-ctor-dtor.ll =================================================================== --- llvm/test/CodeGen/AMDGPU/lower-ctor-dtor.ll +++ llvm/test/CodeGen/AMDGPU/lower-ctor-dtor.ll @@ -1,4 +1,5 @@ ; RUN: opt -S -mtriple=amdgcn-- -amdgpu-lower-ctor-dtor < %s | FileCheck %s +; RUN: opt -S -mtriple=amdgcn-- -passes=amdgpu-lower-ctor-dtor < %s | FileCheck %s ; RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx700 -filetype=obj -o - < %s | llvm-readelf -s - 2>&1 | FileCheck %s -check-prefix=CHECK-VIS @llvm.global_ctors = appending addrspace(1) global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 1, void ()* @foo, i8* null }] @@ -24,4 +25,4 @@ } ; CHECK: attributes #0 = { "device-init" } -; CHECK: attributes #1 = { "device-fini" } +; CHECK: attributes #1 = { "device-fini" }