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

Michael Spencer bigcheesegs at gmail.com
Thu Aug 19 09:02:11 PDT 2010


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
>>
>




More information about the llvm-commits mailing list