[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