[clang][SPIR][SPIRV] Materialize non-generic null pointers via addrspacecast (#161773)
LLVM models ConstantPointerNull as all-zero, but some GPUs (e.g. AMDGPU and our downstream GPU target) use a non-zero sentinel for null in private / local address spaces. SPIR-V is a supported input for our GPU target. This PR preserves a canonical zero form in the generic AS while allowing later lowering to substitute the target’s real sentinel.
This commit is contained in:
@@ -61,6 +61,9 @@ public:
|
||||
QualType SampledType, CodeGenModule &CGM) const;
|
||||
void
|
||||
setOCLKernelStubCallingConvention(const FunctionType *&FT) const override;
|
||||
llvm::Constant *getNullPointer(const CodeGen::CodeGenModule &CGM,
|
||||
llvm::PointerType *T,
|
||||
QualType QT) const override;
|
||||
};
|
||||
class SPIRVTargetCodeGenInfo : public CommonSPIRTargetCodeGenInfo {
|
||||
public:
|
||||
@@ -240,6 +243,29 @@ void CommonSPIRTargetCodeGenInfo::setOCLKernelStubCallingConvention(
|
||||
FT, FT->getExtInfo().withCallingConv(CC_SpirFunction));
|
||||
}
|
||||
|
||||
// LLVM currently assumes a null pointer has the bit pattern 0, but some GPU
|
||||
// targets use a non-zero encoding for null in certain address spaces.
|
||||
// Because SPIR(-V) is a generic target and the bit pattern of null in
|
||||
// non-generic AS is unspecified, materialize null in non-generic AS via an
|
||||
// addrspacecast from null in generic AS. This allows later lowering to
|
||||
// substitute the target's real sentinel value.
|
||||
llvm::Constant *
|
||||
CommonSPIRTargetCodeGenInfo::getNullPointer(const CodeGen::CodeGenModule &CGM,
|
||||
llvm::PointerType *PT,
|
||||
QualType QT) const {
|
||||
LangAS AS = QT->getUnqualifiedDesugaredType()->isNullPtrType()
|
||||
? LangAS::Default
|
||||
: QT->getPointeeType().getAddressSpace();
|
||||
if (AS == LangAS::Default || AS == LangAS::opencl_generic)
|
||||
return llvm::ConstantPointerNull::get(PT);
|
||||
|
||||
auto &Ctx = CGM.getContext();
|
||||
auto NPT = llvm::PointerType::get(
|
||||
PT->getContext(), Ctx.getTargetAddressSpace(LangAS::opencl_generic));
|
||||
return llvm::ConstantExpr::getAddrSpaceCast(
|
||||
llvm::ConstantPointerNull::get(NPT), PT);
|
||||
}
|
||||
|
||||
LangAS
|
||||
SPIRVTargetCodeGenInfo::getGlobalVarAddressSpace(CodeGenModule &CGM,
|
||||
const VarDecl *D) const {
|
||||
|
||||
@@ -62,19 +62,19 @@ void testBranchingOnAddressSpaceCast(generic long* ptr) {
|
||||
if (to_global(ptr))
|
||||
(void)0;
|
||||
// CHECK: [[P:%[0-9]+]] = call spir_func [[GLOBAL_VOID:ptr addrspace\(1\)]] @__to_global([[GENERIC_VOID:ptr addrspace\(4\)]] {{%[0-9]+}})
|
||||
// CHECK-NEXT: [[BOOL:%[a-z0-9]+]] = icmp ne ptr addrspace(1) [[P]], null
|
||||
// CHECK-NEXT: [[BOOL:%[a-z0-9]+]] = icmp ne ptr addrspace(1) [[P]], addrspacecast (ptr addrspace(4) null to ptr addrspace(1))
|
||||
// CHECK-NEXT: br i1 [[BOOL]]
|
||||
|
||||
if (to_local(ptr))
|
||||
(void)0;
|
||||
// CHECK: [[P:%[0-9]+]] = call spir_func [[LOCAL_VOID:ptr addrspace\(3\)]] @__to_local([[GENERIC_VOID]] {{%[0-9]+}})
|
||||
// CHECK-NEXT: [[BOOL:%[a-z0-9]+]] = icmp ne ptr addrspace(3) [[P]], null
|
||||
// CHECK-NEXT: [[BOOL:%[a-z0-9]+]] = icmp ne ptr addrspace(3) [[P]], addrspacecast (ptr addrspace(4) null to ptr addrspace(3))
|
||||
// CHECK-NEXT: br i1 [[BOOL]]
|
||||
|
||||
if (to_private(ptr))
|
||||
(void)0;
|
||||
// CHECK: [[P:%[0-9]+]] = call spir_func [[PRIVATE_VOID:ptr]] @__to_private([[GENERIC_VOID]] {{%[0-9]+}})
|
||||
// CHECK-NEXT: [[BOOL:%[a-z0-9]+]] = icmp ne ptr [[P]], null
|
||||
// CHECK-NEXT: [[BOOL:%[a-z0-9]+]] = icmp ne ptr [[P]], addrspacecast (ptr addrspace(4) null to ptr)
|
||||
// CHECK-NEXT: br i1 [[BOOL]]
|
||||
}
|
||||
|
||||
|
||||
@@ -35,9 +35,9 @@ void tmpl(T t) {}
|
||||
// CHECK-DAG: [[LOC]].ascast = addrspacecast ptr [[LOC]] to ptr addrspace(4)
|
||||
// CHECK-DAG: [[PRIV]].ascast = addrspacecast ptr [[PRIV]] to ptr addrspace(4)
|
||||
LOC = nullptr;
|
||||
// CHECK-DAG: store ptr addrspace(3) null, ptr addrspace(4) [[LOC]].ascast, align 8
|
||||
// CHECK-DAG: store ptr addrspace(3) addrspacecast (ptr addrspace(4) null to ptr addrspace(3)), ptr addrspace(4) [[LOC]].ascast, align 8
|
||||
GLOB = nullptr;
|
||||
// CHECK-DAG: store ptr addrspace(1) null, ptr addrspace(4) [[GLOB]].ascast, align 8
|
||||
// CHECK-DAG: store ptr addrspace(1) addrspacecast (ptr addrspace(4) null to ptr addrspace(1)), ptr addrspace(4) [[GLOB]].ascast, align 8
|
||||
|
||||
// Explicit conversions
|
||||
// From named address spaces to default address space
|
||||
|
||||
Reference in New Issue
Block a user