Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 23 additions & 15 deletions lib/SPIRV/SPIRVWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -881,14 +881,24 @@ SPIRVType *LLVMToSPIRVBase::transScavengedType(Value *V) {
BM->getErrorLog().checkError(!FnTy->isVarArg(),
SPIRVEC_UnsupportedVarArgFunction);

SPIRVType *RT = transType(FnTy->getReturnType());
// TODO: Replace this AMD intrinsic-only rewrite to Constant AS with a
// generic handling of AS mismatches around `Constant`.
// LLVM's intrinsic table (IntrinsicsAMDGPU.td) is used for getting the
// arguments and return type.
FunctionType *CanonicalFT = nullptr;
if (M->getTargetTriple().getVendor() == Triple::VendorType::AMD &&
F->isIntrinsic())
if (F->getReturnType()->isPtrOrPtrVectorTy())
RT = transType(F->getReturnType()->getWithNewType(
PointerType::get(F->getContext(), SPIRAS_Constant)));
F->hasName() && F->getName().starts_with("llvm.amdgcn.")) {
Intrinsic::ID IID = F->getIntrinsicID();
if (IID != Intrinsic::not_intrinsic && !Intrinsic::isOverloaded(IID))
CanonicalFT = Intrinsic::getType(F->getContext(), IID);
}

SPIRVType *RT = transType(FnTy->getReturnType());
if (CanonicalFT) {
Type *CanonicalRT = CanonicalFT->getReturnType();
if (CanonicalRT->isPtrOrPtrVectorTy())
RT = transType(CanonicalRT->getWithNewType(PointerType::get(
F->getContext(),
mapAMDGCNAddrSpaceToSPIRV(CanonicalRT->getPointerAddressSpace()))));
Comment thread
idubinov marked this conversation as resolved.
}

std::vector<SPIRVType *> PT;
for (Argument &Arg : F->args()) {
Expand All @@ -915,14 +925,12 @@ SPIRVType *LLVMToSPIRVBase::transScavengedType(Value *V) {
transType(ElTy));
PT.push_back(NewType);
continue;
} else if (M->getTargetTriple().getVendor() == Triple::AMD) {
// TODO: this is temporary and rather ugly, we should fix the BIs to
// not take an explicit AS in their signature.
if (F->hasName() &&
(F->getName() == "llvm.amdgcn.is.shared" ||
F->getName() == "llvm.amdgcn.is.private")) {
PT.push_back(transType(PointerType::get(F->getContext(),
SPIRAS_Generic)));
} else if (CanonicalFT) {
Type *CanonicalPT = CanonicalFT->getParamType(Arg.getArgNo());
if (CanonicalPT->isPtrOrPtrVectorTy()) {
PT.push_back(transType(CanonicalPT->getWithNewType(PointerType::get(
F->getContext(), mapAMDGCNAddrSpaceToSPIRV(
CanonicalPT->getPointerAddressSpace())))));
continue;
}
}
Expand Down
30 changes: 30 additions & 0 deletions test/llvm-intrinsics/amdgcn-intrinsic-ptr-arg-addrspace.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
; Test that non-overloaded AMDGCN intrinsics taking pointer *parameters* with a
; specific address space are correctly round-tripped through SPIR-V. The writer
; recovers the canonical parameter address space from LLVM's intrinsic
; declaration (rather than a hardcoded per-name list), so the flat/generic
; pointer parameter of is.shared / is.private must be preserved.

; RUN: llvm-spirv -spirv-allow-unknown-intrinsics=llvm.amdgcn %s -o %t.spv
; RUN: llvm-spirv -r %t.spv -o - | llvm-dis | FileCheck %s

target datalayout = "e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-p7:160:256:256:32-p8:128:128-p9:192:256:256:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5-G1-ni:7:8:9"
target triple = "spirv64-amd-amdhsa"

; CHECK-DAG: declare i1 @llvm.amdgcn.is.shared(ptr)
; CHECK-DAG: declare i1 @llvm.amdgcn.is.private(ptr)

define void @test_amdgcn_ptr_arg_intrinsics(ptr addrspace(4) %generic, ptr addrspace(1) %out) {
entry:
%flat = addrspacecast ptr addrspace(4) %generic to ptr
; CHECK: call i1 @llvm.amdgcn.is.shared(ptr %{{[0-9a-zA-Z._]+}})
%shared = call i1 @llvm.amdgcn.is.shared(ptr %flat)
; CHECK: call i1 @llvm.amdgcn.is.private(ptr %{{[0-9a-zA-Z._]+}})
%private = call i1 @llvm.amdgcn.is.private(ptr %flat)
%r = or i1 %shared, %private
%z = zext i1 %r to i32
store i32 %z, ptr addrspace(1) %out
ret void
}

declare i1 @llvm.amdgcn.is.shared(ptr)
declare i1 @llvm.amdgcn.is.private(ptr)
Loading