| 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 |