diff options
Diffstat (limited to 'lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp')
-rw-r--r-- | lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp b/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp index 202f7ab4e1..24a1937c44 100644 --- a/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp +++ b/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp @@ -81,6 +81,7 @@ SUnit *ScheduleDAGSDNodes::Clone(SUnit *Old) { SUnit *SU = NewSUnit(Old->getNode()); SU->OrigNode = Old->OrigNode; SU->Latency = Old->Latency; + SU->isVRegCycle = Old->isVRegCycle; SU->isCall = Old->isCall; SU->isTwoAddress = Old->isTwoAddress; SU->isCommutable = Old->isCommutable; @@ -341,6 +342,10 @@ void ScheduleDAGSDNodes::BuildSchedUnits() { assert(N->getNodeId() == -1 && "Node already inserted!"); N->setNodeId(NodeSUnit->NodeNum); + // Set isVRegCycle if the node operands are live into and value is live out + // of a single block loop. + InitVRegCycleFlag(NodeSUnit); + // Compute NumRegDefsLeft. This must be done before AddSchedEdges. InitNumRegDefsLeft(NodeSUnit); @@ -507,6 +512,47 @@ void ScheduleDAGSDNodes::RegDefIter::Advance() { } } +// Set isVRegCycle if this node's single use is CopyToReg and its only active +// data operands are CopyFromReg. +// +// This is only relevant for single-block loops, in which case the VRegCycle +// node is likely an induction variable in which the operand and target virtual +// registers should be coalesced (e.g. pre/post increment values). Setting the +// isVRegCycle flag helps the scheduler prioritize other uses of the same +// CopyFromReg so that this node becomes the virtual register "kill". This +// avoids interference between the values live in and out of the block and +// eliminates a copy inside the loop. +void ScheduleDAGSDNodes::InitVRegCycleFlag(SUnit *SU) { + if (!BB->isSuccessor(BB)) + return; + + SDNode *N = SU->getNode(); + if (N->getGluedNode()) + return; + + if (!N->hasOneUse() || N->use_begin()->getOpcode() != ISD::CopyToReg) + return; + + bool FoundLiveIn = false; + for (SDNode::op_iterator OI = N->op_begin(), E = N->op_end(); OI != E; ++OI) { + EVT OpVT = OI->getValueType(); + assert(OpVT != MVT::Glue && "Glued nodes should be in same sunit!"); + + if (OpVT == MVT::Other) + continue; // ignore chain operands + + if (isPassiveNode(OI->getNode())) + continue; // ignore constants and such + + if (OI->getNode()->getOpcode() != ISD::CopyFromReg) + return; + + FoundLiveIn = true; + } + if (FoundLiveIn) + SU->isVRegCycle = true; +} + void ScheduleDAGSDNodes::InitNumRegDefsLeft(SUnit *SU) { assert(SU->NumRegDefsLeft == 0 && "expect a new node"); for (RegDefIter I(SU, this); I.IsValid(); I.Advance()) { |