LLVM 24.0.0git
DXILRemoveUnusedResources.cpp
Go to the documentation of this file.
1//===- DXILResourceAccess.cpp - Resource access via load/store ------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "DirectX.h"
10#include "llvm/ADT/SetVector.h"
12#include "llvm/IR/BasicBlock.h"
14#include "llvm/IR/Dominators.h"
15#include "llvm/IR/Instruction.h"
18#include "llvm/IR/Intrinsics.h"
19#include "llvm/IR/IntrinsicsDirectX.h"
20#include "llvm/IR/LLVMContext.h"
23
24#define DEBUG_TYPE "dxil-remove-unused-resources"
25
26// Hidden option to disable the pass to make it easier to test
27// other passes related to DXIL resources using llc.
29 "disable-dxil-remove-unused-resources",
30 llvm::cl::desc("Disable dxil-remove-unused-resources pass"),
32
33using namespace llvm;
34
36 return ID == Intrinsic::dx_resource_handlefrombinding ||
37 ID == Intrinsic::dx_resource_handlefromimplicitbinding ||
38 ID == Intrinsic::dx_resource_handlefromheap;
39}
40
41// Removes all calls to resource handle creation intrinsics that
42// either are not used, or their only use is in a store instruction, which
43// stores the initialized handle into a global variable that does not have
44// external linkage and that is not used anywhere else in the module.
47 return false;
48
51 for (BasicBlock &BB : make_early_inc_range(F)) {
52 for (Instruction &I : BB) {
53 if (auto *II = dyn_cast<IntrinsicInst>(&I)) {
54 if (!isResourceHandleCreation(II->getIntrinsicID()))
55 continue;
56 if (II->user_empty()) {
57 // Initialized handle is not used anywhere.
58 DeadInstr.push_back(II);
59 continue;
60 }
61 if (!II->hasOneUser())
62 continue;
63
64 // Initialized handle is only used in one store instruction, the store
65 // is into global variable, and that global variable is not used
66 // anywhere else and does not have external linkage.
67 auto *SI = dyn_cast<StoreInst>(*II->user_begin());
68 if (!SI)
69 continue;
70 assert(SI->getValueOperand() == II &&
71 "expected value operand to be the resource handle");
72
73 GlobalVariable *GV = dyn_cast<GlobalVariable>(SI->getPointerOperand());
74 if (!GV || GV->hasExternalLinkage())
75 continue;
76
77 if (GV->hasOneUser()) {
78 assert(*GV->user_begin() == SI &&
79 "expected single user to be the store instruction");
80 DeadInstr.push_back(SI);
81 DeadInstr.push_back(II);
82 DeadGlobals.insert(GV);
83 }
84 }
85 }
86 }
87
88 if (DeadInstr.empty())
89 return false;
90
91 for (auto *Instr : DeadInstr) {
92 if (auto *II = dyn_cast<IntrinsicInst>(Instr)) {
93 assert(isResourceHandleCreation(II->getIntrinsicID()));
94 // A heap resource does not have an associated global variable to remove.
95 if (II->getIntrinsicID() == Intrinsic::dx_resource_handlefromheap)
96 continue;
97 const unsigned ResourceNameOpIndex = 4;
99 II->getArgOperand(ResourceNameOpIndex));
100 if (ResourceName)
101 DeadGlobals.insert(ResourceName);
102 }
103 Instr->eraseFromParent();
104 }
105
106 for (auto *GV : DeadGlobals)
107 if (GV->use_empty())
108 GV->eraseFromParent();
109
110 return true;
111}
112
118
119namespace {
120class DXILRemoveUnusedResourcesLegacy : public FunctionPass {
121public:
122 bool runOnFunction(Function &F) override { return removeUnusedResources(F); }
123 StringRef getPassName() const override {
124 return "DXIL Remove Unused Resources";
125 }
126 DXILRemoveUnusedResourcesLegacy() : FunctionPass(ID) {}
127
128 static char ID; // Pass identification.
129 void getAnalysisUsage(llvm::AnalysisUsage &AU) const override {
130 AU.setPreservesAll();
131 }
132};
133char DXILRemoveUnusedResourcesLegacy::ID = 0;
134} // end anonymous namespace
135
136INITIALIZE_PASS_BEGIN(DXILRemoveUnusedResourcesLegacy, DEBUG_TYPE,
137 "DXIL Remove Unused Resources", false, false)
139INITIALIZE_PASS_END(DXILRemoveUnusedResourcesLegacy, DEBUG_TYPE,
140 "DXIL Remove Unused Resources", false, false)
141
143 return new DXILRemoveUnusedResourcesLegacy();
144}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static llvm::cl::opt< bool > DisableDXILRemoveUnusedResources("disable-dxil-remove-unused-resources", llvm::cl::desc("Disable dxil-remove-unused-resources pass"), llvm::cl::init(false), llvm::cl::Hidden)
static bool removeUnusedResources(Function &F)
static bool isResourceHandleCreation(Intrinsic::ID ID)
static bool runOnFunction(Function &F, bool PostInlining)
#define DEBUG_TYPE
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
uint64_t IntrinsicInst * II
#define INITIALIZE_PASS_DEPENDENCY(depName)
Definition PassSupport.h:42
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition PassSupport.h:44
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Definition PassSupport.h:39
This file implements a set that has insertion order iteration characteristics.
void setPreservesAll()
Set by analyses that do not transform their input at all.
LLVM Basic Block Representation.
Definition BasicBlock.h:62
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:312
bool hasExternalLinkage() const
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
bool insert(const value_type &X)
Insert a new element into the SetVector.
Definition SetVector.h:157
A SetVector that performs no allocations if smaller than a certain size.
Definition SetVector.h:346
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
user_iterator user_begin()
Definition Value.h:404
LLVM_ABI bool hasOneUser() const
Return true if there is exactly one user of this value.
Definition Value.cpp:158
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
Definition STLExtras.h:649
auto dyn_cast_or_null(const Y &Val)
Definition Casting.h:753
FunctionPass * createDXILRemoveUnusedResourcesLegacyPass()
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.