[llvm-branch-commits] [DirectX] Lower `@llvm.dx.handle.fromBinding` to DXIL ops (PR #104251)
Justin Bogner via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Fri Aug 23 10:52:17 PDT 2024
================
@@ -119,6 +123,119 @@ class OpLowerer {
});
}
+ Value *createTmpHandleCast(Value *V, Type *Ty) {
+ Function *CastFn = Intrinsic::getDeclaration(&M, Intrinsic::dx_cast_handle,
+ {Ty, V->getType()});
+ CallInst *Cast = OpBuilder.getIRB().CreateCall(CastFn, {V});
+ CleanupCasts.push_back(Cast);
+ return Cast;
+ }
+
+ void cleanupHandleCasts() {
+ SmallVector<CallInst *> ToRemove;
+ SmallVector<Function *> CastFns;
+
+ for (CallInst *Cast : CleanupCasts) {
+ CastFns.push_back(Cast->getCalledFunction());
+ // All of the ops should be using `dx.types.Handle` at this point, so if
+ // we're not producing that we should be part of a pair. Track this so we
+ // can remove it at the end.
+ if (Cast->getType() != OpBuilder.getHandleType()) {
+ ToRemove.push_back(Cast);
+ continue;
+ }
+ // Otherwise, we're the second handle in a pair. Forward the arguments and
+ // remove the (second) cast.
+ CallInst *Def = cast<CallInst>(Cast->getOperand(0));
+ assert(Def->getIntrinsicID() == Intrinsic::dx_cast_handle &&
+ "Unbalanced pair of temporary handle casts");
+ Cast->replaceAllUsesWith(Def->getOperand(0));
+ Cast->eraseFromParent();
+ }
+ for (CallInst *Cast : ToRemove) {
+ assert(Cast->user_empty() && "Temporary handle cast still has users");
+ Cast->eraseFromParent();
+ }
+ llvm::sort(CastFns);
+ CastFns.erase(llvm::unique(CastFns), CastFns.end());
+ for (Function *F : CastFns)
+ F->eraseFromParent();
+
+ CleanupCasts.clear();
+ }
+
+ void lowerToCreateHandle(Function &F) {
+ IRBuilder<> &IRB = OpBuilder.getIRB();
+ Type *Int8Ty = IRB.getInt8Ty();
+ Type *Int32Ty = IRB.getInt32Ty();
+
+ replaceFunction(F, [&](CallInst *CI) -> Error {
+ IRB.SetInsertPoint(CI);
+
+ dxil::ResourceInfo &RI = DRM[CI];
+ dxil::ResourceInfo::ResourceBinding Binding = RI.getBinding();
+
+ std::array<Value *, 4> Args{
+ ConstantInt::get(Int8Ty, llvm::to_underlying(RI.getResourceClass())),
+ ConstantInt::get(Int32Ty, Binding.RecordID), CI->getArgOperand(3),
+ CI->getArgOperand(4)};
+ Expected<CallInst *> OpCall =
+ OpBuilder.tryCreateOp(OpCode::CreateHandle, Args);
+ if (Error E = OpCall.takeError())
+ return E;
+
+ Value *Cast = createTmpHandleCast(*OpCall, CI->getType());
+
+ CI->replaceAllUsesWith(Cast);
+ CI->eraseFromParent();
+ return Error::success();
+ });
+ }
+
+ void lowerToBindAndAnnotateHandle(Function &F) {
+ IRBuilder<> &IRB = OpBuilder.getIRB();
+
+ replaceFunction(F, [&](CallInst *CI) -> Error {
+ IRB.SetInsertPoint(CI);
+
+ dxil::ResourceInfo &RI = DRM[CI];
+ dxil::ResourceInfo::ResourceBinding Binding = RI.getBinding();
+ std::pair<uint32_t, uint32_t> Props = RI.getAnnotateProps();
+
+ Constant *ResBind = OpBuilder.getResBind(
+ Binding.LowerBound, Binding.LowerBound + Binding.Size - 1,
+ Binding.Space, RI.getResourceClass());
+ std::array<Value *, 3> BindArgs{ResBind, CI->getArgOperand(3),
+ CI->getArgOperand(4)};
+ Expected<CallInst *> OpBind =
+ OpBuilder.tryCreateOp(OpCode::CreateHandleFromBinding, BindArgs);
+ if (Error E = OpBind.takeError())
+ return E;
+
+ std::array<Value *, 2> AnnotateArgs{
+ *OpBind, OpBuilder.getResProps(Props.first, Props.second)};
+ Expected<CallInst *> OpAnnotate =
+ OpBuilder.tryCreateOp(OpCode::AnnotateHandle, AnnotateArgs);
+ if (Error E = OpAnnotate.takeError())
+ return E;
+
+ Value *Cast = createTmpHandleCast(*OpAnnotate, CI->getType());
+
+ CI->replaceAllUsesWith(Cast);
+ CI->eraseFromParent();
+
+ return Error::success();
+ });
+ }
+
+ void lowerHandleFromBinding(Function &F) {
----------------
bogner wrote:
I added a small doc comment here and a bigger doc comment on the `createTmpHandleCast` function to explain what it's for.
https://github.com/llvm/llvm-project/pull/104251
More information about the llvm-branch-commits
mailing list