CanonicalizeFreezeInLoops.cpp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. //==- CanonicalizeFreezeInLoops - Canonicalize freezes in a loop-*- C++ -*-===//
  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 canonicalizes freeze instructions in a loop by pushing them out to
  10. // the preheader.
  11. //
  12. // loop:
  13. // i = phi init, i.next
  14. // i.next = add nsw i, 1
  15. // i.next.fr = freeze i.next // push this out of this loop
  16. // use(i.next.fr)
  17. // br i1 (i.next <= N), loop, exit
  18. // =>
  19. // init.fr = freeze init
  20. // loop:
  21. // i = phi init.fr, i.next
  22. // i.next = add i, 1 // nsw is dropped here
  23. // use(i.next)
  24. // br i1 (i.next <= N), loop, exit
  25. //
  26. // Removing freezes from these chains help scalar evolution successfully analyze
  27. // expressions.
  28. //
  29. //===----------------------------------------------------------------------===//
  30. #include "llvm/Transforms/Utils/CanonicalizeFreezeInLoops.h"
  31. #include "llvm/ADT/STLExtras.h"
  32. #include "llvm/ADT/SmallVector.h"
  33. #include "llvm/Analysis/IVDescriptors.h"
  34. #include "llvm/Analysis/LoopAnalysisManager.h"
  35. #include "llvm/Analysis/LoopInfo.h"
  36. #include "llvm/Analysis/LoopPass.h"
  37. #include "llvm/Analysis/ScalarEvolution.h"
  38. #include "llvm/Analysis/ValueTracking.h"
  39. #include "llvm/IR/Dominators.h"
  40. #include "llvm/InitializePasses.h"
  41. #include "llvm/Pass.h"
  42. #include "llvm/Support/Debug.h"
  43. #include "llvm/Transforms/Utils.h"
  44. using namespace llvm;
  45. #define DEBUG_TYPE "canon-freeze"
  46. namespace {
  47. class CanonicalizeFreezeInLoops : public LoopPass {
  48. public:
  49. static char ID;
  50. CanonicalizeFreezeInLoops();
  51. private:
  52. bool runOnLoop(Loop *L, LPPassManager &LPM) override;
  53. void getAnalysisUsage(AnalysisUsage &AU) const override;
  54. };
  55. class CanonicalizeFreezeInLoopsImpl {
  56. Loop *L;
  57. ScalarEvolution &SE;
  58. DominatorTree &DT;
  59. struct FrozenIndPHIInfo {
  60. // A freeze instruction that uses an induction phi
  61. FreezeInst *FI = nullptr;
  62. // The induction phi, step instruction, the operand idx of StepInst which is
  63. // a step value
  64. PHINode *PHI;
  65. BinaryOperator *StepInst;
  66. unsigned StepValIdx = 0;
  67. FrozenIndPHIInfo(PHINode *PHI, BinaryOperator *StepInst)
  68. : PHI(PHI), StepInst(StepInst) {}
  69. };
  70. // Can freeze instruction be pushed into operands of I?
  71. // In order to do this, I should not create a poison after I's flags are
  72. // stripped.
  73. bool canHandleInst(const Instruction *I) {
  74. auto Opc = I->getOpcode();
  75. // If add/sub/mul, drop nsw/nuw flags.
  76. return Opc == Instruction::Add || Opc == Instruction::Sub ||
  77. Opc == Instruction::Mul;
  78. }
  79. void InsertFreezeAndForgetFromSCEV(Use &U);
  80. public:
  81. CanonicalizeFreezeInLoopsImpl(Loop *L, ScalarEvolution &SE, DominatorTree &DT)
  82. : L(L), SE(SE), DT(DT) {}
  83. bool run();
  84. };
  85. } // anonymous namespace
  86. // Given U = (value, user), replace value with freeze(value), and let
  87. // SCEV forget user. The inserted freeze is placed in the preheader.
  88. void CanonicalizeFreezeInLoopsImpl::InsertFreezeAndForgetFromSCEV(Use &U) {
  89. auto *PH = L->getLoopPreheader();
  90. auto *UserI = cast<Instruction>(U.getUser());
  91. auto *ValueToFr = U.get();
  92. assert(L->contains(UserI->getParent()) &&
  93. "Should not process an instruction that isn't inside the loop");
  94. if (isGuaranteedNotToBeUndefOrPoison(ValueToFr, nullptr, UserI, &DT))
  95. return;
  96. LLVM_DEBUG(dbgs() << "canonfr: inserting freeze:\n");
  97. LLVM_DEBUG(dbgs() << "\tUser: " << *U.getUser() << "\n");
  98. LLVM_DEBUG(dbgs() << "\tOperand: " << *U.get() << "\n");
  99. U.set(new FreezeInst(ValueToFr, ValueToFr->getName() + ".frozen",
  100. PH->getTerminator()));
  101. SE.forgetValue(UserI);
  102. }
  103. bool CanonicalizeFreezeInLoopsImpl::run() {
  104. // The loop should be in LoopSimplify form.
  105. if (!L->isLoopSimplifyForm())
  106. return false;
  107. SmallVector<FrozenIndPHIInfo, 4> Candidates;
  108. for (auto &PHI : L->getHeader()->phis()) {
  109. InductionDescriptor ID;
  110. if (!InductionDescriptor::isInductionPHI(&PHI, L, &SE, ID))
  111. continue;
  112. LLVM_DEBUG(dbgs() << "canonfr: PHI: " << PHI << "\n");
  113. FrozenIndPHIInfo Info(&PHI, ID.getInductionBinOp());
  114. if (!Info.StepInst || !canHandleInst(Info.StepInst)) {
  115. // The stepping instruction has unknown form.
  116. // Ignore this PHI.
  117. continue;
  118. }
  119. Info.StepValIdx = Info.StepInst->getOperand(0) == &PHI;
  120. Value *StepV = Info.StepInst->getOperand(Info.StepValIdx);
  121. if (auto *StepI = dyn_cast<Instruction>(StepV)) {
  122. if (L->contains(StepI->getParent())) {
  123. // The step value is inside the loop. Freezing step value will introduce
  124. // another freeze into the loop, so skip this PHI.
  125. continue;
  126. }
  127. }
  128. auto Visit = [&](User *U) {
  129. if (auto *FI = dyn_cast<FreezeInst>(U)) {
  130. LLVM_DEBUG(dbgs() << "canonfr: found: " << *FI << "\n");
  131. Info.FI = FI;
  132. Candidates.push_back(Info);
  133. }
  134. };
  135. for_each(PHI.users(), Visit);
  136. for_each(Info.StepInst->users(), Visit);
  137. }
  138. if (Candidates.empty())
  139. return false;
  140. SmallSet<PHINode *, 8> ProcessedPHIs;
  141. for (const auto &Info : Candidates) {
  142. PHINode *PHI = Info.PHI;
  143. if (!ProcessedPHIs.insert(Info.PHI).second)
  144. continue;
  145. BinaryOperator *StepI = Info.StepInst;
  146. assert(StepI && "Step instruction should have been found");
  147. // Drop flags from the step instruction.
  148. if (!isGuaranteedNotToBeUndefOrPoison(StepI, nullptr, StepI, &DT)) {
  149. LLVM_DEBUG(dbgs() << "canonfr: drop flags: " << *StepI << "\n");
  150. StepI->dropPoisonGeneratingFlags();
  151. SE.forgetValue(StepI);
  152. }
  153. InsertFreezeAndForgetFromSCEV(StepI->getOperandUse(Info.StepValIdx));
  154. unsigned OperandIdx =
  155. PHI->getOperandNumForIncomingValue(PHI->getIncomingValue(0) == StepI);
  156. InsertFreezeAndForgetFromSCEV(PHI->getOperandUse(OperandIdx));
  157. }
  158. // Finally, remove the old freeze instructions.
  159. for (const auto &Item : Candidates) {
  160. auto *FI = Item.FI;
  161. LLVM_DEBUG(dbgs() << "canonfr: removing " << *FI << "\n");
  162. SE.forgetValue(FI);
  163. FI->replaceAllUsesWith(FI->getOperand(0));
  164. FI->eraseFromParent();
  165. }
  166. return true;
  167. }
  168. CanonicalizeFreezeInLoops::CanonicalizeFreezeInLoops() : LoopPass(ID) {
  169. initializeCanonicalizeFreezeInLoopsPass(*PassRegistry::getPassRegistry());
  170. }
  171. void CanonicalizeFreezeInLoops::getAnalysisUsage(AnalysisUsage &AU) const {
  172. AU.addPreservedID(LoopSimplifyID);
  173. AU.addRequired<LoopInfoWrapperPass>();
  174. AU.addPreserved<LoopInfoWrapperPass>();
  175. AU.addRequiredID(LoopSimplifyID);
  176. AU.addRequired<ScalarEvolutionWrapperPass>();
  177. AU.addPreserved<ScalarEvolutionWrapperPass>();
  178. AU.addRequired<DominatorTreeWrapperPass>();
  179. AU.addPreserved<DominatorTreeWrapperPass>();
  180. }
  181. bool CanonicalizeFreezeInLoops::runOnLoop(Loop *L, LPPassManager &) {
  182. if (skipLoop(L))
  183. return false;
  184. auto &SE = getAnalysis<ScalarEvolutionWrapperPass>().getSE();
  185. auto &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
  186. return CanonicalizeFreezeInLoopsImpl(L, SE, DT).run();
  187. }
  188. PreservedAnalyses
  189. CanonicalizeFreezeInLoopsPass::run(Loop &L, LoopAnalysisManager &AM,
  190. LoopStandardAnalysisResults &AR,
  191. LPMUpdater &U) {
  192. if (!CanonicalizeFreezeInLoopsImpl(&L, AR.SE, AR.DT).run())
  193. return PreservedAnalyses::all();
  194. return getLoopPassPreservedAnalyses();
  195. }
  196. INITIALIZE_PASS_BEGIN(CanonicalizeFreezeInLoops, "canon-freeze",
  197. "Canonicalize Freeze Instructions in Loops", false, false)
  198. INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
  199. INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass)
  200. INITIALIZE_PASS_DEPENDENCY(LoopSimplify)
  201. INITIALIZE_PASS_END(CanonicalizeFreezeInLoops, "canon-freeze",
  202. "Canonicalize Freeze Instructions in Loops", false, false)
  203. Pass *llvm::createCanonicalizeFreezeInLoopsPass() {
  204. return new CanonicalizeFreezeInLoops();
  205. }
  206. char CanonicalizeFreezeInLoops::ID = 0;