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 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
121 void addEpilog(CfgNode *Node) override; | 121 void addEpilog(CfgNode *Node) override; |
122 | 122 |
123 Operand *loOperand(Operand *Operand); | 123 Operand *loOperand(Operand *Operand); |
124 Operand *hiOperand(Operand *Operand); | 124 Operand *hiOperand(Operand *Operand); |
125 void finishArgumentLowering(Variable *Arg, Variable *FramePtr, | 125 void finishArgumentLowering(Variable *Arg, Variable *FramePtr, |
126 size_t BasicFrameOffset, size_t &InArgsSizeBytes); | 126 size_t BasicFrameOffset, size_t &InArgsSizeBytes); |
127 | 127 |
128 bool hasCPUFeature(TargetARM32Features::ARM32InstructionSet I) const { | 128 bool hasCPUFeature(TargetARM32Features::ARM32InstructionSet I) const { |
129 return CPUFeatures.hasFeature(I); | 129 return CPUFeatures.hasFeature(I); |
130 } | 130 } |
| 131 |
| 132 enum OperandLegalization { |
| 133 Legal_None = 0, |
| 134 Legal_Reg = 1 << 0, /// physical register, not stack location |
| 135 Legal_Flex = 1 << 1, /// A flexible operand2, which can hold rotated small |
| 136 /// immediates, shifted registers, or modified fp imm. |
| 137 Legal_Mem = 1 << 2, /// includes [r0, r1 lsl #2] as well as [sp, #12] |
| 138 Legal_All = ~Legal_None |
| 139 }; |
| 140 |
| 141 using LegalMask = uint32_t; |
131 Operand *legalizeUndef(Operand *From, int32_t RegNum = Variable::NoRegister); | 142 Operand *legalizeUndef(Operand *From, int32_t RegNum = Variable::NoRegister); |
| 143 Operand *legalize(Operand *From, LegalMask Allowed = Legal_All, |
| 144 int32_t RegNum = Variable::NoRegister); |
| 145 Variable *legalizeToReg(Operand *From, int32_t RegNum = Variable::NoRegister); |
| 146 |
| 147 GlobalContext *getCtx() const { return Ctx; } |
132 | 148 |
133 protected: | 149 protected: |
134 explicit TargetARM32(Cfg *Func); | 150 explicit TargetARM32(Cfg *Func); |
135 | 151 |
136 void postLower() override; | 152 void postLower() override; |
137 | 153 |
138 enum SafeBoolChain { | 154 enum SafeBoolChain { |
139 SBC_No, | 155 SBC_No, |
140 SBC_Yes, | 156 SBC_Yes, |
141 }; | 157 }; |
142 | 158 |
143 void lowerAlloca(const InstAlloca *Inst) override; | 159 void lowerAlloca(const InstAlloca *Inst) override; |
144 SafeBoolChain lowerInt1Arithmetic(const InstArithmetic *Inst); | 160 SafeBoolChain lowerInt1Arithmetic(const InstArithmetic *Inst); |
| 161 void lowerInt64Arithmetic(InstArithmetic::OpKind Op, Variable *Dest, |
| 162 Operand *Src0, Operand *Src1); |
145 void lowerArithmetic(const InstArithmetic *Inst) override; | 163 void lowerArithmetic(const InstArithmetic *Inst) override; |
146 void lowerAssign(const InstAssign *Inst) override; | 164 void lowerAssign(const InstAssign *Inst) override; |
147 void lowerBr(const InstBr *Inst) override; | 165 void lowerBr(const InstBr *Inst) override; |
148 void lowerCall(const InstCall *Inst) override; | 166 void lowerCall(const InstCall *Inst) override; |
149 void lowerCast(const InstCast *Inst) override; | 167 void lowerCast(const InstCast *Inst) override; |
150 void lowerExtractElement(const InstExtractElement *Inst) override; | 168 void lowerExtractElement(const InstExtractElement *Inst) override; |
151 | 169 |
152 /// CondWhenTrue is a helper type returned by every method in the lowering | 170 /// CondWhenTrue is a helper type returned by every method in the lowering |
153 /// that emits code to set the condition codes. | 171 /// that emits code to set the condition codes. |
154 class CondWhenTrue { | 172 class CondWhenTrue { |
(...skipping 18 matching lines...) Expand all Loading... |
173 case CondARM32::AL: | 191 case CondARM32::AL: |
174 return CondWhenTrue(CondARM32::kNone); | 192 return CondWhenTrue(CondARM32::kNone); |
175 case CondARM32::kNone: | 193 case CondARM32::kNone: |
176 return CondWhenTrue(CondARM32::AL); | 194 return CondWhenTrue(CondARM32::AL); |
177 } | 195 } |
178 } | 196 } |
179 }; | 197 }; |
180 | 198 |
181 CondWhenTrue lowerFcmpCond(const InstFcmp *Instr); | 199 CondWhenTrue lowerFcmpCond(const InstFcmp *Instr); |
182 void lowerFcmp(const InstFcmp *Instr) override; | 200 void lowerFcmp(const InstFcmp *Instr) override; |
| 201 CondWhenTrue lowerInt8AndInt16IcmpCond(InstIcmp::ICond Condition, |
| 202 Operand *Src0, Operand *Src1); |
| 203 CondWhenTrue lowerInt32IcmpCond(InstIcmp::ICond Condition, Operand *Src0, |
| 204 Operand *Src1); |
| 205 CondWhenTrue lowerInt64IcmpCond(InstIcmp::ICond Condition, Operand *Src0, |
| 206 Operand *Src1); |
183 CondWhenTrue lowerIcmpCond(const InstIcmp *Instr); | 207 CondWhenTrue lowerIcmpCond(const InstIcmp *Instr); |
184 void lowerIcmp(const InstIcmp *Instr) override; | 208 void lowerIcmp(const InstIcmp *Instr) override; |
185 void lowerAtomicRMW(Variable *Dest, uint32_t Operation, Operand *Ptr, | 209 void lowerAtomicRMW(Variable *Dest, uint32_t Operation, Operand *Ptr, |
186 Operand *Val); | 210 Operand *Val); |
187 void lowerIntrinsicCall(const InstIntrinsicCall *Inst) override; | 211 void lowerIntrinsicCall(const InstIntrinsicCall *Inst) override; |
188 void lowerInsertElement(const InstInsertElement *Inst) override; | 212 void lowerInsertElement(const InstInsertElement *Inst) override; |
189 void lowerLoad(const InstLoad *Inst) override; | 213 void lowerLoad(const InstLoad *Inst) override; |
190 void lowerPhi(const InstPhi *Inst) override; | 214 void lowerPhi(const InstPhi *Inst) override; |
191 void lowerRet(const InstRet *Inst) override; | 215 void lowerRet(const InstRet *Inst) override; |
192 void lowerSelect(const InstSelect *Inst) override; | 216 void lowerSelect(const InstSelect *Inst) override; |
193 void lowerStore(const InstStore *Inst) override; | 217 void lowerStore(const InstStore *Inst) override; |
194 void lowerSwitch(const InstSwitch *Inst) override; | 218 void lowerSwitch(const InstSwitch *Inst) override; |
195 void lowerUnreachable(const InstUnreachable *Inst) override; | 219 void lowerUnreachable(const InstUnreachable *Inst) override; |
196 void prelowerPhis() override; | 220 void prelowerPhis() override; |
197 void doAddressOptLoad() override; | 221 void doAddressOptLoad() override; |
198 void doAddressOptStore() override; | 222 void doAddressOptStore() override; |
199 void randomlyInsertNop(float Probability, | 223 void randomlyInsertNop(float Probability, |
200 RandomNumberGenerator &RNG) override; | 224 RandomNumberGenerator &RNG) override; |
201 | 225 |
202 enum OperandLegalization { | |
203 Legal_None = 0, | |
204 Legal_Reg = 1 << 0, /// physical register, not stack location | |
205 Legal_Flex = 1 << 1, /// A flexible operand2, which can hold rotated small | |
206 /// immediates, or shifted registers. | |
207 Legal_Mem = 1 << 2, /// includes [r0, r1 lsl #2] as well as [sp, #12] | |
208 Legal_All = ~Legal_None | |
209 }; | |
210 using LegalMask = uint32_t; | |
211 Operand *legalize(Operand *From, LegalMask Allowed = Legal_All, | |
212 int32_t RegNum = Variable::NoRegister); | |
213 Variable *legalizeToReg(Operand *From, int32_t RegNum = Variable::NoRegister); | |
214 OperandARM32Mem *formMemoryOperand(Operand *Ptr, Type Ty); | 226 OperandARM32Mem *formMemoryOperand(Operand *Ptr, Type Ty); |
215 | 227 |
216 Variable64On32 *makeI64RegPair(); | 228 Variable64On32 *makeI64RegPair(); |
217 Variable *makeReg(Type Ty, int32_t RegNum = Variable::NoRegister); | 229 Variable *makeReg(Type Ty, int32_t RegNum = Variable::NoRegister); |
218 static Type stackSlotType(); | 230 static Type stackSlotType(); |
219 Variable *copyToReg(Operand *Src, int32_t RegNum = Variable::NoRegister); | 231 Variable *copyToReg(Operand *Src, int32_t RegNum = Variable::NoRegister); |
220 void alignRegisterPow2(Variable *Reg, uint32_t Align); | 232 void alignRegisterPow2(Variable *Reg, uint32_t Align); |
221 | 233 |
222 /// Returns a vector in a register with the given constant entries. | 234 /// Returns a vector in a register with the given constant entries. |
223 Variable *makeVectorOfZeros(Type Ty, int32_t RegNum = Variable::NoRegister); | 235 Variable *makeVectorOfZeros(Type Ty, int32_t RegNum = Variable::NoRegister); |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
280 } | 292 } |
281 void _br(CfgNode *Target) { | 293 void _br(CfgNode *Target) { |
282 Context.insert(InstARM32Br::create(Func, Target)); | 294 Context.insert(InstARM32Br::create(Func, Target)); |
283 } | 295 } |
284 void _br(CfgNode *Target, CondARM32::Cond Condition) { | 296 void _br(CfgNode *Target, CondARM32::Cond Condition) { |
285 Context.insert(InstARM32Br::create(Func, Target, Condition)); | 297 Context.insert(InstARM32Br::create(Func, Target, Condition)); |
286 } | 298 } |
287 void _br(InstARM32Label *Label, CondARM32::Cond Condition) { | 299 void _br(InstARM32Label *Label, CondARM32::Cond Condition) { |
288 Context.insert(InstARM32Br::create(Func, Label, Condition)); | 300 Context.insert(InstARM32Br::create(Func, Label, Condition)); |
289 } | 301 } |
| 302 void _cmn(Variable *Src0, Operand *Src1, |
| 303 CondARM32::Cond Pred = CondARM32::AL) { |
| 304 Context.insert(InstARM32Cmn::create(Func, Src0, Src1, Pred)); |
| 305 } |
290 void _cmp(Variable *Src0, Operand *Src1, | 306 void _cmp(Variable *Src0, Operand *Src1, |
291 CondARM32::Cond Pred = CondARM32::AL) { | 307 CondARM32::Cond Pred = CondARM32::AL) { |
292 Context.insert(InstARM32Cmp::create(Func, Src0, Src1, Pred)); | 308 Context.insert(InstARM32Cmp::create(Func, Src0, Src1, Pred)); |
293 } | 309 } |
294 void _clz(Variable *Dest, Variable *Src0, | 310 void _clz(Variable *Dest, Variable *Src0, |
295 CondARM32::Cond Pred = CondARM32::AL) { | 311 CondARM32::Cond Pred = CondARM32::AL) { |
296 Context.insert(InstARM32Clz::create(Func, Dest, Src0, Pred)); | 312 Context.insert(InstARM32Clz::create(Func, Dest, Src0, Pred)); |
297 } | 313 } |
298 void _dmb() { Context.insert(InstARM32Dmb::create(Func)); } | 314 void _dmb() { Context.insert(InstARM32Dmb::create(Func)); } |
299 void _eor(Variable *Dest, Variable *Src0, Operand *Src1, | 315 void _eor(Variable *Dest, Variable *Src0, Operand *Src1, |
(...skipping 13 matching lines...) Expand all Loading... |
313 Context.insert(InstARM32Ldrex::create(Func, Dest, Addr, Pred)); | 329 Context.insert(InstARM32Ldrex::create(Func, Dest, Addr, Pred)); |
314 if (auto *Dest64 = llvm::dyn_cast<Variable64On32>(Dest)) { | 330 if (auto *Dest64 = llvm::dyn_cast<Variable64On32>(Dest)) { |
315 Context.insert(InstFakeDef::create(Func, Dest64->getLo(), Dest)); | 331 Context.insert(InstFakeDef::create(Func, Dest64->getLo(), Dest)); |
316 Context.insert(InstFakeDef::create(Func, Dest64->getHi(), Dest)); | 332 Context.insert(InstFakeDef::create(Func, Dest64->getHi(), Dest)); |
317 } | 333 } |
318 } | 334 } |
319 void _lsl(Variable *Dest, Variable *Src0, Operand *Src1, | 335 void _lsl(Variable *Dest, Variable *Src0, Operand *Src1, |
320 CondARM32::Cond Pred = CondARM32::AL) { | 336 CondARM32::Cond Pred = CondARM32::AL) { |
321 Context.insert(InstARM32Lsl::create(Func, Dest, Src0, Src1, Pred)); | 337 Context.insert(InstARM32Lsl::create(Func, Dest, Src0, Src1, Pred)); |
322 } | 338 } |
| 339 void _lsls(Variable *Dest, Variable *Src0, Operand *Src1, |
| 340 CondARM32::Cond Pred = CondARM32::AL) { |
| 341 constexpr bool SetFlags = true; |
| 342 Context.insert( |
| 343 InstARM32Lsl::create(Func, Dest, Src0, Src1, Pred, SetFlags)); |
| 344 } |
323 void _lsr(Variable *Dest, Variable *Src0, Operand *Src1, | 345 void _lsr(Variable *Dest, Variable *Src0, Operand *Src1, |
324 CondARM32::Cond Pred = CondARM32::AL) { | 346 CondARM32::Cond Pred = CondARM32::AL) { |
325 Context.insert(InstARM32Lsr::create(Func, Dest, Src0, Src1, Pred)); | 347 Context.insert(InstARM32Lsr::create(Func, Dest, Src0, Src1, Pred)); |
326 } | 348 } |
327 void _mla(Variable *Dest, Variable *Src0, Variable *Src1, Variable *Acc, | 349 void _mla(Variable *Dest, Variable *Src0, Variable *Src1, Variable *Acc, |
328 CondARM32::Cond Pred = CondARM32::AL) { | 350 CondARM32::Cond Pred = CondARM32::AL) { |
329 Context.insert(InstARM32Mla::create(Func, Dest, Src0, Src1, Acc, Pred)); | 351 Context.insert(InstARM32Mla::create(Func, Dest, Src0, Src1, Acc, Pred)); |
330 } | 352 } |
331 void _mls(Variable *Dest, Variable *Src0, Variable *Src1, Variable *Acc, | 353 void _mls(Variable *Dest, Variable *Src0, Variable *Src1, Variable *Acc, |
332 CondARM32::Cond Pred = CondARM32::AL) { | 354 CondARM32::Cond Pred = CondARM32::AL) { |
(...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
635 CondARM32::Cond Pred = CondARM32::AL) { | 657 CondARM32::Cond Pred = CondARM32::AL) { |
636 Context.insert(InstARM32Rbit::create(Func, Dest, Src0, Pred)); | 658 Context.insert(InstARM32Rbit::create(Func, Dest, Src0, Pred)); |
637 } | 659 } |
638 void _rev(Variable *Dest, Variable *Src0, | 660 void _rev(Variable *Dest, Variable *Src0, |
639 CondARM32::Cond Pred = CondARM32::AL) { | 661 CondARM32::Cond Pred = CondARM32::AL) { |
640 Context.insert(InstARM32Rev::create(Func, Dest, Src0, Pred)); | 662 Context.insert(InstARM32Rev::create(Func, Dest, Src0, Pred)); |
641 } | 663 } |
642 void _ret(Variable *LR, Variable *Src0 = nullptr) { | 664 void _ret(Variable *LR, Variable *Src0 = nullptr) { |
643 Context.insert(InstARM32Ret::create(Func, LR, Src0)); | 665 Context.insert(InstARM32Ret::create(Func, LR, Src0)); |
644 } | 666 } |
| 667 void _rscs(Variable *Dest, Variable *Src0, Operand *Src1, |
| 668 CondARM32::Cond Pred = CondARM32::AL) { |
| 669 constexpr bool SetFlags = true; |
| 670 Context.insert( |
| 671 InstARM32Rsc::create(Func, Dest, Src0, Src1, Pred, SetFlags)); |
| 672 } |
| 673 void _rsc(Variable *Dest, Variable *Src0, Operand *Src1, |
| 674 CondARM32::Cond Pred = CondARM32::AL) { |
| 675 Context.insert(InstARM32Rsc::create(Func, Dest, Src0, Src1, Pred)); |
| 676 } |
| 677 void _rsbs(Variable *Dest, Variable *Src0, Operand *Src1, |
| 678 CondARM32::Cond Pred = CondARM32::AL) { |
| 679 constexpr bool SetFlags = true; |
| 680 Context.insert( |
| 681 InstARM32Rsb::create(Func, Dest, Src0, Src1, Pred, SetFlags)); |
| 682 } |
645 void _rsb(Variable *Dest, Variable *Src0, Operand *Src1, | 683 void _rsb(Variable *Dest, Variable *Src0, Operand *Src1, |
646 CondARM32::Cond Pred = CondARM32::AL) { | 684 CondARM32::Cond Pred = CondARM32::AL) { |
647 Context.insert(InstARM32Rsb::create(Func, Dest, Src0, Src1, Pred)); | 685 Context.insert(InstARM32Rsb::create(Func, Dest, Src0, Src1, Pred)); |
648 } | 686 } |
649 void _sbc(Variable *Dest, Variable *Src0, Operand *Src1, | 687 void _sbc(Variable *Dest, Variable *Src0, Operand *Src1, |
650 CondARM32::Cond Pred = CondARM32::AL) { | 688 CondARM32::Cond Pred = CondARM32::AL) { |
651 Context.insert(InstARM32Sbc::create(Func, Dest, Src0, Src1, Pred)); | 689 Context.insert(InstARM32Sbc::create(Func, Dest, Src0, Src1, Pred)); |
652 } | 690 } |
653 void _sbcs(Variable *Dest, Variable *Src0, Operand *Src1, | 691 void _sbcs(Variable *Dest, Variable *Src0, Operand *Src1, |
654 CondARM32::Cond Pred = CondARM32::AL) { | 692 CondARM32::Cond Pred = CondARM32::AL) { |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
726 CondARM32::Cond Pred = CondARM32::AL) { | 764 CondARM32::Cond Pred = CondARM32::AL) { |
727 Context.insert(InstARM32Vcvt::create(Func, Dest, Src, Variant, Pred)); | 765 Context.insert(InstARM32Vcvt::create(Func, Dest, Src, Variant, Pred)); |
728 } | 766 } |
729 void _vdiv(Variable *Dest, Variable *Src0, Variable *Src1) { | 767 void _vdiv(Variable *Dest, Variable *Src0, Variable *Src1) { |
730 Context.insert(InstARM32Vdiv::create(Func, Dest, Src0, Src1)); | 768 Context.insert(InstARM32Vdiv::create(Func, Dest, Src0, Src1)); |
731 } | 769 } |
732 void _vcmp(Variable *Src0, Variable *Src1, | 770 void _vcmp(Variable *Src0, Variable *Src1, |
733 CondARM32::Cond Pred = CondARM32::AL) { | 771 CondARM32::Cond Pred = CondARM32::AL) { |
734 Context.insert(InstARM32Vcmp::create(Func, Src0, Src1, Pred)); | 772 Context.insert(InstARM32Vcmp::create(Func, Src0, Src1, Pred)); |
735 } | 773 } |
| 774 void _vcmp(Variable *Src0, OperandARM32FlexFpZero *FpZero, |
| 775 CondARM32::Cond Pred = CondARM32::AL) { |
| 776 Context.insert(InstARM32Vcmp::create(Func, Src0, FpZero, Pred)); |
| 777 } |
736 void _vmrs(CondARM32::Cond Pred = CondARM32::AL) { | 778 void _vmrs(CondARM32::Cond Pred = CondARM32::AL) { |
737 Context.insert(InstARM32Vmrs::create(Func, Pred)); | 779 Context.insert(InstARM32Vmrs::create(Func, Pred)); |
738 } | 780 } |
739 void _vmul(Variable *Dest, Variable *Src0, Variable *Src1) { | 781 void _vmul(Variable *Dest, Variable *Src0, Variable *Src1) { |
740 Context.insert(InstARM32Vmul::create(Func, Dest, Src0, Src1)); | 782 Context.insert(InstARM32Vmul::create(Func, Dest, Src0, Src1)); |
741 } | 783 } |
| 784 void _veor(Variable *Dest, Variable *Src0, Variable *Src1) { |
| 785 Context.insert(InstARM32Veor::create(Func, Dest, Src0, Src1)); |
| 786 } |
742 void _vsqrt(Variable *Dest, Variable *Src, | 787 void _vsqrt(Variable *Dest, Variable *Src, |
743 CondARM32::Cond Pred = CondARM32::AL) { | 788 CondARM32::Cond Pred = CondARM32::AL) { |
744 Context.insert(InstARM32Vsqrt::create(Func, Dest, Src, Pred)); | 789 Context.insert(InstARM32Vsqrt::create(Func, Dest, Src, Pred)); |
745 } | 790 } |
746 void _vsub(Variable *Dest, Variable *Src0, Variable *Src1) { | 791 void _vsub(Variable *Dest, Variable *Src0, Variable *Src1) { |
747 Context.insert(InstARM32Vsub::create(Func, Dest, Src0, Src1)); | 792 Context.insert(InstARM32Vsub::create(Func, Dest, Src0, Src1)); |
748 } | 793 } |
749 | 794 |
750 /// Run a pass through stack variables and ensure that the offsets are legal. | 795 /// Run a pass through stack variables and ensure that the offsets are legal. |
751 /// If the offset is not legal, use a new base register that accounts for the | 796 /// If the offset is not legal, use a new base register that accounts for the |
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
932 | 977 |
933 private: | 978 private: |
934 ~TargetHeaderARM32() = default; | 979 ~TargetHeaderARM32() = default; |
935 | 980 |
936 TargetARM32Features CPUFeatures; | 981 TargetARM32Features CPUFeatures; |
937 }; | 982 }; |
938 | 983 |
939 } // end of namespace Ice | 984 } // end of namespace Ice |
940 | 985 |
941 #endif // SUBZERO_SRC_ICETARGETLOWERINGARM32_H | 986 #endif // SUBZERO_SRC_ICETARGETLOWERINGARM32_H |
OLD | NEW |