HLPreprocess.cpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // //
  3. // HLPreprocess.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. // Preprocess HLModule after inline. //
  9. // //
  10. ///////////////////////////////////////////////////////////////////////////////
  11. #include "llvm/IR/Function.h"
  12. #include "llvm/IR/Module.h"
  13. #include "llvm/IR/IRBuilder.h"
  14. #include "llvm/IR/Intrinsics.h"
  15. #include "dxc/HLSL/DxilGenerationPass.h"
  16. using namespace llvm;
  17. ///////////////////////////////////////////////////////////////////////////////
  18. // HLPreprocess.
  19. // Inliner will create stacksave stackstore if there are allocas inside block
  20. // other than entry block. HLPreprocess will remove stacksave and stackstore and
  21. // put all allocas inside entry block.
  22. //
  23. namespace {
  24. class HLPreprocess : public ModulePass {
  25. public:
  26. static char ID; // Pass identification, replacement for typeid
  27. explicit HLPreprocess() : ModulePass(ID) {}
  28. const char *getPassName() const override {
  29. return "Preprocess HLModule after inline";
  30. }
  31. bool runOnModule(Module &M) override {
  32. bool bUpdated = false;
  33. // Remove stacksave and stackstore.
  34. // Get the two intrinsics we care about.
  35. Function *StackSave = Intrinsic::getDeclaration(&M, Intrinsic::stacksave);
  36. Function *StackRestore =
  37. Intrinsic::getDeclaration(&M, Intrinsic::stackrestore);
  38. // If has user, remove user first.
  39. if (!StackSave->user_empty() || !StackRestore->user_empty()) {
  40. for (auto it = StackRestore->user_begin();
  41. it != StackRestore->user_end();) {
  42. Instruction *I = cast<Instruction>(*(it++));
  43. I->eraseFromParent();
  44. }
  45. for (auto it = StackSave->user_begin(); it != StackSave->user_end(); ) {
  46. Instruction *I = cast<Instruction>(*(it++));
  47. I->eraseFromParent();
  48. }
  49. bUpdated = true;
  50. }
  51. StackSave->eraseFromParent();
  52. StackRestore->eraseFromParent();
  53. // If stacksave/store is present, it means alloca not in the
  54. // entry block. However, there could be other cases where allocas
  55. // could be present in the non-entry blocks.
  56. // Therefore, always go through all non-entry blocks and
  57. // make sure all allocas are moved to the entry block.
  58. for (Function &F : M.functions()) {
  59. bUpdated |= MoveAllocasToEntryBlock(&F);
  60. }
  61. return bUpdated;
  62. }
  63. private:
  64. bool MoveAllocasToEntryBlock(Function *F);
  65. };
  66. char HLPreprocess::ID = 0;
  67. // Make sure all allocas are in entry block.
  68. bool HLPreprocess::MoveAllocasToEntryBlock(Function *F) {
  69. bool changed = false;
  70. if (F->getBasicBlockList().size() < 2)
  71. return changed;
  72. BasicBlock &Entry = F->getEntryBlock();
  73. IRBuilder<> Builder(Entry.getFirstInsertionPt());
  74. for (auto bb = F->begin(); bb != F->end(); bb++) {
  75. BasicBlock *BB = bb;
  76. if (BB == &Entry)
  77. continue;
  78. for (auto it = BB->begin(); it != BB->end();) {
  79. Instruction *I = (it++);
  80. if (isa<AllocaInst>(I)) {
  81. I->removeFromParent();
  82. Builder.Insert(I);
  83. changed = true;
  84. }
  85. }
  86. }
  87. return changed;
  88. }
  89. } // namespace
  90. ModulePass *llvm::createHLPreprocessPass() { return new HLPreprocess(); }
  91. INITIALIZE_PASS(HLPreprocess, "hl-preprocess",
  92. "Preprocess HLModule after inline", false, false)