summaryrefslogtreecommitdiff
path: root/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp
diff options
context:
space:
mode:
authorAndrew Trick <atrick@apple.com>2011-04-07 19:54:57 +0000
committerAndrew Trick <atrick@apple.com>2011-04-07 19:54:57 +0000
commit54699765064842fd08d1466adc93453660bc2a85 (patch)
tree7b7dd1f577848063e5f0a0beb05f633edbe7705e /lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp
parent9777e7afd4a9a348f043e914192d491b620659f1 (diff)
downloadllvm-54699765064842fd08d1466adc93453660bc2a85.tar.gz
llvm-54699765064842fd08d1466adc93453660bc2a85.tar.bz2
llvm-54699765064842fd08d1466adc93453660bc2a85.tar.xz
Added a check in the preRA scheduler for potential interference on a
induction variable. The preRA scheduler is unaware of induction vars, so we look for potential "virtual register cycles" instead. Fixes <rdar://problem/8946719> Bad scheduling prevents coalescing git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@129100 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp')
-rw-r--r--lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp46
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()) {