1 //===-- NVPTXImageOptimizer.cpp - Image optimization pass -----------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This pass implements IR-level optimizations of image access code,
12 // 1. Eliminate istypep intrinsics when image access qualifier is known
14 //===----------------------------------------------------------------------===//
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"
28 class NVPTXImageOptimizer : public FunctionPass {
31 SmallVector<Instruction*, 4> InstrToDelete;
34 NVPTXImageOptimizer();
36 bool runOnFunction(Function &F) override;
39 bool replaceIsTypePSampler(Instruction &I);
40 bool replaceIsTypePSurface(Instruction &I);
41 bool replaceIsTypePTexture(Instruction &I);
42 Value *cleanupValue(Value *V);
43 void replaceWith(Instruction *From, ConstantInt *To);
47 char NVPTXImageOptimizer::ID = 0;
49 NVPTXImageOptimizer::NVPTXImageOptimizer()
52 bool NVPTXImageOptimizer::runOnFunction(Function &F) {
57 InstrToDelete.clear();
59 // Look for call instructions in the function
60 for (Function::iterator BI = F.begin(), BE = F.end(); BI != BE;
62 for (BasicBlock::iterator I = (*BI).begin(), E = (*BI).end();
64 Instruction &Instr = *I;
65 if (CallInst *CI = dyn_cast<CallInst>(I)) {
66 Function *CalledF = CI->getCalledFunction();
67 if (CalledF && CalledF->isIntrinsic()) {
68 // This is an intrinsic function call, check if its an istypep
69 switch (CalledF->getIntrinsicID()) {
71 case Intrinsic::nvvm_istypep_sampler:
72 Changed |= replaceIsTypePSampler(Instr);
74 case Intrinsic::nvvm_istypep_surface:
75 Changed |= replaceIsTypePSurface(Instr);
77 case Intrinsic::nvvm_istypep_texture:
78 Changed |= replaceIsTypePTexture(Instr);
86 // Delete any istypep instances we replaced in the IR
87 for (unsigned i = 0, e = InstrToDelete.size(); i != e; ++i)
88 InstrToDelete[i]->eraseFromParent();
93 bool NVPTXImageOptimizer::replaceIsTypePSampler(Instruction &I) {
94 Value *TexHandle = cleanupValue(I.getOperand(0));
95 if (isSampler(*TexHandle)) {
96 // This is an OpenCL sampler, so it must be a samplerref
97 replaceWith(&I, ConstantInt::getTrue(I.getContext()));
99 } else if (isImage(*TexHandle)) {
100 // This is an OpenCL image, so it cannot be a samplerref
101 replaceWith(&I, ConstantInt::getFalse(I.getContext()));
104 // The image type is unknown, so we cannot eliminate the intrinsic
109 bool NVPTXImageOptimizer::replaceIsTypePSurface(Instruction &I) {
110 Value *TexHandle = cleanupValue(I.getOperand(0));
111 if (isImageReadWrite(*TexHandle) ||
112 isImageWriteOnly(*TexHandle)) {
113 // This is an OpenCL read-only/read-write image, so it must be a surfref
114 replaceWith(&I, ConstantInt::getTrue(I.getContext()));
116 } else if (isImageReadOnly(*TexHandle) ||
117 isSampler(*TexHandle)) {
118 // This is an OpenCL read-only/ imageor sampler, so it cannot be
120 replaceWith(&I, ConstantInt::getFalse(I.getContext()));
123 // The image type is unknown, so we cannot eliminate the intrinsic
128 bool NVPTXImageOptimizer::replaceIsTypePTexture(Instruction &I) {
129 Value *TexHandle = cleanupValue(I.getOperand(0));
130 if (isImageReadOnly(*TexHandle)) {
131 // This is an OpenCL read-only image, so it must be a texref
132 replaceWith(&I, ConstantInt::getTrue(I.getContext()));
134 } else if (isImageWriteOnly(*TexHandle) ||
135 isImageReadWrite(*TexHandle) ||
136 isSampler(*TexHandle)) {
137 // This is an OpenCL read-write/write-only image or a sampler, so it
138 // cannot be a texref
139 replaceWith(&I, ConstantInt::getFalse(I.getContext()));
142 // The image type is unknown, so we cannot eliminate the intrinsic
147 void NVPTXImageOptimizer::replaceWith(Instruction *From, ConstantInt *To) {
148 // We implement "poor man's DCE" here to make sure any code that is no longer
149 // live is actually unreachable and can be trivially eliminated by the
150 // unreachable block elimination pass.
151 for (CallInst::use_iterator UI = From->use_begin(), UE = From->use_end();
153 if (BranchInst *BI = dyn_cast<BranchInst>(*UI)) {
154 if (BI->isUnconditional()) continue;
158 Dest = BI->getSuccessor(1);
161 Dest = BI->getSuccessor(0);
162 BranchInst::Create(Dest, BI);
163 InstrToDelete.push_back(BI);
166 From->replaceAllUsesWith(To);
167 InstrToDelete.push_back(From);
170 Value *NVPTXImageOptimizer::cleanupValue(Value *V) {
171 if (ExtractValueInst *EVI = dyn_cast<ExtractValueInst>(V)) {
172 return cleanupValue(EVI->getAggregateOperand());
177 FunctionPass *llvm::createNVPTXImageOptimizerPass() {
178 return new NVPTXImageOptimizer();