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