-
-void ScheduleDAGList::BuildSchedUnits() {
- // 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.
- SUnits.reserve(NodeCount);
-
- const InstrItineraryData &InstrItins = TM.getInstrItineraryData();
-
- // Pass 1: create the SUnit's.
- for (unsigned i = 0, NC = NodeCount; i < NC; i++) {
- NodeInfo *NI = &Info[i];
- SDNode *N = NI->Node;
- if (isPassiveNode(N))
- continue;
-
- SUnit *SU;
- if (NI->isInGroup()) {
- if (NI != NI->Group->getBottom()) // Bottom up, so only look at bottom
- continue; // node of the NodeGroup
-
- SU = NewSUnit(N);
- // Find the flagged nodes.
- SDOperand FlagOp = N->getOperand(N->getNumOperands() - 1);
- SDNode *Flag = FlagOp.Val;
- unsigned ResNo = FlagOp.ResNo;
- while (Flag->getValueType(ResNo) == MVT::Flag) {
- NodeInfo *FNI = getNI(Flag);
- assert(FNI->Group == NI->Group);
- SU->FlaggedNodes.insert(SU->FlaggedNodes.begin(), Flag);
- SUnitMap[Flag] = SU;
-
- FlagOp = Flag->getOperand(Flag->getNumOperands() - 1);
- Flag = FlagOp.Val;
- ResNo = FlagOp.ResNo;
- }
- } else {
- SU = NewSUnit(N);
- }
- SUnitMap[N] = SU;
-
- // Compute the latency for the node. We use the sum of the latencies for
- // all nodes flagged together into this SUnit.
- if (InstrItins.isEmpty() || !UseLatencies) {
- // No latency information.
- SU->Latency = 1;
- } else {
- SU->Latency = 0;
- if (N->isTargetOpcode()) {
- unsigned SchedClass = TII->getSchedClass(N->getTargetOpcode());
- InstrStage *S = InstrItins.begin(SchedClass);
- 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->isTargetOpcode()) {
- unsigned SchedClass = TII->getSchedClass(FNode->getTargetOpcode());
- InstrStage *S = InstrItins.begin(SchedClass);
- InstrStage *E = InstrItins.end(SchedClass);
- for (; S != E; ++S)
- SU->Latency += S->Cycles;
- }
- }
- }
- }
-
- // Pass 2: add the preds, succs, etc.
- for (unsigned i = 0, e = SUnits.size(); i != e; ++i) {
- SUnit *SU = &SUnits[i];
- SDNode *N = SU->Node;
- NodeInfo *NI = getNI(N);
-
- if (N->isTargetOpcode() && TII->isTwoAddrInstr(N->getTargetOpcode()))
- SU->isTwoAddress = true;
-
- if (NI->isInGroup()) {
- // Find all predecessors (of the group).
- NodeGroupOpIterator NGOI(NI);
- while (!NGOI.isEnd()) {
- SDOperand Op = NGOI.next();
- SDNode *OpN = Op.Val;
- MVT::ValueType VT = OpN->getValueType(Op.ResNo);
- NodeInfo *OpNI = getNI(OpN);
- if (OpNI->Group != NI->Group && !isPassiveNode(OpN)) {
- assert(VT != MVT::Flag);
- SUnit *OpSU = SUnitMap[OpN];
- if (VT == MVT::Other) {
- if (SU->ChainPreds.insert(OpSU).second)
- SU->NumChainPredsLeft++;
- if (OpSU->ChainSuccs.insert(SU).second)
- OpSU->NumChainSuccsLeft++;
- } else {
- if (SU->Preds.insert(OpSU).second)
- SU->NumPredsLeft++;
- if (OpSU->Succs.insert(SU).second)
- OpSU->NumSuccsLeft++;
- }
- }
- }
- } else {
- // Find node predecessors.
- for (unsigned j = 0, e = N->getNumOperands(); j != e; j++) {
- SDOperand Op = N->getOperand(j);
- SDNode *OpN = Op.Val;
- MVT::ValueType VT = OpN->getValueType(Op.ResNo);
- if (!isPassiveNode(OpN)) {
- assert(VT != MVT::Flag);
- SUnit *OpSU = SUnitMap[OpN];
- if (VT == MVT::Other) {
- if (SU->ChainPreds.insert(OpSU).second)
- SU->NumChainPredsLeft++;
- if (OpSU->ChainSuccs.insert(SU).second)
- OpSU->NumChainSuccsLeft++;
- } else {
- if (SU->Preds.insert(OpSU).second)
- SU->NumPredsLeft++;
- if (OpSU->Succs.insert(SU).second)
- OpSU->NumSuccsLeft++;
- if (j == 0 && SU->isTwoAddress)
- OpSU->isDefNUseOperand = true;
- }
- }
- }
- }
-
- DEBUG(SU->dumpAll(&DAG));
- }
-}
-
-/// EmitSchedule - Emit the machine code in scheduled order.
-void ScheduleDAGList::EmitSchedule() {
- for (unsigned i = 0, e = Sequence.size(); i != e; i++) {
- if (SUnit *SU = Sequence[i]) {
- for (unsigned j = 0, ee = SU->FlaggedNodes.size(); j != ee; j++) {
- SDNode *N = SU->FlaggedNodes[j];
- EmitNode(getNI(N));
- }
- EmitNode(getNI(SU->Node));
- } else {
- // Null SUnit* is a noop.
- EmitNoop();
- }
- }
-}
-
-/// dump - dump the schedule.
-void ScheduleDAGList::dumpSchedule() const {
- for (unsigned i = 0, e = Sequence.size(); i != e; i++) {
- if (SUnit *SU = Sequence[i])
- SU->dump(&DAG);
- else
- std::cerr << "**** NOOP ****\n";
- }
-}
-
-/// Schedule - Schedule the DAG using list scheduling.
-/// FIXME: Right now it only supports the burr (bottom up register reducing)
-/// heuristic.
-void ScheduleDAGList::Schedule() {
- DEBUG(std::cerr << "********** List Scheduling **********\n");
-
- // Build scheduling units.
- BuildSchedUnits();
-
- PriorityQueue->initNodes(SUnits);
-
- // Execute the actual scheduling loop Top-Down or Bottom-Up as appropriate.
- if (isBottomUp)
- ListScheduleBottomUp();
- else
- ListScheduleTopDown();
-
- PriorityQueue->releaseState();
-
- DEBUG(std::cerr << "*** Final schedule ***\n");
- DEBUG(dumpSchedule());
- DEBUG(std::cerr << "\n");
-
- // Emit in scheduled order
- EmitSchedule();
-}
-