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