blob: 06d8ed9b25d0a89330dffd1c3b7f9cc7e0ce055b [file] [log] [blame]
Dan Gohman343f0c02008-11-19 23:18:57 +00001//===---- ScheduleDAG.cpp - Implement the ScheduleDAG class ---------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This implements the ScheduleDAG class, which is a base class used by
11// scheduling implementation classes.
12//
13//===----------------------------------------------------------------------===//
14
15#define DEBUG_TYPE "sched-instrs"
16#include "llvm/CodeGen/ScheduleDAGInstrs.h"
17#include "llvm/Target/TargetMachine.h"
18#include "llvm/Target/TargetInstrInfo.h"
19#include "llvm/Target/TargetRegisterInfo.h"
20#include "llvm/Support/Debug.h"
21#include "llvm/Support/raw_ostream.h"
22using namespace llvm;
23
24ScheduleDAGInstrs::ScheduleDAGInstrs(MachineBasicBlock *bb,
25 const TargetMachine &tm)
26 : ScheduleDAG(0, bb, tm) {}
27
28void ScheduleDAGInstrs::BuildSchedUnits() {
29 SUnits.clear();
30 SUnits.reserve(BB->size());
31
32 std::vector<SUnit *> PendingLoads;
33 SUnit *Terminator = 0;
34 SUnit *Chain = 0;
35 SUnit *Defs[TargetRegisterInfo::FirstVirtualRegister] = {};
36 std::vector<SUnit *> Uses[TargetRegisterInfo::FirstVirtualRegister] = {};
37 int Cost = 1; // FIXME
38
39 for (MachineBasicBlock::iterator MII = BB->end(), MIE = BB->begin();
40 MII != MIE; --MII) {
41 MachineInstr *MI = prior(MII);
42 SUnit *SU = NewSUnit(MI);
43
44 for (unsigned j = 0, n = MI->getNumOperands(); j != n; ++j) {
45 const MachineOperand &MO = MI->getOperand(j);
46 if (!MO.isReg()) continue;
47 unsigned Reg = MO.getReg();
48 if (Reg == 0) continue;
49
50 assert(TRI->isPhysicalRegister(Reg) && "Virtual register encountered!");
51 std::vector<SUnit *> &UseList = Uses[Reg];
52 SUnit *&Def = Defs[Reg];
Dan Gohmanc8c28272008-11-21 00:12:10 +000053 // Optionally add output and anti dependences.
Dan Gohman343f0c02008-11-19 23:18:57 +000054 if (Def && Def != SU)
55 Def->addPred(SU, /*isCtrl=*/true, /*isSpecial=*/false,
56 /*PhyReg=*/Reg, Cost);
57 for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) {
58 SUnit *&Def = Defs[*Alias];
59 if (Def && Def != SU)
60 Def->addPred(SU, /*isCtrl=*/true, /*isSpecial=*/false,
61 /*PhyReg=*/*Alias, Cost);
62 }
63
64 if (MO.isDef()) {
65 // Add any data dependencies.
66 for (unsigned i = 0, e = UseList.size(); i != e; ++i)
67 if (UseList[i] != SU)
68 UseList[i]->addPred(SU, /*isCtrl=*/false, /*isSpecial=*/false,
69 /*PhysReg=*/Reg, Cost);
70 for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) {
71 std::vector<SUnit *> &UseList = Uses[*Alias];
72 for (unsigned i = 0, e = UseList.size(); i != e; ++i)
73 if (UseList[i] != SU)
74 UseList[i]->addPred(SU, /*isCtrl=*/false, /*isSpecial=*/false,
75 /*PhysReg=*/*Alias, Cost);
76 }
77
78 UseList.clear();
79 Def = SU;
80 } else {
81 UseList.push_back(SU);
82 }
83 }
84 bool False = false;
85 bool True = true;
86 if (!MI->isSafeToMove(TII, False)) {
87 if (Chain)
88 Chain->addPred(SU, /*isCtrl=*/false, /*isSpecial=*/false);
89 for (unsigned k = 0, m = PendingLoads.size(); k != m; ++k)
90 PendingLoads[k]->addPred(SU, /*isCtrl=*/false, /*isSpecial=*/false);
91 PendingLoads.clear();
92 Chain = SU;
93 } else if (!MI->isSafeToMove(TII, True)) {
94 if (Chain)
95 Chain->addPred(SU, /*isCtrl=*/false, /*isSpecial=*/false);
96 PendingLoads.push_back(SU);
97 }
98 if (Terminator && SU->Succs.empty())
99 Terminator->addPred(SU, /*isCtrl=*/false, /*isSpecial=*/false);
Dan Gohman8eaf41d2008-11-20 19:58:35 +0000100 if (MI->getDesc().isTerminator() || MI->isLabel())
Dan Gohman343f0c02008-11-19 23:18:57 +0000101 Terminator = SU;
102 }
103}
104
Dan Gohmanc8c28272008-11-21 00:12:10 +0000105void ScheduleDAGInstrs::ComputeLatency(SUnit *SU) {
106 const InstrItineraryData &InstrItins = TM.getInstrItineraryData();
107
108 // Compute the latency for the node. We use the sum of the latencies for
109 // all nodes flagged together into this SUnit.
110 SU->Latency =
111 InstrItins.getLatency(SU->getInstr()->getDesc().getSchedClass());
112}
113
Dan Gohman343f0c02008-11-19 23:18:57 +0000114void ScheduleDAGInstrs::dumpNode(const SUnit *SU) const {
115 SU->getInstr()->dump();
116}
117
118std::string ScheduleDAGInstrs::getGraphNodeLabel(const SUnit *SU) const {
119 std::string s;
120 raw_string_ostream oss(s);
121 SU->getInstr()->print(oss);
122 return oss.str();
123}
124
125// EmitSchedule - Emit the machine code in scheduled order.
126MachineBasicBlock *ScheduleDAGInstrs::EmitSchedule() {
127 // For MachineInstr-based scheduling, we're rescheduling the instructions in
128 // the block, so start by removing them from the block.
129 while (!BB->empty())
130 BB->remove(BB->begin());
131
132 for (unsigned i = 0, e = Sequence.size(); i != e; i++) {
133 SUnit *SU = Sequence[i];
134 if (!SU) {
135 // Null SUnit* is a noop.
136 EmitNoop();
137 continue;
138 }
139
140 BB->push_back(SU->getInstr());
141 }
142
143 return BB;
144}