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 612 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
623 // do not have a known offset from either the stack or frame pointer. | 623 // do not have a known offset from either the stack or frame pointer. |
624 // They grow up from a user pointer from an alloca. | 624 // They grow up from a user pointer from an alloca. |
625 sortAndCombineAllocas(AlignedAllocas, MaxAlignment, Insts, BVT_UserPointer); | 625 sortAndCombineAllocas(AlignedAllocas, MaxAlignment, Insts, BVT_UserPointer); |
626 } | 626 } |
627 // Otherwise, fixed size allocas are always addressed relative to the stack | 627 // Otherwise, fixed size allocas are always addressed relative to the stack |
628 // unless there are dynamic allocas. | 628 // unless there are dynamic allocas. |
629 // TODO(sehr): re-enable frame pointer and decrementing addressing. | 629 // TODO(sehr): re-enable frame pointer and decrementing addressing. |
630 AllocaBaseVariableType BasePointerType = | 630 AllocaBaseVariableType BasePointerType = |
631 (HasDynamicAllocation ? BVT_UserPointer : BVT_StackPointer); | 631 (HasDynamicAllocation ? BVT_UserPointer : BVT_StackPointer); |
632 sortAndCombineAllocas(FixedAllocas, MaxAlignment, Insts, BasePointerType); | 632 sortAndCombineAllocas(FixedAllocas, MaxAlignment, Insts, BasePointerType); |
| 633 |
| 634 if (!FixedAllocas.empty() || !AlignedAllocas.empty()) |
| 635 // No use calling findRematerializable() unless there is some |
| 636 // rematerializable alloca instruction to seed it. |
| 637 findRematerializable(); |
| 638 } |
| 639 |
| 640 namespace { |
| 641 |
| 642 // Helpers for findRematerializable(). For each of them, if a suitable |
| 643 // rematerialization is found, the instruction's Dest variable is set to be |
| 644 // rematerializable and it returns true, otherwise it returns false. |
| 645 |
| 646 bool rematerializeArithmetic(const Inst *Instr) { |
| 647 // Check that it's an Arithmetic instruction with an Add operation. |
| 648 auto *Arith = llvm::dyn_cast<InstArithmetic>(Instr); |
| 649 if (Arith == nullptr || Arith->getOp() != InstArithmetic::Add) |
| 650 return false; |
| 651 // Check that Src(0) is rematerializable. |
| 652 auto *Src0Var = llvm::dyn_cast<Variable>(Arith->getSrc(0)); |
| 653 if (Src0Var == nullptr || !Src0Var->isRematerializable()) |
| 654 return false; |
| 655 // Check that Src(1) is an immediate. |
| 656 auto *Src1Imm = llvm::dyn_cast<ConstantInteger32>(Arith->getSrc(1)); |
| 657 if (Src1Imm == nullptr) |
| 658 return false; |
| 659 Arith->getDest()->setRematerializable( |
| 660 Src0Var->getRegNum(), Src0Var->getStackOffset() + Src1Imm->getValue()); |
| 661 return true; |
| 662 } |
| 663 |
| 664 bool rematerializeAssign(const Inst *Instr) { |
| 665 // An InstAssign only originates from an inttoptr or ptrtoint instruction, |
| 666 // which never occurs in a MINIMAL build. |
| 667 if (BuildDefs::minimal()) |
| 668 return false; |
| 669 // Check that it's an Assign instruction. |
| 670 if (!llvm::isa<InstAssign>(Instr)) |
| 671 return false; |
| 672 // Check that Src(0) is rematerializable. |
| 673 auto *Src0Var = llvm::dyn_cast<Variable>(Instr->getSrc(0)); |
| 674 if (Src0Var == nullptr || !Src0Var->isRematerializable()) |
| 675 return false; |
| 676 Instr->getDest()->setRematerializable(Src0Var->getRegNum(), |
| 677 Src0Var->getStackOffset()); |
| 678 return true; |
| 679 } |
| 680 |
| 681 bool rematerializeCast(const Inst *Instr) { |
| 682 // An pointer-type bitcast never occurs in a MINIMAL build. |
| 683 if (BuildDefs::minimal()) |
| 684 return false; |
| 685 // Check that it's a Cast instruction with a Bitcast operation. |
| 686 auto *Cast = llvm::dyn_cast<InstCast>(Instr); |
| 687 if (Cast == nullptr || Cast->getCastKind() != InstCast::Bitcast) |
| 688 return false; |
| 689 // Check that Src(0) is rematerializable. |
| 690 auto *Src0Var = llvm::dyn_cast<Variable>(Cast->getSrc(0)); |
| 691 if (Src0Var == nullptr || !Src0Var->isRematerializable()) |
| 692 return false; |
| 693 // Check that Dest and Src(0) have the same type. |
| 694 Variable *Dest = Cast->getDest(); |
| 695 if (Dest->getType() != Src0Var->getType()) |
| 696 return false; |
| 697 Dest->setRematerializable(Src0Var->getRegNum(), Src0Var->getStackOffset()); |
| 698 return true; |
| 699 } |
| 700 |
| 701 } // end of anonymous namespace |
| 702 |
| 703 /// Scan the function to find additional rematerializable variables. This is |
| 704 /// possible when the source operand of an InstAssignment is a rematerializable |
| 705 /// variable, or the same for a pointer-type InstCast::Bitcast, or when an |
| 706 /// InstArithmetic is an add of a rematerializable variable and an immediate. |
| 707 /// Note that InstAssignment instructions and pointer-type InstCast::Bitcast |
| 708 /// instructions generally only come about from the IceConverter's treatment of |
| 709 /// inttoptr, ptrtoint, and bitcast instructions. TODO(stichnot): Consider |
| 710 /// other possibilities, however unlikely, such as InstArithmetic::Sub, or |
| 711 /// commutativity. |
| 712 void Cfg::findRematerializable() { |
| 713 // Scan the instructions in order, and repeat until no new opportunities are |
| 714 // found. It may take more than one iteration because a variable's defining |
| 715 // block may happen to come after a block where it is used, depending on the |
| 716 // CfgNode linearization order. |
| 717 bool FoundNewAssignment; |
| 718 do { |
| 719 FoundNewAssignment = false; |
| 720 for (CfgNode *Node : getNodes()) { |
| 721 // No need to process Phi instructions. |
| 722 for (Inst &Instr : Node->getInsts()) { |
| 723 if (Instr.isDeleted()) |
| 724 continue; |
| 725 Variable *Dest = Instr.getDest(); |
| 726 if (Dest == nullptr || Dest->isRematerializable()) |
| 727 continue; |
| 728 if (rematerializeArithmetic(&Instr) || rematerializeAssign(&Instr) || |
| 729 rematerializeCast(&Instr)) { |
| 730 FoundNewAssignment = true; |
| 731 } |
| 732 } |
| 733 } |
| 734 } while (FoundNewAssignment); |
633 } | 735 } |
634 | 736 |
635 void Cfg::doAddressOpt() { | 737 void Cfg::doAddressOpt() { |
636 TimerMarker T(TimerStack::TT_doAddressOpt, this); | 738 TimerMarker T(TimerStack::TT_doAddressOpt, this); |
637 for (CfgNode *Node : Nodes) | 739 for (CfgNode *Node : Nodes) |
638 Node->doAddressOpt(); | 740 Node->doAddressOpt(); |
639 } | 741 } |
640 | 742 |
641 void Cfg::doNopInsertion() { | 743 void Cfg::doNopInsertion() { |
642 if (!Ctx->getFlags().shouldDoNopInsertion()) | 744 if (!Ctx->getFlags().shouldDoNopInsertion()) |
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
900 OstreamLocker L(Ctx); | 1002 OstreamLocker L(Ctx); |
901 Ostream &Str = Ctx->getStrEmit(); | 1003 Ostream &Str = Ctx->getStrEmit(); |
902 IceString MangledName = Ctx->mangleName(getFunctionName()); | 1004 IceString MangledName = Ctx->mangleName(getFunctionName()); |
903 const Assembler *Asm = getAssembler<>(); | 1005 const Assembler *Asm = getAssembler<>(); |
904 const bool NeedSandboxing = Ctx->getFlags().getUseSandboxing(); | 1006 const bool NeedSandboxing = Ctx->getFlags().getUseSandboxing(); |
905 | 1007 |
906 emitTextHeader(MangledName, Ctx, Asm); | 1008 emitTextHeader(MangledName, Ctx, Asm); |
907 deleteJumpTableInsts(); | 1009 deleteJumpTableInsts(); |
908 if (Ctx->getFlags().getDecorateAsm()) { | 1010 if (Ctx->getFlags().getDecorateAsm()) { |
909 for (Variable *Var : getVariables()) { | 1011 for (Variable *Var : getVariables()) { |
910 if (Var->getStackOffset()) { | 1012 if (Var->getStackOffset() && !Var->isRematerializable()) { |
911 Str << "\t" << Var->getSymbolicStackOffset(this) << " = " | 1013 Str << "\t" << Var->getSymbolicStackOffset(this) << " = " |
912 << Var->getStackOffset() << "\n"; | 1014 << Var->getStackOffset() << "\n"; |
913 } | 1015 } |
914 } | 1016 } |
915 } | 1017 } |
916 for (CfgNode *Node : Nodes) { | 1018 for (CfgNode *Node : Nodes) { |
917 if (NeedSandboxing && Node->needsAlignment()) { | 1019 if (NeedSandboxing && Node->needsAlignment()) { |
918 Str << "\t" << Asm->getAlignDirective() << " " | 1020 Str << "\t" << Asm->getAlignDirective() << " " |
919 << Asm->getBundleAlignLog2Bytes() << "\n"; | 1021 << Asm->getBundleAlignLog2Bytes() << "\n"; |
920 } | 1022 } |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
994 } | 1096 } |
995 } | 1097 } |
996 // Print each basic block | 1098 // Print each basic block |
997 for (CfgNode *Node : Nodes) | 1099 for (CfgNode *Node : Nodes) |
998 Node->dump(this); | 1100 Node->dump(this); |
999 if (isVerbose(IceV_Instructions)) | 1101 if (isVerbose(IceV_Instructions)) |
1000 Str << "}\n"; | 1102 Str << "}\n"; |
1001 } | 1103 } |
1002 | 1104 |
1003 } // end of namespace Ice | 1105 } // end of namespace Ice |
OLD | NEW |