| 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 |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 153 "ARM32InstructionSet range different from TargetInstructionSet"); | 153 "ARM32InstructionSet range different from TargetInstructionSet"); |
| 154 if (Flags.getTargetInstructionSet() != | 154 if (Flags.getTargetInstructionSet() != |
| 155 TargetInstructionSet::BaseInstructionSet) { | 155 TargetInstructionSet::BaseInstructionSet) { |
| 156 InstructionSet = static_cast<ARM32InstructionSet>( | 156 InstructionSet = static_cast<ARM32InstructionSet>( |
| 157 (Flags.getTargetInstructionSet() - | 157 (Flags.getTargetInstructionSet() - |
| 158 TargetInstructionSet::ARM32InstructionSet_Begin) + | 158 TargetInstructionSet::ARM32InstructionSet_Begin) + |
| 159 ARM32InstructionSet::Begin); | 159 ARM32InstructionSet::Begin); |
| 160 } | 160 } |
| 161 } | 161 } |
| 162 | 162 |
| 163 namespace { |
| 164 constexpr SizeT NumGPRArgs = |
| 165 #define X(val, encode, name, cc_arg, scratch, preserved, stackptr, frameptr, \ |
| 166 isInt, isI64Pair, isFP32, isFP64, isVec128, alias_init) \ |
| 167 +(((cc_arg) > 0) ? 1 : 0) |
| 168 REGARM32_GPR_TABLE |
| 169 #undef X |
| 170 ; |
| 171 std::array<uint32_t, NumGPRArgs> GPRArgInitializer; |
| 172 |
| 173 constexpr SizeT NumI64Args = |
| 174 #define X(val, encode, name, cc_arg, scratch, preserved, stackptr, frameptr, \ |
| 175 isInt, isI64Pair, isFP32, isFP64, isVec128, alias_init) \ |
| 176 +(((cc_arg) > 0) ? 1 : 0) |
| 177 REGARM32_I64PAIR_TABLE |
| 178 #undef X |
| 179 ; |
| 180 std::array<uint32_t, NumI64Args> I64ArgInitializer; |
| 181 |
| 182 constexpr SizeT NumFP32Args = |
| 183 #define X(val, encode, name, cc_arg, scratch, preserved, stackptr, frameptr, \ |
| 184 isInt, isI64Pair, isFP32, isFP64, isVec128, alias_init) \ |
| 185 +(((cc_arg) > 0) ? 1 : 0) |
| 186 REGARM32_FP32_TABLE |
| 187 #undef X |
| 188 ; |
| 189 std::array<uint32_t, NumFP32Args> FP32ArgInitializer; |
| 190 |
| 191 constexpr SizeT NumFP64Args = |
| 192 #define X(val, encode, name, cc_arg, scratch, preserved, stackptr, frameptr, \ |
| 193 isInt, isI64Pair, isFP32, isFP64, isVec128, alias_init) \ |
| 194 +(((cc_arg) > 0) ? 1 : 0) |
| 195 REGARM32_FP64_TABLE |
| 196 #undef X |
| 197 ; |
| 198 std::array<uint32_t, NumFP64Args> FP64ArgInitializer; |
| 199 |
| 200 constexpr SizeT NumVec128Args = |
| 201 #define X(val, encode, name, cc_arg, scratch, preserved, stackptr, frameptr, \ |
| 202 isInt, isI64Pair, isFP32, isFP64, isVec128, alias_init) \ |
| 203 +(((cc_arg > 0)) ? 1 : 0) |
| 204 REGARM32_VEC128_TABLE |
| 205 #undef X |
| 206 ; |
| 207 std::array<uint32_t, NumVec128Args> Vec128ArgInitializer; |
| 208 } // end of anonymous namespace |
| 209 |
| 163 TargetARM32::TargetARM32(Cfg *Func) | 210 TargetARM32::TargetARM32(Cfg *Func) |
| 164 : TargetLowering(Func), NeedSandboxing(Ctx->getFlags().getUseSandboxing()), | 211 : TargetLowering(Func), NeedSandboxing(Ctx->getFlags().getUseSandboxing()), |
| 165 CPUFeatures(Func->getContext()->getFlags()) {} | 212 CPUFeatures(Func->getContext()->getFlags()) {} |
| 166 | 213 |
| 167 void TargetARM32::staticInit() { | 214 void TargetARM32::staticInit() { |
| 168 // Limit this size (or do all bitsets need to be the same width)??? | 215 // Limit this size (or do all bitsets need to be the same width)??? |
| 169 llvm::SmallBitVector IntegerRegisters(RegARM32::Reg_NUM); | 216 llvm::SmallBitVector IntegerRegisters(RegARM32::Reg_NUM); |
| 170 llvm::SmallBitVector I64PairRegisters(RegARM32::Reg_NUM); | 217 llvm::SmallBitVector I64PairRegisters(RegARM32::Reg_NUM); |
| 171 llvm::SmallBitVector Float32Registers(RegARM32::Reg_NUM); | 218 llvm::SmallBitVector Float32Registers(RegARM32::Reg_NUM); |
| 172 llvm::SmallBitVector Float64Registers(RegARM32::Reg_NUM); | 219 llvm::SmallBitVector Float64Registers(RegARM32::Reg_NUM); |
| 173 llvm::SmallBitVector VectorRegisters(RegARM32::Reg_NUM); | 220 llvm::SmallBitVector VectorRegisters(RegARM32::Reg_NUM); |
| 174 llvm::SmallBitVector InvalidRegisters(RegARM32::Reg_NUM); | 221 llvm::SmallBitVector InvalidRegisters(RegARM32::Reg_NUM); |
| 175 ScratchRegs.resize(RegARM32::Reg_NUM); | 222 ScratchRegs.resize(RegARM32::Reg_NUM); |
| 176 #define X(val, encode, name, scratch, preserved, stackptr, frameptr, isInt, \ | 223 #define X(val, encode, name, cc_arg, scratch, preserved, stackptr, frameptr, \ |
| 177 isI64Pair, isFP32, isFP64, isVec128, alias_init) \ | 224 isInt, isI64Pair, isFP32, isFP64, isVec128, alias_init) \ |
| 178 IntegerRegisters[RegARM32::val] = isInt; \ | 225 IntegerRegisters[RegARM32::val] = isInt; \ |
| 179 I64PairRegisters[RegARM32::val] = isI64Pair; \ | 226 I64PairRegisters[RegARM32::val] = isI64Pair; \ |
| 180 Float32Registers[RegARM32::val] = isFP32; \ | 227 Float32Registers[RegARM32::val] = isFP32; \ |
| 181 Float64Registers[RegARM32::val] = isFP64; \ | 228 Float64Registers[RegARM32::val] = isFP64; \ |
| 182 VectorRegisters[RegARM32::val] = isVec128; \ | 229 VectorRegisters[RegARM32::val] = isVec128; \ |
| 183 RegisterAliases[RegARM32::val].resize(RegARM32::Reg_NUM); \ | 230 RegisterAliases[RegARM32::val].resize(RegARM32::Reg_NUM); \ |
| 184 for (SizeT RegAlias : alias_init) { \ | 231 for (SizeT RegAlias : alias_init) { \ |
| 185 assert(!RegisterAliases[RegARM32::val][RegAlias] && \ | 232 assert((!RegisterAliases[RegARM32::val][RegAlias] || \ |
| 233 RegAlias != RegARM32::val) && \ |
| 186 "Duplicate alias for " #val); \ | 234 "Duplicate alias for " #val); \ |
| 187 RegisterAliases[RegARM32::val].set(RegAlias); \ | 235 RegisterAliases[RegARM32::val].set(RegAlias); \ |
| 188 } \ | 236 } \ |
| 189 RegisterAliases[RegARM32::val].set(RegARM32::val); \ | 237 RegisterAliases[RegARM32::val].set(RegARM32::val); \ |
| 190 ScratchRegs[RegARM32::val] = scratch; | 238 ScratchRegs[RegARM32::val] = scratch; \ |
| 239 if ((isInt) && (cc_arg) > 0) { \ |
| 240 GPRArgInitializer[(cc_arg)-1] = RegARM32::val; \ |
| 241 } else if ((isI64Pair) && (cc_arg) > 0) { \ |
| 242 I64ArgInitializer[(cc_arg)-1] = RegARM32::val; \ |
| 243 } else if ((isFP32) && (cc_arg) > 0) { \ |
| 244 FP32ArgInitializer[(cc_arg)-1] = RegARM32::val; \ |
| 245 } else if ((isFP64) && (cc_arg) > 0) { \ |
| 246 FP64ArgInitializer[(cc_arg)-1] = RegARM32::val; \ |
| 247 } else if ((isVec128) && (cc_arg) > 0) { \ |
| 248 Vec128ArgInitializer[(cc_arg)-1] = RegARM32::val; \ |
| 249 } |
| 191 REGARM32_TABLE; | 250 REGARM32_TABLE; |
| 192 #undef X | 251 #undef X |
| 193 TypeToRegisterSet[IceType_void] = InvalidRegisters; | 252 TypeToRegisterSet[IceType_void] = InvalidRegisters; |
| 194 TypeToRegisterSet[IceType_i1] = IntegerRegisters; | 253 TypeToRegisterSet[IceType_i1] = IntegerRegisters; |
| 195 TypeToRegisterSet[IceType_i8] = IntegerRegisters; | 254 TypeToRegisterSet[IceType_i8] = IntegerRegisters; |
| 196 TypeToRegisterSet[IceType_i16] = IntegerRegisters; | 255 TypeToRegisterSet[IceType_i16] = IntegerRegisters; |
| 197 TypeToRegisterSet[IceType_i32] = IntegerRegisters; | 256 TypeToRegisterSet[IceType_i32] = IntegerRegisters; |
| 198 TypeToRegisterSet[IceType_i64] = I64PairRegisters; | 257 TypeToRegisterSet[IceType_i64] = I64PairRegisters; |
| 199 TypeToRegisterSet[IceType_f32] = Float32Registers; | 258 TypeToRegisterSet[IceType_f32] = Float32Registers; |
| 200 TypeToRegisterSet[IceType_f64] = Float64Registers; | 259 TypeToRegisterSet[IceType_f64] = Float64Registers; |
| (...skipping 29 matching lines...) Expand all Loading... |
| 230 Lo->setRegNum(FirstReg); | 289 Lo->setRegNum(FirstReg); |
| 231 Lo->setMustHaveReg(); | 290 Lo->setMustHaveReg(); |
| 232 Hi->setRegNum(FirstReg + 1); | 291 Hi->setRegNum(FirstReg + 1); |
| 233 Hi->setMustHaveReg(); | 292 Hi->setMustHaveReg(); |
| 234 } | 293 } |
| 235 } | 294 } |
| 236 } // end of anonymous namespace | 295 } // end of anonymous namespace |
| 237 | 296 |
| 238 uint32_t TargetARM32::getCallStackArgumentsSizeBytes(const InstCall *Call) { | 297 uint32_t TargetARM32::getCallStackArgumentsSizeBytes(const InstCall *Call) { |
| 239 TargetARM32::CallingConv CC; | 298 TargetARM32::CallingConv CC; |
| 299 int32_t DummyReg; |
| 240 size_t OutArgsSizeBytes = 0; | 300 size_t OutArgsSizeBytes = 0; |
| 241 for (SizeT i = 0, NumArgs = Call->getNumArgs(); i < NumArgs; ++i) { | 301 for (SizeT i = 0, NumArgs = Call->getNumArgs(); i < NumArgs; ++i) { |
| 242 Operand *Arg = legalizeUndef(Call->getArg(i)); | 302 Operand *Arg = legalizeUndef(Call->getArg(i)); |
| 243 Type Ty = Arg->getType(); | 303 const Type Ty = Arg->getType(); |
| 244 if (Ty == IceType_i64) { | 304 if (isScalarIntegerType(Ty)) { |
| 245 std::pair<int32_t, int32_t> Regs; | 305 if (CC.argInGPR(Ty, &DummyReg)) { |
| 246 if (CC.I64InRegs(&Regs)) { | |
| 247 continue; | |
| 248 } | |
| 249 } else if (isVectorType(Ty) || isFloatingType(Ty)) { | |
| 250 int32_t Reg; | |
| 251 if (CC.FPInReg(Ty, &Reg)) { | |
| 252 continue; | 306 continue; |
| 253 } | 307 } |
| 254 } else { | 308 } else { |
| 255 assert(Ty == IceType_i32); | 309 if (CC.argInVFP(Ty, &DummyReg)) { |
| 256 int32_t Reg; | |
| 257 if (CC.I32InReg(&Reg)) { | |
| 258 continue; | 310 continue; |
| 259 } | 311 } |
| 260 } | 312 } |
| 261 | 313 |
| 262 OutArgsSizeBytes = applyStackAlignmentTy(OutArgsSizeBytes, Ty); | 314 OutArgsSizeBytes = applyStackAlignmentTy(OutArgsSizeBytes, Ty); |
| 263 OutArgsSizeBytes += typeWidthInBytesOnStack(Ty); | 315 OutArgsSizeBytes += typeWidthInBytesOnStack(Ty); |
| 264 } | 316 } |
| 265 | 317 |
| 266 return applyStackAlignment(OutArgsSizeBytes); | 318 return applyStackAlignment(OutArgsSizeBytes); |
| 267 } | 319 } |
| (...skipping 494 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 762 } | 814 } |
| 763 | 815 |
| 764 bool TargetARM32::doBranchOpt(Inst *I, const CfgNode *NextNode) { | 816 bool TargetARM32::doBranchOpt(Inst *I, const CfgNode *NextNode) { |
| 765 if (auto *Br = llvm::dyn_cast<InstARM32Br>(I)) { | 817 if (auto *Br = llvm::dyn_cast<InstARM32Br>(I)) { |
| 766 return Br->optimizeBranch(NextNode); | 818 return Br->optimizeBranch(NextNode); |
| 767 } | 819 } |
| 768 return false; | 820 return false; |
| 769 } | 821 } |
| 770 | 822 |
| 771 const char *RegARM32::RegNames[] = { | 823 const char *RegARM32::RegNames[] = { |
| 772 #define X(val, encode, name, scratch, preserved, stackptr, frameptr, isInt, \ | 824 #define X(val, encode, name, cc_arg, scratch, preserved, stackptr, frameptr, \ |
| 773 isI64Pair, isFP32, isFP64, isVec128, alias_init) \ | 825 isInt, isI64Pair, isFP32, isFP64, isVec128, alias_init) \ |
| 774 name, | 826 name, |
| 775 REGARM32_TABLE | 827 REGARM32_TABLE |
| 776 #undef X | 828 #undef X |
| 777 }; | 829 }; |
| 778 | 830 |
| 779 IceString TargetARM32::getRegName(SizeT RegNum, Type Ty) const { | 831 IceString TargetARM32::getRegName(SizeT RegNum, Type Ty) const { |
| 780 assert(RegNum < RegARM32::Reg_NUM); | 832 assert(RegNum < RegARM32::Reg_NUM); |
| 781 (void)Ty; | 833 (void)Ty; |
| 782 return RegARM32::RegNames[RegNum]; | 834 return RegARM32::RegNames[RegNum]; |
| 783 } | 835 } |
| 784 | 836 |
| 785 Variable *TargetARM32::getPhysicalRegister(SizeT RegNum, Type Ty) { | 837 Variable *TargetARM32::getPhysicalRegister(SizeT RegNum, Type Ty) { |
| 786 static const Type DefaultType[] = { | 838 static const Type DefaultType[] = { |
| 787 #define X(val, encode, name, scratch, preserved, stackptr, frameptr, isInt, \ | 839 #define X(val, encode, name, cc_arg, scratch, preserved, stackptr, frameptr, \ |
| 788 isI64Pair, isFP32, isFP64, isVec128, alias_init) \ | 840 isInt, isI64Pair, isFP32, isFP64, isVec128, alias_init) \ |
| 789 (isFP32) \ | 841 (isFP32) \ |
| 790 ? IceType_f32 \ | 842 ? IceType_f32 \ |
| 791 : ((isFP64) ? IceType_f64 : ((isVec128 ? IceType_v4i32 : IceType_i32))), | 843 : ((isFP64) ? IceType_f64 : ((isVec128 ? IceType_v4i32 : IceType_i32))), |
| 792 REGARM32_TABLE | 844 REGARM32_TABLE |
| 793 #undef X | 845 #undef X |
| 794 }; | 846 }; |
| 795 | 847 |
| 796 assert(RegNum < RegARM32::Reg_NUM); | 848 assert(RegNum < RegARM32::Reg_NUM); |
| 797 if (Ty == IceType_void) { | 849 if (Ty == IceType_void) { |
| 798 assert(RegNum < llvm::array_lengthof(DefaultType)); | 850 assert(RegNum < llvm::array_lengthof(DefaultType)); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 841 BaseRegNum = getFrameOrStackReg(); | 893 BaseRegNum = getFrameOrStackReg(); |
| 842 } | 894 } |
| 843 const Type VarTy = Var->getType(); | 895 const Type VarTy = Var->getType(); |
| 844 Str << "[" << getRegName(BaseRegNum, VarTy); | 896 Str << "[" << getRegName(BaseRegNum, VarTy); |
| 845 if (Offset != 0) { | 897 if (Offset != 0) { |
| 846 Str << ", " << getConstantPrefix() << Offset; | 898 Str << ", " << getConstantPrefix() << Offset; |
| 847 } | 899 } |
| 848 Str << "]"; | 900 Str << "]"; |
| 849 } | 901 } |
| 850 | 902 |
| 851 bool TargetARM32::CallingConv::I64InRegs(std::pair<int32_t, int32_t> *Regs) { | 903 TargetARM32::CallingConv::CallingConv() |
| 852 if (NumGPRRegsUsed >= ARM32_MAX_GPR_ARG) | 904 : GPRegsUsed(RegARM32::Reg_NUM), |
| 905 GPRArgs(GPRArgInitializer.rbegin(), GPRArgInitializer.rend()), |
| 906 I64Args(I64ArgInitializer.rbegin(), I64ArgInitializer.rend()), |
| 907 VFPRegsUsed(RegARM32::Reg_NUM), |
| 908 FP32Args(FP32ArgInitializer.rbegin(), FP32ArgInitializer.rend()), |
| 909 FP64Args(FP64ArgInitializer.rbegin(), FP64ArgInitializer.rend()), |
| 910 Vec128Args(Vec128ArgInitializer.rbegin(), Vec128ArgInitializer.rend()) {} |
| 911 |
| 912 bool TargetARM32::CallingConv::argInGPR(Type Ty, int32_t *Reg) { |
| 913 CfgVector<SizeT> *Source; |
| 914 |
| 915 switch (Ty) { |
| 916 default: { |
| 917 assert(isScalarIntegerType(Ty)); |
| 918 Source = &GPRArgs; |
| 919 } break; |
| 920 case IceType_i64: { |
| 921 Source = &I64Args; |
| 922 } break; |
| 923 } |
| 924 |
| 925 discardUnavailableGPRsAndTheirAliases(Source); |
| 926 |
| 927 if (Source->empty()) { |
| 928 GPRegsUsed.set(); |
| 853 return false; | 929 return false; |
| 854 int32_t RegLo, RegHi; | 930 } |
| 855 // Always start i64 registers at an even register, so this may end up padding | 931 |
| 856 // away a register. | 932 *Reg = Source->back(); |
| 857 NumGPRRegsUsed = Utils::applyAlignment(NumGPRRegsUsed, 2); | 933 // Note that we don't Source->pop_back() here. This is intentional. Notice how |
| 858 RegLo = RegARM32::Reg_r0 + NumGPRRegsUsed; | 934 // we mark all of Reg's aliases as Used. So, for the next argument, |
| 859 ++NumGPRRegsUsed; | 935 // Source->back() is marked as unavailable, and it is thus implicitly popped |
| 860 RegHi = RegARM32::Reg_r0 + NumGPRRegsUsed; | 936 // from the stack. |
| 861 ++NumGPRRegsUsed; | 937 GPRegsUsed |= RegisterAliases[*Reg]; |
| 862 // If this bumps us past the boundary, don't allocate to a register and leave | |
| 863 // any previously speculatively consumed registers as consumed. | |
| 864 if (NumGPRRegsUsed > ARM32_MAX_GPR_ARG) | |
| 865 return false; | |
| 866 Regs->first = RegLo; | |
| 867 Regs->second = RegHi; | |
| 868 return true; | 938 return true; |
| 869 } | 939 } |
| 870 | 940 |
| 871 bool TargetARM32::CallingConv::I32InReg(int32_t *Reg) { | 941 // GPR are not packed when passing parameters. Thus, a function foo(i32, i64, |
| 872 if (NumGPRRegsUsed >= ARM32_MAX_GPR_ARG) | 942 // i32) will have the first argument in r0, the second in r1-r2, and the third |
| 943 // on the stack. To model this behavior, whenever we pop a register from Regs, |
| 944 // we remove all of its aliases from the pool of available GPRs. This has the |
| 945 // effect of computing the "closure" on the GPR registers. |
| 946 void TargetARM32::CallingConv::discardUnavailableGPRsAndTheirAliases( |
| 947 CfgVector<SizeT> *Regs) { |
| 948 while (!Regs->empty() && GPRegsUsed[Regs->back()]) { |
| 949 GPRegsUsed |= RegisterAliases[Regs->back()]; |
| 950 Regs->pop_back(); |
| 951 } |
| 952 } |
| 953 |
| 954 bool TargetARM32::CallingConv::argInVFP(Type Ty, int32_t *Reg) { |
| 955 CfgVector<SizeT> *Source; |
| 956 |
| 957 switch (Ty) { |
| 958 default: { |
| 959 assert(isVectorType(Ty)); |
| 960 Source = &Vec128Args; |
| 961 } break; |
| 962 case IceType_f32: { |
| 963 Source = &FP32Args; |
| 964 } break; |
| 965 case IceType_f64: { |
| 966 Source = &FP64Args; |
| 967 } break; |
| 968 } |
| 969 |
| 970 discardUnavailableVFPRegs(Source); |
| 971 |
| 972 if (Source->empty()) { |
| 973 VFPRegsUsed.set(); |
| 873 return false; | 974 return false; |
| 874 *Reg = RegARM32::Reg_r0 + NumGPRRegsUsed; | 975 } |
| 875 ++NumGPRRegsUsed; | 976 |
| 977 *Reg = Source->back(); |
| 978 VFPRegsUsed |= RegisterAliases[*Reg]; |
| 876 return true; | 979 return true; |
| 877 } | 980 } |
| 878 | 981 |
| 879 // The calling convention helper class (TargetARM32::CallingConv) expects the | 982 // Arguments in VFP registers are not packed, so we don't mark the popped |
| 880 // following registers to be declared in a certain order, so we have these | 983 // registers' aliases as unavailable. |
| 881 // sanity checks to ensure nothing breaks unknowingly. | 984 void TargetARM32::CallingConv::discardUnavailableVFPRegs( |
| 882 // TODO(jpp): modify the CallingConv class so it does not rely on any register | 985 CfgVector<SizeT> *Regs) { |
| 883 // declaration order. | 986 while (!Regs->empty() && VFPRegsUsed[Regs->back()]) { |
| 884 #define SANITY_CHECK_QS(_0, _1) \ | 987 Regs->pop_back(); |
| 885 static_assert((RegARM32::Reg_##_1 + 1) == RegARM32::Reg_##_0, \ | |
| 886 "ARM32 " #_0 " and " #_1 " registers are declared " \ | |
| 887 "incorrectly.") | |
| 888 SANITY_CHECK_QS(q0, q1); | |
| 889 SANITY_CHECK_QS(q1, q2); | |
| 890 SANITY_CHECK_QS(q2, q3); | |
| 891 SANITY_CHECK_QS(q3, q4); | |
| 892 #undef SANITY_CHECK_QS | |
| 893 #define SANITY_CHECK_DS(_0, _1) \ | |
| 894 static_assert((RegARM32::Reg_##_1 + 1) == RegARM32::Reg_##_0, \ | |
| 895 "ARM32 " #_0 " and " #_1 " registers are declared " \ | |
| 896 "incorrectly.") | |
| 897 SANITY_CHECK_DS(d0, d1); | |
| 898 SANITY_CHECK_DS(d1, d2); | |
| 899 SANITY_CHECK_DS(d2, d3); | |
| 900 SANITY_CHECK_DS(d3, d4); | |
| 901 SANITY_CHECK_DS(d4, d5); | |
| 902 SANITY_CHECK_DS(d5, d6); | |
| 903 SANITY_CHECK_DS(d6, d7); | |
| 904 SANITY_CHECK_DS(d7, d8); | |
| 905 #undef SANITY_CHECK_DS | |
| 906 #define SANITY_CHECK_SS(_0, _1) \ | |
| 907 static_assert((RegARM32::Reg_##_0 + 1) == RegARM32::Reg_##_1, \ | |
| 908 "ARM32 " #_0 " and " #_1 " registers are declared " \ | |
| 909 "incorrectly.") | |
| 910 SANITY_CHECK_SS(s0, s1); | |
| 911 SANITY_CHECK_SS(s1, s2); | |
| 912 SANITY_CHECK_SS(s2, s3); | |
| 913 SANITY_CHECK_SS(s3, s4); | |
| 914 SANITY_CHECK_SS(s4, s5); | |
| 915 SANITY_CHECK_SS(s5, s6); | |
| 916 SANITY_CHECK_SS(s6, s7); | |
| 917 SANITY_CHECK_SS(s7, s8); | |
| 918 SANITY_CHECK_SS(s8, s9); | |
| 919 SANITY_CHECK_SS(s9, s10); | |
| 920 SANITY_CHECK_SS(s10, s11); | |
| 921 SANITY_CHECK_SS(s11, s12); | |
| 922 SANITY_CHECK_SS(s12, s13); | |
| 923 SANITY_CHECK_SS(s13, s14); | |
| 924 SANITY_CHECK_SS(s14, s15); | |
| 925 #undef SANITY_CHECK_SS | |
| 926 | |
| 927 bool TargetARM32::CallingConv::FPInReg(Type Ty, int32_t *Reg) { | |
| 928 if (!VFPRegsFree.any()) { | |
| 929 return false; | |
| 930 } | 988 } |
| 931 | |
| 932 if (isVectorType(Ty)) { | |
| 933 // Q registers are declared in reverse order, so RegARM32::Reg_q0 > | |
| 934 // RegARM32::Reg_q1. Therefore, we need to subtract QRegStart from Reg_q0. | |
| 935 // Same thing goes for D registers. | |
| 936 int32_t QRegStart = (VFPRegsFree & ValidV128Regs).find_first(); | |
| 937 if (QRegStart >= 0) { | |
| 938 VFPRegsFree.reset(QRegStart, QRegStart + 4); | |
| 939 *Reg = RegARM32::Reg_q0 - (QRegStart / 4); | |
| 940 return true; | |
| 941 } | |
| 942 } else if (Ty == IceType_f64) { | |
| 943 int32_t DRegStart = (VFPRegsFree & ValidF64Regs).find_first(); | |
| 944 if (DRegStart >= 0) { | |
| 945 VFPRegsFree.reset(DRegStart, DRegStart + 2); | |
| 946 *Reg = RegARM32::Reg_d0 - (DRegStart / 2); | |
| 947 return true; | |
| 948 } | |
| 949 } else { | |
| 950 assert(Ty == IceType_f32); | |
| 951 int32_t SReg = VFPRegsFree.find_first(); | |
| 952 assert(SReg >= 0); | |
| 953 VFPRegsFree.reset(SReg); | |
| 954 *Reg = RegARM32::Reg_s0 + SReg; | |
| 955 return true; | |
| 956 } | |
| 957 | |
| 958 // Parameter allocation failed. From now on, every fp register must be placed | |
| 959 // on the stack. We clear VFRegsFree in case there are any "holes" from S and | |
| 960 // D registers. | |
| 961 VFPRegsFree.clear(); | |
| 962 return false; | |
| 963 } | 989 } |
| 964 | 990 |
| 965 void TargetARM32::lowerArguments() { | 991 void TargetARM32::lowerArguments() { |
| 966 VarList &Args = Func->getArgs(); | 992 VarList &Args = Func->getArgs(); |
| 967 TargetARM32::CallingConv CC; | 993 TargetARM32::CallingConv CC; |
| 968 | 994 |
| 969 // For each register argument, replace Arg in the argument list with the home | 995 // For each register argument, replace Arg in the argument list with the home |
| 970 // register. Then generate an instruction in the prolog to copy the home | 996 // register. Then generate an instruction in the prolog to copy the home |
| 971 // register to the assigned location of Arg. | 997 // register to the assigned location of Arg. |
| 972 Context.init(Func->getEntryNode()); | 998 Context.init(Func->getEntryNode()); |
| 973 Context.setInsertPoint(Context.getCur()); | 999 Context.setInsertPoint(Context.getCur()); |
| 974 | 1000 |
| 975 for (SizeT I = 0, E = Args.size(); I < E; ++I) { | 1001 for (SizeT I = 0, E = Args.size(); I < E; ++I) { |
| 976 Variable *Arg = Args[I]; | 1002 Variable *Arg = Args[I]; |
| 977 Type Ty = Arg->getType(); | 1003 Type Ty = Arg->getType(); |
| 978 if (Ty == IceType_i64) { | 1004 int RegNum; |
| 979 std::pair<int32_t, int32_t> RegPair; | 1005 if (isScalarIntegerType(Ty)) { |
| 980 if (!CC.I64InRegs(&RegPair)) | 1006 if (!CC.argInGPR(Ty, &RegNum)) { |
| 981 continue; | 1007 continue; |
| 982 Variable *RegisterArg = Func->makeVariable(Ty); | 1008 } |
| 983 auto *RegisterArg64On32 = llvm::cast<Variable64On32>(RegisterArg); | 1009 } else { |
| 984 if (BuildDefs::dump()) | 1010 if (!CC.argInVFP(Ty, &RegNum)) { |
| 985 RegisterArg64On32->setName(Func, "home_reg:" + Arg->getName(Func)); | 1011 continue; |
| 986 RegisterArg64On32->initHiLo(Func); | 1012 } |
| 987 RegisterArg64On32->setIsArg(); | 1013 } |
| 988 RegisterArg64On32->getLo()->setRegNum(RegPair.first); | |
| 989 RegisterArg64On32->getHi()->setRegNum(RegPair.second); | |
| 990 Arg->setIsArg(false); | |
| 991 | 1014 |
| 992 Args[I] = RegisterArg64On32; | 1015 Variable *RegisterArg = Func->makeVariable(Ty); |
| 993 Context.insert(InstAssign::create(Func, Arg, RegisterArg)); | 1016 if (BuildDefs::dump()) { |
| 994 continue; | 1017 RegisterArg->setName(Func, "home_reg:" + Arg->getName(Func)); |
| 995 } else { | |
| 996 int32_t RegNum; | |
| 997 if (isVectorType(Ty) || isFloatingType(Ty)) { | |
| 998 if (!CC.FPInReg(Ty, &RegNum)) | |
| 999 continue; | |
| 1000 } else { | |
| 1001 assert(Ty == IceType_i32); | |
| 1002 if (!CC.I32InReg(&RegNum)) | |
| 1003 continue; | |
| 1004 } | |
| 1005 Variable *RegisterArg = Func->makeVariable(Ty); | |
| 1006 if (BuildDefs::dump()) { | |
| 1007 RegisterArg->setName(Func, "home_reg:" + Arg->getName(Func)); | |
| 1008 } | |
| 1009 RegisterArg->setRegNum(RegNum); | |
| 1010 RegisterArg->setIsArg(); | |
| 1011 Arg->setIsArg(false); | |
| 1012 | |
| 1013 Args[I] = RegisterArg; | |
| 1014 Context.insert(InstAssign::create(Func, Arg, RegisterArg)); | |
| 1015 continue; | |
| 1016 } | 1018 } |
| 1019 RegisterArg->setIsArg(); |
| 1020 Arg->setIsArg(false); |
| 1021 Args[I] = RegisterArg; |
| 1022 switch (Ty) { |
| 1023 default: { RegisterArg->setRegNum(RegNum); } break; |
| 1024 case IceType_i64: { |
| 1025 auto *RegisterArg64 = llvm::cast<Variable64On32>(RegisterArg); |
| 1026 RegisterArg64->initHiLo(Func); |
| 1027 RegisterArg64->getLo()->setRegNum( |
| 1028 RegARM32::getI64PairFirstGPRNum(RegNum)); |
| 1029 RegisterArg64->getHi()->setRegNum( |
| 1030 RegARM32::getI64PairSecondGPRNum(RegNum)); |
| 1031 } break; |
| 1032 } |
| 1033 Context.insert(InstAssign::create(Func, Arg, RegisterArg)); |
| 1017 } | 1034 } |
| 1018 } | 1035 } |
| 1019 | 1036 |
| 1020 // Helper function for addProlog(). | 1037 // Helper function for addProlog(). |
| 1021 // | 1038 // |
| 1022 // This assumes Arg is an argument passed on the stack. This sets the frame | 1039 // This assumes Arg is an argument passed on the stack. This sets the frame |
| 1023 // offset for Arg and updates InArgsSizeBytes according to Arg's width. For an | 1040 // offset for Arg and updates InArgsSizeBytes according to Arg's width. For an |
| 1024 // I64 arg that has been split into Lo and Hi components, it calls itself | 1041 // I64 arg that has been split into Lo and Hi components, it calls itself |
| 1025 // recursively on the components, taking care to handle Lo first because of the | 1042 // recursively on the components, taking care to handle Lo first because of the |
| 1026 // little-endian architecture. Lastly, this function generates an instruction | 1043 // little-endian architecture. Lastly, this function generates an instruction |
| (...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1263 // Arg[0] is closest to the stack/frame pointer. | 1280 // Arg[0] is closest to the stack/frame pointer. |
| 1264 Variable *FramePtr = getPhysicalRegister(getFrameOrStackReg()); | 1281 Variable *FramePtr = getPhysicalRegister(getFrameOrStackReg()); |
| 1265 size_t BasicFrameOffset = PreservedRegsSizeBytes; | 1282 size_t BasicFrameOffset = PreservedRegsSizeBytes; |
| 1266 if (!UsesFramePointer) | 1283 if (!UsesFramePointer) |
| 1267 BasicFrameOffset += SpillAreaSizeBytes; | 1284 BasicFrameOffset += SpillAreaSizeBytes; |
| 1268 | 1285 |
| 1269 const VarList &Args = Func->getArgs(); | 1286 const VarList &Args = Func->getArgs(); |
| 1270 size_t InArgsSizeBytes = 0; | 1287 size_t InArgsSizeBytes = 0; |
| 1271 TargetARM32::CallingConv CC; | 1288 TargetARM32::CallingConv CC; |
| 1272 for (Variable *Arg : Args) { | 1289 for (Variable *Arg : Args) { |
| 1273 Type Ty = Arg->getType(); | 1290 int32_t DummyReg; |
| 1274 bool InRegs = false; | 1291 const Type Ty = Arg->getType(); |
| 1292 |
| 1275 // Skip arguments passed in registers. | 1293 // Skip arguments passed in registers. |
| 1276 if (isVectorType(Ty) || isFloatingType(Ty)) { | 1294 if (isScalarIntegerType(Ty)) { |
| 1277 int32_t DummyReg; | 1295 if (CC.argInGPR(Ty, &DummyReg)) { |
| 1278 InRegs = CC.FPInReg(Ty, &DummyReg); | 1296 continue; |
| 1279 } else if (Ty == IceType_i64) { | 1297 } |
| 1280 std::pair<int32_t, int32_t> DummyRegs; | |
| 1281 InRegs = CC.I64InRegs(&DummyRegs); | |
| 1282 } else { | 1298 } else { |
| 1283 assert(Ty == IceType_i32); | 1299 if (CC.argInVFP(Ty, &DummyReg)) { |
| 1284 int32_t DummyReg; | 1300 continue; |
| 1285 InRegs = CC.I32InReg(&DummyReg); | 1301 } |
| 1286 } | 1302 } |
| 1287 if (!InRegs) | 1303 finishArgumentLowering(Arg, FramePtr, BasicFrameOffset, &InArgsSizeBytes); |
| 1288 finishArgumentLowering(Arg, FramePtr, BasicFrameOffset, &InArgsSizeBytes); | |
| 1289 } | 1304 } |
| 1290 | 1305 |
| 1291 // Fill in stack offsets for locals. | 1306 // Fill in stack offsets for locals. |
| 1292 assignVarStackSlots(SortedSpilledVariables, SpillAreaPaddingBytes, | 1307 assignVarStackSlots(SortedSpilledVariables, SpillAreaPaddingBytes, |
| 1293 SpillAreaSizeBytes, GlobalsAndSubsequentPaddingSize, | 1308 SpillAreaSizeBytes, GlobalsAndSubsequentPaddingSize, |
| 1294 UsesFramePointer); | 1309 UsesFramePointer); |
| 1295 this->HasComputedFrame = true; | 1310 this->HasComputedFrame = true; |
| 1296 | 1311 |
| 1297 if (BuildDefs::dump() && Func->isVerbose(IceV_Frame)) { | 1312 if (BuildDefs::dump() && Func->isVerbose(IceV_Frame)) { |
| 1298 OstreamLocker _(Func->getContext()); | 1313 OstreamLocker _(Func->getContext()); |
| (...skipping 506 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1805 } | 1820 } |
| 1806 } | 1821 } |
| 1807 llvm::report_fatal_error("Unsupported operand type"); | 1822 llvm::report_fatal_error("Unsupported operand type"); |
| 1808 return nullptr; | 1823 return nullptr; |
| 1809 } | 1824 } |
| 1810 | 1825 |
| 1811 llvm::SmallBitVector TargetARM32::getRegisterSet(RegSetMask Include, | 1826 llvm::SmallBitVector TargetARM32::getRegisterSet(RegSetMask Include, |
| 1812 RegSetMask Exclude) const { | 1827 RegSetMask Exclude) const { |
| 1813 llvm::SmallBitVector Registers(RegARM32::Reg_NUM); | 1828 llvm::SmallBitVector Registers(RegARM32::Reg_NUM); |
| 1814 | 1829 |
| 1815 #define X(val, encode, name, scratch, preserved, stackptr, frameptr, isInt, \ | 1830 #define X(val, encode, name, cc_arg, scratch, preserved, stackptr, frameptr, \ |
| 1816 isI64Pair, isFP32, isFP64, isVec128, alias_init) \ | 1831 isInt, isI64Pair, isFP32, isFP64, isVec128, alias_init) \ |
| 1817 if (scratch && (Include & RegSet_CallerSave)) \ | 1832 if (scratch && (Include & RegSet_CallerSave)) \ |
| 1818 Registers[RegARM32::val] = true; \ | 1833 Registers[RegARM32::val] = true; \ |
| 1819 if (preserved && (Include & RegSet_CalleeSave)) \ | 1834 if (preserved && (Include & RegSet_CalleeSave)) \ |
| 1820 Registers[RegARM32::val] = true; \ | 1835 Registers[RegARM32::val] = true; \ |
| 1821 if (stackptr && (Include & RegSet_StackPointer)) \ | 1836 if (stackptr && (Include & RegSet_StackPointer)) \ |
| 1822 Registers[RegARM32::val] = true; \ | 1837 Registers[RegARM32::val] = true; \ |
| 1823 if (frameptr && (Include & RegSet_FramePointer)) \ | 1838 if (frameptr && (Include & RegSet_FramePointer)) \ |
| 1824 Registers[RegARM32::val] = true; \ | 1839 Registers[RegARM32::val] = true; \ |
| 1825 if (scratch && (Exclude & RegSet_CallerSave)) \ | 1840 if (scratch && (Exclude & RegSet_CallerSave)) \ |
| 1826 Registers[RegARM32::val] = false; \ | 1841 Registers[RegARM32::val] = false; \ |
| (...skipping 1396 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3223 if (TargetHelperPreamble != ARM32HelpersPreamble.end()) { | 3238 if (TargetHelperPreamble != ARM32HelpersPreamble.end()) { |
| 3224 (this->*TargetHelperPreamble->second)(Instr); | 3239 (this->*TargetHelperPreamble->second)(Instr); |
| 3225 } | 3240 } |
| 3226 } | 3241 } |
| 3227 MaybeLeafFunc = false; | 3242 MaybeLeafFunc = false; |
| 3228 NeedsStackAlignment = true; | 3243 NeedsStackAlignment = true; |
| 3229 | 3244 |
| 3230 // Assign arguments to registers and stack. Also reserve stack. | 3245 // Assign arguments to registers and stack. Also reserve stack. |
| 3231 TargetARM32::CallingConv CC; | 3246 TargetARM32::CallingConv CC; |
| 3232 // Pair of Arg Operand -> GPR number assignments. | 3247 // Pair of Arg Operand -> GPR number assignments. |
| 3233 llvm::SmallVector<std::pair<Operand *, int32_t>, | 3248 llvm::SmallVector<std::pair<Operand *, int32_t>, NumGPRArgs> GPRArgs; |
| 3234 TargetARM32::CallingConv::ARM32_MAX_GPR_ARG> GPRArgs; | 3249 llvm::SmallVector<std::pair<Operand *, int32_t>, NumFP32Args> FPArgs; |
| 3235 llvm::SmallVector<std::pair<Operand *, int32_t>, | |
| 3236 TargetARM32::CallingConv::ARM32_MAX_FP_REG_UNITS> FPArgs; | |
| 3237 // Pair of Arg Operand -> stack offset. | 3250 // Pair of Arg Operand -> stack offset. |
| 3238 llvm::SmallVector<std::pair<Operand *, int32_t>, 8> StackArgs; | 3251 llvm::SmallVector<std::pair<Operand *, int32_t>, 8> StackArgs; |
| 3239 size_t ParameterAreaSizeBytes = 0; | 3252 size_t ParameterAreaSizeBytes = 0; |
| 3240 | 3253 |
| 3241 // Classify each argument operand according to the location where the | 3254 // Classify each argument operand according to the location where the |
| 3242 // argument is passed. | 3255 // argument is passed. |
| 3243 for (SizeT i = 0, NumArgs = Instr->getNumArgs(); i < NumArgs; ++i) { | 3256 for (SizeT i = 0, NumArgs = Instr->getNumArgs(); i < NumArgs; ++i) { |
| 3244 Operand *Arg = legalizeUndef(Instr->getArg(i)); | 3257 Operand *Arg = legalizeUndef(Instr->getArg(i)); |
| 3245 Type Ty = Arg->getType(); | 3258 const Type Ty = Arg->getType(); |
| 3246 bool InRegs = false; | 3259 bool InReg = false; |
| 3247 if (Ty == IceType_i64) { | 3260 int32_t Reg; |
| 3248 std::pair<int32_t, int32_t> Regs; | 3261 if (isScalarIntegerType(Ty)) { |
| 3249 if (CC.I64InRegs(&Regs)) { | 3262 InReg = CC.argInGPR(Ty, &Reg); |
| 3250 InRegs = true; | |
| 3251 Operand *Lo = loOperand(Arg); | |
| 3252 Operand *Hi = hiOperand(Arg); | |
| 3253 GPRArgs.push_back(std::make_pair(Lo, Regs.first)); | |
| 3254 GPRArgs.push_back(std::make_pair(Hi, Regs.second)); | |
| 3255 } | |
| 3256 } else if (isVectorType(Ty) || isFloatingType(Ty)) { | |
| 3257 int32_t Reg; | |
| 3258 if (CC.FPInReg(Ty, &Reg)) { | |
| 3259 InRegs = true; | |
| 3260 FPArgs.push_back(std::make_pair(Arg, Reg)); | |
| 3261 } | |
| 3262 } else { | 3263 } else { |
| 3263 assert(Ty == IceType_i32); | 3264 InReg = CC.argInVFP(Ty, &Reg); |
| 3264 int32_t Reg; | |
| 3265 if (CC.I32InReg(&Reg)) { | |
| 3266 InRegs = true; | |
| 3267 GPRArgs.push_back(std::make_pair(Arg, Reg)); | |
| 3268 } | |
| 3269 } | 3265 } |
| 3270 | 3266 |
| 3271 if (!InRegs) { | 3267 if (!InReg) { |
| 3272 ParameterAreaSizeBytes = | 3268 ParameterAreaSizeBytes = |
| 3273 applyStackAlignmentTy(ParameterAreaSizeBytes, Ty); | 3269 applyStackAlignmentTy(ParameterAreaSizeBytes, Ty); |
| 3274 StackArgs.push_back(std::make_pair(Arg, ParameterAreaSizeBytes)); | 3270 StackArgs.push_back(std::make_pair(Arg, ParameterAreaSizeBytes)); |
| 3275 ParameterAreaSizeBytes += typeWidthInBytesOnStack(Ty); | 3271 ParameterAreaSizeBytes += typeWidthInBytesOnStack(Ty); |
| 3272 continue; |
| 3273 } |
| 3274 |
| 3275 if (Ty == IceType_i64) { |
| 3276 Operand *Lo = loOperand(Arg); |
| 3277 Operand *Hi = hiOperand(Arg); |
| 3278 GPRArgs.push_back( |
| 3279 std::make_pair(Lo, RegARM32::getI64PairFirstGPRNum(Reg))); |
| 3280 GPRArgs.push_back( |
| 3281 std::make_pair(Hi, RegARM32::getI64PairSecondGPRNum(Reg))); |
| 3282 } else if (isScalarIntegerType(Ty)) { |
| 3283 GPRArgs.push_back(std::make_pair(Arg, Reg)); |
| 3284 } else { |
| 3285 FPArgs.push_back(std::make_pair(Arg, Reg)); |
| 3276 } | 3286 } |
| 3277 } | 3287 } |
| 3278 | 3288 |
| 3279 // Adjust the parameter area so that the stack is aligned. It is assumed that | 3289 // Adjust the parameter area so that the stack is aligned. It is assumed that |
| 3280 // the stack is already aligned at the start of the calling sequence. | 3290 // the stack is already aligned at the start of the calling sequence. |
| 3281 ParameterAreaSizeBytes = applyStackAlignment(ParameterAreaSizeBytes); | 3291 ParameterAreaSizeBytes = applyStackAlignment(ParameterAreaSizeBytes); |
| 3282 | 3292 |
| 3283 if (ParameterAreaSizeBytes > MaxOutArgsSizeBytes) { | 3293 if (ParameterAreaSizeBytes > MaxOutArgsSizeBytes) { |
| 3284 llvm::report_fatal_error("MaxOutArgsSizeBytes is not really a max."); | 3294 llvm::report_fatal_error("MaxOutArgsSizeBytes is not really a max."); |
| 3285 } | 3295 } |
| (...skipping 3147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6433 // Technically R9 is used for TLS with Sandboxing, and we reserve it. | 6443 // Technically R9 is used for TLS with Sandboxing, and we reserve it. |
| 6434 // However, for compatibility with current NaCl LLVM, don't claim that. | 6444 // However, for compatibility with current NaCl LLVM, don't claim that. |
| 6435 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n"; | 6445 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n"; |
| 6436 } | 6446 } |
| 6437 | 6447 |
| 6438 llvm::SmallBitVector TargetARM32::TypeToRegisterSet[IceType_NUM]; | 6448 llvm::SmallBitVector TargetARM32::TypeToRegisterSet[IceType_NUM]; |
| 6439 llvm::SmallBitVector TargetARM32::RegisterAliases[RegARM32::Reg_NUM]; | 6449 llvm::SmallBitVector TargetARM32::RegisterAliases[RegARM32::Reg_NUM]; |
| 6440 llvm::SmallBitVector TargetARM32::ScratchRegs; | 6450 llvm::SmallBitVector TargetARM32::ScratchRegs; |
| 6441 | 6451 |
| 6442 } // end of namespace Ice | 6452 } // end of namespace Ice |
| OLD | NEW |