Skip to content

Commit f0fb4b9

Browse files
committed
[LLVM] Add support for printing and parsing symbolic address spaces
1 parent 5c26015 commit f0fb4b9

File tree

7 files changed

+185
-40
lines changed

7 files changed

+185
-40
lines changed
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// Address space definitions for NVPTX target.
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef LLVM_TARGETPARSER_NVPTX_ADDRESS_SPACES_H
14+
#define LLVM_TARGETPARSER_NVPTX_ADDRESS_SPACES_H
15+
16+
namespace llvm::NVPTX {
17+
18+
using AddressSpaceUnderlyingType = unsigned int;
19+
enum AddressSpace : AddressSpaceUnderlyingType {
20+
Generic = 0,
21+
Global = 1,
22+
Shared = 3,
23+
Const = 4,
24+
Local = 5,
25+
SharedCluster = 7,
26+
27+
// NVPTX Backend Private:
28+
Param = 101
29+
};
30+
31+
} // namespace llvm::NVPTX
32+
33+
#endif // LLVM_TARGETPARSER_NVPTX_ADDRESS_SPACES_H

llvm/include/llvm/TargetParser/Triple.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1362,6 +1362,9 @@ class Triple {
13621362
/// Compute the LLVM IR data layout string based on the triple. Some targets
13631363
/// customize the layout based on the ABIName string.
13641364
LLVM_ABI std::string computeDataLayout(StringRef ABIName = "") const;
1365+
1366+
LLVM_ABI StringRef getAddressSpaceName(unsigned AS) const;
1367+
LLVM_ABI std::optional<unsigned> getAddressSpaceNumber(StringRef Name) const;
13651368
};
13661369

13671370
} // End llvm namespace

llvm/lib/AsmParser/LLParser.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1965,6 +1965,9 @@ bool LLParser::parseOptionalAddrSpace(unsigned &AddrSpace, unsigned DefaultAS) {
19651965
AddrSpace = M->getDataLayout().getDefaultGlobalsAddressSpace();
19661966
} else if (AddrSpaceStr == "P") {
19671967
AddrSpace = M->getDataLayout().getProgramAddressSpace();
1968+
} else if (std::optional<unsigned> AS =
1969+
M->getTargetTriple().getAddressSpaceNumber(AddrSpaceStr)) {
1970+
AddrSpace = *AS;
19681971
} else {
19691972
return tokError("invalid symbolic addrspace '" + AddrSpaceStr + "'");
19701973
}

llvm/lib/IR/AsmWriter.cpp

