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
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
37 return ID == Intrinsic::dx_resource_handlefrombinding ||
38 ID == Intrinsic::dx_resource_handlefromimplicitbinding ||
39 ID == Intrinsic::dx_resource_handlefromheap;
40}
41
42// Removes all calls to resource handle creation intrinsics that
43// either are not used, or their only use is in a store instruction, which
44// stores the initialized handle into a global variable that does not have
45// external linkage and that is not used anywhere else in the module.
48 return false;
49
52 for (BasicBlock &BB : make_early_inc_range(F)) {
53 for (Instruction &I : BB) {
54 if (auto *II = dyn_cast<IntrinsicInst>(&I)) {
55 if (!isResourceHandleCreation(II->getIntrinsicID()))
56 continue;
57 if (II->user_empty()) {
58 // Initialized handle is not used anywhere.
59 DeadInstr.push_back(II);
60 continue;
61 }
62 if (!II->hasOneUser())
63 continue;
64
65 // Initialized handle is only used in one store instruction, the store
66 // is into global variable, and that global variable is not used
67 // anywhere else and does not have external linkage.
68 auto *SI = dyn_cast<StoreInst>(*II->user_begin());
69 if (!SI)
70 continue;
71 assert(SI->getValueOperand() == II &&
72 "expected value operand to be the resource handle");
73
74 GlobalVariable *GV = dyn_cast<GlobalVariable>(SI->getPointerOperand());
75 if (!GV || GV->hasExternalLinkage())
76 continue;
77
78 if (GV->hasOneUser()) {
79 assert(*GV->user_begin() == SI &&
80 "expected single user to be the store instruction");
81 DeadInstr.push_back(SI);
82 DeadInstr.push_back(II);
83 DeadGlobals.insert(GV);
84 }
85 }
86 }
87 }
88
89 if (DeadInstr.empty())
90 return false;
91
92 for (auto *Instr : DeadInstr) {
93 if (auto *II = dyn_cast<IntrinsicInst>(Instr)) {
94 assert(isResourceHandleCreation(II->getIntrinsicID()));
95 // A heap resource does not have an associated global variable to remove.
96 if (II->getIntrinsicID() == Intrinsic::dx_resource_handlefromheap)
97 continue;
98 const unsigned ResourceNameOpIndex = 4;
100 II->getArgOperand(ResourceNameOpIndex));
101 if (ResourceName)
102 DeadGlobals.insert(ResourceName);
103 }
104 Instr->eraseFromParent();
105 }
106
107 for (auto *GV : DeadGlobals)
108 if (GV->use_empty())
109 GV->eraseFromParent();
110
111 return true;
112}
113
119
120namespace {
121class DXILRemoveUnusedResourcesLegacy : public FunctionPass {
122public:
123 bool runOnFunction(Function &F) override { return removeUnusedResources(F); }
124 StringRef getPassName() const override {
125 return "DXIL Remove Unused Resources";
126 }
127 DXILRemoveUnusedResourcesLegacy() : FunctionPass(ID) {}
128
129 static char ID; // Pass identification.
130 void getAnalysisUsage(llvm::AnalysisUsage &AU) const override {
131 AU.setPreservesAll();
132 }
133};
134char DXILRemoveUnusedResourcesLegacy::ID = 0;
135} // end anonymous namespace
136
137INITIALIZE_PASS_BEGIN(DXILRemoveUnusedResourcesLegacy, DEBUG_TYPE,
138 "DXIL Remove Unused Resources", false, false)
140INITIALIZE_PASS_END(DXILRemoveUnusedResourcesLegacy, DEBUG_TYPE,
141 "DXIL Remove Unused Resources", false, false)
142
144 return new DXILRemoveUnusedResourcesLegacy();
145}
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: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: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.
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
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.