brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.5 KiB · b10b086 Raw
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