| 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 /// \file | 10 /// \file |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 64 } InstIcmpAttributes[] = { | 64 } InstIcmpAttributes[] = { |
| 65 #define X(tag, str) \ | 65 #define X(tag, str) \ |
| 66 { str } \ | 66 { str } \ |
| 67 , | 67 , |
| 68 ICEINSTICMP_TABLE | 68 ICEINSTICMP_TABLE |
| 69 #undef X | 69 #undef X |
| 70 }; | 70 }; |
| 71 | 71 |
| 72 } // end of anonymous namespace | 72 } // end of anonymous namespace |
| 73 | 73 |
| 74 Inst::Inst(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest) | 74 Inst::Inst(Cfg *Func, InstKind MyKind, SizeT MyMaxSrcs, Variable *MyDest) |
| 75 : Kind(Kind), Number(Func->newInstNumber()), Dest(Dest), MaxSrcs(MaxSrcs), | 75 : Kind(MyKind), Number(Func->newInstNumber()), Dest(MyDest), |
| 76 Srcs(Func->allocateArrayOf<Operand *>(MaxSrcs)), LiveRangesEnded(0) {} | 76 MaxSrcs(MyMaxSrcs), Srcs(Func->allocateArrayOf<Operand *>(MyMaxSrcs)), |
| 77 LiveRangesEnded(0) {} |
| 77 | 78 |
| 78 // Assign the instruction a new number. | 79 // Assign the instruction a new number. |
| 79 void Inst::renumber(Cfg *Func) { | 80 void Inst::renumber(Cfg *Func) { |
| 80 Number = isDeleted() ? NumberDeleted : Func->newInstNumber(); | 81 Number = isDeleted() ? NumberDeleted : Func->newInstNumber(); |
| 81 } | 82 } |
| 82 | 83 |
| 83 // Delete the instruction if its tentative Dead flag is still set | 84 // Delete the instruction if its tentative Dead flag is still set |
| 84 // after liveness analysis. | 85 // after liveness analysis. |
| 85 void Inst::deleteIfDead() { | 86 void Inst::deleteIfDead() { |
| 86 if (Dead) | 87 if (Dead) |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 230 // has been sorted. | 231 // has been sorted. |
| 231 LiveEnd->push_back(std::make_pair(VarNum, InstNumber)); | 232 LiveEnd->push_back(std::make_pair(VarNum, InstNumber)); |
| 232 } | 233 } |
| 233 } | 234 } |
| 234 } | 235 } |
| 235 } | 236 } |
| 236 } | 237 } |
| 237 return true; | 238 return true; |
| 238 } | 239 } |
| 239 | 240 |
| 240 InstAlloca::InstAlloca(Cfg *Func, Operand *ByteCount, uint32_t AlignInBytes, | 241 InstAlloca::InstAlloca(Cfg *Func, Operand *ByteCount, uint32_t MyAlignInBytes, |
| 241 Variable *Dest) | 242 Variable *Dest) |
| 242 : InstHighLevel(Func, Inst::Alloca, 1, Dest), AlignInBytes(AlignInBytes) { | 243 : InstHighLevel(Func, Inst::Alloca, 1, Dest), AlignInBytes(MyAlignInBytes) { |
| 243 // Verify AlignInBytes is 0 or a power of 2. | 244 // Verify AlignInBytes is 0 or a power of 2. |
| 244 assert(AlignInBytes == 0 || llvm::isPowerOf2_32(AlignInBytes)); | 245 assert(AlignInBytes == 0 || llvm::isPowerOf2_32(AlignInBytes)); |
| 245 addSource(ByteCount); | 246 addSource(ByteCount); |
| 246 } | 247 } |
| 247 | 248 |
| 248 InstArithmetic::InstArithmetic(Cfg *Func, OpKind Op, Variable *Dest, | 249 InstArithmetic::InstArithmetic(Cfg *Func, OpKind MyOp, Variable *Dest, |
| 249 Operand *Source1, Operand *Source2) | 250 Operand *Source1, Operand *Source2) |
| 250 : InstHighLevel(Func, Inst::Arithmetic, 2, Dest), Op(Op) { | 251 : InstHighLevel(Func, Inst::Arithmetic, 2, Dest), Op(MyOp) { |
| 251 addSource(Source1); | 252 addSource(Source1); |
| 252 addSource(Source2); | 253 addSource(Source2); |
| 253 } | 254 } |
| 254 | 255 |
| 255 const char *InstArithmetic::getOpName(OpKind Op) { | 256 const char *InstArithmetic::getOpName(OpKind Op) { |
| 256 size_t OpIndex = static_cast<size_t>(Op); | 257 size_t OpIndex = static_cast<size_t>(Op); |
| 257 return OpIndex < InstArithmetic::_num | 258 return OpIndex < InstArithmetic::_num |
| 258 ? InstArithmeticAttributes[OpIndex].DisplayString | 259 ? InstArithmeticAttributes[OpIndex].DisplayString |
| 259 : "???"; | 260 : "???"; |
| 260 } | 261 } |
| 261 | 262 |
| 262 bool InstArithmetic::isCommutative() const { | 263 bool InstArithmetic::isCommutative() const { |
| 263 return InstArithmeticAttributes[getOp()].IsCommutative; | 264 return InstArithmeticAttributes[getOp()].IsCommutative; |
| 264 } | 265 } |
| 265 | 266 |
| 266 InstAssign::InstAssign(Cfg *Func, Variable *Dest, Operand *Source) | 267 InstAssign::InstAssign(Cfg *Func, Variable *Dest, Operand *Source) |
| 267 : InstHighLevel(Func, Inst::Assign, 1, Dest) { | 268 : InstHighLevel(Func, Inst::Assign, 1, Dest) { |
| 268 addSource(Source); | 269 addSource(Source); |
| 269 } | 270 } |
| 270 | 271 |
| 271 // If TargetTrue==TargetFalse, we turn it into an unconditional | 272 // If TargetTrue==TargetFalse, we turn it into an unconditional |
| 272 // branch. This ensures that, along with the 'switch' instruction | 273 // branch. This ensures that, along with the 'switch' instruction |
| 273 // semantics, there is at most one edge from one node to another. | 274 // semantics, there is at most one edge from one node to another. |
| 274 InstBr::InstBr(Cfg *Func, Operand *Source, CfgNode *TargetTrue_, | 275 InstBr::InstBr(Cfg *Func, Operand *Source, CfgNode *MyTargetTrue, |
| 275 CfgNode *TargetFalse_) | 276 CfgNode *MyTargetFalse) |
| 276 : InstHighLevel(Func, Inst::Br, 1, nullptr), TargetFalse(TargetFalse_), | 277 : InstHighLevel(Func, Inst::Br, 1, nullptr), TargetFalse(MyTargetFalse), |
| 277 TargetTrue(TargetTrue_) { | 278 TargetTrue(MyTargetTrue) { |
| 278 if (TargetTrue == TargetFalse) { | 279 if (TargetTrue == TargetFalse) { |
| 279 TargetTrue = nullptr; // turn into unconditional version | 280 TargetTrue = nullptr; // turn into unconditional version |
| 280 } else { | 281 } else { |
| 281 addSource(Source); | 282 addSource(Source); |
| 282 } | 283 } |
| 283 } | 284 } |
| 284 | 285 |
| 285 InstBr::InstBr(Cfg *Func, CfgNode *Target) | 286 InstBr::InstBr(Cfg *Func, CfgNode *Target) |
| 286 : InstHighLevel(Func, Inst::Br, 0, nullptr), TargetFalse(Target), | 287 : InstHighLevel(Func, Inst::Br, 0, nullptr), TargetFalse(Target), |
| 287 TargetTrue(nullptr) {} | 288 TargetTrue(nullptr) {} |
| (...skipping 11 matching lines...) Expand all Loading... |
| 299 if (TargetFalse == OldNode) { | 300 if (TargetFalse == OldNode) { |
| 300 TargetFalse = NewNode; | 301 TargetFalse = NewNode; |
| 301 return true; | 302 return true; |
| 302 } else if (TargetTrue == OldNode) { | 303 } else if (TargetTrue == OldNode) { |
| 303 TargetTrue = NewNode; | 304 TargetTrue = NewNode; |
| 304 return true; | 305 return true; |
| 305 } | 306 } |
| 306 return false; | 307 return false; |
| 307 } | 308 } |
| 308 | 309 |
| 309 InstCast::InstCast(Cfg *Func, OpKind CastKind, Variable *Dest, Operand *Source) | 310 InstCast::InstCast(Cfg *Func, OpKind MyCastKind, Variable *Dest, |
| 310 : InstHighLevel(Func, Inst::Cast, 1, Dest), CastKind(CastKind) { | 311 Operand *Source) |
| 312 : InstHighLevel(Func, Inst::Cast, 1, Dest), CastKind(MyCastKind) { |
| 311 addSource(Source); | 313 addSource(Source); |
| 312 } | 314 } |
| 313 | 315 |
| 314 InstExtractElement::InstExtractElement(Cfg *Func, Variable *Dest, | 316 InstExtractElement::InstExtractElement(Cfg *Func, Variable *Dest, |
| 315 Operand *Source1, Operand *Source2) | 317 Operand *Source1, Operand *Source2) |
| 316 : InstHighLevel(Func, Inst::ExtractElement, 2, Dest) { | 318 : InstHighLevel(Func, Inst::ExtractElement, 2, Dest) { |
| 317 addSource(Source1); | 319 addSource(Source1); |
| 318 addSource(Source2); | 320 addSource(Source2); |
| 319 } | 321 } |
| 320 | 322 |
| 321 InstFcmp::InstFcmp(Cfg *Func, FCond Condition, Variable *Dest, Operand *Source1, | 323 InstFcmp::InstFcmp(Cfg *Func, FCond MyCondition, Variable *Dest, |
| 322 Operand *Source2) | 324 Operand *Source1, Operand *Source2) |
| 323 : InstHighLevel(Func, Inst::Fcmp, 2, Dest), Condition(Condition) { | 325 : InstHighLevel(Func, Inst::Fcmp, 2, Dest), Condition(MyCondition) { |
| 324 addSource(Source1); | 326 addSource(Source1); |
| 325 addSource(Source2); | 327 addSource(Source2); |
| 326 } | 328 } |
| 327 | 329 |
| 328 InstIcmp::InstIcmp(Cfg *Func, ICond Condition, Variable *Dest, Operand *Source1, | 330 InstIcmp::InstIcmp(Cfg *Func, ICond MyCondition, Variable *Dest, |
| 329 Operand *Source2) | 331 Operand *Source1, Operand *Source2) |
| 330 : InstHighLevel(Func, Inst::Icmp, 2, Dest), Condition(Condition) { | 332 : InstHighLevel(Func, Inst::Icmp, 2, Dest), Condition(MyCondition) { |
| 331 addSource(Source1); | 333 addSource(Source1); |
| 332 addSource(Source2); | 334 addSource(Source2); |
| 333 } | 335 } |
| 334 | 336 |
| 335 InstInsertElement::InstInsertElement(Cfg *Func, Variable *Dest, | 337 InstInsertElement::InstInsertElement(Cfg *Func, Variable *Dest, |
| 336 Operand *Source1, Operand *Source2, | 338 Operand *Source1, Operand *Source2, |
| 337 Operand *Source3) | 339 Operand *Source3) |
| 338 : InstHighLevel(Func, Inst::InsertElement, 3, Dest) { | 340 : InstHighLevel(Func, Inst::InsertElement, 3, Dest) { |
| 339 addSource(Source1); | 341 addSource(Source1); |
| 340 addSource(Source2); | 342 addSource(Source2); |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 427 addSource(Addr); | 429 addSource(Addr); |
| 428 // The 3rd operand is a dummy placeholder for the RMW beacon. | 430 // The 3rd operand is a dummy placeholder for the RMW beacon. |
| 429 addSource(Data); | 431 addSource(Data); |
| 430 } | 432 } |
| 431 | 433 |
| 432 void InstStore::setRmwBeacon(Variable *Beacon) { | 434 void InstStore::setRmwBeacon(Variable *Beacon) { |
| 433 Dest = llvm::dyn_cast<Variable>(getData()); | 435 Dest = llvm::dyn_cast<Variable>(getData()); |
| 434 Srcs[2] = Beacon; | 436 Srcs[2] = Beacon; |
| 435 } | 437 } |
| 436 | 438 |
| 437 InstSwitch::InstSwitch(Cfg *Func, SizeT NumCases, Operand *Source, | 439 InstSwitch::InstSwitch(Cfg *Func, SizeT MyNumCases, Operand *Source, |
| 438 CfgNode *LabelDefault) | 440 CfgNode *MyLabelDefault) |
| 439 : InstHighLevel(Func, Inst::Switch, 1, nullptr), LabelDefault(LabelDefault), | 441 : InstHighLevel(Func, Inst::Switch, 1, nullptr), |
| 440 NumCases(NumCases) { | 442 LabelDefault(MyLabelDefault), NumCases(MyNumCases) { |
| 441 addSource(Source); | 443 addSource(Source); |
| 442 Values = Func->allocateArrayOf<uint64_t>(NumCases); | 444 Values = Func->allocateArrayOf<uint64_t>(NumCases); |
| 443 Labels = Func->allocateArrayOf<CfgNode *>(NumCases); | 445 Labels = Func->allocateArrayOf<CfgNode *>(NumCases); |
| 444 // Initialize in case buggy code doesn't set all entries | 446 // Initialize in case buggy code doesn't set all entries |
| 445 for (SizeT I = 0; I < NumCases; ++I) { | 447 for (SizeT I = 0; I < NumCases; ++I) { |
| 446 Values[I] = 0; | 448 Values[I] = 0; |
| 447 Labels[I] = nullptr; | 449 Labels[I] = nullptr; |
| 448 } | 450 } |
| 449 } | 451 } |
| 450 | 452 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 474 Labels[I] = NewNode; | 476 Labels[I] = NewNode; |
| 475 return true; | 477 return true; |
| 476 } | 478 } |
| 477 } | 479 } |
| 478 return false; | 480 return false; |
| 479 } | 481 } |
| 480 | 482 |
| 481 InstUnreachable::InstUnreachable(Cfg *Func) | 483 InstUnreachable::InstUnreachable(Cfg *Func) |
| 482 : InstHighLevel(Func, Inst::Unreachable, 0, nullptr) {} | 484 : InstHighLevel(Func, Inst::Unreachable, 0, nullptr) {} |
| 483 | 485 |
| 484 InstBundleLock::InstBundleLock(Cfg *Func, InstBundleLock::Option BundleOption) | 486 InstBundleLock::InstBundleLock(Cfg *Func, InstBundleLock::Option MyBundleOption) |
| 485 : InstHighLevel(Func, Inst::BundleLock, 0, nullptr), | 487 : InstHighLevel(Func, Inst::BundleLock, 0, nullptr), |
| 486 BundleOption(BundleOption) {} | 488 BundleOption(MyBundleOption) {} |
| 487 | 489 |
| 488 InstBundleUnlock::InstBundleUnlock(Cfg *Func) | 490 InstBundleUnlock::InstBundleUnlock(Cfg *Func) |
| 489 : InstHighLevel(Func, Inst::BundleUnlock, 0, nullptr) {} | 491 : InstHighLevel(Func, Inst::BundleUnlock, 0, nullptr) {} |
| 490 | 492 |
| 491 InstFakeDef::InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src) | 493 InstFakeDef::InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src) |
| 492 : InstHighLevel(Func, Inst::FakeDef, Src ? 1 : 0, Dest) { | 494 : InstHighLevel(Func, Inst::FakeDef, Src ? 1 : 0, Dest) { |
| 493 assert(Dest); | 495 assert(Dest); |
| 494 if (Src) | 496 if (Src) |
| 495 addSource(Src); | 497 addSource(Src); |
| 496 } | 498 } |
| 497 | 499 |
| 498 InstFakeUse::InstFakeUse(Cfg *Func, Variable *Src) | 500 InstFakeUse::InstFakeUse(Cfg *Func, Variable *Src) |
| 499 : InstHighLevel(Func, Inst::FakeUse, 1, nullptr) { | 501 : InstHighLevel(Func, Inst::FakeUse, 1, nullptr) { |
| 500 assert(Src); | 502 assert(Src); |
| 501 addSource(Src); | 503 addSource(Src); |
| 502 } | 504 } |
| 503 | 505 |
| 504 InstFakeKill::InstFakeKill(Cfg *Func, const Inst *Linked) | 506 InstFakeKill::InstFakeKill(Cfg *Func, const Inst *MyLinked) |
| 505 : InstHighLevel(Func, Inst::FakeKill, 0, nullptr), Linked(Linked) {} | 507 : InstHighLevel(Func, Inst::FakeKill, 0, nullptr), Linked(MyLinked) {} |
| 506 | 508 |
| 507 Type InstCall::getReturnType() const { | 509 Type InstCall::getReturnType() const { |
| 508 if (Dest == nullptr) | 510 if (Dest == nullptr) |
| 509 return IceType_void; | 511 return IceType_void; |
| 510 return Dest->getType(); | 512 return Dest->getType(); |
| 511 } | 513 } |
| 512 | 514 |
| 513 // ======================== Dump routines ======================== // | 515 // ======================== Dump routines ======================== // |
| 514 | 516 |
| 515 void Inst::dumpDecorated(const Cfg *Func) const { | 517 void Inst::dumpDecorated(const Cfg *Func) const { |
| 516 if (!BuildDefs::dump()) | 518 if (!BuildDefs::dump()) |
| 517 return; | 519 return; |
| 518 Ostream &Str = Func->getContext()->getStrDump(); | 520 Ostream &Str = Func->getContext()->getStrDump(); |
| 519 if (!Func->isVerbose(IceV_Deleted) && (isDeleted() || isRedundantAssign())) | 521 if (!Func->isVerbose(IceV_Deleted) && (isDeleted() || isRedundantAssign())) |
| 520 return; | 522 return; |
| 521 if (Func->isVerbose(IceV_InstNumbers)) { | 523 if (Func->isVerbose(IceV_InstNumbers)) { |
| 522 char buf[30]; | 524 char buf[30]; |
| 523 InstNumberT Number = getNumber(); | 525 if (getNumber() == NumberDeleted) |
| 524 if (Number == NumberDeleted) | |
| 525 snprintf(buf, llvm::array_lengthof(buf), "[XXX]"); | 526 snprintf(buf, llvm::array_lengthof(buf), "[XXX]"); |
| 526 else | 527 else |
| 527 snprintf(buf, llvm::array_lengthof(buf), "[%3d]", Number); | 528 snprintf(buf, llvm::array_lengthof(buf), "[%3d]", getNumber()); |
| 528 Str << buf; | 529 Str << buf; |
| 529 } | 530 } |
| 530 Str << " "; | 531 Str << " "; |
| 531 if (isDeleted()) | 532 if (isDeleted()) |
| 532 Str << " //"; | 533 Str << " //"; |
| 533 dump(Func); | 534 dump(Func); |
| 534 dumpExtras(Func); | 535 dumpExtras(Func); |
| 535 Str << "\n"; | 536 Str << "\n"; |
| 536 } | 537 } |
| 537 | 538 |
| (...skipping 397 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 935 // preserve these. | 936 // preserve these. |
| 936 return true; | 937 return true; |
| 937 } | 938 } |
| 938 if (!Dest->hasReg() && !SrcVar->hasReg() && | 939 if (!Dest->hasReg() && !SrcVar->hasReg() && |
| 939 Dest->getStackOffset() == SrcVar->getStackOffset()) | 940 Dest->getStackOffset() == SrcVar->getStackOffset()) |
| 940 return true; | 941 return true; |
| 941 return false; | 942 return false; |
| 942 } | 943 } |
| 943 | 944 |
| 944 } // end of namespace Ice | 945 } // end of namespace Ice |
| OLD | NEW |