[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