VPlanPredicator.cpp 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. //===-- VPlanPredicator.cpp -------------------------------------*- 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. /// \file
  10. /// This file implements the VPlanPredicator class which contains the public
  11. /// interfaces to predicate and linearize the VPlan region.
  12. ///
  13. //===----------------------------------------------------------------------===//
  14. #include "VPlanPredicator.h"
  15. #include "VPlan.h"
  16. #include "llvm/ADT/DepthFirstIterator.h"
  17. #include "llvm/ADT/GraphTraits.h"
  18. #include "llvm/ADT/PostOrderIterator.h"
  19. #include "llvm/Support/Debug.h"
  20. #include "llvm/Support/raw_ostream.h"
  21. #define DEBUG_TYPE "VPlanPredicator"
  22. using namespace llvm;
  23. // Generate VPInstructions at the beginning of CurrBB that calculate the
  24. // predicate being propagated from PredBB to CurrBB depending on the edge type
  25. // between them. For example if:
  26. // i. PredBB is controlled by predicate %BP, and
  27. // ii. The edge PredBB->CurrBB is the false edge, controlled by the condition
  28. // bit value %CBV then this function will generate the following two
  29. // VPInstructions at the start of CurrBB:
  30. // %IntermediateVal = not %CBV
  31. // %FinalVal = and %BP %IntermediateVal
  32. // It returns %FinalVal.
  33. VPValue *VPlanPredicator::getOrCreateNotPredicate(VPBasicBlock *PredBB,
  34. VPBasicBlock *CurrBB) {
  35. VPValue *CBV = PredBB->getCondBit();
  36. // Set the intermediate value - this is either 'CBV', or 'not CBV'
  37. // depending on the edge type.
  38. EdgeType ET = getEdgeTypeBetween(PredBB, CurrBB);
  39. VPValue *IntermediateVal = nullptr;
  40. switch (ET) {
  41. case EdgeType::TRUE_EDGE:
  42. // CurrBB is the true successor of PredBB - nothing to do here.
  43. IntermediateVal = CBV;
  44. break;
  45. case EdgeType::FALSE_EDGE:
  46. // CurrBB is the False successor of PredBB - compute not of CBV.
  47. IntermediateVal = Builder.createNot(CBV, {});
  48. break;
  49. }
  50. // Now AND intermediate value with PredBB's block predicate if it has one.
  51. VPValue *BP = PredBB->getPredicate();
  52. if (BP)
  53. return Builder.createAnd(BP, IntermediateVal, {});
  54. else
  55. return IntermediateVal;
  56. }
  57. // Generate a tree of ORs for all IncomingPredicates in WorkList.
  58. // Note: This function destroys the original Worklist.
  59. //
  60. // P1 P2 P3 P4 P5
  61. // \ / \ / /
  62. // OR1 OR2 /
  63. // \ | /
  64. // \ +/-+
  65. // \ / |
  66. // OR3 |
  67. // \ |
  68. // OR4 <- Returns this
  69. // |
  70. //
  71. // The algorithm uses a worklist of predicates as its main data structure.
  72. // We pop a pair of values from the front (e.g. P1 and P2), generate an OR
  73. // (in this example OR1), and push it back. In this example the worklist
  74. // contains {P3, P4, P5, OR1}.
  75. // The process iterates until we have only one element in the Worklist (OR4).
  76. // The last element is the root predicate which is returned.
  77. VPValue *VPlanPredicator::genPredicateTree(std::list<VPValue *> &Worklist) {
  78. if (Worklist.empty())
  79. return nullptr;
  80. // The worklist initially contains all the leaf nodes. Initialize the tree
  81. // using them.
  82. while (Worklist.size() >= 2) {
  83. // Pop a pair of values from the front.
  84. VPValue *LHS = Worklist.front();
  85. Worklist.pop_front();
  86. VPValue *RHS = Worklist.front();
  87. Worklist.pop_front();
  88. // Create an OR of these values.
  89. VPValue *Or = Builder.createOr(LHS, RHS, {});
  90. // Push OR to the back of the worklist.
  91. Worklist.push_back(Or);
  92. }
  93. assert(Worklist.size() == 1 && "Expected 1 item in worklist");
  94. // The root is the last node in the worklist.
  95. VPValue *Root = Worklist.front();
  96. // This root needs to replace the existing block predicate. This is done in
  97. // the caller function.
  98. return Root;
  99. }
  100. // Return whether the edge FromBlock -> ToBlock is a TRUE_EDGE or FALSE_EDGE
  101. VPlanPredicator::EdgeType
  102. VPlanPredicator::getEdgeTypeBetween(VPBlockBase *FromBlock,
  103. VPBlockBase *ToBlock) {
  104. unsigned Count = 0;
  105. for (VPBlockBase *SuccBlock : FromBlock->getSuccessors()) {
  106. if (SuccBlock == ToBlock) {
  107. assert(Count < 2 && "Switch not supported currently");
  108. return (Count == 0) ? EdgeType::TRUE_EDGE : EdgeType::FALSE_EDGE;
  109. }
  110. Count++;
  111. }
  112. llvm_unreachable("Broken getEdgeTypeBetween");
  113. }
  114. // Generate all predicates needed for CurrBlock by going through its immediate
  115. // predecessor blocks.
  116. void VPlanPredicator::createOrPropagatePredicates(VPBlockBase *CurrBlock,
  117. VPRegionBlock *Region) {
  118. // Blocks that dominate region exit inherit the predicate from the region.
  119. // Return after setting the predicate.
  120. if (VPDomTree.dominates(CurrBlock, Region->getExit())) {
  121. VPValue *RegionBP = Region->getPredicate();
  122. CurrBlock->setPredicate(RegionBP);
  123. return;
  124. }
  125. // Collect all incoming predicates in a worklist.
  126. std::list<VPValue *> IncomingPredicates;
  127. // Set the builder's insertion point to the top of the current BB
  128. VPBasicBlock *CurrBB = cast<VPBasicBlock>(CurrBlock->getEntryBasicBlock());
  129. Builder.setInsertPoint(CurrBB, CurrBB->begin());
  130. // For each predecessor, generate the VPInstructions required for
  131. // computing 'BP AND (not) CBV" at the top of CurrBB.
  132. // Collect the outcome of this calculation for all predecessors
  133. // into IncomingPredicates.
  134. for (VPBlockBase *PredBlock : CurrBlock->getPredecessors()) {
  135. // Skip back-edges
  136. if (VPBlockUtils::isBackEdge(PredBlock, CurrBlock, VPLI))
  137. continue;
  138. VPValue *IncomingPredicate = nullptr;
  139. unsigned NumPredSuccsNoBE =
  140. VPBlockUtils::countSuccessorsNoBE(PredBlock, VPLI);
  141. // If there is an unconditional branch to the currBB, then we don't create
  142. // edge predicates. We use the predecessor's block predicate instead.
  143. if (NumPredSuccsNoBE == 1)
  144. IncomingPredicate = PredBlock->getPredicate();
  145. else if (NumPredSuccsNoBE == 2) {
  146. // Emit recipes into CurrBlock if required
  147. assert(isa<VPBasicBlock>(PredBlock) && "Only BBs have multiple exits");
  148. IncomingPredicate =
  149. getOrCreateNotPredicate(cast<VPBasicBlock>(PredBlock), CurrBB);
  150. } else
  151. llvm_unreachable("FIXME: switch statement ?");
  152. if (IncomingPredicate)
  153. IncomingPredicates.push_back(IncomingPredicate);
  154. }
  155. // Logically OR all incoming predicates by building the Predicate Tree.
  156. VPValue *Predicate = genPredicateTree(IncomingPredicates);
  157. // Now update the block's predicate with the new one.
  158. CurrBlock->setPredicate(Predicate);
  159. }
  160. // Generate all predicates needed for Region.
  161. void VPlanPredicator::predicateRegionRec(VPRegionBlock *Region) {
  162. VPBasicBlock *EntryBlock = cast<VPBasicBlock>(Region->getEntry());
  163. ReversePostOrderTraversal<VPBlockBase *> RPOT(EntryBlock);
  164. // Generate edge predicates and append them to the block predicate. RPO is
  165. // necessary since the predecessor blocks' block predicate needs to be set
  166. // before the current block's block predicate can be computed.
  167. for (VPBlockBase *Block : RPOT) {
  168. // TODO: Handle nested regions once we start generating the same.
  169. assert(!isa<VPRegionBlock>(Block) && "Nested region not expected");
  170. createOrPropagatePredicates(Block, Region);
  171. }
  172. }
  173. // Linearize the CFG within Region.
  174. // TODO: Predication and linearization need RPOT for every region.
  175. // This traversal is expensive. Since predication is not adding new
  176. // blocks, we should be able to compute RPOT once in predication and
  177. // reuse it here. This becomes even more important once we have nested
  178. // regions.
  179. void VPlanPredicator::linearizeRegionRec(VPRegionBlock *Region) {
  180. ReversePostOrderTraversal<VPBlockBase *> RPOT(Region->getEntry());
  181. VPBlockBase *PrevBlock = nullptr;
  182. for (VPBlockBase *CurrBlock : RPOT) {
  183. // TODO: Handle nested regions once we start generating the same.
  184. assert(!isa<VPRegionBlock>(CurrBlock) && "Nested region not expected");
  185. // Linearize control flow by adding an unconditional edge between PrevBlock
  186. // and CurrBlock skipping loop headers and latches to keep intact loop
  187. // header predecessors and loop latch successors.
  188. if (PrevBlock && !VPLI->isLoopHeader(CurrBlock) &&
  189. !VPBlockUtils::blockIsLoopLatch(PrevBlock, VPLI)) {
  190. LLVM_DEBUG(dbgs() << "Linearizing: " << PrevBlock->getName() << "->"
  191. << CurrBlock->getName() << "\n");
  192. PrevBlock->clearSuccessors();
  193. CurrBlock->clearPredecessors();
  194. VPBlockUtils::connectBlocks(PrevBlock, CurrBlock);
  195. }
  196. PrevBlock = CurrBlock;
  197. }
  198. }
  199. // Entry point. The driver function for the predicator.
  200. void VPlanPredicator::predicate() {
  201. // Predicate the blocks within Region.
  202. predicateRegionRec(cast<VPRegionBlock>(Plan.getEntry()));
  203. // Linearlize the blocks with Region.
  204. linearizeRegionRec(cast<VPRegionBlock>(Plan.getEntry()));
  205. }
  206. VPlanPredicator::VPlanPredicator(VPlan &Plan)
  207. : Plan(Plan), VPLI(&(Plan.getVPLoopInfo())) {
  208. // FIXME: Predicator is currently computing the dominator information for the
  209. // top region. Once we start storing dominator information in a VPRegionBlock,
  210. // we can avoid this recalculation.
  211. VPDomTree.recalculate(*(cast<VPRegionBlock>(Plan.getEntry())));
  212. }