Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
35 changes: 33 additions & 2 deletions llvm/lib/Target/DirectX/DXILForwardHandleAccesses.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,17 +87,48 @@ static bool forwardHandleAccesses(Function &F, DominatorTree &DT) {

for (LoadInst *LI : LoadsToProcess) {
Value *V = LI->getPointerOperand();
auto *GV = dyn_cast<GlobalVariable>(LI->getPointerOperand());
auto *GV = dyn_cast<GlobalVariable>(V);

// If we didn't find the global, we may need to walk through a level of
// indirection. This generally happens at -O0.
if (!GV)
if (!GV) {
if (auto *NestedLI = dyn_cast<LoadInst>(V)) {
BasicBlock::iterator BBI(NestedLI);
Value *Loaded = FindAvailableLoadedValue(
NestedLI, NestedLI->getParent(), BBI, 0, nullptr, nullptr);
GV = dyn_cast_or_null<GlobalVariable>(Loaded);
} else if (auto *NestedAlloca = dyn_cast<AllocaInst>(V)) {
for (auto &Use : NestedAlloca->uses()) {
auto *Store = dyn_cast<StoreInst>(Use.getUser());
if (!Store)
continue;

Value *StoredVal = Store->getValueOperand();
if (!StoredVal)
continue;

// Try direct global match
GV = dyn_cast<GlobalVariable>(StoredVal);
if (GV)
break;

// If it's a load, check its source
if (auto *Load = dyn_cast<LoadInst>(StoredVal)) {
GV = dyn_cast<GlobalVariable>(Load->getPointerOperand());
if (GV)
break;

// Try to find available loaded value
BasicBlock::iterator BBI(Load);
Value *Loaded = FindAvailableLoadedValue(Load, Load->getParent(),
BBI, 0, nullptr, nullptr);
GV = dyn_cast<GlobalVariable>(Loaded);
if (GV)
break;
}
}
}
}

auto It = HandleMap.find(GV);
if (It == HandleMap.end()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
; RUN: opt -S -dxil-forward-handle-accesses %s | FileCheck %s

%"class.hlsl::RWStructuredBuffer" = type { target("dx.RawBuffer", i32, 1, 0) }
@_ZL4dest = internal unnamed_addr global %"class.hlsl::RWStructuredBuffer" poison, align 4
@.str = private unnamed_addr constant [5 x i8] c"dest\00", align 1


; NOTE: intent of this test is to confirm load target("dx.RawBuffer", i32, 1, 0)
; is replaced with call @llvm.dx.resource.getpointer
define void @CSMain() local_unnamed_addr {
; CHECK-LABEL: define void @CSMain() local_unnamed_addr {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[AGG_TMP_I1_SROA_0:%.*]] = alloca target("dx.RawBuffer", i32, 1, 0), align 8
; CHECK-NEXT: [[TMP0:%.*]] = tail call target("dx.RawBuffer", i32, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i32_1_0t(i32 0, i32 3, i32 1, i32 0, i1 false, ptr nonnull @.str)
; CHECK-NEXT: store target("dx.RawBuffer", i32, 1, 0) [[TMP0]], ptr @_ZL4dest, align 4
; CHECK-NEXT: [[TMP1:%.*]] = tail call i32 @llvm.dx.thread.id(i32 0)
; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr @_ZL4dest, align 4
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr nonnull [[AGG_TMP_I1_SROA_0]])
; CHECK-NEXT: store i32 [[TMP2]], ptr [[AGG_TMP_I1_SROA_0]], align 8
; CHECK-NEXT: [[TMP3:%.*]] = tail call noundef nonnull align 4 dereferenceable(4) ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_i32_1_0t(target("dx.RawBuffer", i32, 1, 0) [[TMP0]], i32 [[TMP1]])
; CHECK-NEXT: store i32 0, ptr [[TMP3]], align 4
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr nonnull [[AGG_TMP_I1_SROA_0]])
; CHECK-NEXT: ret void
;
entry:
%agg.tmp.i1.sroa.0 = alloca target("dx.RawBuffer", i32, 1, 0), align 8
%0 = tail call target("dx.RawBuffer", i32, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i32_1_0t(i32 0, i32 3, i32 1, i32 0, i1 false, ptr nonnull @.str)
store target("dx.RawBuffer", i32, 1, 0) %0, ptr @_ZL4dest, align 4
%1 = tail call i32 @llvm.dx.thread.id(i32 0)
%2 = load i32, ptr @_ZL4dest, align 4
call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %agg.tmp.i1.sroa.0)
store i32 %2, ptr %agg.tmp.i1.sroa.0, align 8
%agg.tmp.i1.sroa.0.0.agg.tmp.i1.sroa.0.0.agg.tmp.i1.sroa.0.0.agg.tmp.i1.sroa.0.0. = load target("dx.RawBuffer", i32, 1, 0), ptr %agg.tmp.i1.sroa.0, align 8
%3 = tail call noundef nonnull align 4 dereferenceable(4) ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_i32_1_0t(target("dx.RawBuffer", i32, 1, 0) %agg.tmp.i1.sroa.0.0.agg.tmp.i1.sroa.0.0.agg.tmp.i1.sroa.0.0.agg.tmp.i1.sroa.0.0., i32 %1)
store i32 0, ptr %3, align 4
call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %agg.tmp.i1.sroa.0)
ret void
}