Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 //===- subzero/src/IceCfg.cpp - Control flow graph implementation ---------===// | 1 //===- subzero/src/IceCfg.cpp - Control flow graph 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 476 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 487 // upwards from the stack pointer. | 487 // upwards from the stack pointer. |
| 488 Offsets.push_back(CurrentOffset); | 488 Offsets.push_back(CurrentOffset); |
| 489 } | 489 } |
| 490 // Update the running offset of the fused alloca region. | 490 // Update the running offset of the fused alloca region. |
| 491 CurrentOffset += Size; | 491 CurrentOffset += Size; |
| 492 } | 492 } |
| 493 // Round the offset up to the alignment granularity to use as the size. | 493 // Round the offset up to the alignment granularity to use as the size. |
| 494 uint32_t TotalSize = Utils::applyAlignment(CurrentOffset, CombinedAlignment); | 494 uint32_t TotalSize = Utils::applyAlignment(CurrentOffset, CombinedAlignment); |
| 495 // Ensure every alloca was assigned an offset. | 495 // Ensure every alloca was assigned an offset. |
| 496 assert(Allocas.size() == Offsets.size()); | 496 assert(Allocas.size() == Offsets.size()); |
| 497 Variable *BaseVariable = makeVariable(IceType_i32); | 497 |
| 498 Variable *AllocaDest = BaseVariable; | 498 |
| 499 // Emit one addition for each alloca after the first. | 499 switch (BaseVariableType) { |
| 500 for (size_t i = 0; i < Allocas.size(); ++i) { | 500 case BVT_UserPointer: { |
| 501 auto *Alloca = llvm::cast<InstAlloca>(Allocas[i]); | 501 Variable *BaseVariable = makeVariable(IceType_i32); |
| 502 switch (BaseVariableType) { | 502 for (size_t i = 0; i < Allocas.size(); ++i) { |
|
Jim Stichnoth
2015/11/16 14:47:57
For better or worse, most of the Subzero code that
sehr
2015/11/16 18:42:24
Done.
| |
| 503 case BVT_FramePointer: | 503 auto *Alloca = llvm::cast<InstAlloca>(Allocas[i]); |
| 504 case BVT_UserPointer: { | |
| 505 // Emit a new addition operation to replace the alloca. | 504 // Emit a new addition operation to replace the alloca. |
| 506 Operand *AllocaOffset = Ctx->getConstantInt32(Offsets[i]); | 505 Operand *AllocaOffset = Ctx->getConstantInt32(Offsets[i]); |
| 507 InstArithmetic *Add = | 506 InstArithmetic *Add = |
| 508 InstArithmetic::create(this, InstArithmetic::Add, Alloca->getDest(), | 507 InstArithmetic::create(this, InstArithmetic::Add, Alloca->getDest(), |
| 509 BaseVariable, AllocaOffset); | 508 BaseVariable, AllocaOffset); |
| 510 Insts.push_front(Add); | 509 Insts.push_front(Add); |
| 511 } break; | 510 Alloca->setDeleted(); |
| 512 case BVT_StackPointer: { | 511 } |
| 512 Operand *AllocaSize = Ctx->getConstantInt32(TotalSize); | |
| 513 InstAlloca *CombinedAlloca = | |
| 514 InstAlloca::create(this, AllocaSize, CombinedAlignment, BaseVariable); | |
|
Jim Stichnoth
2015/11/16 14:47:57
Wow, I just realized that InstAlloca is unique amo
sehr
2015/11/16 18:42:24
Done.
| |
| 515 CombinedAlloca->setKnownFrameOffset(); | |
| 516 Insts.push_front(CombinedAlloca); | |
| 517 } break; | |
| 518 case BVT_StackPointer: | |
| 519 case BVT_FramePointer: { | |
| 520 for (size_t i = 0; i < Allocas.size(); ++i) { | |
| 521 auto *Alloca = llvm::cast<InstAlloca>(Allocas[i]); | |
| 513 // Emit a fake definition of the rematerializable variable. | 522 // Emit a fake definition of the rematerializable variable. |
| 514 Variable *Dest = Alloca->getDest(); | 523 Variable *Dest = Alloca->getDest(); |
| 515 InstFakeDef *Def = InstFakeDef::create(this, Dest); | 524 InstFakeDef *Def = InstFakeDef::create(this, Dest); |
| 516 Dest->setRematerializable(getTarget()->getStackReg(), Offsets[i]); | 525 if (BaseVariableType == BVT_StackPointer) |
| 526 Dest->setRematerializable(getTarget()->getStackReg(), Offsets[i]); | |
| 527 else | |
| 528 Dest->setRematerializable(getTarget()->getFrameReg(), Offsets[i]); | |
| 517 Insts.push_front(Def); | 529 Insts.push_front(Def); |
| 518 } break; | 530 Alloca->setDeleted(); |
| 519 } | 531 } |
| 520 Alloca->setDeleted(); | 532 // Allocate the fixed area in the function prolog. |
| 533 getTarget()->reserveFixedAllocaArea(TotalSize, CombinedAlignment); | |
| 534 } break; | |
| 521 } | 535 } |
| 522 Operand *AllocaSize = Ctx->getConstantInt32(TotalSize); | |
| 523 switch (BaseVariableType) { | |
| 524 case BVT_FramePointer: { | |
| 525 // Adjust the return of the alloca to the top of the returned region. | |
| 526 AllocaDest = makeVariable(IceType_i32); | |
| 527 InstArithmetic *Add = InstArithmetic::create( | |
| 528 this, InstArithmetic::Add, BaseVariable, AllocaDest, AllocaSize); | |
| 529 Insts.push_front(Add); | |
| 530 } break; | |
| 531 case BVT_StackPointer: { | |
| 532 // Emit a fake use to keep the Alloca live. | |
| 533 InstFakeUse *Use = InstFakeUse::create(this, AllocaDest); | |
| 534 Insts.push_front(Use); | |
| 535 } break; | |
| 536 case BVT_UserPointer: | |
| 537 break; | |
| 538 } | |
| 539 // And insert the fused alloca. | |
| 540 InstAlloca *CombinedAlloca = | |
| 541 InstAlloca::create(this, AllocaSize, CombinedAlignment, AllocaDest); | |
| 542 CombinedAlloca->setKnownFrameOffset(); | |
| 543 Insts.push_front(CombinedAlloca); | |
| 544 } | 536 } |
| 545 | 537 |
| 546 void Cfg::processAllocas(bool SortAndCombine) { | 538 void Cfg::processAllocas(bool SortAndCombine) { |
| 547 const uint32_t StackAlignment = getTarget()->getStackAlignment(); | 539 const uint32_t StackAlignment = getTarget()->getStackAlignment(); |
| 548 CfgNode *EntryNode = getEntryNode(); | 540 CfgNode *EntryNode = getEntryNode(); |
| 549 // LLVM enforces power of 2 alignment. | 541 // LLVM enforces power of 2 alignment. |
| 550 assert(llvm::isPowerOf2_32(StackAlignment)); | 542 assert(llvm::isPowerOf2_32(StackAlignment)); |
| 551 // Determine if there are large alignment allocations in the entry block or | 543 // Determine if there are large alignment allocations in the entry block or |
| 552 // dynamic allocations (variable size in the entry block). | 544 // dynamic allocations (variable size in the entry block). |
| 553 bool HasLargeAlignment = false; | 545 bool HasLargeAlignment = false; |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 588 // Mark the target as requiring a frame pointer. | 580 // Mark the target as requiring a frame pointer. |
| 589 if (HasLargeAlignment || HasDynamicAllocation) | 581 if (HasLargeAlignment || HasDynamicAllocation) |
| 590 getTarget()->setHasFramePointer(); | 582 getTarget()->setHasFramePointer(); |
| 591 // Collect the Allocas into the two vectors. | 583 // Collect the Allocas into the two vectors. |
| 592 // Allocas in the entry block that have constant size and alignment less | 584 // Allocas in the entry block that have constant size and alignment less |
| 593 // than or equal to the function's stack alignment. | 585 // than or equal to the function's stack alignment. |
| 594 CfgVector<Inst *> FixedAllocas; | 586 CfgVector<Inst *> FixedAllocas; |
| 595 // Allocas in the entry block that have constant size and alignment greater | 587 // Allocas in the entry block that have constant size and alignment greater |
| 596 // than the function's stack alignment. | 588 // than the function's stack alignment. |
| 597 CfgVector<Inst *> AlignedAllocas; | 589 CfgVector<Inst *> AlignedAllocas; |
| 598 // Maximum alignment used for the dynamic/aligned allocas. | 590 // Maximum alignment used by any alloca. |
| 599 uint32_t MaxAlignment = StackAlignment; | 591 uint32_t MaxAlignment = StackAlignment; |
| 600 for (Inst &Instr : EntryNode->getInsts()) { | 592 for (Inst &Instr : EntryNode->getInsts()) { |
| 601 if (auto *Alloca = llvm::dyn_cast<InstAlloca>(&Instr)) { | 593 if (auto *Alloca = llvm::dyn_cast<InstAlloca>(&Instr)) { |
| 602 if (!llvm::isa<Constant>(Alloca->getSizeInBytes())) | 594 if (!llvm::isa<Constant>(Alloca->getSizeInBytes())) |
| 603 continue; | 595 continue; |
| 604 uint32_t AlignmentParam = Alloca->getAlignInBytes(); | 596 uint32_t AlignmentParam = Alloca->getAlignInBytes(); |
| 605 // For default align=0, set it to the real value 1, to avoid any | 597 // For default align=0, set it to the real value 1, to avoid any |
| 606 // bit-manipulation problems below. | 598 // bit-manipulation problems below. |
| 607 AlignmentParam = std::max(AlignmentParam, 1u); | 599 AlignmentParam = std::max(AlignmentParam, 1u); |
| 608 assert(llvm::isPowerOf2_32(AlignmentParam)); | 600 assert(llvm::isPowerOf2_32(AlignmentParam)); |
| 609 if (HasDynamicAllocation && AlignmentParam > StackAlignment) { | 601 if (HasDynamicAllocation && AlignmentParam > StackAlignment) { |
| 610 // If we have both dynamic allocations and large stack alignments, | 602 // If we have both dynamic allocations and large stack alignments, |
| 611 // high-alignment allocations are pulled out with their own base. | 603 // high-alignment allocations are pulled out with their own base. |
| 612 AlignedAllocas.push_back(Alloca); | 604 AlignedAllocas.push_back(Alloca); |
| 613 } else { | 605 } else { |
| 614 FixedAllocas.push_back(Alloca); | 606 FixedAllocas.push_back(Alloca); |
| 615 } | 607 } |
| 616 MaxAlignment = std::max(AlignmentParam, MaxAlignment); | 608 MaxAlignment = std::max(AlignmentParam, MaxAlignment); |
| 617 } | 609 } |
| 618 } | 610 } |
| 619 // Add instructions to the head of the entry block in reverse order. | 611 // Add instructions to the head of the entry block in reverse order. |
| 620 InstList &Insts = getEntryNode()->getInsts(); | 612 InstList &Insts = getEntryNode()->getInsts(); |
| 621 if (HasDynamicAllocation && HasLargeAlignment) { | 613 if (HasDynamicAllocation && HasLargeAlignment) { |
| 622 // We are using a frame pointer, but fixed large-alignment alloca addresses, | 614 // We are using a frame pointer, but fixed large-alignment alloca addresses, |
| 623 // do not have a known offset from either the stack or frame pointer. | 615 // do not have a known offset from either the stack or frame pointer. |
| 624 // They grow up from a user pointer from an alloca. | 616 // They grow up from a user pointer from an alloca. |
| 625 sortAndCombineAllocas(AlignedAllocas, MaxAlignment, Insts, BVT_UserPointer); | 617 sortAndCombineAllocas(AlignedAllocas, MaxAlignment, Insts, BVT_UserPointer); |
| 618 // Fixed size allocas are addressed relative to the frame pointer. | |
| 619 sortAndCombineAllocas(FixedAllocas, StackAlignment, Insts, | |
| 620 BVT_FramePointer); | |
| 621 } else { | |
| 622 // Otherwise, fixed size allocas are addressed relative to the stack unless | |
| 623 // there are dynamic allocas. | |
| 624 AllocaBaseVariableType BasePointerType = | |
|
John
2015/11/16 14:00:02
const AllocaBaseVariableType
sehr
2015/11/16 18:42:24
Done.
| |
| 625 (HasDynamicAllocation ? BVT_FramePointer : BVT_StackPointer); | |
| 626 sortAndCombineAllocas(FixedAllocas, MaxAlignment, Insts, BasePointerType); | |
| 626 } | 627 } |
| 627 // Otherwise, fixed size allocas are always addressed relative to the stack | |
| 628 // unless there are dynamic allocas. | |
| 629 // TODO(sehr): re-enable frame pointer and decrementing addressing. | |
| 630 AllocaBaseVariableType BasePointerType = | |
| 631 (HasDynamicAllocation ? BVT_UserPointer : BVT_StackPointer); | |
| 632 sortAndCombineAllocas(FixedAllocas, MaxAlignment, Insts, BasePointerType); | |
| 633 | |
| 634 if (!FixedAllocas.empty() || !AlignedAllocas.empty()) | 628 if (!FixedAllocas.empty() || !AlignedAllocas.empty()) |
| 635 // No use calling findRematerializable() unless there is some | 629 // No use calling findRematerializable() unless there is some |
| 636 // rematerializable alloca instruction to seed it. | 630 // rematerializable alloca instruction to seed it. |
| 637 findRematerializable(); | 631 findRematerializable(); |
| 638 } | 632 } |
| 639 | 633 |
| 640 namespace { | 634 namespace { |
| 641 | 635 |
| 642 // Helpers for findRematerializable(). For each of them, if a suitable | 636 // Helpers for findRematerializable(). For each of them, if a suitable |
| 643 // rematerialization is found, the instruction's Dest variable is set to be | 637 // rematerialization is found, the instruction's Dest variable is set to be |
| (...skipping 452 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1096 } | 1090 } |
| 1097 } | 1091 } |
| 1098 // Print each basic block | 1092 // Print each basic block |
| 1099 for (CfgNode *Node : Nodes) | 1093 for (CfgNode *Node : Nodes) |
| 1100 Node->dump(this); | 1094 Node->dump(this); |
| 1101 if (isVerbose(IceV_Instructions)) | 1095 if (isVerbose(IceV_Instructions)) |
| 1102 Str << "}\n"; | 1096 Str << "}\n"; |
| 1103 } | 1097 } |
| 1104 | 1098 |
| 1105 } // end of namespace Ice | 1099 } // end of namespace Ice |
| OLD | NEW |