[DirectX] Remove unused heap resources (#218093) Add handling of `llvm.dx.resource.handlefromheap` to `DXILRemoveUnusedResources` pass. In practice heap resources are usually assigned to local variables, and get cleaned up in earlier passes if unused. If that does not happen for some reason, they get removed by `DXILRemoveUnusedResources`. Related to #208053 GitOrigin-RevId: 646f69cafd20589fe3eb08ce04c43a8b914e9181
diff --git a/lib/Target/DirectX/DXILRemoveUnusedResources.cpp b/lib/Target/DirectX/DXILRemoveUnusedResources.cpp index aa05f58..6a2d0fb 100644 --- a/lib/Target/DirectX/DXILRemoveUnusedResources.cpp +++ b/lib/Target/DirectX/DXILRemoveUnusedResources.cpp
@@ -33,7 +33,13 @@ using namespace llvm; -// Removes all calls to intrinsics dx_resource_handlefrom{implicit}binding that +static bool isResourceHandleCreation(Intrinsic::ID ID) { + return ID == Intrinsic::dx_resource_handlefrombinding || + ID == Intrinsic::dx_resource_handlefromimplicitbinding || + ID == Intrinsic::dx_resource_handlefromheap; +} + +// Removes all calls to resource handle creation intrinsics that // either are not used, or their only use is in a store instruction, which // stores the initialized handle into a global variable that does not have // external linkage and that is not used anywhere else in the module. @@ -46,9 +52,7 @@ for (BasicBlock &BB : make_early_inc_range(F)) { for (Instruction &I : BB) { if (auto *II = dyn_cast<IntrinsicInst>(&I)) { - if (II->getIntrinsicID() != Intrinsic::dx_resource_handlefrombinding && - II->getIntrinsicID() != - Intrinsic::dx_resource_handlefromimplicitbinding) + if (!isResourceHandleCreation(II->getIntrinsicID())) continue; if (II->user_empty()) { // Initialized handle is not used anywhere. @@ -87,9 +91,10 @@ for (auto *Instr : DeadInstr) { if (auto *II = dyn_cast<IntrinsicInst>(Instr)) { - assert(II->getIntrinsicID() == Intrinsic::dx_resource_handlefrombinding || - II->getIntrinsicID() == - Intrinsic::dx_resource_handlefromimplicitbinding); + assert(isResourceHandleCreation(II->getIntrinsicID())); + // A heap resource does not have an associated global variable to remove. + if (II->getIntrinsicID() == Intrinsic::dx_resource_handlefromheap) + continue; const unsigned ResourceNameOpIndex = 4; GlobalVariable *ResourceName = dyn_cast_or_null<GlobalVariable>( II->getArgOperand(ResourceNameOpIndex));
diff --git a/test/CodeGen/DirectX/unused-resources.ll b/test/CodeGen/DirectX/unused-resources.ll index b11638c..ae9d565 100644 --- a/test/CodeGen/DirectX/unused-resources.ll +++ b/test/CodeGen/DirectX/unused-resources.ll
@@ -7,6 +7,7 @@ ; - unused resource initialization calls ; - unused cbuffers and associated global variables ; - resource name strings +; - unused resource handles created from the descriptor heap %__cblayout_CB = type <{ i32, float }> %"__cblayout_$Globals" = type <{ i32, float }> @@ -37,6 +38,10 @@ @llvm.dx.resource.handlefrombinding(i32 0, i32 6, i32 1, i32 0, ptr @Buf.str) store target("dx.RawBuffer", i16, 1, 0) %uav_handle, ptr @_ZL3Buf, align 4 +; Heap resource + %heap_handle = call target("dx.RawBuffer", i16, 1, 0) + @llvm.dx.resource.handlefromheap(i32 0) + ret void } @@ -55,6 +60,7 @@ ; CHECK-NOT: @Buf.str ; CHECK-NOT: call {{.*}} llvm.dx.resource.handlefrombinding ; CHECK-NOT: call {{.*}} llvm.dx.resource.handlefromimplicitbinding +; CHECK-NOT: call {{.*}} llvm.dx.resource.handlefromheap ; Make sure the resource bindings table is empty ; CHECK-PRINT: ; Resource Bindings: