DxilEliminateVector.cpp 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // //
  3. // DxilEliminateVector.cpp //
  4. // Copyright (C) Microsoft Corporation. All rights reserved. //
  5. // This file is distributed under the University of Illinois Open Source //
  6. // License. See LICENSE.TXT for details. //
  7. // //
  8. // A pass to remove vector instructions, especially in situations where //
  9. // optimizations are turned off. //
  10. // //
  11. ///////////////////////////////////////////////////////////////////////////////
  12. #include "llvm/Pass.h"
  13. #include "llvm/IR/Instructions.h"
  14. #include "llvm/IR/Dominators.h"
  15. #include "llvm/Transforms/Scalar.h"
  16. #include "llvm/Transforms/Utils/PromoteMemToReg.h"
  17. #include "llvm/IR/DebugInfo.h"
  18. #include "llvm/IR/Module.h"
  19. #include "llvm/IR/IntrinsicInst.h"
  20. #include "llvm/IR/DIBuilder.h"
  21. #include "llvm/Analysis/DxilValueCache.h"
  22. #include <vector>
  23. using namespace llvm;
  24. namespace {
  25. class DxilEliminateVector : public FunctionPass {
  26. public:
  27. static char ID;
  28. DxilEliminateVector() : FunctionPass(ID) {
  29. initializeDxilEliminateVectorPass(*PassRegistry::getPassRegistry());
  30. }
  31. void getAnalysisUsage(AnalysisUsage &AU) const override {
  32. AU.addRequired<DxilValueCache>();
  33. AU.addRequired<DominatorTreeWrapperPass>();
  34. AU.setPreservesAll(); // DxilValueCache is safe. CFG is not changed, so DT is okay.
  35. }
  36. bool TryRewriteDebugInfoForVector(InsertElementInst *IE);
  37. bool runOnFunction(Function &F) override;
  38. const char *getPassName() const override { return "Dxil Eliminate Vector"; }
  39. };
  40. char DxilEliminateVector::ID;
  41. }
  42. static
  43. MetadataAsValue *GetAsMetadata(Instruction *I) {
  44. if (auto *L = LocalAsMetadata::getIfExists(I)) {
  45. if (auto *DINode = MetadataAsValue::getIfExists(I->getContext(), L)) {
  46. return DINode;
  47. }
  48. }
  49. return nullptr;
  50. }
  51. static bool IsZeroInitializer(Value *V) {
  52. Constant *C = dyn_cast<Constant>(V);
  53. return C && C->isZeroValue();
  54. }
  55. static
  56. bool CollectVectorElements(Value *V, SmallVector<Value *, 4> &Elements) {
  57. if (InsertElementInst *IE = dyn_cast<InsertElementInst>(V)) {
  58. Value *Vec = IE->getOperand(0);
  59. Value *Element = IE->getOperand(1);
  60. Value *Index = IE->getOperand(2);
  61. if (!isa<UndefValue>(Vec) && !IsZeroInitializer(Vec)) {
  62. if (!CollectVectorElements(Vec, Elements))
  63. return false;
  64. }
  65. ConstantInt *ConstIndex = dyn_cast<ConstantInt>(Index);
  66. if (!ConstIndex)
  67. return false;
  68. uint64_t IdxValue = ConstIndex->getLimitedValue();
  69. if (IdxValue < 4) {
  70. if (Elements.size() <= IdxValue)
  71. Elements.resize(IdxValue+1);
  72. Elements[IdxValue] = Element;
  73. }
  74. return true;
  75. }
  76. return false;
  77. }
  78. static bool HasDebugValue(Value *V) {
  79. Instruction *I = dyn_cast<Instruction>(V);
  80. if (!I) return false;
  81. MetadataAsValue *DebugI = GetAsMetadata(I);
  82. if (!DebugI) return false;
  83. for (User *U : DebugI->users()) {
  84. if (isa<DbgValueInst>(U))
  85. return true;
  86. }
  87. return false;
  88. }
  89. bool DxilEliminateVector::TryRewriteDebugInfoForVector(InsertElementInst *IE) {
  90. // If this is not ever used as meta-data, there's no debug
  91. MetadataAsValue *DebugI = GetAsMetadata(IE);
  92. if (!DebugI)
  93. return false;
  94. // Collect @dbg.value instructions
  95. SmallVector<DbgValueInst *, 4> DbgValueInsts;
  96. for (User *U : DebugI->users()) {
  97. if (DbgValueInst *DbgValueI = dyn_cast<DbgValueInst>(U)) {
  98. DbgValueInsts.push_back(DbgValueI);
  99. }
  100. }
  101. if (!DbgValueInsts.size())
  102. return false;
  103. SmallVector<Value *, 4> Elements;
  104. if (!CollectVectorElements(IE, Elements))
  105. return false;
  106. DIBuilder DIB(*IE->getModule());
  107. const DataLayout &DL = IE->getModule()->getDataLayout();
  108. // Go through the elements and create @dbg.value with bit-piece
  109. // expressions for them.
  110. bool Changed = false;
  111. for (DbgValueInst *DVI : DbgValueInsts) {
  112. DIExpression *ParentExpr = DVI->getExpression();
  113. unsigned BitpieceOffset = 0;
  114. if (ParentExpr->isBitPiece())
  115. BitpieceOffset = ParentExpr->getBitPieceOffset();
  116. for (unsigned i = 0; i < Elements.size(); i++) {
  117. if (!Elements[i])
  118. continue;
  119. unsigned ElementSize = DL.getTypeAllocSizeInBits(Elements[i]->getType());
  120. DIExpression *Expr = DIB.createBitPieceExpression(BitpieceOffset + i * ElementSize, ElementSize);
  121. DIB.insertDbgValueIntrinsic(Elements[i], 0, DVI->getVariable(), Expr, DVI->getDebugLoc(), DVI);
  122. Changed = true;
  123. }
  124. DVI->eraseFromParent();
  125. }
  126. return Changed;
  127. }
  128. bool DxilEliminateVector::runOnFunction(Function &F) {
  129. auto *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
  130. DxilValueCache *DVC = &getAnalysis<DxilValueCache>();
  131. std::vector<Instruction *> VectorInsts;
  132. std::vector<AllocaInst *> VectorAllocas;
  133. // Collect the vector insts and allocas.
  134. for (auto &BB : F) {
  135. for (auto &I : BB)
  136. if (isa<InsertElementInst>(&I) || isa<ExtractElementInst>(&I))
  137. VectorInsts.push_back(&I);
  138. else if (AllocaInst *AI = dyn_cast<AllocaInst>(&I)) {
  139. if (AI->getAllocatedType()->isVectorTy() && llvm::isAllocaPromotable(AI))
  140. VectorAllocas.push_back(AI);
  141. }
  142. }
  143. if (!VectorInsts.size())
  144. return false;
  145. bool Changed = false;
  146. // Promote the allocas if they exist. They could very well exist
  147. // because of precise.
  148. if (VectorAllocas.size()) {
  149. PromoteMemToReg(VectorAllocas, *DT);
  150. Changed = true;
  151. }
  152. // Iteratively try to remove them, untill all gone or unable to
  153. // do it anymore.
  154. unsigned Attempts = VectorInsts.size();
  155. for (unsigned i = 0; i < Attempts; i++) {
  156. bool LocalChange = false;
  157. for (unsigned j = 0; j < VectorInsts.size();) {
  158. auto *I = VectorInsts[j];
  159. bool Remove = false;
  160. if (InsertElementInst *IE = dyn_cast<InsertElementInst>(I)) {
  161. TryRewriteDebugInfoForVector(IE);
  162. }
  163. if (Value *V = DVC->GetValue(I, DT)) {
  164. I->replaceAllUsesWith(V);
  165. Remove = true;
  166. }
  167. else if (I->user_empty()) {
  168. Remove = true;
  169. }
  170. // Do the remove
  171. if (Remove) {
  172. LocalChange = true;
  173. I->eraseFromParent();
  174. VectorInsts.erase(VectorInsts.begin() + j);
  175. }
  176. else {
  177. j++;
  178. }
  179. }
  180. Changed |= LocalChange;
  181. if (!LocalChange)
  182. break;
  183. }
  184. return Changed;
  185. }
  186. Pass *llvm::createDxilEliminateVectorPass() {
  187. return new DxilEliminateVector();
  188. }
  189. INITIALIZE_PASS(DxilEliminateVector, "dxil-elim-vector", "Dxil Eliminate Vectors", false, false)