OLD | NEW |
1 //===- subzero/src/IceTargetLoweringARM32.cpp - ARM32 lowering ------------===// | 1 //===- subzero/src/IceTargetLoweringARM32.cpp - ARM32 lowering ------------===// |
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 |
11 /// This file implements the TargetLoweringARM32 class, which consists almost | 11 /// This file implements the TargetLoweringARM32 class, which consists almost |
12 /// entirely of the lowering sequence for each high-level instruction. | 12 /// entirely of the lowering sequence for each high-level instruction. |
13 /// | 13 /// |
14 //===----------------------------------------------------------------------===// | 14 //===----------------------------------------------------------------------===// |
15 | |
16 #include "IceTargetLoweringARM32.h" | 15 #include "IceTargetLoweringARM32.h" |
17 | 16 |
18 #include "IceCfg.h" | 17 #include "IceCfg.h" |
19 #include "IceCfgNode.h" | 18 #include "IceCfgNode.h" |
20 #include "IceClFlags.h" | 19 #include "IceClFlags.h" |
21 #include "IceDefs.h" | 20 #include "IceDefs.h" |
22 #include "IceELFObjectWriter.h" | 21 #include "IceELFObjectWriter.h" |
23 #include "IceGlobalInits.h" | 22 #include "IceGlobalInits.h" |
24 #include "IceInstARM32.h" | 23 #include "IceInstARM32.h" |
25 #include "IceLiveness.h" | 24 #include "IceLiveness.h" |
(...skipping 437 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
463 | 462 |
464 bool TargetARM32::CallingConv::I32InReg(int32_t *Reg) { | 463 bool TargetARM32::CallingConv::I32InReg(int32_t *Reg) { |
465 if (NumGPRRegsUsed >= ARM32_MAX_GPR_ARG) | 464 if (NumGPRRegsUsed >= ARM32_MAX_GPR_ARG) |
466 return false; | 465 return false; |
467 *Reg = RegARM32::Reg_r0 + NumGPRRegsUsed; | 466 *Reg = RegARM32::Reg_r0 + NumGPRRegsUsed; |
468 ++NumGPRRegsUsed; | 467 ++NumGPRRegsUsed; |
469 return true; | 468 return true; |
470 } | 469 } |
471 | 470 |
472 bool TargetARM32::CallingConv::FPInReg(Type Ty, int32_t *Reg) { | 471 bool TargetARM32::CallingConv::FPInReg(Type Ty, int32_t *Reg) { |
473 if (NumFPRegUnits >= ARM32_MAX_FP_REG_UNITS) | 472 if (!VFPRegsFree.any()) { |
474 return false; | 473 return false; |
| 474 } |
| 475 |
475 if (isVectorType(Ty)) { | 476 if (isVectorType(Ty)) { |
476 NumFPRegUnits = Utils::applyAlignment(NumFPRegUnits, 4); | |
477 // Q registers are declared in reverse order, so | 477 // Q registers are declared in reverse order, so |
478 // RegARM32::Reg_q0 > RegARM32::Reg_q1. Therefore, we need to subtract | 478 // RegARM32::Reg_q0 > RegARM32::Reg_q1. Therefore, we need to subtract |
479 // NumFPRegUnits from Reg_q0. Same thing goes for D registers. | 479 // NumFPRegUnits from Reg_q0. Same thing goes for D registers. |
480 static_assert(RegARM32::Reg_q0 > RegARM32::Reg_q1, | 480 static_assert(RegARM32::Reg_q0 > RegARM32::Reg_q1, |
481 "ARM32 Q registers are possibly declared incorrectly."); | 481 "ARM32 Q registers are possibly declared incorrectly."); |
482 *Reg = RegARM32::Reg_q0 - (NumFPRegUnits / 4); | 482 |
483 NumFPRegUnits += 4; | 483 int32_t QRegStart = (VFPRegsFree & ValidV128Regs).find_first(); |
484 // If this bumps us past the boundary, don't allocate to a register | 484 if (QRegStart >= 0) { |
485 // and leave any previously speculatively consumed registers as consumed. | 485 VFPRegsFree.reset(QRegStart, QRegStart + 4); |
486 if (NumFPRegUnits > ARM32_MAX_FP_REG_UNITS) | 486 *Reg = RegARM32::Reg_q0 - (QRegStart / 4); |
487 return false; | 487 return true; |
| 488 } |
488 } else if (Ty == IceType_f64) { | 489 } else if (Ty == IceType_f64) { |
489 static_assert(RegARM32::Reg_d0 > RegARM32::Reg_d1, | 490 static_assert(RegARM32::Reg_d0 > RegARM32::Reg_d1, |
490 "ARM32 D registers are possibly declared incorrectly."); | 491 "ARM32 D registers are possibly declared incorrectly."); |
491 NumFPRegUnits = Utils::applyAlignment(NumFPRegUnits, 2); | 492 |
492 *Reg = RegARM32::Reg_d0 - (NumFPRegUnits / 2); | 493 int32_t DRegStart = (VFPRegsFree & ValidF64Regs).find_first(); |
493 NumFPRegUnits += 2; | 494 if (DRegStart >= 0) { |
494 // If this bumps us past the boundary, don't allocate to a register | 495 VFPRegsFree.reset(DRegStart, DRegStart + 2); |
495 // and leave any previously speculatively consumed registers as consumed. | 496 *Reg = RegARM32::Reg_d0 - (DRegStart / 2); |
496 if (NumFPRegUnits > ARM32_MAX_FP_REG_UNITS) | 497 return true; |
497 return false; | 498 } |
498 } else { | 499 } else { |
499 static_assert(RegARM32::Reg_s0 < RegARM32::Reg_s1, | 500 static_assert(RegARM32::Reg_s0 < RegARM32::Reg_s1, |
500 "ARM32 S registers are possibly declared incorrectly."); | 501 "ARM32 S registers are possibly declared incorrectly."); |
| 502 |
501 assert(Ty == IceType_f32); | 503 assert(Ty == IceType_f32); |
502 *Reg = RegARM32::Reg_s0 + NumFPRegUnits; | 504 int32_t SReg = VFPRegsFree.find_first(); |
503 ++NumFPRegUnits; | 505 assert(SReg >= 0); |
| 506 VFPRegsFree.reset(SReg); |
| 507 *Reg = RegARM32::Reg_s0 + SReg; |
| 508 return true; |
504 } | 509 } |
505 return true; | 510 |
| 511 // Parameter allocation failed. From now on, every fp register must be placed |
| 512 // on the stack. We clear VFRegsFree in case there are any "holes" from S and |
| 513 // D registers. |
| 514 VFPRegsFree.clear(); |
| 515 return false; |
506 } | 516 } |
507 | 517 |
508 void TargetARM32::lowerArguments() { | 518 void TargetARM32::lowerArguments() { |
509 VarList &Args = Func->getArgs(); | 519 VarList &Args = Func->getArgs(); |
510 TargetARM32::CallingConv CC; | 520 TargetARM32::CallingConv CC; |
511 | 521 |
512 // For each register argument, replace Arg in the argument list with the | 522 // For each register argument, replace Arg in the argument list with the |
513 // home register. Then generate an instruction in the prolog to copy the | 523 // home register. Then generate an instruction in the prolog to copy the |
514 // home register to the assigned location of Arg. | 524 // home register to the assigned location of Arg. |
515 Context.init(Func->getEntryNode()); | 525 Context.init(Func->getEntryNode()); |
(...skipping 1726 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2242 case IceType_v16i1: | 2252 case IceType_v16i1: |
2243 UnimplementedError(Func->getContext()->getFlags()); | 2253 UnimplementedError(Func->getContext()->getFlags()); |
2244 break; | 2254 break; |
2245 case IceType_v8i16: | 2255 case IceType_v8i16: |
2246 UnimplementedError(Func->getContext()->getFlags()); | 2256 UnimplementedError(Func->getContext()->getFlags()); |
2247 break; | 2257 break; |
2248 case IceType_v16i8: | 2258 case IceType_v16i8: |
2249 UnimplementedError(Func->getContext()->getFlags()); | 2259 UnimplementedError(Func->getContext()->getFlags()); |
2250 break; | 2260 break; |
2251 case IceType_v4i32: | 2261 case IceType_v4i32: |
| 2262 // avoid cryptic liveness errors |
| 2263 Context.insert(InstFakeDef::create(Func, Dest)); |
2252 UnimplementedError(Func->getContext()->getFlags()); | 2264 UnimplementedError(Func->getContext()->getFlags()); |
2253 break; | 2265 break; |
2254 case IceType_v4f32: | 2266 case IceType_v4f32: |
2255 UnimplementedError(Func->getContext()->getFlags()); | 2267 UnimplementedError(Func->getContext()->getFlags()); |
2256 break; | 2268 break; |
2257 } | 2269 } |
2258 break; | 2270 break; |
2259 } | 2271 } |
2260 } | 2272 } |
2261 } | 2273 } |
(...skipping 516 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2778 Operand *Addr = Inst->getAddr(); | 2790 Operand *Addr = Inst->getAddr(); |
2779 OperandARM32Mem *NewAddr = formMemoryOperand(Addr, Value->getType()); | 2791 OperandARM32Mem *NewAddr = formMemoryOperand(Addr, Value->getType()); |
2780 Type Ty = NewAddr->getType(); | 2792 Type Ty = NewAddr->getType(); |
2781 | 2793 |
2782 if (Ty == IceType_i64) { | 2794 if (Ty == IceType_i64) { |
2783 Value = legalizeUndef(Value); | 2795 Value = legalizeUndef(Value); |
2784 Variable *ValueHi = legalizeToReg(hiOperand(Value)); | 2796 Variable *ValueHi = legalizeToReg(hiOperand(Value)); |
2785 Variable *ValueLo = legalizeToReg(loOperand(Value)); | 2797 Variable *ValueLo = legalizeToReg(loOperand(Value)); |
2786 _str(ValueHi, llvm::cast<OperandARM32Mem>(hiOperand(NewAddr))); | 2798 _str(ValueHi, llvm::cast<OperandARM32Mem>(hiOperand(NewAddr))); |
2787 _str(ValueLo, llvm::cast<OperandARM32Mem>(loOperand(NewAddr))); | 2799 _str(ValueLo, llvm::cast<OperandARM32Mem>(loOperand(NewAddr))); |
2788 } else if (isVectorType(Ty)) { | |
2789 UnimplementedError(Func->getContext()->getFlags()); | |
2790 } else { | 2800 } else { |
| 2801 if (isVectorType(Ty)) { |
| 2802 UnimplementedError(Func->getContext()->getFlags()); |
| 2803 } |
2791 Variable *ValueR = legalizeToReg(Value); | 2804 Variable *ValueR = legalizeToReg(Value); |
2792 _str(ValueR, NewAddr); | 2805 _str(ValueR, NewAddr); |
2793 } | 2806 } |
2794 } | 2807 } |
2795 | 2808 |
2796 void TargetARM32::doAddressOptStore() { | 2809 void TargetARM32::doAddressOptStore() { |
2797 UnimplementedError(Func->getContext()->getFlags()); | 2810 UnimplementedError(Func->getContext()->getFlags()); |
2798 } | 2811 } |
2799 | 2812 |
2800 void TargetARM32::lowerSwitch(const InstSwitch *Inst) { | 2813 void TargetARM32::lowerSwitch(const InstSwitch *Inst) { |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2842 Variable *Reg = makeReg(Ty, RegNum); | 2855 Variable *Reg = makeReg(Ty, RegNum); |
2843 UnimplementedError(Func->getContext()->getFlags()); | 2856 UnimplementedError(Func->getContext()->getFlags()); |
2844 return Reg; | 2857 return Reg; |
2845 } | 2858 } |
2846 | 2859 |
2847 // Helper for legalize() to emit the right code to lower an operand to a | 2860 // Helper for legalize() to emit the right code to lower an operand to a |
2848 // register of the appropriate type. | 2861 // register of the appropriate type. |
2849 Variable *TargetARM32::copyToReg(Operand *Src, int32_t RegNum) { | 2862 Variable *TargetARM32::copyToReg(Operand *Src, int32_t RegNum) { |
2850 Type Ty = Src->getType(); | 2863 Type Ty = Src->getType(); |
2851 Variable *Reg = makeReg(Ty, RegNum); | 2864 Variable *Reg = makeReg(Ty, RegNum); |
2852 if (isVectorType(Ty) || isFloatingType(Ty)) { | 2865 if (isVectorType(Ty)) { |
| 2866 // TODO(jpp): Src must be a register, or an address with base register. |
| 2867 _vmov(Reg, Src); |
| 2868 } else if (isFloatingType(Ty)) { |
2853 _vmov(Reg, Src); | 2869 _vmov(Reg, Src); |
2854 } else { | 2870 } else { |
2855 // Mov's Src operand can really only be the flexible second operand type | 2871 // Mov's Src operand can really only be the flexible second operand type |
2856 // or a register. Users should guarantee that. | 2872 // or a register. Users should guarantee that. |
2857 _mov(Reg, Src); | 2873 _mov(Reg, Src); |
2858 } | 2874 } |
2859 return Reg; | 2875 return Reg; |
2860 } | 2876 } |
2861 | 2877 |
2862 Operand *TargetARM32::legalize(Operand *From, LegalMask Allowed, | 2878 Operand *TargetARM32::legalize(Operand *From, LegalMask Allowed, |
(...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3205 << ".eabi_attribute 68, 1 @ Tag_Virtualization_use\n"; | 3221 << ".eabi_attribute 68, 1 @ Tag_Virtualization_use\n"; |
3206 if (CPUFeatures.hasFeature(TargetARM32Features::HWDivArm)) { | 3222 if (CPUFeatures.hasFeature(TargetARM32Features::HWDivArm)) { |
3207 Str << ".eabi_attribute 44, 2 @ Tag_DIV_use\n"; | 3223 Str << ".eabi_attribute 44, 2 @ Tag_DIV_use\n"; |
3208 } | 3224 } |
3209 // Technically R9 is used for TLS with Sandboxing, and we reserve it. | 3225 // Technically R9 is used for TLS with Sandboxing, and we reserve it. |
3210 // However, for compatibility with current NaCl LLVM, don't claim that. | 3226 // However, for compatibility with current NaCl LLVM, don't claim that. |
3211 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n"; | 3227 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n"; |
3212 } | 3228 } |
3213 | 3229 |
3214 } // end of namespace Ice | 3230 } // end of namespace Ice |
OLD | NEW |