Skip to content

Commit 6b9da28

Browse files
authored
[AMDGPU][LowerBufferFatPointers] Handle addrspacecast null to p7 (llvm#140775)
Some application code operating on generic pointers (that then gete initialized to buffer fat pointers) may perform tests against nullptr. After address space inference, this results in comparisons against `addrspacecast (ptr null to ptr addrspace(7))`, which were crashing. However, while general casts to ptr addrspace(7) from generic pointers aren't supposted, it is possible to cast null pointers to the all-zerose bufer resource and 0 offset, which this patch adds. It also adds a TODO for casting _out_ of buffer resources, which isn't implemented here but could be.
1 parent 580f70e commit 6b9da28

File tree

2 files changed

+100
-4
lines changed

2 files changed

+100
-4
lines changed

llvm/lib/Target/AMDGPU/AMDGPULowerBufferFatPointers.cpp

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1980,6 +1980,8 @@ PtrParts SplitPtrStructs::visitIntToPtrInst(IntToPtrInst &IP) {
19801980
}
19811981

19821982
PtrParts SplitPtrStructs::visitAddrSpaceCastInst(AddrSpaceCastInst &I) {
1983+
// TODO(krzysz00): handle casts from ptr addrspace(7) to global pointers
1984+
// by computing the effective address.
19831985
if (!isSplitFatPtr(I.getType()))
19841986
return {nullptr, nullptr};
19851987
IRB.SetInsertPoint(&I);
@@ -1990,11 +1992,37 @@ PtrParts SplitPtrStructs::visitAddrSpaceCastInst(AddrSpaceCastInst &I) {
19901992
SplitUsers.insert(&I);
19911993
return {Rsrc, Off};
19921994
}
1993-
if (I.getSrcAddressSpace() != AMDGPUAS::BUFFER_RESOURCE)
1994-
report_fatal_error("Only buffer resources (addrspace 8) can be cast to "
1995-
"buffer fat pointers (addrspace 7)");
1996-
Type *OffTy = cast<StructType>(I.getType())->getElementType(1);
1995+
1996+
auto *ResTy = cast<StructType>(I.getType());
1997+
Type *RsrcTy = ResTy->getElementType(0);
1998+
Type *OffTy = ResTy->getElementType(1);
19971999
Value *ZeroOff = Constant::getNullValue(OffTy);
2000+
2001+
// Special case for null pointers, undef, and poison, which can be created by
2002+
// address space propagation.
2003+
auto *InConst = dyn_cast<Constant>(In);
2004+
if (InConst && InConst->isNullValue()) {
2005+
Value *NullRsrc = Constant::getNullValue(RsrcTy);
2006+
SplitUsers.insert(&I);
2007+
return {NullRsrc, ZeroOff};
2008+
}
2009+
if (isa<PoisonValue>(In)) {
2010+
Value *PoisonRsrc = PoisonValue::get(RsrcTy);
2011+
Value *PoisonOff = PoisonValue::get(OffTy);
2012+
SplitUsers.insert(&I);
2013+
return {PoisonRsrc, PoisonOff};
2014+
}
2015+
if (isa<UndefValue>(In)) {
2016+
Value *UndefRsrc = UndefValue::get(RsrcTy);
2017+
Value *UndefOff = UndefValue::get(OffTy);
2018+
SplitUsers.insert(&I);
2019+
return {UndefRsrc, UndefOff};
2020+
}
2021+
2022+
if (I.getSrcAddressSpace() != AMDGPUAS::BUFFER_RESOURCE)
2023+
report_fatal_error(
2024+
"only buffer resources (addrspace 8) and null/poison pointers can be "
2025+
"cast to buffer fat pointers (addrspace 7)");
19982026
SplitUsers.insert(&I);
19992027
return {In, ZeroOff};
20002028
}

llvm/test/CodeGen/AMDGPU/lower-buffer-fat-pointers-pointer-ops.ll

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,74 @@ define <2 x ptr addrspace(7)> @addrspacecast_vec(<2 x ptr addrspace(8)> %buf) {
332332
ret <2 x ptr addrspace(7)> %ret
333333
}
334334

335+
define ptr addrspace(7) @addrspacecast_null() {
336+
; CHECK-LABEL: define { ptr addrspace(8), i32 } @addrspacecast_null
337+
; CHECK-SAME: () #[[ATTR0]] {
338+
; CHECK-NEXT: ret { ptr addrspace(8), i32 } zeroinitializer
339+
;
340+
%ret = addrspacecast ptr null to ptr addrspace(7)
341+
ret ptr addrspace(7) %ret
342+
}
343+
344+
define <2 x ptr addrspace(7)> @addrspacecast_null_vec() {
345+
; CHECK-LABEL: define { <2 x ptr addrspace(8)>, <2 x i32> } @addrspacecast_null_vec
346+
; CHECK-SAME: () #[[ATTR0]] {
347+
; CHECK-NEXT: ret { <2 x ptr addrspace(8)>, <2 x i32> } zeroinitializer
348+
;
349+
%ret = addrspacecast <2 x ptr> zeroinitializer to <2 x ptr addrspace(7)>
350+
ret <2 x ptr addrspace(7)> %ret
351+
}
352+
353+
define i1 @test_null(ptr addrspace(7) %p) {
354+
; CHECK-LABEL: define i1 @test_null
355+
; CHECK-SAME: ({ ptr addrspace(8), i32 } [[P:%.*]]) #[[ATTR0]] {
356+
; CHECK-NEXT: [[P_RSRC:%.*]] = extractvalue { ptr addrspace(8), i32 } [[P]], 0
357+
; CHECK-NEXT: [[P_OFF:%.*]] = extractvalue { ptr addrspace(8), i32 } [[P]], 1
358+
; CHECK-NEXT: [[IS_NULL_RSRC:%.*]] = icmp eq ptr addrspace(8) [[P_RSRC]], null
359+
; CHECK-NEXT: [[IS_NULL_OFF:%.*]] = icmp eq i32 [[P_OFF]], 0
360+
; CHECK-NEXT: [[IS_NULL:%.*]] = and i1 [[IS_NULL_RSRC]], [[IS_NULL_OFF]]
361+
; CHECK-NEXT: ret i1 [[IS_NULL]]
362+
;
363+
%is.null = icmp eq ptr addrspace(7) %p, addrspacecast (ptr null to ptr addrspace(7))
364+
ret i1 %is.null
365+
}
366+
367+
define ptr addrspace(7) @addrspacecast_undef() {
368+
; CHECK-LABEL: define { ptr addrspace(8), i32 } @addrspacecast_undef
369+
; CHECK-SAME: () #[[ATTR0]] {
370+
; CHECK-NEXT: ret { ptr addrspace(8), i32 } undef
371+
;
372+
%ret = addrspacecast ptr undef to ptr addrspace(7)
373+
ret ptr addrspace(7) %ret
374+
}
375+
376+
define <2 x ptr addrspace(7)> @addrspacecast_undef_vec() {
377+
; CHECK-LABEL: define { <2 x ptr addrspace(8)>, <2 x i32> } @addrspacecast_undef_vec
378+
; CHECK-SAME: () #[[ATTR0]] {
379+
; CHECK-NEXT: ret { <2 x ptr addrspace(8)>, <2 x i32> } undef
380+
;
381+
%ret = addrspacecast <2 x ptr> undef to <2 x ptr addrspace(7)>
382+
ret <2 x ptr addrspace(7)> %ret
383+
}
384+
385+
define ptr addrspace(7) @addrspacecast_poison() {
386+
; CHECK-LABEL: define { ptr addrspace(8), i32 } @addrspacecast_poison
387+
; CHECK-SAME: () #[[ATTR0]] {
388+
; CHECK-NEXT: ret { ptr addrspace(8), i32 } poison
389+
;
390+
%ret = addrspacecast ptr poison to ptr addrspace(7)
391+
ret ptr addrspace(7) %ret
392+
}
393+
394+
define <2 x ptr addrspace(7)> @addrspacecast_poison_vec() {
395+
; CHECK-LABEL: define { <2 x ptr addrspace(8)>, <2 x i32> } @addrspacecast_poison_vec
396+
; CHECK-SAME: () #[[ATTR0]] {
397+
; CHECK-NEXT: ret { <2 x ptr addrspace(8)>, <2 x i32> } poison
398+
;
399+
%ret = addrspacecast <2 x ptr> poison to <2 x ptr addrspace(7)>
400+
ret <2 x ptr addrspace(7)> %ret
401+
}
402+
335403
declare ptr addrspace(7) @llvm.amdgcn.make.buffer.rsrc.p7.p1(ptr addrspace(1), i16, i32, i32)
336404

337405
define ptr addrspace(7) @make_buffer_rsrc(ptr addrspace(1) %buf, i16 %stride, i32 %numRecords, i32 %flags) {

0 commit comments

Comments
 (0)