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