| 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 /// \file | 10 /// \file |
| (...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 318 InstPhi *Phi = nullptr; | 318 InstPhi *Phi = nullptr; |
| 319 Variable *Dest = nullptr; | 319 Variable *Dest = nullptr; |
| 320 Operand *Src = nullptr; | 320 Operand *Src = nullptr; |
| 321 bool Processed = false; | 321 bool Processed = false; |
| 322 size_t NumPred = 0; // number of entries whose Src is this Dest | 322 size_t NumPred = 0; // number of entries whose Src is this Dest |
| 323 int32_t Weight = 0; // preference for topological order | 323 int32_t Weight = 0; // preference for topological order |
| 324 }; | 324 }; |
| 325 using PhiDescList = llvm::SmallVector<PhiDesc, 32>; | 325 using PhiDescList = llvm::SmallVector<PhiDesc, 32>; |
| 326 | 326 |
| 327 // Always pick NumPred=0 over NumPred>0. | 327 // Always pick NumPred=0 over NumPred>0. |
| 328 constexpr int32_t WeightNoPreds = 4; | 328 constexpr int32_t WeightNoPreds = 8; |
| 329 // Prefer Src as a register because the register might free up. | 329 // Prefer Src as a register because the register might free up. |
| 330 constexpr int32_t WeightSrcIsReg = 2; | 330 constexpr int32_t WeightSrcIsReg = 4; |
| 331 // Prefer Dest not as a register because the register stays free longer. | 331 // Prefer Dest not as a register because the register stays free longer. |
| 332 constexpr int32_t WeightDestNotReg = 1; | 332 constexpr int32_t WeightDestNotReg = 2; |
| 333 // Prefer NumPred=1 over NumPred>1. This is used as a tiebreaker when a |
| 334 // dependency cycle must be broken so that hopefully only one temporary |
| 335 // assignment has to be added to break the cycle. |
| 336 constexpr int32_t WeightOnePred = 1; |
| 333 | 337 |
| 334 bool sameVarOrReg(TargetLowering *Target, const Variable *Var1, | 338 bool sameVarOrReg(TargetLowering *Target, const Variable *Var1, |
| 335 const Operand *Opnd) { | 339 const Operand *Opnd) { |
| 336 if (Var1 == Opnd) | 340 if (Var1 == Opnd) |
| 337 return true; | 341 return true; |
| 338 const auto *Var2 = llvm::dyn_cast<Variable>(Opnd); | 342 const auto *Var2 = llvm::dyn_cast<Variable>(Opnd); |
| 339 if (Var2 == nullptr) | 343 if (Var2 == nullptr) |
| 340 return false; | 344 return false; |
| 341 | 345 |
| 342 // If either operand lacks a register, they cannot be the same. | 346 // If either operand lacks a register, they cannot be the same. |
| 343 if (!Var1->hasReg()) | 347 if (!Var1->hasReg()) |
| 344 return false; | 348 return false; |
| 345 if (!Var2->hasReg()) | 349 if (!Var2->hasReg()) |
| 346 return false; | 350 return false; |
| 347 | 351 |
| 348 const auto RegNum1 = Var1->getRegNum(); | 352 const auto RegNum1 = Var1->getRegNum(); |
| 349 const auto RegNum2 = Var2->getRegNum(); | 353 const auto RegNum2 = Var2->getRegNum(); |
| 350 // Quick common-case check. | 354 // Quick common-case check. |
| 351 if (RegNum1 == RegNum2) | 355 if (RegNum1 == RegNum2) |
| 352 return true; | 356 return true; |
| 353 | 357 |
| 354 assert(Target->getAliasesForRegister(RegNum1)[RegNum2] == | 358 assert(Target->getAliasesForRegister(RegNum1)[RegNum2] == |
| 355 Target->getAliasesForRegister(RegNum2)[RegNum1]); | 359 Target->getAliasesForRegister(RegNum2)[RegNum1]); |
| 356 return Target->getAliasesForRegister(RegNum1)[RegNum2]; | 360 return Target->getAliasesForRegister(RegNum1)[RegNum2]; |
| 357 } | 361 } |
| 358 | 362 |
| 359 // Update NumPred for all Phi assignments using Var as their Dest variable. | 363 // Update NumPred for all Phi assignments using Var as their Dest variable. |
| 360 // Also update Weight if NumPred dropped from 1 to 0. | 364 // Also update Weight if NumPred dropped from 2 to 1, or 1 to 0. |
| 361 void updatePreds(PhiDescList &Desc, TargetLowering *Target, Variable *Var) { | 365 void updatePreds(PhiDescList &Desc, TargetLowering *Target, Variable *Var) { |
| 362 for (PhiDesc &Item : Desc) { | 366 for (PhiDesc &Item : Desc) { |
| 363 if (!Item.Processed && sameVarOrReg(Target, Var, Item.Dest)) { | 367 if (!Item.Processed && sameVarOrReg(Target, Var, Item.Dest)) { |
| 364 if (--Item.NumPred == 0) { | 368 --Item.NumPred; |
| 365 Item.Weight += WeightNoPreds; | 369 if (Item.NumPred == 1) { |
| 370 // If NumPred changed from 2 to 1, add in WeightOnePred. |
| 371 Item.Weight += WeightOnePred; |
| 372 } else if (Item.NumPred == 0) { |
| 373 // If NumPred changed from 1 to 0, subtract WeightOnePred and add in |
| 374 // WeightNoPreds. |
| 375 Item.Weight += (WeightNoPreds - WeightOnePred); |
| 366 } | 376 } |
| 367 } | 377 } |
| 368 } | 378 } |
| 369 } | 379 } |
| 370 | 380 |
| 371 } // end of anonymous namespace | 381 } // end of anonymous namespace |
| 372 | 382 |
| 373 // This the "advanced" version of Phi lowering for a basic block, in contrast | 383 // This the "advanced" version of Phi lowering for a basic block, in contrast |
| 374 // to the simple version that lowers through assignments involving temporaries. | 384 // to the simple version that lowers through assignments involving temporaries. |
| 375 // | 385 // |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 472 } | 482 } |
| 473 } | 483 } |
| 474 | 484 |
| 475 // Another pass to compute initial Weight values. | 485 // Another pass to compute initial Weight values. |
| 476 for (PhiDesc &Item : Desc) { | 486 for (PhiDesc &Item : Desc) { |
| 477 if (Item.Processed) | 487 if (Item.Processed) |
| 478 continue; | 488 continue; |
| 479 int32_t Weight = 0; | 489 int32_t Weight = 0; |
| 480 if (Item.NumPred == 0) | 490 if (Item.NumPred == 0) |
| 481 Weight += WeightNoPreds; | 491 Weight += WeightNoPreds; |
| 492 if (Item.NumPred == 1) |
| 493 Weight += WeightOnePred; |
| 482 if (auto *Var = llvm::dyn_cast<Variable>(Item.Src)) | 494 if (auto *Var = llvm::dyn_cast<Variable>(Item.Src)) |
| 483 if (Var->hasReg()) | 495 if (Var->hasReg()) |
| 484 Weight += WeightSrcIsReg; | 496 Weight += WeightSrcIsReg; |
| 485 if (!Item.Dest->hasReg()) | 497 if (!Item.Dest->hasReg()) |
| 486 Weight += WeightDestNotReg; | 498 Weight += WeightDestNotReg; |
| 487 Item.Weight = Weight; | 499 Item.Weight = Weight; |
| 488 } | 500 } |
| 489 | 501 |
| 490 // Repeatedly choose and process the best candidate in the topological sort, | 502 // Repeatedly choose and process the best candidate in the topological sort, |
| 491 // until no candidates remain. This implementation is O(N^2) where N is the | 503 // until no candidates remain. This implementation is O(N^2) where N is the |
| 492 // number of Phi instructions, but with a small constant factor compared to | 504 // number of Phi instructions, but with a small constant factor compared to |
| 493 // a likely implementation of O(N) topological sort. | 505 // a likely implementation of O(N) topological sort. |
| 494 for (; Remaining; --Remaining) { | 506 for (; Remaining; --Remaining) { |
| 495 int32_t BestWeight = -1; | 507 int32_t BestWeight = -1; |
| 496 PhiDesc *BestItem = nullptr; | 508 PhiDesc *BestItem = nullptr; |
| 497 // Find the best candidate. | 509 // Find the best candidate. |
| 498 for (PhiDesc &Item : Desc) { | 510 for (PhiDesc &Item : Desc) { |
| 499 if (Item.Processed) | 511 if (Item.Processed) |
| 500 continue; | 512 continue; |
| 501 int32_t Weight = 0; | 513 const int32_t Weight = Item.Weight; |
| 502 Weight = Item.Weight; | |
| 503 if (Weight > BestWeight) { | 514 if (Weight > BestWeight) { |
| 504 BestItem = &Item; | 515 BestItem = &Item; |
| 505 BestWeight = Weight; | 516 BestWeight = Weight; |
| 506 } | 517 } |
| 507 } | 518 } |
| 508 assert(BestWeight >= 0); | 519 assert(BestWeight >= 0); |
| 509 assert(BestItem->NumPred <= 1); | |
| 510 Variable *Dest = BestItem->Dest; | 520 Variable *Dest = BestItem->Dest; |
| 511 Operand *Src = BestItem->Src; | 521 Operand *Src = BestItem->Src; |
| 512 assert(!sameVarOrReg(Target, Dest, Src)); | 522 assert(!sameVarOrReg(Target, Dest, Src)); |
| 513 // Break a cycle by introducing a temporary. | 523 // Break a cycle by introducing a temporary. |
| 514 if (BestItem->NumPred) { | 524 while (BestItem->NumPred > 0) { |
| 515 bool Found = false; | 525 bool Found = false; |
| 516 // If the target instruction "A=B" is part of a cycle, find the "X=A" | 526 // If the target instruction "A=B" is part of a cycle, find the "X=A" |
| 517 // assignment in the cycle because it will have to be rewritten as | 527 // assignment in the cycle because it will have to be rewritten as |
| 518 // "X=tmp". | 528 // "X=tmp". |
| 519 for (PhiDesc &Item : Desc) { | 529 for (PhiDesc &Item : Desc) { |
| 520 if (Item.Processed) | 530 if (Item.Processed) |
| 521 continue; | 531 continue; |
| 522 Operand *OtherSrc = Item.Src; | 532 Operand *OtherSrc = Item.Src; |
| 523 if (Item.NumPred && sameVarOrReg(Target, Dest, OtherSrc)) { | 533 if (Item.NumPred && sameVarOrReg(Target, Dest, OtherSrc)) { |
| 524 SizeT VarNum = Func->getNumVariables(); | 534 SizeT VarNum = Func->getNumVariables(); |
| (...skipping 921 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1446 auto *Instr = InstIntrinsicCall::create( | 1456 auto *Instr = InstIntrinsicCall::create( |
| 1447 Func, 5, Func->makeVariable(IceType_i64), RMWI64Name, Info->Info); | 1457 Func, 5, Func->makeVariable(IceType_i64), RMWI64Name, Info->Info); |
| 1448 Instr->addArg(AtomicRMWOp); | 1458 Instr->addArg(AtomicRMWOp); |
| 1449 Instr->addArg(Counter); | 1459 Instr->addArg(Counter); |
| 1450 Instr->addArg(One); | 1460 Instr->addArg(One); |
| 1451 Instr->addArg(OrderAcquireRelease); | 1461 Instr->addArg(OrderAcquireRelease); |
| 1452 Insts.push_front(Instr); | 1462 Insts.push_front(Instr); |
| 1453 } | 1463 } |
| 1454 | 1464 |
| 1455 } // end of namespace Ice | 1465 } // end of namespace Ice |
| OLD | NEW |