Coverage Report

Created: 2019-07-24 05:18

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