Chromium Code Reviews| 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 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 via assert() that InsertionPoint is a terminator |
| 111 // instruction. Calling getTerminatorEdges() on a non-terminator | 128 // instruction. Calling getTerminatorEdges() on a non-terminator |
| 112 // instruction will cause an llvm_unreachable(). | 129 // instruction will cause an llvm_unreachable(). |
| 113 assert(((*InsertionPoint)->getTerminatorEdges(), true)); | 130 assert(((*InsertionPoint)->getTerminatorEdges(), true)); |
| 131 if (llvm::isa<InstBr>(*InsertionPoint)) { | |
| 132 if (InsertionPoint != Insts.begin()) { | |
| 133 --InsertionPoint; | |
| 134 if (!llvm::isa<InstIcmp>(*InsertionPoint) && | |
| 135 !llvm::isa<InstFcmp>(*InsertionPoint)) { | |
| 136 ++InsertionPoint; | |
| 137 } | |
| 138 } | |
| 139 } | |
|
JF
2014/05/25 22:50:50
Can you explain this?
Jim Stichnoth
2014/05/29 01:39:46
Done. Also modified the logic to look only for *c
| |
| 114 | 140 |
| 115 // Consider every out-edge. | 141 // Consider every out-edge. |
| 116 for (NodeList::const_iterator I1 = OutEdges.begin(), E1 = OutEdges.end(); | 142 for (NodeList::const_iterator I1 = OutEdges.begin(), E1 = OutEdges.end(); |
| 117 I1 != E1; ++I1) { | 143 I1 != E1; ++I1) { |
| 118 CfgNode *Target = *I1; | 144 CfgNode *Target = *I1; |
| 119 // Consider every Phi instruction at the out-edge. | 145 // Consider every Phi instruction at the out-edge. |
| 120 for (PhiList::const_iterator I2 = Target->Phis.begin(), | 146 for (PhiList::const_iterator I2 = Target->Phis.begin(), |
| 121 E2 = Target->Phis.end(); | 147 E2 = Target->Phis.end(); |
| 122 I2 != E2; ++I2) { | 148 I2 != E2; ++I2) { |
| 123 Operand *Operand = (*I2)->getOperandForTarget(this); | 149 Operand *Operand = (*I2)->getOperandForTarget(this); |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 138 } | 164 } |
| 139 } | 165 } |
| 140 | 166 |
| 141 // Deletes the phi instructions after the loads and stores are placed. | 167 // Deletes the phi instructions after the loads and stores are placed. |
| 142 void CfgNode::deletePhis() { | 168 void CfgNode::deletePhis() { |
| 143 for (PhiList::iterator I = Phis.begin(), E = Phis.end(); I != E; ++I) { | 169 for (PhiList::iterator I = Phis.begin(), E = Phis.end(); I != E; ++I) { |
| 144 (*I)->setDeleted(); | 170 (*I)->setDeleted(); |
| 145 } | 171 } |
| 146 } | 172 } |
| 147 | 173 |
| 174 // Does address mode optimization. Pass each instruction to the | |
| 175 // TargetLowering object. If it returns a new instruction | |
| 176 // (representing the optimized address mode), then insert the new | |
| 177 // instruction and delete the old. | |
| 178 void CfgNode::doAddressOpt() { | |
| 179 TargetLowering *Target = Func->getTarget(); | |
| 180 LoweringContext &Context = Target->getContext(); | |
| 181 Context.init(this); | |
| 182 while (!Context.atEnd()) { | |
| 183 Target->doAddressOpt(); | |
| 184 } | |
| 185 } | |
| 186 | |
| 148 // Drives the target lowering. Passes the current instruction and the | 187 // Drives the target lowering. Passes the current instruction and the |
| 149 // next non-deleted instruction for target lowering. | 188 // next non-deleted instruction for target lowering. |
| 150 void CfgNode::genCode() { | 189 void CfgNode::genCode() { |
| 151 TargetLowering *Target = Func->getTarget(); | 190 TargetLowering *Target = Func->getTarget(); |
| 152 LoweringContext &Context = Target->getContext(); | 191 LoweringContext &Context = Target->getContext(); |
| 153 // Lower only the regular instructions. Defer the Phi instructions. | 192 // Lower only the regular instructions. Defer the Phi instructions. |
| 154 Context.init(this); | 193 Context.init(this); |
| 155 while (!Context.atEnd()) { | 194 while (!Context.atEnd()) { |
| 156 InstList::iterator Orig = Context.getCur(); | 195 InstList::iterator Orig = Context.getCur(); |
| 157 if (llvm::isa<InstRet>(*Orig)) | 196 if (llvm::isa<InstRet>(*Orig)) |
| 158 setHasReturn(); | 197 setHasReturn(); |
| 159 Target->lower(); | 198 Target->lower(); |
| 160 // Ensure target lowering actually moved the cursor. | 199 // Ensure target lowering actually moved the cursor. |
| 161 assert(Context.getCur() != Orig); | 200 assert(Context.getCur() != Orig); |
| 162 } | 201 } |
| 163 } | 202 } |
| 164 | 203 |
| 204 // Performs liveness analysis on the block. Returns true if the | |
| 205 // incoming liveness changed from before, false if it stayed the same. | |
| 206 // (If it changes, the node's predecessors need to be processed | |
| 207 // again.) | |
| 208 bool CfgNode::liveness(LivenessMode Mode, Liveness *Liveness) { | |
| 209 SizeT NumVars; | |
| 210 if (Mode == Liveness_LREndLightweight) | |
| 211 NumVars = Func->getNumVariables(); | |
| 212 else | |
| 213 NumVars = Liveness->getLocalSize(this); | |
| 214 llvm::BitVector Live(NumVars); | |
| 215 if (Mode != Liveness_LREndLightweight) { | |
| 216 // Mark the beginning and ending of each variable's live range | |
| 217 // with the sentinel instruction number 0. | |
| 218 std::vector<int> &LiveBegin = Liveness->getLiveBegin(this); | |
| 219 std::vector<int> &LiveEnd = Liveness->getLiveEnd(this); | |
| 220 LiveBegin.assign(NumVars, 0); | |
| 221 LiveEnd.assign(NumVars, 0); | |
| 222 // Initialize Live to be the union of all successors' LiveIn. | |
| 223 for (NodeList::const_iterator I = OutEdges.begin(), E = OutEdges.end(); | |
| 224 I != E; ++I) { | |
| 225 CfgNode *Succ = *I; | |
| 226 Live |= Liveness->getLiveIn(Succ); | |
| 227 // Mark corresponding argument of phis in successor as live. | |
| 228 for (PhiList::const_iterator I1 = Succ->Phis.begin(), | |
| 229 E1 = Succ->Phis.end(); | |
| 230 I1 != E1; ++I1) { | |
| 231 (*I1)->livenessPhiOperand(Live, this, Liveness); | |
| 232 } | |
| 233 } | |
| 234 Liveness->getLiveOut(this) = Live; | |
| 235 } | |
| 236 | |
| 237 // Process regular instructions in reverse order. | |
| 238 for (InstList::const_reverse_iterator I = Insts.rbegin(), E = Insts.rend(); | |
| 239 I != E; ++I) { | |
| 240 (*I)->liveness(Mode, (*I)->getNumber(), Live, Liveness, this); | |
| 241 } | |
| 242 // Process phis in forward order so that we can override the | |
| 243 // instruction number to be that of the earliest phi instruction in | |
| 244 // the block. | |
| 245 int32_t FirstPhiNumber = 0; // sentinel value | |
| 246 for (PhiList::const_iterator I = Phis.begin(), E = Phis.end(); I != E; ++I) { | |
| 247 if (FirstPhiNumber <= 0) | |
| 248 FirstPhiNumber = (*I)->getNumber(); | |
| 249 (*I)->liveness(Mode, FirstPhiNumber, Live, Liveness, this); | |
| 250 } | |
| 251 | |
| 252 // When using the sparse representation, after traversing the | |
| 253 // instructions in the block, the Live bitvector should only contain | |
| 254 // set bits for global variables upon block entry. We validate this | |
| 255 // by shrinking the Live vector and then testing it against the | |
| 256 // pre-shrunk version. (The shrinking is required, but the | |
| 257 // validation is not.) | |
| 258 if (Mode != Liveness_LREndLightweight) { | |
| 259 llvm::BitVector LiveOrig = Live; | |
| 260 Live.resize(Liveness->getGlobalSize()); | |
| 261 // Non-global arguments in the entry node are allowed to be live on | |
| 262 // entry. | |
| 263 bool IsEntry = (Func->getEntryNode() == this); | |
| 264 assert(IsEntry || Live == LiveOrig); | |
| 265 // The following block helps debug why the previous assertion | |
| 266 // failed. | |
|
JF
2014/05/25 22:50:50
Shouldn't the block be before the assertion?
Jim Stichnoth
2014/05/29 01:39:46
Good point. Fixed this, including replacing the a
| |
| 267 if (!(IsEntry || Live == LiveOrig)) { | |
| 268 Ostream &Str = Func->getContext()->getStrDump(); | |
| 269 Func->setCurrentNode(NULL); | |
| 270 Str << "LiveOrig-Live ="; | |
| 271 for (SizeT i = Live.size(); i < LiveOrig.size(); ++i) { | |
| 272 if (LiveOrig.test(i)) { | |
| 273 Str << " "; | |
| 274 Liveness->getVariable(i, this)->dump(Func); | |
| 275 } | |
| 276 } | |
| 277 Str << "\n"; | |
| 278 } | |
| 279 } | |
| 280 | |
| 281 bool Changed = false; | |
| 282 if (Mode != Liveness_LREndLightweight) { | |
| 283 llvm::BitVector &LiveIn = Liveness->getLiveIn(this); | |
| 284 // Add in current LiveIn | |
| 285 Live |= LiveIn; | |
| 286 // Check result, set LiveIn=Live | |
| 287 Changed = (Live != LiveIn); | |
| 288 if (Changed) | |
| 289 LiveIn = Live; | |
| 290 } | |
| 291 return Changed; | |
| 292 } | |
| 293 | |
| 294 // Now that basic liveness is complete, remove dead instructions that | |
| 295 // were tentatively marked as dead, and compute actual live ranges. | |
| 296 // It is assumed that within a single basic block, a live range begins | |
| 297 // at most once and ends at most once. This is certainly true for | |
| 298 // pure SSA form. It is also true once phis are lowered, since each | |
| 299 // assignment to the phi-based temporary is in a different basic | |
| 300 // block, and there is a single read that ends the live in the basic | |
| 301 // block that contained the actual phi instruction. | |
| 302 void CfgNode::livenessPostprocess(LivenessMode Mode, Liveness *Liveness) { | |
| 303 int32_t FirstInstNum = 0; | |
| 304 int32_t LastInstNum = 0; | |
| 305 // Process phis in any order. Process only Dest operands. | |
| 306 for (PhiList::const_iterator I = Phis.begin(), E = Phis.end(); I != E; ++I) { | |
| 307 InstPhi *Inst = *I; | |
| 308 Inst->deleteIfDead(); | |
| 309 if (Inst->isDeleted()) | |
| 310 continue; | |
| 311 if (FirstInstNum <= 0) | |
| 312 FirstInstNum = Inst->getNumber(); | |
| 313 assert(Inst->getNumber() > LastInstNum); | |
| 314 LastInstNum = Inst->getNumber(); | |
| 315 } | |
| 316 // Process instructions | |
| 317 for (InstList::const_iterator I = Insts.begin(), E = Insts.end(); I != E; | |
| 318 ++I) { | |
| 319 Inst *Inst = *I; | |
| 320 Inst->deleteIfDead(); | |
| 321 if (Inst->isDeleted()) | |
| 322 continue; | |
| 323 if (FirstInstNum <= 0) | |
| 324 FirstInstNum = Inst->getNumber(); | |
| 325 assert(Inst->getNumber() > LastInstNum); | |
| 326 LastInstNum = Inst->getNumber(); | |
| 327 // Create fake live ranges for a Kill instruction, but only if the | |
| 328 // linked instruction is still alive. | |
| 329 if (Mode == Liveness_RangesFull) { | |
| 330 if (InstFakeKill *Kill = llvm::dyn_cast<InstFakeKill>(Inst)) { | |
| 331 if (!Kill->getLinked()->isDeleted()) { | |
| 332 SizeT NumSrcs = Inst->getSrcSize(); | |
| 333 for (SizeT i = 0; i < NumSrcs; ++i) { | |
| 334 Variable *Var = llvm::cast<Variable>(Inst->getSrc(i)); | |
| 335 int32_t InstNumber = Inst->getNumber(); | |
| 336 Liveness->addLiveRange(Var, InstNumber, InstNumber, 1); | |
| 337 } | |
| 338 } | |
| 339 } | |
| 340 } | |
| 341 } | |
| 342 if (Mode != Liveness_RangesFull) | |
| 343 return; | |
| 344 | |
| 345 SizeT NumVars = Liveness->getLocalSize(this); | |
| 346 SizeT NumGlobals = Liveness->getGlobalSize(); | |
| 347 llvm::BitVector &LiveIn = Liveness->getLiveIn(this); | |
| 348 llvm::BitVector &LiveOut = Liveness->getLiveOut(this); | |
| 349 std::vector<int> &LiveBegin = Liveness->getLiveBegin(this); | |
| 350 std::vector<int> &LiveEnd = Liveness->getLiveEnd(this); | |
| 351 for (SizeT i = 0; i < NumVars; ++i) { | |
| 352 // Deal with the case where the variable is both live-in and | |
| 353 // live-out, but LiveEnd comes before LiveBegin. In this case, we | |
| 354 // need to add two segments to the live range because there is a | |
| 355 // hole in the middle. This would typically happen as a result of | |
| 356 // phi lowering in the presence of loopback edges. | |
| 357 bool IsGlobal = (i < NumGlobals); | |
| 358 if (IsGlobal && LiveIn[i] && LiveOut[i] && LiveBegin[i] > LiveEnd[i]) { | |
| 359 Variable *Var = Liveness->getVariable(i, this); | |
| 360 Liveness->addLiveRange(Var, FirstInstNum, LiveEnd[i], 1); | |
| 361 Liveness->addLiveRange(Var, LiveBegin[i], LastInstNum + 1, 1); | |
| 362 continue; | |
| 363 } | |
| 364 int32_t Begin = (IsGlobal && LiveIn[i]) ? FirstInstNum : LiveBegin[i]; | |
| 365 int32_t End = (IsGlobal && LiveOut[i]) ? LastInstNum + 1 : LiveEnd[i]; | |
| 366 if (Begin <= 0 && End <= 0) | |
| 367 continue; | |
| 368 if (Begin <= FirstInstNum) | |
| 369 Begin = FirstInstNum; | |
| 370 if (End <= 0) | |
| 371 End = LastInstNum + 1; | |
| 372 Variable *Var = Liveness->getVariable(i, this); | |
| 373 Liveness->addLiveRange(Var, Begin, End, 1); | |
| 374 } | |
| 375 } | |
| 376 | |
| 165 // ======================== Dump routines ======================== // | 377 // ======================== Dump routines ======================== // |
| 166 | 378 |
| 167 void CfgNode::emit(Cfg *Func) const { | 379 void CfgNode::emit(Cfg *Func) const { |
| 168 Func->setCurrentNode(this); | 380 Func->setCurrentNode(this); |
| 169 Ostream &Str = Func->getContext()->getStrEmit(); | 381 Ostream &Str = Func->getContext()->getStrEmit(); |
| 170 if (Func->getEntryNode() == this) { | 382 if (Func->getEntryNode() == this) { |
| 171 Str << Func->getContext()->mangleName(Func->getFunctionName()) << ":\n"; | 383 Str << Func->getContext()->mangleName(Func->getFunctionName()) << ":\n"; |
| 172 } | 384 } |
| 173 Str << getAsmName() << ":\n"; | 385 Str << getAsmName() << ":\n"; |
| 174 for (PhiList::const_iterator I = Phis.begin(), E = Phis.end(); I != E; ++I) { | 386 for (PhiList::const_iterator I = Phis.begin(), E = Phis.end(); I != E; ++I) { |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 187 // suppress them. | 399 // suppress them. |
| 188 if (Inst->isRedundantAssign()) | 400 if (Inst->isRedundantAssign()) |
| 189 continue; | 401 continue; |
| 190 (*I)->emit(Func); | 402 (*I)->emit(Func); |
| 191 } | 403 } |
| 192 } | 404 } |
| 193 | 405 |
| 194 void CfgNode::dump(Cfg *Func) const { | 406 void CfgNode::dump(Cfg *Func) const { |
| 195 Func->setCurrentNode(this); | 407 Func->setCurrentNode(this); |
| 196 Ostream &Str = Func->getContext()->getStrDump(); | 408 Ostream &Str = Func->getContext()->getStrDump(); |
| 409 Liveness *Liveness = Func->getLiveness(); | |
| 197 if (Func->getContext()->isVerbose(IceV_Instructions)) { | 410 if (Func->getContext()->isVerbose(IceV_Instructions)) { |
| 198 Str << getName() << ":\n"; | 411 Str << getName() << ":\n"; |
| 199 } | 412 } |
| 200 // Dump list of predecessor nodes. | 413 // Dump list of predecessor nodes. |
| 201 if (Func->getContext()->isVerbose(IceV_Preds) && !InEdges.empty()) { | 414 if (Func->getContext()->isVerbose(IceV_Preds) && !InEdges.empty()) { |
| 202 Str << " // preds = "; | 415 Str << " // preds = "; |
| 203 for (NodeList::const_iterator I = InEdges.begin(), E = InEdges.end(); | 416 for (NodeList::const_iterator I = InEdges.begin(), E = InEdges.end(); |
| 204 I != E; ++I) { | 417 I != E; ++I) { |
| 205 if (I != InEdges.begin()) | 418 if (I != InEdges.begin()) |
| 206 Str << ", "; | 419 Str << ", "; |
| 207 Str << "%" << (*I)->getName(); | 420 Str << "%" << (*I)->getName(); |
| 208 } | 421 } |
| 209 Str << "\n"; | 422 Str << "\n"; |
| 210 } | 423 } |
| 424 // Dump the live-in variables. | |
| 425 llvm::BitVector LiveIn; | |
| 426 if (Liveness) | |
| 427 LiveIn = Liveness->getLiveIn(this); | |
| 428 if (Func->getContext()->isVerbose(IceV_Liveness) && !LiveIn.empty()) { | |
| 429 Str << " // LiveIn:"; | |
| 430 for (SizeT i = 0; i < LiveIn.size(); ++i) { | |
| 431 if (LiveIn[i]) { | |
| 432 Str << " %" << Liveness->getVariable(i, this)->getName(); | |
| 433 } | |
| 434 } | |
| 435 Str << "\n"; | |
| 436 } | |
| 211 // Dump each instruction. | 437 // Dump each instruction. |
| 212 if (Func->getContext()->isVerbose(IceV_Instructions)) { | 438 if (Func->getContext()->isVerbose(IceV_Instructions)) { |
| 213 for (PhiList::const_iterator I = Phis.begin(), E = Phis.end(); I != E; | 439 for (PhiList::const_iterator I = Phis.begin(), E = Phis.end(); I != E; |
| 214 ++I) { | 440 ++I) { |
| 215 const Inst *Inst = *I; | 441 const Inst *Inst = *I; |
| 216 Inst->dumpDecorated(Func); | 442 Inst->dumpDecorated(Func); |
| 217 } | 443 } |
| 218 InstList::const_iterator I = Insts.begin(), E = Insts.end(); | 444 InstList::const_iterator I = Insts.begin(), E = Insts.end(); |
| 219 while (I != E) { | 445 while (I != E) { |
| 220 Inst *Inst = *I++; | 446 Inst *Inst = *I++; |
| 221 Inst->dumpDecorated(Func); | 447 Inst->dumpDecorated(Func); |
| 222 } | 448 } |
| 223 } | 449 } |
| 450 // Dump the live-out variables. | |
| 451 llvm::BitVector LiveOut; | |
| 452 if (Liveness) | |
| 453 LiveOut = Liveness->getLiveOut(this); | |
| 454 if (Func->getContext()->isVerbose(IceV_Liveness) && !LiveOut.empty()) { | |
| 455 Str << " // LiveOut:"; | |
| 456 for (SizeT i = 0; i < LiveOut.size(); ++i) { | |
| 457 if (LiveOut[i]) { | |
| 458 Str << " %" << Liveness->getVariable(i, this)->getName(); | |
| 459 } | |
| 460 } | |
| 461 Str << "\n"; | |
| 462 } | |
| 224 // Dump list of successor nodes. | 463 // Dump list of successor nodes. |
| 225 if (Func->getContext()->isVerbose(IceV_Succs)) { | 464 if (Func->getContext()->isVerbose(IceV_Succs)) { |
| 226 Str << " // succs = "; | 465 Str << " // succs = "; |
| 227 for (NodeList::const_iterator I = OutEdges.begin(), E = OutEdges.end(); | 466 for (NodeList::const_iterator I = OutEdges.begin(), E = OutEdges.end(); |
| 228 I != E; ++I) { | 467 I != E; ++I) { |
| 229 if (I != OutEdges.begin()) | 468 if (I != OutEdges.begin()) |
| 230 Str << ", "; | 469 Str << ", "; |
| 231 Str << "%" << (*I)->getName(); | 470 Str << "%" << (*I)->getName(); |
| 232 } | 471 } |
| 233 Str << "\n"; | 472 Str << "\n"; |
| 234 } | 473 } |
| 235 } | 474 } |
| 236 | 475 |
| 237 } // end of namespace Ice | 476 } // end of namespace Ice |
| OLD | NEW |