LLVM 23.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
10#include "DirectX.h"
11#include "llvm/ADT/SetVector.h"
13#include "llvm/IR/BasicBlock.h"
15#include "llvm/IR/Dominators.h"
16#include "llvm/IR/Instruction.h"
19#include "llvm/IR/Intrinsics.h"
20#include "llvm/IR/IntrinsicsDirectX.h"
21#include "llvm/IR/LLVMContext.h"
24
25#define DEBUG_TYPE "dxil-remove-unused-resources"
26
27// Hidden option to disable the pass to make it easier to test
28// other passes related to DXIL resources using llc.
30 "disable-dxil-remove-unused-resources",
31 llvm::cl::desc("Disable dxil-remove-unused-resources pass"),
33
34using namespace llvm;
35
36// Removes all calls to intrinsics dx_resource_handlefrom{implicit}binding that
37// either are not used, or their only use is in a store instruction, which
38// stores the initialized handle into a global variable that does not have
39// external linkage and that is not used anywhere else in the module.
42 return false;
43
46 for (BasicBlock &BB : make_early_inc_range(F)) {
47 for (Instruction &I : BB) {
48 if (auto *II = dyn_cast<IntrinsicInst>(&I)) {
49 if (II->getIntrinsicID() != Intrinsic::dx_resource_handlefrombinding &&
50 II->getIntrinsicID() !=
51 Intrinsic::dx_resource_handlefromimplicitbinding)
52 continue;
53 if (II->user_empty()) {
54 // Initialized handle is not used anywhere.
55 DeadInstr.push_back(II);
56 continue;
57 }
58 if (!II->hasOneUser())
59 continue;
60
61 // Initialized handle is only used in one store instruction, the store
62 // is into global variable, and that global variable is not used
63 // anywhere else and does not have external linkage.
64 auto *SI = dyn_cast<StoreInst>(*II->user_begin());
65 if (!SI)
66 continue;
67 assert(SI->getValueOperand() == II &&
68 "expected value operand to be the resource handle");
69
70 GlobalVariable *GV = dyn_cast<GlobalVariable>(SI->getPointerOperand());
71 if (!GV || GV->hasExternalLinkage())
72 continue;
73
74 if (GV->hasOneUser()) {
75 assert(*GV->user_begin() == SI &&
76 "expected single user to be the store instruction");
77 DeadInstr.push_back(SI);
78 DeadInstr.push_back(II);
79 DeadGlobals.insert(GV);
80 }
81 }
82 }
83 }
84
85 if (DeadInstr.empty())
86 return false;
87
88 for (auto *Instr : DeadInstr) {
89 if (auto *II = dyn_cast<IntrinsicInst>(Instr)) {
90 assert(II->getIntrinsicID() == Intrinsic::dx_resource_handlefrombinding ||
91 II->getIntrinsicID() ==
92 Intrinsic::dx_resource_handlefromimplicitbinding);
93 const unsigned ResourceNameOpIndex = 4;
95 II->getArgOperand(ResourceNameOpIndex));
96 if (ResourceName)
97 DeadGlobals.insert(ResourceName);
98 }
99 Instr->eraseFromParent();
100 }
101
102 for (auto *GV : DeadGlobals)
103 if (GV->use_empty())
104 GV->eraseFromParent();
105
106 return true;
107}
108
114
115namespace {
116class DXILRemoveUnusedResourcesLegacy : public FunctionPass {
117public:
118 bool runOnFunction(Function &F) override { return removeUnusedResources(F); }
119 StringRef getPassName() const override {
120 return "DXIL Remove Unused Resources";
121 }
122 DXILRemoveUnusedResourcesLegacy() : FunctionPass(ID) {}
123
124 static char ID; // Pass identification.
125 void getAnalysisUsage(llvm::AnalysisUsage &AU) const override {
126 AU.setPreservesAll();
127 }
128};
129char DXILRemoveUnusedResourcesLegacy::ID = 0;
130} // end anonymous namespace
131
132INITIALIZE_PASS_BEGIN(DXILRemoveUnusedResourcesLegacy, DEBUG_TYPE,
133 "DXIL Remove Unused Resources", false, false)
135INITIALIZE_PASS_END(DXILRemoveUnusedResourcesLegacy, DEBUG_TYPE,
136 "DXIL Remove Unused Resources", false, false)
137
139 return new DXILRemoveUnusedResourcesLegacy();
140}
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 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:314
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:151
A SetVector that performs no allocations if smaller than a certain size.
Definition SetVector.h:339
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:402
LLVM_ABI bool hasOneUser() const
Return true if there is exactly one user of this value.
Definition Value.cpp:163
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
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:633
auto dyn_cast_or_null(const Y &Val)
Definition Casting.h:753
FunctionPass * createDXILRemoveUnusedResourcesLegacyPass()
Pass to update remove unsused resources.
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.