Skip to content
Open
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
28 changes: 28 additions & 0 deletions clang/lib/CodeGen/Targets/SPIR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ class CommonSPIRTargetCodeGenInfo : public TargetCodeGenInfo {
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:
Expand Down Expand Up @@ -240,6 +243,31 @@ 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 virtual target and the bit pattern of a non-generic
// null is unspecified, materialize non-generic null via an addrspacecast from
// the generic null.
// This allows later lowering to substitute the target’s real sentinel value.
llvm::Constant *
CommonSPIRTargetCodeGenInfo::getNullPointer(const CodeGen::CodeGenModule &CGM,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you directly copy the AMDGPU implementation, which checks against getTargetNullPointerValue

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you directly copy the AMDGPU implementation, which checks against getTargetNullPointerValue

getTargetNullPointerValue requires defining getNullPointerValue in BaseSPIRTargetInfo, like

uint64_t getNullPointerValue(LangAS AS) const override {
// FIXME: Also should handle region.
return (AS == LangAS::opencl_local || AS == LangAS::opencl_private ||
AS == LangAS::sycl_local || AS == LangAS::sycl_private)
? ~0
: 0;
}

However, we don't know the return value of getNullPointerValue in BaseSPIRTargetInfo except for generic address space, right?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, seems like getNullPointerValue should be able to fail. My main worry here is special casing generic address space, as opposed to default address space

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, seems like getNullPointerValue should be able to fail. My main worry here is special casing generic address space, as opposed to default address space

thanks @arsenm, you're right that the default AS is not checked.

I copied the logic from ASTContext::getTargetNullPointerValue into CommonSPIRTargetCodeGenInfo::getNullPointer in 5c5e13e to avoid changing return type of both getNullPointerValue and getTargetNullPointerValue to std::optional<uint64_t>. Since getTargetNullPointerValue is used in many places, changing its return type looks like unnecessary churn.

llvm::PointerType *PT,
QualType QT) const {
LangAS AS;
if (QT->getUnqualifiedDesugaredType()->isNullPtrType())
AS = LangAS::Default;
else
AS = 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 {
Expand Down
6 changes: 3 additions & 3 deletions clang/test/CodeGenOpenCL/builtins.cl
Original file line number Diff line number Diff line change
Expand Up @@ -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]]
}

4 changes: 2 additions & 2 deletions clang/test/CodeGenSYCL/address-space-conversions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down