177 lines · cpp
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-exception6//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 known13//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/IntrinsicsNVPTX.h"22#include "llvm/Pass.h"23 24using namespace llvm;25 26namespace {27class NVPTXImageOptimizer : public FunctionPass {28private:29 static char ID;30 SmallVector<Instruction*, 4> InstrToDelete;31 32public:33 NVPTXImageOptimizer();34 35 bool runOnFunction(Function &F) override;36 37 StringRef getPassName() const override { return "NVPTX Image Optimizer"; }38 39private:40 bool replaceIsTypePSampler(Instruction &I);41 bool replaceIsTypePSurface(Instruction &I);42 bool replaceIsTypePTexture(Instruction &I);43 Value *cleanupValue(Value *V);44 void replaceWith(Instruction *From, ConstantInt *To);45};46}47 48char NVPTXImageOptimizer::ID = 0;49 50NVPTXImageOptimizer::NVPTXImageOptimizer()51 : FunctionPass(ID) {}52 53bool NVPTXImageOptimizer::runOnFunction(Function &F) {54 if (skipFunction(F))55 return false;56 57 bool Changed = false;58 InstrToDelete.clear();59 60 // Look for call instructions in the function61 for (BasicBlock &BB : F) {62 for (Instruction &Instr : BB) {63 if (CallInst *CI = dyn_cast<CallInst>(&Instr)) {64 Function *CalledF = CI->getCalledFunction();65 if (CalledF && CalledF->isIntrinsic()) {66 // This is an intrinsic function call, check if its an istypep67 switch (CalledF->getIntrinsicID()) {68 default: break;69 case Intrinsic::nvvm_istypep_sampler:70 Changed |= replaceIsTypePSampler(Instr);71 break;72 case Intrinsic::nvvm_istypep_surface:73 Changed |= replaceIsTypePSurface(Instr);74 break;75 case Intrinsic::nvvm_istypep_texture:76 Changed |= replaceIsTypePTexture(Instr);77 break;78 }79 }80 }81 }82 }83 84 // Delete any istypep instances we replaced in the IR85 for (Instruction *I : InstrToDelete)86 I->eraseFromParent();87 88 return Changed;89}90 91bool NVPTXImageOptimizer::replaceIsTypePSampler(Instruction &I) {92 Value *TexHandle = cleanupValue(I.getOperand(0));93 if (isSampler(*TexHandle)) {94 // This is an OpenCL sampler, so it must be a samplerref95 replaceWith(&I, ConstantInt::getTrue(I.getContext()));96 return true;97 } else if (isImage(*TexHandle)) {98 // This is an OpenCL image, so it cannot be a samplerref99 replaceWith(&I, ConstantInt::getFalse(I.getContext()));100 return true;101 } else {102 // The image type is unknown, so we cannot eliminate the intrinsic103 return false;104 }105}106 107bool NVPTXImageOptimizer::replaceIsTypePSurface(Instruction &I) {108 Value *TexHandle = cleanupValue(I.getOperand(0));109 if (isImageReadWrite(*TexHandle) ||110 isImageWriteOnly(*TexHandle)) {111 // This is an OpenCL read-only/read-write image, so it must be a surfref112 replaceWith(&I, ConstantInt::getTrue(I.getContext()));113 return true;114 } else if (isImageReadOnly(*TexHandle) ||115 isSampler(*TexHandle)) {116 // This is an OpenCL read-only/ imageor sampler, so it cannot be117 // a surfref118 replaceWith(&I, ConstantInt::getFalse(I.getContext()));119 return true;120 } else {121 // The image type is unknown, so we cannot eliminate the intrinsic122 return false;123 }124}125 126bool NVPTXImageOptimizer::replaceIsTypePTexture(Instruction &I) {127 Value *TexHandle = cleanupValue(I.getOperand(0));128 if (isImageReadOnly(*TexHandle)) {129 // This is an OpenCL read-only image, so it must be a texref130 replaceWith(&I, ConstantInt::getTrue(I.getContext()));131 return true;132 } else if (isImageWriteOnly(*TexHandle) ||133 isImageReadWrite(*TexHandle) ||134 isSampler(*TexHandle)) {135 // This is an OpenCL read-write/write-only image or a sampler, so it136 // cannot be a texref137 replaceWith(&I, ConstantInt::getFalse(I.getContext()));138 return true;139 } else {140 // The image type is unknown, so we cannot eliminate the intrinsic141 return false;142 }143}144 145void NVPTXImageOptimizer::replaceWith(Instruction *From, ConstantInt *To) {146 // We implement "poor man's DCE" here to make sure any code that is no longer147 // live is actually unreachable and can be trivially eliminated by the148 // unreachable block elimination pass.149 for (Use &U : From->uses()) {150 if (BranchInst *BI = dyn_cast<BranchInst>(U)) {151 if (BI->isUnconditional()) continue;152 BasicBlock *Dest;153 if (To->isZero())154 // Get false block155 Dest = BI->getSuccessor(1);156 else157 // Get true block158 Dest = BI->getSuccessor(0);159 BranchInst::Create(Dest, BI->getIterator());160 InstrToDelete.push_back(BI);161 }162 }163 From->replaceAllUsesWith(To);164 InstrToDelete.push_back(From);165}166 167Value *NVPTXImageOptimizer::cleanupValue(Value *V) {168 if (ExtractValueInst *EVI = dyn_cast<ExtractValueInst>(V)) {169 return cleanupValue(EVI->getAggregateOperand());170 }171 return V;172}173 174FunctionPass *llvm::createNVPTXImageOptimizerPass() {175 return new NVPTXImageOptimizer();176}177