NVPTXImageOptimizer.cpp revision cd81d94322a39503e4a3e87b6ee03d4fcb3465fb
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
25using namespace llvm;
26
27namespace {
28class NVPTXImageOptimizer : public FunctionPass {
29private:
30  static char ID;
31  SmallVector<Instruction*, 4> InstrToDelete;
32
33public:
34  NVPTXImageOptimizer();
35
36  bool runOnFunction(Function &F) override;
37
38private:
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
47char NVPTXImageOptimizer::ID = 0;
48
49NVPTXImageOptimizer::NVPTXImageOptimizer()
50  : FunctionPass(ID) {}
51
52bool 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
90bool 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
108bool 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
127bool 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
146void 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
169Value *NVPTXImageOptimizer::cleanupValue(Value *V) {
170  if (ExtractValueInst *EVI = dyn_cast<ExtractValueInst>(V)) {
171    return cleanupValue(EVI->getAggregateOperand());
172  }
173  return V;
174}
175
176FunctionPass *llvm::createNVPTXImageOptimizerPass() {
177  return new NVPTXImageOptimizer();
178}
179