forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			179 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			179 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			C++
		
	
	
	
//===-- NVPTXImageOptimizer.cpp - Image optimization pass -----------------===//
 | 
						|
//
 | 
						|
//                     The LLVM Compiler Infrastructure
 | 
						|
//
 | 
						|
// This file is distributed under the University of Illinois Open Source 
 | 
						|
// License. See LICENSE.TXT for details.
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
//
 | 
						|
// This pass implements IR-level optimizations of image access code,
 | 
						|
// including:
 | 
						|
//
 | 
						|
// 1. Eliminate istypep intrinsics when image access qualifier is known
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
#include "NVPTX.h"
 | 
						|
#include "NVPTXUtilities.h"
 | 
						|
#include "llvm/IR/Instructions.h"
 | 
						|
#include "llvm/IR/Intrinsics.h"
 | 
						|
#include "llvm/IR/Module.h"
 | 
						|
#include "llvm/Pass.h"
 | 
						|
#include "llvm/Analysis/ConstantFolding.h"
 | 
						|
 | 
						|
using namespace llvm;
 | 
						|
 | 
						|
namespace {
 | 
						|
class NVPTXImageOptimizer : public FunctionPass {
 | 
						|
private:
 | 
						|
  static char ID;
 | 
						|
  SmallVector<Instruction*, 4> InstrToDelete;
 | 
						|
 | 
						|
public:
 | 
						|
  NVPTXImageOptimizer();
 | 
						|
 | 
						|
  bool runOnFunction(Function &F) override;
 | 
						|
 | 
						|
private:
 | 
						|
  bool replaceIsTypePSampler(Instruction &I);
 | 
						|
  bool replaceIsTypePSurface(Instruction &I);
 | 
						|
  bool replaceIsTypePTexture(Instruction &I);
 | 
						|
  Value *cleanupValue(Value *V);
 | 
						|
  void replaceWith(Instruction *From, ConstantInt *To);
 | 
						|
};
 | 
						|
}
 | 
						|
 | 
						|
char NVPTXImageOptimizer::ID = 0;
 | 
						|
 | 
						|
NVPTXImageOptimizer::NVPTXImageOptimizer()
 | 
						|
  : FunctionPass(ID) {}
 | 
						|
 | 
						|
