[llvm] [DirectX] Implement the ForwardHandleAccesses pass (PR #135378)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Apr 11 07:31:49 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-analysis
Author: Justin Bogner (bogner)
<details>
<summary>Changes</summary>
This pass attempts to forward resource handle creation to accesses of the handle global. This avoids dependence on optimizations like CSE and GlobalOpt for correctness of DXIL.
Fixes #<!-- -->134574.
---
Patch is 20.80 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/135378.diff
13 Files Affected:
- (modified) llvm/include/llvm/Analysis/DXILResource.h (+18)
- (modified) llvm/lib/Target/DirectX/CMakeLists.txt (+1)
- (added) llvm/lib/Target/DirectX/DXILForwardHandleAccesses.cpp (+165)
- (added) llvm/lib/Target/DirectX/DXILForwardHandleAccesses.h (+28)
- (modified) llvm/lib/Target/DirectX/DirectX.h (+6)
- (modified) llvm/lib/Target/DirectX/DirectXPassRegistry.def (+1)
- (modified) llvm/lib/Target/DirectX/DirectXTargetMachine.cpp (+3)
- (added) llvm/test/CodeGen/DirectX/ForwardHandleAccesses/alloca.ll (+20)
- (added) llvm/test/CodeGen/DirectX/ForwardHandleAccesses/ambiguous.ll (+21)
- (added) llvm/test/CodeGen/DirectX/ForwardHandleAccesses/buffer-O0.ll (+44)
- (added) llvm/test/CodeGen/DirectX/ForwardHandleAccesses/cbuffer-access.ll (+23)
- (added) llvm/test/CodeGen/DirectX/ForwardHandleAccesses/undominated.ll (+16)
- (modified) llvm/test/CodeGen/DirectX/llc-pipeline.ll (+2-1)
``````````diff
diff --git a/llvm/include/llvm/Analysis/DXILResource.h b/llvm/include/llvm/Analysis/DXILResource.h
index ff7961c9ad51c..7d37eb70e1ca9 100644
--- a/llvm/include/llvm/Analysis/DXILResource.h
+++ b/llvm/include/llvm/Analysis/DXILResource.h
@@ -196,6 +196,24 @@ class SamplerExtType : public TargetExtType {
}
};
+class AnyResourceExtType : public TargetExtType {
+public:
+ AnyResourceExtType() = delete;
+ AnyResourceExtType(const AnyResourceExtType &) = delete;
+ AnyResourceExtType &operator=(const AnyResourceExtType &) = delete;
+
+ static bool classof(const TargetExtType *T) {
+ return isa<RawBufferExtType>(T) || isa<TypedBufferExtType>(T) ||
+ isa<TextureExtType>(T) || isa<MSTextureExtType>(T) ||
+ isa<FeedbackTextureExtType>(T) || isa<CBufferExtType>(T) ||
+ isa<SamplerExtType>(T);
+ }
+
+ static bool classof(const Type *T) {
+ return isa<TargetExtType>(T) && classof(cast<TargetExtType>(T));
+ }
+};
+
/// The dx.Layout target extension type
///
/// `target("dx.Layout", <Type>, <size>, [offsets...])`
diff --git a/llvm/lib/Target/DirectX/CMakeLists.txt b/llvm/lib/Target/DirectX/CMakeLists.txt
index 13f8adbe4f132..823419fb830ae 100644
--- a/llvm/lib/Target/DirectX/CMakeLists.txt
+++ b/llvm/lib/Target/DirectX/CMakeLists.txt
@@ -22,6 +22,7 @@ add_llvm_target(DirectXCodeGen
DXContainerGlobals.cpp
DXILDataScalarization.cpp
DXILFinalizeLinkage.cpp
+ DXILForwardHandleAccesses.cpp
DXILFlattenArrays.cpp
DXILIntrinsicExpansion.cpp
DXILOpBuilder.cpp
diff --git a/llvm/lib/Target/DirectX/DXILForwardHandleAccesses.cpp b/llvm/lib/Target/DirectX/DXILForwardHandleAccesses.cpp
new file mode 100644
index 0000000000000..888ba6b00d9e8
--- /dev/null
+++ b/llvm/lib/Target/DirectX/DXILForwardHandleAccesses.cpp
@@ -0,0 +1,165 @@
+//===- DXILForwardHandleAccesses.cpp - Cleanup Handles --------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "DXILForwardHandleAccesses.h"
+#include "DXILShaderFlags.h"
+#include "DirectX.h"
+#include "llvm/Analysis/DXILResource.h"
+#include "llvm/Analysis/Loads.h"
+#include "llvm/IR/DiagnosticInfo.h"
+#include "llvm/IR/Dominators.h"
+#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/Intrinsics.h"
+#include "llvm/IR/IntrinsicsDirectX.h"
+#include "llvm/IR/Module.h"
+#include "llvm/InitializePasses.h"
+#include "llvm/Pass.h"
+#include "llvm/Transforms/Utils/Local.h"
+
+#define DEBUG_TYPE "dxil-forward-handle-accesses"
+
+using namespace llvm;
+
+static void diagnoseAmbiguousHandle(IntrinsicInst *NewII,
+ IntrinsicInst *PrevII) {
+ Function *F = NewII->getFunction();
+ LLVMContext &Context = F->getParent()->getContext();
+ Context.diagnose(DiagnosticInfoGeneric(
+ Twine("Handle at \"") + NewII->getName() + "\" overwrites handle at \"" +
+ PrevII->getName() + "\""));
+}
+
+static void diagnoseHandleNotFound(LoadInst *LI) {
+ Function *F = LI->getFunction();
+ LLVMContext &Context = F->getParent()->getContext();
+ Context.diagnose(DiagnosticInfoGeneric(
+ LI, Twine("Load of \"") + LI->getPointerOperand()->getName() +
+ "\" is not a global resource handle"));
+}
+
+static void diagnoseUndominatedLoad(LoadInst *LI, IntrinsicInst *Handle) {
+ Function *F = LI->getFunction();
+ LLVMContext &Context = F->getParent()->getContext();
+ Context.diagnose(DiagnosticInfoGeneric(
+ LI, Twine("Load at \"") + LI->getName() +
+ "\" is not dominated by handle creation at \"" +
+ Handle->getName() + "\""));
+}
+
+static void
+processHandle(IntrinsicInst *II,
+ DenseMap<GlobalVariable *, IntrinsicInst *> &HandleMap) {
+ for (User *U : II->users())
+ if (auto *SI = dyn_cast<StoreInst>(U))
+ if (auto *GV = dyn_cast<GlobalVariable>(SI->getPointerOperand())) {
+ auto Entry = HandleMap.try_emplace(GV, II);
+ if (Entry.second)
+ LLVM_DEBUG(dbgs() << "Added " << GV->getName() << " to handle map\n");
+ else
+ diagnoseAmbiguousHandle(II, Entry.first->second);
+ }
+}
+
+static bool forwardHandleAccesses(Function &F, DominatorTree &DT) {
+ bool Changed = false;
+
+ DenseMap<GlobalVariable *, IntrinsicInst *> HandleMap;
+ SmallVector<LoadInst *> LoadsToProcess;
+ for (BasicBlock &BB : F)
+ for (Instruction &Inst : BB)
+ if (auto *II = dyn_cast<IntrinsicInst>(&Inst)) {
+ switch (II->getIntrinsicID()) {
+ case Intrinsic::dx_resource_handlefrombinding:
+ processHandle(II, HandleMap);
+ break;
+ default:
+ continue;
+ }
+ } else if (auto *LI = dyn_cast<LoadInst>(&Inst))
+ if (isa<dxil::AnyResourceExtType>(LI->getType()))
+ LoadsToProcess.push_back(LI);
+
+ for (LoadInst *LI : LoadsToProcess) {
+ Value *V = LI->getPointerOperand();
+ auto *GV = dyn_cast<GlobalVariable>(LI->getPointerOperand());
+
+ // 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 (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);
+ }
+
+ auto It = HandleMap.find(GV);
+ if (It == HandleMap.end()) {
+ diagnoseHandleNotFound(LI);
+ continue;
+ }
+ Changed = true;
+
+ if (!DT.dominates(It->second, LI)) {
+ diagnoseUndominatedLoad(LI, It->second);
+ continue;
+ }
+
+ LLVM_DEBUG(dbgs() << "Replacing uses of " << GV->getName() << " at "
+ << LI->getName() << " with " << It->second->getName()
+ << "\n");
+ LI->replaceAllUsesWith(It->second);
+ LI->eraseFromParent();
+ }
+
+ return Changed;
+}
+
+PreservedAnalyses DXILForwardHandleAccesses::run(Function &F,
+ FunctionAnalysisManager &AM) {
+ PreservedAnalyses PA;
+
+ DominatorTree *DT = &AM.getResult<DominatorTreeAnalysis>(F);
+ bool Changed = forwardHandleAccesses(F, *DT);
+
+ if (!Changed)
+ return PreservedAnalyses::all();
+ return PA;
+}
+
+namespace {
+class DXILForwardHandleAccessesLegacy : public FunctionPass {
+public:
+ bool runOnFunction(Function &F) override {
+ DominatorTree *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
+ return forwardHandleAccesses(F, *DT);
+ }
+ StringRef getPassName() const override {
+ return "DXIL Forward Handle Accesses";
+ }
+
+ void getAnalysisUsage(AnalysisUsage &AU) const override {
+ AU.addRequired<DominatorTreeWrapperPass>();
+ }
+
+ DXILForwardHandleAccessesLegacy() : FunctionPass(ID) {}
+
+ static char ID; // Pass identification.
+};
+char DXILForwardHandleAccessesLegacy::ID = 0;
+} // end anonymous namespace
+
+INITIALIZE_PASS_BEGIN(DXILForwardHandleAccessesLegacy, DEBUG_TYPE,
+ "DXIL Forward Handle Accesses", false, false)
+INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
+INITIALIZE_PASS_END(DXILForwardHandleAccessesLegacy, DEBUG_TYPE,
+ "DXIL Forward Handle Accesses", false, false)
+
+FunctionPass *llvm::createDXILForwardHandleAccessesLegacyPass() {
+ return new DXILForwardHandleAccessesLegacy();
+}
diff --git a/llvm/lib/Target/DirectX/DXILForwardHandleAccesses.h b/llvm/lib/Target/DirectX/DXILForwardHandleAccesses.h
new file mode 100644
index 0000000000000..76940287a50ad
--- /dev/null
+++ b/llvm/lib/Target/DirectX/DXILForwardHandleAccesses.h
@@ -0,0 +1,28 @@
+//===- DXILForwardHandleAccesses.h - Cleanup Handles ------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// \file Eliminate redundant stores and loads from handle globals.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_DIRECTX_DXILFORWARDHANDLEACCESS_H
+#define LLVM_LIB_TARGET_DIRECTX_DXILFORWARDHANDLEACCESS_H
+
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+
+class DXILForwardHandleAccesses
+ : public PassInfoMixin<DXILForwardHandleAccesses> {
+public:
+ PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
+};
+
+} // namespace llvm
+
+#endif // LLVM_LIB_TARGET_DIRECTX_DXILFORWARDHANDLEACCESS_H
diff --git a/llvm/lib/Target/DirectX/DirectX.h b/llvm/lib/Target/DirectX/DirectX.h
index 96a8a08c875f8..6e11eea11fed6 100644
--- a/llvm/lib/Target/DirectX/DirectX.h
+++ b/llvm/lib/Target/DirectX/DirectX.h
@@ -47,6 +47,12 @@ void initializeDXILFlattenArraysLegacyPass(PassRegistry &);
/// Pass to flatten arrays into a one dimensional DXIL legal form
ModulePass *createDXILFlattenArraysLegacyPass();
+/// Initializer for DXIL Forward Handle Accesses Pass
+void initializeDXILForwardHandleAccessesLegacyPass(PassRegistry &);
+
+/// Pass to eliminate redundant stores and loads from handle globals.
+FunctionPass *createDXILForwardHandleAccessesLegacyPass();
+
/// Initializer DXIL legalizationPass
void initializeDXILLegalizeLegacyPass(PassRegistry &);
diff --git a/llvm/lib/Target/DirectX/DirectXPassRegistry.def b/llvm/lib/Target/DirectX/DirectXPassRegistry.def
index 87d91ead1896f..afea7c24a833a 100644
--- a/llvm/lib/Target/DirectX/DirectXPassRegistry.def
+++ b/llvm/lib/Target/DirectX/DirectXPassRegistry.def
@@ -37,6 +37,7 @@ MODULE_PASS("print<dxil-root-signature>", dxil::RootSignatureAnalysisPrinter(dbg
#ifndef FUNCTION_PASS
#define FUNCTION_PASS(NAME, CREATE_PASS)
#endif
+FUNCTION_PASS("dxil-forward-handle-accesses", DXILForwardHandleAccesses())
FUNCTION_PASS("dxil-resource-access", DXILResourceAccess())
FUNCTION_PASS("dxil-legalize", DXILLegalizePass())
#undef FUNCTION_PASS
diff --git a/llvm/lib/Target/DirectX/DirectXTargetMachine.cpp b/llvm/lib/Target/DirectX/DirectXTargetMachine.cpp
index 747e4b3eb9411..5aaa400589456 100644
--- a/llvm/lib/Target/DirectX/DirectXTargetMachine.cpp
+++ b/llvm/lib/Target/DirectX/DirectXTargetMachine.cpp
@@ -14,6 +14,7 @@
#include "DirectXTargetMachine.h"
#include "DXILDataScalarization.h"
#include "DXILFlattenArrays.h"
+#include "DXILForwardHandleAccesses.h"
#include "DXILIntrinsicExpansion.h"
#include "DXILLegalizePass.h"
#include "DXILOpLowering.h"
@@ -65,6 +66,7 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeDirectXTarget() {
initializeRootSignatureAnalysisWrapperPass(*PR);
initializeDXILFinalizeLinkageLegacyPass(*PR);
initializeDXILPrettyPrinterLegacyPass(*PR);
+ initializeDXILForwardHandleAccessesLegacyPass(*PR);
}
class DXILTargetObjectFile : public TargetLoweringObjectFile {
@@ -102,6 +104,7 @@ class DirectXPassConfig : public TargetPassConfig {
ScalarizerPassOptions DxilScalarOptions;
DxilScalarOptions.ScalarizeLoadStore = true;
addPass(createScalarizerPass(DxilScalarOptions));
+ addPass(createDXILForwardHandleAccessesLegacyPass());
addPass(createDXILLegalizeLegacyPass());
addPass(createDXILTranslateMetadataLegacyPass());
addPass(createDXILOpLoweringLegacyPass());
diff --git a/llvm/test/CodeGen/DirectX/ForwardHandleAccesses/alloca.ll b/llvm/test/CodeGen/DirectX/ForwardHandleAccesses/alloca.ll
new file mode 100644
index 0000000000000..f9abfbddeae57
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/ForwardHandleAccesses/alloca.ll
@@ -0,0 +1,20 @@
+; RUN: not opt -S -dxil-forward-handle-accesses -mtriple=dxil--shadermodel6.3-library %s 2>&1 | FileCheck %s
+
+; CHECK: error: Load of "buf" is not a global resource handle
+
+%"class.hlsl::RWStructuredBuffer" = type { target("dx.RawBuffer", <4 x float>, 1, 0) }
+ at Buf = internal global %"class.hlsl::RWStructuredBuffer" poison, align 4
+
+define float @f() {
+entry:
+ %buf = alloca target("dx.RawBuffer", <4 x float>, 1, 0), align 4
+ %h = call target("dx.RawBuffer", <4 x float>, 1, 0) @llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 1, i32 0, i1 false)
+ store target("dx.RawBuffer", <4 x float>, 1, 0) %h, ptr %buf, align 4
+
+ %b = load target("dx.RawBuffer", <4 x float>, 1, 0), ptr %buf, align 4
+ %l = call { <4 x float>, i1 } @llvm.dx.resource.load.rawbuffer(target("dx.RawBuffer", <4 x float>, 1, 0) %b, i32 0, i32 0)
+ %x = extractvalue { <4 x float>, i1 } %l, 0
+ %v = extractelement <4 x float> %x, i32 0
+
+ ret float %v
+}
diff --git a/llvm/test/CodeGen/DirectX/ForwardHandleAccesses/ambiguous.ll b/llvm/test/CodeGen/DirectX/ForwardHandleAccesses/ambiguous.ll
new file mode 100644
index 0000000000000..62cd04e0032fb
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/ForwardHandleAccesses/ambiguous.ll
@@ -0,0 +1,21 @@
+; RUN: not opt -S -dxil-forward-handle-accesses -mtriple=dxil--shadermodel6.3-library %s 2>&1 | FileCheck %s
+
+; CHECK: error: Handle at "h2" overwrites handle at "h1"
+
+%"class.hlsl::RWStructuredBuffer" = type { target("dx.RawBuffer", <4 x float>, 1, 0) }
+ at Buf = internal global %"class.hlsl::RWStructuredBuffer" poison, align 4
+
+define float @f() {
+entry:
+ %h1 = call target("dx.RawBuffer", <4 x float>, 1, 0) @llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 1, i32 0, i1 false)
+ store target("dx.RawBuffer", <4 x float>, 1, 0) %h1, ptr @Buf, align 4
+ %h2 = call target("dx.RawBuffer", <4 x float>, 1, 0) @llvm.dx.resource.handlefrombinding(i32 0, i32 1, i32 1, i32 0, i1 false)
+ store target("dx.RawBuffer", <4 x float>, 1, 0) %h2, ptr @Buf, align 4
+
+ %b = load target("dx.RawBuffer", <4 x float>, 1, 0), ptr @Buf, align 4
+ %l = call { <4 x float>, i1 } @llvm.dx.resource.load.rawbuffer(target("dx.RawBuffer", <4 x float>, 1, 0) %b, i32 0, i32 0)
+ %x = extractvalue { <4 x float>, i1 } %l, 0
+ %v = extractelement <4 x float> %x, i32 0
+
+ ret float %v
+}
diff --git a/llvm/test/CodeGen/DirectX/ForwardHandleAccesses/buffer-O0.ll b/llvm/test/CodeGen/DirectX/ForwardHandleAccesses/buffer-O0.ll
new file mode 100644
index 0000000000000..880fefd57e029
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/ForwardHandleAccesses/buffer-O0.ll
@@ -0,0 +1,44 @@
+; RUN: opt -S -dxil-forward-handle-accesses -mtriple=dxil--shadermodel6.3-library %s | FileCheck %s
+
+%"class.hlsl::RWStructuredBuffer" = type { target("dx.RawBuffer", <4 x float>, 1, 0) }
+
+ at _ZL2In = internal global %"class.hlsl::RWStructuredBuffer" poison, align 4
+ at _ZL3Out = internal global %"class.hlsl::RWStructuredBuffer" poison, align 4
+
+define void @main() #1 {
+entry:
+ %this.addr.i.i.i = alloca ptr, align 4
+ %this.addr.i.i = alloca ptr, align 4
+ %this.addr.i1 = alloca ptr, align 4
+ %Index.addr.i2 = alloca i32, align 4
+ %this.addr.i = alloca ptr, align 4
+ %Index.addr.i = alloca i32, align 4
+ ; CHECK: [[IN:%.*]] = call target("dx.RawBuffer", <4 x float>, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_v4f32_1_0t(i32 0, i32 0, i32 1, i32 0, i1 false)
+ %_ZL2In_h.i.i = call target("dx.RawBuffer", <4 x float>, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_v4f32_1_0t(i32 0, i32 0, i32 1, i32 0, i1 false)
+ store target("dx.RawBuffer", <4 x float>, 1, 0) %_ZL2In_h.i.i, ptr @_ZL2In, align 4
+ store ptr @_ZL2In, ptr %this.addr.i.i, align 4
+ %this1.i.i = load ptr, ptr %this.addr.i.i, align 4
+ ; CHECK: [[OUT:%.*]] = call target("dx.RawBuffer", <4 x float>, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_v4f32_1_0t(i32 0, i32 1, i32 1, i32 0, i1 false)
+ %_ZL3Out_h.i.i = call target("dx.RawBuffer", <4 x float>, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_v4f32_1_0t(i32 0, i32 1, i32 1, i32 0, i1 false)
+ store target("dx.RawBuffer", <4 x float>, 1, 0) %_ZL3Out_h.i.i, ptr @_ZL3Out, align 4
+ store ptr @_ZL3Out, ptr %this.addr.i.i.i, align 4
+ %this1.i.i.i = load ptr, ptr %this.addr.i.i.i, align 4
+ store ptr @_ZL2In, ptr %this.addr.i1, align 4
+ store i32 0, ptr %Index.addr.i2, align 4
+ %this1.i3 = load ptr, ptr %this.addr.i1, align 4
+ ; CHECK-NOT: load target("dx.RawBuffer", <4 x float>, 1, 0)
+ %0 = load target("dx.RawBuffer", <4 x float>, 1, 0), ptr %this1.i3, align 4
+ %1 = load i32, ptr %Index.addr.i2, align 4
+ ; CHECK: call { <4 x float>, i1 } @llvm.dx.resource.load.rawbuffer.v4f32.tdx.RawBuffer_v4f32_1_0t(target("dx.RawBuffer", <4 x float>, 1, 0) [[IN]],
+ %2 = call { <4 x float>, i1 } @llvm.dx.resource.load.rawbuffer.v4f32.tdx.RawBuffer_v4f32_1_0t(target("dx.RawBuffer", <4 x float>, 1, 0) %0, i32 %1, i32 0)
+ %3 = extractvalue { <4 x float>, i1 } %2, 0
+ store ptr @_ZL3Out, ptr %this.addr.i, align 4
+ store i32 0, ptr %Index.addr.i, align 4
+ %this1.i = load ptr, ptr %this.addr.i, align 4
+ ; CHECK-NOT: load target("dx.RawBuffer", <4 x float>, 1, 0)
+ %4 = load target("dx.RawBuffer", <4 x float>, 1, 0), ptr %this1.i, align 4
+ %5 = load i32, ptr %Index.addr.i, align 4
+ ; CHECK: call void @llvm.dx.resource.store.rawbuffer.tdx.RawBuffer_v4f32_1_0t.v4f32(target("dx.RawBuffer", <4 x float>, 1, 0) [[OUT]],
+ call void @llvm.dx.resource.store.rawbuffer.tdx.RawBuffer_v4f32_1_0t.v4f32(target("dx.RawBuffer", <4 x float>, 1, 0) %4, i32 %5, i32 0, <4 x float> %3)
+ ret void
+}
diff --git a/llvm/test/CodeGen/DirectX/ForwardHandleAccesses/cbuffer-access.ll b/llvm/test/CodeGen/DirectX/ForwardHandleAccesses/cbuffer-access.ll
new file mode 100644
index 0000000000000..7790cd3ad2ec6
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/ForwardHandleAccesses/cbuffer-access.ll
@@ -0,0 +1,23 @@
+; RUN: opt -S -dxil-forward-handle-accesses -mtriple=dxil--shadermodel6.3-library %s | FileCheck %s
+
+%__cblayout_CB = type <{ float, i32, i32 }>
+%struct.Scalars = type { float, i32, i32 }
+
+ at CB.cb = local_unnamed_addr global target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 12, 0, 4, 8)) poison
+
+define void @main() local_unnamed_addr #1 {
+entry:
+ ; CHECK: [[CB:%.*]] = tail call target({{.*}}) @llvm.dx.resource.handlefrombinding
+ %h = tail call target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 12, 0, 4, 8)) @llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 1, i32 0, i1 false)
+ store target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 12, 0, 4, 8)) %h, ptr @CB.cb, align 4
+ %_ZL3Out_h.i.i = tail call target("dx.RawBuffer", %struct.Scalars, 1, 0) @llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 1, i32 0, i1 false)
+ ; CHECK-NOT: load target({{.*}}), ptr @CB.cb
+ %cb = load target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 12, 0, 4, 8)), ptr @CB.cb, align 4
+ ; CHECK: call { float, float, float, float } @llvm.dx.resource.load.cbufferrow.4.{{.*}}(target({{.*}}) [[CB]], i32 0)
+ %0 = call { float, float, float, float } @llvm.dx.resource.load.cbufferrow.4(target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 12, 0, 4, 8)) %cb, i32 0)
+ %1 = extractvalue { float, float, float, float } %0, 0
+ call void @llvm.dx.resource.store.rawbuffer(target("dx.RawBuffer", %struct.Scalars, 1, 0) %_ZL3Out_h.i.i, i32 0, i32 0, float %1)
+ ret void
+}
+
+attributes #0 = { mustprogress nofree noinline norecurse nosync nounwind willreturn memory(readwrite, argmem: write, inaccessiblemem: none) "approx-func-fp-math"="false" "frame-pointer"="all" "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
diff --git a/llvm/test/CodeGen/DirectX/ForwardHandleAccesses/undominated.ll b/llvm/test/CodeGen/DirectX/ForwardHandleAccesses/undominated.ll
new file mode 100644
index 0000000000000..03406ca97c62f
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/ForwardHandleAccesses/undominated.ll
@@ -0,0 +1,16 @@
+; RUN: not opt -S -dxil-forward-handle-accesses -mtriple=dxil--shadermodel6.3-library %s 2>&1 | FileCheck %s
+
+; CHECK: error: Load at "b" is not dominated by handle creation at "h1"
+
+%"class.hlsl::RWStructuredBuffer" = type { target("dx.RawBuffer", <4 x float>, 1, 0) }
+ at Buf = internal global %"class.hlsl::RWStructuredBuffer" poison, align 4
+
+define void @f() {
+entry:
+ %b = load target("dx.RawBuffer", <4 x float>, 1, 0), ptr @Buf, align 4
+
+ %h1 = call target("dx.RawBuffer", <4 x fl...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/135378
More information about the llvm-commits
mailing list