[PATCH] Separate Machine IR from CodeGen: Move SplitCriticalEdge out of MachineBasicBlock

Duncan P. N. Exon Smith dexonsmith at apple.com
Wed May 27 10:15:55 PDT 2015


> On 2015 May 27, at 09:49, Alex Lorenz <arphaman at gmail.com> wrote:
> 
> Hi dexonsmith, bogner, bob.wilson,
> 
> This patch is related to my proposal for separating machine IR from CodeGen: http://lists.cs.uiuc.edu/pipermail/llvmdev/2015-May/086063.html.
> 
> This patch moves the SplitCriticalEdge method out of MachineBasicBlock class so that MachineBasicBlock.cpp won't have to include several header 
> files that declare passes that won't be moved from CodeGen to the new Machine IR library.
> 
> REPOSITORY
>  rL LLVM
> 
> http://reviews.llvm.org/D10064
> 
> Files:
>  include/llvm/CodeGen/MachineBasicBlock.h
>  include/llvm/CodeGen/MachineIRUtils.h
>  lib/CodeGen/CMakeLists.txt
>  lib/CodeGen/MachineBasicBlock.cpp
>  lib/CodeGen/MachineIRUtils.cpp
>  lib/CodeGen/MachineLICM.cpp
>  lib/CodeGen/MachineSink.cpp
>  lib/CodeGen/PHIElimination.cpp
> 
> EMAIL PREFERENCES
>  http://reviews.llvm.org/settings/panel/emailpreferences/
> <D10064.26608.patch>

