[llvm-commits] [llvm] r111393 - in /llvm/trunk/lib/CodeGen: SplitKit.cpp SplitKit.h

Michael Spencer bigcheesegs at gmail.com
Thu Aug 19 07:10:36 PDT 2010


On Wed, Aug 18, 2010 at 3:00 PM, Jakob Stoklund Olesen <stoklund at 2pi.dk> wrote:
> Author: stoklund
> Date: Wed Aug 18 14:00:08 2010
> New Revision: 111393
>
> URL: http://llvm.org/viewvc/llvm-project?rev=111393&view=rev
> Log:
> Add the LiveIntervalMap class. Don't hook it up yet.
>
> LiveIntervalMap maps values from a parent LiveInterval to a child interval that
> is a strict subset. It will create phi-def values as needed to preserve the
> VNInfo SSA form in the child interval.
>
> This leads to an algorithm very similar to the one in SSAUpdaterImpl.h, but with
> enough differences that the code can't be reused:
>
> - We don't need to manipulate PHI instructions.
> - LiveIntervals have kills.
> - We have MachineDominatorTree.
> - We can use df_iterator.
>
> Modified:
>    llvm/trunk/lib/CodeGen/SplitKit.cpp
>    llvm/trunk/lib/CodeGen/SplitKit.h
>
> Modified: llvm/trunk/lib/CodeGen/SplitKit.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SplitKit.cpp?rev=111393&r1=111392&r2=111393&view=diff
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/SplitKit.cpp (original)
> +++ llvm/trunk/lib/CodeGen/SplitKit.cpp Wed Aug 18 14:00:08 2010
> @@ -17,7 +17,7 @@
>  #include "VirtRegMap.h"
>  #include "llvm/CodeGen/CalcSpillWeights.h"
>  #include "llvm/CodeGen/LiveIntervalAnalysis.h"
> -#include "llvm/CodeGen/MachineFunctionPass.h"
> +#include "llvm/CodeGen/MachineDominators.h"
>  #include "llvm/CodeGen/MachineInstrBuilder.h"
>  #include "llvm/CodeGen/MachineLoopInfo.h"
>  #include "llvm/CodeGen/MachineRegisterInfo.h"
> @@ -337,6 +337,218 @@
>  }
>
>  //===----------------------------------------------------------------------===//
> +//                               LiveIntervalMap
> +//===----------------------------------------------------------------------===//
> +
> +// defValue - Introduce a li_ def for ParentVNI that could be later than
> +// ParentVNI->def.
> +VNInfo *LiveIntervalMap::defValue(const VNInfo *ParentVNI, SlotIndex Idx) {
> +  assert(ParentVNI && "Mapping  NULL value");
> +  assert(Idx.isValid() && "Invalid SlotIndex");
> +  assert(parentli_.getVNInfoAt(Idx) == ParentVNI && "Bad ParentVNI");
> +
> +  // Is this a simple 1-1 mapping? Not likely.
> +  if (Idx == ParentVNI->def)
> +    return mapValue(ParentVNI, Idx);
> +
> +  // This is a complex def. Mark with a NULL in valueMap.
> +  VNInfo *OldVNI =
> +    valueMap_.insert(ValueMap::value_type(ParentVNI, 0)).first->second;

This produces an error in visual studio 2010.

1>  SplitKit.cpp
1>G:\Program Files (x86)\Microsoft Visual Studio
10.0\VC\include\utility(163): error C2440: 'initializing' : cannot
convert from 'int' to 'llvm::VNInfo *'
1>          Conversion from integral type to pointer type requires
reinterpret_cast, C-style cast or function-style cast
1>          G:\Program Files (x86)\Microsoft Visual Studio
10.0\VC\include\utility(247) : see reference to function template
instantiation 'std::_Pair_base<_Ty1,_Ty2>::_Pair_base<const
llvm::VNInfo*&,_Ty>(_Other1,_Other2 &&)' being compiled
1>          with
1>          [
1>              _Ty1=const llvm::VNInfo *,
1>              _Ty2=llvm::VNInfo *,
1>              _Ty=int,
1>              _Other1=const llvm::VNInfo *&,
1>              _Other2=int
1>          ]
1>          ..\..\..\..\llvm\lib\CodeGen\SplitKit.cpp(355) : see
reference to function template instantiation
'std::pair<_Ty1,_Ty2>::pair<const llvm::VNInfo*&,int>(_Other1,_Other2
&&)' being compiled
1>          with
1>          [
1>              _Ty1=const llvm::VNInfo *,
1>              _Ty2=llvm::VNInfo *,
1>              _Other1=const llvm::VNInfo *&,
1>              _Other2=int
1>          ]
1>G:\Program Files (x86)\Microsoft Visual Studio
10.0\VC\include\utility(163): error C2439:
'std::_Pair_base<_Ty1,_Ty2>::second' : member could not be initialized
1>          with
1>          [
1>              _Ty1=const llvm::VNInfo *,
1>              _Ty2=llvm::VNInfo *
1>          ]
1>          G:\Program Files (x86)\Microsoft Visual Studio
10.0\VC\include\utility(167) : see declaration of
'std::_Pair_base<_Ty1,_Ty2>::second'
1>          with
1>          [
1>              _Ty1=const llvm::VNInfo *,
1>              _Ty2=llvm::VNInfo *
1>          ]

