Index: lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp =================================================================== --- lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp +++ lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp @@ -123,12 +123,47 @@ AsmPrinter::EmitFunctionEntryLabel(); } +static bool isModuleLinkage(const GlobalValue *GV) { + switch (GV->getLinkage()) { + case GlobalValue::InternalLinkage: + case GlobalValue::CommonLinkage: + return true; + case GlobalValue::ExternalLinkage: + return false; + default: llvm_unreachable("unknown linkage type"); + } +} + void AMDGPUAsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { const Module *M = GV->getParent(); if (Triple(M->getTargetTriple()).getOS() != Triple::AMDHSA || - !AMDGPU::isGroupSegment(GV)) - return AsmPrinter::EmitGlobalVariable(GV); + GV->isDeclaration() || AMDGPU::isReadOnlySegment(GV)) { + AsmPrinter::EmitGlobalVariable(GV); + return; + } + + // Group segment variables aren't emitted in HSA. + if (AMDGPU::isGroupSegment(GV)) + return; + + AMDGPUTargetStreamer *TS = + static_cast(OutStreamer->getTargetStreamer()); + if (isModuleLinkage(GV)) { + TS->EmitAMDGPUHsaModuleScopeGlobal(GV->getName()); + } else { + TS->EmitAMDGPUHsaProgramScopeGlobal(GV->getName()); + } + + const DataLayout &DL = getDataLayout(); + OutStreamer->PushSection(); + OutStreamer->SwitchSection( + getObjFileLowering().SectionForGlobal(GV, *Mang, TM)); + MCSymbol *GVSym = getSymbol(GV); + const Constant *C = GV->getInitializer(); + OutStreamer->EmitLabel(GVSym); + EmitGlobalConstant(DL, C); + OutStreamer->PopSection(); } bool AMDGPUAsmPrinter::runOnMachineFunction(MachineFunction &MF) { Index: lib/Target/AMDGPU/AMDGPUHSATargetObjectFile.h =================================================================== --- lib/Target/AMDGPU/AMDGPUHSATargetObjectFile.h +++ lib/Target/AMDGPU/AMDGPUHSATargetObjectFile.h @@ -22,6 +22,14 @@ namespace llvm { class AMDGPUHSATargetObjectFile final : public TargetLoweringObjectFileELF { +private: + MCSection *DataGlobalAgentSection; + MCSection *DataGlobalProgramSection; + + bool isAgentAllocationSection(const char *SectionName) const; + bool isAgentAllocation(const GlobalValue *GV) const; + bool isProgramAllocation(const GlobalValue *GV) const; + public: void Initialize(MCContext &Ctx, const TargetMachine &TM) override; Index: lib/Target/AMDGPU/AMDGPUHSATargetObjectFile.cpp =================================================================== --- lib/Target/AMDGPU/AMDGPUHSATargetObjectFile.cpp +++ lib/Target/AMDGPU/AMDGPUHSATargetObjectFile.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "AMDGPUHSATargetObjectFile.h" +#include "AMDGPU.h" #include "Utils/AMDGPUBaseInfo.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCSectionELF.h" @@ -22,6 +23,29 @@ TextSection = AMDGPU::getHSATextSection(Ctx); + DataGlobalAgentSection = AMDGPU::getHSADataGlobalAgentSection(Ctx); + DataGlobalProgramSection = AMDGPU::getHSADataGlobalProgramSection(Ctx); + +} + +bool AMDGPUHSATargetObjectFile::isAgentAllocationSection( + const char *SectionName) const { + return cast(DataGlobalAgentSection) + ->getSectionName() + .equals(SectionName); +} + +bool AMDGPUHSATargetObjectFile::isAgentAllocation(const GlobalValue *GV) const { + // Read-only segments can only have agent allocation. + return AMDGPU::isReadOnlySegment(GV) || + (AMDGPU::isGlobalSegment(GV) && GV->hasSection() && + isAgentAllocationSection(GV->getSection())); +} + +bool AMDGPUHSATargetObjectFile::isProgramAllocation( + const GlobalValue *GV) const { + // The default for global segments is program allocation. + return AMDGPU::isGlobalSegment(GV) && !isAgentAllocation(GV); } MCSection *AMDGPUHSATargetObjectFile::SelectSectionForGlobal( @@ -31,5 +55,11 @@ if (Kind.isText() && !GV->hasComdat()) return getTextSection(); + if (AMDGPU::isGlobalSegment(GV) && isAgentAllocation(GV)) + return DataGlobalAgentSection; + + if (AMDGPU::isGlobalSegment(GV) && isProgramAllocation(GV)) + return DataGlobalProgramSection; + return TargetLoweringObjectFileELF::SelectSectionForGlobal(GV, Kind, Mang, TM); } Index: lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp =================================================================== --- lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp +++ lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp @@ -358,6 +358,10 @@ bool ParseSectionDirectiveHSAText(); bool subtargetHasRegister(const MCRegisterInfo &MRI, unsigned RegNo) const; bool ParseDirectiveAMDGPUHsaKernel(); + bool ParseDirectiveAMDGPUHsaModuleGlobal(); + bool ParseDirectiveAMDGPUHsaProgramGlobal(); + bool ParseSectionDirectiveHSADataGlobalAgent(); + bool ParseSectionDirectiveHSADataGlobalProgram(); public: public: @@ -957,6 +961,40 @@ return false; } +bool AMDGPUAsmParser::ParseDirectiveAMDGPUHsaModuleGlobal() { + if (getLexer().isNot(AsmToken::Identifier)) + return TokError("expected symbol name"); + + StringRef GlobalName = Parser.getTok().getIdentifier(); + + getTargetStreamer().EmitAMDGPUHsaModuleScopeGlobal(GlobalName); + Lex(); + return false; +} + +bool AMDGPUAsmParser::ParseDirectiveAMDGPUHsaProgramGlobal() { + if (getLexer().isNot(AsmToken::Identifier)) + return TokError("expected symbol name"); + + StringRef GlobalName = Parser.getTok().getIdentifier(); + + getTargetStreamer().EmitAMDGPUHsaProgramScopeGlobal(GlobalName); + Lex(); + return false; +} + +bool AMDGPUAsmParser::ParseSectionDirectiveHSADataGlobalAgent() { + getParser().getStreamer().SwitchSection( + AMDGPU::getHSADataGlobalAgentSection(getContext())); + return false; +} + +bool AMDGPUAsmParser::ParseSectionDirectiveHSADataGlobalProgram() { + getParser().getStreamer().SwitchSection( + AMDGPU::getHSADataGlobalProgramSection(getContext())); + return false; +} + bool AMDGPUAsmParser::ParseDirective(AsmToken DirectiveID) { StringRef IDVal = DirectiveID.getString(); @@ -975,6 +1013,18 @@ if (IDVal == ".amdgpu_hsa_kernel") return ParseDirectiveAMDGPUHsaKernel(); + if (IDVal == ".amdgpu_hsa_module_global") + return ParseDirectiveAMDGPUHsaModuleGlobal(); + + if (IDVal == ".amdgpu_hsa_program_global") + return ParseDirectiveAMDGPUHsaProgramGlobal(); + + if (IDVal == ".hsadata_global_agent") + return ParseSectionDirectiveHSADataGlobalAgent(); + + if (IDVal == ".hsadata_global_program") + return ParseSectionDirectiveHSADataGlobalProgram(); + return true; } Index: lib/Target/AMDGPU/MCTargetDesc/AMDGPUMCAsmInfo.cpp =================================================================== --- lib/Target/AMDGPU/MCTargetDesc/AMDGPUMCAsmInfo.cpp +++ lib/Target/AMDGPU/MCTargetDesc/AMDGPUMCAsmInfo.cpp @@ -36,6 +36,7 @@ } bool AMDGPUMCAsmInfo::shouldOmitSectionDirective(StringRef SectionName) const { - return SectionName == ".hsatext" || + return SectionName == ".hsatext" || SectionName == ".hsadata_global_agent" || + SectionName == ".hsadata_global_program" || MCAsmInfo::shouldOmitSectionDirective(SectionName); } Index: lib/Target/AMDGPU/MCTargetDesc/AMDGPUTargetStreamer.h =================================================================== --- lib/Target/AMDGPU/MCTargetDesc/AMDGPUTargetStreamer.h +++ lib/Target/AMDGPU/MCTargetDesc/AMDGPUTargetStreamer.h @@ -32,6 +32,10 @@ virtual void EmitAMDKernelCodeT(const amd_kernel_code_t &Header) = 0; virtual void EmitAMDGPUSymbolType(StringRef SymbolName, unsigned Type) = 0; + + virtual void EmitAMDGPUHsaModuleScopeGlobal(StringRef GlobalName) = 0; + + virtual void EmitAMDGPUHsaProgramScopeGlobal(StringRef GlobalName) = 0; }; class AMDGPUTargetAsmStreamer : public AMDGPUTargetStreamer { @@ -48,6 +52,10 @@ void EmitAMDKernelCodeT(const amd_kernel_code_t &Header) override; void EmitAMDGPUSymbolType(StringRef SymbolName, unsigned Type) override; + + void EmitAMDGPUHsaModuleScopeGlobal(StringRef GlobalName) override; + + void EmitAMDGPUHsaProgramScopeGlobal(StringRef GlobalName) override; }; class AMDGPUTargetELFStreamer : public AMDGPUTargetStreamer { @@ -80,6 +88,10 @@ void EmitAMDKernelCodeT(const amd_kernel_code_t &Header) override; void EmitAMDGPUSymbolType(StringRef SymbolName, unsigned Type) override; + + void EmitAMDGPUHsaModuleScopeGlobal(StringRef GlobalName) override; + + void EmitAMDGPUHsaProgramScopeGlobal(StringRef GlobalName) override; }; } Index: lib/Target/AMDGPU/MCTargetDesc/AMDGPUTargetStreamer.cpp =================================================================== --- lib/Target/AMDGPU/MCTargetDesc/AMDGPUTargetStreamer.cpp +++ lib/Target/AMDGPU/MCTargetDesc/AMDGPUTargetStreamer.cpp @@ -231,6 +231,16 @@ } } +void AMDGPUTargetAsmStreamer::EmitAMDGPUHsaModuleScopeGlobal( + StringRef GlobalName) { + OS << "\t.amdgpu_hsa_module_global " << GlobalName << '\n'; +} + +void AMDGPUTargetAsmStreamer::EmitAMDGPUHsaProgramScopeGlobal( + StringRef GlobalName) { + OS << "\t.amdgpu_hsa_program_global " << GlobalName << '\n'; +} + //===----------------------------------------------------------------------===// // AMDGPUTargetELFStreamer //===----------------------------------------------------------------------===// @@ -316,3 +326,21 @@ getStreamer().getContext().getOrCreateSymbol(SymbolName)); Symbol->setType(ELF::STT_AMDGPU_HSA_KERNEL); } + +void AMDGPUTargetELFStreamer::EmitAMDGPUHsaModuleScopeGlobal( + StringRef GlobalName) { + + MCSymbolELF *Symbol = cast( + getStreamer().getContext().getOrCreateSymbol(GlobalName)); + Symbol->setType(ELF::STT_OBJECT); + Symbol->setBinding(ELF::STB_LOCAL); +} + +void AMDGPUTargetELFStreamer::EmitAMDGPUHsaProgramScopeGlobal( + StringRef GlobalName) { + + MCSymbolELF *Symbol = cast( + getStreamer().getContext().getOrCreateSymbol(GlobalName)); + Symbol->setType(ELF::STT_OBJECT); + Symbol->setBinding(ELF::STB_GLOBAL); +} Index: lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h =================================================================== --- lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h +++ lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h @@ -32,7 +32,13 @@ const FeatureBitset &Features); MCSection *getHSATextSection(MCContext &Ctx); +MCSection *getHSADataGlobalAgentSection(MCContext &Ctx); + +MCSection *getHSADataGlobalProgramSection(MCContext &Ctx); + bool isGroupSegment(const GlobalValue *GV); +bool isGlobalSegment(const GlobalValue *GV); +bool isReadOnlySegment(const GlobalValue *GV); } // end namespace AMDGPU } // end namespace llvm Index: lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp =================================================================== --- lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp +++ lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp @@ -68,9 +68,30 @@ ELF::SHF_AMDGPU_HSA_CODE); } +MCSection *getHSADataGlobalAgentSection(MCContext &Ctx) { + return Ctx.getELFSection(".hsadata_global_agent", ELF::SHT_PROGBITS, + ELF::SHF_ALLOC | ELF::SHF_WRITE | + ELF::SHF_AMDGPU_HSA_GLOBAL | + ELF::SHF_AMDGPU_HSA_AGENT); +} + +MCSection *getHSADataGlobalProgramSection(MCContext &Ctx) { + return Ctx.getELFSection(".hsadata_global_program", ELF::SHT_PROGBITS, + ELF::SHF_ALLOC | ELF::SHF_WRITE | + ELF::SHF_AMDGPU_HSA_GLOBAL); +} + bool isGroupSegment(const GlobalValue *GV) { return GV->getType()->getAddressSpace() == AMDGPUAS::LOCAL_ADDRESS; } +bool isGlobalSegment(const GlobalValue *GV) { + return GV->getType()->getAddressSpace() == AMDGPUAS::GLOBAL_ADDRESS; +} + +bool isReadOnlySegment(const GlobalValue *GV) { + return GV->getType()->getAddressSpace() == AMDGPUAS::CONSTANT_ADDRESS; +} + } // End namespace AMDGPU } // End namespace llvm Index: test/CodeGen/AMDGPU/hsa-globals.ll =================================================================== --- /dev/null +++ test/CodeGen/AMDGPU/hsa-globals.ll @@ -0,0 +1,105 @@ +; RUN: llc < %s -mtriple=amdgcn--amdhsa -mcpu=kaveri | FileCheck --check-prefix=ASM %s +; RUN: llc < %s -mtriple=amdgcn--amdhsa -mcpu=kaveri | llvm-mc -filetype=obj -triple amdgcn--amdhsa -mcpu=kaveri | llvm-readobj -symbols -s | FileCheck %s --check-prefix=ELF + +@internal_global_program = internal addrspace(1) global i32 0 +@common_global_program = common addrspace(1) global i32 0 +@external_global_program = addrspace(1) global i32 0 + +@internal_global_agent = internal addrspace(1) global i32 0, section ".hsadata_global_agent" +@common_global_agent = common addrspace(1) global i32 0, section ".hsadata_global_agent" +@external_global_agent = addrspace(1) global i32 0, section ".hsadata_global_agent" + +define void @test() { + ret void +} + +; ASM: .amdgpu_hsa_module_global internal_global +; ASM: .hsadata_global_program +; ASM: internal_global_program: +; ASM: .long 0 + +; ASM: .amdgpu_hsa_module_global common_global +; ASM: .hsadata_global_program +; ASM: common_global_program: +; ASM: .long 0 + +; ASM: .amdgpu_hsa_program_global external_global +; ASM: .hsadata_global_program +; ASM: external_global_program: +; ASM: .long 0 + +; ASM: .amdgpu_hsa_module_global internal_global +; ASM: .hsadata_global_agent +; ASM: internal_global_agent: +; ASM: .long 0 + +; ASM: .amdgpu_hsa_module_global common_global +; ASM: .hsadata_global_agent +; ASM: common_global_agent: +; ASM: .long 0 + +; ASM: .amdgpu_hsa_program_global external_global +; ASM: .hsadata_global_agent +; ASM: external_global_agent: +; ASM: .long 0 + +; ELF: Section { +; ELF: Name: .hsadata_global_program +; ELF: Type: SHT_PROGBITS (0x1) +; ELF: Flags [ (0x100003) +; ELF: SHF_ALLOC (0x2) +; ELF: SHF_AMDGPU_HSA_GLOBAL (0x100000) +; ELF: SHF_WRITE (0x1) +; ELF: ] +; ELF: } + +; ELF: Section { +; ELF: Name: .hsadata_global_agent +; ELF: Type: SHT_PROGBITS (0x1) +; ELF: Flags [ (0x900003) +; ELF: SHF_ALLOC (0x2) +; ELF: SHF_AMDGPU_HSA_AGENT (0x800000) +; ELF: SHF_AMDGPU_HSA_GLOBAL (0x100000) +; ELF: SHF_WRITE (0x1) +; ELF: ] +; ELF: } + +; ELF: Symbol { +; ELF: Name: common_global_agent +; ELF: Binding: Local +; ELF: Section: .hsadata_global_agent +; ELF: } + +; ELF: Symbol { +; ELF: Name: common_global_program +; ELF: Binding: Local +; ELF: Section: .hsadata_global_program +; ELF: } + +; ELF: Symbol { +; ELF: Name: internal_global_agent +; ELF: Binding: Local +; ELF: Type: Object +; ELF: Section: .hsadata_global_agent +; ELF: } + +; ELF: Symbol { +; ELF: Name: internal_global_program +; ELF: Binding: Local +; ELF: Type: Object +; ELF: Section: .hsadata_global_program +; ELF: } + +; ELF: Symbol { +; ELF: Name: external_global_agent +; ELF: Binding: Global +; ELF: Type: Object +; ELF: Section: .hsadata_global_agent +; ELF: } + +; ELF: Symbol { +; ELF: Name: external_global_program +; ELF: Binding: Global +; ELF: Type: Object +; ELF: Section: .hsadata_global_program +; ELF: }