[llvm] [DirectX][ResourceAccess] Resolve resource handles at access (PR #182106)
Finn Plummer via llvm-commits
llvm-commits at lists.llvm.org
Fri Feb 20 11:13:41 PST 2026
================
@@ -419,6 +428,217 @@ static void createLoadIntrinsic(IntrinsicInst *II, LoadInst *LI,
llvm_unreachable("Unhandled case in switch");
}
+static Instruction *getPointerOperand(Instruction *AI) {
+ if (auto *LI = dyn_cast<LoadInst>(AI))
+ return dyn_cast<Instruction>(LI->getPointerOperand());
+ if (auto *SI = dyn_cast<StoreInst>(AI))
+ return dyn_cast<Instruction>(SI->getPointerOperand());
+
+ return nullptr;
+}
+
+static const std::array<Intrinsic::ID, 2> HandleIntrins = {
+ Intrinsic::dx_resource_handlefrombinding,
+ Intrinsic::dx_resource_handlefromimplicitbinding,
+};
+
+static SmallVector<IntrinsicInst *> collectUsedHandles(Value *Ptr) {
+ SmallVector<Value *> Worklist = {Ptr};
+ SmallVector<IntrinsicInst *> Handles;
+
+ while (!Worklist.empty()) {
+ Value *X = Worklist.pop_back_val();
+
+ if (!X->getType()->isPointerTy() && !X->getType()->isTargetExtTy())
+ return {}; // Early exit on store/load into non-resource
+
+ if (auto *Phi = dyn_cast<PHINode>(X))
+ for (Use &V : Phi->incoming_values())
+ Worklist.push_back(V.get());
+ else if (auto *Select = dyn_cast<SelectInst>(X))
+ for (Value *V : {Select->getTrueValue(), Select->getFalseValue()})
+ Worklist.push_back(V);
+ else if (auto *II = dyn_cast<IntrinsicInst>(X)) {
+ Intrinsic::ID IID = II->getIntrinsicID();
+
+ if (IID == Intrinsic::dx_resource_getpointer)
+ Worklist.push_back(II->getArgOperand(/*Handle=*/0));
+
+ if (llvm::is_contained(HandleIntrins, IID))
+ Handles.push_back(II);
+ }
+ }
+
+ return Handles;
+}
+
+static hlsl::Binding getHandleIntrinsicBinding(IntrinsicInst *Handle,
+ DXILResourceTypeMap &DRTM) {
+ assert(llvm::is_contained(HandleIntrins, Handle->getIntrinsicID()) &&
+ "Only expects a Handle as determined from collectUsedHandles.");
+
+ auto *HandleTy = cast<TargetExtType>(Handle->getType());
+ dxil::ResourceClass Class = DRTM[HandleTy].getResourceClass();
+ uint32_t Space = cast<ConstantInt>(Handle->getArgOperand(0))->getZExtValue();
+ uint32_t LowerBound =
+ cast<ConstantInt>(Handle->getArgOperand(1))->getZExtValue();
+ int32_t Size = cast<ConstantInt>(Handle->getArgOperand(2))->getZExtValue();
+ uint32_t UpperBound = Size < 0 ? UINT32_MAX : LowerBound + Size - 1;
+
+ return hlsl::Binding(Class, Space, LowerBound, UpperBound, nullptr);
+}
+namespace {
+/// Helper for propogating the current handle and ptr indicies.
+struct AccessIndicies {
+ Value *GetPtrIdx;
+ Value *HandleIdx;
+
+ bool hasGetPtrIdx() { return GetPtrIdx != nullptr; }
+};
+} // namespace
+
+// getAccessIndicies traverses up the control flow that a ptr came from and
+// propagates back the indicies used to access the resource (AccessIndicies):
+//
+// - GetPtrIdx is the index of dx.resource.getpointer
+// - HandleIdx is the index of dx.resource.handlefrom.*
+static AccessIndicies
+getAccessIndicies(Instruction *I,
+ SmallSetVector<Instruction *, 16> &DeadInsts) {
+ if (auto *II = dyn_cast<IntrinsicInst>(I)) {
+ if (llvm::is_contained(HandleIntrins, II->getIntrinsicID())) {
+ DeadInsts.insert(II);
+ return {nullptr, II->getArgOperand(/*Index=*/3)};
+ }
+
+ if (II->getIntrinsicID() == Intrinsic::dx_resource_getpointer) {
+ auto *V = dyn_cast<Instruction>(II->getArgOperand(/*Handle=*/0));
+ auto AccessIdx = getAccessIndicies(V, DeadInsts);
+ assert(!AccessIdx.hasGetPtrIdx() &&
+ "Encountered multiple dx.resource.getpointers in ptr chain?");
+ AccessIdx.GetPtrIdx = II->getArgOperand(1);
+
+ DeadInsts.insert(II);
+ return AccessIdx;
+ }
+ }
+
+ if (auto *Phi = dyn_cast<PHINode>(I)) {
+ unsigned NumEdges = Phi->getNumIncomingValues();
+ assert(NumEdges != 0 && "Malformed Phi Node");
+
+ IRBuilder<> Builder(Phi);
+ PHINode *GetPtrPhi = PHINode::Create(Builder.getInt32Ty(), NumEdges);
+ PHINode *HandlePhi = PHINode::Create(Builder.getInt32Ty(), NumEdges);
+
+ bool HasGetPtr = true;
+ for (unsigned I = 0; I < NumEdges; I++) {
----------------
inbelic wrote:
Whoops, updated the wrong instance. Got it now
https://github.com/llvm/llvm-project/pull/182106
More information about the llvm-commits
mailing list