HLPreprocess.cpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  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. // Has stacksave/store mean alloca not in entry block.
  54. if (bUpdated) {
  55. // Make sure all allocas are in entry block.
  56. for (Function &F : M.functions()) {
  57. MoveAllocasToEntryBlock(&F);
  58. }
  59. }
  60. return bUpdated;
  61. }
  62. private:
  63. void MoveAllocasToEntryBlock(Function *F);
  64. };
  65. char HLPreprocess::ID = 0;
  66. // Make sure all allocas are in entry block.
  67. void HLPreprocess::MoveAllocasToEntryBlock(Function *F) {
  68. if (F->getBasicBlockList().size() < 2)
  69. return;
  70. BasicBlock &Entry = F->getEntryBlock();
  71. IRBuilder<> Builder(Entry.getFirstInsertionPt());
  72. for (auto bb = F->begin(); bb != F->end(); bb++) {
  73. BasicBlock *BB = bb;
  74. if (BB == &Entry)
  75. continue;
  76. for (auto it = BB->begin(); it != BB->end();) {
  77. Instruction *I = (it++);
  78. if (isa<AllocaInst>(I)) {
  79. I->removeFromParent();
  80. Builder.Insert(I);
  81. }
  82. }
  83. }
  84. }
  85. } // namespace
  86. ModulePass *llvm::createHLPreprocessPass() { return new HLPreprocess(); }
  87. INITIALIZE_PASS(HLPreprocess, "hl-preprocess",
  88. "Preprocess HLModule after inline", false, false)