| 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 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 292 if (!I.isDeleted() && I.repointEdges(this, NewNode)) | 292 if (!I.isDeleted() && I.repointEdges(this, NewNode)) |
| 293 Found = true; | 293 Found = true; |
| 294 assert(Found); | 294 assert(Found); |
| 295 (void)Found; | 295 (void)Found; |
| 296 return NewNode; | 296 return NewNode; |
| 297 } | 297 } |
| 298 | 298 |
| 299 namespace { | 299 namespace { |
| 300 | 300 |
| 301 // Helper function used by advancedPhiLowering(). | 301 // Helper function used by advancedPhiLowering(). |
| 302 bool sameVarOrReg(const Variable *Var, const Operand *Opnd) { | 302 bool sameVarOrReg(TargetLowering *Target, const Variable *Var1, |
| 303 if (Var == Opnd) | 303 const Operand *Opnd) { |
| 304 if (Var1 == Opnd) |
| 304 return true; | 305 return true; |
| 305 if (const auto Var2 = llvm::dyn_cast<Variable>(Opnd)) { | 306 const auto Var2 = llvm::dyn_cast<Variable>(Opnd); |
| 306 if (Var->hasReg() && Var->getRegNum() == Var2->getRegNum()) | 307 if (Var2 == nullptr) |
| 307 return true; | 308 return false; |
| 308 } | 309 |
| 309 return false; | 310 // If either operand lacks a register, they cannot be the same. |
| 311 if (!Var1->hasReg()) |
| 312 return false; |
| 313 if (!Var2->hasReg()) |
| 314 return false; |
| 315 |
| 316 int32_t RegNum1 = Var1->getRegNum(); |
| 317 int32_t RegNum2 = Var2->getRegNum(); |
| 318 // Quick common-case check. |
| 319 if (RegNum1 == RegNum2) |
| 320 return true; |
| 321 |
| 322 assert(Target->getAliasesForRegister(RegNum1)[RegNum2] == |
| 323 Target->getAliasesForRegister(RegNum2)[RegNum1]); |
| 324 return Target->getAliasesForRegister(RegNum1)[RegNum2]; |
| 310 } | 325 } |
| 311 | 326 |
| 312 } // end of anonymous namespace | 327 } // end of anonymous namespace |
| 313 | 328 |
| 314 // This the "advanced" version of Phi lowering for a basic block, in contrast | 329 // This the "advanced" version of Phi lowering for a basic block, in contrast |
| 315 // to the simple version that lowers through assignments involving temporaries. | 330 // to the simple version that lowers through assignments involving temporaries. |
| 316 // | 331 // |
| 317 // All Phi instructions in a basic block are conceptually executed in parallel. | 332 // All Phi instructions in a basic block are conceptually executed in parallel. |
| 318 // However, if we lower Phis early and commit to a sequential ordering, we may | 333 // However, if we lower Phis early and commit to a sequential ordering, we may |
| 319 // end up creating unnecessary interferences which lead to worse register | 334 // end up creating unnecessary interferences which lead to worse register |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 376 // marking the phi dest variable as live on entry. | 391 // marking the phi dest variable as live on entry. |
| 377 SizeT VarNum = Func->getLiveness()->getLiveIndex(Dest->getIndex()); | 392 SizeT VarNum = Func->getLiveness()->getLiveIndex(Dest->getIndex()); |
| 378 assert(!Func->getLiveness()->getLiveIn(this)[VarNum]); | 393 assert(!Func->getLiveness()->getLiveIn(this)[VarNum]); |
| 379 Func->getLiveness()->getLiveIn(this)[VarNum] = true; | 394 Func->getLiveness()->getLiveIn(this)[VarNum] = true; |
| 380 Inst->setDeleted(); | 395 Inst->setDeleted(); |
| 381 } | 396 } |
| 382 } | 397 } |
| 383 if (NumPhis == 0) | 398 if (NumPhis == 0) |
| 384 return; | 399 return; |
| 385 | 400 |
| 401 TargetLowering *Target = Func->getTarget(); |
| 386 SizeT InEdgeIndex = 0; | 402 SizeT InEdgeIndex = 0; |
| 387 for (CfgNode *Pred : InEdges) { | 403 for (CfgNode *Pred : InEdges) { |
| 388 CfgNode *Split = splitIncomingEdge(Pred, InEdgeIndex++); | 404 CfgNode *Split = splitIncomingEdge(Pred, InEdgeIndex++); |
| 389 SizeT Remaining = NumPhis; | 405 SizeT Remaining = NumPhis; |
| 390 | 406 |
| 391 // First pass computes Src and initializes NumPred. | 407 // First pass computes Src and initializes NumPred. |
| 392 for (size_t I = 0; I < NumPhis; ++I) { | 408 for (size_t I = 0; I < NumPhis; ++I) { |
| 393 Variable *Dest = Desc[I].Dest; | 409 Variable *Dest = Desc[I].Dest; |
| 394 Operand *Src = Desc[I].Phi->getOperandForTarget(Pred); | 410 Operand *Src = Desc[I].Phi->getOperandForTarget(Pred); |
| 395 Desc[I].Src = Src; | 411 Desc[I].Src = Src; |
| 396 Desc[I].Processed = false; | 412 Desc[I].Processed = false; |
| 397 Desc[I].NumPred = 0; | 413 Desc[I].NumPred = 0; |
| 398 // Cherry-pick any trivial assignments, so that they don't contribute to | 414 // Cherry-pick any trivial assignments, so that they don't contribute to |
| 399 // the running complexity of the topological sort. | 415 // the running complexity of the topological sort. |
| 400 if (sameVarOrReg(Dest, Src)) { | 416 if (sameVarOrReg(Target, Dest, Src)) { |
| 401 Desc[I].Processed = true; | 417 Desc[I].Processed = true; |
| 402 --Remaining; | 418 --Remaining; |
| 403 if (Dest != Src) | 419 if (Dest != Src) |
| 404 // If Dest and Src are syntactically the same, don't bother adding | 420 // If Dest and Src are syntactically the same, don't bother adding |
| 405 // the assignment, because in all respects it would be redundant, and | 421 // the assignment, because in all respects it would be redundant, and |
| 406 // if Dest/Src are on the stack, the target lowering may naively | 422 // if Dest/Src are on the stack, the target lowering may naively |
| 407 // decide to lower it using a temporary register. | 423 // decide to lower it using a temporary register. |
| 408 Split->appendInst(InstAssign::create(Func, Dest, Src)); | 424 Split->appendInst(InstAssign::create(Func, Dest, Src)); |
| 409 } | 425 } |
| 410 } | 426 } |
| 411 // Second pass computes NumPred by comparing every pair of Phi | 427 // Second pass computes NumPred by comparing every pair of Phi |
| 412 // instructions. | 428 // instructions. |
| 413 for (size_t I = 0; I < NumPhis; ++I) { | 429 for (size_t I = 0; I < NumPhis; ++I) { |
| 414 if (Desc[I].Processed) | 430 if (Desc[I].Processed) |
| 415 continue; | 431 continue; |
| 416 const Variable *Dest = Desc[I].Dest; | 432 const Variable *Dest = Desc[I].Dest; |
| 417 for (size_t J = 0; J < NumPhis; ++J) { | 433 for (size_t J = 0; J < NumPhis; ++J) { |
| 418 if (Desc[J].Processed) | 434 if (Desc[J].Processed) |
| 419 continue; | 435 continue; |
| 420 if (I != J) { | 436 if (I != J) { |
| 421 // There shouldn't be two Phis with the same Dest variable or | 437 // There shouldn't be two Phis with the same Dest variable or |
| 422 // register. | 438 // register. |
| 423 assert(!sameVarOrReg(Dest, Desc[J].Dest)); | 439 assert(!sameVarOrReg(Target, Dest, Desc[J].Dest)); |
| 424 } | 440 } |
| 425 const Operand *Src = Desc[J].Src; | 441 const Operand *Src = Desc[J].Src; |
| 426 if (sameVarOrReg(Dest, Src)) | 442 if (sameVarOrReg(Target, Dest, Src)) |
| 427 ++Desc[I].NumPred; | 443 ++Desc[I].NumPred; |
| 428 } | 444 } |
| 429 } | 445 } |
| 430 | 446 |
| 431 // Another pass to compute initial Weight values. | 447 // Another pass to compute initial Weight values. |
| 432 | 448 |
| 433 // Always pick NumPred=0 over NumPred>0. | 449 // Always pick NumPred=0 over NumPred>0. |
| 434 constexpr int32_t WeightNoPreds = 4; | 450 constexpr int32_t WeightNoPreds = 4; |
| 435 // Prefer Src as a register because the register might free up. | 451 // Prefer Src as a register because the register might free up. |
| 436 constexpr int32_t WeightSrcIsReg = 2; | 452 constexpr int32_t WeightSrcIsReg = 2; |
| (...skipping 29 matching lines...) Expand all Loading... |
| 466 Weight = Desc[I].Weight; | 482 Weight = Desc[I].Weight; |
| 467 if (Weight > BestWeight) { | 483 if (Weight > BestWeight) { |
| 468 BestIndex = I; | 484 BestIndex = I; |
| 469 BestWeight = Weight; | 485 BestWeight = Weight; |
| 470 } | 486 } |
| 471 } | 487 } |
| 472 assert(BestWeight >= 0); | 488 assert(BestWeight >= 0); |
| 473 assert(Desc[BestIndex].NumPred <= 1); | 489 assert(Desc[BestIndex].NumPred <= 1); |
| 474 Variable *Dest = Desc[BestIndex].Dest; | 490 Variable *Dest = Desc[BestIndex].Dest; |
| 475 Operand *Src = Desc[BestIndex].Src; | 491 Operand *Src = Desc[BestIndex].Src; |
| 476 assert(!sameVarOrReg(Dest, Src)); | 492 assert(!sameVarOrReg(Target, Dest, Src)); |
| 477 // Break a cycle by introducing a temporary. | 493 // Break a cycle by introducing a temporary. |
| 478 if (Desc[BestIndex].NumPred) { | 494 if (Desc[BestIndex].NumPred) { |
| 479 bool Found = false; | 495 bool Found = false; |
| 480 // If the target instruction "A=B" is part of a cycle, find the "X=A" | 496 // If the target instruction "A=B" is part of a cycle, find the "X=A" |
| 481 // assignment in the cycle because it will have to be rewritten as | 497 // assignment in the cycle because it will have to be rewritten as |
| 482 // "X=tmp". | 498 // "X=tmp". |
| 483 for (size_t J = 0; !Found && J < NumPhis; ++J) { | 499 for (size_t J = 0; !Found && J < NumPhis; ++J) { |
| 484 if (Desc[J].Processed) | 500 if (Desc[J].Processed) |
| 485 continue; | 501 continue; |
| 486 Operand *OtherSrc = Desc[J].Src; | 502 Operand *OtherSrc = Desc[J].Src; |
| 487 if (Desc[J].NumPred && sameVarOrReg(Dest, OtherSrc)) { | 503 if (Desc[J].NumPred && sameVarOrReg(Target, Dest, OtherSrc)) { |
| 488 SizeT VarNum = Func->getNumVariables(); | 504 SizeT VarNum = Func->getNumVariables(); |
| 489 Variable *Tmp = Func->makeVariable(OtherSrc->getType()); | 505 Variable *Tmp = Func->makeVariable(OtherSrc->getType()); |
| 490 if (BuildDefs::dump()) | 506 if (BuildDefs::dump()) |
| 491 Tmp->setName(Func, "__split_" + std::to_string(VarNum)); | 507 Tmp->setName(Func, "__split_" + std::to_string(VarNum)); |
| 492 Split->appendInst(InstAssign::create(Func, Tmp, OtherSrc)); | 508 Split->appendInst(InstAssign::create(Func, Tmp, OtherSrc)); |
| 493 Desc[J].Src = Tmp; | 509 Desc[J].Src = Tmp; |
| 494 Found = true; | 510 Found = true; |
| 495 } | 511 } |
| 496 } | 512 } |
| 497 assert(Found); | 513 assert(Found); |
| 498 } | 514 } |
| 499 // Now that a cycle (if any) has been broken, create the actual | 515 // Now that a cycle (if any) has been broken, create the actual |
| 500 // assignment. | 516 // assignment. |
| 501 Split->appendInst(InstAssign::create(Func, Dest, Src)); | 517 Split->appendInst(InstAssign::create(Func, Dest, Src)); |
| 502 // Update NumPred for all Phi assignments using this Phi's Src as their | 518 // Update NumPred for all Phi assignments using this Phi's Src as their |
| 503 // Dest variable. Also update Weight if NumPred dropped from 1 to 0. | 519 // Dest variable. Also update Weight if NumPred dropped from 1 to 0. |
| 504 if (auto Var = llvm::dyn_cast<Variable>(Src)) { | 520 if (auto Var = llvm::dyn_cast<Variable>(Src)) { |
| 505 for (size_t I = 0; I < NumPhis; ++I) { | 521 for (size_t I = 0; I < NumPhis; ++I) { |
| 506 if (Desc[I].Processed) | 522 if (Desc[I].Processed) |
| 507 continue; | 523 continue; |
| 508 if (sameVarOrReg(Var, Desc[I].Dest)) { | 524 if (sameVarOrReg(Target, Var, Desc[I].Dest)) { |
| 509 if (--Desc[I].NumPred == 0) | 525 if (--Desc[I].NumPred == 0) |
| 510 Desc[I].Weight += WeightNoPreds; | 526 Desc[I].Weight += WeightNoPreds; |
| 511 } | 527 } |
| 512 } | 528 } |
| 513 } | 529 } |
| 514 Desc[BestIndex].Processed = true; | 530 Desc[BestIndex].Processed = true; |
| 515 } | 531 } |
| 516 Split->appendInst(InstBr::create(Func, this)); | 532 Split->appendInst(InstBr::create(Func, this)); |
| 517 | 533 |
| 518 Split->genCode(); | 534 Split->genCode(); |
| (...skipping 504 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1023 if (I.isRedundantAssign()) { | 1039 if (I.isRedundantAssign()) { |
| 1024 // Usually, redundant assignments end the live range of the src variable | 1040 // Usually, redundant assignments end the live range of the src variable |
| 1025 // and begin the live range of the dest variable, with no net effect on | 1041 // and begin the live range of the dest variable, with no net effect on |
| 1026 // the liveness of their register. However, if the register allocator | 1042 // the liveness of their register. However, if the register allocator |
| 1027 // infers the AllowOverlap condition, then this may be a redundant | 1043 // infers the AllowOverlap condition, then this may be a redundant |
| 1028 // assignment that does not end the src variable's live range, in which | 1044 // assignment that does not end the src variable's live range, in which |
| 1029 // case the active variable count for that register needs to be bumped. | 1045 // case the active variable count for that register needs to be bumped. |
| 1030 // That normally would have happened as part of emitLiveRangesEnded(), | 1046 // That normally would have happened as part of emitLiveRangesEnded(), |
| 1031 // but that isn't called for redundant assignments. | 1047 // but that isn't called for redundant assignments. |
| 1032 Variable *Dest = I.getDest(); | 1048 Variable *Dest = I.getDest(); |
| 1033 if (DecorateAsm && Dest->hasReg() && !I.isLastUse(I.getSrc(0))) | 1049 if (DecorateAsm && Dest->hasReg()) { |
| 1034 ++LiveRegCount[Dest->getRegNum()]; | 1050 ++LiveRegCount[Dest->getRegNum()]; |
| 1051 if (I.isLastUse(I.getSrc(0))) |
| 1052 --LiveRegCount[llvm::cast<Variable>(I.getSrc(0))->getRegNum()]; |
| 1053 } |
| 1035 continue; | 1054 continue; |
| 1036 } | 1055 } |
| 1037 I.emit(Func); | 1056 I.emit(Func); |
| 1038 if (DecorateAsm) | 1057 if (DecorateAsm) |
| 1039 emitLiveRangesEnded(Str, Func, &I, LiveRegCount); | 1058 emitLiveRangesEnded(Str, Func, &I, LiveRegCount); |
| 1040 Str << "\n"; | 1059 Str << "\n"; |
| 1041 updateStats(Func, &I); | 1060 updateStats(Func, &I); |
| 1042 } | 1061 } |
| 1043 if (DecorateAsm) { | 1062 if (DecorateAsm) { |
| 1044 constexpr bool IsLiveIn = false; | 1063 constexpr bool IsLiveIn = false; |
| (...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1373 InstIntrinsicCall *Inst = InstIntrinsicCall::create( | 1392 InstIntrinsicCall *Inst = InstIntrinsicCall::create( |
| 1374 Func, 5, Func->makeVariable(IceType_i64), RMWI64Name, Info->Info); | 1393 Func, 5, Func->makeVariable(IceType_i64), RMWI64Name, Info->Info); |
| 1375 Inst->addArg(AtomicRMWOp); | 1394 Inst->addArg(AtomicRMWOp); |
| 1376 Inst->addArg(Counter); | 1395 Inst->addArg(Counter); |
| 1377 Inst->addArg(One); | 1396 Inst->addArg(One); |
| 1378 Inst->addArg(OrderAcquireRelease); | 1397 Inst->addArg(OrderAcquireRelease); |
| 1379 Insts.push_front(Inst); | 1398 Insts.push_front(Inst); |
| 1380 } | 1399 } |
| 1381 | 1400 |
| 1382 } // end of namespace Ice | 1401 } // end of namespace Ice |
| OLD | NEW |