21#include "llvm/IR/IntrinsicsDirectX.h"
27#define DEBUG_TYPE "dxil-forward-handle-accesses"
36 Twine(
"Handle at \"") + NewII->
getName() +
"\" overwrites handle at \"" +
45 "\" is not a global resource handle"));
53 "\" is not dominated by handle creation at \"" +
60 for (
User *U :
II->users())
61 if (
auto *SI = dyn_cast<StoreInst>(U))
62 if (
auto *GV = dyn_cast<GlobalVariable>(SI->getPointerOperand())) {
65 LLVM_DEBUG(
dbgs() <<
"Added " << GV->getName() <<
" to handle map\n");
79 if (
auto *
II = dyn_cast<IntrinsicInst>(&Inst)) {
80 switch (
II->getIntrinsicID()) {
81 case Intrinsic::dx_resource_handlefrombinding:
82 case Intrinsic::dx_resource_handlefromimplicitbinding:
85 case Intrinsic::lifetime_start:
86 case Intrinsic::lifetime_end:
87 if (
II->arg_size() >= 1) {
89 if (
auto *Alloca = dyn_cast<AllocaInst>(
Ptr))
90 LifeTimeIntrinsicMap[Alloca].push_back(
II);
96 }
else if (
auto *LI = dyn_cast<LoadInst>(&Inst))
97 if (isa<dxil::AnyResourceExtType>(LI->getType()))
100 for (
LoadInst *LI : LoadsToProcess) {
101 Value *V = LI->getPointerOperand();
102 auto *GV = dyn_cast<GlobalVariable>(V);
107 if (
auto *NestedLI = dyn_cast<LoadInst>(V)) {
110 NestedLI, NestedLI->getParent(), BBI, 0,
nullptr,
nullptr);
111 GV = dyn_cast_or_null<GlobalVariable>(Loaded);
112 }
else if (
auto *NestedAlloca = dyn_cast<AllocaInst>(V)) {
114 if (
auto It = LifeTimeIntrinsicMap.
find(NestedAlloca);
115 It != LifeTimeIntrinsicMap.
end()) {
118 LifeTimeIntrinsicMap.
erase(It);
121 for (
auto *
User : NestedAlloca->
users()) {
122 auto *Store = dyn_cast<StoreInst>(
User);
126 Value *StoredVal = Store->getValueOperand();
131 GV = dyn_cast<GlobalVariable>(StoredVal);
136 if (
auto *Load = dyn_cast<LoadInst>(StoredVal)) {
137 GV = dyn_cast<GlobalVariable>(Load->getPointerOperand());
146 BBI, 0,
nullptr,
nullptr);
147 GV = dyn_cast<GlobalVariable>(Loaded);
155 auto It = HandleMap.
find(GV);
156 if (It == HandleMap.
end()) {
167 LLVM_DEBUG(
dbgs() <<
"Replacing uses of " << GV->getName() <<
" at "
168 << LI->getName() <<
" with " << It->second->getName()
170 LI->replaceAllUsesWith(It->second);
171 LI->eraseFromParent();
190class DXILForwardHandleAccessesLegacy :
public FunctionPass {
193 DominatorTree *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
197 return "DXIL Forward Handle Accesses";
208char DXILForwardHandleAccessesLegacy::ID = 0;
212 "DXIL Forward Handle Accesses",
false,
false)
218 return new DXILForwardHandleAccessesLegacy();
static void diagnoseHandleNotFound(LoadInst *LI)
static void diagnoseUndominatedLoad(LoadInst *LI, IntrinsicInst *Handle)
static void diagnoseAmbiguousHandle(IntrinsicInst *NewII, IntrinsicInst *PrevII)
DXIL Forward Handle Accesses
static bool forwardHandleAccesses(Function &F, DominatorTree &DT)
static void processHandle(IntrinsicInst *II, DenseMap< GlobalVariable *, IntrinsicInst * > &HandleMap)
static bool runOnFunction(Function &F, bool PostInlining)
Module.h This file contains the declarations for the Module class.
uint64_t IntrinsicInst * II
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
A container for analyses that lazily runs them and caches their results.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
LLVM Basic Block Representation.
InstListType::iterator iterator
Instruction iterators...
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
iterator find(const_arg_type_t< KeyT > Val)
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
bool erase(const KeyT &Val)
Analysis pass which computes a DominatorTree.
Legacy analysis pass which computes a DominatorTree.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
LLVM_ABI bool dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
FunctionPass class - This class is used to implement most global optimizations.
LLVM_ABI const Function * getFunction() const
Return the function this instruction belongs to.
A wrapper class for inspecting calls to intrinsic functions.
This is an important class for using LLVM in a threaded context.
An instruction for reading from memory.
Value * getPointerOperand()
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
LLVM Value Representation.
iterator_range< user_iterator > users()
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
This is an optimization pass for GlobalISel generic memory operations.
UnaryFunction for_each(R &&Range, UnaryFunction F)
Provide wrappers to std::for_each which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI Value * FindAvailableLoadedValue(LoadInst *Load, BasicBlock *ScanBB, BasicBlock::iterator &ScanFrom, unsigned MaxInstsToScan=DefMaxInstsToScan, BatchAAResults *AA=nullptr, bool *IsLoadCSE=nullptr, unsigned *NumScanedInst=nullptr)
Scan backwards to see if we have the value of the given load available locally within a small number ...
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
FunctionPass * createDXILForwardHandleAccessesLegacyPass()
Pass to eliminate redundant stores and loads from handle globals.