Home | History | Annotate | Line # | Download | only in Vectorize
      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.
     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.
     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
    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.
    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.
    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.
    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.
    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 
    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