The problem isn't obvious to me, but I think it's msvc's fault. I'm
looking into it, but would appreciate any help.

- Michael Spencer

> +  (void)OldVNI;
> +  assert(OldVNI == 0 && "Simple/Complex values mixed");
> +
> +  // Should we insert a minimal snippet of VNI LiveRange, or can we count on
> +  // callers to do that? We need it for lookups of complex values.
> +  VNInfo *VNI = li_.getNextValue(Idx, 0, true, lis_.getVNInfoAllocator());
> +  return VNI;
> +}
> +
> +// mapValue - Find the mapped value for ParentVNI at Idx.
> +// Potentially create phi-def values.
> +VNInfo *LiveIntervalMap::mapValue(const VNInfo *ParentVNI, SlotIndex Idx) {
> +  assert(ParentVNI && "Mapping  NULL value");
> +  assert(Idx.isValid() && "Invalid SlotIndex");
> +  assert(parentli_.getVNInfoAt(Idx) == ParentVNI && "Bad ParentVNI");
> +
> +  // Use insert for lookup, so we can add missing values with a second lookup.
> +  std::pair<ValueMap::iterator,bool> InsP =
> +    valueMap_.insert(ValueMap::value_type(ParentVNI, 0));
> +
> +  // This was an unknown value. Create a simple mapping.
> +  if (InsP.second)
> +    return InsP.first->second = li_.createValueCopy(ParentVNI,
> +                                                    lis_.getVNInfoAllocator());
> +  // This was a simple mapped value.
> +  if (InsP.first->second)
> +    return InsP.first->second;
> +
> +  // This is a complex mapped value. There may be multiple defs, and we may need
> +  // to create phi-defs.
> +  MachineBasicBlock *IdxMBB = lis_.getMBBFromIndex(Idx);
> +  assert(IdxMBB && "No MBB at Idx");
> +
> +  // Is there a def in the same MBB we can extend?
> +  if (VNInfo *VNI = extendTo(IdxMBB, Idx))
> +    return VNI;
> +
> +  // Now for the fun part. We know that ParentVNI potentially has multiple defs,
> +  // and we may need to create even more phi-defs to preserve VNInfo SSA form.
> +  // Perform a depth-first search for predecessor blocks where we know the
> +  // dominating VNInfo. Insert phi-def VNInfos along the path back to IdxMBB.
> +
> +  // Track MBBs where we have created or learned the dominating value.
> +  // This may change during the DFS as we create new phi-defs.
> +  typedef DenseMap<MachineBasicBlock*, VNInfo*> MBBValueMap;
> +  MBBValueMap DomValue;
> +
> +  for (idf_iterator<MachineBasicBlock*>
> +         IDFI = idf_begin(IdxMBB),
> +         IDFE = idf_end(IdxMBB); IDFI != IDFE;) {
> +    MachineBasicBlock *MBB = *IDFI;
> +    SlotIndex End = lis_.getMBBEndIdx(MBB);
> +
> +    // We are operating on the restricted CFG where ParentVNI is live.
> +    if (parentli_.getVNInfoAt(End.getPrevSlot()) != ParentVNI) {
> +      IDFI.skipChildren();
> +      continue;
> +    }
> +
> +    // Do we have a dominating value in this block?
> +    VNInfo *VNI = extendTo(MBB, End);
> +    if (!VNI) {
> +      ++IDFI;
> +      continue;
> +    }
> +
> +    // Yes, VNI dominates MBB. Track the path back to IdxMBB, creating phi-defs
> +    // as needed along the way.
> +    for (unsigned PI = IDFI.getPathLength()-1; PI != 0; --PI) {
> +      // Start from MBB's immediate successor.
> +      MachineBasicBlock *Succ = IDFI.getPath(PI-1);
> +      std::pair<MBBValueMap::iterator, bool> InsP =
> +        DomValue.insert(MBBValueMap::value_type(Succ, VNI));
> +      SlotIndex Start = lis_.getMBBStartIdx(Succ);
> +      if (InsP.second) {
> +        // This is the first time we backtrack to Succ. Verify dominance.
> +        if (Succ->pred_size() == 1 || dt_.dominates(MBB, Succ))
> +          continue;
> +      } else if (InsP.first->second == VNI ||
> +                 InsP.first->second->def == Start) {
> +        // We have previously backtracked VNI to Succ, or Succ already has a
> +        // phi-def. No need to backtrack further.
> +        break;
> +      }
> +      // VNI does not dominate Succ, we need a new phi-def.
> +      VNI = li_.getNextValue(Start, 0, true, lis_.getVNInfoAllocator());
> +      VNI->setIsPHIDef(true);
> +      InsP.first->second = VNI;
> +      MBB = Succ;
> +    }
> +
> +    // No need to search the children, we found a dominating value.
> +    // FIXME: We could prune up to the last phi-def we inserted, need df_iterator
> +    // for that.
> +    IDFI.skipChildren();
> +  }
> +
> +  // The search should at least find a dominating value for IdxMBB.
> +  assert(!DomValue.empty() && "Couldn't find a reaching definition");
> +
> +  // Since we went through the trouble of a full DFS visiting all reaching defs,
> +  // the values in DomValue are now accurate. No more phi-defs are needed for
> +  // these blocks, so we can color the live ranges.
> +  // This makes the next mapValue call much faster.
> +  VNInfo *IdxVNI = 0;
> +  for (MBBValueMap::iterator I = DomValue.begin(), E = DomValue.end(); I != E;
> +       ++I) {
> +     MachineBasicBlock *MBB = I->first;
> +     VNInfo *VNI = I->second;
> +     SlotIndex Start = lis_.getMBBStartIdx(MBB);
> +     if (MBB == IdxMBB) {
> +       // Don't add full liveness to IdxMBB, stop at Idx.
> +       if (Start != Idx)
> +         li_.addRange(LiveRange(Start, Idx, VNI));
> +       IdxVNI = VNI;
> +     } else
> +      li_.addRange(LiveRange(Start, lis_.getMBBEndIdx(MBB), VNI));
> +  }
> +
> +  assert(IdxVNI && "Didn't find value for Idx");
> +  return IdxVNI;
> +}
> +
> +// extendTo - Find the last li_ value defined in MBB at or before Idx. The
> +// parentli_ is assumed to be live at Idx. Extend the live range to Idx.
> +// Return the found VNInfo, or NULL.
> +VNInfo *LiveIntervalMap::extendTo(MachineBasicBlock *MBB, SlotIndex Idx) {
> +  LiveInterval::iterator I = std::upper_bound(li_.begin(), li_.end(), Idx);
> +  if (I == li_.begin())
> +    return 0;
> +  --I;
> +  if (I->start < lis_.getMBBStartIdx(MBB))
> +    return 0;
> +  if (I->end < Idx)
> +    I->end = Idx;
> +  return I->valno;
> +}
> +
> +// addSimpleRange - Add a simple range from parentli_ to li_.
> +// ParentVNI must be live in the [Start;End) interval.
> +void LiveIntervalMap::addSimpleRange(SlotIndex Start, SlotIndex End,
> +                                     const VNInfo *ParentVNI) {
> +  VNInfo *VNI = mapValue(ParentVNI, Start);
> +  // A simple mappoing is easy.
> +  if (VNI->def == ParentVNI->def) {
> +    li_.addRange(LiveRange(Start, End, VNI));
> +    return;
> +  }
> +
> +  // ParentVNI is a complex value. We must map per MBB.
> +  MachineFunction::iterator MBB = lis_.getMBBFromIndex(Start);
> +  MachineFunction::iterator MBBE = lis_.getMBBFromIndex(End);
> +
> +  if (MBB == MBBE) {
> +    li_.addRange(LiveRange(Start, End, VNI));
> +    return;
> +  }
> +
> +  // First block.
> +  li_.addRange(LiveRange(Start, lis_.getMBBEndIdx(MBB), VNI));
> +
> +  // Run sequence of full blocks.
> +  for (++MBB; MBB != MBBE; ++MBB) {
> +    Start = lis_.getMBBStartIdx(MBB);
> +    li_.addRange(LiveRange(Start, lis_.getMBBEndIdx(MBB),
> +                           mapValue(ParentVNI, Start)));
> +  }
> +
> +  // Final block.
> +  Start = lis_.getMBBStartIdx(MBB);
> +  if (Start != End)
> +    li_.addRange(LiveRange(Start, End, mapValue(ParentVNI, Start)));
> +}
> +
> +/// addRange - Add live ranges to li_ where [Start;End) intersects parentli_.
> +/// All needed values whose def is not inside [Start;End) must be defined
> +/// beforehand so mapValue will work.
> +void LiveIntervalMap::addRange(SlotIndex Start, SlotIndex End) {
> +  LiveInterval::const_iterator B = parentli_.begin(), E = parentli_.end();
> +  LiveInterval::const_iterator I = std::lower_bound(B, E, Start);
> +
> +  // Check if --I begins before Start and overlaps.
> +  if (I != B) {
> +    --I;
> +    if (I->end > Start)
> +      addSimpleRange(Start, std::min(End, I->end), I->valno);
> +    ++I;
> +  }
> +
> +  // The remaining ranges begin after Start.
> +  for (;I != E && I->start < End; ++I)
> +    addSimpleRange(I->start, std::min(End, I->end), I->valno);
> +}
> +
> +//===----------------------------------------------------------------------===//
>  //                               Split Editor
>  //===----------------------------------------------------------------------===//
>
>
> Modified: llvm/trunk/lib/CodeGen/SplitKit.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SplitKit.h?rev=111393&r1=111392&r2=111393&view=diff
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/SplitKit.h (original)
> +++ llvm/trunk/lib/CodeGen/SplitKit.h Wed Aug 18 14:00:08 2010
> @@ -20,6 +20,7 @@
>
>  class LiveInterval;
>  class LiveIntervals;
> +class MachineDominatorTree;
>  class MachineInstr;
>  class MachineLoop;
>  class MachineLoopInfo;
> @@ -135,6 +136,71 @@
>   const MachineBasicBlock *getBlockForInsideSplit();
>  };
>
> +
> +/// LiveIntervalMap - Map values from a large LiveInterval into a small
> +/// interval that is a subset. Insert phi-def values as needed. This class is
> +/// used by SplitEditor to create new smaller LiveIntervals.
> +///
> +/// parentli_ is the larger interval, li_ is the subset interval. Every value
> +/// in li_ corresponds to exactly one value in parentli_, and the live range
> +/// of the value is contained within the live range of the parentli_ value.
> +/// Values in parentli_ may map to any number of openli_ values, including 0.
> +class LiveIntervalMap {
> +  LiveIntervals &lis_;
> +  MachineDominatorTree &dt_;
> +
> +  // The parent interval is never changed.
> +  const LiveInterval &parentli_;
> +
> +  // The child interval's values are fully contained inside parentli_ values.
> +  LiveInterval &li_;
> +
> +  typedef DenseMap<const VNInfo*, VNInfo*> ValueMap;
> +
> +  // Map parentli_ values to simple values in li_ that are defined at the same
> +  // SlotIndex, or NULL for parentli_ values that have complex li_ defs.
> +  // Note there is a difference between values mapping to NULL (complex), and
> +  // values not present (unknown/unmapped).
> +  ValueMap valueMap_;
> +
> +  // extendTo - Find the last li_ value defined in MBB at or before Idx. The
> +  // parentli_ is assumed to be live at Idx. Extend the live range to Idx.
> +  // Return the found VNInfo, or NULL.
> +  VNInfo *extendTo(MachineBasicBlock *MBB, SlotIndex Idx);
> +
> +  // addSimpleRange - Add a simple range from parentli_ to li_.
> +  // ParentVNI must be live in the [Start;End) interval.
> +  void addSimpleRange(SlotIndex Start, SlotIndex End, const VNInfo *ParentVNI);
> +
> +public:
> +  LiveIntervalMap(LiveIntervals &lis,
> +                  MachineDominatorTree &dt,
> +                  const LiveInterval &parentli,
> +                  LiveInterval &li)
> +    : lis_(lis), dt_(dt), parentli_(parentli), li_(li) {}
> +
> +  /// defValue - define a value in li_ from the parentli_ value VNI and Idx.
> +  /// Idx does not have to be ParentVNI->def, but it must be contained within
> +  /// ParentVNI's live range in parentli_.
> +  /// Return the new li_ value.
> +  VNInfo *defValue(const VNInfo *ParentVNI, SlotIndex Idx);
> +
> +  /// mapValue - map ParentVNI to the corresponding li_ value at Idx. It is
> +  /// assumed that ParentVNI is live at Idx.
> +  /// If ParentVNI has not been defined by defValue, it is assumed that
> +  /// ParentVNI->def dominates Idx.
> +  /// If ParentVNI has been defined by defValue one or more times, a value that
> +  /// dominates Idx will be returned. This may require creating extra phi-def
> +  /// values and adding live ranges to li_.
> +  VNInfo *mapValue(const VNInfo *ParentVNI, SlotIndex Idx);
> +
> +  /// addRange - Add live ranges to li_ where [Start;End) intersects parentli_.
> +  /// All needed values whose def is not inside [Start;End) must be defined
> +  /// beforehand so mapValue will work.
> +  void addRange(SlotIndex Start, SlotIndex End);
> +};
> +
> +
>  /// SplitEditor - Edit machine code and LiveIntervals for live range
>  /// splitting.
>  ///
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>




More information about the llvm-commits mailing list