blob: 8d00bbb5e9c262cde5de4265a3385d3df3fdd25b [file] [log] [blame]
Justin Holewinski30d56a72014-04-09 15:39:15 +00001//===-- NVPTXImageOptimizer.cpp - Image optimization pass -----------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This pass implements IR-level optimizations of image access code,
11// including:
12//
13// 1. Eliminate istypep intrinsics when image access qualifier is known
14//
15//===----------------------------------------------------------------------===//
16
17#include "NVPTX.h"
18#include "NVPTXUtilities.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000019#include "llvm/Analysis/ConstantFolding.h"
Justin Holewinski30d56a72014-04-09 15:39:15 +000020#include "llvm/IR/Instructions.h"
21#include "llvm/IR/Intrinsics.h"
22#include "llvm/IR/Module.h"
23#include "llvm/Pass.h"
Justin Holewinski30d56a72014-04-09 15:39:15 +000024
25using namespace llvm;
26
27namespace {
28class NVPTXImageOptimizer : public FunctionPass {
29private:
30 static char ID;
31 SmallVector<Instruction*, 4> InstrToDelete;
32
33public:
34 NVPTXImageOptimizer();
35
Craig Topper2865c982014-04-29 07:57:44 +000036 bool runOnFunction(Function &F) override;
Justin Holewinski30d56a72014-04-09 15:39:15 +000037
38private:
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);
44};
Alexander Kornienkof00654e2015-06-23 09:49:53 +000045}
Justin Holewinski30d56a72014-04-09 15:39:15 +000046
47char NVPTXImageOptimizer::ID = 0;
48
49NVPTXImageOptimizer::NVPTXImageOptimizer()
50 : FunctionPass(ID) {}
51
52bool NVPTXImageOptimizer::runOnFunction(Function &F) {
Andrew Kaylor87b10dd2016-04-26 23:44:31 +000053 if (skipFunction(F))
54 return false;
55
Justin Holewinski30d56a72014-04-09 15:39:15 +000056 bool Changed = false;
57 InstrToDelete.clear();
58
59 // Look for call instructions in the function
60 for (Function::iterator BI = F.begin(), BE = F.end(); BI != BE;
61 ++BI) {
62 for (BasicBlock::iterator I = (*BI).begin(), E = (*BI).end();
63 I != E; ++I) {
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()) {
70 default: break;
71 case Intrinsic::nvvm_istypep_sampler:
72 Changed |= replaceIsTypePSampler(Instr);
73 break;
74 case Intrinsic::nvvm_istypep_surface:
75 Changed |= replaceIsTypePSurface(Instr);
76 break;
77 case Intrinsic::nvvm_istypep_texture:
78 Changed |= replaceIsTypePTexture(Instr);
79 break;
80 }
81 }
82 }
83 }
84 }
85
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();
89
90 return Changed;
91}
92
93bool 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()));
98 return true;
99 } else if (isImageWriteOnly(*TexHandle) ||
100 isImageReadWrite(*TexHandle) ||
101 isImageReadOnly(*TexHandle)) {
102 // This is an OpenCL image, so it cannot be a samplerref
103 replaceWith(&I, ConstantInt::getFalse(I.getContext()));
104 return true;
105 } else {
106 // The image type is unknown, so we cannot eliminate the intrinsic
107 return false;
108 }
109}
110
111bool NVPTXImageOptimizer::replaceIsTypePSurface(Instruction &I) {
112 Value *TexHandle = cleanupValue(I.getOperand(0));
113 if (isImageReadWrite(*TexHandle) ||
114 isImageWriteOnly(*TexHandle)) {
115 // This is an OpenCL read-only/read-write image, so it must be a surfref
116 replaceWith(&I, ConstantInt::getTrue(I.getContext()));
117 return true;
118 } else if (isImageReadOnly(*TexHandle) ||
119 isSampler(*TexHandle)) {
120 // This is an OpenCL read-only/ imageor sampler, so it cannot be
121 // a surfref
122 replaceWith(&I, ConstantInt::getFalse(I.getContext()));
123 return true;
124 } else {
125 // The image type is unknown, so we cannot eliminate the intrinsic
126 return false;
127 }
128}
129
130bool NVPTXImageOptimizer::replaceIsTypePTexture(Instruction &I) {
131 Value *TexHandle = cleanupValue(I.getOperand(0));
132 if (isImageReadOnly(*TexHandle)) {
133 // This is an OpenCL read-only image, so it must be a texref
134 replaceWith(&I, ConstantInt::getTrue(I.getContext()));
135 return true;
136 } else if (isImageWriteOnly(*TexHandle) ||
137 isImageReadWrite(*TexHandle) ||
138 isSampler(*TexHandle)) {
139 // This is an OpenCL read-write/write-only image or a sampler, so it
140 // cannot be a texref
141 replaceWith(&I, ConstantInt::getFalse(I.getContext()));
142 return true;
143 } else {
144 // The image type is unknown, so we cannot eliminate the intrinsic
145 return false;
146 }
147}
148
149void NVPTXImageOptimizer::replaceWith(Instruction *From, ConstantInt *To) {
150 // We implement "poor man's DCE" here to make sure any code that is no longer
151 // live is actually unreachable and can be trivially eliminated by the
Alp Toker5c536392014-06-07 21:23:09 +0000152 // unreachable block elimination pass.
Justin Holewinski30d56a72014-04-09 15:39:15 +0000153 for (CallInst::use_iterator UI = From->use_begin(), UE = From->use_end();
154 UI != UE; ++UI) {
155 if (BranchInst *BI = dyn_cast<BranchInst>(*UI)) {
156 if (BI->isUnconditional()) continue;
157 BasicBlock *Dest;
158 if (To->isZero())
159 // Get false block
160 Dest = BI->getSuccessor(1);
161 else
162 // Get true block
163 Dest = BI->getSuccessor(0);
164 BranchInst::Create(Dest, BI);
165 InstrToDelete.push_back(BI);
166 }
167 }
168 From->replaceAllUsesWith(To);
169 InstrToDelete.push_back(From);
170}
171
172Value *NVPTXImageOptimizer::cleanupValue(Value *V) {
173 if (ExtractValueInst *EVI = dyn_cast<ExtractValueInst>(V)) {
174 return cleanupValue(EVI->getAggregateOperand());
175 }
176 return V;
177}
178
179FunctionPass *llvm::createNVPTXImageOptimizerPass() {
180 return new NVPTXImageOptimizer();
181}