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 |