1 | //===--- ScheduleDAGSDNodes.cpp - Implement the ScheduleDAGSDNodes 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 "pre-RA-sched"
|
---|
16 | #include "SDNodeDbgValue.h"
|
---|
17 | #include "ScheduleDAGSDNodes.h"
|
---|
18 | #include "InstrEmitter.h"
|
---|
19 | #include "llvm/CodeGen/SelectionDAG.h"
|
---|
20 | #include "llvm/Target/TargetMachine.h"
|
---|
21 | #include "llvm/Target/TargetInstrInfo.h"
|
---|
22 | #include "llvm/Target/TargetLowering.h"
|
---|
23 | #include "llvm/Target/TargetRegisterInfo.h"
|
---|
24 | #include "llvm/Target/TargetSubtarget.h"
|
---|
25 | #include "llvm/ADT/DenseMap.h"
|
---|
26 | #include "llvm/ADT/SmallPtrSet.h"
|
---|
27 | #include "llvm/ADT/SmallSet.h"
|
---|
28 | #include "llvm/ADT/SmallVector.h"
|
---|
29 | #include "llvm/ADT/Statistic.h"
|
---|
30 | #include "llvm/Support/Debug.h"
|
---|
31 | #include "llvm/Support/raw_ostream.h"
|
---|
32 | using namespace llvm;
|
---|
33 |
|
---|
34 | STATISTIC(LoadsClustered, "Number of loads clustered together");
|
---|
35 |
|
---|
36 | ScheduleDAGSDNodes::ScheduleDAGSDNodes(MachineFunction &mf)
|
---|
37 | : ScheduleDAG(mf) {
|
---|
38 | }
|
---|
39 |
|
---|
40 | /// Run - perform scheduling.
|
---|
41 | ///
|
---|
42 | void ScheduleDAGSDNodes::Run(SelectionDAG *dag, MachineBasicBlock *bb,
|
---|
43 | MachineBasicBlock::iterator insertPos) {
|
---|
44 | DAG = dag;
|
---|
45 | ScheduleDAG::Run(bb, insertPos);
|
---|
46 | }
|
---|
47 |
|
---|
48 | /// NewSUnit - Creates a new SUnit and return a ptr to it.
|
---|
49 | ///
|
---|
50 | SUnit *ScheduleDAGSDNodes::NewSUnit(SDNode *N) {
|
---|
51 | #ifndef NDEBUG
|
---|
52 | const SUnit *Addr = 0;
|
---|
53 | if (!SUnits.empty())
|
---|
54 | Addr = &SUnits[0];
|
---|
55 | #endif
|
---|
56 | SUnits.push_back(SUnit(N, (unsigned)SUnits.size()));
|
---|
57 | assert((Addr == 0 || Addr == &SUnits[0]) &&
|
---|
58 | "SUnits std::vector reallocated on the fly!");
|
---|
59 | SUnits.back().OrigNode = &SUnits.back();
|
---|
60 | SUnit *SU = &SUnits.back();
|
---|
61 | const TargetLowering &TLI = DAG->getTargetLoweringInfo();
|
---|
62 | if (!N ||
|
---|
63 | (N->isMachineOpcode() &&
|
---|
64 | N->getMachineOpcode() == TargetOpcode::IMPLICIT_DEF))
|
---|
65 | SU->SchedulingPref = Sched::None;
|
---|
66 | else
|
---|
67 | SU->SchedulingPref = TLI.getSchedulingPreference(N);
|
---|
68 | return SU;
|
---|
69 | }
|
---|
70 |
|
---|
71 | SUnit *ScheduleDAGSDNodes::Clone(SUnit *Old) {
|
---|
72 | SUnit *SU = NewSUnit(Old->getNode());
|
---|
73 | SU->OrigNode = Old->OrigNode;
|
---|
74 | SU->Latency = Old->Latency;
|
---|
75 | SU->isTwoAddress = Old->isTwoAddress;
|
---|
76 | SU->isCommutable = Old->isCommutable;
|
---|
77 | SU->hasPhysRegDefs = Old->hasPhysRegDefs;
|
---|
78 | SU->hasPhysRegClobbers = Old->hasPhysRegClobbers;
|
---|
79 | SU->SchedulingPref = Old->SchedulingPref;
|
---|
80 | Old->isCloned = true;
|
---|
81 | return SU;
|
---|
82 | }
|
---|
83 |
|
---|
84 | /// CheckForPhysRegDependency - Check if the dependency between def and use of
|
---|
85 | /// a specified operand is a physical register dependency. If so, returns the
|
---|
86 | /// register and the cost of copying the register.
|
---|
87 | static void CheckForPhysRegDependency(SDNode *Def, SDNode *User, unsigned Op,
|
---|
88 | const TargetRegisterInfo *TRI,
|
---|
89 | const TargetInstrInfo *TII,
|
---|
90 | unsigned &PhysReg, int &Cost) {
|
---|
91 | if (Op != 2 || User->getOpcode() != ISD::CopyToReg)
|
---|
92 | return;
|
---|
93 |
|
---|
94 | unsigned Reg = cast<RegisterSDNode>(User->getOperand(1))->getReg();
|
---|
95 | if (TargetRegisterInfo::isVirtualRegister(Reg))
|
---|
96 | return;
|
---|
97 |
|
---|
98 | unsigned ResNo = User->getOperand(2).getResNo();
|
---|
99 | if (Def->isMachineOpcode()) {
|
---|
100 | const TargetInstrDesc &II = TII->get(Def->getMachineOpcode());
|
---|
101 | if (ResNo >= II.getNumDefs() &&
|
---|
102 | II.ImplicitDefs[ResNo - II.getNumDefs()] == Reg) {
|
---|
103 | PhysReg = Reg;
|
---|
104 | const TargetRegisterClass *RC =
|
---|
105 | TRI->getMinimalPhysRegClass(Reg, Def->getValueType(ResNo));
|
---|
106 | Cost = RC->getCopyCost();
|
---|
107 | }
|
---|
108 | }
|
---|
109 | }
|
---|
110 |
|
---|
111 | static void AddFlags(SDNode *N, SDValue Flag, bool AddFlag,
|
---|
112 | SelectionDAG *DAG) {
|
---|
113 | SmallVector<EVT, 4> VTs;
|
---|
114 | SDNode *FlagDestNode = Flag.getNode();
|
---|
115 |
|
---|
116 | // Don't add a flag from a node to itself.
|
---|
117 | if (FlagDestNode == N) return;
|
---|
118 |
|
---|
119 | // Don't add a flag to something which already has a flag.
|
---|
120 | if (N->getValueType(N->getNumValues() - 1) == MVT::Flag) return;
|
---|
121 |
|
---|
122 | for (unsigned I = 0, E = N->getNumValues(); I != E; ++I)
|
---|
123 | VTs.push_back(N->getValueType(I));
|
---|
124 |
|
---|
125 | if (AddFlag)
|
---|
126 | VTs.push_back(MVT::Flag);
|
---|
127 |
|
---|
128 | SmallVector<SDValue, 4> Ops;
|
---|
129 | for (unsigned I = 0, E = N->getNumOperands(); I != E; ++I)
|
---|
130 | Ops.push_back(N->getOperand(I));
|
---|
131 |
|
---|
132 | if (FlagDestNode)
|
---|
133 | Ops.push_back(Flag);
|
---|
134 |
|
---|
135 | SDVTList VTList = DAG->getVTList(&VTs[0], VTs.size());
|
---|
136 | MachineSDNode::mmo_iterator Begin = 0, End = 0;
|
---|
137 | MachineSDNode *MN = dyn_cast<MachineSDNode>(N);
|
---|
138 |
|
---|
139 | // Store memory references.
|
---|
140 | if (MN) {
|
---|
141 | Begin = MN->memoperands_begin();
|
---|
142 | End = MN->memoperands_end();
|
---|
143 | }
|
---|
144 |
|
---|
145 | DAG->MorphNodeTo(N, N->getOpcode(), VTList, &Ops[0], Ops.size());
|
---|
146 |
|
---|
147 | // Reset the memory references
|
---|
148 | if (MN)
|
---|
149 | MN->setMemRefs(Begin, End);
|
---|
150 | }
|
---|
151 |
|
---|
152 | /// ClusterNeighboringLoads - Force nearby loads together by "flagging" them.
|
---|
153 | /// This function finds loads of the same base and different offsets. If the
|
---|
154 | /// offsets are not far apart (target specific), it add MVT::Flag inputs and
|
---|
155 | /// outputs to ensure they are scheduled together and in order. This
|
---|
156 | /// optimization may benefit some targets by improving cache locality.
|
---|
157 | void ScheduleDAGSDNodes::ClusterNeighboringLoads(SDNode *Node) {
|
---|
158 | SDNode *Chain = 0;
|
---|
159 | unsigned NumOps = Node->getNumOperands();
|
---|
160 | if (Node->getOperand(NumOps-1).getValueType() == MVT::Other)
|
---|
161 | Chain = Node->getOperand(NumOps-1).getNode();
|
---|
162 | if (!Chain)
|
---|
163 | return;
|
---|
164 |
|
---|
165 | // Look for other loads of the same chain. Find loads that are loading from
|
---|
166 | // the same base pointer and different offsets.
|
---|
167 | SmallPtrSet<SDNode*, 16> Visited;
|
---|
168 | SmallVector<int64_t, 4> Offsets;
|
---|
169 | DenseMap<long long, SDNode*> O2SMap; // Map from offset to SDNode.
|
---|
170 | bool Cluster = false;
|
---|
171 | SDNode *Base = Node;
|
---|
172 | for (SDNode::use_iterator I = Chain->use_begin(), E = Chain->use_end();
|
---|
173 | I != E; ++I) {
|
---|
174 | SDNode *User = *I;
|
---|
175 | if (User == Node || !Visited.insert(User))
|
---|
176 | continue;
|
---|
177 | int64_t Offset1, Offset2;
|
---|
178 | if (!TII->areLoadsFromSameBasePtr(Base, User, Offset1, Offset2) ||
|
---|
179 | Offset1 == Offset2)
|
---|
180 | // FIXME: Should be ok if they addresses are identical. But earlier
|
---|
181 | // optimizations really should have eliminated one of the loads.
|
---|
182 | continue;
|
---|
183 | if (O2SMap.insert(std::make_pair(Offset1, Base)).second)
|
---|
184 | Offsets.push_back(Offset1);
|
---|
185 | O2SMap.insert(std::make_pair(Offset2, User));
|
---|
186 | Offsets.push_back(Offset2);
|
---|
187 | if (Offset2 < Offset1)
|
---|
188 | Base = User;
|
---|
189 | Cluster = true;
|
---|
190 | }
|
---|
191 |
|
---|
192 | if (!Cluster)
|
---|
193 | return;
|
---|
194 |
|
---|
195 | // Sort them in increasing order.
|
---|
196 | std::sort(Offsets.begin(), Offsets.end());
|
---|
197 |
|
---|
198 | // Check if the loads are close enough.
|
---|
199 | SmallVector<SDNode*, 4> Loads;
|
---|
200 | unsigned NumLoads = 0;
|
---|
201 | int64_t BaseOff = Offsets[0];
|
---|
202 | SDNode *BaseLoad = O2SMap[BaseOff];
|
---|
203 | Loads.push_back(BaseLoad);
|
---|
204 | for (unsigned i = 1, e = Offsets.size(); i != e; ++i) {
|
---|
205 | int64_t Offset = Offsets[i];
|
---|
206 | SDNode *Load = O2SMap[Offset];
|
---|
207 | if (!TII->shouldScheduleLoadsNear(BaseLoad, Load, BaseOff, Offset,NumLoads))
|
---|
208 | break; // Stop right here. Ignore loads that are further away.
|
---|
209 | Loads.push_back(Load);
|
---|
210 | ++NumLoads;
|
---|
211 | }
|
---|
212 |
|
---|
213 | if (NumLoads == 0)
|
---|
214 | return;
|
---|
215 |
|
---|
216 | // Cluster loads by adding MVT::Flag outputs and inputs. This also
|
---|
217 | // ensure they are scheduled in order of increasing addresses.
|
---|
218 | SDNode *Lead = Loads[0];
|
---|
219 | AddFlags(Lead, SDValue(0, 0), true, DAG);
|
---|
220 |
|
---|
221 | SDValue InFlag = SDValue(Lead, Lead->getNumValues() - 1);
|
---|
222 | for (unsigned I = 1, E = Loads.size(); I != E; ++I) {
|
---|
223 | bool OutFlag = I < E - 1;
|
---|
224 | SDNode *Load = Loads[I];
|
---|
225 |
|
---|
226 | AddFlags(Load, InFlag, OutFlag, DAG);
|
---|
227 |
|
---|
228 | if (OutFlag)
|
---|
229 | InFlag = SDValue(Load, Load->getNumValues() - 1);
|
---|
230 |
|
---|
231 | ++LoadsClustered;
|
---|
232 | }
|
---|
233 | }
|
---|
234 |
|
---|
235 | /// ClusterNodes - Cluster certain nodes which should be scheduled together.
|
---|
236 | ///
|
---|
237 | void ScheduleDAGSDNodes::ClusterNodes() {
|
---|
238 | for (SelectionDAG::allnodes_iterator NI = DAG->allnodes_begin(),
|
---|
239 | E = DAG->allnodes_end(); NI != E; ++NI) {
|
---|
240 | SDNode *Node = &*NI;
|
---|
241 | if (!Node || !Node->isMachineOpcode())
|
---|
242 | continue;
|
---|
243 |
|
---|
244 | unsigned Opc = Node->getMachineOpcode();
|
---|
245 | const TargetInstrDesc &TID = TII->get(Opc);
|
---|
246 | if (TID.mayLoad())
|
---|
247 | // Cluster loads from "near" addresses into combined SUnits.
|
---|
248 | ClusterNeighboringLoads(Node);
|
---|
249 | }
|
---|
250 | }
|
---|
251 |
|
---|
252 | void ScheduleDAGSDNodes::BuildSchedUnits() {
|
---|
253 | // During scheduling, the NodeId field of SDNode is used to map SDNodes
|
---|
254 | // to their associated SUnits by holding SUnits table indices. A value
|
---|
255 | // of -1 means the SDNode does not yet have an associated SUnit.
|
---|
256 | unsigned NumNodes = 0;
|
---|
257 | for (SelectionDAG::allnodes_iterator NI = DAG->allnodes_begin(),
|
---|
258 | E = DAG->allnodes_end(); NI != E; ++NI) {
|
---|
259 | NI->setNodeId(-1);
|
---|
260 | ++NumNodes;
|
---|
261 | }
|
---|
262 |
|
---|
263 | // Reserve entries in the vector for each of the SUnits we are creating. This
|
---|
264 | // ensure that reallocation of the vector won't happen, so SUnit*'s won't get
|
---|
265 | // invalidated.
|
---|
266 | // FIXME: Multiply by 2 because we may clone nodes during scheduling.
|
---|
267 | // This is a temporary workaround.
|
---|
268 | SUnits.reserve(NumNodes * 2);
|
---|
269 |
|
---|
270 | // Add all nodes in depth first order.
|
---|
271 | SmallVector<SDNode*, 64> Worklist;
|
---|
272 | SmallPtrSet<SDNode*, 64> Visited;
|
---|
273 | Worklist.push_back(DAG->getRoot().getNode());
|
---|
274 | Visited.insert(DAG->getRoot().getNode());
|
---|
275 |
|
---|
276 | while (!Worklist.empty()) {
|
---|
277 | SDNode *NI = Worklist.pop_back_val();
|
---|
278 |
|
---|
279 | // Add all operands to the worklist unless they've already been added.
|
---|
280 | for (unsigned i = 0, e = NI->getNumOperands(); i != e; ++i)
|
---|
281 | if (Visited.insert(NI->getOperand(i).getNode()))
|
---|
282 | Worklist.push_back(NI->getOperand(i).getNode());
|
---|
283 |
|
---|
284 | if (isPassiveNode(NI)) // Leaf node, e.g. a TargetImmediate.
|
---|
285 | continue;
|
---|
286 |
|
---|
287 | // If this node has already been processed, stop now.
|
---|
288 | if (NI->getNodeId() != -1) continue;
|
---|
289 |
|
---|
290 | SUnit *NodeSUnit = NewSUnit(NI);
|
---|
291 |
|
---|
292 | // See if anything is flagged to this node, if so, add them to flagged
|
---|
293 | // nodes. Nodes can have at most one flag input and one flag output. Flags
|
---|
294 | // are required to be the last operand and result of a node.
|
---|
295 |
|
---|
296 | // Scan up to find flagged preds.
|
---|
297 | SDNode *N = NI;
|
---|
298 | while (N->getNumOperands() &&
|
---|
299 | N->getOperand(N->getNumOperands()-1).getValueType() == MVT::Flag) {
|
---|
300 | N = N->getOperand(N->getNumOperands()-1).getNode();
|
---|
301 | assert(N->getNodeId() == -1 && "Node already inserted!");
|
---|
302 | N->setNodeId(NodeSUnit->NodeNum);
|
---|
303 | }
|
---|
304 |
|
---|
305 | // Scan down to find any flagged succs.
|
---|
306 | N = NI;
|
---|
307 | while (N->getValueType(N->getNumValues()-1) == MVT::Flag) {
|
---|
308 | SDValue FlagVal(N, N->getNumValues()-1);
|
---|
309 |
|
---|
310 | // There are either zero or one users of the Flag result.
|
---|
311 | bool HasFlagUse = false;
|
---|
312 | for (SDNode::use_iterator UI = N->use_begin(), E = N->use_end();
|
---|
313 | UI != E; ++UI)
|
---|
314 | if (FlagVal.isOperandOf(*UI)) {
|
---|
315 | HasFlagUse = true;
|
---|
316 | assert(N->getNodeId() == -1 && "Node already inserted!");
|
---|
317 | N->setNodeId(NodeSUnit->NodeNum);
|
---|
318 | N = *UI;
|
---|
319 | break;
|
---|
320 | }
|
---|
321 | if (!HasFlagUse) break;
|
---|
322 | }
|
---|
323 |
|
---|
324 | // If there are flag operands involved, N is now the bottom-most node
|
---|
325 | // of the sequence of nodes that are flagged together.
|
---|
326 | // Update the SUnit.
|
---|
327 | NodeSUnit->setNode(N);
|
---|
328 | assert(N->getNodeId() == -1 && "Node already inserted!");
|
---|
329 | N->setNodeId(NodeSUnit->NodeNum);
|
---|
330 |
|
---|
331 | // Assign the Latency field of NodeSUnit using target-provided information.
|
---|
332 | ComputeLatency(NodeSUnit);
|
---|
333 | }
|
---|
334 | }
|
---|
335 |
|
---|
336 | void ScheduleDAGSDNodes::AddSchedEdges() {
|
---|
337 | const TargetSubtarget &ST = TM.getSubtarget<TargetSubtarget>();
|
---|
338 |
|
---|
339 | // Check to see if the scheduler cares about latencies.
|
---|
340 | bool UnitLatencies = ForceUnitLatencies();
|
---|
341 |
|
---|
342 | // Pass 2: add the preds, succs, etc.
|
---|
343 | for (unsigned su = 0, e = SUnits.size(); su != e; ++su) {
|
---|
344 | SUnit *SU = &SUnits[su];
|
---|
345 | SDNode *MainNode = SU->getNode();
|
---|
346 |
|
---|
347 | if (MainNode->isMachineOpcode()) {
|
---|
348 | unsigned Opc = MainNode->getMachineOpcode();
|
---|
349 | const TargetInstrDesc &TID = TII->get(Opc);
|
---|
350 | for (unsigned i = 0; i != TID.getNumOperands(); ++i) {
|
---|
351 | if (TID.getOperandConstraint(i, TOI::TIED_TO) != -1) {
|
---|
352 | SU->isTwoAddress = true;
|
---|
353 | break;
|
---|
354 | }
|
---|
355 | }
|
---|
356 | if (TID.isCommutable())
|
---|
357 | SU->isCommutable = true;
|
---|
358 | }
|
---|
359 |
|
---|
360 | // Find all predecessors and successors of the group.
|
---|
361 | for (SDNode *N = SU->getNode(); N; N = N->getFlaggedNode()) {
|
---|
362 | if (N->isMachineOpcode() &&
|
---|
363 | TII->get(N->getMachineOpcode()).getImplicitDefs()) {
|
---|
364 | SU->hasPhysRegClobbers = true;
|
---|
365 | unsigned NumUsed = InstrEmitter::CountResults(N);
|
---|
366 | while (NumUsed != 0 && !N->hasAnyUseOfValue(NumUsed - 1))
|
---|
367 | --NumUsed; // Skip over unused values at the end.
|
---|
368 | if (NumUsed > TII->get(N->getMachineOpcode()).getNumDefs())
|
---|
369 | SU->hasPhysRegDefs = true;
|
---|
370 | }
|
---|
371 |
|
---|
372 | for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) {
|
---|
373 | SDNode *OpN = N->getOperand(i).getNode();
|
---|
374 | if (isPassiveNode(OpN)) continue; // Not scheduled.
|
---|
375 | SUnit *OpSU = &SUnits[OpN->getNodeId()];
|
---|
376 | assert(OpSU && "Node has no SUnit!");
|
---|
377 | if (OpSU == SU) continue; // In the same group.
|
---|
378 |
|
---|
379 | EVT OpVT = N->getOperand(i).getValueType();
|
---|
380 | assert(OpVT != MVT::Flag && "Flagged nodes should be in same sunit!");
|
---|
381 | bool isChain = OpVT == MVT::Other;
|
---|
382 |
|
---|
383 | unsigned PhysReg = 0;
|
---|
384 | int Cost = 1;
|
---|
385 | // Determine if this is a physical register dependency.
|
---|
386 | CheckForPhysRegDependency(OpN, N, i, TRI, TII, PhysReg, Cost);
|
---|
387 | assert((PhysReg == 0 || !isChain) &&
|
---|
388 | "Chain dependence via physreg data?");
|
---|
389 | // FIXME: See ScheduleDAGSDNodes::EmitCopyFromReg. For now, scheduler
|
---|
390 | // emits a copy from the physical register to a virtual register unless
|
---|
391 | // it requires a cross class copy (cost < 0). That means we are only
|
---|
392 | // treating "expensive to copy" register dependency as physical register
|
---|
393 | // dependency. This may change in the future though.
|
---|
394 | if (Cost >= 0)
|
---|
395 | PhysReg = 0;
|
---|
396 |
|
---|
397 | // If this is a ctrl dep, latency is 1.
|
---|
398 | unsigned OpLatency = isChain ? 1 : OpSU->Latency;
|
---|
399 | const SDep &dep = SDep(OpSU, isChain ? SDep::Order : SDep::Data,
|
---|
400 | OpLatency, PhysReg);
|
---|
401 | if (!isChain && !UnitLatencies) {
|
---|
402 | ComputeOperandLatency(OpN, N, i, const_cast<SDep &>(dep));
|
---|
403 | ST.adjustSchedDependency(OpSU, SU, const_cast<SDep &>(dep));
|
---|
404 | }
|
---|
405 |
|
---|
406 | SU->addPred(dep);
|
---|
407 | }
|
---|
408 | }
|
---|
409 | }
|
---|
410 | }
|
---|
411 |
|
---|
412 | /// BuildSchedGraph - Build the SUnit graph from the selection dag that we
|
---|
413 | /// are input. This SUnit graph is similar to the SelectionDAG, but
|
---|
414 | /// excludes nodes that aren't interesting to scheduling, and represents
|
---|
415 | /// flagged together nodes with a single SUnit.
|
---|
416 | void ScheduleDAGSDNodes::BuildSchedGraph(AliasAnalysis *AA) {
|
---|
417 | // Cluster certain nodes which should be scheduled together.
|
---|
418 | ClusterNodes();
|
---|
419 | // Populate the SUnits array.
|
---|
420 | BuildSchedUnits();
|
---|
421 | // Compute all the scheduling dependencies between nodes.
|
---|
422 | AddSchedEdges();
|
---|
423 | }
|
---|
424 |
|
---|
425 | void ScheduleDAGSDNodes::ComputeLatency(SUnit *SU) {
|
---|
426 | // Check to see if the scheduler cares about latencies.
|
---|
427 | if (ForceUnitLatencies()) {
|
---|
428 | SU->Latency = 1;
|
---|
429 | return;
|
---|
430 | }
|
---|
431 |
|
---|
432 | const InstrItineraryData &InstrItins = TM.getInstrItineraryData();
|
---|
433 | if (InstrItins.isEmpty()) {
|
---|
434 | SU->Latency = 1;
|
---|
435 | return;
|
---|
436 | }
|
---|
437 |
|
---|
438 | // Compute the latency for the node. We use the sum of the latencies for
|
---|
439 | // all nodes flagged together into this SUnit.
|
---|
440 | SU->Latency = 0;
|
---|
441 | for (SDNode *N = SU->getNode(); N; N = N->getFlaggedNode())
|
---|
442 | if (N->isMachineOpcode()) {
|
---|
443 | SU->Latency += InstrItins.
|
---|
444 | getStageLatency(TII->get(N->getMachineOpcode()).getSchedClass());
|
---|
445 | }
|
---|
446 | }
|
---|
447 |
|
---|
448 | void ScheduleDAGSDNodes::ComputeOperandLatency(SDNode *Def, SDNode *Use,
|
---|
449 | unsigned OpIdx, SDep& dep) const{
|
---|
450 | // Check to see if the scheduler cares about latencies.
|
---|
451 | if (ForceUnitLatencies())
|
---|
452 | return;
|
---|
453 |
|
---|
454 | const InstrItineraryData &InstrItins = TM.getInstrItineraryData();
|
---|
455 | if (InstrItins.isEmpty())
|
---|
456 | return;
|
---|
457 |
|
---|
458 | if (dep.getKind() != SDep::Data)
|
---|
459 | return;
|
---|
460 |
|
---|
461 | unsigned DefIdx = Use->getOperand(OpIdx).getResNo();
|
---|
462 | if (Def->isMachineOpcode()) {
|
---|
463 | const TargetInstrDesc &II = TII->get(Def->getMachineOpcode());
|
---|
464 | if (DefIdx >= II.getNumDefs())
|
---|
465 | return;
|
---|
466 | int DefCycle = InstrItins.getOperandCycle(II.getSchedClass(), DefIdx);
|
---|
467 | if (DefCycle < 0)
|
---|
468 | return;
|
---|
469 | int UseCycle = 1;
|
---|
470 | if (Use->isMachineOpcode()) {
|
---|
471 | const unsigned UseClass = TII->get(Use->getMachineOpcode()).getSchedClass();
|
---|
472 | UseCycle = InstrItins.getOperandCycle(UseClass, OpIdx);
|
---|
473 | }
|
---|
474 | if (UseCycle >= 0) {
|
---|
475 | int Latency = DefCycle - UseCycle + 1;
|
---|
476 | if (Latency >= 0)
|
---|
477 | dep.setLatency(Latency);
|
---|
478 | }
|
---|
479 | }
|
---|
480 | }
|
---|
481 |
|
---|
482 | void ScheduleDAGSDNodes::dumpNode(const SUnit *SU) const {
|
---|
483 | if (!SU->getNode()) {
|
---|
484 | dbgs() << "PHYS REG COPY\n";
|
---|
485 | return;
|
---|
486 | }
|
---|
487 |
|
---|
488 | SU->getNode()->dump(DAG);
|
---|
489 | dbgs() << "\n";
|
---|
490 | SmallVector<SDNode *, 4> FlaggedNodes;
|
---|
491 | for (SDNode *N = SU->getNode()->getFlaggedNode(); N; N = N->getFlaggedNode())
|
---|
492 | FlaggedNodes.push_back(N);
|
---|
493 | while (!FlaggedNodes.empty()) {
|
---|
494 | dbgs() << " ";
|
---|
495 | FlaggedNodes.back()->dump(DAG);
|
---|
496 | dbgs() << "\n";
|
---|
497 | FlaggedNodes.pop_back();
|
---|
498 | }
|
---|
499 | }
|
---|
500 |
|
---|
501 | namespace {
|
---|
502 | struct OrderSorter {
|
---|
503 | bool operator()(const std::pair<unsigned, MachineInstr*> &A,
|
---|
504 | const std::pair<unsigned, MachineInstr*> &B) {
|
---|
505 | return A.first < B.first;
|
---|
506 | }
|
---|
507 | };
|
---|
508 | }
|
---|
509 |
|
---|
510 | // ProcessSourceNode - Process nodes with source order numbers. These are added
|
---|
511 | // to a vector which EmitSchedule uses to determine how to insert dbg_value
|
---|
512 | // instructions in the right order.
|
---|
513 | static void ProcessSourceNode(SDNode *N, SelectionDAG *DAG,
|
---|
514 | InstrEmitter &Emitter,
|
---|
515 | DenseMap<SDValue, unsigned> &VRBaseMap,
|
---|
516 | SmallVector<std::pair<unsigned, MachineInstr*>, 32> &Orders,
|
---|
517 | SmallSet<unsigned, 8> &Seen) {
|
---|
518 | unsigned Order = DAG->GetOrdering(N);
|
---|
519 | if (!Order || !Seen.insert(Order))
|
---|
520 | return;
|
---|
521 |
|
---|
522 | MachineBasicBlock *BB = Emitter.getBlock();
|
---|
523 | if (Emitter.getInsertPos() == BB->begin() || BB->back().isPHI()) {
|
---|
524 | // Did not insert any instruction.
|
---|
525 | Orders.push_back(std::make_pair(Order, (MachineInstr*)0));
|
---|
526 | return;
|
---|
527 | }
|
---|
528 |
|
---|
529 | Orders.push_back(std::make_pair(Order, prior(Emitter.getInsertPos())));
|
---|
530 | if (!N->getHasDebugValue())
|
---|
531 | return;
|
---|
532 | // Opportunistically insert immediate dbg_value uses, i.e. those with source
|
---|
533 | // order number right after the N.
|
---|
534 | MachineBasicBlock::iterator InsertPos = Emitter.getInsertPos();
|
---|
535 | SmallVector<SDDbgValue*,2> &DVs = DAG->GetDbgValues(N);
|
---|
536 | for (unsigned i = 0, e = DVs.size(); i != e; ++i) {
|
---|
537 | if (DVs[i]->isInvalidated())
|
---|
538 | continue;
|
---|
539 | unsigned DVOrder = DVs[i]->getOrder();
|
---|
540 | if (DVOrder == ++Order) {
|
---|
541 | MachineInstr *DbgMI = Emitter.EmitDbgValue(DVs[i], VRBaseMap);
|
---|
542 | if (DbgMI) {
|
---|
543 | Orders.push_back(std::make_pair(DVOrder, DbgMI));
|
---|
544 | BB->insert(InsertPos, DbgMI);
|
---|
545 | }
|
---|
546 | DVs[i]->setIsInvalidated();
|
---|
547 | }
|
---|
548 | }
|
---|
549 | }
|
---|
550 |
|
---|
551 |
|
---|
552 | /// EmitSchedule - Emit the machine code in scheduled order.
|
---|
553 | MachineBasicBlock *ScheduleDAGSDNodes::EmitSchedule() {
|
---|
554 | InstrEmitter Emitter(BB, InsertPos);
|
---|
555 | DenseMap<SDValue, unsigned> VRBaseMap;
|
---|
556 | DenseMap<SUnit*, unsigned> CopyVRBaseMap;
|
---|
557 | SmallVector<std::pair<unsigned, MachineInstr*>, 32> Orders;
|
---|
558 | SmallSet<unsigned, 8> Seen;
|
---|
559 | bool HasDbg = DAG->hasDebugValues();
|
---|
560 |
|
---|
561 | // If this is the first BB, emit byval parameter dbg_value's.
|
---|
562 | if (HasDbg && BB->getParent()->begin() == MachineFunction::iterator(BB)) {
|
---|
563 | SDDbgInfo::DbgIterator PDI = DAG->ByvalParmDbgBegin();
|
---|
564 | SDDbgInfo::DbgIterator PDE = DAG->ByvalParmDbgEnd();
|
---|
565 | for (; PDI != PDE; ++PDI) {
|
---|
566 | MachineInstr *DbgMI= Emitter.EmitDbgValue(*PDI, VRBaseMap);
|
---|
567 | if (DbgMI)
|
---|
568 | BB->insert(InsertPos, DbgMI);
|
---|
569 | }
|
---|
570 | }
|
---|
571 |
|
---|
572 | for (unsigned i = 0, e = Sequence.size(); i != e; i++) {
|
---|
573 | SUnit *SU = Sequence[i];
|
---|
574 | if (!SU) {
|
---|
575 | // Null SUnit* is a noop.
|
---|
576 | EmitNoop();
|
---|
577 | continue;
|
---|
578 | }
|
---|
579 |
|
---|
580 | // For pre-regalloc scheduling, create instructions corresponding to the
|
---|
581 | // SDNode and any flagged SDNodes and append them to the block.
|
---|
582 | if (!SU->getNode()) {
|
---|
583 | // Emit a copy.
|
---|
584 | EmitPhysRegCopy(SU, CopyVRBaseMap);
|
---|
585 | continue;
|
---|
586 | }
|
---|
587 |
|
---|
588 | SmallVector<SDNode *, 4> FlaggedNodes;
|
---|
589 | for (SDNode *N = SU->getNode()->getFlaggedNode(); N;
|
---|
590 | N = N->getFlaggedNode())
|
---|
591 | FlaggedNodes.push_back(N);
|
---|
592 | while (!FlaggedNodes.empty()) {
|
---|
593 | SDNode *N = FlaggedNodes.back();
|
---|
594 | Emitter.EmitNode(FlaggedNodes.back(), SU->OrigNode != SU, SU->isCloned,
|
---|
595 | VRBaseMap);
|
---|
596 | // Remember the source order of the inserted instruction.
|
---|
597 | if (HasDbg)
|
---|
598 | ProcessSourceNode(N, DAG, Emitter, VRBaseMap, Orders, Seen);
|
---|
599 | FlaggedNodes.pop_back();
|
---|
600 | }
|
---|
601 | Emitter.EmitNode(SU->getNode(), SU->OrigNode != SU, SU->isCloned,
|
---|
602 | VRBaseMap);
|
---|
603 | // Remember the source order of the inserted instruction.
|
---|
604 | if (HasDbg)
|
---|
605 | ProcessSourceNode(SU->getNode(), DAG, Emitter, VRBaseMap, Orders,
|
---|
606 | Seen);
|
---|
607 | }
|
---|
608 |
|
---|
609 | // Insert all the dbg_values which have not already been inserted in source
|
---|
610 | // order sequence.
|
---|
611 | if (HasDbg) {
|
---|
612 | MachineBasicBlock::iterator BBBegin = BB->getFirstNonPHI();
|
---|
613 |
|
---|
614 | // Sort the source order instructions and use the order to insert debug
|
---|
615 | // values.
|
---|
616 | std::sort(Orders.begin(), Orders.end(), OrderSorter());
|
---|
617 |
|
---|
618 | SDDbgInfo::DbgIterator DI = DAG->DbgBegin();
|
---|
619 | SDDbgInfo::DbgIterator DE = DAG->DbgEnd();
|
---|
620 | // Now emit the rest according to source order.
|
---|
621 | unsigned LastOrder = 0;
|
---|
622 | for (unsigned i = 0, e = Orders.size(); i != e && DI != DE; ++i) {
|
---|
623 | unsigned Order = Orders[i].first;
|
---|
624 | MachineInstr *MI = Orders[i].second;
|
---|
625 | // Insert all SDDbgValue's whose order(s) are before "Order".
|
---|
626 | if (!MI)
|
---|
627 | continue;
|
---|
628 | #ifndef NDEBUG
|
---|
629 | unsigned LastDIOrder = 0;
|
---|
630 | #endif
|
---|
631 | for (; DI != DE &&
|
---|
632 | (*DI)->getOrder() >= LastOrder && (*DI)->getOrder() < Order; ++DI) {
|
---|
633 | #ifndef NDEBUG
|
---|
634 | assert((*DI)->getOrder() >= LastDIOrder &&
|
---|
635 | "SDDbgValue nodes must be in source order!");
|
---|
636 | LastDIOrder = (*DI)->getOrder();
|
---|
637 | #endif
|
---|
638 | if ((*DI)->isInvalidated())
|
---|
639 | continue;
|
---|
640 | MachineInstr *DbgMI = Emitter.EmitDbgValue(*DI, VRBaseMap);
|
---|
641 | if (DbgMI) {
|
---|
642 | if (!LastOrder)
|
---|
643 | // Insert to start of the BB (after PHIs).
|
---|
644 | BB->insert(BBBegin, DbgMI);
|
---|
645 | else {
|
---|
646 | // Insert at the instruction, which may be in a different
|
---|
647 | // block, if the block was split by a custom inserter.
|
---|
648 | MachineBasicBlock::iterator Pos = MI;
|
---|
649 | MI->getParent()->insert(llvm::next(Pos), DbgMI);
|
---|
650 | }
|
---|
651 | }
|
---|
652 | }
|
---|
653 | LastOrder = Order;
|
---|
654 | }
|
---|
655 | // Add trailing DbgValue's before the terminator. FIXME: May want to add
|
---|
656 | // some of them before one or more conditional branches?
|
---|
657 | while (DI != DE) {
|
---|
658 | MachineBasicBlock *InsertBB = Emitter.getBlock();
|
---|
659 | MachineBasicBlock::iterator Pos= Emitter.getBlock()->getFirstTerminator();
|
---|
660 | if (!(*DI)->isInvalidated()) {
|
---|
661 | MachineInstr *DbgMI= Emitter.EmitDbgValue(*DI, VRBaseMap);
|
---|
662 | if (DbgMI)
|
---|
663 | InsertBB->insert(Pos, DbgMI);
|
---|
664 | }
|
---|
665 | ++DI;
|
---|
666 | }
|
---|
667 | }
|
---|
668 |
|
---|
669 | BB = Emitter.getBlock();
|
---|
670 | InsertPos = Emitter.getInsertPos();
|
---|
671 | return BB;
|
---|
672 | }
|
---|