diff --git a/llvm/lib/Target/AMDGPU/AMDGPULowerBufferFatPointers.cpp b/llvm/lib/Target/AMDGPU/AMDGPULowerBufferFatPointers.cpp index 275b3a6f16e54..20ccdcaa0e9a0 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPULowerBufferFatPointers.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPULowerBufferFatPointers.cpp @@ -1980,6 +1980,8 @@ PtrParts SplitPtrStructs::visitIntToPtrInst(IntToPtrInst &IP) { } PtrParts SplitPtrStructs::visitAddrSpaceCastInst(AddrSpaceCastInst &I) { + // TODO(krzysz00): handle casts from ptr addrspace(7) to global pointers + // by computing the effective address. if (!isSplitFatPtr(I.getType())) return {nullptr, nullptr}; IRB.SetInsertPoint(&I); @@ -1990,11 +1992,37 @@ PtrParts SplitPtrStructs::visitAddrSpaceCastInst(AddrSpaceCastInst &I) { SplitUsers.insert(&I); return {Rsrc, Off}; } - if (I.getSrcAddressSpace() != AMDGPUAS::BUFFER_RESOURCE) - report_fatal_error("Only buffer resources (addrspace 8) can be cast to " - "buffer fat pointers (addrspace 7)"); - Type *OffTy = cast(I.getType())->getElementType(1); + + auto *ResTy = cast(I.getType()); + Type *RsrcTy = ResTy->getElementType(0); + Type *OffTy = ResTy->getElementType(1); Value *ZeroOff = Constant::getNullValue(OffTy); + + // Special case for null pointers, undef, and poison, which can be created by + // address space propagation. + auto *InConst = dyn_cast(In); + if (InConst && InConst->isNullValue()) { + Value *NullRsrc = Constant::getNullValue(RsrcTy); + SplitUsers.insert(&I); + return {NullRsrc, ZeroOff}; + } + if (isa(In)) { + Value *PoisonRsrc = PoisonValue::get(RsrcTy); + Value *PoisonOff = PoisonValue::get(OffTy); + SplitUsers.insert(&I); + return {PoisonRsrc, PoisonOff}; + } + if (isa(In)) { + Value *UndefRsrc = UndefValue::get(RsrcTy); + Value *UndefOff = UndefValue::get(OffTy); + SplitUsers.insert(&I); + return {UndefRsrc, UndefOff}; + } + + if (I.getSrcAddressSpace() != AMDGPUAS::BUFFER_RESOURCE) + report_fatal_error( + "only buffer resources (addrspace 8) and null/poison pointers can be " + "cast to buffer fat pointers (addrspace 7)"); SplitUsers.insert(&I); return {In, ZeroOff}; } diff --git a/llvm/test/CodeGen/AMDGPU/lower-buffer-fat-pointers-pointer-ops.ll b/llvm/test/CodeGen/AMDGPU/lower-buffer-fat-pointers-pointer-ops.ll index fd5bf579cdeb2..63c0463149b79 100644 --- a/llvm/test/CodeGen/AMDGPU/lower-buffer-fat-pointers-pointer-ops.ll +++ b/llvm/test/CodeGen/AMDGPU/lower-buffer-fat-pointers-pointer-ops.ll @@ -332,6 +332,74 @@ define <2 x ptr addrspace(7)> @addrspacecast_vec(<2 x ptr addrspace(8)> %buf) { ret <2 x ptr addrspace(7)> %ret } +define ptr addrspace(7) @addrspacecast_null() { +; CHECK-LABEL: define { ptr addrspace(8), i32 } @addrspacecast_null +; CHECK-SAME: () #[[ATTR0]] { +; CHECK-NEXT: ret { ptr addrspace(8), i32 } zeroinitializer +; + %ret = addrspacecast ptr null to ptr addrspace(7) + ret ptr addrspace(7) %ret +} + +define <2 x ptr addrspace(7)> @addrspacecast_null_vec() { +; CHECK-LABEL: define { <2 x ptr addrspace(8)>, <2 x i32> } @addrspacecast_null_vec +; CHECK-SAME: () #[[ATTR0]] { +; CHECK-NEXT: ret { <2 x ptr addrspace(8)>, <2 x i32> } zeroinitializer +; + %ret = addrspacecast <2 x ptr> zeroinitializer to <2 x ptr addrspace(7)> + ret <2 x ptr addrspace(7)> %ret +} + +define i1 @test_null(ptr addrspace(7) %p) { +; CHECK-LABEL: define i1 @test_null +; CHECK-SAME: ({ ptr addrspace(8), i32 } [[P:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: [[P_RSRC:%.*]] = extractvalue { ptr addrspace(8), i32 } [[P]], 0 +; CHECK-NEXT: [[P_OFF:%.*]] = extractvalue { ptr addrspace(8), i32 } [[P]], 1 +; CHECK-NEXT: [[IS_NULL_RSRC:%.*]] = icmp eq ptr addrspace(8) [[P_RSRC]], null +; CHECK-NEXT: [[IS_NULL_OFF:%.*]] = icmp eq i32 [[P_OFF]], 0 +; CHECK-NEXT: [[IS_NULL:%.*]] = and i1 [[IS_NULL_RSRC]], [[IS_NULL_OFF]] +; CHECK-NEXT: ret i1 [[IS_NULL]] +; + %is.null = icmp eq ptr addrspace(7) %p, addrspacecast (ptr null to ptr addrspace(7)) + ret i1 %is.null +} + +define ptr addrspace(7) @addrspacecast_undef() { +; CHECK-LABEL: define { ptr addrspace(8), i32 } @addrspacecast_undef +; CHECK-SAME: () #[[ATTR0]] { +; CHECK-NEXT: ret { ptr addrspace(8), i32 } undef +; + %ret = addrspacecast ptr undef to ptr addrspace(7) + ret ptr addrspace(7) %ret +} + +define <2 x ptr addrspace(7)> @addrspacecast_undef_vec() { +; CHECK-LABEL: define { <2 x ptr addrspace(8)>, <2 x i32> } @addrspacecast_undef_vec +; CHECK-SAME: () #[[ATTR0]] { +; CHECK-NEXT: ret { <2 x ptr addrspace(8)>, <2 x i32> } undef +; + %ret = addrspacecast <2 x ptr> undef to <2 x ptr addrspace(7)> + ret <2 x ptr addrspace(7)> %ret +} + +define ptr addrspace(7) @addrspacecast_poison() { +; CHECK-LABEL: define { ptr addrspace(8), i32 } @addrspacecast_poison +; CHECK-SAME: () #[[ATTR0]] { +; CHECK-NEXT: ret { ptr addrspace(8), i32 } poison +; + %ret = addrspacecast ptr poison to ptr addrspace(7) + ret ptr addrspace(7) %ret +} + +define <2 x ptr addrspace(7)> @addrspacecast_poison_vec() { +; CHECK-LABEL: define { <2 x ptr addrspace(8)>, <2 x i32> } @addrspacecast_poison_vec +; CHECK-SAME: () #[[ATTR0]] { +; CHECK-NEXT: ret { <2 x ptr addrspace(8)>, <2 x i32> } poison +; + %ret = addrspacecast <2 x ptr> poison to <2 x ptr addrspace(7)> + ret <2 x ptr addrspace(7)> %ret +} + declare ptr addrspace(7) @llvm.amdgcn.make.buffer.rsrc.p7.p1(ptr addrspace(1), i16, i32, i32) define ptr addrspace(7) @make_buffer_rsrc(ptr addrspace(1) %buf, i16 %stride, i32 %numRecords, i32 %flags) {