LLVM 20.0.0git
NVPTXImageOptimizer.cpp
Go to the documentation of this file.
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"
20#include "llvm/IR/Intrinsics.h"
21#include "llvm/IR/IntrinsicsNVPTX.h"
22#include "llvm/IR/Module.h"
23#include "llvm/Pass.h"
24
25using namespace llvm;
26
27namespace {
28class NVPTXImageOptimizer : public FunctionPass {
29private:
30 static char ID;
31 SmallVector<Instruction*, 4> InstrToDelete;
32
33public:
34 NVPTXImageOptimizer();
35
36 bool runOnFunction(Function &F) override;
37
38 StringRef getPassName() const override { return "NVPTX Image Optimizer"; }
39
40private:
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
49char NVPTXImageOptimizer::ID = 0;
50
51NVPTXImageOptimizer::NVPTXImageOptimizer()
52 : FunctionPass(ID) {}
53
54bool 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
92bool 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
108bool 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
127bool 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
146void 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
168Value *NVPTXImageOptimizer::cleanupValue(Value *V) {
169 if (ExtractValueInst *EVI = dyn_cast<ExtractValueInst>(V)) {
170 return cleanupValue(EVI->getAggregateOperand());
171 }
172 return V;
173}
174
176 return new NVPTXImageOptimizer();
177}
BlockVerifier::State From
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
Module.h This file contains the declarations for the Module class.
LLVM Basic Block Representation.
Definition: BasicBlock.h:61
Conditional or Unconditional Branch instruction.
static BranchInst * Create(BasicBlock *IfTrue, InsertPosition InsertBefore=nullptr)
This class represents a function call, abstracting a target machine's calling convention.
This is the shared class of boolean and integer constants.
Definition: Constants.h:81
static ConstantInt * getTrue(LLVMContext &Context)
Definition: Constants.cpp:850
bool isZero() const
This is just a convenience method to make client code smaller for a common code.
Definition: Constants.h:206
static ConstantInt * getFalse(LLVMContext &Context)
Definition: Constants.cpp:857
This instruction extracts a struct member or array element value from an aggregate value.
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:310
virtual bool runOnFunction(Function &F)=0
runOnFunction - Virtual method overriden by subclasses to do the per-function processing of the pass.
Intrinsic::ID getIntrinsicID() const LLVM_READONLY
getIntrinsicID - This method returns the ID number of the specified function, or Intrinsic::not_intri...
Definition: Function.h:249
bool isIntrinsic() const
isIntrinsic - Returns true if the function's name starts with "llvm.".
Definition: Function.h:254
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Definition: Pass.cpp:81
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1210
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
A Use represents the edge between a Value definition and its users.
Definition: Use.h:43
LLVM Value Representation.
Definition: Value.h:74
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
bool isImage(const Value &val)
bool isImageReadOnly(const Value &val)
FunctionPass * createNVPTXImageOptimizerPass()
bool isImageWriteOnly(const Value &val)
bool isImageReadWrite(const Value &val)
bool isSampler(const Value &val)