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

Bob Wilson bob.wilson at apple.com
Thu Aug 19 09:15:05 PDT 2010


Yes, please commit that change.  (Jakob is on vacation.)

On Aug 19, 2010, at 9:02 AM, Michael Spencer wrote:

> On Thu, Aug 19, 2010 at 10:10 AM, Michael Spencer <bigcheesegs at gmail.com> wrote:
>> 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
> 
> Apparently this is a known problem with msvc 2010 because it
> implements a buggy version of C++0x. The problem has been fixed in
> C++0x, but not in msvc yet.
> 
> The workaround is:
> 
> @@ -352,7 +352,7 @@ VNInfo *LiveIntervalMap::defValue(const VNInfo
> *ParentVNI, SlotIndex Idx) {
> 
>   // This is a complex def. Mark with a NULL in valueMap.
>   VNInfo *OldVNI =
> -    valueMap_.insert(ValueMap::value_type(ParentVNI, 0)).first->second;
> +    valueMap_.insert(ValueMap::value_type(ParentVNI,
> static_cast<VNInfo *>(0))).first->second;
>   (void)OldVNI;
>   assert(OldVNI == 0 && "Simple/Complex values mixed");
> 
> @@ -371,7 +371,7 @@ VNInfo *LiveIntervalMap::mapValue(const VNInfo
> *ParentVNI, SlotIndex Idx) {
> 
>   // 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));
> +    valueMap_.insert(ValueMap::value_type(ParentVNI,
> static_cast<VNInfo *>(0)));
> 
>   // This was an unknown value. Create a simple mapping.
>   if (InsP.second)
> 
> With this change all of llvm + clang compiles and works with msvc
> 2010. Is it ok to commit?
> 
> - 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
>>> 
>> 
> 
> _______________________________________________
> 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