| OLD | NEW |
| 1 //===- subzero/src/IceTargetLoweringARM32.h - ARM32 lowering ----*- C++ -*-===// | 1 //===- subzero/src/IceTargetLoweringARM32.h - ARM32 lowering ----*- C++ -*-===// |
| 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 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 83 const llvm::SmallBitVector &getAliasesForRegister(SizeT Reg) const override { | 83 const llvm::SmallBitVector &getAliasesForRegister(SizeT Reg) const override { |
| 84 return RegisterAliases[Reg]; | 84 return RegisterAliases[Reg]; |
| 85 } | 85 } |
| 86 bool hasFramePointer() const override { return UsesFramePointer; } | 86 bool hasFramePointer() const override { return UsesFramePointer; } |
| 87 void setHasFramePointer() override { UsesFramePointer = true; } | 87 void setHasFramePointer() override { UsesFramePointer = true; } |
| 88 SizeT getStackReg() const override { return RegARM32::Reg_sp; } | 88 SizeT getStackReg() const override { return RegARM32::Reg_sp; } |
| 89 SizeT getFrameReg() const override { return RegARM32::Reg_fp; } | 89 SizeT getFrameReg() const override { return RegARM32::Reg_fp; } |
| 90 SizeT getFrameOrStackReg() const override { | 90 SizeT getFrameOrStackReg() const override { |
| 91 return UsesFramePointer ? getFrameReg() : getStackReg(); | 91 return UsesFramePointer ? getFrameReg() : getStackReg(); |
| 92 } | 92 } |
| 93 SizeT getReservedTmpReg() const { return RegARM32::Reg_ip; } | 93 int32_t getReservedTmpReg() const { return RegARM32::Reg_ip; } |
| 94 | 94 |
| 95 size_t typeWidthInBytesOnStack(Type Ty) const override { | 95 size_t typeWidthInBytesOnStack(Type Ty) const override { |
| 96 // Round up to the next multiple of 4 bytes. In particular, i1, i8, and i16 | 96 // Round up to the next multiple of 4 bytes. In particular, i1, i8, and i16 |
| 97 // are rounded up to 4 bytes. | 97 // are rounded up to 4 bytes. |
| 98 return (typeWidthInBytes(Ty) + 3) & ~3; | 98 return (typeWidthInBytes(Ty) + 3) & ~3; |
| 99 } | 99 } |
| 100 uint32_t getStackAlignment() const override; | 100 uint32_t getStackAlignment() const override; |
| 101 void reserveFixedAllocaArea(size_t Size, size_t Align) override { | 101 void reserveFixedAllocaArea(size_t Size, size_t Align) override { |
| 102 FixedAllocaSizeBytes = Size; | 102 FixedAllocaSizeBytes = Size; |
| 103 assert(llvm::isPowerOf2_32(Align)); | 103 assert(llvm::isPowerOf2_32(Align)); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 134 Operand *loOperand(Operand *Operand); | 134 Operand *loOperand(Operand *Operand); |
| 135 Operand *hiOperand(Operand *Operand); | 135 Operand *hiOperand(Operand *Operand); |
| 136 void finishArgumentLowering(Variable *Arg, Variable *FramePtr, | 136 void finishArgumentLowering(Variable *Arg, Variable *FramePtr, |
| 137 size_t BasicFrameOffset, size_t *InArgsSizeBytes); | 137 size_t BasicFrameOffset, size_t *InArgsSizeBytes); |
| 138 | 138 |
| 139 bool hasCPUFeature(TargetARM32Features::ARM32InstructionSet I) const { | 139 bool hasCPUFeature(TargetARM32Features::ARM32InstructionSet I) const { |
| 140 return CPUFeatures.hasFeature(I); | 140 return CPUFeatures.hasFeature(I); |
| 141 } | 141 } |
| 142 | 142 |
| 143 enum OperandLegalization { | 143 enum OperandLegalization { |
| 144 Legal_None = 0, | |
| 145 Legal_Reg = 1 << 0, /// physical register, not stack location | 144 Legal_Reg = 1 << 0, /// physical register, not stack location |
| 146 Legal_Flex = 1 << 1, /// A flexible operand2, which can hold rotated small | 145 Legal_Flex = 1 << 1, /// A flexible operand2, which can hold rotated small |
| 147 /// immediates, shifted registers, or modified fp imm. | 146 /// immediates, shifted registers, or modified fp imm. |
| 148 Legal_Mem = 1 << 2, /// includes [r0, r1 lsl #2] as well as [sp, #12] | 147 Legal_Mem = 1 << 2, /// includes [r0, r1 lsl #2] as well as [sp, #12] |
| 149 Legal_All = ~Legal_None | 148 Legal_Rematerializable = 1 << 3, |
| 149 Legal_All = ~Legal_Rematerializable, |
| 150 }; | 150 }; |
| 151 | 151 |
| 152 using LegalMask = uint32_t; | 152 using LegalMask = uint32_t; |
| 153 Operand *legalizeUndef(Operand *From, int32_t RegNum = Variable::NoRegister); | 153 Operand *legalizeUndef(Operand *From, int32_t RegNum = Variable::NoRegister); |
| 154 Operand *legalize(Operand *From, LegalMask Allowed = Legal_All, | 154 Operand *legalize(Operand *From, LegalMask Allowed = Legal_All, |
| 155 int32_t RegNum = Variable::NoRegister); | 155 int32_t RegNum = Variable::NoRegister); |
| 156 Variable *legalizeToReg(Operand *From, int32_t RegNum = Variable::NoRegister); | 156 Variable *legalizeToReg(Operand *From, int32_t RegNum = Variable::NoRegister); |
| 157 | 157 |
| 158 OperandARM32ShAmtImm *shAmtImm(uint32_t ShAmtImm) const { | 158 OperandARM32ShAmtImm *shAmtImm(uint32_t ShAmtImm) const { |
| 159 assert(ShAmtImm < 32); | 159 assert(ShAmtImm < 32); |
| (...skipping 649 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 809 Context.insert(InstARM32Vsub::create(Func, Dest, Src0, Src1)); | 809 Context.insert(InstARM32Vsub::create(Func, Dest, Src0, Src1)); |
| 810 } | 810 } |
| 811 | 811 |
| 812 // Iterates over the CFG and determines the maximum outgoing stack arguments | 812 // Iterates over the CFG and determines the maximum outgoing stack arguments |
| 813 // bytes. This information is later used during addProlog() to pre-allocate | 813 // bytes. This information is later used during addProlog() to pre-allocate |
| 814 // the outargs area. | 814 // the outargs area. |
| 815 // TODO(jpp): This could live in the Parser, if we provided a Target-specific | 815 // TODO(jpp): This could live in the Parser, if we provided a Target-specific |
| 816 // method that the Parser could call. | 816 // method that the Parser could call. |
| 817 void findMaxStackOutArgsSize(); | 817 void findMaxStackOutArgsSize(); |
| 818 | 818 |
| 819 /// Run a pass through stack variables and ensure that the offsets are legal. | 819 /// Returns true if the given Offset can be represented in a Load/Store Mem |
| 820 /// If the offset is not legal, use a new base register that accounts for the | 820 /// Operand. |
| 821 /// offset, such that the addressing mode offset bits are now legal. | |
| 822 void legalizeStackSlots(); | |
| 823 /// Returns true if the given Offset can be represented in a ldr/str. | |
| 824 bool isLegalMemOffset(Type Ty, int32_t Offset) const; | 821 bool isLegalMemOffset(Type Ty, int32_t Offset) const; |
| 825 // Creates a new Base register centered around | 822 |
| 826 // [OrigBaseReg, +/- Offset]. | 823 void postLowerLegalization(); |
| 827 Variable *newBaseRegister(int32_t Offset, Variable *OrigBaseReg); | 824 |
| 828 /// Creates a new, legal OperandARM32Mem for accessing OrigBase + Offset. The | 825 class PostLoweringLegalizer { |
| 829 /// returned mem operand is a legal operand for accessing memory that is of | 826 PostLoweringLegalizer() = delete; |
| 830 /// type Ty. | 827 PostLoweringLegalizer(const PostLoweringLegalizer &) = delete; |
| 831 /// | 828 PostLoweringLegalizer &operator=(const PostLoweringLegalizer &) = delete; |
| 832 /// If [OrigBaseReg, #Offset] is encodable, then the method returns a Mem | 829 |
| 833 /// operand expressing it. Otherwise, | 830 public: |
| 834 /// | 831 explicit PostLoweringLegalizer(TargetARM32 *Target) |
| 835 /// if [*NewBaseReg, #Offset-*NewBaseOffset] is encodable, the method will | 832 : Target(Target), StackOrFrameReg(Target->getPhysicalRegister( |
| 836 /// return that. Otherwise, | 833 Target->getFrameOrStackReg())) {} |
| 837 /// | 834 |
| 838 /// a new base register ip=OrigBaseReg+Offset is created, and the method | 835 void resetTempBaseIfClobberedBy(const Inst *Instr); |
| 839 /// returns [ip, #0]. | 836 |
| 840 OperandARM32Mem *createMemOperand(Type Ty, int32_t Offset, | 837 // Ensures that the TempBase register held by the this legalizer (if any) is |
| 841 Variable *OrigBaseReg, | 838 // assigned to IP. |
| 842 Variable **NewBaseReg, | 839 void assertNoTempOrAssignedToIP() const { |
| 843 int32_t *NewBaseOffset); | 840 assert(TempBaseReg == nullptr || |
| 844 /// Legalizes Mov if its Source (or Destination) is a spilled Variable. Moves | 841 TempBaseReg->getRegNum() == Target->getReservedTmpReg()); |
| 845 /// to memory become store instructions, and moves from memory, loads. | 842 } |
| 846 void legalizeMov(InstARM32Mov *Mov, Variable *OrigBaseReg, | 843 |
| 847 Variable **NewBaseReg, int32_t *NewBaseOffset); | 844 // Legalizes Mem. if Mem.Base is a Reamaterializable variable, Mem.Offset is |
| 845 // fixed up. |
| 846 OperandARM32Mem *legalizeMemOperand(OperandARM32Mem *Mem, |
| 847 bool AllowOffsets = true); |
| 848 |
| 849 /// Legalizes Mov if its Source (or Destination) is a spilled Variable, or |
| 850 /// if its Source is a Rematerializable variable (this form is used in lieu |
| 851 /// of lea, which is not available in ARM.) |
| 852 /// |
| 853 /// Moves to memory become store instructions, and moves from memory, loads. |
| 854 void legalizeMov(InstARM32Mov *Mov); |
| 855 |
| 856 private: |
| 857 /// Creates a new Base register centered around [Base, +/- Offset]. |
| 858 Variable *newBaseRegister(Variable *Base, int32_t Offset, |
| 859 int32_t ScratchRegNum); |
| 860 |
| 861 /// Creates a new, legal OperandARM32Mem for accessing Base + Offset. |
| 862 /// The returned mem operand is a legal operand for accessing memory that is |
| 863 /// of type Ty. |
| 864 /// |
| 865 /// If [Base, #Offset] is encodable, then the method returns a Mem operand |
| 866 /// expressing it. Otherwise, |
| 867 /// |
| 868 /// if [TempBaseReg, #Offset-TempBaseOffset] is a valid memory operand, the |
| 869 /// method will return that. Otherwise, |
| 870 /// |
| 871 /// a new base register ip=Base+Offset is created, and the method returns a |
| 872 /// memory operand expressing [ip, #0]. |
| 873 OperandARM32Mem *createMemOperand(Type Ty, Variable *Base, int32_t Offset, |
| 874 bool AllowOffsets = true); |
| 875 TargetARM32 *const Target; |
| 876 Variable *const StackOrFrameReg; |
| 877 Variable *TempBaseReg = nullptr; |
| 878 int32_t TempBaseOffset = 0; |
| 879 }; |
| 848 | 880 |
| 849 TargetARM32Features CPUFeatures; | 881 TargetARM32Features CPUFeatures; |
| 850 bool UsesFramePointer = false; | 882 bool UsesFramePointer = false; |
| 851 bool NeedsStackAlignment = false; | 883 bool NeedsStackAlignment = false; |
| 852 bool MaybeLeafFunc = true; | 884 bool MaybeLeafFunc = true; |
| 853 size_t SpillAreaSizeBytes = 0; | 885 size_t SpillAreaSizeBytes = 0; |
| 854 size_t FixedAllocaSizeBytes = 0; | 886 size_t FixedAllocaSizeBytes = 0; |
| 855 size_t FixedAllocaAlignBytes = 0; | 887 size_t FixedAllocaAlignBytes = 0; |
| 856 bool PrologEmitsFixedAllocas = false; | 888 bool PrologEmitsFixedAllocas = false; |
| 857 uint32_t MaxOutArgsSizeBytes = 0; | 889 uint32_t MaxOutArgsSizeBytes = 0; |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1044 | 1076 |
| 1045 private: | 1077 private: |
| 1046 ~TargetHeaderARM32() = default; | 1078 ~TargetHeaderARM32() = default; |
| 1047 | 1079 |
| 1048 TargetARM32Features CPUFeatures; | 1080 TargetARM32Features CPUFeatures; |
| 1049 }; | 1081 }; |
| 1050 | 1082 |
| 1051 } // end of namespace Ice | 1083 } // end of namespace Ice |
| 1052 | 1084 |
| 1053 #endif // SUBZERO_SRC_ICETARGETLOWERINGARM32_H | 1085 #endif // SUBZERO_SRC_ICETARGETLOWERINGARM32_H |
| OLD | NEW |