1 //===-- NVPTXImageOptimizer.cpp - Image optimization pass -----------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This pass implements IR-level optimizations of image access code,
12 // 1. Eliminate istypep intrinsics when image access qualifier is known
14 //===----------------------------------------------------------------------===//
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"
27 class NVPTXImageOptimizer
: public FunctionPass
{
30 SmallVector
<Instruction
*, 4> InstrToDelete
;
33 NVPTXImageOptimizer();
35 bool runOnFunction(Function
&F
) override
;
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
);
46 char NVPTXImageOptimizer::ID
= 0;
48 NVPTXImageOptimizer::NVPTXImageOptimizer()
51 bool NVPTXImageOptimizer::runOnFunction(Function
&F
) {
56 InstrToDelete
.clear();
58 // Look for call instructions in the function
59 for (Function::iterator BI
= F
.begin(), BE
= F
.end(); BI
!= BE
;
61 for (BasicBlock::iterator I
= (*BI
).begin(), E
= (*BI
).end();
63 Instruction
&Instr
= *I
;
64 if (CallInst
*CI
= dyn_cast
<CallInst
>(I
)) {
65 Function
*CalledF
= CI
->getCalledFunction();
66 if (CalledF
&& CalledF
->isIntrinsic()) {
67 // This is an intrinsic function call, check if its an istypep
68 switch (CalledF
->getIntrinsicID()) {
70 case Intrinsic::nvvm_istypep_sampler
:
71 Changed
|= replaceIsTypePSampler(Instr
);
73 case Intrinsic::nvvm_istypep_surface
:
74 Changed
|= replaceIsTypePSurface(Instr
);
76 case Intrinsic::nvvm_istypep_texture
:
77 Changed
|= replaceIsTypePTexture(Instr
);
85 // Delete any istypep instances we replaced in the IR
86 for (unsigned i
= 0, e
= InstrToDelete
.size(); i
!= e
; ++i
)
87 InstrToDelete
[i
]->eraseFromParent();
92 bool NVPTXImageOptimizer::replaceIsTypePSampler(Instruction
&I
) {
93 Value
*TexHandle
= cleanupValue(I
.getOperand(0));
94 if (isSampler(*TexHandle
)) {
95 // This is an OpenCL sampler, so it must be a samplerref
96 replaceWith(&I
, ConstantInt::getTrue(I
.getContext()));
98 } else if (isImage(*TexHandle
)) {
99 // This is an OpenCL image, so it cannot be a samplerref
100 replaceWith(&I
, ConstantInt::getFalse(I
.getContext()));
103 // The image type is unknown, so we cannot eliminate the intrinsic
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()));
115 } else if (isImageReadOnly(*TexHandle
) ||
116 isSampler(*TexHandle
)) {
117 // This is an OpenCL read-only/ imageor sampler, so it cannot be
119 replaceWith(&I
, ConstantInt::getFalse(I
.getContext()));
122 // The image type is unknown, so we cannot eliminate the intrinsic
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()));
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()));
141 // The image type is unknown, so we cannot eliminate the intrinsic
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();
152 if (BranchInst
*BI
= dyn_cast
<BranchInst
>(*UI
)) {
153 if (BI
->isUnconditional()) continue;
157 Dest
= BI
->getSuccessor(1);
160 Dest
= BI
->getSuccessor(0);
161 BranchInst::Create(Dest
, BI
);
162 InstrToDelete
.push_back(BI
);
165 From
->replaceAllUsesWith(To
);
166 InstrToDelete
.push_back(From
);
169 Value
*NVPTXImageOptimizer::cleanupValue(Value
*V
) {
170 if (ExtractValueInst
*EVI
= dyn_cast
<ExtractValueInst
>(V
)) {
171 return cleanupValue(EVI
->getAggregateOperand());
176 FunctionPass
*llvm::createNVPTXImageOptimizerPass() {
177 return new NVPTXImageOptimizer();