/// Update the dominator tree after if-conversion erased some blocks.
void AArch64ConditionalCompares::updateDomTree(
    ArrayRef<MachineBasicBlock *> Removed) {
  // convert() removes CmpBB which was previously dominated by Head.
  // CmpBB children should be transferred to Head.
  MachineDomTreeNode *HeadNode = DomTree->getNode(CmpConv.Head);
  for (unsigned i = 0, e = Removed.size(); i != e; ++i) {
    MachineDomTreeNode *Node = DomTree->getNode(Removed[i]);
    assert(Node != HeadNode && "Cannot erase the head node");
    assert(Node->getIDom() == HeadNode && "CmpBB should be dominated by Head");
    while (Node->getNumChildren())
      DomTree->changeImmediateDominator(Node->getChildren().back(), HeadNode);
    DomTree->eraseNode(Removed[i]);
  }
}
/// computeDFS - Computes the DFS-in and DFS-out numbers of the dominator tree
/// of the given MachineFunction.  These numbers are then used in other parts
/// of the PHI elimination process.
void StrongPHIElimination::computeDFS(MachineFunction& MF) {
  SmallPtrSet<MachineDomTreeNode*, 8> frontier;
  SmallPtrSet<MachineDomTreeNode*, 8> visited;
  
  unsigned time = 0;
  
  MachineDominatorTree& DT = getAnalysis<MachineDominatorTree>();
  
  MachineDomTreeNode* node = DT.getRootNode();
  
  std::vector<MachineDomTreeNode*> worklist;
  worklist.push_back(node);
  
  while (!worklist.empty()) {
    MachineDomTreeNode* currNode = worklist.back();
    
    if (!frontier.count(currNode)) {
      frontier.insert(currNode);
      ++time;
      preorder.insert(std::make_pair(currNode->getBlock(), time));
    }
    
    bool inserted = false;
    for (MachineDomTreeNode::iterator I = currNode->begin(), E = currNode->end();
         I != E; ++I)
      if (!frontier.count(*I) && !visited.count(*I)) {
        worklist.push_back(*I);
        inserted = true;
        break;
      }
    
    if (!inserted) {
      frontier.erase(currNode);
      visited.insert(currNode);
      maxpreorder.insert(std::make_pair(currNode->getBlock(), time));
      
      worklist.pop_back();
    }
  }
}
Exemplo n.º 3
0
bool MachineCSE::PerformCSE(MachineDomTreeNode *Node) {
  SmallVector<MachineDomTreeNode*, 32> Scopes;
  SmallVector<MachineDomTreeNode*, 8> WorkList;
  DenseMap<MachineDomTreeNode*, MachineDomTreeNode*> ParentMap;
  DenseMap<MachineDomTreeNode*, unsigned> OpenChildren;

  CurrVN = 0;

  // Perform a DFS walk to determine the order of visit.
  WorkList.push_back(Node);
  do {
    Node = WorkList.pop_back_val();
    Scopes.push_back(Node);
    const std::vector<MachineDomTreeNode*> &Children = Node->getChildren();
    unsigned NumChildren = Children.size();
    OpenChildren[Node] = NumChildren;
    for (unsigned i = 0; i != NumChildren; ++i) {
      MachineDomTreeNode *Child = Children[i];
      ParentMap[Child] = Node;
      WorkList.push_back(Child);
    }
  } while (!WorkList.empty());

  // Now perform CSE.
  bool Changed = false;
  for (unsigned i = 0, e = Scopes.size(); i != e; ++i) {
    MachineDomTreeNode *Node = Scopes[i];
    MachineBasicBlock *MBB = Node->getBlock();
    EnterScope(MBB);
    Changed |= ProcessBlock(MBB);
    // If it's a leaf node, it's done. Traverse upwards to pop ancestors.
    ExitScopeIfDone(Node, OpenChildren, ParentMap);
  }

  return Changed;
}
Exemplo n.º 4
0
// This is essentially the same iterative algorithm that SSAUpdater uses,
// except we already have a dominator tree, so we don't have to recompute it.
void LiveRangeCalc::updateSSA() {
    assert(Indexes && "Missing SlotIndexes");
    assert(DomTree && "Missing dominator tree");

    // Interate until convergence.
    unsigned Changes;
    do {
        Changes = 0;
        // Propagate live-out values down the dominator tree, inserting phi-defs
        // when necessary.
        for (SmallVectorImpl<LiveInBlock>::iterator I = LiveIn.begin(),
                E = LiveIn.end(); I != E; ++I) {
            MachineDomTreeNode *Node = I->DomNode;
            // Skip block if the live-in value has already been determined.
            if (!Node)
                continue;
            MachineBasicBlock *MBB = Node->getBlock();
            MachineDomTreeNode *IDom = Node->getIDom();
            LiveOutPair IDomValue;

            // We need a live-in value to a block with no immediate dominator?
            // This is probably an unreachable block that has survived somehow.
            bool needPHI = !IDom || !Seen.test(IDom->getBlock()->getNumber());

            // IDom dominates all of our predecessors, but it may not be their
            // immediate dominator. Check if any of them have live-out values that are
            // properly dominated by IDom. If so, we need a phi-def here.
            if (!needPHI) {
                IDomValue = LiveOut[IDom->getBlock()];

                // Cache the DomTree node that defined the value.
                if (IDomValue.first && !IDomValue.second)
                    LiveOut[IDom->getBlock()].second = IDomValue.second =
                                                           DomTree->getNode(Indexes->getMBBFromIndex(IDomValue.first->def));

                for (MachineBasicBlock::pred_iterator PI = MBB->pred_begin(),
                        PE = MBB->pred_end(); PI != PE; ++PI) {
                    LiveOutPair &Value = LiveOut[*PI];
                    if (!Value.first || Value.first == IDomValue.first)
                        continue;

                    // Cache the DomTree node that defined the value.
                    if (!Value.second)
                        Value.second =
                            DomTree->getNode(Indexes->getMBBFromIndex(Value.first->def));

                    // This predecessor is carrying something other than IDomValue.
                    // It could be because IDomValue hasn't propagated yet, or it could be
                    // because MBB is in the dominance frontier of that value.
                    if (DomTree->dominates(IDom, Value.second)) {
                        needPHI = true;
                        break;
                    }
                }
            }

            // The value may be live-through even if Kill is set, as can happen when
            // we are called from extendRange. In that case LiveOutSeen is true, and
            // LiveOut indicates a foreign or missing value.
            LiveOutPair &LOP = LiveOut[MBB];

            // Create a phi-def if required.
            if (needPHI) {
                ++Changes;
                assert(Alloc && "Need VNInfo allocator to create PHI-defs");
                SlotIndex Start, End;
                tie(Start, End) = Indexes->getMBBRange(MBB);
                VNInfo *VNI = I->LI->getNextValue(Start, *Alloc);
                I->Value = VNI;
                // This block is done, we know the final value.
                I->DomNode = 0;

                // Add liveness since updateLiveIns now skips this node.
                if (I->Kill.isValid())
                    I->LI->addRange(LiveRange(Start, I->Kill, VNI));
                else {
                    I->LI->addRange(LiveRange(Start, End, VNI));
                    LOP = LiveOutPair(VNI, Node);
                }
            } else if (IDomValue.first) {
                // No phi-def here. Remember incoming value.
                I->Value = IDomValue.first;

                // If the IDomValue is killed in the block, don't propagate through.
                if (I->Kill.isValid())
                    continue;

                // Propagate IDomValue if it isn't killed:
                // MBB is live-out and doesn't define its own value.
                if (LOP.first == IDomValue.first)
                    continue;
                ++Changes;
                LOP = IDomValue;
            }
        }
    } while (Changes);
}
Exemplo n.º 5
0
/// Walk the specified loop in the CFG (defined by all blocks dominated by the
/// specified header block, and that are in the current loop) in depth first
/// order w.r.t the DominatorTree. This allows us to visit definitions before
/// uses, allowing us to hoist a loop body in one pass without iteration.
///
void MachineLICM::HoistOutOfLoop(MachineDomTreeNode *HeaderN) {
  MachineBasicBlock *Preheader = getCurPreheader();
  if (!Preheader)
    return;

  SmallVector<MachineDomTreeNode*, 32> Scopes;
  SmallVector<MachineDomTreeNode*, 8> WorkList;
  DenseMap<MachineDomTreeNode*, MachineDomTreeNode*> ParentMap;
  DenseMap<MachineDomTreeNode*, unsigned> OpenChildren;

  // Perform a DFS walk to determine the order of visit.
  WorkList.push_back(HeaderN);
  while (!WorkList.empty()) {
    MachineDomTreeNode *Node = WorkList.pop_back_val();
    assert(Node && "Null dominator tree node?");
    MachineBasicBlock *BB = Node->getBlock();

    // If the header of the loop containing this basic block is a landing pad,
    // then don't try to hoist instructions out of this loop.
    const MachineLoop *ML = MLI->getLoopFor(BB);
    if (ML && ML->getHeader()->isEHPad())
      continue;

    // If this subregion is not in the top level loop at all, exit.
    if (!CurLoop->contains(BB))
      continue;

    Scopes.push_back(Node);
    const std::vector<MachineDomTreeNode*> &Children = Node->getChildren();
    unsigned NumChildren = Children.size();

    // Don't hoist things out of a large switch statement.  This often causes
    // code to be hoisted that wasn't going to be executed, and increases
    // register pressure in a situation where it's likely to matter.
    if (BB->succ_size() >= 25)
      NumChildren = 0;

    OpenChildren[Node] = NumChildren;
    // Add children in reverse order as then the next popped worklist node is
    // the first child of this node.  This means we ultimately traverse the
    // DOM tree in exactly the same order as if we'd recursed.
    for (int i = (int)NumChildren-1; i >= 0; --i) {
      MachineDomTreeNode *Child = Children[i];
      ParentMap[Child] = Node;
      WorkList.push_back(Child);
    }
  }

  if (Scopes.size() == 0)
    return;

  // Compute registers which are livein into the loop headers.
  RegSeen.clear();
  BackTrace.clear();
  InitRegPressure(Preheader);

  // Now perform LICM.
  for (MachineDomTreeNode *Node : Scopes) {
    MachineBasicBlock *MBB = Node->getBlock();

    EnterScope(MBB);

    // Process the block
    SpeculationState = SpeculateUnknown;
    for (MachineBasicBlock::iterator
         MII = MBB->begin(), E = MBB->end(); MII != E; ) {
      MachineBasicBlock::iterator NextMII = MII; ++NextMII;
      MachineInstr *MI = &*MII;
      if (!Hoist(MI, Preheader))
        UpdateRegPressure(MI);
      MII = NextMII;
    }

    // If it's a leaf node, it's done. Traverse upwards to pop ancestors.
    ExitScopeIfDone(Node, OpenChildren, ParentMap);
  }
}
Exemplo n.º 6
0
// This is essentially the same iterative algorithm that SSAUpdater uses,
// except we already have a dominator tree, so we don't have to recompute it.
void LiveRangeCalc::updateSSA() {
  assert(Indexes && "Missing SlotIndexes");
  assert(DomTree && "Missing dominator tree");

  // Interate until convergence.
  bool Changed;
  do {
    Changed = false;
    // Propagate live-out values down the dominator tree, inserting phi-defs
    // when necessary.
    for (LiveInBlock &I : LiveIn) {
      MachineDomTreeNode *Node = I.DomNode;
      // Skip block if the live-in value has already been determined.
      if (!Node)
        continue;
      MachineBasicBlock *MBB = Node->getBlock();
      MachineDomTreeNode *IDom = Node->getIDom();
      LiveOutPair IDomValue;

      // We need a live-in value to a block with no immediate dominator?
      // This is probably an unreachable block that has survived somehow.
      bool needPHI = !IDom || !Seen.test(IDom->getBlock()->getNumber());

      // IDom dominates all of our predecessors, but it may not be their
      // immediate dominator. Check if any of them have live-out values that are
      // properly dominated by IDom. If so, we need a phi-def here.
      if (!needPHI) {
        IDomValue = Map[IDom->getBlock()];

        // Cache the DomTree node that defined the value.
        if (IDomValue.first && IDomValue.first != &UndefVNI &&
            !IDomValue.second) {
          Map[IDom->getBlock()].second = IDomValue.second =
            DomTree->getNode(Indexes->getMBBFromIndex(IDomValue.first->def));
        }

        for (MachineBasicBlock *Pred : MBB->predecessors()) {
          LiveOutPair &Value = Map[Pred];
          if (!Value.first || Value.first == IDomValue.first)
            continue;
          if (Value.first == &UndefVNI) {
            needPHI = true;
            break;
          }

          // Cache the DomTree node that defined the value.
          if (!Value.second)
            Value.second =
              DomTree->getNode(Indexes->getMBBFromIndex(Value.first->def));

          // This predecessor is carrying something other than IDomValue.
          // It could be because IDomValue hasn't propagated yet, or it could be
          // because MBB is in the dominance frontier of that value.
          if (DomTree->dominates(IDom, Value.second)) {
            needPHI = true;
            break;
          }
        }
      }

      // The value may be live-through even if Kill is set, as can happen when
      // we are called from extendRange. In that case LiveOutSeen is true, and
      // LiveOut indicates a foreign or missing value.
      LiveOutPair &LOP = Map[MBB];

      // Create a phi-def if required.
      if (needPHI) {
        Changed = true;
        assert(Alloc && "Need VNInfo allocator to create PHI-defs");
        SlotIndex Start, End;
        std::tie(Start, End) = Indexes->getMBBRange(MBB);
        LiveRange &LR = I.LR;
        VNInfo *VNI = LR.getNextValue(Start, *Alloc);
        I.Value = VNI;
        // This block is done, we know the final value.
        I.DomNode = nullptr;

        // Add liveness since updateFromLiveIns now skips this node.
        if (I.Kill.isValid()) {
          if (VNI)
            LR.addSegment(LiveInterval::Segment(Start, I.Kill, VNI));
        } else {
          if (VNI)
            LR.addSegment(LiveInterval::Segment(Start, End, VNI));
          LOP = LiveOutPair(VNI, Node);
        }
      } else if (IDomValue.first && IDomValue.first != &UndefVNI) {
        // No phi-def here. Remember incoming value.
        I.Value = IDomValue.first;

        // If the IDomValue is killed in the block, don't propagate through.
        if (I.Kill.isValid())
          continue;

        // Propagate IDomValue if it isn't killed:
        // MBB is live-out and doesn't define its own value.
        if (LOP.first == IDomValue.first)
          continue;
        Changed = true;
        LOP = IDomValue;
      }
    }
  } while (Changed);
}