}
SUnit *ScheduleDAG::Clone(SUnit *Old) {
- SUnit *SU = NewSUnit(Old->Node);
+ SUnit *SU = NewSUnit(Old->getNode());
SU->OrigNode = Old->OrigNode;
- SU->FlaggedNodes = Old->FlaggedNodes;
SU->Latency = Old->Latency;
SU->isTwoAddress = Old->isTwoAddress;
SU->isCommutable = Old->isCommutable;
/// This SUnit graph is similar to the SelectionDAG, but represents flagged
/// together nodes with a single SUnit.
void ScheduleDAG::BuildSchedUnits() {
+ // For post-regalloc scheduling, build the SUnits from the MachineInstrs
+ // in the MachineBasicBlock.
+ if (!DAG) {
+ BuildSchedUnitsFromMBB();
+ return;
+ }
+
// Reserve entries in the vector for each of the SUnits we are creating. This
// ensure that reallocation of the vector won't happen, so SUnit*'s won't get
// invalidated.
// nodes. Nodes can have at most one flag input and one flag output. Flags
// are required the be the last operand and result of a node.
- // Scan up, adding flagged preds to FlaggedNodes.
+ // Scan up to find flagged preds.
SDNode *N = NI;
if (N->getNumOperands() &&
N->getOperand(N->getNumOperands()-1).getValueType() == MVT::Flag) {
do {
N = N->getOperand(N->getNumOperands()-1).getNode();
- NodeSUnit->FlaggedNodes.push_back(N);
assert(N->getNodeId() == -1 && "Node already inserted!");
N->setNodeId(NodeSUnit->NodeNum);
} while (N->getNumOperands() &&
N->getOperand(N->getNumOperands()-1).getValueType()== MVT::Flag);
- std::reverse(NodeSUnit->FlaggedNodes.begin(),
- NodeSUnit->FlaggedNodes.end());
}
- // Scan down, adding this node and any flagged succs to FlaggedNodes if they
- // have a user of the flag operand.
+ // Scan down to find any flagged succs.
N = NI;
while (N->getValueType(N->getNumValues()-1) == MVT::Flag) {
SDValue FlagVal(N, N->getNumValues()-1);
UI != E; ++UI)
if (FlagVal.isOperandOf(*UI)) {
HasFlagUse = true;
- NodeSUnit->FlaggedNodes.push_back(N);
assert(N->getNodeId() == -1 && "Node already inserted!");
N->setNodeId(NodeSUnit->NodeNum);
N = *UI;
if (!HasFlagUse) break;
}
- // Now all flagged nodes are in FlaggedNodes and N is the bottom-most node.
- // Update the SUnit
- NodeSUnit->Node = N;
+ // If there are flag operands involved, N is now the bottom-most node
+ // of the sequence of nodes that are flagged together.
+ // Update the SUnit.
+ NodeSUnit->setNode(N);
assert(N->getNodeId() == -1 && "Node already inserted!");
N->setNodeId(NodeSUnit->NodeNum);
// Pass 2: add the preds, succs, etc.
for (unsigned su = 0, e = SUnits.size(); su != e; ++su) {
SUnit *SU = &SUnits[su];
- SDNode *MainNode = SU->Node;
+ SDNode *MainNode = SU->getNode();
if (MainNode->isMachineOpcode()) {
unsigned Opc = MainNode->getMachineOpcode();
}
// Find all predecessors and successors of the group.
- // Temporarily add N to make code simpler.
- SU->FlaggedNodes.push_back(MainNode);
-
- for (unsigned n = 0, e = SU->FlaggedNodes.size(); n != e; ++n) {
- SDNode *N = SU->FlaggedNodes[n];
+ for (SDNode *N = SU->getNode(); N; N = N->getFlaggedNode()) {
if (N->isMachineOpcode() &&
TII->get(N->getMachineOpcode()).getImplicitDefs() &&
CountResults(N) > TII->get(N->getMachineOpcode()).getNumDefs())
SU->addPred(OpSU, isChain, false, PhysReg, Cost);
}
}
-
- // Remove MainNode from FlaggedNodes again.
- SU->FlaggedNodes.pop_back();
+ }
+}
+
+void ScheduleDAG::BuildSchedUnitsFromMBB() {
+ SUnits.clear();
+ SUnits.reserve(BB->size());
+
+ std::vector<SUnit *> PendingLoads;
+ SUnit *Terminator = 0;
+ SUnit *Chain = 0;
+ SUnit *Defs[TargetRegisterInfo::FirstVirtualRegister] = {};
+ std::vector<SUnit *> Uses[TargetRegisterInfo::FirstVirtualRegister] = {};
+ int Cost = 1; // FIXME
+
+ for (MachineBasicBlock::iterator MII = BB->end(), MIE = BB->begin();
+ MII != MIE; --MII) {
+ MachineInstr *MI = prior(MII);
+ SUnit *SU = NewSUnit(MI);
+
+ for (unsigned j = 0, n = MI->getNumOperands(); j != n; ++j) {
+ const MachineOperand &MO = MI->getOperand(j);
+ if (!MO.isReg()) continue;
+ unsigned Reg = MO.getReg();
+ if (Reg == 0) continue;
+
+ assert(TRI->isPhysicalRegister(Reg) && "Virtual register encountered!");
+ std::vector<SUnit *> &UseList = Uses[Reg];
+ SUnit *&Def = Defs[Reg];
+ // Optionally add output and anti dependences
+ if (Def && Def != SU)
+ Def->addPred(SU, /*isCtrl=*/true, /*isSpecial=*/false,
+ /*PhyReg=*/Reg, Cost);
+ for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) {
+ SUnit *&Def = Defs[*Alias];
+ if (Def && Def != SU)
+ Def->addPred(SU, /*isCtrl=*/true, /*isSpecial=*/false,
+ /*PhyReg=*/*Alias, Cost);
+ }
+
+ if (MO.isDef()) {
+ // Add any data dependencies.
+ for (unsigned i = 0, e = UseList.size(); i != e; ++i)
+ if (UseList[i] != SU)
+ UseList[i]->addPred(SU, /*isCtrl=*/false, /*isSpecial=*/false,
+ /*PhysReg=*/Reg, Cost);
+ for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) {
+ std::vector<SUnit *> &UseList = Uses[*Alias];
+ for (unsigned i = 0, e = UseList.size(); i != e; ++i)
+ if (UseList[i] != SU)
+ UseList[i]->addPred(SU, /*isCtrl=*/false, /*isSpecial=*/false,
+ /*PhysReg=*/*Alias, Cost);
+ }
+
+ UseList.clear();
+ Def = SU;
+ } else {
+ UseList.push_back(SU);
+ }
+ }
+ bool False = false;
+ bool True = true;
+ if (!MI->isSafeToMove(TII, False)) {
+ if (Chain)
+ Chain->addPred(SU, /*isCtrl=*/false, /*isSpecial=*/false);
+ for (unsigned k = 0, m = PendingLoads.size(); k != m; ++k)
+ PendingLoads[k]->addPred(SU, /*isCtrl=*/false, /*isSpecial=*/false);
+ PendingLoads.clear();
+ Chain = SU;
+ } else if (!MI->isSafeToMove(TII, True)) {
+ if (Chain)
+ Chain->addPred(SU, /*isCtrl=*/false, /*isSpecial=*/false);
+ PendingLoads.push_back(SU);
+ }
+ if (Terminator && SU->Succs.empty())
+ Terminator->addPred(SU, /*isCtrl=*/false, /*isSpecial=*/false);
+ if (MI->getDesc().isTerminator())
+ Terminator = SU;
}
}
}
SU->Latency = 0;
- if (SU->Node->isMachineOpcode()) {
- unsigned SchedClass = TII->get(SU->Node->getMachineOpcode()).getSchedClass();
- const InstrStage *S = InstrItins.begin(SchedClass);
- const InstrStage *E = InstrItins.end(SchedClass);
- for (; S != E; ++S)
- SU->Latency += S->Cycles;
- }
- for (unsigned i = 0, e = SU->FlaggedNodes.size(); i != e; ++i) {
- SDNode *FNode = SU->FlaggedNodes[i];
- if (FNode->isMachineOpcode()) {
- unsigned SchedClass = TII->get(FNode->getMachineOpcode()).getSchedClass();
+ for (SDNode *N = SU->getNode(); N; N = N->getFlaggedNode()) {
+ if (N->isMachineOpcode()) {
+ unsigned SchedClass = TII->get(N->getMachineOpcode()).getSchedClass();
const InstrStage *S = InstrItins.begin(SchedClass);
const InstrStage *E = InstrItins.end(SchedClass);
for (; S != E; ++S)
void ScheduleDAG::dumpSchedule() const {
for (unsigned i = 0, e = Sequence.size(); i != e; i++) {
if (SUnit *SU = Sequence[i])
- SU->dump(DAG);
+ SU->dump(this);
else
cerr << "**** NOOP ****\n";
}
/// SUnit - Scheduling unit. It's an wrapper around either a single SDNode or
/// a group of nodes flagged together.
-void SUnit::dump(const SelectionDAG *G) const {
+void SUnit::dump(const ScheduleDAG *G) const {
cerr << "SU(" << NodeNum << "): ";
- if (Node)
- Node->dump(G);
+ if (getNode())
+ getNode()->dump(G->DAG);
else
cerr << "CROSS RC COPY ";
cerr << "\n";
- if (FlaggedNodes.size() != 0) {
- for (unsigned i = 0, e = FlaggedNodes.size(); i != e; i++) {
- cerr << " ";
- FlaggedNodes[i]->dump(G);
- cerr << "\n";
- }
+ SmallVector<SDNode *, 4> FlaggedNodes;
+ for (SDNode *N = getNode()->getFlaggedNode(); N; N = N->getFlaggedNode())
+ FlaggedNodes.push_back(N);
+ while (!FlaggedNodes.empty()) {
+ cerr << " ";
+ FlaggedNodes.back()->dump(G->DAG);
+ cerr << "\n";
+ FlaggedNodes.pop_back();
}
}
-void SUnit::dumpAll(const SelectionDAG *G) const {
+void SUnit::dumpAll(const ScheduleDAG *G) const {
dump(G);
cerr << " # preds left : " << NumPredsLeft << "\n";