Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Target/NVPTX/NVPTXImageOptimizer.cpp
35271 views
1
//===-- NVPTXImageOptimizer.cpp - Image optimization pass -----------------===//
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
// This pass implements IR-level optimizations of image access code,
10
// including:
11
//
12
// 1. Eliminate istypep intrinsics when image access qualifier is known
13
//
14
//===----------------------------------------------------------------------===//
15
16
#include "NVPTX.h"
17
#include "NVPTXUtilities.h"
18
#include "llvm/Analysis/ConstantFolding.h"
19
#include "llvm/IR/Instructions.h"
20
#include "llvm/IR/Intrinsics.h"
21
#include "llvm/IR/IntrinsicsNVPTX.h"
22
#include "llvm/IR/Module.h"
23
#include "llvm/Pass.h"
24
25
using namespace llvm;
26
27
namespace {
28
class NVPTXImageOptimizer : public FunctionPass {
29
private:
30
static char ID;
31
SmallVector<Instruction*, 4> InstrToDelete;
32
33
public:
34
NVPTXImageOptimizer();
35
36
bool runOnFunction(Function &F) override;
37
38
StringRef getPassName() const override { return "NVPTX Image Optimizer"; }
39
40
private:
41
bool replaceIsTypePSampler(Instruction &I);
42
bool replaceIsTypePSurface(Instruction &I);
43
bool replaceIsTypePTexture(Instruction &I);
44
Value *cleanupValue(Value *V);
45
void replaceWith(Instruction *From, ConstantInt *To);
46
};
47
}
48
49
char NVPTXImageOptimizer::ID = 0;
50
51
NVPTXImageOptimizer::NVPTXImageOptimizer()
52
: FunctionPass(ID) {}
53
54
bool NVPTXImageOptimizer::runOnFunction(Function &F) {
55
if (skipFunction(F))
56
return false;
57
58
bool Changed = false;
59
InstrToDelete.clear();
60
61
// Look for call instructions in the function
62
for (BasicBlock &BB : F) {
63
for (Instruction &Instr : BB) {
64
if (CallInst *CI = dyn_cast<CallInst>(&Instr)) {
65
Function *CalledF = CI->getCalledFunction();
66
if (CalledF && CalledF->isIntrinsic()) {
67
// This is an intrinsic function call, check if its an istypep
68
switch (CalledF->getIntrinsicID()) {
69
default: break;
70
case Intrinsic::nvvm_istypep_sampler:
71
Changed |= replaceIsTypePSampler(Instr);
72
break;
73
case Intrinsic::nvvm_istypep_surface:
74
Changed |= replaceIsTypePSurface(Instr);
75
break;
76
case Intrinsic::nvvm_istypep_texture:
77
Changed |= replaceIsTypePTexture(Instr);
78
break;
79
}
80
}
81
}
82
}
83
}
84
85
// Delete any istypep instances we replaced in the IR
86
for (Instruction *I : InstrToDelete)
87
I->eraseFromParent();
88
89
return Changed;
90
}
91
92
bool NVPTXImageOptimizer::replaceIsTypePSampler(Instruction &I) {
93
Value *TexHandle = cleanupValue(I.getOperand(0));
94
if (isSampler(*TexHandle)) {
95
// This is an OpenCL sampler, so it must be a samplerref
96
replaceWith(&I, ConstantInt::getTrue(I.getContext()));
97
return true;
98
} else if (isImage(*TexHandle)) {
99
// This is an OpenCL image, so it cannot be a samplerref
100
replaceWith(&I, ConstantInt::getFalse(I.getContext()));
101
return true;
102
} else {
103
// The image type is unknown, so we cannot eliminate the intrinsic
104
return false;
105
}
106
}
107
108
bool NVPTXImageOptimizer::replaceIsTypePSurface(Instruction &I) {
109
Value *TexHandle = cleanupValue(I.getOperand(0));
110
if (isImageReadWrite(*TexHandle) ||
111
isImageWriteOnly(*TexHandle)) {
112
// This is an OpenCL read-only/read-write image, so it must be a surfref
113
replaceWith(&I, ConstantInt::getTrue(I.getContext()));
114
return true;
115
} else if (isImageReadOnly(*TexHandle) ||
116
isSampler(*TexHandle)) {
117
// This is an OpenCL read-only/ imageor sampler, so it cannot be
118
// a surfref
119
replaceWith(&I, ConstantInt::getFalse(I.getContext()));
120
return true;
121
} else {
122
// The image type is unknown, so we cannot eliminate the intrinsic
123
return false;
124
}
125
}
126
127
bool NVPTXImageOptimizer::replaceIsTypePTexture(Instruction &I) {
128
Value *TexHandle = cleanupValue(I.getOperand(0));
129
if (isImageReadOnly(*TexHandle)) {
130
// This is an OpenCL read-only image, so it must be a texref
131
replaceWith(&I, ConstantInt::getTrue(I.getContext()));
132
return true;
133
} else if (isImageWriteOnly(*TexHandle) ||
134
isImageReadWrite(*TexHandle) ||
135
isSampler(*TexHandle)) {
136
// This is an OpenCL read-write/write-only image or a sampler, so it
137
// cannot be a texref
138
replaceWith(&I, ConstantInt::getFalse(I.getContext()));
139
return true;
140
} else {
141
// The image type is unknown, so we cannot eliminate the intrinsic
142
return false;
143
}
144
}
145
146
void NVPTXImageOptimizer::replaceWith(Instruction *From, ConstantInt *To) {
147
// We implement "poor man's DCE" here to make sure any code that is no longer
148
// live is actually unreachable and can be trivially eliminated by the
149
// unreachable block elimination pass.
150
for (Use &U : From->uses()) {
151
if (BranchInst *BI = dyn_cast<BranchInst>(U)) {
152
if (BI->isUnconditional()) continue;
153
BasicBlock *Dest;
154
if (To->isZero())
155
// Get false block
156
Dest = BI->getSuccessor(1);
157
else
158
// Get true block
159
Dest = BI->getSuccessor(0);
160
BranchInst::Create(Dest, BI->getIterator());
161
InstrToDelete.push_back(BI);
162
}
163
}
164
From->replaceAllUsesWith(To);
165
InstrToDelete.push_back(From);
166
}
167
168
Value *NVPTXImageOptimizer::cleanupValue(Value *V) {
169
if (ExtractValueInst *EVI = dyn_cast<ExtractValueInst>(V)) {
170
return cleanupValue(EVI->getAggregateOperand());
171
}
172
return V;
173
}
174
175
FunctionPass *llvm::createNVPTXImageOptimizerPass() {
176
return new NVPTXImageOptimizer();
177
}
178
179