LLVM 24.0.0git
SPIRVRemoveUnusedResources.cpp
Go to the documentation of this file.
1//===- SPIRVRemoveUnusedResources.cpp - Remove unused resources ----------===//
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// \file Pass for removing unused resources and their associated
10// global variables
11//
12//===----------------------------------------------------------------------===//
13
14#include "SPIRV.h"
15#include "llvm/ADT/STLExtras.h"
16#include "llvm/ADT/SetVector.h"
22#include "llvm/IR/IntrinsicsSPIRV.h"
23#include "llvm/IR/Module.h"
24#include "llvm/Pass.h"
26
27#define DEBUG_TYPE "spirv-remove-unused-resources"
28
29using namespace llvm;
30
32 "disable-spirv-remove-unused-resources",
33 cl::desc("Disable spirv-remove-unused-resources pass"), cl::init(false),
35
38 return false;
39
41 SmallVector<IntrinsicInst *> CounterHandles;
43
44 for (Function &F : M) {
45 for (Instruction &I : instructions(F)) {
46 if (auto *II = dyn_cast<IntrinsicInst>(&I)) {
47 switch (II->getIntrinsicID()) {
48 default:
49 continue;
50 case Intrinsic::spv_resource_handlefrombinding:
51 case Intrinsic::spv_resource_handlefromimplicitbinding:
52 Handles.push_back(II);
53 break;
54 case Intrinsic::spv_resource_counterhandlefrombinding:
55 case Intrinsic::spv_resource_counterhandlefromimplicitbinding:
56 CounterHandles.push_back(II);
57 break;
58 }
59 }
60 }
61 }
62
63 bool Changed = false;
64
65 auto VisitHandle = [&](Instruction *Handle, bool IsCounter) {
66 for (User *U : make_early_inc_range(Handle->users())) {
67 auto *SI = dyn_cast<StoreInst>(U);
68 if (!SI || SI->isVolatile() || SI->getValueOperand() != Handle)
69 continue;
70 auto *GV = dyn_cast<GlobalVariable>(SI->getPointerOperand());
71 if (!GV || !GV->hasLocalLinkage() || !GV->hasOneUser())
72 continue;
73 SI->eraseFromParent();
74 DeadGlobals.insert(GV);
75 Changed = true;
76 }
77
78 const unsigned ResourceNameOpIndex = 4;
79 if (Handle->use_empty()) {
80 if (!IsCounter) {
81 if (auto *Name = dyn_cast<GlobalVariable>(
82 Handle->getOperand(ResourceNameOpIndex)))
83 DeadGlobals.insert(Name);
84 }
85 Handle->eraseFromParent();
86 Changed = true;
87 }
88 };
89
90 // Visit implicit counters first since they may use other handles
91 // that are otherwise dead
92 for (auto *Counter : CounterHandles)
93 VisitHandle(Counter, true);
94 for (auto *Handle : Handles)
95 VisitHandle(Handle, false);
96
97 for (auto *GV : DeadGlobals) {
98 if (GV->user_empty()) {
99 GV->eraseFromParent();
100 Changed = true;
101 }
102 }
103
104 return Changed;
105}
106
112
113namespace {
114class SPIRVRemoveUnusedResourcesLegacy : public ModulePass {
115public:
116 SPIRVRemoveUnusedResourcesLegacy() : ModulePass(ID) {}
117
118 bool runOnModule(Module &M) override { return removeUnusedResources(M); }
119
120 StringRef getPassName() const override {
121 return "SPIRV Remove Unused Resources";
122 }
123
124 static char ID;
125};
126char SPIRVRemoveUnusedResourcesLegacy::ID = 0;
127} // namespace
128
129INITIALIZE_PASS(SPIRVRemoveUnusedResourcesLegacy, DEBUG_TYPE,
130 "SPIRV Remove Unused Resources", false, false)
131
133 return new SPIRVRemoveUnusedResourcesLegacy();
134}
Expand Atomic instructions
static bool removeUnusedResources(Function &F)
#define DEBUG_TYPE
Module.h This file contains the declarations for the Module class.
#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(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
static bool removeUnusedResources(Module &M)
static cl::opt< bool > DisableSPIRVRemoveUnusedResources("disable-spirv-remove-unused-resources", cl::desc("Disable spirv-remove-unused-resources pass"), cl::init(false), cl::Hidden)
This file contains some templates that are useful if you are working with the STL at all.
This file implements a set that has insertion order iteration characteristics.
This file defines the SmallVector class.
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
iterator_range< user_iterator > users()
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Definition Pass.h:253
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:68
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
Definition Analysis.h:115
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
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:345
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Value * getOperand(unsigned i) const
Definition User.h:207
bool use_empty() const
Definition Value.h:348
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
ModulePass * createSPIRVRemoveUnusedResourcesLegacyPass()
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
Definition MIRParser.h:39