OLD | NEW |
1 //===- subzero/src/IceCfg.cpp - Control flow graph implementation ---------===// | 1 //===- subzero/src/IceCfg.cpp - Control flow graph 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 Cfg class, including constant pool | 10 // This file implements the Cfg class, including constant pool |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
198 } | 198 } |
199 } | 199 } |
200 if (Mode == Liveness_Intervals) { | 200 if (Mode == Liveness_Intervals) { |
201 // Reset each variable's live range. | 201 // Reset each variable's live range. |
202 for (Variable *Var : Variables) | 202 for (Variable *Var : Variables) |
203 Var->resetLiveRange(); | 203 Var->resetLiveRange(); |
204 } | 204 } |
205 // Collect timing for just the portion that constructs the live | 205 // Collect timing for just the portion that constructs the live |
206 // range intervals based on the end-of-live-range computation, for a | 206 // range intervals based on the end-of-live-range computation, for a |
207 // finer breakdown of the cost. | 207 // finer breakdown of the cost. |
| 208 TimerMarker T1(TimerStack::TT_liveRange, this); |
208 // Make a final pass over instructions to delete dead instructions | 209 // Make a final pass over instructions to delete dead instructions |
209 // and build each Variable's live range. | 210 // and build each Variable's live range. |
210 TimerMarker T1(TimerStack::TT_liveRange, this); | |
211 for (CfgNode *Node : Nodes) | 211 for (CfgNode *Node : Nodes) |
212 Node->livenessPostprocess(Mode, getLiveness()); | 212 Node->livenessPostprocess(Mode, getLiveness()); |
213 if (Mode == Liveness_Intervals) { | 213 if (Mode == Liveness_Intervals) { |
214 // Special treatment for live in-args. Their liveness needs to | 214 // Special treatment for live in-args. Their liveness needs to |
215 // extend beyond the beginning of the function, otherwise an arg | 215 // extend beyond the beginning of the function, otherwise an arg |
216 // whose only use is in the first instruction will end up having | 216 // whose only use is in the first instruction will end up having |
217 // the trivial live range [1,1) and will *not* interfere with | 217 // the trivial live range [1,1) and will *not* interfere with |
218 // other arguments. So if the first instruction of the method is | 218 // other arguments. So if the first instruction of the method is |
219 // "r=arg1+arg2", both args may be assigned the same register. | 219 // "r=arg1+arg2", both args may be assigned the same register. |
220 for (SizeT I = 0; I < Args.size(); ++I) { | 220 for (SizeT I = 0; I < Args.size(); ++I) { |
(...skipping 18 matching lines...) Expand all Loading... |
239 // Remove Variable::LiveRange and redirect to | 239 // Remove Variable::LiveRange and redirect to |
240 // Liveness::LiveRanges. TODO: make sure Variable weights | 240 // Liveness::LiveRanges. TODO: make sure Variable weights |
241 // are applied properly. | 241 // are applied properly. |
242 SizeT NumVars = Variables.size(); | 242 SizeT NumVars = Variables.size(); |
243 for (SizeT i = 0; i < NumVars; ++i) { | 243 for (SizeT i = 0; i < NumVars; ++i) { |
244 Variable *Var = Variables[i]; | 244 Variable *Var = Variables[i]; |
245 Var->setLiveRange(Live->getLiveRange(Var)); | 245 Var->setLiveRange(Live->getLiveRange(Var)); |
246 if (Var->getWeight().isInf()) | 246 if (Var->getWeight().isInf()) |
247 Var->setLiveRangeInfiniteWeight(); | 247 Var->setLiveRangeInfiniteWeight(); |
248 } | 248 } |
249 dump(); | |
250 } | 249 } |
251 } | 250 } |
252 | 251 |
253 // Traverse every Variable of every Inst and verify that it | 252 // Traverse every Variable of every Inst and verify that it |
254 // appears within the Variable's computed live range. | 253 // appears within the Variable's computed live range. |
255 bool Cfg::validateLiveness() const { | 254 bool Cfg::validateLiveness() const { |
256 TimerMarker T(TimerStack::TT_validateLiveness, this); | 255 TimerMarker T(TimerStack::TT_validateLiveness, this); |
257 bool Valid = true; | 256 bool Valid = true; |
258 Ostream &Str = Ctx->getStrDump(); | 257 Ostream &Str = Ctx->getStrDump(); |
259 for (CfgNode *Node : Nodes) { | 258 for (CfgNode *Node : Nodes) { |
| 259 Inst *FirstInst = NULL; |
260 for (Inst *Inst : Node->getInsts()) { | 260 for (Inst *Inst : Node->getInsts()) { |
261 if (Inst->isDeleted()) | 261 if (Inst->isDeleted()) |
262 continue; | 262 continue; |
263 if (llvm::isa<InstFakeKill>(Inst)) | 263 if (llvm::isa<InstFakeKill>(Inst)) |
264 continue; | 264 continue; |
| 265 if (FirstInst == NULL) |
| 266 FirstInst = Inst; |
265 InstNumberT InstNumber = Inst->getNumber(); | 267 InstNumberT InstNumber = Inst->getNumber(); |
266 Variable *Dest = Inst->getDest(); | 268 if (Variable *Dest = Inst->getDest()) { |
267 if (Dest) { | 269 if (!Dest->getIgnoreLiveness()) { |
268 // TODO: This instruction should actually begin Dest's live | 270 bool Invalid = false; |
269 // range, so we could probably test that this instruction is | 271 const bool IsDest = true; |
270 // the beginning of some segment of Dest's live range. But | 272 if (!Dest->getLiveRange().containsValue(InstNumber, IsDest)) |
271 // this wouldn't work with non-SSA temporaries during | 273 Invalid = true; |
272 // lowering. | 274 // Check that this instruction actually *begins* Dest's live |
273 if (!Dest->getLiveRange().containsValue(InstNumber)) { | 275 // range, by checking that Dest is not live in the previous |
274 Valid = false; | 276 // instruction. As a special exception, we don't check this |
275 Str << "Liveness error: inst " << Inst->getNumber() << " dest "; | 277 // for the first instruction of the block, because a Phi |
276 Dest->dump(this); | 278 // temporary may be live at the end of the previous block, |
277 Str << " live range " << Dest->getLiveRange() << "\n"; | 279 // and if it is also assigned in the first instruction of |
| 280 // this block, the adjacent live ranges get merged. |
| 281 if (Inst != FirstInst && !Inst->isDestNonKillable() && |
| 282 Dest->getLiveRange().containsValue(InstNumber - 1, IsDest)) |
| 283 Invalid = true; |
| 284 if (Invalid) { |
| 285 Valid = false; |
| 286 Str << "Liveness error: inst " << Inst->getNumber() << " dest "; |
| 287 Dest->dump(this); |
| 288 Str << " live range " << Dest->getLiveRange() << "\n"; |
| 289 } |
278 } | 290 } |
279 } | 291 } |
280 for (SizeT I = 0; I < Inst->getSrcSize(); ++I) { | 292 for (SizeT I = 0; I < Inst->getSrcSize(); ++I) { |
281 Operand *Src = Inst->getSrc(I); | 293 Operand *Src = Inst->getSrc(I); |
282 SizeT NumVars = Src->getNumVars(); | 294 SizeT NumVars = Src->getNumVars(); |
283 for (SizeT J = 0; J < NumVars; ++J) { | 295 for (SizeT J = 0; J < NumVars; ++J) { |
284 const Variable *Var = Src->getVar(J); | 296 const Variable *Var = Src->getVar(J); |
285 if (!Var->getLiveRange().containsValue(InstNumber)) { | 297 const bool IsDest = false; |
| 298 if (!Var->getIgnoreLiveness() && |
| 299 !Var->getLiveRange().containsValue(InstNumber, IsDest)) { |
286 Valid = false; | 300 Valid = false; |
287 Str << "Liveness error: inst " << Inst->getNumber() << " var "; | 301 Str << "Liveness error: inst " << Inst->getNumber() << " var "; |
288 Var->dump(this); | 302 Var->dump(this); |
289 Str << " live range " << Var->getLiveRange() << "\n"; | 303 Str << " live range " << Var->getLiveRange() << "\n"; |
290 } | 304 } |
291 } | 305 } |
292 } | 306 } |
293 } | 307 } |
294 } | 308 } |
295 return Valid; | 309 return Valid; |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
374 } | 388 } |
375 } | 389 } |
376 // Print each basic block | 390 // Print each basic block |
377 for (CfgNode *Node : Nodes) | 391 for (CfgNode *Node : Nodes) |
378 Node->dump(this); | 392 Node->dump(this); |
379 if (getContext()->isVerbose(IceV_Instructions)) | 393 if (getContext()->isVerbose(IceV_Instructions)) |
380 Str << "}\n"; | 394 Str << "}\n"; |
381 } | 395 } |
382 | 396 |
383 } // end of namespace Ice | 397 } // end of namespace Ice |
OLD | NEW |