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