Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Target/DirectX/DXILForwardHandleAccesses.cpp
213799 views
1
//===- DXILForwardHandleAccesses.cpp - Cleanup Handles --------------------===//
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 "DXILForwardHandleAccesses.h"
10
#include "DXILShaderFlags.h"
11
#include "DirectX.h"
12
#include "llvm/Analysis/DXILResource.h"
13
#include "llvm/Analysis/Loads.h"
14
#include "llvm/IR/DiagnosticInfo.h"
15
#include "llvm/IR/Dominators.h"
16
#include "llvm/IR/IntrinsicInst.h"
17
#include "llvm/IR/Intrinsics.h"
18
#include "llvm/IR/IntrinsicsDirectX.h"
19
#include "llvm/IR/Module.h"
20
#include "llvm/InitializePasses.h"
21
#include "llvm/Pass.h"
22
#include "llvm/Transforms/Utils/Local.h"
23
24
#define DEBUG_TYPE "dxil-forward-handle-accesses"
25
26
using namespace llvm;
27
28
static void diagnoseAmbiguousHandle(IntrinsicInst *NewII,
29
IntrinsicInst *PrevII) {
30
Function *F = NewII->getFunction();
31
LLVMContext &Context = F->getParent()->getContext();
32
Context.diagnose(DiagnosticInfoGeneric(
33
Twine("Handle at \"") + NewII->getName() + "\" overwrites handle at \"" +
34
PrevII->getName() + "\""));
35
}
36
37
static void diagnoseHandleNotFound(LoadInst *LI) {
38
Function *F = LI->getFunction();
39
LLVMContext &Context = F->getParent()->getContext();
40
Context.diagnose(DiagnosticInfoGeneric(
41
LI, Twine("Load of \"") + LI->getPointerOperand()->getName() +
42
"\" is not a global resource handle"));
43
}
44
45
static void diagnoseUndominatedLoad(LoadInst *LI, IntrinsicInst *Handle) {
46
Function *F = LI->getFunction();
47
LLVMContext &Context = F->getParent()->getContext();
48
Context.diagnose(DiagnosticInfoGeneric(
49
LI, Twine("Load at \"") + LI->getName() +
50
"\" is not dominated by handle creation at \"" +
51
Handle->getName() + "\""));
52
}
53
54
static void
55
processHandle(IntrinsicInst *II,
56
DenseMap<GlobalVariable *, IntrinsicInst *> &HandleMap) {
57
for (User *U : II->users())
58
if (auto *SI = dyn_cast<StoreInst>(U))
59
if (auto *GV = dyn_cast<GlobalVariable>(SI->getPointerOperand())) {
60
auto Entry = HandleMap.try_emplace(GV, II);
61
if (Entry.second)
62
LLVM_DEBUG(dbgs() << "Added " << GV->getName() << " to handle map\n");
63
else
64
diagnoseAmbiguousHandle(II, Entry.first->second);
65
}
66
}
67
68
static bool forwardHandleAccesses(Function &F, DominatorTree &DT) {
69
bool Changed = false;
70
71
DenseMap<GlobalVariable *, IntrinsicInst *> HandleMap;
72
SmallVector<LoadInst *> LoadsToProcess;
73
for (BasicBlock &BB : F)
74
for (Instruction &Inst : BB)
75
if (auto *II = dyn_cast<IntrinsicInst>(&Inst)) {
76
switch (II->getIntrinsicID()) {
77
case Intrinsic::dx_resource_handlefrombinding:
78
case Intrinsic::dx_resource_handlefromimplicitbinding:
79
processHandle(II, HandleMap);
80
break;
81
default:
82
continue;
83
}
84
} else if (auto *LI = dyn_cast<LoadInst>(&Inst))
85
if (isa<dxil::AnyResourceExtType>(LI->getType()))
86
LoadsToProcess.push_back(LI);
87
88
for (LoadInst *LI : LoadsToProcess) {
89
Value *V = LI->getPointerOperand();
90
auto *GV = dyn_cast<GlobalVariable>(LI->getPointerOperand());
91
92
// If we didn't find the global, we may need to walk through a level of
93
// indirection. This generally happens at -O0.
94
if (!GV)
95
if (auto *NestedLI = dyn_cast<LoadInst>(V)) {
96
BasicBlock::iterator BBI(NestedLI);
97
Value *Loaded = FindAvailableLoadedValue(
98
NestedLI, NestedLI->getParent(), BBI, 0, nullptr, nullptr);
99
GV = dyn_cast_or_null<GlobalVariable>(Loaded);
100
}
101
102
auto It = HandleMap.find(GV);
103
if (It == HandleMap.end()) {
104
diagnoseHandleNotFound(LI);
105
continue;
106
}
107
Changed = true;
108
109
if (!DT.dominates(It->second, LI)) {
110
diagnoseUndominatedLoad(LI, It->second);
111
continue;
112
}
113
114
LLVM_DEBUG(dbgs() << "Replacing uses of " << GV->getName() << " at "
115
<< LI->getName() << " with " << It->second->getName()
116
<< "\n");
117
LI->replaceAllUsesWith(It->second);
118
LI->eraseFromParent();
119
}
120
121
return Changed;
122
}
123
124
PreservedAnalyses DXILForwardHandleAccesses::run(Function &F,
125
FunctionAnalysisManager &AM) {
126
PreservedAnalyses PA;
127
128
DominatorTree *DT = &AM.getResult<DominatorTreeAnalysis>(F);
129
bool Changed = forwardHandleAccesses(F, *DT);
130
131
if (!Changed)
132
return PreservedAnalyses::all();
133
return PA;
134
}
135
136
namespace {
137
class DXILForwardHandleAccessesLegacy : public FunctionPass {
138
public:
139
bool runOnFunction(Function &F) override {
140
DominatorTree *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
141
return forwardHandleAccesses(F, *DT);
142
}
143
StringRef getPassName() const override {
144
return "DXIL Forward Handle Accesses";
145
}
146
147
void getAnalysisUsage(AnalysisUsage &AU) const override {
148
AU.addRequired<DominatorTreeWrapperPass>();
149
}
150
151
DXILForwardHandleAccessesLegacy() : FunctionPass(ID) {}
152
153
static char ID; // Pass identification.
154
};
155
char DXILForwardHandleAccessesLegacy::ID = 0;
156
} // end anonymous namespace
157
158
INITIALIZE_PASS_BEGIN(DXILForwardHandleAccessesLegacy, DEBUG_TYPE,
159
"DXIL Forward Handle Accesses", false, false)
160
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
161
INITIALIZE_PASS_END(DXILForwardHandleAccessesLegacy, DEBUG_TYPE,
162
"DXIL Forward Handle Accesses", false, false)
163
164
FunctionPass *llvm::createDXILForwardHandleAccessesLegacyPass() {
165
return new DXILForwardHandleAccessesLegacy();
166
}
167
168