Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(499)

Side by Side Diff: src/IceTargetLoweringARM32.cpp

Issue 1508423003: Subzero. ARM32. Introduces explicit register parameter attribute. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: New IceRegistersARM32.def file. Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/IceTargetLoweringARM32.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/IceTargetLoweringARM32.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698