LLVM API Documentation
00001 //===-- NVPTXImageOptimizer.cpp - Image optimization pass -----------------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This pass implements IR-level optimizations of image access code, 00011 // including: 00012 // 00013 // 1. Eliminate istypep intrinsics when image access qualifier is known 00014 // 00015 //===----------------------------------------------------------------------===// 00016 00017 #include "NVPTX.h" 00018 #include "NVPTXUtilities.h" 00019 #include "llvm/IR/Instructions.h" 00020 #include "llvm/IR/Intrinsics.h" 00021 #include "llvm/IR/Module.h" 00022 #include "llvm/Pass.h" 00023 #include "llvm/Analysis/ConstantFolding.h" 00024 00025 using namespace llvm; 00026 00027 namespace { 00028 class NVPTXImageOptimizer : public FunctionPass { 00029 private: 00030 static char ID; 00031 SmallVector<Instruction*, 4> InstrToDelete; 00032 00033 public: 00034 NVPTXImageOptimizer(); 00035 00036 bool runOnFunction(Function &F) override; 00037 00038 private: 00039 bool replaceIsTypePSampler(Instruction &I); 00040 bool replaceIsTypePSurface(Instruction &I); 00041 bool replaceIsTypePTexture(Instruction &I); 00042 Value *cleanupValue(Value *V); 00043 void replaceWith(Instruction *From, ConstantInt *To); 00044 }; 00045 } 00046 00047 char NVPTXImageOptimizer::ID = 0; 00048 00049 NVPTXImageOptimizer::NVPTXImageOptimizer() 00050 : FunctionPass(ID) {} 00051 00052 bool NVPTXImageOptimizer::runOnFunction(Function &F) { 00053 bool Changed = false; 00054 InstrToDelete.clear(); 00055 00056 // Look for call instructions in the function 00057 for (Function::iterator BI = F.begin(), BE = F.end(); BI != BE; 00058 ++BI) { 00059 for (BasicBlock::iterator I = (*BI).begin(), E = (*BI).end(); 00060 I != E; ++I) { 00061 Instruction &Instr = *I; 00062 if (CallInst *CI = dyn_cast<CallInst>(I)) { 00063 Function *CalledF = CI->getCalledFunction(); 00064 if (CalledF && CalledF->isIntrinsic()) { 00065 // This is an intrinsic function call, check if its an istypep 00066 switch (CalledF->getIntrinsicID()) { 00067 default: break; 00068 case Intrinsic::nvvm_istypep_sampler: 00069 Changed |= replaceIsTypePSampler(Instr); 00070 break; 00071 case Intrinsic::nvvm_istypep_surface: 00072 Changed |= replaceIsTypePSurface(Instr); 00073 break; 00074 case Intrinsic::nvvm_istypep_texture: 00075 Changed |= replaceIsTypePTexture(Instr); 00076 break; 00077 } 00078 } 00079 } 00080 } 00081 } 00082 00083 // Delete any istypep instances we replaced in the IR 00084 for (unsigned i = 0, e = InstrToDelete.size(); i != e; ++i) 00085 InstrToDelete[i]->eraseFromParent(); 00086 00087 return Changed; 00088 } 00089 00090 bool NVPTXImageOptimizer::replaceIsTypePSampler(Instruction &I) { 00091 Value *TexHandle = cleanupValue(I.getOperand(0)); 00092 if (isSampler(*TexHandle)) { 00093 // This is an OpenCL sampler, so it must be a samplerref 00094 replaceWith(&I, ConstantInt::getTrue(I.getContext())); 00095 return true; 00096 } else if (isImageWriteOnly(*TexHandle) || 00097 isImageReadWrite(*TexHandle) || 00098 isImageReadOnly(*TexHandle)) { 00099 // This is an OpenCL image, so it cannot be a samplerref 00100 replaceWith(&I, ConstantInt::getFalse(I.getContext())); 00101 return true; 00102 } else { 00103 // The image type is unknown, so we cannot eliminate the intrinsic 00104 return false; 00105 } 00106 } 00107 00108 bool NVPTXImageOptimizer::replaceIsTypePSurface(Instruction &I) { 00109 Value *TexHandle = cleanupValue(I.getOperand(0)); 00110 if (isImageReadWrite(*TexHandle) || 00111 isImageWriteOnly(*TexHandle)) { 00112 // This is an OpenCL read-only/read-write image, so it must be a surfref 00113 replaceWith(&I, ConstantInt::getTrue(I.getContext())); 00114 return true; 00115 } else if (isImageReadOnly(*TexHandle) || 00116 isSampler(*TexHandle)) { 00117 // This is an OpenCL read-only/ imageor sampler, so it cannot be 00118 // a surfref 00119 replaceWith(&I, ConstantInt::getFalse(I.getContext())); 00120 return true; 00121 } else { 00122 // The image type is unknown, so we cannot eliminate the intrinsic 00123 return false; 00124 } 00125 } 00126 00127 bool NVPTXImageOptimizer::replaceIsTypePTexture(Instruction &I) { 00128 Value *TexHandle = cleanupValue(I.getOperand(0)); 00129 if (isImageReadOnly(*TexHandle)) { 00130 // This is an OpenCL read-only image, so it must be a texref 00131 replaceWith(&I, ConstantInt::getTrue(I.getContext())); 00132 return true; 00133 } else if (isImageWriteOnly(*TexHandle) || 00134 isImageReadWrite(*TexHandle) || 00135 isSampler(*TexHandle)) { 00136 // This is an OpenCL read-write/write-only image or a sampler, so it 00137 // cannot be a texref 00138 replaceWith(&I, ConstantInt::getFalse(I.getContext())); 00139 return true; 00140 } else { 00141 // The image type is unknown, so we cannot eliminate the intrinsic 00142 return false; 00143 } 00144 } 00145 00146 void NVPTXImageOptimizer::replaceWith(Instruction *From, ConstantInt *To) { 00147 // We implement "poor man's DCE" here to make sure any code that is no longer 00148 // live is actually unreachable and can be trivially eliminated by the 00149 // unreachable block elimination pass. 00150 for (CallInst::use_iterator UI = From->use_begin(), UE = From->use_end(); 00151 UI != UE; ++UI) { 00152 if (BranchInst *BI = dyn_cast<BranchInst>(*UI)) { 00153 if (BI->isUnconditional()) continue; 00154 BasicBlock *Dest; 00155 if (To->isZero()) 00156 // Get false block 00157 Dest = BI->getSuccessor(1); 00158 else 00159 // Get true block 00160 Dest = BI->getSuccessor(0); 00161 BranchInst::Create(Dest, BI); 00162 InstrToDelete.push_back(BI); 00163 } 00164 } 00165 From->replaceAllUsesWith(To); 00166 InstrToDelete.push_back(From); 00167 } 00168 00169 Value *NVPTXImageOptimizer::cleanupValue(Value *V) { 00170 if (ExtractValueInst *EVI = dyn_cast<ExtractValueInst>(V)) { 00171 return cleanupValue(EVI->getAggregateOperand()); 00172 } 00173 return V; 00174 } 00175 00176 FunctionPass *llvm::createNVPTXImageOptimizerPass() { 00177 return new NVPTXImageOptimizer(); 00178 }