Lines changed: 39 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -543,7 +543,8 @@ namespace {
543543

544544
class TypePrinting {
545545
public:
546-
TypePrinting(const Module *M = nullptr) : DeferredM(M) {}
546+
TypePrinting(const Module *M = nullptr)
547+
: M(M), TypesIncorporated(M == nullptr) {}
547548

548549
TypePrinting(const TypePrinting &) = delete;
549550
TypePrinting &operator=(const TypePrinting &) = delete;
@@ -564,7 +565,8 @@ class TypePrinting {
564565
void incorporateTypes();
565566

566567
/// A module to process lazily when needed. Set to nullptr as soon as used.
567-
const Module *DeferredM;
568+
const Module *M;
569+
bool TypesIncorporated;
568570

569571
TypeFinder NamedTypes;
570572

@@ -605,11 +607,11 @@ bool TypePrinting::empty() {
605607
}
606608

607609
void TypePrinting::incorporateTypes() {
608-
if (!DeferredM)
610+
if (TypesIncorporated)
609611
return;
610612

611-
NamedTypes.run(*DeferredM, false);
612-
DeferredM = nullptr;
613+
NamedTypes.run(*M, false);
614+
TypesIncorporated = true;
613615

614616
// The list of struct types we got back includes all the struct types, split
615617
// the unnamed ones out to a numbering and remove the anonymous structs.
@@ -630,6 +632,20 @@ void TypePrinting::incorporateTypes() {
630632
NamedTypes.erase(NextToUse, NamedTypes.end());
631633
}
632634

635+
static void printAddressSpace(const Module *M, unsigned AS, raw_ostream &OS,
636+
StringRef Prefix = " ", StringRef Suffix = "",
637+
bool ForcePrint = false) {
638+
if (AS == 0 && !ForcePrint)
639+
return;
640+
OS << Prefix << "addrspace(";
641+
StringRef ASName = M ? M->getTargetTriple().getAddressSpaceName(AS) : "";
642+
if (!ASName.empty())
643+
OS << "\"" << ASName << "\"";
644+
else
645+
OS << AS;
646+
OS << ")" << Suffix;
647+
}
648+
633649
/// Write the specified type to the specified raw_ostream, making use of type
634650
/// names or up references to shorten the type name where possible.
635651
void TypePrinting::print(Type *Ty, raw_ostream &OS) {
@@ -686,8 +702,7 @@ void TypePrinting::print(Type *Ty, raw_ostream &OS) {
686702
case Type::PointerTyID: {
687703
PointerType *PTy = cast<PointerType>(Ty);
688704
OS << "ptr";
689-
if (unsigned AddressSpace = PTy->getAddressSpace())
690-
OS << " addrspace(" << AddressSpace << ')';
705+
printAddressSpace(M, PTy->getAddressSpace(), OS);
691706
return;
692707
}
693708
case Type::ArrayTyID: {
@@ -3896,10 +3911,10 @@ void AssemblyWriter::printGlobal(const GlobalVariable *GV) {
38963911
printThreadLocalModel(GV->getThreadLocalMode(), Out);
38973912
StringRef UA = getUnnamedAddrEncoding(GV->getUnnamedAddr());
38983913
if (!UA.empty())
3899-
Out << UA << ' ';
3914+
Out << UA << ' ';
39003915

3901-
if (unsigned AddressSpace = GV->getType()->getAddressSpace())
3902-
Out << "addrspace(" << AddressSpace << ") ";
3916+
printAddressSpace(GV->getParent(), GV->getType()->getAddressSpace(), Out,
3917+
/*Prefix=*/"", /*Suffix=*/" ");
39033918
if (GV->isExternallyInitialized()) Out << "externally_initialized ";
39043919
Out << (GV->isConstant() ? "constant " : "global ");
39053920
TypePrinter.print(GV->getValueType(), Out);
@@ -4174,9 +4189,10 @@ void AssemblyWriter::printFunction(const Function *F) {
41744189
// a module with a non-zero program address space or if there is no valid
41754190
// Module* so that the file can be parsed without the datalayout string.
41764191
const Module *Mod = F->getParent();
4177-
if (F->getAddressSpace() != 0 || !Mod ||
4178-
Mod->getDataLayout().getProgramAddressSpace() != 0)
4179-
Out << " addrspace(" << F->getAddressSpace() << ")";
4192+
bool ForcePrintAddressSpace =
4193+
!Mod || Mod->getDataLayout().getProgramAddressSpace() != 0;
4194+
printAddressSpace(Mod, F->getAddressSpace(), Out, /*Prefix=*/" ",
4195+
/*Suffix=*/"", ForcePrintAddressSpace);
41804196
if (Attrs.hasFnAttrs())
41814197
Out << " #" << Machine.getAttributeGroupSlot(Attrs.getFnAttrs());
41824198
if (F->hasSection()) {
@@ -4358,17 +4374,14 @@ static void maybePrintCallAddrSpace(const Value *Operand, const Instruction *I,
43584374
return;
43594375
}
43604376
unsigned CallAddrSpace = Operand->getType()->getPointerAddressSpace();
4361-
bool PrintAddrSpace = CallAddrSpace != 0;
4362-
if (!PrintAddrSpace) {
4363-
const Module *Mod = getModuleFromVal(I);
4364-
// We also print it if it is zero but not equal to the program address space
4365-
// or if we can't find a valid Module* to make it possible to parse
4366-
// the resulting file even without a datalayout string.
4367-
if (!Mod || Mod->getDataLayout().getProgramAddressSpace() != 0)
4368-
PrintAddrSpace = true;
4369-
}
4370-
if (PrintAddrSpace)
4371-
Out << " addrspace(" << CallAddrSpace << ")";
4377+
const Module *Mod = getModuleFromVal(I);
4378+
// We also print it if it is zero but not equal to the program address space
4379+
// or if we can't find a valid Module* to make it possible to parse
4380+
// the resulting file even without a datalayout string.
4381+
bool ForcePrintAddrSpace =
4382+
!Mod || Mod->getDataLayout().getProgramAddressSpace() != 0;
4383+
printAddressSpace(Mod, CallAddrSpace, Out, /*Prefix=*/" ", /*Suffix=*/"",
4384+
ForcePrintAddrSpace);
43724385
}
43734386

43744387
// This member is called for each Instruction in a function..
@@ -4735,9 +4748,8 @@ void AssemblyWriter::printInstruction(const Instruction &I) {
47354748
Out << ", align " << A->value();
47364749
}
47374750

4738-
unsigned AddrSpace = AI->getAddressSpace();
4739-
if (AddrSpace != 0)
4740-
Out << ", addrspace(" << AddrSpace << ')';
4751+
printAddressSpace(AI->getModule(), AI->getAddressSpace(), Out,
4752+
/*Prefix=*/", ");
47414753
} else if (isa<CastInst>(I)) {
47424754
if (Operand) {
47434755
Out << ' ';

llvm/lib/Target/NVPTX/NVPTX.h

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
#include "llvm/Support/AtomicOrdering.h"
2121
#include "llvm/Support/CodeGen.h"
2222
#include "llvm/Target/TargetMachine.h"
23+
#include "llvm/TargetParser/NVPTXAddressSpaces.h"
24+
2325
namespace llvm {
2426
class FunctionPass;
2527
class MachineFunctionPass;
@@ -176,19 +178,6 @@ enum Scope : ScopeUnderlyingType {
176178
LASTSCOPE = DefaultDevice
177179
};
178180

179-
using AddressSpaceUnderlyingType = unsigned int;
180-
enum AddressSpace : AddressSpaceUnderlyingType {
181-
Generic = 0,
182-
Global = 1,
183-
Shared = 3,
184-
Const = 4,
185-
Local = 5,
186-
SharedCluster = 7,
187-
188-
// NVPTX Backend Private:
189-
Param = 101
190-
};
191-
192181
namespace PTXLdStInstCode {
193182
enum FromType { Unsigned = 0, Signed, Float, Untyped };
194183
} // namespace PTXLdStInstCode

llvm/lib/TargetParser/Triple.cpp

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "llvm/TargetParser/ARMTargetParser.h"
1818
#include "llvm/TargetParser/ARMTargetParserCommon.h"
1919
#include "llvm/TargetParser/Host.h"
20+
#include "llvm/TargetParser/NVPTXAddressSpaces.h"
2021
#include <cassert>
2122
#include <cstring>
2223
using namespace llvm;
@@ -2361,6 +2362,56 @@ ExceptionHandling Triple::getDefaultExceptionHandling() const {
23612362
return ExceptionHandling::None;
23622363
}
23632364

2365+
static StringRef getNVPTXAddressSpaceName(unsigned AS) {
2366+
switch (AS) {
2367+
case NVPTX::Generic:
2368+
return "generic";
2369+
case NVPTX::Global:
2370+
return "global";
2371+
case NVPTX::Shared:
2372+
return "shared";
2373+
case NVPTX::Const:
2374+
return "const";
2375+
case NVPTX::Local:
2376+
return "local";
2377+
case NVPTX::SharedCluster:
2378+
return "shared_cluster";
2379+
default:
2380+
return "";
2381+
}
2382+
}
2383+
2384+
static std::optional<unsigned> getNVPTXAddressSpaceNumber(StringRef Name) {
2385+
return StringSwitch<std::optional<unsigned>>(Name)
2386+
.Case("generic", NVPTX::Generic)
2387+
.Case("global", NVPTX::Global)
2388+
.Case("shared", NVPTX::Shared)
2389+
.Case("const", NVPTX::Const)
2390+
.Case("local", NVPTX::Local)
2391+
.Case("shared_cluster", NVPTX::SharedCluster)
2392+
.Default(std::nullopt);
2393+
}
2394+
2395+
StringRef Triple::getAddressSpaceName(unsigned AS) const {
2396+
switch (getArch()) {
2397+
case Triple::nvptx:
2398+
case Triple::nvptx64:
2399+
return getNVPTXAddressSpaceName(AS);
2400+
default:
2401+
return "";
2402+
}
2403+
}
2404+
2405+
std::optional<unsigned> Triple::getAddressSpaceNumber(StringRef Name) const {
2406+
switch (getArch()) {
2407+
case Triple::nvptx:
2408+
case Triple::nvptx64:
2409+
return getNVPTXAddressSpaceNumber(Name);
2410+
default:
2411+
return std::nullopt;
2412+
}
2413+
}
2414+
23642415
// HLSL triple environment orders are relied on in the front end
23652416
static_assert(Triple::Vertex - Triple::Pixel == 1,
23662417
"incorrect HLSL stage order");
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
;; Check that we can parse/print symbolic addres space for NVPTX triple.
2+
; RUN: split-file %s %t --leading-lines
3+
; RUN: llvm-as < %t/num-to-sym.ll | llvm-dis | FileCheck %t/num-to-sym.ll
4+
; RUN: llvm-as < %t/sym-to-sym.ll | llvm-dis | FileCheck %t/sym-to-sym.ll
5+
; RUN: not llvm-as < %t/invalid-sym.ll 2>&1 | FileCheck %t/invalid-sym.ll
6+
7+
;--- num-to-sym.ll
8+
target triple = "nvptx64-nvidia-cuda"
9+
10+
; CHECK: @str0 = private addrspace("global") constant
11+
@str0 = private addrspace(1) constant [4 x i8] c"str\00"
12+
13+
; CHECK: @gvs = external addrspace("shared") global i32
14+
@gvs = external addrspace(3) global i32
15+
16+
; CHECK: @gv_unknown_as = external addrspace(100) global i32
17+
@gv_unknown_as = external addrspace(100) global i32
18+
19+
define void @foo() {
20+
; CHECK: %alloca = alloca i32, align 4, addrspace("local")
21+
%alloca = alloca i32, addrspace(5)
22+
; CHECK: store i32 0, ptr addrspace("local") %alloca
23+
store i32 0, ptr addrspace(5) %alloca
24+
; CHECK: store i32 3, ptr addrspace("shared") @gvs
25+
store i32 3, ptr addrspace(3) @gvs
26+
ret void
27+
}
28+
29+
;--- sym-to-sym.ll
30+
target triple = "nvptx64-nvidia-cuda"
31+
32+
; CHECK: @str0 = private addrspace("global") constant
33+
@str0 = private addrspace("global") constant [4 x i8] c"str\00"
34+
35+
; CHECK: @gvs = external addrspace("shared") global i32
36+
@gvs = external addrspace("shared") global i32
37+
38+
; CHECK: @gv_unknown_as = external addrspace(100) global i32
39+
@gv_unknown_as = external addrspace(100) global i32
40+
41+
define void @foo() {
42+
; CHECK: %alloca = alloca i32, align 4, addrspace("local")
43+
%alloca = alloca i32, addrspace("local")
44+
; CHECK: store i32 0, ptr addrspace("local") %alloca
45+
store i32 0, ptr addrspace("local") %alloca
46+
; CHECK: store i32 3, ptr addrspace("shared") @gvs
47+
store i32 3, ptr addrspace("shared") @gvs
48+
ret void
49+
}
50+
51+
;--- invalid-sym.ll
52+
target triple = "nvptx64-nvidia-cuda"
53+
; CHECK: error: invalid symbolic addrspace 'ram'
54+
@str0 = private addrspace("ram") constant [4 x i8] c"str\00"

0 commit comments

Comments
 (0)