> Index: include/llvm/CodeGen/MachineBasicBlock.h
> ===================================================================
> --- include/llvm/CodeGen/MachineBasicBlock.h
> +++ include/llvm/CodeGen/MachineBasicBlock.h
> @@ -21,7 +21,6 @@
>  
>  namespace llvm {
>  
> -class Pass;
>  class BasicBlock;
>  class MachineFunction;
>  class MCSymbol;
> @@ -472,14 +471,6 @@
>    iterator getLastNonDebugInstr();
>    const_iterator getLastNonDebugInstr() const;
>  
> -  /// SplitCriticalEdge - Split the critical edge from this block to the
> -  /// given successor block, and return the newly created block, or null
> -  /// if splitting is not possible.
> -  ///
> -  /// This function updates LiveVariables, MachineDominatorTree, and
> -  /// MachineLoopInfo, as applicable.
> -  MachineBasicBlock *SplitCriticalEdge(MachineBasicBlock *Succ, Pass *P);
> -
>    void pop_front() { Insts.pop_front(); }
>    void pop_back() { Insts.pop_back(); }
>    void push_back(MachineInstr *MI) { Insts.push_back(MI); }
> Index: include/llvm/CodeGen/MachineIRUtils.h
> ===================================================================
> --- /dev/null
> +++ include/llvm/CodeGen/MachineIRUtils.h

This name is pretty generic.  Is there a list of things you're planning
to add here?  If not, `SplitCriticalEdge.h` seems like a better name.
If so, it'd be good to get a high-level view of all the code motion
you're going to do up front.

> @@ -0,0 +1,38 @@
> +//===-- llvm/CodeGen/MachineIRUtils.h ---------------------------*- C++ -*-===//
> +//
> +//                     The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +//
> +// This file contains the declarations of functions that implement machine IR
> +// utility algorithms.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#ifndef LLVM_CODEGEN_MACHINEIRUTILS_H
> +#define LLVM_CODEGEN_MACHINEIRUTILS_H
> +
> +namespace llvm {
> +
> +class Pass;
> +class MachineBasicBlock;
> +
> +namespace MachineIRUtils {

Do we need the extra namespace?

> +
> +/// SplitCriticalEdge - Split the critical edge from this block to the

Since you're moving this anyway, please fix up the old-style comment
(stop repeating the function name).

Also, the comment talks about "this" block, but should probably refer
to "BB".

> +/// given successor block, and return the newly created block, or null
> +/// if splitting is not possible.
> +///
> +/// This function updates LiveVariables, MachineDominatorTree, and
> +/// MachineLoopInfo, as applicable.
> +MachineBasicBlock *SplitCriticalEdge(MachineBasicBlock *BB,
> +                                     MachineBasicBlock *Succ, Pass *P);

Since you're moving this and updating all the callers anyway, please
take the opportunity to fix the function name.  It should be
`splitCriticalEdge()`.

> +
> +} // End namespace MachineIRUtils
> +
> +} // End namespace llvm
> +
> +#endif
> Index: lib/CodeGen/CMakeLists.txt
> ===================================================================
> --- lib/CodeGen/CMakeLists.txt
> +++ lib/CodeGen/CMakeLists.txt
> @@ -58,6 +58,7 @@
>    MachineFunctionPrinterPass.cpp
>    MachineInstr.cpp
>    MachineInstrBundle.cpp
> +  MachineIRUtils.cpp
>    MachineLICM.cpp
>    MachineLoopInfo.cpp
>    MachineModuleInfo.cpp
> Index: lib/CodeGen/MachineBasicBlock.cpp
> ===================================================================
> --- lib/CodeGen/MachineBasicBlock.cpp
> +++ lib/CodeGen/MachineBasicBlock.cpp
> @@ -14,12 +14,8 @@
>  #include "llvm/CodeGen/MachineBasicBlock.h"
>  #include "llvm/ADT/SmallPtrSet.h"
>  #include "llvm/ADT/SmallString.h"
> -#include "llvm/CodeGen/LiveIntervalAnalysis.h"
> -#include "llvm/CodeGen/LiveVariables.h"
> -#include "llvm/CodeGen/MachineDominators.h"
>  #include "llvm/CodeGen/MachineFunction.h"
>  #include "llvm/CodeGen/MachineInstrBuilder.h"
> -#include "llvm/CodeGen/MachineLoopInfo.h"
>  #include "llvm/CodeGen/MachineRegisterInfo.h"
>  #include "llvm/CodeGen/SlotIndexes.h"
>  #include "llvm/IR/BasicBlock.h"
> @@ -664,270 +660,6 @@
>    return FBB == nullptr;
>  }
>  
> -MachineBasicBlock *
> -MachineBasicBlock::SplitCriticalEdge(MachineBasicBlock *Succ, Pass *P) {
> -  // Splitting the critical edge to a landing pad block is non-trivial. Don't do
> -  // it in this generic function.
> -  if (Succ->isLandingPad())
> -    return nullptr;
> -
> -  MachineFunction *MF = getParent();
> -  DebugLoc dl;  // FIXME: this is nowhere
> -
> -  // Performance might be harmed on HW that implements branching using exec mask
> -  // where both sides of the branches are always executed.
> -  if (MF->getTarget().requiresStructuredCFG())
> -    return nullptr;
> -
> -  // We may need to update this's terminator, but we can't do that if
> -  // AnalyzeBranch fails. If this uses a jump table, we won't touch it.
> -  const TargetInstrInfo *TII = MF->getSubtarget().getInstrInfo();
> -  MachineBasicBlock *TBB = nullptr, *FBB = nullptr;
> -  SmallVector<MachineOperand, 4> Cond;
> -  if (TII->AnalyzeBranch(*this, TBB, FBB, Cond))
> -    return nullptr;
> -
> -  // Avoid bugpoint weirdness: A block may end with a conditional branch but
> -  // jumps to the same MBB is either case. We have duplicate CFG edges in that
> -  // case that we can't handle. Since this never happens in properly optimized
> -  // code, just skip those edges.
> -  if (TBB && TBB == FBB) {
> -    DEBUG(dbgs() << "Won't split critical edge after degenerate BB#"
> -                 << getNumber() << '\n');
> -    return nullptr;
> -  }
> -
> -  MachineBasicBlock *NMBB = MF->CreateMachineBasicBlock();
> -  MF->insert(std::next(MachineFunction::iterator(this)), NMBB);
> -  DEBUG(dbgs() << "Splitting critical edge:"
> -        " BB#" << getNumber()
> -        << " -- BB#" << NMBB->getNumber()
> -        << " -- BB#" << Succ->getNumber() << '\n');
> -
> -  LiveIntervals *LIS = P->getAnalysisIfAvailable<LiveIntervals>();
> -  SlotIndexes *Indexes = P->getAnalysisIfAvailable<SlotIndexes>();
> -  if (LIS)
> -    LIS->insertMBBInMaps(NMBB);
> -  else if (Indexes)
> -    Indexes->insertMBBInMaps(NMBB);
> -
> -  // On some targets like Mips, branches may kill virtual registers. Make sure
> -  // that LiveVariables is properly updated after updateTerminator replaces the
> -  // terminators.
> -  LiveVariables *LV = P->getAnalysisIfAvailable<LiveVariables>();
> -
> -  // Collect a list of virtual registers killed by the terminators.
> -  SmallVector<unsigned, 4> KilledRegs;
> -  if (LV)
> -    for (instr_iterator I = getFirstInstrTerminator(), E = instr_end();
> -         I != E; ++I) {
> -      MachineInstr *MI = I;
> -      for (MachineInstr::mop_iterator OI = MI->operands_begin(),
> -           OE = MI->operands_end(); OI != OE; ++OI) {
> -        if (!OI->isReg() || OI->getReg() == 0 ||
> -            !OI->isUse() || !OI->isKill() || OI->isUndef())
> -          continue;
> -        unsigned Reg = OI->getReg();
> -        if (TargetRegisterInfo::isPhysicalRegister(Reg) ||
> -            LV->getVarInfo(Reg).removeKill(MI)) {
> -          KilledRegs.push_back(Reg);
> -          DEBUG(dbgs() << "Removing terminator kill: " << *MI);
> -          OI->setIsKill(false);
> -        }
> -      }
> -    }
> -
> -  SmallVector<unsigned, 4> UsedRegs;
> -  if (LIS) {
> -    for (instr_iterator I = getFirstInstrTerminator(), E = instr_end();
> -         I != E; ++I) {
> -      MachineInstr *MI = I;
> -
> -      for (MachineInstr::mop_iterator OI = MI->operands_begin(),
> -           OE = MI->operands_end(); OI != OE; ++OI) {
> -        if (!OI->isReg() || OI->getReg() == 0)
> -          continue;
> -
> -        unsigned Reg = OI->getReg();
> -        if (std::find(UsedRegs.begin(), UsedRegs.end(), Reg) == UsedRegs.end())
> -          UsedRegs.push_back(Reg);
> -      }
> -    }
> -  }
> -
> -  ReplaceUsesOfBlockWith(Succ, NMBB);
> -
> -  // If updateTerminator() removes instructions, we need to remove them from
> -  // SlotIndexes.
> -  SmallVector<MachineInstr*, 4> Terminators;
> -  if (Indexes) {
> -    for (instr_iterator I = getFirstInstrTerminator(), E = instr_end();
> -         I != E; ++I)
> -      Terminators.push_back(I);
> -  }
> -
> -  updateTerminator();
> -
> -  if (Indexes) {
> -    SmallVector<MachineInstr*, 4> NewTerminators;
> -    for (instr_iterator I = getFirstInstrTerminator(), E = instr_end();
> -         I != E; ++I)
> -      NewTerminators.push_back(I);
> -
> -    for (SmallVectorImpl<MachineInstr*>::iterator I = Terminators.begin(),
> -        E = Terminators.end(); I != E; ++I) {
> -      if (std::find(NewTerminators.begin(), NewTerminators.end(), *I) ==
> -          NewTerminators.end())
> -       Indexes->removeMachineInstrFromMaps(*I);
> -    }
> -  }
> -
> -  // Insert unconditional "jump Succ" instruction in NMBB if necessary.
> -  NMBB->addSuccessor(Succ);
> -  if (!NMBB->isLayoutSuccessor(Succ)) {
> -    Cond.clear();
> -    MF->getSubtarget().getInstrInfo()->InsertBranch(*NMBB, Succ, nullptr, Cond,
> -                                                    dl);
> -
> -    if (Indexes) {
> -      for (instr_iterator I = NMBB->instr_begin(), E = NMBB->instr_end();
> -           I != E; ++I) {
> -        // Some instructions may have been moved to NMBB by updateTerminator(),
> -        // so we first remove any instruction that already has an index.
> -        if (Indexes->hasIndex(I))
> -          Indexes->removeMachineInstrFromMaps(I);
> -        Indexes->insertMachineInstrInMaps(I);
> -      }
> -    }
> -  }
> -
> -  // Fix PHI nodes in Succ so they refer to NMBB instead of this
> -  for (MachineBasicBlock::instr_iterator
> -         i = Succ->instr_begin(),e = Succ->instr_end();
> -       i != e && i->isPHI(); ++i)
> -    for (unsigned ni = 1, ne = i->getNumOperands(); ni != ne; ni += 2)
> -      if (i->getOperand(ni+1).getMBB() == this)
> -        i->getOperand(ni+1).setMBB(NMBB);
> -
> -  // Inherit live-ins from the successor
> -  for (MachineBasicBlock::livein_iterator I = Succ->livein_begin(),
> -         E = Succ->livein_end(); I != E; ++I)
> -    NMBB->addLiveIn(*I);
> -
> -  // Update LiveVariables.
> -  const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
> -  if (LV) {
> -    // Restore kills of virtual registers that were killed by the terminators.
> -    while (!KilledRegs.empty()) {
> -      unsigned Reg = KilledRegs.pop_back_val();
> -      for (instr_iterator I = instr_end(), E = instr_begin(); I != E;) {
> -        if (!(--I)->addRegisterKilled(Reg, TRI, /* addIfNotFound= */ false))
> -          continue;
> -        if (TargetRegisterInfo::isVirtualRegister(Reg))
> -          LV->getVarInfo(Reg).Kills.push_back(I);
> -        DEBUG(dbgs() << "Restored terminator kill: " << *I);
> -        break;
> -      }
> -    }
> -    // Update relevant live-through information.
> -    LV->addNewBlock(NMBB, this, Succ);
> -  }
> -
> -  if (LIS) {
> -    // After splitting the edge and updating SlotIndexes, live intervals may be
> -    // in one of two situations, depending on whether this block was the last in
> -    // the function. If the original block was the last in the function, all live
> -    // intervals will end prior to the beginning of the new split block. If the
> -    // original block was not at the end of the function, all live intervals will
> -    // extend to the end of the new split block.
> -
> -    bool isLastMBB =
> -      std::next(MachineFunction::iterator(NMBB)) == getParent()->end();
> -
> -    SlotIndex StartIndex = Indexes->getMBBEndIdx(this);
> -    SlotIndex PrevIndex = StartIndex.getPrevSlot();
> -    SlotIndex EndIndex = Indexes->getMBBEndIdx(NMBB);
> -
> -    // Find the registers used from NMBB in PHIs in Succ.
> -    SmallSet<unsigned, 8> PHISrcRegs;
> -    for (MachineBasicBlock::instr_iterator
> -         I = Succ->instr_begin(), E = Succ->instr_end();
> -         I != E && I->isPHI(); ++I) {
> -      for (unsigned ni = 1, ne = I->getNumOperands(); ni != ne; ni += 2) {
> -        if (I->getOperand(ni+1).getMBB() == NMBB) {
> -          MachineOperand &MO = I->getOperand(ni);
> -          unsigned Reg = MO.getReg();
> -          PHISrcRegs.insert(Reg);
> -          if (MO.isUndef())
> -            continue;
> -
> -          LiveInterval &LI = LIS->getInterval(Reg);
> -          VNInfo *VNI = LI.getVNInfoAt(PrevIndex);
> -          assert(VNI && "PHI sources should be live out of their predecessors.");
> -          LI.addSegment(LiveInterval::Segment(StartIndex, EndIndex, VNI));
> -        }
> -      }
> -    }
> -
> -    MachineRegisterInfo *MRI = &getParent()->getRegInfo();
> -    for (unsigned i = 0, e = MRI->getNumVirtRegs(); i != e; ++i) {
> -      unsigned Reg = TargetRegisterInfo::index2VirtReg(i);
> -      if (PHISrcRegs.count(Reg) || !LIS->hasInterval(Reg))
> -        continue;
> -
> -      LiveInterval &LI = LIS->getInterval(Reg);
> -      if (!LI.liveAt(PrevIndex))
> -        continue;
> -
> -      bool isLiveOut = LI.liveAt(LIS->getMBBStartIdx(Succ));
> -      if (isLiveOut && isLastMBB) {
> -        VNInfo *VNI = LI.getVNInfoAt(PrevIndex);
> -        assert(VNI && "LiveInterval should have VNInfo where it is live.");
> -        LI.addSegment(LiveInterval::Segment(StartIndex, EndIndex, VNI));
> -      } else if (!isLiveOut && !isLastMBB) {
> -        LI.removeSegment(StartIndex, EndIndex);
> -      }
> -    }
> -
> -    // Update all intervals for registers whose uses may have been modified by
> -    // updateTerminator().
> -    LIS->repairIntervalsInRange(this, getFirstTerminator(), end(), UsedRegs);
> -  }
> -
> -  if (MachineDominatorTree *MDT =
> -      P->getAnalysisIfAvailable<MachineDominatorTree>())
> -    MDT->recordSplitCriticalEdge(this, Succ, NMBB);
> -
> -  if (MachineLoopInfo *MLI = P->getAnalysisIfAvailable<MachineLoopInfo>())
> -    if (MachineLoop *TIL = MLI->getLoopFor(this)) {
> -      // If one or the other blocks were not in a loop, the new block is not
> -      // either, and thus LI doesn't need to be updated.
> -      if (MachineLoop *DestLoop = MLI->getLoopFor(Succ)) {
> -        if (TIL == DestLoop) {
> -          // Both in the same loop, the NMBB joins loop.
> -          DestLoop->addBasicBlockToLoop(NMBB, MLI->getBase());
> -        } else if (TIL->contains(DestLoop)) {
> -          // Edge from an outer loop to an inner loop.  Add to the outer loop.
> -          TIL->addBasicBlockToLoop(NMBB, MLI->getBase());
> -        } else if (DestLoop->contains(TIL)) {
> -          // Edge from an inner loop to an outer loop.  Add to the outer loop.
> -          DestLoop->addBasicBlockToLoop(NMBB, MLI->getBase());
> -        } else {
> -          // Edge from two loops with no containment relation.  Because these
> -          // are natural loops, we know that the destination block must be the
> -          // header of its loop (adding a branch into a loop elsewhere would
> -          // create an irreducible loop).
> -          assert(DestLoop->getHeader() == Succ &&
> -                 "Should not create irreducible loops!");
> -          if (MachineLoop *P = DestLoop->getParentLoop())
> -            P->addBasicBlockToLoop(NMBB, MLI->getBase());
> -        }
> -      }
> -    }
> -
> -  return NMBB;
> -}
> -
>  /// Prepare MI to be removed from its bundle. This fixes bundle flags on MI's
>  /// neighboring instructions so the bundle won't be broken by removing MI.
>  static void unbundleSingleMI(MachineInstr *MI) {
> Index: lib/CodeGen/MachineIRUtils.cpp
> ===================================================================
> --- /dev/null
> +++ lib/CodeGen/MachineIRUtils.cpp
> @@ -0,0 +1,308 @@
> +//===-- llvm/CodeGen/MachineIRUtils.cpp -------------------------*- C++ -*-===//
> +//
> +//                     The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +//
> +// This file implements the implement machine IR utility algorithms.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#include "llvm/CodeGen/MachineIRUtils.h"
> +#include "llvm/CodeGen/LiveIntervalAnalysis.h"
> +#include "llvm/CodeGen/LiveVariables.h"
> +#include "llvm/CodeGen/MachineDominators.h"
> +#include "llvm/CodeGen/MachineFunction.h"
> +#include "llvm/CodeGen/MachineLoopInfo.h"
> +#include "llvm/CodeGen/MachineRegisterInfo.h"
> +#include "llvm/CodeGen/SlotIndexes.h"
> +#include "llvm/Support/Debug.h"
> +#include "llvm/Support/raw_ostream.h"
> +#include "llvm/Target/TargetInstrInfo.h"
> +#include "llvm/Target/TargetMachine.h"
> +#include "llvm/Target/TargetRegisterInfo.h"
> +#include <algorithm>
> +using namespace llvm;
> +
> +#define DEBUG_TYPE "codegen"
> +
> +MachineBasicBlock *MachineIRUtils::SplitCriticalEdge(MachineBasicBlock *BB,
> +                                                     MachineBasicBlock *Succ,
> +                                                     Pass *P) {
> +  // Splitting the critical edge to a landing pad block is non-trivial. Don't do
> +  // it in this generic function.
> +  if (Succ->isLandingPad())
> +    return nullptr;
> +
> +  MachineFunction *MF = BB->getParent();
> +  DebugLoc dl; // FIXME: this is nowhere
> +
> +  // Performance might be harmed on HW that implements branching using exec mask
> +  // where both sides of the branches are always executed.
> +  if (MF->getTarget().requiresStructuredCFG())
> +    return nullptr;
> +
> +  // We may need to update this's terminator, but we can't do that if
> +  // AnalyzeBranch fails. If this uses a jump table, we won't touch it.
> +  const TargetInstrInfo *TII = MF->getSubtarget().getInstrInfo();
> +  MachineBasicBlock *TBB = nullptr, *FBB = nullptr;
> +  SmallVector<MachineOperand, 4> Cond;
> +  if (TII->AnalyzeBranch(*BB, TBB, FBB, Cond))
> +    return nullptr;
> +
> +  // Avoid bugpoint weirdness: A block may end with a conditional branch but
> +  // jumps to the same MBB is either case. We have duplicate CFG edges in that
> +  // case that we can't handle. Since this never happens in properly optimized
> +  // code, just skip those edges.
> +  if (TBB && TBB == FBB) {
> +    DEBUG(dbgs() << "Won't split critical edge after degenerate BB#"
> +                 << BB->getNumber() << '\n');
> +    return nullptr;
> +  }
> +
> +  MachineBasicBlock *NMBB = MF->CreateMachineBasicBlock();
> +  MF->insert(std::next(MachineFunction::iterator(BB)), NMBB);
> +  DEBUG(dbgs() << "Splitting critical edge:"
> +                  " BB#" << BB->getNumber() << " -- BB#" << NMBB->getNumber()
> +               << " -- BB#" << Succ->getNumber() << '\n');
> +
> +  LiveIntervals *LIS = P->getAnalysisIfAvailable<LiveIntervals>();
> +  SlotIndexes *Indexes = P->getAnalysisIfAvailable<SlotIndexes>();
> +  if (LIS)
> +    LIS->insertMBBInMaps(NMBB);
> +  else if (Indexes)
> +    Indexes->insertMBBInMaps(NMBB);
> +
> +  // On some targets like Mips, branches may kill virtual registers. Make sure
> +  // that LiveVariables is properly updated after updateTerminator replaces the
> +  // terminators.
> +  LiveVariables *LV = P->getAnalysisIfAvailable<LiveVariables>();
> +
> +  // Collect a list of virtual registers killed by the terminators.
> +  SmallVector<unsigned, 4> KilledRegs;
> +  if (LV)
> +    for (MachineBasicBlock::instr_iterator I = BB->getFirstInstrTerminator(),
> +                                           E = BB->instr_end();
> +         I != E; ++I) {
> +      MachineInstr *MI = I;
> +      for (MachineInstr::mop_iterator OI = MI->operands_begin(),
> +                                      OE = MI->operands_end();
> +           OI != OE; ++OI) {
> +        if (!OI->isReg() || OI->getReg() == 0 || !OI->isUse() ||
> +            !OI->isKill() || OI->isUndef())
> +          continue;
> +        unsigned Reg = OI->getReg();
> +        if (TargetRegisterInfo::isPhysicalRegister(Reg) ||
> +            LV->getVarInfo(Reg).removeKill(MI)) {
> +          KilledRegs.push_back(Reg);
> +          DEBUG(dbgs() << "Removing terminator kill: " << *MI);
> +          OI->setIsKill(false);
> +        }
> +      }
> +    }
> +
> +  SmallVector<unsigned, 4> UsedRegs;
> +  if (LIS) {
> +    for (MachineBasicBlock::instr_iterator I = BB->getFirstInstrTerminator(),
> +                                           E = BB->instr_end();
> +         I != E; ++I) {
> +      MachineInstr *MI = I;
> +
> +      for (MachineInstr::mop_iterator OI = MI->operands_begin(),
> +                                      OE = MI->operands_end();
> +           OI != OE; ++OI) {
> +        if (!OI->isReg() || OI->getReg() == 0)
> +          continue;
> +
> +        unsigned Reg = OI->getReg();
> +        if (std::find(UsedRegs.begin(), UsedRegs.end(), Reg) == UsedRegs.end())
> +          UsedRegs.push_back(Reg);
> +      }
> +    }
> +  }
> +
> +  BB->ReplaceUsesOfBlockWith(Succ, NMBB);
> +
> +  // If updateTerminator() removes instructions, we need to remove them from
> +  // SlotIndexes.
> +  SmallVector<MachineInstr *, 4> Terminators;
> +  if (Indexes) {
> +    for (MachineBasicBlock::instr_iterator I = BB->getFirstInstrTerminator(),
> +                                           E = BB->instr_end();
> +         I != E; ++I)
> +      Terminators.push_back(I);
> +  }
> +
> +  BB->updateTerminator();
> +
> +  if (Indexes) {
> +    SmallVector<MachineInstr *, 4> NewTerminators;
> +    for (MachineBasicBlock::instr_iterator I = BB->getFirstInstrTerminator(),
> +                                           E = BB->instr_end();
> +         I != E; ++I)
> +      NewTerminators.push_back(I);
> +
> +    for (SmallVectorImpl<MachineInstr *>::iterator I = Terminators.begin(),
> +                                                   E = Terminators.end();
> +         I != E; ++I) {
> +      if (std::find(NewTerminators.begin(), NewTerminators.end(), *I) ==
> +          NewTerminators.end())
> +        Indexes->removeMachineInstrFromMaps(*I);
> +    }
> +  }
> +
> +  // Insert unconditional "jump Succ" instruction in NMBB if necessary.
> +  NMBB->addSuccessor(Succ);
> +  if (!NMBB->isLayoutSuccessor(Succ)) {
> +    Cond.clear();
> +    MF->getSubtarget().getInstrInfo()->InsertBranch(*NMBB, Succ, nullptr, Cond,
> +                                                    dl);
> +
> +    if (Indexes) {
> +      for (MachineBasicBlock::instr_iterator I = NMBB->instr_begin(),
> +                                             E = NMBB->instr_end();
> +           I != E; ++I) {
> +        // Some instructions may have been moved to NMBB by updateTerminator(),
> +        // so we first remove any instruction that already has an index.
> +        if (Indexes->hasIndex(I))
> +          Indexes->removeMachineInstrFromMaps(I);
> +        Indexes->insertMachineInstrInMaps(I);
> +      }
> +    }
> +  }
> +
> +  // Fix PHI nodes in Succ so they refer to NMBB instead of this
> +  for (MachineBasicBlock::instr_iterator i = Succ->instr_begin(),
> +                                         e = Succ->instr_end();
> +       i != e && i->isPHI(); ++i)
> +    for (unsigned ni = 1, ne = i->getNumOperands(); ni != ne; ni += 2)
> +      if (i->getOperand(ni + 1).getMBB() == BB)
> +        i->getOperand(ni + 1).setMBB(NMBB);
> +
> +  // Inherit live-ins from the successor
> +  for (MachineBasicBlock::livein_iterator I = Succ->livein_begin(),
> +                                          E = Succ->livein_end();
> +       I != E; ++I)
> +    NMBB->addLiveIn(*I);
> +
> +  // Update LiveVariables.
> +  const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
> +  if (LV) {
> +    // Restore kills of virtual registers that were killed by the terminators.
> +    while (!KilledRegs.empty()) {
> +      unsigned Reg = KilledRegs.pop_back_val();
> +      for (MachineBasicBlock::instr_iterator I = BB->instr_end(),
> +                                             E = BB->instr_begin();
> +           I != E;) {
> +        if (!(--I)->addRegisterKilled(Reg, TRI, /* addIfNotFound= */ false))
> +          continue;
> +        if (TargetRegisterInfo::isVirtualRegister(Reg))
> +          LV->getVarInfo(Reg).Kills.push_back(I);
> +        DEBUG(dbgs() << "Restored terminator kill: " << *I);
> +        break;
> +      }
> +    }
> +    // Update relevant live-through information.
> +    LV->addNewBlock(NMBB, BB, Succ);
> +  }
> +
> +  if (LIS) {
> +    // After splitting the edge and updating SlotIndexes, live intervals may be
> +    // in one of two situations, depending on whether this block was the last in
> +    // the function. If the original block was the last in the function, all
> +    // live
> +    // intervals will end prior to the beginning of the new split block. If the
> +    // original block was not at the end of the function, all live intervals
> +    // will
> +    // extend to the end of the new split block.
> +
> +    bool isLastMBB = std::next(MachineFunction::iterator(NMBB)) == MF->end();
> +
> +    SlotIndex StartIndex = Indexes->getMBBEndIdx(BB);
> +    SlotIndex PrevIndex = StartIndex.getPrevSlot();
> +    SlotIndex EndIndex = Indexes->getMBBEndIdx(NMBB);
> +
> +    // Find the registers used from NMBB in PHIs in Succ.
> +    SmallSet<unsigned, 8> PHISrcRegs;
> +    for (MachineBasicBlock::instr_iterator I = Succ->instr_begin(),
> +                                           E = Succ->instr_end();
> +         I != E && I->isPHI(); ++I) {
> +      for (unsigned ni = 1, ne = I->getNumOperands(); ni != ne; ni += 2) {
> +        if (I->getOperand(ni + 1).getMBB() == NMBB) {
> +          MachineOperand &MO = I->getOperand(ni);
> +          unsigned Reg = MO.getReg();
> +          PHISrcRegs.insert(Reg);
> +          if (MO.isUndef())
> +            continue;
> +
> +          LiveInterval &LI = LIS->getInterval(Reg);
> +          VNInfo *VNI = LI.getVNInfoAt(PrevIndex);
> +          assert(VNI &&
> +                 "PHI sources should be live out of their predecessors.");
> +          LI.addSegment(LiveInterval::Segment(StartIndex, EndIndex, VNI));
> +        }
> +      }
> +    }
> +
> +    MachineRegisterInfo *MRI = &MF->getRegInfo();
> +    for (unsigned i = 0, e = MRI->getNumVirtRegs(); i != e; ++i) {
> +      unsigned Reg = TargetRegisterInfo::index2VirtReg(i);
> +      if (PHISrcRegs.count(Reg) || !LIS->hasInterval(Reg))
> +        continue;
> +
> +      LiveInterval &LI = LIS->getInterval(Reg);
> +      if (!LI.liveAt(PrevIndex))
> +        continue;
> +
> +      bool isLiveOut = LI.liveAt(LIS->getMBBStartIdx(Succ));
> +      if (isLiveOut && isLastMBB) {
> +        VNInfo *VNI = LI.getVNInfoAt(PrevIndex);
> +        assert(VNI && "LiveInterval should have VNInfo where it is live.");
> +        LI.addSegment(LiveInterval::Segment(StartIndex, EndIndex, VNI));
> +      } else if (!isLiveOut && !isLastMBB) {
> +        LI.removeSegment(StartIndex, EndIndex);
> +      }
> +    }
> +
> +    // Update all intervals for registers whose uses may have been modified by
> +    // updateTerminator().
> +    LIS->repairIntervalsInRange(BB, BB->getFirstTerminator(), BB->end(),
> +                                UsedRegs);
> +  }
> +
> +  if (MachineDominatorTree *MDT =
> +          P->getAnalysisIfAvailable<MachineDominatorTree>())
> +    MDT->recordSplitCriticalEdge(BB, Succ, NMBB);
> +
> +  if (MachineLoopInfo *MLI = P->getAnalysisIfAvailable<MachineLoopInfo>())
> +    if (MachineLoop *TIL = MLI->getLoopFor(BB)) {
> +      // If one or the other blocks were not in a loop, the new block is not
> +      // either, and thus LI doesn't need to be updated.
> +      if (MachineLoop *DestLoop = MLI->getLoopFor(Succ)) {
> +        if (TIL == DestLoop) {
> +          // Both in the same loop, the NMBB joins loop.
> +          DestLoop->addBasicBlockToLoop(NMBB, MLI->getBase());
> +        } else if (TIL->contains(DestLoop)) {
> +          // Edge from an outer loop to an inner loop.  Add to the outer loop.
> +          TIL->addBasicBlockToLoop(NMBB, MLI->getBase());
> +        } else if (DestLoop->contains(TIL)) {
> +          // Edge from an inner loop to an outer loop.  Add to the outer loop.
> +          DestLoop->addBasicBlockToLoop(NMBB, MLI->getBase());
> +        } else {
> +          // Edge from two loops with no containment relation.  Because these
> +          // are natural loops, we know that the destination block must be the
> +          // header of its loop (adding a branch into a loop elsewhere would
> +          // create an irreducible loop).
> +          assert(DestLoop->getHeader() == Succ &&
> +                 "Should not create irreducible loops!");
> +          if (MachineLoop *P = DestLoop->getParentLoop())
> +            P->addBasicBlockToLoop(NMBB, MLI->getBase());
> +        }
> +      }
> +    }
> +
> +  return NMBB;
> +}
> Index: lib/CodeGen/MachineLICM.cpp
> ===================================================================
> --- lib/CodeGen/MachineLICM.cpp
> +++ lib/CodeGen/MachineLICM.cpp
> @@ -23,6 +23,7 @@
>  #include "llvm/Analysis/AliasAnalysis.h"
>  #include "llvm/CodeGen/MachineDominators.h"
>  #include "llvm/CodeGen/MachineFrameInfo.h"
> +#include "llvm/CodeGen/MachineIRUtils.h"
>  #include "llvm/CodeGen/MachineLoopInfo.h"
>  #include "llvm/CodeGen/MachineMemOperand.h"
>  #include "llvm/CodeGen/MachineRegisterInfo.h"
> @@ -1459,7 +1460,8 @@
>          return nullptr;
>        }
>  
> -      CurPreheader = Pred->SplitCriticalEdge(CurLoop->getHeader(), this);
> +      CurPreheader =
> +          MachineIRUtils::SplitCriticalEdge(Pred, CurLoop->getHeader(), this);
>        if (!CurPreheader) {
>          CurPreheader = reinterpret_cast<MachineBasicBlock *>(-1);
>          return nullptr;
> Index: lib/CodeGen/MachineSink.cpp
> ===================================================================
> --- lib/CodeGen/MachineSink.cpp
> +++ lib/CodeGen/MachineSink.cpp
> @@ -24,6 +24,7 @@
>  #include "llvm/Analysis/AliasAnalysis.h"
>  #include "llvm/CodeGen/MachineBlockFrequencyInfo.h"
>  #include "llvm/CodeGen/MachineDominators.h"
> +#include "llvm/CodeGen/MachineIRUtils.h"
>  #include "llvm/CodeGen/MachineLoopInfo.h"
>  #include "llvm/CodeGen/MachinePostDominators.h"
>  #include "llvm/CodeGen/MachineRegisterInfo.h"
> @@ -275,7 +276,8 @@
>  
>      // If we have anything we marked as toSplit, split it now.
>      for (auto &Pair : ToSplit) {
> -      auto NewSucc = Pair.first->SplitCriticalEdge(Pair.second, this);
> +      auto NewSucc =
> +          MachineIRUtils::SplitCriticalEdge(Pair.first, Pair.second, this);
>        if (NewSucc != nullptr) {
>          DEBUG(dbgs() << " *** Splitting critical edge:"
>                " BB#" << Pair.first->getNumber()
> Index: lib/CodeGen/PHIElimination.cpp
> ===================================================================
> --- lib/CodeGen/PHIElimination.cpp
> +++ lib/CodeGen/PHIElimination.cpp
> @@ -23,6 +23,7 @@
>  #include "llvm/CodeGen/MachineDominators.h"
>  #include "llvm/CodeGen/MachineInstr.h"
>  #include "llvm/CodeGen/MachineInstrBuilder.h"
> +#include "llvm/CodeGen/MachineIRUtils.h"
>  #include "llvm/CodeGen/MachineLoopInfo.h"
>  #include "llvm/CodeGen/MachineRegisterInfo.h"
>  #include "llvm/IR/Function.h"
> @@ -612,7 +613,7 @@
>        }
>        if (!ShouldSplit && !SplitAllCriticalEdges)
>          continue;
> -      if (!PreMBB->SplitCriticalEdge(&MBB, this)) {
> +      if (!MachineIRUtils::SplitCriticalEdge(PreMBB, &MBB, this)) {
>          DEBUG(dbgs() << "Failed to split critical edge.\n");
>          continue;
>        }
> 





More information about the llvm-commits mailing list