Skip to content

Commit df43b63

Browse files
committed
[SPIRV][SPIRVPrepareGlobals] Map AMD's dynamic LDS 0-element globals to arrays with UINT32_MAX elements
In HIP, dynamic LDS globals are represented using 0-element global arrays in the __shared__ language addressspace. extern __shared__ LDS[]; These are not representable in SPIRV directly. To represent them, for AMD, we use an array with UINT32_MAX-elements. These are reverse translated to 0-element arrays later in AMD's SPIRV runtime pipeline.
1 parent 0e5ddeb commit df43b63

File tree

2 files changed

+47
-0
lines changed

2 files changed

+47
-0
lines changed

llvm/lib/Target/SPIRV/SPIRVPrepareGlobals.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
#include "SPIRV.h"
1515

16+
#include "llvm/ADT/STLExtras.h"
1617
#include "llvm/IR/Module.h"
1718

1819
using namespace llvm;
@@ -43,6 +44,29 @@ bool tryExtendLLVMBitcodeMarker(GlobalVariable &Bitcode) {
4344
return true;
4445
}
4546

47+
bool tryExtendDynamicLDSGlobal(GlobalVariable &GV) {
48+
constexpr unsigned WorkgroupAS = 3;
49+
const bool IsWorkgroupExternal =
50+
GV.hasExternalLinkage() && GV.getAddressSpace() == WorkgroupAS;
51+
if (!IsWorkgroupExternal)
52+
return false;
53+
54+
const ArrayType *AT = dyn_cast<ArrayType>(GV.getValueType());
55+
if (!AT || AT->getNumElements() != 0)
56+
return false;
57+
58+
constexpr auto Magic = std::numeric_limits<uint32_t>::max();
59+
ArrayType *NewAT = ArrayType::get(AT->getElementType(), Magic);
60+
GlobalVariable *NewGV = new GlobalVariable(
61+
*GV.getParent(), NewAT, GV.isConstant(), GV.getLinkage(), nullptr, "",
62+
&GV, GV.getThreadLocalMode(), WorkgroupAS, GV.isExternallyInitialized());
63+
NewGV->takeName(&GV);
64+
GV.replaceAllUsesWith(NewGV);
65+
GV.eraseFromParent();
66+
67+
return true;
68+
}
69+
4670
bool SPIRVPrepareGlobals::runOnModule(Module &M) {
4771
const bool IsAMD = M.getTargetTriple().getVendor() == Triple::AMD;
4872
if (!IsAMD)
@@ -52,6 +76,9 @@ bool SPIRVPrepareGlobals::runOnModule(Module &M) {
5276
if (GlobalVariable *Bitcode = M.getNamedGlobal("llvm.embedded.module"))
5377
Changed |= tryExtendLLVMBitcodeMarker(*Bitcode);
5478

79+
for (GlobalVariable &GV : make_early_inc_range(M.globals()))
80+
Changed |= tryExtendDynamicLDSGlobal(GV);
81+
5582
return Changed;
5683
}
5784
char SPIRVPrepareGlobals::ID = 0;
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
; RUN: llc -verify-machineinstrs -mtriple=spirv64-amd-amdhsa %s -o - | FileCheck %s
2+
; RUN: %if spirv-tools %{ llc -mtriple=spirv64-amd-amdhsa %s -o - -filetype=obj | spirv-val %}
3+
4+
; CHECK: OpName %[[#LDS:]] "lds"
5+
; CHECK: OpDecorate %[[#LDS]] LinkageAttributes "lds" Import
6+
; CHECK: %[[#UINT:]] = OpTypeInt 32 0
7+
; CHECK: %[[#UINT_MAX:]] = OpConstant %[[#UINT]] 4294967295
8+
; CHECK: %[[#LDS_ARR_TY:]] = OpTypeArray %[[#UINT]] %[[#UINT_MAX]]
9+
; CHECK: %[[#LDS_ARR_PTR_WG:]] = OpTypePointer Workgroup %[[#LDS_ARR_TY]]
10+
; CHECK: %[[#LDS]] = OpVariable %[[#LDS_ARR_PTR_WG]] Workgroup
11+
12+
@lds = external addrspace(3) global [0 x i32]
13+
14+
define spir_kernel void @foo(ptr addrspace(4) %in, ptr addrspace(4) %out) {
15+
entry:
16+
%val = load i32, ptr addrspace(4) %in
17+
%add = add i32 %val, 1
18+
store i32 %add, ptr addrspace(4) %out
19+
ret void
20+
}

0 commit comments

Comments
 (0)