blob: 74ab2f7b8453d3799422374dbd632621817ed1bf [file] [log] [blame]
Justin Holewinski30d56a72014-04-09 15:39:15 +00001//===-- NVPTXImageOptimizer.cpp - Image optimization pass -----------------===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// 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
Justin Holewinski30d56a72014-04-09 15:39:15 +00006//
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"
Chandler Carruthd9903882015-01-14 11:23:27 +000018#include "llvm/Analysis/ConstantFolding.h"
Justin Holewinski30d56a72014-04-09 15:39:15 +000019#include "llvm/IR/Instructions.h"
20#include "llvm/IR/Intrinsics.h"
21#include "llvm/IR/Module.h"
22#include "llvm/Pass.h"
Justin Holewinski30d56a72014-04-09 15:39:15 +000023
24using namespace llvm;
25
26namespace {
27class NVPTXImageOptimizer : public FunctionPass {
28private:
29 static char ID;
30 SmallVector<Instruction*, 4> InstrToDelete;
31
32public:
33 NVPTXImageOptimizer();
34
Craig Topper2865c982014-04-29 07:57:44 +000035 bool runOnFunction(Function &F) override;
Justin Holewinski30d56a72014-04-09 15:39:15 +000036
37private:
38 bool replaceIsTypePSampler(Instruction &I);
39 bool replaceIsTypePSurface(Instruction &I);
40 bool replaceIsTypePTexture(Instruction &I);
41 Value *cleanupValue(Value *V);
42 void replaceWith(Instruction *From, ConstantInt *To);
43};
Alexander Kornienkof00654e2015-06-23 09:49:53 +000044}
Justin Holewinski30d56a72014-04-09 15:39:15 +000045
46char NVPTXImageOptimizer::ID = 0;
47
48NVPTXImageOptimizer::NVPTXImageOptimizer()
49 : FunctionPass(ID) {}
50
51bool NVPTXImageOptimizer::runOnFunction(Function &F) {
Andrew Kaylor87b10dd2016-04-26 23:44:31 +000052 if (skipFunction(F))
53 return false;
54
Justin Holewinski30d56a72014-04-09 15:39:15 +000055 bool Changed = false;
56 InstrToDelete.clear();
57
58 // Look for call instructions in the function
59 for (Function::iterator BI = F.begin(), BE = F.end(); BI != BE;
60 ++BI) {
61 for (BasicBlock::iterator I = (*BI).begin(), E = (*BI).end();
62 I != E; ++I) {
63 Instruction &Instr = *I;
64 if (CallInst *CI = dyn_cast<CallInst>(I)) {
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 (unsigned i = 0, e = InstrToDelete.size(); i != e; ++i)
87 InstrToDelete[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;
Justin Lebar1d1cf7b2017-03-08 01:14:15 +000098 } else if (isImage(*TexHandle)) {
Justin Holewinski30d56a72014-04-09 15:39:15 +000099 // 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
Alp Toker5c536392014-06-07 21:23:09 +0000149 // unreachable block elimination pass.
Justin Holewinski30d56a72014-04-09 15:39:15 +0000150 for (CallInst::use_iterator UI = From->use_begin(), UE = From->use_end();
151 UI != UE; ++UI) {
152 if (BranchInst *BI = dyn_cast<BranchInst>(*UI)) {
153 if (BI->isUnconditional()) continue;
154 BasicBlock *Dest;
155 if (To->isZero())
156 // Get false block
157 Dest = BI->getSuccessor(1);
158 else
159 // Get true block
160 Dest = BI->getSuccessor(0);
161 BranchInst::Create(Dest, BI);
162 InstrToDelete.push_back(BI);
163 }
164 }
165 From->replaceAllUsesWith(To);
166 InstrToDelete.push_back(From);
167}
168
169Value *NVPTXImageOptimizer::cleanupValue(Value *V) {
170 if (ExtractValueInst *EVI = dyn_cast<ExtractValueInst>(V)) {
171 return cleanupValue(EVI->getAggregateOperand());
172 }
173 return V;
174}
175
176FunctionPass *llvm::createNVPTXImageOptimizerPass() {
177 return new NVPTXImageOptimizer();
178}