NVPTXImageOptimizer.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  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-exception
  6. //
  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 known
  13. //
  14. //===----------------------------------------------------------------------===//
  15. #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"
  23. using namespace llvm;
  24. namespace {
  25. class NVPTXImageOptimizer : public FunctionPass {
  26. private:
  27. static char ID;
  28. SmallVector<Instruction*, 4> InstrToDelete;
  29. public:
  30. NVPTXImageOptimizer();
  31. bool runOnFunction(Function &F) override;
  32. StringRef getPassName() const override { return "NVPTX Image Optimizer"; }
  33. private:
  34. bool replaceIsTypePSampler(Instruction &I);
  35. bool replaceIsTypePSurface(Instruction &I);
  36. bool replaceIsTypePTexture(Instruction &I);
  37. Value *cleanupValue(Value *V);
  38. void replaceWith(Instruction *From, ConstantInt *To);
  39. };
  40. }
  41. char NVPTXImageOptimizer::ID = 0;
  42. NVPTXImageOptimizer::NVPTXImageOptimizer()
  43. : FunctionPass(ID) {}
  44. bool NVPTXImageOptimizer::runOnFunction(Function &F) {
  45. if (skipFunction(F))
  46. return false;
  47. bool Changed = false;
  48. InstrToDelete.clear();
  49. // Look for call instructions in the function
  50. for (BasicBlock &BB : F) {
  51. for (Instruction &Instr : BB) {
  52. if (CallInst *CI = dyn_cast<CallInst>(&Instr)) {
  53. Function *CalledF = CI->getCalledFunction();
  54. if (CalledF && CalledF->isIntrinsic()) {
  55. // This is an intrinsic function call, check if its an istypep
  56. switch (CalledF->getIntrinsicID()) {
  57. default: break;
  58. case Intrinsic::nvvm_istypep_sampler:
  59. Changed |= replaceIsTypePSampler(Instr);
  60. break;
  61. case Intrinsic::nvvm_istypep_surface:
  62. Changed |= replaceIsTypePSurface(Instr);
  63. break;
  64. case Intrinsic::nvvm_istypep_texture:
  65. Changed |= replaceIsTypePTexture(Instr);
  66. break;
  67. }
  68. }
  69. }
  70. }
  71. }
  72. // Delete any istypep instances we replaced in the IR
  73. for (Instruction *I : InstrToDelete)
  74. I->eraseFromParent();
  75. return Changed;
  76. }
  77. bool NVPTXImageOptimizer::replaceIsTypePSampler(Instruction &I) {
  78. Value *TexHandle = cleanupValue(I.getOperand(0));
  79. if (isSampler(*TexHandle)) {
  80. // This is an OpenCL sampler, so it must be a samplerref
  81. replaceWith(&I, ConstantInt::getTrue(I.getContext()));
  82. return true;
  83. } else if (isImage(*TexHandle)) {
  84. // This is an OpenCL image, so it cannot be a samplerref
  85. replaceWith(&I, ConstantInt::getFalse(I.getContext()));
  86. return true;
  87. } else {
  88. // The image type is unknown, so we cannot eliminate the intrinsic
  89. return false;
  90. }
  91. }
  92. bool NVPTXImageOptimizer::replaceIsTypePSurface(Instruction &I) {
  93. Value *TexHandle = cleanupValue(I.getOperand(0));
  94. if (isImageReadWrite(*TexHandle) ||
  95. isImageWriteOnly(*TexHandle)) {
  96. // This is an OpenCL read-only/read-write image, so it must be a surfref
  97. replaceWith(&I, ConstantInt::getTrue(I.getContext()));
  98. return true;
  99. } else if (isImageReadOnly(*TexHandle) ||
  100. isSampler(*TexHandle)) {
  101. // This is an OpenCL read-only/ imageor sampler, so it cannot be
  102. // a surfref
  103. replaceWith(&I, ConstantInt::getFalse(I.getContext()));
  104. return true;
  105. } else {
  106. // The image type is unknown, so we cannot eliminate the intrinsic
  107. return false;
  108. }
  109. }
  110. bool NVPTXImageOptimizer::replaceIsTypePTexture(Instruction &I) {
  111. Value *TexHandle = cleanupValue(I.getOperand(0));
  112. if (isImageReadOnly(*TexHandle)) {
  113. // This is an OpenCL read-only image, so it must be a texref
  114. replaceWith(&I, ConstantInt::getTrue(I.getContext()));
  115. return true;
  116. } else if (isImageWriteOnly(*TexHandle) ||
  117. isImageReadWrite(*TexHandle) ||
  118. isSampler(*TexHandle)) {
  119. // This is an OpenCL read-write/write-only image or a sampler, so it
  120. // cannot be a texref
  121. replaceWith(&I, ConstantInt::getFalse(I.getContext()));
  122. return true;
  123. } else {
  124. // The image type is unknown, so we cannot eliminate the intrinsic
  125. return false;
  126. }
  127. }
  128. void NVPTXImageOptimizer::replaceWith(Instruction *From, ConstantInt *To) {
  129. // We implement "poor man's DCE" here to make sure any code that is no longer
  130. // live is actually unreachable and can be trivially eliminated by the
  131. // unreachable block elimination pass.
  132. for (Use &U : From->uses()) {
  133. if (BranchInst *BI = dyn_cast<BranchInst>(U)) {
  134. if (BI->isUnconditional()) continue;
  135. BasicBlock *Dest;
  136. if (To->isZero())
  137. // Get false block
  138. Dest = BI->getSuccessor(1);
  139. else
  140. // Get true block
  141. Dest = BI->getSuccessor(0);
  142. BranchInst::Create(Dest, BI);
  143. InstrToDelete.push_back(BI);
  144. }
  145. }
  146. From->replaceAllUsesWith(To);
  147. InstrToDelete.push_back(From);
  148. }
  149. Value *NVPTXImageOptimizer::cleanupValue(Value *V) {
  150. if (ExtractValueInst *EVI = dyn_cast<ExtractValueInst>(V)) {
  151. return cleanupValue(EVI->getAggregateOperand());
  152. }
  153. return V;
  154. }
  155. FunctionPass *llvm::createNVPTXImageOptimizerPass() {
  156. return new NVPTXImageOptimizer();
  157. }