Path: blob/main/contrib/llvm-project/llvm/lib/Target/NVPTX/NVPTXImageOptimizer.cpp
35271 views
//===-- NVPTXImageOptimizer.cpp - Image optimization pass -----------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This pass implements IR-level optimizations of image access code,9// including:10//11// 1. Eliminate istypep intrinsics when image access qualifier is known12//13//===----------------------------------------------------------------------===//1415#include "NVPTX.h"16#include "NVPTXUtilities.h"17#include "llvm/Analysis/ConstantFolding.h"18#include "llvm/IR/Instructions.h"19#include "llvm/IR/Intrinsics.h"20#include "llvm/IR/IntrinsicsNVPTX.h"21#include "llvm/IR/Module.h"22#include "llvm/Pass.h"2324using namespace llvm;2526namespace {27class NVPTXImageOptimizer : public FunctionPass {28private:29static char ID;30SmallVector<Instruction*, 4> InstrToDelete;3132public:33NVPTXImageOptimizer();3435bool runOnFunction(Function &F) override;3637StringRef getPassName() const override { return "NVPTX Image Optimizer"; }3839private:40bool replaceIsTypePSampler(Instruction &I);41bool replaceIsTypePSurface(Instruction &I);42bool replaceIsTypePTexture(Instruction &I);43Value *cleanupValue(Value *V);44void replaceWith(Instruction *From, ConstantInt *To);45};46}4748char NVPTXImageOptimizer::ID = 0;4950NVPTXImageOptimizer::NVPTXImageOptimizer()51: FunctionPass(ID) {}5253bool NVPTXImageOptimizer::runOnFunction(Function &F) {54if (skipFunction(F))55return false;5657bool Changed = false;58InstrToDelete.clear();5960// Look for call instructions in the function61for (BasicBlock &BB : F) {62for (Instruction &Instr : BB) {63if (CallInst *CI = dyn_cast<CallInst>(&Instr)) {64Function *CalledF = CI->getCalledFunction();65if (CalledF && CalledF->isIntrinsic()) {66// This is an intrinsic function call, check if its an istypep67switch (CalledF->getIntrinsicID()) {68default: break;69case Intrinsic::nvvm_istypep_sampler:70Changed |= replaceIsTypePSampler(Instr);71break;72case Intrinsic::nvvm_istypep_surface:73Changed |= replaceIsTypePSurface(Instr);74break;75case Intrinsic::nvvm_istypep_texture:76Changed |= replaceIsTypePTexture(Instr);77break;78}79}80}81}82}8384// Delete any istypep instances we replaced in the IR85for (Instruction *I : InstrToDelete)86I->eraseFromParent();8788return Changed;89}9091bool NVPTXImageOptimizer::replaceIsTypePSampler(Instruction &I) {92Value *TexHandle = cleanupValue(I.getOperand(0));93if (isSampler(*TexHandle)) {94// This is an OpenCL sampler, so it must be a samplerref95replaceWith(&I, ConstantInt::getTrue(I.getContext()));96return true;97} else if (isImage(*TexHandle)) {98// This is an OpenCL image, so it cannot be a samplerref99replaceWith(&I, ConstantInt::getFalse(I.getContext()));100return true;101} else {102// The image type is unknown, so we cannot eliminate the intrinsic103return false;104}105}106107bool NVPTXImageOptimizer::replaceIsTypePSurface(Instruction &I) {108Value *TexHandle = cleanupValue(I.getOperand(0));109if (isImageReadWrite(*TexHandle) ||110isImageWriteOnly(*TexHandle)) {111// This is an OpenCL read-only/read-write image, so it must be a surfref112replaceWith(&I, ConstantInt::getTrue(I.getContext()));113return true;114} else if (isImageReadOnly(*TexHandle) ||115isSampler(*TexHandle)) {116// This is an OpenCL read-only/ imageor sampler, so it cannot be117// a surfref118replaceWith(&I, ConstantInt::getFalse(I.getContext()));119return true;120} else {121// The image type is unknown, so we cannot eliminate the intrinsic122return false;123}124}125126bool NVPTXImageOptimizer::replaceIsTypePTexture(Instruction &I) {127Value *TexHandle = cleanupValue(I.getOperand(0));128if (isImageReadOnly(*TexHandle)) {129// This is an OpenCL read-only image, so it must be a texref130replaceWith(&I, ConstantInt::getTrue(I.getContext()));131return true;132} else if (isImageWriteOnly(*TexHandle) ||133isImageReadWrite(*TexHandle) ||134isSampler(*TexHandle)) {135// This is an OpenCL read-write/write-only image or a sampler, so it136// cannot be a texref137replaceWith(&I, ConstantInt::getFalse(I.getContext()));138return true;139} else {140// The image type is unknown, so we cannot eliminate the intrinsic141return false;142}143}144145void 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.149for (Use &U : From->uses()) {150if (BranchInst *BI = dyn_cast<BranchInst>(U)) {151if (BI->isUnconditional()) continue;152BasicBlock *Dest;153if (To->isZero())154// Get false block155Dest = BI->getSuccessor(1);156else157// Get true block158Dest = BI->getSuccessor(0);159BranchInst::Create(Dest, BI->getIterator());160InstrToDelete.push_back(BI);161}162}163From->replaceAllUsesWith(To);164InstrToDelete.push_back(From);165}166167Value *NVPTXImageOptimizer::cleanupValue(Value *V) {168if (ExtractValueInst *EVI = dyn_cast<ExtractValueInst>(V)) {169return cleanupValue(EVI->getAggregateOperand());170}171return V;172}173174FunctionPass *llvm::createNVPTXImageOptimizerPass() {175return new NVPTXImageOptimizer();176}177178179