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 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 |
| 144 enum OperandLegalization { |
| 145 Legal_None = 0, |
| 146 Legal_Reg = 1 << 0, /// physical register, not stack location |
| 147 Legal_Flex = 1 << 1, /// A flexible operand2, which can hold rotated small |
| 148 /// immediates, shifted registers, or modified fp imm. |
| 149 Legal_Mem = 1 << 2, /// includes [r0, r1 lsl #2] as well as [sp, #12] |
| 150 Legal_All = ~Legal_None |
| 151 }; |
| 152 |
| 153 using LegalMask = uint32_t; |
143 Operand *legalizeUndef(Operand *From, int32_t RegNum = Variable::NoRegister); | 154 Operand *legalizeUndef(Operand *From, int32_t RegNum = Variable::NoRegister); |
| 155 Operand *legalize(Operand *From, LegalMask Allowed = Legal_All, |
| 156 int32_t RegNum = Variable::NoRegister); |
| 157 Variable *legalizeToReg(Operand *From, int32_t RegNum = Variable::NoRegister); |
| 158 |
| 159 GlobalContext *getCtx() const { return Ctx; } |
144 | 160 |
145 protected: | 161 protected: |
146 explicit TargetARM32(Cfg *Func); | 162 explicit TargetARM32(Cfg *Func); |
147 | 163 |
148 void postLower() override; | 164 void postLower() override; |
149 | 165 |
150 enum SafeBoolChain { | 166 enum SafeBoolChain { |
151 SBC_No, | 167 SBC_No, |
152 SBC_Yes, | 168 SBC_Yes, |
153 }; | 169 }; |
154 | 170 |
155 void lowerAlloca(const InstAlloca *Inst) override; | 171 void lowerAlloca(const InstAlloca *Inst) override; |
156 SafeBoolChain lowerInt1Arithmetic(const InstArithmetic *Inst); | 172 SafeBoolChain lowerInt1Arithmetic(const InstArithmetic *Inst); |
| 173 void lowerInt64Arithmetic(InstArithmetic::OpKind Op, Variable *Dest, |
| 174 Operand *Src0, Operand *Src1); |
157 void lowerArithmetic(const InstArithmetic *Inst) override; | 175 void lowerArithmetic(const InstArithmetic *Inst) override; |
158 void lowerAssign(const InstAssign *Inst) override; | 176 void lowerAssign(const InstAssign *Inst) override; |
159 void lowerBr(const InstBr *Inst) override; | 177 void lowerBr(const InstBr *Inst) override; |
160 void lowerCall(const InstCall *Inst) override; | 178 void lowerCall(const InstCall *Inst) override; |
161 void lowerCast(const InstCast *Inst) override; | 179 void lowerCast(const InstCast *Inst) override; |
162 void lowerExtractElement(const InstExtractElement *Inst) override; | 180 void lowerExtractElement(const InstExtractElement *Inst) override; |
163 | 181 |
164 /// CondWhenTrue is a helper type returned by every method in the lowering | 182 /// CondWhenTrue is a helper type returned by every method in the lowering |
165 /// that emits code to set the condition codes. | 183 /// that emits code to set the condition codes. |
166 class CondWhenTrue { | 184 class CondWhenTrue { |
(...skipping 18 matching lines...) Expand all Loading... |
185 case CondARM32::AL: | 203 case CondARM32::AL: |
186 return CondWhenTrue(CondARM32::kNone); | 204 return CondWhenTrue(CondARM32::kNone); |
187 case CondARM32::kNone: | 205 case CondARM32::kNone: |
188 return CondWhenTrue(CondARM32::AL); | 206 return CondWhenTrue(CondARM32::AL); |
189 } | 207 } |
190 } | 208 } |
191 }; | 209 }; |
192 | 210 |
193 CondWhenTrue lowerFcmpCond(const InstFcmp *Instr); | 211 CondWhenTrue lowerFcmpCond(const InstFcmp *Instr); |
194 void lowerFcmp(const InstFcmp *Instr) override; | 212 void lowerFcmp(const InstFcmp *Instr) override; |
| 213 CondWhenTrue lowerInt8AndInt16IcmpCond(InstIcmp::ICond Condition, |
| 214 Operand *Src0, Operand *Src1); |
| 215 CondWhenTrue lowerInt32IcmpCond(InstIcmp::ICond Condition, Operand *Src0, |
| 216 Operand *Src1); |
| 217 CondWhenTrue lowerInt64IcmpCond(InstIcmp::ICond Condition, Operand *Src0, |
| 218 Operand *Src1); |
195 CondWhenTrue lowerIcmpCond(const InstIcmp *Instr); | 219 CondWhenTrue lowerIcmpCond(const InstIcmp *Instr); |
196 void lowerIcmp(const InstIcmp *Instr) override; | 220 void lowerIcmp(const InstIcmp *Instr) override; |
197 void lowerAtomicRMW(Variable *Dest, uint32_t Operation, Operand *Ptr, | 221 void lowerAtomicRMW(Variable *Dest, uint32_t Operation, Operand *Ptr, |
198 Operand *Val); | 222 Operand *Val); |
199 void lowerIntrinsicCall(const InstIntrinsicCall *Inst) override; | 223 void lowerIntrinsicCall(const InstIntrinsicCall *Inst) override; |
200 void lowerInsertElement(const InstInsertElement *Inst) override; | 224 void lowerInsertElement(const InstInsertElement *Inst) override; |
201 void lowerLoad(const InstLoad *Inst) override; | 225 void lowerLoad(const InstLoad *Inst) override; |
202 void lowerPhi(const InstPhi *Inst) override; | 226 void lowerPhi(const InstPhi *Inst) override; |
203 void lowerRet(const InstRet *Inst) override; | 227 void lowerRet(const InstRet *Inst) override; |
204 void lowerSelect(const InstSelect *Inst) override; | 228 void lowerSelect(const InstSelect *Inst) override; |
205 void lowerStore(const InstStore *Inst) override; | 229 void lowerStore(const InstStore *Inst) override; |
206 void lowerSwitch(const InstSwitch *Inst) override; | 230 void lowerSwitch(const InstSwitch *Inst) override; |
207 void lowerUnreachable(const InstUnreachable *Inst) override; | 231 void lowerUnreachable(const InstUnreachable *Inst) override; |
208 void prelowerPhis() override; | 232 void prelowerPhis() override; |
209 void doAddressOptLoad() override; | 233 void doAddressOptLoad() override; |
210 void doAddressOptStore() override; | 234 void doAddressOptStore() override; |
211 void randomlyInsertNop(float Probability, | 235 void randomlyInsertNop(float Probability, |
212 RandomNumberGenerator &RNG) override; | 236 RandomNumberGenerator &RNG) override; |
213 | 237 |
214 enum OperandLegalization { | |
215 Legal_None = 0, | |
216 Legal_Reg = 1 << 0, /// physical register, not stack location | |
217 Legal_Flex = 1 << 1, /// A flexible operand2, which can hold rotated small | |
218 /// immediates, or shifted registers. | |
219 Legal_Mem = 1 << 2, /// includes [r0, r1 lsl #2] as well as [sp, #12] | |
220 Legal_All = ~Legal_None | |
221 }; | |
222 using LegalMask = uint32_t; | |
223 Operand *legalize(Operand *From, LegalMask Allowed = Legal_All, | |
224 int32_t RegNum = Variable::NoRegister); | |
225 Variable *legalizeToReg(Operand *From, int32_t RegNum = Variable::NoRegister); | |
226 OperandARM32Mem *formMemoryOperand(Operand *Ptr, Type Ty); | 238 OperandARM32Mem *formMemoryOperand(Operand *Ptr, Type Ty); |
227 | 239 |
228 Variable64On32 *makeI64RegPair(); | 240 Variable64On32 *makeI64RegPair(); |
229 Variable *makeReg(Type Ty, int32_t RegNum = Variable::NoRegister); | 241 Variable *makeReg(Type Ty, int32_t RegNum = Variable::NoRegister); |
230 static Type stackSlotType(); | 242 static Type stackSlotType(); |
231 Variable *copyToReg(Operand *Src, int32_t RegNum = Variable::NoRegister); | 243 Variable *copyToReg(Operand *Src, int32_t RegNum = Variable::NoRegister); |
232 void alignRegisterPow2(Variable *Reg, uint32_t Align); | 244 void alignRegisterPow2(Variable *Reg, uint32_t Align); |
233 | 245 |
234 /// Returns a vector in a register with the given constant entries. | 246 /// Returns a vector in a register with the given constant entries. |
235 Variable *makeVectorOfZeros(Type Ty, int32_t RegNum = Variable::NoRegister); | 247 Variable *makeVectorOfZeros(Type Ty, int32_t RegNum = Variable::NoRegister); |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
292 } | 304 } |
293 void _br(CfgNode *Target) { | 305 void _br(CfgNode *Target) { |
294 Context.insert(InstARM32Br::create(Func, Target)); | 306 Context.insert(InstARM32Br::create(Func, Target)); |
295 } | 307 } |
296 void _br(CfgNode *Target, CondARM32::Cond Condition) { | 308 void _br(CfgNode *Target, CondARM32::Cond Condition) { |
297 Context.insert(InstARM32Br::create(Func, Target, Condition)); | 309 Context.insert(InstARM32Br::create(Func, Target, Condition)); |
298 } | 310 } |
299 void _br(InstARM32Label *Label, CondARM32::Cond Condition) { | 311 void _br(InstARM32Label *Label, CondARM32::Cond Condition) { |
300 Context.insert(InstARM32Br::create(Func, Label, Condition)); | 312 Context.insert(InstARM32Br::create(Func, Label, Condition)); |
301 } | 313 } |
| 314 void _cmn(Variable *Src0, Operand *Src1, |
| 315 CondARM32::Cond Pred = CondARM32::AL) { |
| 316 Context.insert(InstARM32Cmn::create(Func, Src0, Src1, Pred)); |
| 317 } |
302 void _cmp(Variable *Src0, Operand *Src1, | 318 void _cmp(Variable *Src0, Operand *Src1, |
303 CondARM32::Cond Pred = CondARM32::AL) { | 319 CondARM32::Cond Pred = CondARM32::AL) { |
304 Context.insert(InstARM32Cmp::create(Func, Src0, Src1, Pred)); | 320 Context.insert(InstARM32Cmp::create(Func, Src0, Src1, Pred)); |
305 } | 321 } |
306 void _clz(Variable *Dest, Variable *Src0, | 322 void _clz(Variable *Dest, Variable *Src0, |
307 CondARM32::Cond Pred = CondARM32::AL) { | 323 CondARM32::Cond Pred = CondARM32::AL) { |
308 Context.insert(InstARM32Clz::create(Func, Dest, Src0, Pred)); | 324 Context.insert(InstARM32Clz::create(Func, Dest, Src0, Pred)); |
309 } | 325 } |
310 void _dmb() { Context.insert(InstARM32Dmb::create(Func)); } | 326 void _dmb() { Context.insert(InstARM32Dmb::create(Func)); } |
311 void _eor(Variable *Dest, Variable *Src0, Operand *Src1, | 327 void _eor(Variable *Dest, Variable *Src0, Operand *Src1, |
(...skipping 13 matching lines...) Expand all Loading... |
325 Context.insert(InstARM32Ldrex::create(Func, Dest, Addr, Pred)); | 341 Context.insert(InstARM32Ldrex::create(Func, Dest, Addr, Pred)); |
326 if (auto *Dest64 = llvm::dyn_cast<Variable64On32>(Dest)) { | 342 if (auto *Dest64 = llvm::dyn_cast<Variable64On32>(Dest)) { |
327 Context.insert(InstFakeDef::create(Func, Dest64->getLo(), Dest)); | 343 Context.insert(InstFakeDef::create(Func, Dest64->getLo(), Dest)); |
328 Context.insert(InstFakeDef::create(Func, Dest64->getHi(), Dest)); | 344 Context.insert(InstFakeDef::create(Func, Dest64->getHi(), Dest)); |
329 } | 345 } |
330 } | 346 } |
331 void _lsl(Variable *Dest, Variable *Src0, Operand *Src1, | 347 void _lsl(Variable *Dest, Variable *Src0, Operand *Src1, |
332 CondARM32::Cond Pred = CondARM32::AL) { | 348 CondARM32::Cond Pred = CondARM32::AL) { |
333 Context.insert(InstARM32Lsl::create(Func, Dest, Src0, Src1, Pred)); | 349 Context.insert(InstARM32Lsl::create(Func, Dest, Src0, Src1, Pred)); |
334 } | 350 } |
| 351 void _lsls(Variable *Dest, Variable *Src0, Operand *Src1, |
| 352 CondARM32::Cond Pred = CondARM32::AL) { |
| 353 constexpr bool SetFlags = true; |
| 354 Context.insert( |
| 355 InstARM32Lsl::create(Func, Dest, Src0, Src1, Pred, SetFlags)); |
| 356 } |
335 void _lsr(Variable *Dest, Variable *Src0, Operand *Src1, | 357 void _lsr(Variable *Dest, Variable *Src0, Operand *Src1, |
336 CondARM32::Cond Pred = CondARM32::AL) { | 358 CondARM32::Cond Pred = CondARM32::AL) { |
337 Context.insert(InstARM32Lsr::create(Func, Dest, Src0, Src1, Pred)); | 359 Context.insert(InstARM32Lsr::create(Func, Dest, Src0, Src1, Pred)); |
338 } | 360 } |
339 void _mla(Variable *Dest, Variable *Src0, Variable *Src1, Variable *Acc, | 361 void _mla(Variable *Dest, Variable *Src0, Variable *Src1, Variable *Acc, |
340 CondARM32::Cond Pred = CondARM32::AL) { | 362 CondARM32::Cond Pred = CondARM32::AL) { |
341 Context.insert(InstARM32Mla::create(Func, Dest, Src0, Src1, Acc, Pred)); | 363 Context.insert(InstARM32Mla::create(Func, Dest, Src0, Src1, Acc, Pred)); |
342 } | 364 } |
343 void _mls(Variable *Dest, Variable *Src0, Variable *Src1, Variable *Acc, | 365 void _mls(Variable *Dest, Variable *Src0, Variable *Src1, Variable *Acc, |
344 CondARM32::Cond Pred = CondARM32::AL) { | 366 CondARM32::Cond Pred = CondARM32::AL) { |
(...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
647 CondARM32::Cond Pred = CondARM32::AL) { | 669 CondARM32::Cond Pred = CondARM32::AL) { |
648 Context.insert(InstARM32Rbit::create(Func, Dest, Src0, Pred)); | 670 Context.insert(InstARM32Rbit::create(Func, Dest, Src0, Pred)); |
649 } | 671 } |
650 void _rev(Variable *Dest, Variable *Src0, | 672 void _rev(Variable *Dest, Variable *Src0, |
651 CondARM32::Cond Pred = CondARM32::AL) { | 673 CondARM32::Cond Pred = CondARM32::AL) { |
652 Context.insert(InstARM32Rev::create(Func, Dest, Src0, Pred)); | 674 Context.insert(InstARM32Rev::create(Func, Dest, Src0, Pred)); |
653 } | 675 } |
654 void _ret(Variable *LR, Variable *Src0 = nullptr) { | 676 void _ret(Variable *LR, Variable *Src0 = nullptr) { |
655 Context.insert(InstARM32Ret::create(Func, LR, Src0)); | 677 Context.insert(InstARM32Ret::create(Func, LR, Src0)); |
656 } | 678 } |
| 679 void _rscs(Variable *Dest, Variable *Src0, Operand *Src1, |
| 680 CondARM32::Cond Pred = CondARM32::AL) { |
| 681 constexpr bool SetFlags = true; |
| 682 Context.insert( |
| 683 InstARM32Rsc::create(Func, Dest, Src0, Src1, Pred, SetFlags)); |
| 684 } |
| 685 void _rsc(Variable *Dest, Variable *Src0, Operand *Src1, |
| 686 CondARM32::Cond Pred = CondARM32::AL) { |
| 687 Context.insert(InstARM32Rsc::create(Func, Dest, Src0, Src1, Pred)); |
| 688 } |
| 689 void _rsbs(Variable *Dest, Variable *Src0, Operand *Src1, |
| 690 CondARM32::Cond Pred = CondARM32::AL) { |
| 691 constexpr bool SetFlags = true; |
| 692 Context.insert( |
| 693 InstARM32Rsb::create(Func, Dest, Src0, Src1, Pred, SetFlags)); |
| 694 } |
657 void _rsb(Variable *Dest, Variable *Src0, Operand *Src1, | 695 void _rsb(Variable *Dest, Variable *Src0, Operand *Src1, |
658 CondARM32::Cond Pred = CondARM32::AL) { | 696 CondARM32::Cond Pred = CondARM32::AL) { |
659 Context.insert(InstARM32Rsb::create(Func, Dest, Src0, Src1, Pred)); | 697 Context.insert(InstARM32Rsb::create(Func, Dest, Src0, Src1, Pred)); |
660 } | 698 } |
661 void _sbc(Variable *Dest, Variable *Src0, Operand *Src1, | 699 void _sbc(Variable *Dest, Variable *Src0, Operand *Src1, |
662 CondARM32::Cond Pred = CondARM32::AL) { | 700 CondARM32::Cond Pred = CondARM32::AL) { |
663 Context.insert(InstARM32Sbc::create(Func, Dest, Src0, Src1, Pred)); | 701 Context.insert(InstARM32Sbc::create(Func, Dest, Src0, Src1, Pred)); |
664 } | 702 } |
665 void _sbcs(Variable *Dest, Variable *Src0, Operand *Src1, | 703 void _sbcs(Variable *Dest, Variable *Src0, Operand *Src1, |
666 CondARM32::Cond Pred = CondARM32::AL) { | 704 CondARM32::Cond Pred = CondARM32::AL) { |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
738 CondARM32::Cond Pred = CondARM32::AL) { | 776 CondARM32::Cond Pred = CondARM32::AL) { |
739 Context.insert(InstARM32Vcvt::create(Func, Dest, Src, Variant, Pred)); | 777 Context.insert(InstARM32Vcvt::create(Func, Dest, Src, Variant, Pred)); |
740 } | 778 } |
741 void _vdiv(Variable *Dest, Variable *Src0, Variable *Src1) { | 779 void _vdiv(Variable *Dest, Variable *Src0, Variable *Src1) { |
742 Context.insert(InstARM32Vdiv::create(Func, Dest, Src0, Src1)); | 780 Context.insert(InstARM32Vdiv::create(Func, Dest, Src0, Src1)); |
743 } | 781 } |
744 void _vcmp(Variable *Src0, Variable *Src1, | 782 void _vcmp(Variable *Src0, Variable *Src1, |
745 CondARM32::Cond Pred = CondARM32::AL) { | 783 CondARM32::Cond Pred = CondARM32::AL) { |
746 Context.insert(InstARM32Vcmp::create(Func, Src0, Src1, Pred)); | 784 Context.insert(InstARM32Vcmp::create(Func, Src0, Src1, Pred)); |
747 } | 785 } |
| 786 void _vcmp(Variable *Src0, OperandARM32FlexFpZero *FpZero, |
| 787 CondARM32::Cond Pred = CondARM32::AL) { |
| 788 Context.insert(InstARM32Vcmp::create(Func, Src0, FpZero, Pred)); |
| 789 } |
748 void _vmrs(CondARM32::Cond Pred = CondARM32::AL) { | 790 void _vmrs(CondARM32::Cond Pred = CondARM32::AL) { |
749 Context.insert(InstARM32Vmrs::create(Func, Pred)); | 791 Context.insert(InstARM32Vmrs::create(Func, Pred)); |
750 } | 792 } |
751 void _vmul(Variable *Dest, Variable *Src0, Variable *Src1) { | 793 void _vmul(Variable *Dest, Variable *Src0, Variable *Src1) { |
752 Context.insert(InstARM32Vmul::create(Func, Dest, Src0, Src1)); | 794 Context.insert(InstARM32Vmul::create(Func, Dest, Src0, Src1)); |
753 } | 795 } |
| 796 void _veor(Variable *Dest, Variable *Src0, Variable *Src1) { |
| 797 Context.insert(InstARM32Veor::create(Func, Dest, Src0, Src1)); |
| 798 } |
754 void _vsqrt(Variable *Dest, Variable *Src, | 799 void _vsqrt(Variable *Dest, Variable *Src, |
755 CondARM32::Cond Pred = CondARM32::AL) { | 800 CondARM32::Cond Pred = CondARM32::AL) { |
756 Context.insert(InstARM32Vsqrt::create(Func, Dest, Src, Pred)); | 801 Context.insert(InstARM32Vsqrt::create(Func, Dest, Src, Pred)); |
757 } | 802 } |
758 void _vsub(Variable *Dest, Variable *Src0, Variable *Src1) { | 803 void _vsub(Variable *Dest, Variable *Src0, Variable *Src1) { |
759 Context.insert(InstARM32Vsub::create(Func, Dest, Src0, Src1)); | 804 Context.insert(InstARM32Vsub::create(Func, Dest, Src0, Src1)); |
760 } | 805 } |
761 | 806 |
762 /// Run a pass through stack variables and ensure that the offsets are legal. | 807 /// Run a pass through stack variables and ensure that the offsets are legal. |
763 /// If the offset is not legal, use a new base register that accounts for the | 808 /// 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... |
944 | 989 |
945 private: | 990 private: |
946 ~TargetHeaderARM32() = default; | 991 ~TargetHeaderARM32() = default; |
947 | 992 |
948 TargetARM32Features CPUFeatures; | 993 TargetARM32Features CPUFeatures; |
949 }; | 994 }; |
950 | 995 |
951 } // end of namespace Ice | 996 } // end of namespace Ice |
952 | 997 |
953 #endif // SUBZERO_SRC_ICETARGETLOWERINGARM32_H | 998 #endif // SUBZERO_SRC_ICETARGETLOWERINGARM32_H |
OLD | NEW |