bool NVPTXImageOptimizer::runOnFunction(Function &F) {
 | 
						|
  bool Changed = false;
 | 
						|
  InstrToDelete.clear();
 | 
						|
 | 
						|
  // Look for call instructions in the function
 | 
						|
  for (Function::iterator BI = F.begin(), BE = F.end(); BI != BE;
 | 
						|
       ++BI) {
 | 
						|
    for (BasicBlock::iterator I = (*BI).begin(), E = (*BI).end();
 | 
						|
         I != E; ++I) {
 | 
						|
      Instruction &Instr = *I;
 | 
						|
      if (CallInst *CI = dyn_cast<CallInst>(I)) {
 | 
						|
        Function *CalledF = CI->getCalledFunction();
 | 
						|
        if (CalledF && CalledF->isIntrinsic()) {
 | 
						|
          // This is an intrinsic function call, check if its an istypep
 | 
						|
          switch (CalledF->getIntrinsicID()) {
 | 
						|
          default: break;
 | 
						|
          case Intrinsic::nvvm_istypep_sampler:
 | 
						|
            Changed |= replaceIsTypePSampler(Instr);
 | 
						|
            break;
 | 
						|
          case Intrinsic::nvvm_istypep_surface:
 | 
						|
            Changed |= replaceIsTypePSurface(Instr);
 | 
						|
            break;
 | 
						|
          case Intrinsic::nvvm_istypep_texture:
 | 
						|
            Changed |= replaceIsTypePTexture(Instr);
 | 
						|
            break;
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  // Delete any istypep instances we replaced in the IR
 | 
						|
  for (unsigned i = 0, e = InstrToDelete.size(); i != e; ++i)
 | 
						|
    InstrToDelete[i]->eraseFromParent();
 | 
						|
 | 
						|
  return Changed;
 | 
						|
}
 | 
						|
 | 
						|
bool NVPTXImageOptimizer::replaceIsTypePSampler(Instruction &I) {
 | 
						|
  Value *TexHandle = cleanupValue(I.getOperand(0));
 | 
						|
  if (isSampler(*TexHandle)) {
 | 
						|
    // This is an OpenCL sampler, so it must be a samplerref
 | 
						|
    replaceWith(&I, ConstantInt::getTrue(I.getContext()));
 | 
						|
    return true;
 | 
						|
  } else if (isImageWriteOnly(*TexHandle) ||
 | 
						|
             isImageReadWrite(*TexHandle) ||
 | 
						|
             isImageReadOnly(*TexHandle)) {
 | 
						|
    // This is an OpenCL image, so it cannot be a samplerref
 | 
						|
    replaceWith(&I, ConstantInt::getFalse(I.getContext()));
 | 
						|
    return true;
 | 
						|
  } else {
 | 
						|
    // The image type is unknown, so we cannot eliminate the intrinsic
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
bool NVPTXImageOptimizer::replaceIsTypePSurface(Instruction &I) {
 | 
						|
  Value *TexHandle = cleanupValue(I.getOperand(0));
 | 
						|
  if (isImageReadWrite(*TexHandle) ||
 | 
						|
      isImageWriteOnly(*TexHandle)) {
 | 
						|
    // This is an OpenCL read-only/read-write image, so it must be a surfref
 | 
						|
    replaceWith(&I, ConstantInt::getTrue(I.getContext()));
 | 
						|
    return true;
 | 
						|
  } else if (isImageReadOnly(*TexHandle) ||
 | 
						|
             isSampler(*TexHandle)) {
 | 
						|
    // This is an OpenCL read-only/ imageor sampler, so it cannot be
 | 
						|
    // a surfref
 | 
						|
    replaceWith(&I, ConstantInt::getFalse(I.getContext()));
 | 
						|
    return true;
 | 
						|
  } else {
 | 
						|
    // The image type is unknown, so we cannot eliminate the intrinsic
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
bool NVPTXImageOptimizer::replaceIsTypePTexture(Instruction &I) {
 | 
						|
  Value *TexHandle = cleanupValue(I.getOperand(0));
 | 
						|
  if (isImageReadOnly(*TexHandle)) {
 | 
						|
    // This is an OpenCL read-only image, so it must be a texref
 | 
						|
    replaceWith(&I, ConstantInt::getTrue(I.getContext()));
 | 
						|
    return true;
 | 
						|
  } else if (isImageWriteOnly(*TexHandle) ||
 | 
						|
             isImageReadWrite(*TexHandle) ||
 | 
						|
             isSampler(*TexHandle)) {
 | 
						|
    // This is an OpenCL read-write/write-only image or a sampler, so it
 | 
						|
    // cannot be a texref
 | 
						|
    replaceWith(&I, ConstantInt::getFalse(I.getContext()));
 | 
						|
    return true;
 | 
						|
  } else {
 | 
						|
    // The image type is unknown, so we cannot eliminate the intrinsic
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void NVPTXImageOptimizer::replaceWith(Instruction *From, ConstantInt *To) {
 | 
						|
  // We implement "poor man's DCE" here to make sure any code that is no longer
 | 
						|
  // live is actually unreachable and can be trivially eliminated by the
 | 
						|
  // unreachable block elimination pass.
 | 
						|
  for (CallInst::use_iterator UI = From->use_begin(), UE = From->use_end();
 | 
						|
       UI != UE; ++UI) {
 | 
						|
    if (BranchInst *BI = dyn_cast<BranchInst>(*UI)) {
 | 
						|
      if (BI->isUnconditional()) continue;
 | 
						|
      BasicBlock *Dest;
 | 
						|
      if (To->isZero())
 | 
						|
        // Get false block
 | 
						|
        Dest = BI->getSuccessor(1);
 | 
						|
      else
 | 
						|
        // Get true block
 | 
						|
        Dest = BI->getSuccessor(0);
 | 
						|
      BranchInst::Create(Dest, BI);
 | 
						|
      InstrToDelete.push_back(BI);
 | 
						|
    }
 | 
						|
  }
 | 
						|
  From->replaceAllUsesWith(To);
 | 
						|
  InstrToDelete.push_back(From);
 | 
						|
}
 | 
						|
 | 
						|
Value *NVPTXImageOptimizer::cleanupValue(Value *V) {
 | 
						|
  if (ExtractValueInst *EVI = dyn_cast<ExtractValueInst>(V)) {
 | 
						|
    return cleanupValue(EVI->getAggregateOperand());
 | 
						|
  }
 | 
						|
  return V;
 | 
						|
}
 | 
						|
 | 
						|
FunctionPass *llvm::createNVPTXImageOptimizerPass() {
 | 
						|
  return new NVPTXImageOptimizer();
 | 
						|
}
 |