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 if ((*I)->isDeleted()) |
| 217 continue; |
| 218 (*I)->livenessLightweight(Live); |
| 219 } |
| 220 for (PhiList::const_iterator I = Phis.begin(), E = Phis.end(); I != E; ++I) { |
| 221 if ((*I)->isDeleted()) |
| 222 continue; |
| 223 (*I)->livenessLightweight(Live); |
| 224 } |
| 225 } |
| 226 |
| 227 // Performs liveness analysis on the block. Returns true if the |
| 228 // incoming liveness changed from before, false if it stayed the same. |
| 229 // (If it changes, the node's predecessors need to be processed |
| 230 // again.) |
| 231 bool CfgNode::liveness(Liveness *Liveness) { |
| 232 SizeT NumVars = Liveness->getNumVarsInNode(this); |
| 233 llvm::BitVector Live(NumVars); |
| 234 // Mark the beginning and ending of each variable's live range |
| 235 // with the sentinel instruction number 0. |
| 236 std::vector<InstNumberT> &LiveBegin = Liveness->getLiveBegin(this); |
| 237 std::vector<InstNumberT> &LiveEnd = Liveness->getLiveEnd(this); |
| 238 LiveBegin.assign(NumVars, Inst::NumberSentinel); |
| 239 LiveEnd.assign(NumVars, Inst::NumberSentinel); |
| 240 // Initialize Live to be the union of all successors' LiveIn. |
| 241 for (NodeList::const_iterator I = OutEdges.begin(), E = OutEdges.end(); |
| 242 I != E; ++I) { |
| 243 CfgNode *Succ = *I; |
| 244 Live |= Liveness->getLiveIn(Succ); |
| 245 // Mark corresponding argument of phis in successor as live. |
| 246 for (PhiList::const_iterator I1 = Succ->Phis.begin(), E1 = Succ->Phis.end(); |
| 247 I1 != E1; ++I1) { |
| 248 (*I1)->livenessPhiOperand(Live, this, Liveness); |
| 249 } |
| 250 } |
| 251 Liveness->getLiveOut(this) = Live; |
| 252 |
| 253 // Process regular instructions in reverse order. |
| 254 for (InstList::const_reverse_iterator I = Insts.rbegin(), E = Insts.rend(); |
| 255 I != E; ++I) { |
| 256 if ((*I)->isDeleted()) |
| 257 continue; |
| 258 (*I)->liveness((*I)->getNumber(), Live, Liveness, this); |
| 259 } |
| 260 // Process phis in forward order so that we can override the |
| 261 // instruction number to be that of the earliest phi instruction in |
| 262 // the block. |
| 263 InstNumberT FirstPhiNumber = Inst::NumberSentinel; |
| 264 for (PhiList::const_iterator I = Phis.begin(), E = Phis.end(); I != E; ++I) { |
| 265 if ((*I)->isDeleted()) |
| 266 continue; |
| 267 if (FirstPhiNumber == Inst::NumberSentinel) |
| 268 FirstPhiNumber = (*I)->getNumber(); |
| 269 (*I)->liveness(FirstPhiNumber, Live, Liveness, this); |
| 270 } |
| 271 |
| 272 // When using the sparse representation, after traversing the |
| 273 // instructions in the block, the Live bitvector should only contain |
| 274 // set bits for global variables upon block entry. We validate this |
| 275 // by shrinking the Live vector and then testing it against the |
| 276 // pre-shrunk version. (The shrinking is required, but the |
| 277 // validation is not.) |
| 278 llvm::BitVector LiveOrig = Live; |
| 279 Live.resize(Liveness->getNumGlobalVars()); |
| 280 // Non-global arguments in the entry node are allowed to be live on |
| 281 // entry. |
| 282 bool IsEntry = (Func->getEntryNode() == this); |
| 283 if (!(IsEntry || Live == LiveOrig)) { |
| 284 // This is a fatal liveness consistency error. Print some |
| 285 // diagnostics and abort. |
| 286 Ostream &Str = Func->getContext()->getStrDump(); |
| 287 Func->setCurrentNode(NULL); |
| 288 Str << "LiveOrig-Live ="; |
| 289 for (SizeT i = Live.size(); i < LiveOrig.size(); ++i) { |
| 290 if (LiveOrig.test(i)) { |
| 291 Str << " "; |
| 292 Liveness->getVariable(i, this)->dump(Func); |
| 293 } |
| 294 } |
| 295 Str << "\n"; |
| 296 llvm_unreachable("Fatal inconsistency in liveness analysis"); |
| 297 } |
| 298 |
| 299 bool Changed = false; |
| 300 llvm::BitVector &LiveIn = Liveness->getLiveIn(this); |
| 301 // Add in current LiveIn |
| 302 Live |= LiveIn; |
| 303 // Check result, set LiveIn=Live |
| 304 Changed = (Live != LiveIn); |
| 305 if (Changed) |
| 306 LiveIn = Live; |
| 307 return Changed; |
| 308 } |
| 309 |
| 310 // Now that basic liveness is complete, remove dead instructions that |
| 311 // were tentatively marked as dead, and compute actual live ranges. |
| 312 // It is assumed that within a single basic block, a live range begins |
| 313 // at most once and ends at most once. This is certainly true for |
| 314 // pure SSA form. It is also true once phis are lowered, since each |
| 315 // assignment to the phi-based temporary is in a different basic |
| 316 // block, and there is a single read that ends the live in the basic |
| 317 // block that contained the actual phi instruction. |
| 318 void CfgNode::livenessPostprocess(LivenessMode Mode, Liveness *Liveness) { |
| 319 InstNumberT FirstInstNum = Inst::NumberSentinel; |
| 320 InstNumberT LastInstNum = Inst::NumberSentinel; |
| 321 // Process phis in any order. Process only Dest operands. |
| 322 for (PhiList::const_iterator I = Phis.begin(), E = Phis.end(); I != E; ++I) { |
| 323 InstPhi *Inst = *I; |
| 324 Inst->deleteIfDead(); |
| 325 if (Inst->isDeleted()) |
| 326 continue; |
| 327 if (FirstInstNum == Inst::NumberSentinel) |
| 328 FirstInstNum = Inst->getNumber(); |
| 329 assert(Inst->getNumber() > LastInstNum); |
| 330 LastInstNum = Inst->getNumber(); |
| 331 } |
| 332 // Process instructions |
| 333 for (InstList::const_iterator I = Insts.begin(), E = Insts.end(); I != E; |
| 334 ++I) { |
| 335 Inst *Inst = *I; |
| 336 Inst->deleteIfDead(); |
| 337 if (Inst->isDeleted()) |
| 338 continue; |
| 339 if (FirstInstNum == Inst::NumberSentinel) |
| 340 FirstInstNum = Inst->getNumber(); |
| 341 assert(Inst->getNumber() > LastInstNum); |
| 342 LastInstNum = Inst->getNumber(); |
| 343 // Create fake live ranges for a Kill instruction, but only if the |
| 344 // linked instruction is still alive. |
| 345 if (Mode == Liveness_Intervals) { |
| 346 if (InstFakeKill *Kill = llvm::dyn_cast<InstFakeKill>(Inst)) { |
| 347 if (!Kill->getLinked()->isDeleted()) { |
| 348 SizeT NumSrcs = Inst->getSrcSize(); |
| 349 for (SizeT i = 0; i < NumSrcs; ++i) { |
| 350 Variable *Var = llvm::cast<Variable>(Inst->getSrc(i)); |
| 351 InstNumberT InstNumber = Inst->getNumber(); |
| 352 Liveness->addLiveRange(Var, InstNumber, InstNumber, 1); |
| 353 } |
| 354 } |
| 355 } |
| 356 } |
| 357 } |
| 358 if (Mode != Liveness_Intervals) |
| 359 return; |
| 360 |
| 361 SizeT NumVars = Liveness->getNumVarsInNode(this); |
| 362 SizeT NumGlobals = Liveness->getNumGlobalVars(); |
| 363 llvm::BitVector &LiveIn = Liveness->getLiveIn(this); |
| 364 llvm::BitVector &LiveOut = Liveness->getLiveOut(this); |
| 365 std::vector<InstNumberT> &LiveBegin = Liveness->getLiveBegin(this); |
| 366 std::vector<InstNumberT> &LiveEnd = Liveness->getLiveEnd(this); |
| 367 for (SizeT i = 0; i < NumVars; ++i) { |
| 368 // Deal with the case where the variable is both live-in and |
| 369 // live-out, but LiveEnd comes before LiveBegin. In this case, we |
| 370 // need to add two segments to the live range because there is a |
| 371 // hole in the middle. This would typically happen as a result of |
| 372 // phi lowering in the presence of loopback edges. |
| 373 bool IsGlobal = (i < NumGlobals); |
| 374 if (IsGlobal && LiveIn[i] && LiveOut[i] && LiveBegin[i] > LiveEnd[i]) { |
| 375 Variable *Var = Liveness->getVariable(i, this); |
| 376 Liveness->addLiveRange(Var, FirstInstNum, LiveEnd[i], 1); |
| 377 Liveness->addLiveRange(Var, LiveBegin[i], LastInstNum + 1, 1); |
| 378 continue; |
| 379 } |
| 380 InstNumberT Begin = (IsGlobal && LiveIn[i]) ? FirstInstNum : LiveBegin[i]; |
| 381 InstNumberT End = (IsGlobal && LiveOut[i]) ? LastInstNum + 1 : LiveEnd[i]; |
| 382 if (Begin == Inst::NumberSentinel && End == Inst::NumberSentinel) |
| 383 continue; |
| 384 if (Begin <= FirstInstNum) |
| 385 Begin = FirstInstNum; |
| 386 if (End == Inst::NumberSentinel) |
| 387 End = LastInstNum + 1; |
| 388 Variable *Var = Liveness->getVariable(i, this); |
| 389 Liveness->addLiveRange(Var, Begin, End, 1); |
| 390 } |
| 391 } |
| 392 |
165 // ======================== Dump routines ======================== // | 393 // ======================== Dump routines ======================== // |
166 | 394 |
167 void CfgNode::emit(Cfg *Func) const { | 395 void CfgNode::emit(Cfg *Func) const { |
168 Func->setCurrentNode(this); | 396 Func->setCurrentNode(this); |
169 Ostream &Str = Func->getContext()->getStrEmit(); | 397 Ostream &Str = Func->getContext()->getStrEmit(); |
170 if (Func->getEntryNode() == this) { | 398 if (Func->getEntryNode() == this) { |
171 Str << Func->getContext()->mangleName(Func->getFunctionName()) << ":\n"; | 399 Str << Func->getContext()->mangleName(Func->getFunctionName()) << ":\n"; |
172 } | 400 } |
173 Str << getAsmName() << ":\n"; | 401 Str << getAsmName() << ":\n"; |
174 for (PhiList::const_iterator I = Phis.begin(), E = Phis.end(); I != E; ++I) { | 402 for (PhiList::const_iterator I = Phis.begin(), E = Phis.end(); I != E; ++I) { |
(...skipping 12 matching lines...) Expand all Loading... |
187 // suppress them. | 415 // suppress them. |
188 if (Inst->isRedundantAssign()) | 416 if (Inst->isRedundantAssign()) |
189 continue; | 417 continue; |
190 (*I)->emit(Func); | 418 (*I)->emit(Func); |
191 } | 419 } |
192 } | 420 } |
193 | 421 |
194 void CfgNode::dump(Cfg *Func) const { | 422 void CfgNode::dump(Cfg *Func) const { |
195 Func->setCurrentNode(this); | 423 Func->setCurrentNode(this); |
196 Ostream &Str = Func->getContext()->getStrDump(); | 424 Ostream &Str = Func->getContext()->getStrDump(); |
| 425 Liveness *Liveness = Func->getLiveness(); |
197 if (Func->getContext()->isVerbose(IceV_Instructions)) { | 426 if (Func->getContext()->isVerbose(IceV_Instructions)) { |
198 Str << getName() << ":\n"; | 427 Str << getName() << ":\n"; |
199 } | 428 } |
200 // Dump list of predecessor nodes. | 429 // Dump list of predecessor nodes. |
201 if (Func->getContext()->isVerbose(IceV_Preds) && !InEdges.empty()) { | 430 if (Func->getContext()->isVerbose(IceV_Preds) && !InEdges.empty()) { |
202 Str << " // preds = "; | 431 Str << " // preds = "; |
203 for (NodeList::const_iterator I = InEdges.begin(), E = InEdges.end(); | 432 for (NodeList::const_iterator I = InEdges.begin(), E = InEdges.end(); |
204 I != E; ++I) { | 433 I != E; ++I) { |
205 if (I != InEdges.begin()) | 434 if (I != InEdges.begin()) |
206 Str << ", "; | 435 Str << ", "; |
207 Str << "%" << (*I)->getName(); | 436 Str << "%" << (*I)->getName(); |
208 } | 437 } |
209 Str << "\n"; | 438 Str << "\n"; |
210 } | 439 } |
| 440 // Dump the live-in variables. |
| 441 llvm::BitVector LiveIn; |
| 442 if (Liveness) |
| 443 LiveIn = Liveness->getLiveIn(this); |
| 444 if (Func->getContext()->isVerbose(IceV_Liveness) && !LiveIn.empty()) { |
| 445 Str << " // LiveIn:"; |
| 446 for (SizeT i = 0; i < LiveIn.size(); ++i) { |
| 447 if (LiveIn[i]) { |
| 448 Str << " %" << Liveness->getVariable(i, this)->getName(); |
| 449 } |
| 450 } |
| 451 Str << "\n"; |
| 452 } |
211 // Dump each instruction. | 453 // Dump each instruction. |
212 if (Func->getContext()->isVerbose(IceV_Instructions)) { | 454 if (Func->getContext()->isVerbose(IceV_Instructions)) { |
213 for (PhiList::const_iterator I = Phis.begin(), E = Phis.end(); I != E; | 455 for (PhiList::const_iterator I = Phis.begin(), E = Phis.end(); I != E; |
214 ++I) { | 456 ++I) { |
215 const Inst *Inst = *I; | 457 const Inst *Inst = *I; |
216 Inst->dumpDecorated(Func); | 458 Inst->dumpDecorated(Func); |
217 } | 459 } |
218 InstList::const_iterator I = Insts.begin(), E = Insts.end(); | 460 InstList::const_iterator I = Insts.begin(), E = Insts.end(); |
219 while (I != E) { | 461 while (I != E) { |
220 Inst *Inst = *I++; | 462 Inst *Inst = *I++; |
221 Inst->dumpDecorated(Func); | 463 Inst->dumpDecorated(Func); |
222 } | 464 } |
223 } | 465 } |
| 466 // Dump the live-out variables. |
| 467 llvm::BitVector LiveOut; |
| 468 if (Liveness) |
| 469 LiveOut = Liveness->getLiveOut(this); |
| 470 if (Func->getContext()->isVerbose(IceV_Liveness) && !LiveOut.empty()) { |
| 471 Str << " // LiveOut:"; |
| 472 for (SizeT i = 0; i < LiveOut.size(); ++i) { |
| 473 if (LiveOut[i]) { |
| 474 Str << " %" << Liveness->getVariable(i, this)->getName(); |
| 475 } |
| 476 } |
| 477 Str << "\n"; |
| 478 } |
224 // Dump list of successor nodes. | 479 // Dump list of successor nodes. |
225 if (Func->getContext()->isVerbose(IceV_Succs)) { | 480 if (Func->getContext()->isVerbose(IceV_Succs)) { |
226 Str << " // succs = "; | 481 Str << " // succs = "; |
227 for (NodeList::const_iterator I = OutEdges.begin(), E = OutEdges.end(); | 482 for (NodeList::const_iterator I = OutEdges.begin(), E = OutEdges.end(); |
228 I != E; ++I) { | 483 I != E; ++I) { |
229 if (I != OutEdges.begin()) | 484 if (I != OutEdges.begin()) |
230 Str << ", "; | 485 Str << ", "; |
231 Str << "%" << (*I)->getName(); | 486 Str << "%" << (*I)->getName(); |
232 } | 487 } |
233 Str << "\n"; | 488 Str << "\n"; |
234 } | 489 } |
235 } | 490 } |
236 | 491 |
237 } // end of namespace Ice | 492 } // end of namespace Ice |
OLD | NEW |