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 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 |