LLVM API Documentation

NVPTXImageOptimizer.cpp
Go to the documentation of this file.
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 }