1 //===-- VPlanPredicator.cpp -------------------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
10 /// This file implements the VPlanPredicator class which contains the public
11 /// interfaces to predicate and linearize the VPlan region.
13 //===----------------------------------------------------------------------===//
15 #include "VPlanPredicator.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"
23 #define DEBUG_TYPE "VPlanPredicator"
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.
37 VPValue
*VPlanPredicator::getOrCreateNotPredicate(VPBasicBlock
*PredBB
,
38 VPBasicBlock
*CurrBB
) {
39 VPValue
*CBV
= PredBB
->getCondBit();
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;
46 case EdgeType::TRUE_EDGE
:
47 // CurrBB is the true successor of PredBB - nothing to do here.
48 IntermediateVal
= CBV
;
51 case EdgeType::FALSE_EDGE
:
52 // CurrBB is the False successor of PredBB - compute not of CBV.
53 IntermediateVal
= Builder
.createNot(CBV
);
57 // Now AND intermediate value with PredBB's block predicate if it has one.
58 VPValue
*BP
= PredBB
->getPredicate();
60 return Builder
.createAnd(BP
, IntermediateVal
);
62 return IntermediateVal
;
65 // Generate a tree of ORs for all IncomingPredicates in WorkList.
66 // Note: This function destroys the original Worklist.
76 // OR4 <- Returns this
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.
85 VPValue
*VPlanPredicator::genPredicateTree(std::list
<VPValue
*> &Worklist
) {
89 // The worklist initially contains all the leaf nodes. Initialize the tree
91 while (Worklist
.size() >= 2) {
92 // Pop a pair of values from the front.
93 VPValue
*LHS
= Worklist
.front();
95 VPValue
*RHS
= Worklist
.front();
98 // Create an OR of these values.
99 VPValue
*Or
= Builder
.createOr(LHS
, RHS
);
101 // Push OR to the back of the worklist.
102 Worklist
.push_back(Or
);
105 assert(Worklist
.size() == 1 && "Expected 1 item in worklist");
107 // The root is the last node in the worklist.
108 VPValue
*Root
= Worklist
.front();
110 // This root needs to replace the existing block predicate. This is done in
111 // the caller function.
115 // Return whether the edge FromBlock -> ToBlock is a TRUE_EDGE or FALSE_EDGE
116 VPlanPredicator::EdgeType
117 VPlanPredicator::getEdgeTypeBetween(VPBlockBase
*FromBlock
,
118 VPBlockBase
*ToBlock
) {
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
;
128 llvm_unreachable("Broken getEdgeTypeBetween");
131 // Generate all predicates needed for CurrBlock by going through its immediate
132 // predecessor blocks.
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
);
143 // Collect all incoming predicates in a worklist.
144 std::list
<VPValue
*> IncomingPredicates
;
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());
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()) {
156 if (VPBlockUtils::isBackEdge(PredBlock
, CurrBlock
, VPLI
))
159 VPValue
*IncomingPredicate
= nullptr;
160 unsigned NumPredSuccsNoBE
=
161 VPBlockUtils::countSuccessorsNoBE(PredBlock
, VPLI
);
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");
171 getOrCreateNotPredicate(cast
<VPBasicBlock
>(PredBlock
), CurrBB
);
173 llvm_unreachable("FIXME: switch statement ?");
175 if (IncomingPredicate
)
176 IncomingPredicates
.push_back(IncomingPredicate
);
179 // Logically OR all incoming predicates by building the Predicate Tree.
180 VPValue
*Predicate
= genPredicateTree(IncomingPredicates
);
182 // Now update the block's predicate with the new one.
183 CurrBlock
->setPredicate(Predicate
);
186 // Generate all predicates needed for Region.
187 void VPlanPredicator::predicateRegionRec(VPRegionBlock
*Region
) {
188 VPBasicBlock
*EntryBlock
= cast
<VPBasicBlock
>(Region
->getEntry());
189 ReversePostOrderTraversal
<VPBlockBase
*> RPOT(EntryBlock
);
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
: make_range(RPOT
.begin(), RPOT
.end())) {
195 // TODO: Handle nested regions once we start generating the same.
196 assert(!isa
<VPRegionBlock
>(Block
) && "Nested region not expected");
197 createOrPropagatePredicates(Block
, Region
);
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
207 void VPlanPredicator::linearizeRegionRec(VPRegionBlock
*Region
) {
208 ReversePostOrderTraversal
<VPBlockBase
*> RPOT(Region
->getEntry());
209 VPBlockBase
*PrevBlock
= nullptr;
211 for (VPBlockBase
*CurrBlock
: make_range(RPOT
.begin(), RPOT
.end())) {
212 // TODO: Handle nested regions once we start generating the same.
213 assert(!isa
<VPRegionBlock
>(CurrBlock
) && "Nested region not expected");
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
)) {
221 LLVM_DEBUG(dbgs() << "Linearizing: " << PrevBlock
->getName() << "->"
222 << CurrBlock
->getName() << "\n");
224 PrevBlock
->clearSuccessors();
225 CurrBlock
->clearPredecessors();
226 VPBlockUtils::connectBlocks(PrevBlock
, CurrBlock
);
229 PrevBlock
= CurrBlock
;
233 // Entry point. The driver function for the predicator.
234 void VPlanPredicator::predicate(void) {
235 // Predicate the blocks within Region.
236 predicateRegionRec(cast
<VPRegionBlock
>(Plan
.getEntry()));
238 // Linearlize the blocks with Region.
239 linearizeRegionRec(cast
<VPRegionBlock
>(Plan
.getEntry()));
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())));