OLD | NEW |
1 //===- subzero/src/IceInst.cpp - High-level instruction implementation ----===// | 1 //===- subzero/src/IceInst.cpp - High-level instruction 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 Inst class, primarily the various | 10 // This file implements the Inst class, primarily the various |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
173 | 173 |
174 // TODO: A Switch instruction (and maybe others) can add duplicate | 174 // TODO: A Switch instruction (and maybe others) can add duplicate |
175 // edges. We may want to de-dup Phis and validate consistency (i.e., | 175 // edges. We may want to de-dup Phis and validate consistency (i.e., |
176 // the source operands are the same for duplicate edges), though it | 176 // the source operands are the same for duplicate edges), though it |
177 // seems the current lowering code is OK with this situation. | 177 // seems the current lowering code is OK with this situation. |
178 void InstPhi::addArgument(Operand *Source, CfgNode *Label) { | 178 void InstPhi::addArgument(Operand *Source, CfgNode *Label) { |
179 Labels[getSrcSize()] = Label; | 179 Labels[getSrcSize()] = Label; |
180 addSource(Source); | 180 addSource(Source); |
181 } | 181 } |
182 | 182 |
| 183 // Find the source operand corresponding to the incoming edge for the |
| 184 // given node. TODO: This uses a linear-time search, which could be |
| 185 // improved if it becomes a problem. |
| 186 Operand *InstPhi::getOperandForTarget(CfgNode *Target) const { |
| 187 for (SizeT I = 0; I < getSrcSize(); ++I) { |
| 188 if (Labels[I] == Target) |
| 189 return getSrc(I); |
| 190 } |
| 191 llvm_unreachable("Phi target not found"); |
| 192 return NULL; |
| 193 } |
| 194 |
| 195 // Change "a=phi(...)" to "a_phi=phi(...)" and return a new |
| 196 // instruction "a=a_phi". |
| 197 Inst *InstPhi::lower(Cfg *Func, CfgNode *Node) { |
| 198 Variable *Dest = getDest(); |
| 199 assert(Dest); |
| 200 IceString PhiName = Dest->getName() + "_phi"; |
| 201 Variable *NewSrc = Func->makeVariable(Dest->getType(), Node, PhiName); |
| 202 this->Dest = NewSrc; |
| 203 InstAssign *NewInst = InstAssign::create(Func, Dest, NewSrc); |
| 204 // Set Dest and NewSrc to have affinity with each other, as a hint |
| 205 // for register allocation. |
| 206 Dest->setPreferredRegister(NewSrc, false); |
| 207 NewSrc->setPreferredRegister(Dest, false); |
| 208 Dest->replaceDefinition(NewInst, Node); |
| 209 return NewInst; |
| 210 } |
| 211 |
183 InstRet::InstRet(Cfg *Func, Operand *RetValue) | 212 InstRet::InstRet(Cfg *Func, Operand *RetValue) |
184 : Inst(Func, Ret, RetValue ? 1 : 0, NULL) { | 213 : Inst(Func, Ret, RetValue ? 1 : 0, NULL) { |
185 if (RetValue) | 214 if (RetValue) |
186 addSource(RetValue); | 215 addSource(RetValue); |
187 } | 216 } |
188 | 217 |
189 InstSelect::InstSelect(Cfg *Func, Variable *Dest, Operand *Condition, | 218 InstSelect::InstSelect(Cfg *Func, Variable *Dest, Operand *Condition, |
190 Operand *SourceTrue, Operand *SourceFalse) | 219 Operand *SourceTrue, Operand *SourceFalse) |
191 : Inst(Func, Inst::Select, 3, Dest) { | 220 : Inst(Func, Inst::Select, 3, Dest) { |
192 assert(Condition->getType() == IceType_i1); | 221 assert(Condition->getType() == IceType_i1); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
226 OutEdges.push_back(LabelDefault); | 255 OutEdges.push_back(LabelDefault); |
227 for (SizeT I = 0; I < NumCases; ++I) { | 256 for (SizeT I = 0; I < NumCases; ++I) { |
228 OutEdges.push_back(Labels[I]); | 257 OutEdges.push_back(Labels[I]); |
229 } | 258 } |
230 return OutEdges; | 259 return OutEdges; |
231 } | 260 } |
232 | 261 |
233 InstUnreachable::InstUnreachable(Cfg *Func) | 262 InstUnreachable::InstUnreachable(Cfg *Func) |
234 : Inst(Func, Inst::Unreachable, 0, NULL) {} | 263 : Inst(Func, Inst::Unreachable, 0, NULL) {} |
235 | 264 |
| 265 InstFakeDef::InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src) |
| 266 : Inst(Func, Inst::FakeDef, Src ? 1 : 0, Dest) { |
| 267 assert(Dest); |
| 268 if (Src) |
| 269 addSource(Src); |
| 270 } |
| 271 |
| 272 InstFakeUse::InstFakeUse(Cfg *Func, Variable *Src) |
| 273 : Inst(Func, Inst::FakeUse, 1, NULL) { |
| 274 assert(Src); |
| 275 addSource(Src); |
| 276 } |
| 277 |
| 278 InstFakeKill::InstFakeKill(Cfg *Func, const VarList &KilledRegs, |
| 279 const Inst *Linked) |
| 280 : Inst(Func, Inst::FakeKill, KilledRegs.size(), NULL), Linked(Linked) { |
| 281 for (VarList::const_iterator I = KilledRegs.begin(), E = KilledRegs.end(); |
| 282 I != E; ++I) { |
| 283 Variable *Var = *I; |
| 284 addSource(Var); |
| 285 } |
| 286 } |
| 287 |
236 // ======================== Dump routines ======================== // | 288 // ======================== Dump routines ======================== // |
237 | 289 |
238 void Inst::dumpDecorated(const Cfg *Func) const { | 290 void Inst::dumpDecorated(const Cfg *Func) const { |
239 Ostream &Str = Func->getContext()->getStrDump(); | 291 Ostream &Str = Func->getContext()->getStrDump(); |
240 if (!Func->getContext()->isVerbose(IceV_Deleted) && isDeleted()) | 292 if (!Func->getContext()->isVerbose(IceV_Deleted) && |
| 293 (isDeleted() || isRedundantAssign())) |
241 return; | 294 return; |
242 if (Func->getContext()->isVerbose(IceV_InstNumbers)) { | 295 if (Func->getContext()->isVerbose(IceV_InstNumbers)) { |
243 char buf[30]; | 296 char buf[30]; |
244 int32_t Number = getNumber(); | 297 int32_t Number = getNumber(); |
245 if (Number < 0) | 298 if (Number < 0) |
246 snprintf(buf, llvm::array_lengthof(buf), "[XXX]"); | 299 snprintf(buf, llvm::array_lengthof(buf), "[XXX]"); |
247 else | 300 else |
248 snprintf(buf, llvm::array_lengthof(buf), "[%3d]", Number); | 301 snprintf(buf, llvm::array_lengthof(buf), "[%3d]", Number); |
249 Str << buf; | 302 Str << buf; |
250 } | 303 } |
251 Str << " "; | 304 Str << " "; |
252 if (isDeleted()) | 305 if (isDeleted()) |
253 Str << " //"; | 306 Str << " //"; |
254 dump(Func); | 307 dump(Func); |
255 Str << "\n"; | 308 Str << "\n"; |
256 } | 309 } |
257 | 310 |
| 311 void Inst::emit(const Cfg */*Func*/) const { |
| 312 llvm_unreachable("emit() called on a non-lowered instruction"); |
| 313 } |
| 314 |
258 void Inst::dump(const Cfg *Func) const { | 315 void Inst::dump(const Cfg *Func) const { |
259 Ostream &Str = Func->getContext()->getStrDump(); | 316 Ostream &Str = Func->getContext()->getStrDump(); |
260 dumpDest(Func); | 317 dumpDest(Func); |
261 Str << " =~ "; | 318 Str << " =~ "; |
262 dumpSources(Func); | 319 dumpSources(Func); |
263 } | 320 } |
264 | 321 |
265 void Inst::dumpSources(const Cfg *Func) const { | 322 void Inst::dumpSources(const Cfg *Func) const { |
266 Ostream &Str = Func->getContext()->getStrDump(); | 323 Ostream &Str = Func->getContext()->getStrDump(); |
267 for (SizeT I = 0; I < getSrcSize(); ++I) { | 324 for (SizeT I = 0; I < getSrcSize(); ++I) { |
268 if (I > 0) | 325 if (I > 0) |
269 Str << ", "; | 326 Str << ", "; |
270 getSrc(I)->dump(Func); | 327 getSrc(I)->dump(Func); |
271 } | 328 } |
272 } | 329 } |
273 | 330 |
| 331 void Inst::emitSources(const Cfg *Func) const { |
| 332 Ostream &Str = Func->getContext()->getStrEmit(); |
| 333 for (SizeT I = 0; I < getSrcSize(); ++I) { |
| 334 if (I > 0) |
| 335 Str << ", "; |
| 336 getSrc(I)->emit(Func); |
| 337 } |
| 338 } |
| 339 |
274 void Inst::dumpDest(const Cfg *Func) const { | 340 void Inst::dumpDest(const Cfg *Func) const { |
275 if (getDest()) | 341 if (getDest()) |
276 getDest()->dump(Func); | 342 getDest()->dump(Func); |
277 } | 343 } |
278 | 344 |
279 void InstAlloca::dump(const Cfg *Func) const { | 345 void InstAlloca::dump(const Cfg *Func) const { |
280 Ostream &Str = Func->getContext()->getStrDump(); | 346 Ostream &Str = Func->getContext()->getStrDump(); |
281 dumpDest(Func); | 347 dumpDest(Func); |
282 Str << " = alloca i8, i32 "; | 348 Str << " = alloca i8, i32 "; |
283 getSizeInBytes()->dump(Func); | 349 getSizeInBytes()->dump(Func); |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
399 if (I > 0) | 465 if (I > 0) |
400 Str << ", "; | 466 Str << ", "; |
401 Str << "[ "; | 467 Str << "[ "; |
402 getSrc(I)->dump(Func); | 468 getSrc(I)->dump(Func); |
403 Str << ", %" << Labels[I]->getName() << " ]"; | 469 Str << ", %" << Labels[I]->getName() << " ]"; |
404 } | 470 } |
405 } | 471 } |
406 | 472 |
407 void InstRet::dump(const Cfg *Func) const { | 473 void InstRet::dump(const Cfg *Func) const { |
408 Ostream &Str = Func->getContext()->getStrDump(); | 474 Ostream &Str = Func->getContext()->getStrDump(); |
409 Type Ty = hasRetValue() ? getSrc(0)->getType() : IceType_void; | 475 Type Ty = hasRetValue() ? getRetValue()->getType() : IceType_void; |
410 Str << "ret " << Ty; | 476 Str << "ret " << Ty; |
411 if (hasRetValue()) { | 477 if (hasRetValue()) { |
412 Str << " "; | 478 Str << " "; |
413 dumpSources(Func); | 479 dumpSources(Func); |
414 } | 480 } |
415 } | 481 } |
416 | 482 |
417 void InstSelect::dump(const Cfg *Func) const { | 483 void InstSelect::dump(const Cfg *Func) const { |
418 Ostream &Str = Func->getContext()->getStrDump(); | 484 Ostream &Str = Func->getContext()->getStrDump(); |
419 dumpDest(Func); | 485 dumpDest(Func); |
420 Operand *Condition = getCondition(); | 486 Operand *Condition = getCondition(); |
421 Operand *TrueOp = getTrueOperand(); | 487 Operand *TrueOp = getTrueOperand(); |
422 Operand *FalseOp = getFalseOperand(); | 488 Operand *FalseOp = getFalseOperand(); |
423 Str << " = select " << Condition->getType() << " "; | 489 Str << " = select " << Condition->getType() << " "; |
424 Condition->dump(Func); | 490 Condition->dump(Func); |
425 Str << ", " << TrueOp->getType() << " "; | 491 Str << ", " << TrueOp->getType() << " "; |
426 TrueOp->dump(Func); | 492 TrueOp->dump(Func); |
427 Str << ", " << FalseOp->getType() << " "; | 493 Str << ", " << FalseOp->getType() << " "; |
428 FalseOp->dump(Func); | 494 FalseOp->dump(Func); |
429 } | 495 } |
430 | 496 |
431 void InstUnreachable::dump(const Cfg *Func) const { | 497 void InstUnreachable::dump(const Cfg *Func) const { |
432 Ostream &Str = Func->getContext()->getStrDump(); | 498 Ostream &Str = Func->getContext()->getStrDump(); |
433 Str << "unreachable"; | 499 Str << "unreachable"; |
434 } | 500 } |
435 | 501 |
| 502 void InstFakeDef::emit(const Cfg *Func) const { |
| 503 Ostream &Str = Func->getContext()->getStrEmit(); |
| 504 Str << "\t# "; |
| 505 getDest()->emit(Func); |
| 506 Str << " = def.pseudo "; |
| 507 emitSources(Func); |
| 508 Str << "\n"; |
| 509 } |
| 510 |
| 511 void InstFakeDef::dump(const Cfg *Func) const { |
| 512 Ostream &Str = Func->getContext()->getStrDump(); |
| 513 dumpDest(Func); |
| 514 Str << " = def.pseudo "; |
| 515 dumpSources(Func); |
| 516 } |
| 517 |
| 518 void InstFakeUse::emit(const Cfg *Func) const { |
| 519 Ostream &Str = Func->getContext()->getStrEmit(); |
| 520 Str << "\t# "; |
| 521 Str << "use.pseudo "; |
| 522 emitSources(Func); |
| 523 Str << "\n"; |
| 524 } |
| 525 |
| 526 void InstFakeUse::dump(const Cfg *Func) const { |
| 527 Ostream &Str = Func->getContext()->getStrDump(); |
| 528 Str << "use.pseudo "; |
| 529 dumpSources(Func); |
| 530 } |
| 531 |
| 532 void InstFakeKill::emit(const Cfg *Func) const { |
| 533 Ostream &Str = Func->getContext()->getStrEmit(); |
| 534 Str << "\t# "; |
| 535 if (Linked->isDeleted()) |
| 536 Str << "// "; |
| 537 Str << "kill.pseudo "; |
| 538 emitSources(Func); |
| 539 Str << "\n"; |
| 540 } |
| 541 |
| 542 void InstFakeKill::dump(const Cfg *Func) const { |
| 543 Ostream &Str = Func->getContext()->getStrDump(); |
| 544 if (Linked->isDeleted()) |
| 545 Str << "// "; |
| 546 Str << "kill.pseudo "; |
| 547 dumpSources(Func); |
| 548 } |
| 549 |
| 550 void InstTarget::dump(const Cfg *Func) const { |
| 551 Ostream &Str = Func->getContext()->getStrDump(); |
| 552 Str << "[TARGET] "; |
| 553 Inst::dump(Func); |
| 554 } |
| 555 |
436 } // end of namespace Ice | 556 } // end of namespace Ice |
OLD | NEW |