CanonicalizeFreezeInLoops.cpp 7.9 KB

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