OLD | NEW |
---|---|
1 //===- subzero/src/IceCfgNode.cpp - Basic block (node) implementation -----===// | 1 //===- subzero/src/IceCfgNode.cpp - Basic block (node) implementation -----===// |
2 // | 2 // |
3 // The Subzero Code Generator | 3 // The Subzero Code Generator |
4 // | 4 // |
5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
7 // | 7 // |
8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
9 // | 9 // |
10 // This file implements the CfgNode class, including the complexities | 10 // This file implements the CfgNode class, including the complexities |
11 // of instruction insertion and in-edge calculation. | 11 // of instruction insertion and in-edge calculation. |
12 // | 12 // |
13 //===----------------------------------------------------------------------===// | 13 //===----------------------------------------------------------------------===// |
14 | 14 |
15 #include "IceCfg.h" | 15 #include "IceCfg.h" |
16 #include "IceCfgNode.h" | 16 #include "IceCfgNode.h" |
17 #include "IceInst.h" | 17 #include "IceInst.h" |
18 #include "IceLiveness.h" | |
18 #include "IceOperand.h" | 19 #include "IceOperand.h" |
19 #include "IceTargetLowering.h" | 20 #include "IceTargetLowering.h" |
20 | 21 |
21 namespace Ice { | 22 namespace Ice { |
22 | 23 |
23 CfgNode::CfgNode(Cfg *Func, SizeT LabelNumber, IceString Name) | 24 CfgNode::CfgNode(Cfg *Func, SizeT LabelNumber, IceString Name) |
24 : Func(Func), Number(LabelNumber), Name(Name), HasReturn(false) {} | 25 : Func(Func), Number(LabelNumber), Name(Name), HasReturn(false) {} |
25 | 26 |
26 // Returns the name the node was created with. If no name was given, | 27 // Returns the name the node was created with. If no name was given, |
27 // it synthesizes a (hopefully) unique name. | 28 // it synthesizes a (hopefully) unique name. |
(...skipping 14 matching lines...) Expand all Loading... | |
42 Func->setError("Phi instruction added to the middle of a block"); | 43 Func->setError("Phi instruction added to the middle of a block"); |
43 return; | 44 return; |
44 } | 45 } |
45 Phis.push_back(Phi); | 46 Phis.push_back(Phi); |
46 } else { | 47 } else { |
47 Insts.push_back(Inst); | 48 Insts.push_back(Inst); |
48 } | 49 } |
49 Inst->updateVars(this); | 50 Inst->updateVars(this); |
50 } | 51 } |
51 | 52 |
53 // Renumbers the non-deleted instructions in the node. This needs to | |
54 // be done in preparation for live range analysis. The instruction | |
55 // numbers in a block must be monotonically increasing. The range of | |
56 // instruction numbers in a block, from lowest to highest, must not | |
57 // overlap with the range of any other block. | |
58 void CfgNode::renumberInstructions() { | |
59 for (PhiList::const_iterator I = Phis.begin(), E = Phis.end(); I != E; ++I) { | |
60 (*I)->renumber(Func); | |
61 } | |
62 InstList::const_iterator I = Insts.begin(), E = Insts.end(); | |
63 while (I != E) { | |
64 Inst *Inst = *I++; | |
65 Inst->renumber(Func); | |
66 } | |
67 } | |
68 | |
52 // When a node is created, the OutEdges are immediately knows, but the | 69 // When a node is created, the OutEdges are immediately knows, but the |
53 // InEdges have to be built up incrementally. After the CFG has been | 70 // InEdges have to be built up incrementally. After the CFG has been |
54 // constructed, the computePredecessors() pass finalizes it by | 71 // constructed, the computePredecessors() pass finalizes it by |
55 // creating the InEdges list. | 72 // creating the InEdges list. |
56 void CfgNode::computePredecessors() { | 73 void CfgNode::computePredecessors() { |
57 OutEdges = (*Insts.rbegin())->getTerminatorEdges(); | 74 OutEdges = (*Insts.rbegin())->getTerminatorEdges(); |
58 for (NodeList::const_iterator I = OutEdges.begin(), E = OutEdges.end(); | 75 for (NodeList::const_iterator I = OutEdges.begin(), E = OutEdges.end(); |
59 I != E; ++I) { | 76 I != E; ++I) { |
60 CfgNode *Node = *I; | 77 CfgNode *Node = *I; |
61 Node->InEdges.push_back(this); | 78 Node->InEdges.push_back(this); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
100 // Find the insertion point. TODO: After branch/compare fusing is | 117 // Find the insertion point. TODO: After branch/compare fusing is |
101 // implemented, try not to insert Phi stores between the compare and | 118 // implemented, try not to insert Phi stores between the compare and |
102 // conditional branch instructions, otherwise the branch/compare | 119 // conditional branch instructions, otherwise the branch/compare |
103 // pattern matching may fail. However, the branch/compare sequence | 120 // pattern matching may fail. However, the branch/compare sequence |
104 // will have to be broken if the compare result is read (by the | 121 // will have to be broken if the compare result is read (by the |
105 // assignment) before it is written (by the compare). | 122 // assignment) before it is written (by the compare). |
106 InstList::iterator InsertionPoint = Insts.end(); | 123 InstList::iterator InsertionPoint = Insts.end(); |
107 // Every block must end in a terminator instruction. | 124 // Every block must end in a terminator instruction. |
108 assert(InsertionPoint != Insts.begin()); | 125 assert(InsertionPoint != Insts.begin()); |
109 --InsertionPoint; | 126 --InsertionPoint; |
110 // Confirm via assert() that InsertionPoint is a terminator | 127 // Confirm that InsertionPoint is a terminator instruction. Calling |
111 // instruction. Calling getTerminatorEdges() on a non-terminator | 128 // getTerminatorEdges() on a non-terminator instruction will cause |
112 // instruction will cause an llvm_unreachable(). | 129 // an llvm_unreachable(). |
113 assert(((*InsertionPoint)->getTerminatorEdges(), true)); | 130 (void)(*InsertionPoint)->getTerminatorEdges(); |
131 // If the current insertion point is at a conditional branch | |
132 // instruction, and the previous instruction is a compare | |
133 // instruction, then we move the insertion point before the compare | |
134 // instruction so as not to interfere with compare/branch fusing. | |
135 if (InstBr *Branch = llvm::dyn_cast<InstBr>(*InsertionPoint)) { | |
136 if (!Branch->isUnconditional()) { | |
137 if (InsertionPoint != Insts.begin()) { | |
138 --InsertionPoint; | |
139 if (!llvm::isa<InstIcmp>(*InsertionPoint) && | |
140 !llvm::isa<InstFcmp>(*InsertionPoint)) { | |
141 ++InsertionPoint; | |
142 } | |
143 } | |
144 } | |
145 } | |
114 | 146 |
115 // Consider every out-edge. | 147 // Consider every out-edge. |
116 for (NodeList::const_iterator I1 = OutEdges.begin(), E1 = OutEdges.end(); | 148 for (NodeList::const_iterator I1 = OutEdges.begin(), E1 = OutEdges.end(); |
117 I1 != E1; ++I1) { | 149 I1 != E1; ++I1) { |
118 CfgNode *Target = *I1; | 150 CfgNode *Target = *I1; |
119 // Consider every Phi instruction at the out-edge. | 151 // Consider every Phi instruction at the out-edge. |
120 for (PhiList::const_iterator I2 = Target->Phis.begin(), | 152 for (PhiList::const_iterator I2 = Target->Phis.begin(), |
121 E2 = Target->Phis.end(); | 153 E2 = Target->Phis.end(); |
122 I2 != E2; ++I2) { | 154 I2 != E2; ++I2) { |
123 Operand *Operand = (*I2)->getOperandForTarget(this); | 155 Operand *Operand = (*I2)->getOperandForTarget(this); |
(...skipping 14 matching lines...) Expand all Loading... | |
138 } | 170 } |
139 } | 171 } |
140 | 172 |
141 // Deletes the phi instructions after the loads and stores are placed. | 173 // Deletes the phi instructions after the loads and stores are placed. |
142 void CfgNode::deletePhis() { | 174 void CfgNode::deletePhis() { |
143 for (PhiList::iterator I = Phis.begin(), E = Phis.end(); I != E; ++I) { | 175 for (PhiList::iterator I = Phis.begin(), E = Phis.end(); I != E; ++I) { |
144 (*I)->setDeleted(); | 176 (*I)->setDeleted(); |
145 } | 177 } |
146 } | 178 } |
147 | 179 |
180 // Does address mode optimization. Pass each instruction to the | |
181 // TargetLowering object. If it returns a new instruction | |
182 // (representing the optimized address mode), then insert the new | |
183 // instruction and delete the old. | |
184 void CfgNode::doAddressOpt() { | |
185 TargetLowering *Target = Func->getTarget(); | |
186 LoweringContext &Context = Target->getContext(); | |
187 Context.init(this); | |
188 while (!Context.atEnd()) { | |
189 Target->doAddressOpt(); | |
190 } | |
191 } | |
192 | |
148 // Drives the target lowering. Passes the current instruction and the | 193 // Drives the target lowering. Passes the current instruction and the |
149 // next non-deleted instruction for target lowering. | 194 // next non-deleted instruction for target lowering. |
150 void CfgNode::genCode() { | 195 void CfgNode::genCode() { |
151 TargetLowering *Target = Func->getTarget(); | 196 TargetLowering *Target = Func->getTarget(); |
152 LoweringContext &Context = Target->getContext(); | 197 LoweringContext &Context = Target->getContext(); |
153 // Lower only the regular instructions. Defer the Phi instructions. | 198 // Lower only the regular instructions. Defer the Phi instructions. |
154 Context.init(this); | 199 Context.init(this); |
155 while (!Context.atEnd()) { | 200 while (!Context.atEnd()) { |
156 InstList::iterator Orig = Context.getCur(); | 201 InstList::iterator Orig = Context.getCur(); |
157 if (llvm::isa<InstRet>(*Orig)) | 202 if (llvm::isa<InstRet>(*Orig)) |
158 setHasReturn(); | 203 setHasReturn(); |
159 Target->lower(); | 204 Target->lower(); |
160 // Ensure target lowering actually moved the cursor. | 205 // Ensure target lowering actually moved the cursor. |
161 assert(Context.getCur() != Orig); | 206 assert(Context.getCur() != Orig); |
162 } | 207 } |
163 } | 208 } |
164 | 209 |
210 void CfgNode::livenessLightweight() { | |
211 SizeT NumVars = Func->getNumVariables(); | |
212 llvm::BitVector Live(NumVars); | |
213 // Process regular instructions in reverse order. | |
214 for (InstList::const_reverse_iterator I = Insts.rbegin(), E = Insts.rend(); | |
215 I != E; ++I) { | |
216 (*I)->livenessLightweight(Live); | |
217 } | |
218 for (PhiList::const_iterator I = Phis.begin(), E = Phis.end(); I != E; ++I) { | |
219 (*I)->livenessLightweight(Live); | |
220 } | |
221 } | |
222 | |
223 // Performs liveness analysis on the block. Returns true if the | |
224 // incoming liveness changed from before, false if it stayed the same. | |
225 // (If it changes, the node's predecessors need to be processed | |
226 // again.) | |
227 bool CfgNode::liveness(Liveness *Liveness) { | |
228 SizeT NumVars = Liveness->getLocalSize(this); | |
229 llvm::BitVector Live(NumVars); | |
230 // Mark the beginning and ending of each variable's live range | |
231 // with the sentinel instruction number 0. | |
232 std::vector<int> &LiveBegin = Liveness->getLiveBegin(this); | |
233 std::vector<int> &LiveEnd = Liveness->getLiveEnd(this); | |
234 LiveBegin.assign(NumVars, 0); | |
235 LiveEnd.assign(NumVars, 0); | |
236 // Initialize Live to be the union of all successors' LiveIn. | |
237 for (NodeList::const_iterator I = OutEdges.begin(), E = OutEdges.end(); | |
238 I != E; ++I) { | |
239 CfgNode *Succ = *I; | |
240 Live |= Liveness->getLiveIn(Succ); | |
241 // Mark corresponding argument of phis in successor as live. | |
242 for (PhiList::const_iterator I1 = Succ->Phis.begin(), E1 = Succ->Phis.end(); | |
243 I1 != E1; ++I1) { | |
244 (*I1)->livenessPhiOperand(Live, this, Liveness); | |
245 } | |
246 } | |
247 Liveness->getLiveOut(this) = Live; | |
248 | |
249 // Process regular instructions in reverse order. | |
250 for (InstList::const_reverse_iterator I = Insts.rbegin(), E = Insts.rend(); | |
251 I != E; ++I) { | |
252 (*I)->liveness((*I)->getNumber(), Live, Liveness, this); | |
253 } | |
254 // Process phis in forward order so that we can override the | |
255 // instruction number to be that of the earliest phi instruction in | |
256 // the block. | |
257 int32_t FirstPhiNumber = 0; // sentinel value | |
258 for (PhiList::const_iterator I = Phis.begin(), E = Phis.end(); I != E; ++I) { | |
259 if (FirstPhiNumber <= 0) | |
jvoung (off chromium)
2014/05/30 15:41:31
nit: could be a strict == test, since you're just
Jim Stichnoth
2014/05/30 23:06:18
As it turns out, the <= test also makes us ignore
| |
260 FirstPhiNumber = (*I)->getNumber(); | |
261 (*I)->liveness(FirstPhiNumber, Live, Liveness, this); | |
262 } | |
263 | |
264 // When using the sparse representation, after traversing the | |
265 // instructions in the block, the Live bitvector should only contain | |
266 // set bits for global variables upon block entry. We validate this | |
267 // by shrinking the Live vector and then testing it against the | |
268 // pre-shrunk version. (The shrinking is required, but the | |
269 // validation is not.) | |
270 llvm::BitVector LiveOrig = Live; | |
271 Live.resize(Liveness->getGlobalSize()); | |
272 // Non-global arguments in the entry node are allowed to be live on | |
273 // entry. | |
274 bool IsEntry = (Func->getEntryNode() == this); | |
275 if (!(IsEntry || Live == LiveOrig)) { | |
276 // This is a fatal liveness consistency error. Print some | |
277 // diagnostics and abort. | |
278 Ostream &Str = Func->getContext()->getStrDump(); | |
279 Func->setCurrentNode(NULL); | |
280 Str << "LiveOrig-Live ="; | |
281 for (SizeT i = Live.size(); i < LiveOrig.size(); ++i) { | |
282 if (LiveOrig.test(i)) { | |
283 Str << " "; | |
284 Liveness->getVariable(i, this)->dump(Func); | |
285 } | |
286 } | |
287 Str << "\n"; | |
288 llvm_unreachable("Fatal inconsistency in liveness analysis"); | |
289 } | |
290 | |
291 bool Changed = false; | |
292 llvm::BitVector &LiveIn = Liveness->getLiveIn(this); | |
293 // Add in current LiveIn | |
294 Live |= LiveIn; | |
295 // Check result, set LiveIn=Live | |
296 Changed = (Live != LiveIn); | |
297 if (Changed) | |
298 LiveIn = Live; | |
299 return Changed; | |
300 } | |
301 | |
302 // Now that basic liveness is complete, remove dead instructions that | |
303 // were tentatively marked as dead, and compute actual live ranges. | |
304 // It is assumed that within a single basic block, a live range begins | |
305 // at most once and ends at most once. This is certainly true for | |
306 // pure SSA form. It is also true once phis are lowered, since each | |
307 // assignment to the phi-based temporary is in a different basic | |
308 // block, and there is a single read that ends the live in the basic | |
309 // block that contained the actual phi instruction. | |
310 void CfgNode::livenessPostprocess(LivenessMode Mode, Liveness *Liveness) { | |
311 int32_t FirstInstNum = 0; | |
312 int32_t LastInstNum = 0; | |
313 // Process phis in any order. Process only Dest operands. | |
314 for (PhiList::const_iterator I = Phis.begin(), E = Phis.end(); I != E; ++I) { | |
315 InstPhi *Inst = *I; | |
316 Inst->deleteIfDead(); | |
317 if (Inst->isDeleted()) | |
318 continue; | |
319 if (FirstInstNum <= 0) | |
320 FirstInstNum = Inst->getNumber(); | |
321 assert(Inst->getNumber() > LastInstNum); | |
322 LastInstNum = Inst->getNumber(); | |
323 } | |
324 // Process instructions | |
325 for (InstList::const_iterator I = Insts.begin(), E = Insts.end(); I != E; | |
326 ++I) { | |
327 Inst *Inst = *I; | |
328 Inst->deleteIfDead(); | |
329 if (Inst->isDeleted()) | |
330 continue; | |
331 if (FirstInstNum <= 0) | |
332 FirstInstNum = Inst->getNumber(); | |
333 assert(Inst->getNumber() > LastInstNum); | |
334 LastInstNum = Inst->getNumber(); | |
335 // Create fake live ranges for a Kill instruction, but only if the | |
336 // linked instruction is still alive. | |
337 if (Mode == Liveness_Intervals) { | |
338 if (InstFakeKill *Kill = llvm::dyn_cast<InstFakeKill>(Inst)) { | |
339 if (!Kill->getLinked()->isDeleted()) { | |
340 SizeT NumSrcs = Inst->getSrcSize(); | |
341 for (SizeT i = 0; i < NumSrcs; ++i) { | |
342 Variable *Var = llvm::cast<Variable>(Inst->getSrc(i)); | |
343 int32_t InstNumber = Inst->getNumber(); | |
344 Liveness->addLiveRange(Var, InstNumber, InstNumber, 1); | |
345 } | |
346 } | |
347 } | |
348 } | |
349 } | |
350 if (Mode != Liveness_Intervals) | |
351 return; | |
352 | |
353 SizeT NumVars = Liveness->getLocalSize(this); | |
354 SizeT NumGlobals = Liveness->getGlobalSize(); | |
355 llvm::BitVector &LiveIn = Liveness->getLiveIn(this); | |
356 llvm::BitVector &LiveOut = Liveness->getLiveOut(this); | |
357 std::vector<int> &LiveBegin = Liveness->getLiveBegin(this); | |
358 std::vector<int> &LiveEnd = Liveness->getLiveEnd(this); | |
359 for (SizeT i = 0; i < NumVars; ++i) { | |
360 // Deal with the case where the variable is both live-in and | |
361 // live-out, but LiveEnd comes before LiveBegin. In this case, we | |
362 // need to add two segments to the live range because there is a | |
363 // hole in the middle. This would typically happen as a result of | |
364 // phi lowering in the presence of loopback edges. | |
365 bool IsGlobal = (i < NumGlobals); | |
366 if (IsGlobal && LiveIn[i] && LiveOut[i] && LiveBegin[i] > LiveEnd[i]) { | |
367 Variable *Var = Liveness->getVariable(i, this); | |
368 Liveness->addLiveRange(Var, FirstInstNum, LiveEnd[i], 1); | |
369 Liveness->addLiveRange(Var, LiveBegin[i], LastInstNum + 1, 1); | |
370 continue; | |
371 } | |
372 int32_t Begin = (IsGlobal && LiveIn[i]) ? FirstInstNum : LiveBegin[i]; | |
373 int32_t End = (IsGlobal && LiveOut[i]) ? LastInstNum + 1 : LiveEnd[i]; | |
374 if (Begin <= 0 && End <= 0) | |
375 continue; | |
376 if (Begin <= FirstInstNum) | |
377 Begin = FirstInstNum; | |
378 if (End <= 0) | |
379 End = LastInstNum + 1; | |
380 Variable *Var = Liveness->getVariable(i, this); | |
381 Liveness->addLiveRange(Var, Begin, End, 1); | |
382 } | |
383 } | |
384 | |
165 // ======================== Dump routines ======================== // | 385 // ======================== Dump routines ======================== // |
166 | 386 |
167 void CfgNode::emit(Cfg *Func) const { | 387 void CfgNode::emit(Cfg *Func) const { |
168 Func->setCurrentNode(this); | 388 Func->setCurrentNode(this); |
169 Ostream &Str = Func->getContext()->getStrEmit(); | 389 Ostream &Str = Func->getContext()->getStrEmit(); |
170 if (Func->getEntryNode() == this) { | 390 if (Func->getEntryNode() == this) { |
171 Str << Func->getContext()->mangleName(Func->getFunctionName()) << ":\n"; | 391 Str << Func->getContext()->mangleName(Func->getFunctionName()) << ":\n"; |
172 } | 392 } |
173 Str << getAsmName() << ":\n"; | 393 Str << getAsmName() << ":\n"; |
174 for (PhiList::const_iterator I = Phis.begin(), E = Phis.end(); I != E; ++I) { | 394 for (PhiList::const_iterator I = Phis.begin(), E = Phis.end(); I != E; ++I) { |
(...skipping 12 matching lines...) Expand all Loading... | |
187 // suppress them. | 407 // suppress them. |
188 if (Inst->isRedundantAssign()) | 408 if (Inst->isRedundantAssign()) |
189 continue; | 409 continue; |
190 (*I)->emit(Func); | 410 (*I)->emit(Func); |
191 } | 411 } |
192 } | 412 } |
193 | 413 |
194 void CfgNode::dump(Cfg *Func) const { | 414 void CfgNode::dump(Cfg *Func) const { |
195 Func->setCurrentNode(this); | 415 Func->setCurrentNode(this); |
196 Ostream &Str = Func->getContext()->getStrDump(); | 416 Ostream &Str = Func->getContext()->getStrDump(); |
417 Liveness *Liveness = Func->getLiveness(); | |
197 if (Func->getContext()->isVerbose(IceV_Instructions)) { | 418 if (Func->getContext()->isVerbose(IceV_Instructions)) { |
198 Str << getName() << ":\n"; | 419 Str << getName() << ":\n"; |
199 } | 420 } |
200 // Dump list of predecessor nodes. | 421 // Dump list of predecessor nodes. |
201 if (Func->getContext()->isVerbose(IceV_Preds) && !InEdges.empty()) { | 422 if (Func->getContext()->isVerbose(IceV_Preds) && !InEdges.empty()) { |
202 Str << " // preds = "; | 423 Str << " // preds = "; |
203 for (NodeList::const_iterator I = InEdges.begin(), E = InEdges.end(); | 424 for (NodeList::const_iterator I = InEdges.begin(), E = InEdges.end(); |
204 I != E; ++I) { | 425 I != E; ++I) { |
205 if (I != InEdges.begin()) | 426 if (I != InEdges.begin()) |
206 Str << ", "; | 427 Str << ", "; |
207 Str << "%" << (*I)->getName(); | 428 Str << "%" << (*I)->getName(); |
208 } | 429 } |
209 Str << "\n"; | 430 Str << "\n"; |
210 } | 431 } |
432 // Dump the live-in variables. | |
433 llvm::BitVector LiveIn; | |
434 if (Liveness) | |
435 LiveIn = Liveness->getLiveIn(this); | |
436 if (Func->getContext()->isVerbose(IceV_Liveness) && !LiveIn.empty()) { | |
437 Str << " // LiveIn:"; | |
438 for (SizeT i = 0; i < LiveIn.size(); ++i) { | |
439 if (LiveIn[i]) { | |
440 Str << " %" << Liveness->getVariable(i, this)->getName(); | |
441 } | |
442 } | |
443 Str << "\n"; | |
444 } | |
211 // Dump each instruction. | 445 // Dump each instruction. |
212 if (Func->getContext()->isVerbose(IceV_Instructions)) { | 446 if (Func->getContext()->isVerbose(IceV_Instructions)) { |
213 for (PhiList::const_iterator I = Phis.begin(), E = Phis.end(); I != E; | 447 for (PhiList::const_iterator I = Phis.begin(), E = Phis.end(); I != E; |
214 ++I) { | 448 ++I) { |
215 const Inst *Inst = *I; | 449 const Inst *Inst = *I; |
216 Inst->dumpDecorated(Func); | 450 Inst->dumpDecorated(Func); |
217 } | 451 } |
218 InstList::const_iterator I = Insts.begin(), E = Insts.end(); | 452 InstList::const_iterator I = Insts.begin(), E = Insts.end(); |
219 while (I != E) { | 453 while (I != E) { |
220 Inst *Inst = *I++; | 454 Inst *Inst = *I++; |
221 Inst->dumpDecorated(Func); | 455 Inst->dumpDecorated(Func); |
222 } | 456 } |
223 } | 457 } |
458 // Dump the live-out variables. | |
459 llvm::BitVector LiveOut; | |
460 if (Liveness) | |
461 LiveOut = Liveness->getLiveOut(this); | |
462 if (Func->getContext()->isVerbose(IceV_Liveness) && !LiveOut.empty()) { | |
463 Str << " // LiveOut:"; | |
464 for (SizeT i = 0; i < LiveOut.size(); ++i) { | |
465 if (LiveOut[i]) { | |
466 Str << " %" << Liveness->getVariable(i, this)->getName(); | |
467 } | |
468 } | |
469 Str << "\n"; | |
470 } | |
224 // Dump list of successor nodes. | 471 // Dump list of successor nodes. |
225 if (Func->getContext()->isVerbose(IceV_Succs)) { | 472 if (Func->getContext()->isVerbose(IceV_Succs)) { |
226 Str << " // succs = "; | 473 Str << " // succs = "; |
227 for (NodeList::const_iterator I = OutEdges.begin(), E = OutEdges.end(); | 474 for (NodeList::const_iterator I = OutEdges.begin(), E = OutEdges.end(); |
228 I != E; ++I) { | 475 I != E; ++I) { |
229 if (I != OutEdges.begin()) | 476 if (I != OutEdges.begin()) |
230 Str << ", "; | 477 Str << ", "; |
231 Str << "%" << (*I)->getName(); | 478 Str << "%" << (*I)->getName(); |
232 } | 479 } |
233 Str << "\n"; | 480 Str << "\n"; |
234 } | 481 } |
235 } | 482 } |
236 | 483 |
237 } // end of namespace Ice | 484 } // end of namespace Ice |
OLD | NEW |