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 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
128 void emit(const ConstantFloat *C) const final; | 128 void emit(const ConstantFloat *C) const final; |
129 void emit(const ConstantDouble *C) const final; | 129 void emit(const ConstantDouble *C) const final; |
130 | 130 |
131 void lowerArguments() override; | 131 void lowerArguments() override; |
132 void addProlog(CfgNode *Node) override; | 132 void addProlog(CfgNode *Node) override; |
133 void addEpilog(CfgNode *Node) override; | 133 void addEpilog(CfgNode *Node) override; |
134 | 134 |
135 Operand *loOperand(Operand *Operand); | 135 Operand *loOperand(Operand *Operand); |
136 Operand *hiOperand(Operand *Operand); | 136 Operand *hiOperand(Operand *Operand); |
137 void finishArgumentLowering(Variable *Arg, Variable *FramePtr, | 137 void finishArgumentLowering(Variable *Arg, Variable *FramePtr, |
138 size_t BasicFrameOffset, size_t &InArgsSizeBytes); | 138 size_t BasicFrameOffset, size_t *InArgsSizeBytes); |
139 | 139 |
140 bool hasCPUFeature(TargetARM32Features::ARM32InstructionSet I) const { | 140 bool hasCPUFeature(TargetARM32Features::ARM32InstructionSet I) const { |
141 return CPUFeatures.hasFeature(I); | 141 return CPUFeatures.hasFeature(I); |
142 } | 142 } |
143 | 143 |
144 enum OperandLegalization { | 144 enum OperandLegalization { |
145 Legal_None = 0, | 145 Legal_None = 0, |
146 Legal_Reg = 1 << 0, /// physical register, not stack location | 146 Legal_Reg = 1 << 0, /// physical register, not stack location |
147 Legal_Flex = 1 << 1, /// A flexible operand2, which can hold rotated small | 147 Legal_Flex = 1 << 1, /// A flexible operand2, which can hold rotated small |
148 /// immediates, shifted registers, or modified fp imm. | 148 /// immediates, shifted registers, or modified fp imm. |
(...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
377 /// all types (integer, floating point, and vectors), as well as moves between | 377 /// all types (integer, floating point, and vectors), as well as moves between |
378 /// Core and VFP registers. This is not a panacea: you must obey the (weird, | 378 /// Core and VFP registers. This is not a panacea: you must obey the (weird, |
379 /// confusing, non-uniform) rules for data moves in ARM. | 379 /// confusing, non-uniform) rules for data moves in ARM. |
380 void _mov(Variable *Dest, Operand *Src0, | 380 void _mov(Variable *Dest, Operand *Src0, |
381 CondARM32::Cond Pred = CondARM32::AL) { | 381 CondARM32::Cond Pred = CondARM32::AL) { |
382 // _mov used to be unique in the sense that it would create a temporary | 382 // _mov used to be unique in the sense that it would create a temporary |
383 // automagically if Dest was nullptr. It won't do that anymore, so we keep | 383 // automagically if Dest was nullptr. It won't do that anymore, so we keep |
384 // an assert around just in case there is some untested code path where Dest | 384 // an assert around just in case there is some untested code path where Dest |
385 // is nullptr. | 385 // is nullptr. |
386 assert(Dest != nullptr); | 386 assert(Dest != nullptr); |
| 387 assert(!llvm::isa<OperandARM32Mem>(Src0)); |
387 auto *Instr = InstARM32Mov::create(Func, Dest, Src0, Pred); | 388 auto *Instr = InstARM32Mov::create(Func, Dest, Src0, Pred); |
388 | 389 |
389 Context.insert(Instr); | 390 Context.insert(Instr); |
390 if (Instr->isMultiDest()) { | 391 if (Instr->isMultiDest()) { |
391 // If Instr is multi-dest, then Dest must be a Variable64On32. We add a | 392 // If Instr is multi-dest, then Dest must be a Variable64On32. We add a |
392 // fake-def for Instr.DestHi here. | 393 // fake-def for Instr.DestHi here. |
393 assert(llvm::isa<Variable64On32>(Dest)); | 394 assert(llvm::isa<Variable64On32>(Dest)); |
394 Context.insert(InstFakeDef::create(Func, Instr->getDestHi())); | 395 Context.insert(InstFakeDef::create(Func, Instr->getDestHi())); |
395 } | 396 } |
396 } | 397 } |
(...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
787 Context.insert(InstARM32Vdiv::create(Func, Dest, Src0, Src1)); | 788 Context.insert(InstARM32Vdiv::create(Func, Dest, Src0, Src1)); |
788 } | 789 } |
789 void _vcmp(Variable *Src0, Variable *Src1, | 790 void _vcmp(Variable *Src0, Variable *Src1, |
790 CondARM32::Cond Pred = CondARM32::AL) { | 791 CondARM32::Cond Pred = CondARM32::AL) { |
791 Context.insert(InstARM32Vcmp::create(Func, Src0, Src1, Pred)); | 792 Context.insert(InstARM32Vcmp::create(Func, Src0, Src1, Pred)); |
792 } | 793 } |
793 void _vcmp(Variable *Src0, OperandARM32FlexFpZero *FpZero, | 794 void _vcmp(Variable *Src0, OperandARM32FlexFpZero *FpZero, |
794 CondARM32::Cond Pred = CondARM32::AL) { | 795 CondARM32::Cond Pred = CondARM32::AL) { |
795 Context.insert(InstARM32Vcmp::create(Func, Src0, FpZero, Pred)); | 796 Context.insert(InstARM32Vcmp::create(Func, Src0, FpZero, Pred)); |
796 } | 797 } |
| 798 void _veor(Variable *Dest, Variable *Src0, Variable *Src1) { |
| 799 Context.insert(InstARM32Veor::create(Func, Dest, Src0, Src1)); |
| 800 } |
797 void _vmrs(CondARM32::Cond Pred = CondARM32::AL) { | 801 void _vmrs(CondARM32::Cond Pred = CondARM32::AL) { |
798 Context.insert(InstARM32Vmrs::create(Func, Pred)); | 802 Context.insert(InstARM32Vmrs::create(Func, Pred)); |
799 } | 803 } |
800 void _vmul(Variable *Dest, Variable *Src0, Variable *Src1) { | 804 void _vmul(Variable *Dest, Variable *Src0, Variable *Src1) { |
801 Context.insert(InstARM32Vmul::create(Func, Dest, Src0, Src1)); | 805 Context.insert(InstARM32Vmul::create(Func, Dest, Src0, Src1)); |
802 } | 806 } |
803 void _veor(Variable *Dest, Variable *Src0, Variable *Src1) { | |
804 Context.insert(InstARM32Veor::create(Func, Dest, Src0, Src1)); | |
805 } | |
806 void _vsqrt(Variable *Dest, Variable *Src, | 807 void _vsqrt(Variable *Dest, Variable *Src, |
807 CondARM32::Cond Pred = CondARM32::AL) { | 808 CondARM32::Cond Pred = CondARM32::AL) { |
808 Context.insert(InstARM32Vsqrt::create(Func, Dest, Src, Pred)); | 809 Context.insert(InstARM32Vsqrt::create(Func, Dest, Src, Pred)); |
809 } | 810 } |
810 void _vsub(Variable *Dest, Variable *Src0, Variable *Src1) { | 811 void _vsub(Variable *Dest, Variable *Src0, Variable *Src1) { |
811 Context.insert(InstARM32Vsub::create(Func, Dest, Src0, Src1)); | 812 Context.insert(InstARM32Vsub::create(Func, Dest, Src0, Src1)); |
812 } | 813 } |
813 | 814 |
814 /// Run a pass through stack variables and ensure that the offsets are legal. | 815 /// Run a pass through stack variables and ensure that the offsets are legal. |
815 /// If the offset is not legal, use a new base register that accounts for the | 816 /// If the offset is not legal, use a new base register that accounts for the |
816 /// offset, such that the addressing mode offset bits are now legal. | 817 /// offset, such that the addressing mode offset bits are now legal. |
817 void legalizeStackSlots(); | 818 void legalizeStackSlots(); |
818 /// Returns true if the given Offset can be represented in a ldr/str. | 819 /// Returns true if the given Offset can be represented in a ldr/str. |
819 bool isLegalMemOffset(Type Ty, int32_t Offset) const; | 820 bool isLegalMemOffset(Type Ty, int32_t Offset) const; |
820 // Creates a new Base register centered around | 821 // Creates a new Base register centered around |
821 // [OrigBaseReg, +/- Offset+StackAdjust]. | 822 // [OrigBaseReg, +/- Offset+StackAdjust]. |
822 Variable *newBaseRegister(int32_t Offset, int32_t StackAdjust, | 823 Variable *newBaseRegister(int32_t Offset, int32_t StackAdjust, |
823 Variable *OrigBaseReg); | 824 Variable *OrigBaseReg); |
824 /// Creates a new, legal StackVariable w.r.t. ARM's Immediate requirements. | 825 /// Creates a new, legal OperandARM32Mem for accessing OrigBase + Offset + |
825 /// This method is not very smart: it will always create and return a new | 826 /// StackAdjust. The returned mem operand is a legal operand for accessing |
826 /// StackVariable, even if Offset + StackAdjust is encodable. | 827 /// memory that is of type Ty. |
827 StackVariable *legalizeStackSlot(Type Ty, int32_t Offset, int32_t StackAdjust, | 828 /// |
828 Variable *OrigBaseReg, Variable **NewBaseReg, | 829 /// If [OrigBaseReg, #Offset+StackAdjust] is encodable, then the method |
829 int32_t *NewBaseOffset); | 830 /// returns a Mem operand expressing it. Otherwise, |
830 /// Legalizes Mov if its Source (or Destination) contains an invalid | 831 /// |
831 /// immediate. | 832 /// if [*NewBaseReg, #Offset+StackAdjust-*NewBaseOffset] is encodable, the |
832 void legalizeMovStackAddrImm(InstARM32Mov *Mov, int32_t StackAdjust, | 833 /// method will return that. Otherwise, |
833 Variable *OrigBaseReg, Variable **NewBaseReg, | 834 /// |
834 int32_t *NewBaseOffset); | 835 /// a new base register ip=OrigBaseReg+Offset+StackAdjust is created, and the |
| 836 /// method returns [ip, #0]. |
| 837 OperandARM32Mem *createMemOperand(Type Ty, int32_t Offset, |
| 838 int32_t StackAdjust, Variable *OrigBaseReg, |
| 839 Variable **NewBaseReg, |
| 840 int32_t *NewBaseOffset); |
| 841 /// Legalizes Mov if its Source (or Destination) is a spilled Variable. Moves |
| 842 /// to memory become store instructions, and moves from memory, loads. |
| 843 void legalizeMov(InstARM32Mov *Mov, int32_t StackAdjust, |
| 844 Variable *OrigBaseReg, Variable **NewBaseReg, |
| 845 int32_t *NewBaseOffset); |
835 | 846 |
836 TargetARM32Features CPUFeatures; | 847 TargetARM32Features CPUFeatures; |
837 bool UsesFramePointer = false; | 848 bool UsesFramePointer = false; |
838 bool NeedsStackAlignment = false; | 849 bool NeedsStackAlignment = false; |
839 bool MaybeLeafFunc = true; | 850 bool MaybeLeafFunc = true; |
840 size_t SpillAreaSizeBytes = 0; | 851 size_t SpillAreaSizeBytes = 0; |
841 // TODO(jpp): std::array instead of array. | 852 // TODO(jpp): std::array instead of array. |
842 static llvm::SmallBitVector TypeToRegisterSet[RCARM32_NUM]; | 853 static llvm::SmallBitVector TypeToRegisterSet[RCARM32_NUM]; |
843 static llvm::SmallBitVector RegisterAliases[RegARM32::Reg_NUM]; | 854 static llvm::SmallBitVector RegisterAliases[RegARM32::Reg_NUM]; |
844 static llvm::SmallBitVector ScratchRegs; | 855 static llvm::SmallBitVector ScratchRegs; |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
996 | 1007 |
997 private: | 1008 private: |
998 ~TargetHeaderARM32() = default; | 1009 ~TargetHeaderARM32() = default; |
999 | 1010 |
1000 TargetARM32Features CPUFeatures; | 1011 TargetARM32Features CPUFeatures; |
1001 }; | 1012 }; |
1002 | 1013 |
1003 } // end of namespace Ice | 1014 } // end of namespace Ice |
1004 | 1015 |
1005 #endif // SUBZERO_SRC_ICETARGETLOWERINGARM32_H | 1016 #endif // SUBZERO_SRC_ICETARGETLOWERINGARM32_H |
OLD | NEW |