| 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 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 226 } | 226 } |
| 227 | 227 |
| 228 namespace { | 228 namespace { |
| 229 constexpr SizeT NumGPRArgs = | 229 constexpr SizeT NumGPRArgs = |
| 230 #define X(val, encode, name, cc_arg, scratch, preserved, stackptr, frameptr, \ | 230 #define X(val, encode, name, cc_arg, scratch, preserved, stackptr, frameptr, \ |
| 231 isGPR, isInt, isI64Pair, isFP32, isFP64, isVec128, alias_init) \ | 231 isGPR, isInt, isI64Pair, isFP32, isFP64, isVec128, alias_init) \ |
| 232 +(((cc_arg) > 0) ? 1 : 0) | 232 +(((cc_arg) > 0) ? 1 : 0) |
| 233 REGARM32_GPR_TABLE | 233 REGARM32_GPR_TABLE |
| 234 #undef X | 234 #undef X |
| 235 ; | 235 ; |
| 236 std::array<uint32_t, NumGPRArgs> GPRArgInitializer; | 236 std::array<RegNumT, NumGPRArgs> GPRArgInitializer; |
| 237 | 237 |
| 238 constexpr SizeT NumI64Args = | 238 constexpr SizeT NumI64Args = |
| 239 #define X(val, encode, name, cc_arg, scratch, preserved, stackptr, frameptr, \ | 239 #define X(val, encode, name, cc_arg, scratch, preserved, stackptr, frameptr, \ |
| 240 isGPR, isInt, isI64Pair, isFP32, isFP64, isVec128, alias_init) \ | 240 isGPR, isInt, isI64Pair, isFP32, isFP64, isVec128, alias_init) \ |
| 241 +(((cc_arg) > 0) ? 1 : 0) | 241 +(((cc_arg) > 0) ? 1 : 0) |
| 242 REGARM32_I64PAIR_TABLE | 242 REGARM32_I64PAIR_TABLE |
| 243 #undef X | 243 #undef X |
| 244 ; | 244 ; |
| 245 std::array<uint32_t, NumI64Args> I64ArgInitializer; | 245 std::array<RegNumT, NumI64Args> I64ArgInitializer; |
| 246 | 246 |
| 247 constexpr SizeT NumFP32Args = | 247 constexpr SizeT NumFP32Args = |
| 248 #define X(val, encode, name, cc_arg, scratch, preserved, stackptr, frameptr, \ | 248 #define X(val, encode, name, cc_arg, scratch, preserved, stackptr, frameptr, \ |
| 249 isGPR, isInt, isI64Pair, isFP32, isFP64, isVec128, alias_init) \ | 249 isGPR, isInt, isI64Pair, isFP32, isFP64, isVec128, alias_init) \ |
| 250 +(((cc_arg) > 0) ? 1 : 0) | 250 +(((cc_arg) > 0) ? 1 : 0) |
| 251 REGARM32_FP32_TABLE | 251 REGARM32_FP32_TABLE |
| 252 #undef X | 252 #undef X |
| 253 ; | 253 ; |
| 254 std::array<uint32_t, NumFP32Args> FP32ArgInitializer; | 254 std::array<RegNumT, NumFP32Args> FP32ArgInitializer; |
| 255 | 255 |
| 256 constexpr SizeT NumFP64Args = | 256 constexpr SizeT NumFP64Args = |
| 257 #define X(val, encode, name, cc_arg, scratch, preserved, stackptr, frameptr, \ | 257 #define X(val, encode, name, cc_arg, scratch, preserved, stackptr, frameptr, \ |
| 258 isGPR, isInt, isI64Pair, isFP32, isFP64, isVec128, alias_init) \ | 258 isGPR, isInt, isI64Pair, isFP32, isFP64, isVec128, alias_init) \ |
| 259 +(((cc_arg) > 0) ? 1 : 0) | 259 +(((cc_arg) > 0) ? 1 : 0) |
| 260 REGARM32_FP64_TABLE | 260 REGARM32_FP64_TABLE |
| 261 #undef X | 261 #undef X |
| 262 ; | 262 ; |
| 263 std::array<uint32_t, NumFP64Args> FP64ArgInitializer; | 263 std::array<RegNumT, NumFP64Args> FP64ArgInitializer; |
| 264 | 264 |
| 265 constexpr SizeT NumVec128Args = | 265 constexpr SizeT NumVec128Args = |
| 266 #define X(val, encode, name, cc_arg, scratch, preserved, stackptr, frameptr, \ | 266 #define X(val, encode, name, cc_arg, scratch, preserved, stackptr, frameptr, \ |
| 267 isGPR, isInt, isI64Pair, isFP32, isFP64, isVec128, alias_init) \ | 267 isGPR, isInt, isI64Pair, isFP32, isFP64, isVec128, alias_init) \ |
| 268 +(((cc_arg > 0)) ? 1 : 0) | 268 +(((cc_arg > 0)) ? 1 : 0) |
| 269 REGARM32_VEC128_TABLE | 269 REGARM32_VEC128_TABLE |
| 270 #undef X | 270 #undef X |
| 271 ; | 271 ; |
| 272 std::array<uint32_t, NumVec128Args> Vec128ArgInitializer; | 272 std::array<RegNumT, NumVec128Args> Vec128ArgInitializer; |
| 273 | 273 |
| 274 IceString getRegClassName(RegClass C) { | 274 IceString getRegClassName(RegClass C) { |
| 275 auto ClassNum = static_cast<RegARM32::RegClassARM32>(C); | 275 auto ClassNum = static_cast<RegARM32::RegClassARM32>(C); |
| 276 assert(ClassNum < RegARM32::RCARM32_NUM); | 276 assert(ClassNum < RegARM32::RCARM32_NUM); |
| 277 switch (ClassNum) { | 277 switch (ClassNum) { |
| 278 default: | 278 default: |
| 279 assert(C < RC_Target); | 279 assert(C < RC_Target); |
| 280 return regClassString(C); | 280 return regClassString(C); |
| 281 // Add handling of new register classes below. | 281 // Add handling of new register classes below. |
| 282 } | 282 } |
| 283 } | 283 } |
| 284 | 284 |
| 285 } // end of anonymous namespace | 285 } // end of anonymous namespace |
| 286 | 286 |
| 287 TargetARM32::TargetARM32(Cfg *Func) | 287 TargetARM32::TargetARM32(Cfg *Func) |
| 288 : TargetLowering(Func), NeedSandboxing(SandboxingType == ST_NaCl), | 288 : TargetLowering(Func), NeedSandboxing(SandboxingType == ST_NaCl), |
| 289 CPUFeatures(Func->getContext()->getFlags()) {} | 289 CPUFeatures(Func->getContext()->getFlags()) {} |
| 290 | 290 |
| 291 void TargetARM32::staticInit(GlobalContext *Ctx) { | 291 void TargetARM32::staticInit(GlobalContext *Ctx) { |
| 292 | 292 RegNumT::setLimit(RegARM32::Reg_NUM); |
| 293 // Limit this size (or do all bitsets need to be the same width)??? | 293 // Limit this size (or do all bitsets need to be the same width)??? |
| 294 llvm::SmallBitVector IntegerRegisters(RegARM32::Reg_NUM); | 294 llvm::SmallBitVector IntegerRegisters(RegARM32::Reg_NUM); |
| 295 llvm::SmallBitVector I64PairRegisters(RegARM32::Reg_NUM); | 295 llvm::SmallBitVector I64PairRegisters(RegARM32::Reg_NUM); |
| 296 llvm::SmallBitVector Float32Registers(RegARM32::Reg_NUM); | 296 llvm::SmallBitVector Float32Registers(RegARM32::Reg_NUM); |
| 297 llvm::SmallBitVector Float64Registers(RegARM32::Reg_NUM); | 297 llvm::SmallBitVector Float64Registers(RegARM32::Reg_NUM); |
| 298 llvm::SmallBitVector VectorRegisters(RegARM32::Reg_NUM); | 298 llvm::SmallBitVector VectorRegisters(RegARM32::Reg_NUM); |
| 299 llvm::SmallBitVector QtoSRegisters(RegARM32::Reg_NUM); | 299 llvm::SmallBitVector QtoSRegisters(RegARM32::Reg_NUM); |
| 300 llvm::SmallBitVector InvalidRegisters(RegARM32::Reg_NUM); | 300 llvm::SmallBitVector InvalidRegisters(RegARM32::Reg_NUM); |
| 301 const unsigned EncodedReg_q8 = RegARM32::RegTable[RegARM32::Reg_q8].Encoding; | 301 const unsigned EncodedReg_q8 = RegARM32::RegTable[RegARM32::Reg_q8].Encoding; |
| 302 for (int i = 0; i < RegARM32::Reg_NUM; ++i) { | 302 for (int i = 0; i < RegARM32::Reg_NUM; ++i) { |
| 303 const auto &Entry = RegARM32::RegTable[i]; | 303 const auto &Entry = RegARM32::RegTable[i]; |
| 304 IntegerRegisters[i] = Entry.IsInt; | 304 IntegerRegisters[i] = Entry.IsInt; |
| 305 I64PairRegisters[i] = Entry.IsI64Pair; | 305 I64PairRegisters[i] = Entry.IsI64Pair; |
| 306 Float32Registers[i] = Entry.IsFP32; | 306 Float32Registers[i] = Entry.IsFP32; |
| 307 Float64Registers[i] = Entry.IsFP64; | 307 Float64Registers[i] = Entry.IsFP64; |
| 308 VectorRegisters[i] = Entry.IsVec128; | 308 VectorRegisters[i] = Entry.IsVec128; |
| 309 RegisterAliases[i].resize(RegARM32::Reg_NUM); | 309 RegisterAliases[i].resize(RegARM32::Reg_NUM); |
| 310 // TODO(eholk): It would be better to store a QtoS flag in the | 310 // TODO(eholk): It would be better to store a QtoS flag in the |
| 311 // IceRegistersARM32 table than to compare their encodings here. | 311 // IceRegistersARM32 table than to compare their encodings here. |
| 312 QtoSRegisters[i] = Entry.IsVec128 && Entry.Encoding < EncodedReg_q8; | 312 QtoSRegisters[i] = Entry.IsVec128 && Entry.Encoding < EncodedReg_q8; |
| 313 for (int j = 0; j < Entry.NumAliases; ++j) { | 313 for (int j = 0; j < Entry.NumAliases; ++j) { |
| 314 assert(i == j || !RegisterAliases[i][Entry.Aliases[j]]); | 314 assert(i == j || !RegisterAliases[i][Entry.Aliases[j]]); |
| 315 RegisterAliases[i].set(Entry.Aliases[j]); | 315 RegisterAliases[i].set(Entry.Aliases[j]); |
| 316 } | 316 } |
| 317 assert(RegisterAliases[i][i]); | 317 assert(RegisterAliases[i][i]); |
| 318 if (Entry.CCArg <= 0) { | 318 if (Entry.CCArg <= 0) { |
| 319 continue; | 319 continue; |
| 320 } | 320 } |
| 321 const auto RegNum = RegNumT::fromInt(i); |
| 321 if (Entry.IsGPR) { | 322 if (Entry.IsGPR) { |
| 322 GPRArgInitializer[Entry.CCArg - 1] = i; | 323 GPRArgInitializer[Entry.CCArg - 1] = RegNum; |
| 323 } else if (Entry.IsI64Pair) { | 324 } else if (Entry.IsI64Pair) { |
| 324 I64ArgInitializer[Entry.CCArg - 1] = i; | 325 I64ArgInitializer[Entry.CCArg - 1] = RegNum; |
| 325 } else if (Entry.IsFP32) { | 326 } else if (Entry.IsFP32) { |
| 326 FP32ArgInitializer[Entry.CCArg - 1] = i; | 327 FP32ArgInitializer[Entry.CCArg - 1] = RegNum; |
| 327 } else if (Entry.IsFP64) { | 328 } else if (Entry.IsFP64) { |
| 328 FP64ArgInitializer[Entry.CCArg - 1] = i; | 329 FP64ArgInitializer[Entry.CCArg - 1] = RegNum; |
| 329 } else if (Entry.IsVec128) { | 330 } else if (Entry.IsVec128) { |
| 330 Vec128ArgInitializer[Entry.CCArg - 1] = i; | 331 Vec128ArgInitializer[Entry.CCArg - 1] = RegNum; |
| 331 } | 332 } |
| 332 } | 333 } |
| 333 TypeToRegisterSet[IceType_void] = InvalidRegisters; | 334 TypeToRegisterSet[IceType_void] = InvalidRegisters; |
| 334 TypeToRegisterSet[IceType_i1] = IntegerRegisters; | 335 TypeToRegisterSet[IceType_i1] = IntegerRegisters; |
| 335 TypeToRegisterSet[IceType_i8] = IntegerRegisters; | 336 TypeToRegisterSet[IceType_i8] = IntegerRegisters; |
| 336 TypeToRegisterSet[IceType_i16] = IntegerRegisters; | 337 TypeToRegisterSet[IceType_i16] = IntegerRegisters; |
| 337 TypeToRegisterSet[IceType_i32] = IntegerRegisters; | 338 TypeToRegisterSet[IceType_i32] = IntegerRegisters; |
| 338 TypeToRegisterSet[IceType_i64] = I64PairRegisters; | 339 TypeToRegisterSet[IceType_i64] = I64PairRegisters; |
| 339 TypeToRegisterSet[IceType_f32] = Float32Registers; | 340 TypeToRegisterSet[IceType_f32] = Float32Registers; |
| 340 TypeToRegisterSet[IceType_f64] = Float64Registers; | 341 TypeToRegisterSet[IceType_f64] = Float64Registers; |
| 341 TypeToRegisterSet[IceType_v4i1] = VectorRegisters; | 342 TypeToRegisterSet[IceType_v4i1] = VectorRegisters; |
| 342 TypeToRegisterSet[IceType_v8i1] = VectorRegisters; | 343 TypeToRegisterSet[IceType_v8i1] = VectorRegisters; |
| 343 TypeToRegisterSet[IceType_v16i1] = VectorRegisters; | 344 TypeToRegisterSet[IceType_v16i1] = VectorRegisters; |
| 344 TypeToRegisterSet[IceType_v16i8] = VectorRegisters; | 345 TypeToRegisterSet[IceType_v16i8] = VectorRegisters; |
| 345 TypeToRegisterSet[IceType_v8i16] = VectorRegisters; | 346 TypeToRegisterSet[IceType_v8i16] = VectorRegisters; |
| 346 TypeToRegisterSet[IceType_v4i32] = VectorRegisters; | 347 TypeToRegisterSet[IceType_v4i32] = VectorRegisters; |
| 347 TypeToRegisterSet[IceType_v4f32] = VectorRegisters; | 348 TypeToRegisterSet[IceType_v4f32] = VectorRegisters; |
| 348 TypeToRegisterSet[RegARM32::RCARM32_QtoS] = QtoSRegisters; | 349 TypeToRegisterSet[RegARM32::RCARM32_QtoS] = QtoSRegisters; |
| 349 | 350 |
| 350 for (size_t i = 0; i < llvm::array_lengthof(TypeToRegisterSet); ++i) | 351 for (size_t i = 0; i < llvm::array_lengthof(TypeToRegisterSet); ++i) |
| 351 TypeToRegisterSetUnfiltered[i] = TypeToRegisterSet[i]; | 352 TypeToRegisterSetUnfiltered[i] = TypeToRegisterSet[i]; |
| 352 | 353 |
| 353 filterTypeToRegisterSet( | 354 filterTypeToRegisterSet( |
| 354 Ctx, RegARM32::Reg_NUM, TypeToRegisterSet, | 355 Ctx, RegARM32::Reg_NUM, TypeToRegisterSet, |
| 355 llvm::array_lengthof(TypeToRegisterSet), [](int32_t RegNum) -> IceString { | 356 llvm::array_lengthof(TypeToRegisterSet), [](RegNumT RegNum) -> IceString { |
| 356 // This function simply removes ", " from the register name. | 357 // This function simply removes ", " from the register name. |
| 357 IceString Name = RegARM32::getRegName(RegNum); | 358 IceString Name = RegARM32::getRegName(RegNum); |
| 358 constexpr const char RegSeparator[] = ", "; | 359 constexpr const char RegSeparator[] = ", "; |
| 359 constexpr size_t RegSeparatorWidth = | 360 constexpr size_t RegSeparatorWidth = |
| 360 llvm::array_lengthof(RegSeparator) - 1; | 361 llvm::array_lengthof(RegSeparator) - 1; |
| 361 for (size_t Pos = Name.find(RegSeparator); Pos != std::string::npos; | 362 for (size_t Pos = Name.find(RegSeparator); Pos != std::string::npos; |
| 362 Pos = Name.find(RegSeparator)) { | 363 Pos = Name.find(RegSeparator)) { |
| 363 Name.replace(Pos, RegSeparatorWidth, ""); | 364 Name.replace(Pos, RegSeparatorWidth, ""); |
| 364 } | 365 } |
| 365 return Name; | 366 return Name; |
| 366 }, getRegClassName); | 367 }, getRegClassName); |
| 367 } | 368 } |
| 368 | 369 |
| 369 namespace { | 370 namespace { |
| 370 void copyRegAllocFromInfWeightVariable64On32(const VarList &Vars) { | 371 void copyRegAllocFromInfWeightVariable64On32(const VarList &Vars) { |
| 371 for (Variable *Var : Vars) { | 372 for (Variable *Var : Vars) { |
| 372 auto *Var64 = llvm::dyn_cast<Variable64On32>(Var); | 373 auto *Var64 = llvm::dyn_cast<Variable64On32>(Var); |
| 373 if (!Var64) { | 374 if (!Var64) { |
| 374 // This is not the variable we are looking for. | 375 // This is not the variable we are looking for. |
| 375 continue; | 376 continue; |
| 376 } | 377 } |
| 377 assert(Var64->hasReg() || !Var64->mustHaveReg()); | 378 assert(Var64->hasReg() || !Var64->mustHaveReg()); |
| 378 if (!Var64->hasReg()) { | 379 if (!Var64->hasReg()) { |
| 379 continue; | 380 continue; |
| 380 } | 381 } |
| 381 SizeT FirstReg = RegARM32::getI64PairFirstGPRNum(Var->getRegNum()); | 382 const auto FirstReg = |
| 383 RegNumT::fixme(RegARM32::getI64PairFirstGPRNum(Var->getRegNum())); |
| 382 // This assumes little endian. | 384 // This assumes little endian. |
| 383 Variable *Lo = Var64->getLo(); | 385 Variable *Lo = Var64->getLo(); |
| 384 Variable *Hi = Var64->getHi(); | 386 Variable *Hi = Var64->getHi(); |
| 385 assert(Lo->hasReg() == Hi->hasReg()); | 387 assert(Lo->hasReg() == Hi->hasReg()); |
| 386 if (Lo->hasReg()) { | 388 if (Lo->hasReg()) { |
| 387 continue; | 389 continue; |
| 388 } | 390 } |
| 389 Lo->setRegNum(FirstReg); | 391 Lo->setRegNum(FirstReg); |
| 390 Lo->setMustHaveReg(); | 392 Lo->setMustHaveReg(); |
| 391 Hi->setRegNum(FirstReg + 1); | 393 Hi->setRegNum(RegNumT::fixme(FirstReg + 1)); |
| 392 Hi->setMustHaveReg(); | 394 Hi->setMustHaveReg(); |
| 393 } | 395 } |
| 394 } | 396 } |
| 395 } // end of anonymous namespace | 397 } // end of anonymous namespace |
| 396 | 398 |
| 397 uint32_t TargetARM32::getCallStackArgumentsSizeBytes(const InstCall *Call) { | 399 uint32_t TargetARM32::getCallStackArgumentsSizeBytes(const InstCall *Call) { |
| 398 TargetARM32::CallingConv CC; | 400 TargetARM32::CallingConv CC; |
| 399 int32_t DummyReg; | 401 RegNumT DummyReg; |
| 400 size_t OutArgsSizeBytes = 0; | 402 size_t OutArgsSizeBytes = 0; |
| 401 for (SizeT i = 0, NumArgs = Call->getNumArgs(); i < NumArgs; ++i) { | 403 for (SizeT i = 0, NumArgs = Call->getNumArgs(); i < NumArgs; ++i) { |
| 402 Operand *Arg = legalizeUndef(Call->getArg(i)); | 404 Operand *Arg = legalizeUndef(Call->getArg(i)); |
| 403 const Type Ty = Arg->getType(); | 405 const Type Ty = Arg->getType(); |
| 404 if (isScalarIntegerType(Ty)) { | 406 if (isScalarIntegerType(Ty)) { |
| 405 if (CC.argInGPR(Ty, &DummyReg)) { | 407 if (CC.argInGPR(Ty, &DummyReg)) { |
| 406 continue; | 408 continue; |
| 407 } | 409 } |
| 408 } else { | 410 } else { |
| 409 if (CC.argInVFP(Ty, &DummyReg)) { | 411 if (CC.argInVFP(Ty, &DummyReg)) { |
| (...skipping 503 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 913 return ARM32_STACK_ALIGNMENT_BYTES; | 915 return ARM32_STACK_ALIGNMENT_BYTES; |
| 914 } | 916 } |
| 915 | 917 |
| 916 bool TargetARM32::doBranchOpt(Inst *I, const CfgNode *NextNode) { | 918 bool TargetARM32::doBranchOpt(Inst *I, const CfgNode *NextNode) { |
| 917 if (auto *Br = llvm::dyn_cast<InstARM32Br>(I)) { | 919 if (auto *Br = llvm::dyn_cast<InstARM32Br>(I)) { |
| 918 return Br->optimizeBranch(NextNode); | 920 return Br->optimizeBranch(NextNode); |
| 919 } | 921 } |
| 920 return false; | 922 return false; |
| 921 } | 923 } |
| 922 | 924 |
| 923 IceString TargetARM32::getRegName(SizeT RegNum, Type Ty) const { | 925 IceString TargetARM32::getRegName(RegNumT RegNum, Type Ty) const { |
| 924 assert(RegNum < RegARM32::Reg_NUM); | |
| 925 (void)Ty; | 926 (void)Ty; |
| 926 return RegARM32::getRegName(RegNum); | 927 return RegARM32::getRegName(RegNum); |
| 927 } | 928 } |
| 928 | 929 |
| 929 Variable *TargetARM32::getPhysicalRegister(SizeT RegNum, Type Ty) { | 930 Variable *TargetARM32::getPhysicalRegister(RegNumT RegNum, Type Ty) { |
| 930 static const Type DefaultType[] = { | 931 static const Type DefaultType[] = { |
| 931 #define X(val, encode, name, cc_arg, scratch, preserved, stackptr, frameptr, \ | 932 #define X(val, encode, name, cc_arg, scratch, preserved, stackptr, frameptr, \ |
| 932 isGPR, isInt, isI64Pair, isFP32, isFP64, isVec128, alias_init) \ | 933 isGPR, isInt, isI64Pair, isFP32, isFP64, isVec128, alias_init) \ |
| 933 (isFP32) \ | 934 (isFP32) \ |
| 934 ? IceType_f32 \ | 935 ? IceType_f32 \ |
| 935 : ((isFP64) ? IceType_f64 : ((isVec128 ? IceType_v4i32 : IceType_i32))), | 936 : ((isFP64) ? IceType_f64 : ((isVec128 ? IceType_v4i32 : IceType_i32))), |
| 936 REGARM32_TABLE | 937 REGARM32_TABLE |
| 937 #undef X | 938 #undef X |
| 938 }; | 939 }; |
| 939 | 940 |
| 940 assert(RegNum < RegARM32::Reg_NUM); | |
| 941 if (Ty == IceType_void) { | 941 if (Ty == IceType_void) { |
| 942 assert(RegNum < llvm::array_lengthof(DefaultType)); | 942 assert(unsigned(RegNum) < llvm::array_lengthof(DefaultType)); |
| 943 Ty = DefaultType[RegNum]; | 943 Ty = DefaultType[RegNum]; |
| 944 } | 944 } |
| 945 if (PhysicalRegisters[Ty].empty()) | 945 if (PhysicalRegisters[Ty].empty()) |
| 946 PhysicalRegisters[Ty].resize(RegARM32::Reg_NUM); | 946 PhysicalRegisters[Ty].resize(RegARM32::Reg_NUM); |
| 947 assert(RegNum < PhysicalRegisters[Ty].size()); | 947 assert(unsigned(RegNum) < PhysicalRegisters[Ty].size()); |
| 948 Variable *Reg = PhysicalRegisters[Ty][RegNum]; | 948 Variable *Reg = PhysicalRegisters[Ty][RegNum]; |
| 949 if (Reg == nullptr) { | 949 if (Reg == nullptr) { |
| 950 Reg = Func->makeVariable(Ty); | 950 Reg = Func->makeVariable(Ty); |
| 951 Reg->setRegNum(RegNum); | 951 Reg->setRegNum(RegNum); |
| 952 PhysicalRegisters[Ty][RegNum] = Reg; | 952 PhysicalRegisters[Ty][RegNum] = Reg; |
| 953 // Specially mark a named physical register as an "argument" so that it is | 953 // Specially mark a named physical register as an "argument" so that it is |
| 954 // considered live upon function entry. Otherwise it's possible to get | 954 // considered live upon function entry. Otherwise it's possible to get |
| 955 // liveness validation errors for saving callee-save registers. | 955 // liveness validation errors for saving callee-save registers. |
| 956 Func->addImplicitArg(Reg); | 956 Func->addImplicitArg(Reg); |
| 957 // Don't bother tracking the live range of a named physical register. | 957 // Don't bother tracking the live range of a named physical register. |
| (...skipping 16 matching lines...) Expand all Loading... |
| 974 Str << getRegName(Var->getRegNum(), Var->getType()); | 974 Str << getRegName(Var->getRegNum(), Var->getType()); |
| 975 return; | 975 return; |
| 976 } | 976 } |
| 977 if (Var->mustHaveReg()) { | 977 if (Var->mustHaveReg()) { |
| 978 llvm::report_fatal_error("Infinite-weight Variable (" + Var->getName(Func) + | 978 llvm::report_fatal_error("Infinite-weight Variable (" + Var->getName(Func) + |
| 979 ") has no register assigned - function " + | 979 ") has no register assigned - function " + |
| 980 Func->getFunctionName()); | 980 Func->getFunctionName()); |
| 981 } | 981 } |
| 982 assert(!Var->isRematerializable()); | 982 assert(!Var->isRematerializable()); |
| 983 int32_t Offset = Var->getStackOffset(); | 983 int32_t Offset = Var->getStackOffset(); |
| 984 int32_t BaseRegNum = Var->getBaseRegNum(); | 984 auto BaseRegNum = Var->getBaseRegNum(); |
| 985 if (BaseRegNum == Variable::NoRegister) { | 985 if (BaseRegNum == RegNumT::NoRegister) { |
| 986 BaseRegNum = getFrameOrStackReg(); | 986 BaseRegNum = getFrameOrStackReg(); |
| 987 } | 987 } |
| 988 const Type VarTy = Var->getType(); | 988 const Type VarTy = Var->getType(); |
| 989 Str << "[" << getRegName(BaseRegNum, VarTy); | 989 Str << "[" << getRegName(BaseRegNum, VarTy); |
| 990 if (Offset != 0) { | 990 if (Offset != 0) { |
| 991 Str << ", #" << Offset; | 991 Str << ", #" << Offset; |
| 992 } | 992 } |
| 993 Str << "]"; | 993 Str << "]"; |
| 994 } | 994 } |
| 995 | 995 |
| 996 TargetARM32::CallingConv::CallingConv() | 996 TargetARM32::CallingConv::CallingConv() |
| 997 : GPRegsUsed(RegARM32::Reg_NUM), | 997 : GPRegsUsed(RegARM32::Reg_NUM), |
| 998 GPRArgs(GPRArgInitializer.rbegin(), GPRArgInitializer.rend()), | 998 GPRArgs(GPRArgInitializer.rbegin(), GPRArgInitializer.rend()), |
| 999 I64Args(I64ArgInitializer.rbegin(), I64ArgInitializer.rend()), | 999 I64Args(I64ArgInitializer.rbegin(), I64ArgInitializer.rend()), |
| 1000 VFPRegsUsed(RegARM32::Reg_NUM), | 1000 VFPRegsUsed(RegARM32::Reg_NUM), |
| 1001 FP32Args(FP32ArgInitializer.rbegin(), FP32ArgInitializer.rend()), | 1001 FP32Args(FP32ArgInitializer.rbegin(), FP32ArgInitializer.rend()), |
| 1002 FP64Args(FP64ArgInitializer.rbegin(), FP64ArgInitializer.rend()), | 1002 FP64Args(FP64ArgInitializer.rbegin(), FP64ArgInitializer.rend()), |
| 1003 Vec128Args(Vec128ArgInitializer.rbegin(), Vec128ArgInitializer.rend()) {} | 1003 Vec128Args(Vec128ArgInitializer.rbegin(), Vec128ArgInitializer.rend()) {} |
| 1004 | 1004 |
| 1005 bool TargetARM32::CallingConv::argInGPR(Type Ty, int32_t *Reg) { | 1005 bool TargetARM32::CallingConv::argInGPR(Type Ty, RegNumT *Reg) { |
| 1006 CfgVector<SizeT> *Source; | 1006 CfgVector<RegNumT> *Source; |
| 1007 | 1007 |
| 1008 switch (Ty) { | 1008 switch (Ty) { |
| 1009 default: { | 1009 default: { |
| 1010 assert(isScalarIntegerType(Ty)); | 1010 assert(isScalarIntegerType(Ty)); |
| 1011 Source = &GPRArgs; | 1011 Source = &GPRArgs; |
| 1012 } break; | 1012 } break; |
| 1013 case IceType_i64: { | 1013 case IceType_i64: { |
| 1014 Source = &I64Args; | 1014 Source = &I64Args; |
| 1015 } break; | 1015 } break; |
| 1016 } | 1016 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1030 GPRegsUsed |= RegisterAliases[*Reg]; | 1030 GPRegsUsed |= RegisterAliases[*Reg]; |
| 1031 return true; | 1031 return true; |
| 1032 } | 1032 } |
| 1033 | 1033 |
| 1034 // GPR are not packed when passing parameters. Thus, a function foo(i32, i64, | 1034 // GPR are not packed when passing parameters. Thus, a function foo(i32, i64, |
| 1035 // i32) will have the first argument in r0, the second in r1-r2, and the third | 1035 // i32) will have the first argument in r0, the second in r1-r2, and the third |
| 1036 // on the stack. To model this behavior, whenever we pop a register from Regs, | 1036 // on the stack. To model this behavior, whenever we pop a register from Regs, |
| 1037 // we remove all of its aliases from the pool of available GPRs. This has the | 1037 // we remove all of its aliases from the pool of available GPRs. This has the |
| 1038 // effect of computing the "closure" on the GPR registers. | 1038 // effect of computing the "closure" on the GPR registers. |
| 1039 void TargetARM32::CallingConv::discardUnavailableGPRsAndTheirAliases( | 1039 void TargetARM32::CallingConv::discardUnavailableGPRsAndTheirAliases( |
| 1040 CfgVector<SizeT> *Regs) { | 1040 CfgVector<RegNumT> *Regs) { |
| 1041 while (!Regs->empty() && GPRegsUsed[Regs->back()]) { | 1041 while (!Regs->empty() && GPRegsUsed[Regs->back()]) { |
| 1042 GPRegsUsed |= RegisterAliases[Regs->back()]; | 1042 GPRegsUsed |= RegisterAliases[Regs->back()]; |
| 1043 Regs->pop_back(); | 1043 Regs->pop_back(); |
| 1044 } | 1044 } |
| 1045 } | 1045 } |
| 1046 | 1046 |
| 1047 bool TargetARM32::CallingConv::argInVFP(Type Ty, int32_t *Reg) { | 1047 bool TargetARM32::CallingConv::argInVFP(Type Ty, RegNumT *Reg) { |
| 1048 CfgVector<SizeT> *Source; | 1048 CfgVector<RegNumT> *Source; |
| 1049 | 1049 |
| 1050 switch (Ty) { | 1050 switch (Ty) { |
| 1051 default: { | 1051 default: { |
| 1052 assert(isVectorType(Ty)); | 1052 assert(isVectorType(Ty)); |
| 1053 Source = &Vec128Args; | 1053 Source = &Vec128Args; |
| 1054 } break; | 1054 } break; |
| 1055 case IceType_f32: { | 1055 case IceType_f32: { |
| 1056 Source = &FP32Args; | 1056 Source = &FP32Args; |
| 1057 } break; | 1057 } break; |
| 1058 case IceType_f64: { | 1058 case IceType_f64: { |
| 1059 Source = &FP64Args; | 1059 Source = &FP64Args; |
| 1060 } break; | 1060 } break; |
| 1061 } | 1061 } |
| 1062 | 1062 |
| 1063 discardUnavailableVFPRegs(Source); | 1063 discardUnavailableVFPRegs(Source); |
| 1064 | 1064 |
| 1065 if (Source->empty()) { | 1065 if (Source->empty()) { |
| 1066 VFPRegsUsed.set(); | 1066 VFPRegsUsed.set(); |
| 1067 return false; | 1067 return false; |
| 1068 } | 1068 } |
| 1069 | 1069 |
| 1070 *Reg = Source->back(); | 1070 *Reg = Source->back(); |
| 1071 VFPRegsUsed |= RegisterAliases[*Reg]; | 1071 VFPRegsUsed |= RegisterAliases[*Reg]; |
| 1072 return true; | 1072 return true; |
| 1073 } | 1073 } |
| 1074 | 1074 |
| 1075 // Arguments in VFP registers are not packed, so we don't mark the popped | 1075 // Arguments in VFP registers are not packed, so we don't mark the popped |
| 1076 // registers' aliases as unavailable. | 1076 // registers' aliases as unavailable. |
| 1077 void TargetARM32::CallingConv::discardUnavailableVFPRegs( | 1077 void TargetARM32::CallingConv::discardUnavailableVFPRegs( |
| 1078 CfgVector<SizeT> *Regs) { | 1078 CfgVector<RegNumT> *Regs) { |
| 1079 while (!Regs->empty() && VFPRegsUsed[Regs->back()]) { | 1079 while (!Regs->empty() && VFPRegsUsed[Regs->back()]) { |
| 1080 Regs->pop_back(); | 1080 Regs->pop_back(); |
| 1081 } | 1081 } |
| 1082 } | 1082 } |
| 1083 | 1083 |
| 1084 void TargetARM32::lowerArguments() { | 1084 void TargetARM32::lowerArguments() { |
| 1085 VarList &Args = Func->getArgs(); | 1085 VarList &Args = Func->getArgs(); |
| 1086 TargetARM32::CallingConv CC; | 1086 TargetARM32::CallingConv CC; |
| 1087 | 1087 |
| 1088 // For each register argument, replace Arg in the argument list with the home | 1088 // For each register argument, replace Arg in the argument list with the home |
| 1089 // register. Then generate an instruction in the prolog to copy the home | 1089 // register. Then generate an instruction in the prolog to copy the home |
| 1090 // register to the assigned location of Arg. | 1090 // register to the assigned location of Arg. |
| 1091 Context.init(Func->getEntryNode()); | 1091 Context.init(Func->getEntryNode()); |
| 1092 Context.setInsertPoint(Context.getCur()); | 1092 Context.setInsertPoint(Context.getCur()); |
| 1093 | 1093 |
| 1094 for (SizeT I = 0, E = Args.size(); I < E; ++I) { | 1094 for (SizeT I = 0, E = Args.size(); I < E; ++I) { |
| 1095 Variable *Arg = Args[I]; | 1095 Variable *Arg = Args[I]; |
| 1096 Type Ty = Arg->getType(); | 1096 Type Ty = Arg->getType(); |
| 1097 int RegNum; | 1097 RegNumT RegNum; |
| 1098 if (isScalarIntegerType(Ty)) { | 1098 if (isScalarIntegerType(Ty)) { |
| 1099 if (!CC.argInGPR(Ty, &RegNum)) { | 1099 if (!CC.argInGPR(Ty, &RegNum)) { |
| 1100 continue; | 1100 continue; |
| 1101 } | 1101 } |
| 1102 } else { | 1102 } else { |
| 1103 if (!CC.argInVFP(Ty, &RegNum)) { | 1103 if (!CC.argInVFP(Ty, &RegNum)) { |
| 1104 continue; | 1104 continue; |
| 1105 } | 1105 } |
| 1106 } | 1106 } |
| 1107 | 1107 |
| 1108 Variable *RegisterArg = Func->makeVariable(Ty); | 1108 Variable *RegisterArg = Func->makeVariable(Ty); |
| 1109 if (BuildDefs::dump()) { | 1109 if (BuildDefs::dump()) { |
| 1110 RegisterArg->setName(Func, "home_reg:" + Arg->getName(Func)); | 1110 RegisterArg->setName(Func, "home_reg:" + Arg->getName(Func)); |
| 1111 } | 1111 } |
| 1112 RegisterArg->setIsArg(); | 1112 RegisterArg->setIsArg(); |
| 1113 Arg->setIsArg(false); | 1113 Arg->setIsArg(false); |
| 1114 Args[I] = RegisterArg; | 1114 Args[I] = RegisterArg; |
| 1115 switch (Ty) { | 1115 switch (Ty) { |
| 1116 default: { RegisterArg->setRegNum(RegNum); } break; | 1116 default: { RegisterArg->setRegNum(RegNum); } break; |
| 1117 case IceType_i64: { | 1117 case IceType_i64: { |
| 1118 auto *RegisterArg64 = llvm::cast<Variable64On32>(RegisterArg); | 1118 auto *RegisterArg64 = llvm::cast<Variable64On32>(RegisterArg); |
| 1119 RegisterArg64->initHiLo(Func); | 1119 RegisterArg64->initHiLo(Func); |
| 1120 RegisterArg64->getLo()->setRegNum( | 1120 RegisterArg64->getLo()->setRegNum( |
| 1121 RegARM32::getI64PairFirstGPRNum(RegNum)); | 1121 RegNumT::fixme(RegARM32::getI64PairFirstGPRNum(RegNum))); |
| 1122 RegisterArg64->getHi()->setRegNum( | 1122 RegisterArg64->getHi()->setRegNum( |
| 1123 RegARM32::getI64PairSecondGPRNum(RegNum)); | 1123 RegNumT::fixme(RegARM32::getI64PairSecondGPRNum(RegNum))); |
| 1124 } break; | 1124 } break; |
| 1125 } | 1125 } |
| 1126 Context.insert<InstAssign>(Arg, RegisterArg); | 1126 Context.insert<InstAssign>(Arg, RegisterArg); |
| 1127 } | 1127 } |
| 1128 } | 1128 } |
| 1129 | 1129 |
| 1130 // Helper function for addProlog(). | 1130 // Helper function for addProlog(). |
| 1131 // | 1131 // |
| 1132 // This assumes Arg is an argument passed on the stack. This sets the frame | 1132 // This assumes Arg is an argument passed on the stack. This sets the frame |
| 1133 // offset for Arg and updates InArgsSizeBytes according to Arg's width. For an | 1133 // offset for Arg and updates InArgsSizeBytes according to Arg's width. For an |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1298 &PreservedSRegs)}; | 1298 &PreservedSRegs)}; |
| 1299 for (const auto &RegClass : RegClasses) { | 1299 for (const auto &RegClass : RegClasses) { |
| 1300 const uint32_t FirstRegInClass = std::get<0>(RegClass); | 1300 const uint32_t FirstRegInClass = std::get<0>(RegClass); |
| 1301 const uint32_t LastRegInClass = std::get<1>(RegClass); | 1301 const uint32_t LastRegInClass = std::get<1>(RegClass); |
| 1302 VarList *const PreservedRegsInClass = std::get<2>(RegClass); | 1302 VarList *const PreservedRegsInClass = std::get<2>(RegClass); |
| 1303 for (uint32_t Reg = FirstRegInClass; Reg <= LastRegInClass; ++Reg) { | 1303 for (uint32_t Reg = FirstRegInClass; Reg <= LastRegInClass; ++Reg) { |
| 1304 if (!ToPreserve[Reg]) { | 1304 if (!ToPreserve[Reg]) { |
| 1305 continue; | 1305 continue; |
| 1306 } | 1306 } |
| 1307 ++NumCallee; | 1307 ++NumCallee; |
| 1308 Variable *PhysicalRegister = getPhysicalRegister(Reg); | 1308 Variable *PhysicalRegister = getPhysicalRegister(RegNumT::fromInt(Reg)); |
| 1309 PreservedRegsSizeBytes += | 1309 PreservedRegsSizeBytes += |
| 1310 typeWidthInBytesOnStack(PhysicalRegister->getType()); | 1310 typeWidthInBytesOnStack(PhysicalRegister->getType()); |
| 1311 PreservedRegsInClass->push_back(PhysicalRegister); | 1311 PreservedRegsInClass->push_back(PhysicalRegister); |
| 1312 } | 1312 } |
| 1313 } | 1313 } |
| 1314 | 1314 |
| 1315 Ctx->statsUpdateRegistersSaved(NumCallee); | 1315 Ctx->statsUpdateRegistersSaved(NumCallee); |
| 1316 if (!PreservedSRegs.empty()) | 1316 if (!PreservedSRegs.empty()) |
| 1317 _push(PreservedSRegs); | 1317 _push(PreservedSRegs); |
| 1318 if (!PreservedGPRs.empty()) | 1318 if (!PreservedGPRs.empty()) |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1373 // Arg[0] is closest to the stack/frame pointer. | 1373 // Arg[0] is closest to the stack/frame pointer. |
| 1374 Variable *FramePtr = getPhysicalRegister(getFrameOrStackReg()); | 1374 Variable *FramePtr = getPhysicalRegister(getFrameOrStackReg()); |
| 1375 size_t BasicFrameOffset = PreservedRegsSizeBytes; | 1375 size_t BasicFrameOffset = PreservedRegsSizeBytes; |
| 1376 if (!UsesFramePointer) | 1376 if (!UsesFramePointer) |
| 1377 BasicFrameOffset += SpillAreaSizeBytes; | 1377 BasicFrameOffset += SpillAreaSizeBytes; |
| 1378 | 1378 |
| 1379 const VarList &Args = Func->getArgs(); | 1379 const VarList &Args = Func->getArgs(); |
| 1380 size_t InArgsSizeBytes = 0; | 1380 size_t InArgsSizeBytes = 0; |
| 1381 TargetARM32::CallingConv CC; | 1381 TargetARM32::CallingConv CC; |
| 1382 for (Variable *Arg : Args) { | 1382 for (Variable *Arg : Args) { |
| 1383 int32_t DummyReg; | 1383 RegNumT DummyReg; |
| 1384 const Type Ty = Arg->getType(); | 1384 const Type Ty = Arg->getType(); |
| 1385 | 1385 |
| 1386 // Skip arguments passed in registers. | 1386 // Skip arguments passed in registers. |
| 1387 if (isScalarIntegerType(Ty)) { | 1387 if (isScalarIntegerType(Ty)) { |
| 1388 if (CC.argInGPR(Ty, &DummyReg)) { | 1388 if (CC.argInGPR(Ty, &DummyReg)) { |
| 1389 continue; | 1389 continue; |
| 1390 } | 1390 } |
| 1391 } else { | 1391 } else { |
| 1392 if (CC.argInVFP(Ty, &DummyReg)) { | 1392 if (CC.argInVFP(Ty, &DummyReg)) { |
| 1393 continue; | 1393 continue; |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1492 | 1492 |
| 1493 RI->setDeleted(); | 1493 RI->setDeleted(); |
| 1494 } | 1494 } |
| 1495 | 1495 |
| 1496 bool TargetARM32::isLegalMemOffset(Type Ty, int32_t Offset) const { | 1496 bool TargetARM32::isLegalMemOffset(Type Ty, int32_t Offset) const { |
| 1497 constexpr bool ZeroExt = false; | 1497 constexpr bool ZeroExt = false; |
| 1498 return OperandARM32Mem::canHoldOffset(Ty, ZeroExt, Offset); | 1498 return OperandARM32Mem::canHoldOffset(Ty, ZeroExt, Offset); |
| 1499 } | 1499 } |
| 1500 | 1500 |
| 1501 Variable *TargetARM32::PostLoweringLegalizer::newBaseRegister( | 1501 Variable *TargetARM32::PostLoweringLegalizer::newBaseRegister( |
| 1502 Variable *Base, int32_t Offset, int32_t ScratchRegNum) { | 1502 Variable *Base, int32_t Offset, RegNumT ScratchRegNum) { |
| 1503 // Legalize will likely need a movw/movt combination, but if the top bits are | 1503 // Legalize will likely need a movw/movt combination, but if the top bits are |
| 1504 // all 0 from negating the offset and subtracting, we could use that instead. | 1504 // all 0 from negating the offset and subtracting, we could use that instead. |
| 1505 const bool ShouldSub = Offset != 0 && (-Offset & 0xFFFF0000) == 0; | 1505 const bool ShouldSub = Offset != 0 && (-Offset & 0xFFFF0000) == 0; |
| 1506 Variable *ScratchReg = Target->makeReg(IceType_i32, ScratchRegNum); | 1506 Variable *ScratchReg = Target->makeReg(IceType_i32, ScratchRegNum); |
| 1507 if (ShouldSub) { | 1507 if (ShouldSub) { |
| 1508 Operand *OffsetVal = | 1508 Operand *OffsetVal = |
| 1509 Target->legalize(Target->Ctx->getConstantInt32(-Offset), | 1509 Target->legalize(Target->Ctx->getConstantInt32(-Offset), |
| 1510 Legal_Reg | Legal_Flex, ScratchRegNum); | 1510 Legal_Reg | Legal_Flex, ScratchRegNum); |
| 1511 Target->_sub(ScratchReg, Base, OffsetVal); | 1511 Target->_sub(ScratchReg, Base, OffsetVal); |
| 1512 } else { | 1512 } else { |
| 1513 Operand *OffsetVal = | 1513 Operand *OffsetVal = |
| 1514 Target->legalize(Target->Ctx->getConstantInt32(Offset), | 1514 Target->legalize(Target->Ctx->getConstantInt32(Offset), |
| 1515 Legal_Reg | Legal_Flex, ScratchRegNum); | 1515 Legal_Reg | Legal_Flex, ScratchRegNum); |
| 1516 Target->_add(ScratchReg, Base, OffsetVal); | 1516 Target->_add(ScratchReg, Base, OffsetVal); |
| 1517 } | 1517 } |
| 1518 | 1518 |
| 1519 if (ScratchRegNum == Target->getReservedTmpReg()) { | 1519 if (ScratchRegNum == Target->getReservedTmpReg()) { |
| 1520 const bool BaseIsStackOrFramePtr = | 1520 const bool BaseIsStackOrFramePtr = |
| 1521 Base->getRegNum() == static_cast<int32_t>(Target->getFrameOrStackReg()); | 1521 Base->getRegNum() == Target->getFrameOrStackReg(); |
| 1522 // There is currently no code path that would trigger this assertion, so we | 1522 // There is currently no code path that would trigger this assertion, so we |
| 1523 // leave this assertion here in case it is ever violated. This is not a | 1523 // leave this assertion here in case it is ever violated. This is not a |
| 1524 // fatal error (thus the use of assert() and not llvm::report_fatal_error) | 1524 // fatal error (thus the use of assert() and not llvm::report_fatal_error) |
| 1525 // as the program compiled by subzero will still work correctly. | 1525 // as the program compiled by subzero will still work correctly. |
| 1526 assert(BaseIsStackOrFramePtr); | 1526 assert(BaseIsStackOrFramePtr); |
| 1527 // Side-effect: updates TempBase to reflect the new Temporary. | 1527 // Side-effect: updates TempBase to reflect the new Temporary. |
| 1528 if (BaseIsStackOrFramePtr) { | 1528 if (BaseIsStackOrFramePtr) { |
| 1529 TempBaseReg = ScratchReg; | 1529 TempBaseReg = ScratchReg; |
| 1530 TempBaseOffset = Offset; | 1530 TempBaseOffset = Offset; |
| 1531 } else { | 1531 } else { |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1618 MovInstr->getPredicate()); | 1618 MovInstr->getPredicate()); |
| 1619 // _str() does not have a Dest, so we add a fake-def(Dest). | 1619 // _str() does not have a Dest, so we add a fake-def(Dest). |
| 1620 Target->Context.insert<InstFakeDef>(Dest); | 1620 Target->Context.insert<InstFakeDef>(Dest); |
| 1621 Legalized = true; | 1621 Legalized = true; |
| 1622 } else if (auto *Var = llvm::dyn_cast<Variable>(Src)) { | 1622 } else if (auto *Var = llvm::dyn_cast<Variable>(Src)) { |
| 1623 if (Var->isRematerializable()) { | 1623 if (Var->isRematerializable()) { |
| 1624 // This is equivalent to an x86 _lea(RematOffset(%esp/%ebp), Variable). | 1624 // This is equivalent to an x86 _lea(RematOffset(%esp/%ebp), Variable). |
| 1625 | 1625 |
| 1626 // ExtraOffset is only needed for frame-pointer based frames as we have | 1626 // ExtraOffset is only needed for frame-pointer based frames as we have |
| 1627 // to account for spill storage. | 1627 // to account for spill storage. |
| 1628 const int32_t ExtraOffset = | 1628 const int32_t ExtraOffset = (Var->getRegNum() == Target->getFrameReg()) |
| 1629 (static_cast<SizeT>(Var->getRegNum()) == Target->getFrameReg()) | 1629 ? Target->getFrameFixedAllocaOffset() |
| 1630 ? Target->getFrameFixedAllocaOffset() | 1630 : 0; |
| 1631 : 0; | |
| 1632 | 1631 |
| 1633 const int32_t Offset = Var->getStackOffset() + ExtraOffset; | 1632 const int32_t Offset = Var->getStackOffset() + ExtraOffset; |
| 1634 Variable *Base = Target->getPhysicalRegister(Var->getRegNum()); | 1633 Variable *Base = Target->getPhysicalRegister(Var->getRegNum()); |
| 1635 Variable *T = newBaseRegister(Base, Offset, Dest->getRegNum()); | 1634 Variable *T = newBaseRegister(Base, Offset, Dest->getRegNum()); |
| 1636 Target->_mov(Dest, T); | 1635 Target->_mov(Dest, T); |
| 1637 Legalized = true; | 1636 Legalized = true; |
| 1638 } else { | 1637 } else { |
| 1639 if (!Var->hasReg()) { | 1638 if (!Var->hasReg()) { |
| 1640 // This is a _mov(Variable, Mem()), i.e., a load. | 1639 // This is a _mov(Variable, Mem()), i.e., a load. |
| 1641 const int32_t Offset = Var->getStackOffset(); | 1640 const int32_t Offset = Var->getStackOffset(); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1689 bool AllowOffsets) { | 1688 bool AllowOffsets) { |
| 1690 assert(!Mem->isRegReg() || !Mem->getIndex()->isRematerializable()); | 1689 assert(!Mem->isRegReg() || !Mem->getIndex()->isRematerializable()); |
| 1691 assert( | 1690 assert( |
| 1692 Mem->isRegReg() || | 1691 Mem->isRegReg() || |
| 1693 Target->isLegalMemOffset(Mem->getType(), Mem->getOffset()->getValue())); | 1692 Target->isLegalMemOffset(Mem->getType(), Mem->getOffset()->getValue())); |
| 1694 | 1693 |
| 1695 bool Legalized = false; | 1694 bool Legalized = false; |
| 1696 Variable *Base = Mem->getBase(); | 1695 Variable *Base = Mem->getBase(); |
| 1697 int32_t Offset = Mem->isRegReg() ? 0 : Mem->getOffset()->getValue(); | 1696 int32_t Offset = Mem->isRegReg() ? 0 : Mem->getOffset()->getValue(); |
| 1698 if (Base->isRematerializable()) { | 1697 if (Base->isRematerializable()) { |
| 1699 const int32_t ExtraOffset = | 1698 const int32_t ExtraOffset = (Base->getRegNum() == Target->getFrameReg()) |
| 1700 (static_cast<SizeT>(Base->getRegNum()) == Target->getFrameReg()) | 1699 ? Target->getFrameFixedAllocaOffset() |
| 1701 ? Target->getFrameFixedAllocaOffset() | 1700 : 0; |
| 1702 : 0; | |
| 1703 Offset += Base->getStackOffset() + ExtraOffset; | 1701 Offset += Base->getStackOffset() + ExtraOffset; |
| 1704 Base = Target->getPhysicalRegister(Base->getRegNum()); | 1702 Base = Target->getPhysicalRegister(Base->getRegNum()); |
| 1705 assert(!Base->isRematerializable()); | 1703 assert(!Base->isRematerializable()); |
| 1706 Legalized = true; | 1704 Legalized = true; |
| 1707 } | 1705 } |
| 1708 | 1706 |
| 1709 if (!Legalized && !Target->NeedSandboxing) { | 1707 if (!Legalized && !Target->NeedSandboxing) { |
| 1710 return nullptr; | 1708 return nullptr; |
| 1711 } | 1709 } |
| 1712 | 1710 |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1912 } | 1910 } |
| 1913 } | 1911 } |
| 1914 llvm::report_fatal_error("Unsupported operand type"); | 1912 llvm::report_fatal_error("Unsupported operand type"); |
| 1915 return nullptr; | 1913 return nullptr; |
| 1916 } | 1914 } |
| 1917 | 1915 |
| 1918 llvm::SmallBitVector TargetARM32::getRegisterSet(RegSetMask Include, | 1916 llvm::SmallBitVector TargetARM32::getRegisterSet(RegSetMask Include, |
| 1919 RegSetMask Exclude) const { | 1917 RegSetMask Exclude) const { |
| 1920 llvm::SmallBitVector Registers(RegARM32::Reg_NUM); | 1918 llvm::SmallBitVector Registers(RegARM32::Reg_NUM); |
| 1921 | 1919 |
| 1922 for (int32_t i = 0; i < RegARM32::Reg_NUM; ++i) { | 1920 for (uint32_t i = 0; i < RegARM32::Reg_NUM; ++i) { |
| 1923 const auto &Entry = RegARM32::RegTable[i]; | 1921 const auto &Entry = RegARM32::RegTable[i]; |
| 1924 if (Entry.Scratch && (Include & RegSet_CallerSave)) | 1922 if (Entry.Scratch && (Include & RegSet_CallerSave)) |
| 1925 Registers[i] = true; | 1923 Registers[i] = true; |
| 1926 if (Entry.Preserved && (Include & RegSet_CalleeSave)) | 1924 if (Entry.Preserved && (Include & RegSet_CalleeSave)) |
| 1927 Registers[i] = true; | 1925 Registers[i] = true; |
| 1928 if (Entry.StackPtr && (Include & RegSet_StackPointer)) | 1926 if (Entry.StackPtr && (Include & RegSet_StackPointer)) |
| 1929 Registers[i] = true; | 1927 Registers[i] = true; |
| 1930 if (Entry.FramePtr && (Include & RegSet_FramePointer)) | 1928 if (Entry.FramePtr && (Include & RegSet_FramePointer)) |
| 1931 Registers[i] = true; | 1929 Registers[i] = true; |
| 1932 if (Entry.Scratch && (Exclude & RegSet_CallerSave)) | 1930 if (Entry.Scratch && (Exclude & RegSet_CallerSave)) |
| (...skipping 1443 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3376 if (TargetHelperPreamble != ARM32HelpersPreamble.end()) { | 3374 if (TargetHelperPreamble != ARM32HelpersPreamble.end()) { |
| 3377 (this->*TargetHelperPreamble->second)(Instr); | 3375 (this->*TargetHelperPreamble->second)(Instr); |
| 3378 } | 3376 } |
| 3379 } | 3377 } |
| 3380 MaybeLeafFunc = false; | 3378 MaybeLeafFunc = false; |
| 3381 NeedsStackAlignment = true; | 3379 NeedsStackAlignment = true; |
| 3382 | 3380 |
| 3383 // Assign arguments to registers and stack. Also reserve stack. | 3381 // Assign arguments to registers and stack. Also reserve stack. |
| 3384 TargetARM32::CallingConv CC; | 3382 TargetARM32::CallingConv CC; |
| 3385 // Pair of Arg Operand -> GPR number assignments. | 3383 // Pair of Arg Operand -> GPR number assignments. |
| 3386 llvm::SmallVector<std::pair<Operand *, int32_t>, NumGPRArgs> GPRArgs; | 3384 llvm::SmallVector<std::pair<Operand *, RegNumT>, NumGPRArgs> GPRArgs; |
| 3387 llvm::SmallVector<std::pair<Operand *, int32_t>, NumFP32Args> FPArgs; | 3385 llvm::SmallVector<std::pair<Operand *, RegNumT>, NumFP32Args> FPArgs; |
| 3388 // Pair of Arg Operand -> stack offset. | 3386 // Pair of Arg Operand -> stack offset. |
| 3389 llvm::SmallVector<std::pair<Operand *, int32_t>, 8> StackArgs; | 3387 llvm::SmallVector<std::pair<Operand *, int32_t>, 8> StackArgs; |
| 3390 size_t ParameterAreaSizeBytes = 0; | 3388 size_t ParameterAreaSizeBytes = 0; |
| 3391 | 3389 |
| 3392 // Classify each argument operand according to the location where the | 3390 // Classify each argument operand according to the location where the |
| 3393 // argument is passed. | 3391 // argument is passed. |
| 3394 for (SizeT i = 0, NumArgs = Instr->getNumArgs(); i < NumArgs; ++i) { | 3392 for (SizeT i = 0, NumArgs = Instr->getNumArgs(); i < NumArgs; ++i) { |
| 3395 Operand *Arg = legalizeUndef(Instr->getArg(i)); | 3393 Operand *Arg = legalizeUndef(Instr->getArg(i)); |
| 3396 const Type Ty = Arg->getType(); | 3394 const Type Ty = Arg->getType(); |
| 3397 bool InReg = false; | 3395 bool InReg = false; |
| 3398 int32_t Reg; | 3396 RegNumT Reg; |
| 3399 if (isScalarIntegerType(Ty)) { | 3397 if (isScalarIntegerType(Ty)) { |
| 3400 InReg = CC.argInGPR(Ty, &Reg); | 3398 InReg = CC.argInGPR(Ty, &Reg); |
| 3401 } else { | 3399 } else { |
| 3402 InReg = CC.argInVFP(Ty, &Reg); | 3400 InReg = CC.argInVFP(Ty, &Reg); |
| 3403 } | 3401 } |
| 3404 | 3402 |
| 3405 if (!InReg) { | 3403 if (!InReg) { |
| 3406 ParameterAreaSizeBytes = | 3404 ParameterAreaSizeBytes = |
| 3407 applyStackAlignmentTy(ParameterAreaSizeBytes, Ty); | 3405 applyStackAlignmentTy(ParameterAreaSizeBytes, Ty); |
| 3408 StackArgs.push_back(std::make_pair(Arg, ParameterAreaSizeBytes)); | 3406 StackArgs.push_back(std::make_pair(Arg, ParameterAreaSizeBytes)); |
| 3409 ParameterAreaSizeBytes += typeWidthInBytesOnStack(Ty); | 3407 ParameterAreaSizeBytes += typeWidthInBytesOnStack(Ty); |
| 3410 continue; | 3408 continue; |
| 3411 } | 3409 } |
| 3412 | 3410 |
| 3413 if (Ty == IceType_i64) { | 3411 if (Ty == IceType_i64) { |
| 3414 Operand *Lo = loOperand(Arg); | 3412 Operand *Lo = loOperand(Arg); |
| 3415 Operand *Hi = hiOperand(Arg); | 3413 Operand *Hi = hiOperand(Arg); |
| 3416 GPRArgs.push_back( | 3414 GPRArgs.push_back(std::make_pair( |
| 3417 std::make_pair(Lo, RegARM32::getI64PairFirstGPRNum(Reg))); | 3415 Lo, RegNumT::fixme(RegARM32::getI64PairFirstGPRNum(Reg)))); |
| 3418 GPRArgs.push_back( | 3416 GPRArgs.push_back(std::make_pair( |
| 3419 std::make_pair(Hi, RegARM32::getI64PairSecondGPRNum(Reg))); | 3417 Hi, RegNumT::fixme(RegARM32::getI64PairSecondGPRNum(Reg)))); |
| 3420 } else if (isScalarIntegerType(Ty)) { | 3418 } else if (isScalarIntegerType(Ty)) { |
| 3421 GPRArgs.push_back(std::make_pair(Arg, Reg)); | 3419 GPRArgs.push_back(std::make_pair(Arg, Reg)); |
| 3422 } else { | 3420 } else { |
| 3423 FPArgs.push_back(std::make_pair(Arg, Reg)); | 3421 FPArgs.push_back(std::make_pair(Arg, Reg)); |
| 3424 } | 3422 } |
| 3425 } | 3423 } |
| 3426 | 3424 |
| 3427 // Adjust the parameter area so that the stack is aligned. It is assumed that | 3425 // Adjust the parameter area so that the stack is aligned. It is assumed that |
| 3428 // the stack is already aligned at the start of the calling sequence. | 3426 // the stack is already aligned at the start of the calling sequence. |
| 3429 ParameterAreaSizeBytes = applyStackAlignment(ParameterAreaSizeBytes); | 3427 ParameterAreaSizeBytes = applyStackAlignment(ParameterAreaSizeBytes); |
| (...skipping 2081 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5511 } | 5509 } |
| 5512 | 5510 |
| 5513 void TargetARM32::lowerUnreachable(const InstUnreachable * /*Instr*/) { | 5511 void TargetARM32::lowerUnreachable(const InstUnreachable * /*Instr*/) { |
| 5514 _trap(); | 5512 _trap(); |
| 5515 } | 5513 } |
| 5516 | 5514 |
| 5517 void TargetARM32::prelowerPhis() { | 5515 void TargetARM32::prelowerPhis() { |
| 5518 PhiLowering::prelowerPhis32Bit<TargetARM32>(this, Context.getNode(), Func); | 5516 PhiLowering::prelowerPhis32Bit<TargetARM32>(this, Context.getNode(), Func); |
| 5519 } | 5517 } |
| 5520 | 5518 |
| 5521 Variable *TargetARM32::makeVectorOfZeros(Type Ty, int32_t RegNum) { | 5519 Variable *TargetARM32::makeVectorOfZeros(Type Ty, RegNumT RegNum) { |
| 5522 Variable *Reg = makeReg(Ty, RegNum); | 5520 Variable *Reg = makeReg(Ty, RegNum); |
| 5523 Context.insert<InstFakeDef>(Reg); | 5521 Context.insert<InstFakeDef>(Reg); |
| 5524 assert(isVectorType(Ty)); | 5522 assert(isVectorType(Ty)); |
| 5525 _veor(Reg, Reg, Reg); | 5523 _veor(Reg, Reg, Reg); |
| 5526 return Reg; | 5524 return Reg; |
| 5527 } | 5525 } |
| 5528 | 5526 |
| 5529 // Helper for legalize() to emit the right code to lower an operand to a | 5527 // Helper for legalize() to emit the right code to lower an operand to a |
| 5530 // register of the appropriate type. | 5528 // register of the appropriate type. |
| 5531 Variable *TargetARM32::copyToReg(Operand *Src, int32_t RegNum) { | 5529 Variable *TargetARM32::copyToReg(Operand *Src, RegNumT RegNum) { |
| 5532 Type Ty = Src->getType(); | 5530 Type Ty = Src->getType(); |
| 5533 Variable *Reg = makeReg(Ty, RegNum); | 5531 Variable *Reg = makeReg(Ty, RegNum); |
| 5534 if (auto *Mem = llvm::dyn_cast<OperandARM32Mem>(Src)) { | 5532 if (auto *Mem = llvm::dyn_cast<OperandARM32Mem>(Src)) { |
| 5535 _ldr(Reg, Mem); | 5533 _ldr(Reg, Mem); |
| 5536 } else { | 5534 } else { |
| 5537 _mov(Reg, Src); | 5535 _mov(Reg, Src); |
| 5538 } | 5536 } |
| 5539 return Reg; | 5537 return Reg; |
| 5540 } | 5538 } |
| 5541 | 5539 |
| 5542 // TODO(jpp): remove unneeded else clauses in legalize. | 5540 // TODO(jpp): remove unneeded else clauses in legalize. |
| 5543 Operand *TargetARM32::legalize(Operand *From, LegalMask Allowed, | 5541 Operand *TargetARM32::legalize(Operand *From, LegalMask Allowed, |
| 5544 int32_t RegNum) { | 5542 RegNumT RegNum) { |
| 5545 Type Ty = From->getType(); | 5543 Type Ty = From->getType(); |
| 5546 // Assert that a physical register is allowed. To date, all calls to | 5544 // Assert that a physical register is allowed. To date, all calls to |
| 5547 // legalize() allow a physical register. Legal_Flex converts registers to the | 5545 // legalize() allow a physical register. Legal_Flex converts registers to the |
| 5548 // right type OperandARM32FlexReg as needed. | 5546 // right type OperandARM32FlexReg as needed. |
| 5549 assert(Allowed & Legal_Reg); | 5547 assert(Allowed & Legal_Reg); |
| 5550 | 5548 |
| 5551 // Copied ipsis literis from TargetX86Base<Machine>. | 5549 // Copied ipsis literis from TargetX86Base<Machine>. |
| 5552 if (RegNum == Variable::NoRegister) { | 5550 if (RegNum == RegNumT::NoRegister) { |
| 5553 if (Variable *Subst = getContext().availabilityGet(From)) { | 5551 if (Variable *Subst = getContext().availabilityGet(From)) { |
| 5554 // At this point we know there is a potential substitution available. | 5552 // At this point we know there is a potential substitution available. |
| 5555 if (!Subst->isRematerializable() && Subst->mustHaveReg() && | 5553 if (!Subst->isRematerializable() && Subst->mustHaveReg() && |
| 5556 !Subst->hasReg()) { | 5554 !Subst->hasReg()) { |
| 5557 // At this point we know the substitution will have a register. | 5555 // At this point we know the substitution will have a register. |
| 5558 if (From->getType() == Subst->getType()) { | 5556 if (From->getType() == Subst->getType()) { |
| 5559 // At this point we know the substitution's register is compatible. | 5557 // At this point we know the substitution's register is compatible. |
| 5560 return Subst; | 5558 return Subst; |
| 5561 } | 5559 } |
| 5562 } | 5560 } |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5726 } | 5724 } |
| 5727 // Check if the variable is guaranteed a physical register. This can happen | 5725 // Check if the variable is guaranteed a physical register. This can happen |
| 5728 // either when the variable is pre-colored or when it is assigned infinite | 5726 // either when the variable is pre-colored or when it is assigned infinite |
| 5729 // weight. | 5727 // weight. |
| 5730 bool MustHaveRegister = (Var->hasReg() || Var->mustHaveReg()); | 5728 bool MustHaveRegister = (Var->hasReg() || Var->mustHaveReg()); |
| 5731 // We need a new physical register for the operand if: | 5729 // We need a new physical register for the operand if: |
| 5732 // Mem is not allowed and Var isn't guaranteed a physical | 5730 // Mem is not allowed and Var isn't guaranteed a physical |
| 5733 // register, or | 5731 // register, or |
| 5734 // RegNum is required and Var->getRegNum() doesn't match. | 5732 // RegNum is required and Var->getRegNum() doesn't match. |
| 5735 if ((!(Allowed & Legal_Mem) && !MustHaveRegister) || | 5733 if ((!(Allowed & Legal_Mem) && !MustHaveRegister) || |
| 5736 (RegNum != Variable::NoRegister && RegNum != Var->getRegNum())) { | 5734 (RegNum != RegNumT::NoRegister && RegNum != Var->getRegNum())) { |
| 5737 From = copyToReg(From, RegNum); | 5735 From = copyToReg(From, RegNum); |
| 5738 } | 5736 } |
| 5739 return From; | 5737 return From; |
| 5740 } | 5738 } |
| 5741 llvm::report_fatal_error("Unhandled operand kind in legalize()"); | 5739 llvm::report_fatal_error("Unhandled operand kind in legalize()"); |
| 5742 | 5740 |
| 5743 return From; | 5741 return From; |
| 5744 } | 5742 } |
| 5745 | 5743 |
| 5746 /// Provide a trivial wrapper to legalize() for this common usage. | 5744 /// Provide a trivial wrapper to legalize() for this common usage. |
| 5747 Variable *TargetARM32::legalizeToReg(Operand *From, int32_t RegNum) { | 5745 Variable *TargetARM32::legalizeToReg(Operand *From, RegNumT RegNum) { |
| 5748 return llvm::cast<Variable>(legalize(From, Legal_Reg, RegNum)); | 5746 return llvm::cast<Variable>(legalize(From, Legal_Reg, RegNum)); |
| 5749 } | 5747 } |
| 5750 | 5748 |
| 5751 /// Legalize undef values to concrete values. | 5749 /// Legalize undef values to concrete values. |
| 5752 Operand *TargetARM32::legalizeUndef(Operand *From, int32_t RegNum) { | 5750 Operand *TargetARM32::legalizeUndef(Operand *From, RegNumT RegNum) { |
| 5753 Type Ty = From->getType(); | 5751 Type Ty = From->getType(); |
| 5754 if (llvm::isa<ConstantUndef>(From)) { | 5752 if (llvm::isa<ConstantUndef>(From)) { |
| 5755 // Lower undefs to zero. Another option is to lower undefs to an | 5753 // Lower undefs to zero. Another option is to lower undefs to an |
| 5756 // uninitialized register; however, using an uninitialized register results | 5754 // uninitialized register; however, using an uninitialized register results |
| 5757 // in less predictable code. | 5755 // in less predictable code. |
| 5758 // | 5756 // |
| 5759 // If in the future the implementation is changed to lower undef values to | 5757 // If in the future the implementation is changed to lower undef values to |
| 5760 // uninitialized registers, a FakeDef will be needed: | 5758 // uninitialized registers, a FakeDef will be needed: |
| 5761 // Context.insert(InstFakeDef::create(Func, Reg)); This is in order to | 5759 // Context.insert(InstFakeDef::create(Func, Reg)); This is in order to |
| 5762 // ensure that the live range of Reg is not overestimated. If the constant | 5760 // ensure that the live range of Reg is not overestimated. If the constant |
| (...skipping 27 matching lines...) Expand all Loading... |
| 5790 Variable64On32 *TargetARM32::makeI64RegPair() { | 5788 Variable64On32 *TargetARM32::makeI64RegPair() { |
| 5791 Variable64On32 *Reg = | 5789 Variable64On32 *Reg = |
| 5792 llvm::cast<Variable64On32>(Func->makeVariable(IceType_i64)); | 5790 llvm::cast<Variable64On32>(Func->makeVariable(IceType_i64)); |
| 5793 Reg->setMustHaveReg(); | 5791 Reg->setMustHaveReg(); |
| 5794 Reg->initHiLo(Func); | 5792 Reg->initHiLo(Func); |
| 5795 Reg->getLo()->setMustNotHaveReg(); | 5793 Reg->getLo()->setMustNotHaveReg(); |
| 5796 Reg->getHi()->setMustNotHaveReg(); | 5794 Reg->getHi()->setMustNotHaveReg(); |
| 5797 return Reg; | 5795 return Reg; |
| 5798 } | 5796 } |
| 5799 | 5797 |
| 5800 Variable *TargetARM32::makeReg(Type Type, int32_t RegNum) { | 5798 Variable *TargetARM32::makeReg(Type Type, RegNumT RegNum) { |
| 5801 // There aren't any 64-bit integer registers for ARM32. | 5799 // There aren't any 64-bit integer registers for ARM32. |
| 5802 assert(Type != IceType_i64); | 5800 assert(Type != IceType_i64); |
| 5803 assert(AllowTemporaryWithNoReg || RegNum != Variable::NoRegister); | 5801 assert(AllowTemporaryWithNoReg || RegNum != RegNumT::NoRegister); |
| 5804 Variable *Reg = Func->makeVariable(Type); | 5802 Variable *Reg = Func->makeVariable(Type); |
| 5805 if (RegNum == Variable::NoRegister) | 5803 if (RegNum == RegNumT::NoRegister) |
| 5806 Reg->setMustHaveReg(); | 5804 Reg->setMustHaveReg(); |
| 5807 else | 5805 else |
| 5808 Reg->setRegNum(RegNum); | 5806 Reg->setRegNum(RegNum); |
| 5809 return Reg; | 5807 return Reg; |
| 5810 } | 5808 } |
| 5811 | 5809 |
| 5812 void TargetARM32::alignRegisterPow2(Variable *Reg, uint32_t Align, | 5810 void TargetARM32::alignRegisterPow2(Variable *Reg, uint32_t Align, |
| 5813 int32_t TmpRegNum) { | 5811 RegNumT TmpRegNum) { |
| 5814 assert(llvm::isPowerOf2_32(Align)); | 5812 assert(llvm::isPowerOf2_32(Align)); |
| 5815 uint32_t RotateAmt; | 5813 uint32_t RotateAmt; |
| 5816 uint32_t Immed_8; | 5814 uint32_t Immed_8; |
| 5817 Operand *Mask; | 5815 Operand *Mask; |
| 5818 // Use AND or BIC to mask off the bits, depending on which immediate fits (if | 5816 // Use AND or BIC to mask off the bits, depending on which immediate fits (if |
| 5819 // it fits at all). Assume Align is usually small, in which case BIC works | 5817 // it fits at all). Assume Align is usually small, in which case BIC works |
| 5820 // better. Thus, this rounds down to the alignment. | 5818 // better. Thus, this rounds down to the alignment. |
| 5821 if (OperandARM32FlexImm::canHoldImm(Align - 1, &RotateAmt, &Immed_8)) { | 5819 if (OperandARM32FlexImm::canHoldImm(Align - 1, &RotateAmt, &Immed_8)) { |
| 5822 Mask = legalize(Ctx->getConstantInt32(Align - 1), Legal_Reg | Legal_Flex, | 5820 Mask = legalize(Ctx->getConstantInt32(Align - 1), Legal_Reg | Legal_Flex, |
| 5823 TmpRegNum); | 5821 TmpRegNum); |
| 5824 _bic(Reg, Reg, Mask); | 5822 _bic(Reg, Reg, Mask); |
| 5825 } else { | 5823 } else { |
| 5826 Mask = legalize(Ctx->getConstantInt32(-Align), Legal_Reg | Legal_Flex, | 5824 Mask = legalize(Ctx->getConstantInt32(-Align), Legal_Reg | Legal_Flex, |
| 5827 TmpRegNum); | 5825 TmpRegNum); |
| 5828 _and(Reg, Reg, Mask); | 5826 _and(Reg, Reg, Mask); |
| 5829 } | 5827 } |
| 5830 } | 5828 } |
| 5831 | 5829 |
| 5832 void TargetARM32::postLower() { | 5830 void TargetARM32::postLower() { |
| 5833 if (Ctx->getFlags().getOptLevel() == Opt_m1) | 5831 if (Ctx->getFlags().getOptLevel() == Opt_m1) |
| 5834 return; | 5832 return; |
| 5835 markRedefinitions(); | 5833 markRedefinitions(); |
| 5836 Context.availabilityUpdate(); | 5834 Context.availabilityUpdate(); |
| 5837 } | 5835 } |
| 5838 | 5836 |
| 5839 void TargetARM32::makeRandomRegisterPermutation( | 5837 void TargetARM32::makeRandomRegisterPermutation( |
| 5840 llvm::SmallVectorImpl<int32_t> &Permutation, | 5838 llvm::SmallVectorImpl<RegNumT> &Permutation, |
| 5841 const llvm::SmallBitVector &ExcludeRegisters, uint64_t Salt) const { | 5839 const llvm::SmallBitVector &ExcludeRegisters, uint64_t Salt) const { |
| 5842 (void)Permutation; | 5840 (void)Permutation; |
| 5843 (void)ExcludeRegisters; | 5841 (void)ExcludeRegisters; |
| 5844 (void)Salt; | 5842 (void)Salt; |
| 5845 UnimplementedError(Func->getContext()->getFlags()); | 5843 UnimplementedError(Func->getContext()->getFlags()); |
| 5846 } | 5844 } |
| 5847 | 5845 |
| 5848 void TargetARM32::emit(const ConstantInteger32 *C) const { | 5846 void TargetARM32::emit(const ConstantInteger32 *C) const { |
| 5849 if (!BuildDefs::dump()) | 5847 if (!BuildDefs::dump()) |
| 5850 return; | 5848 return; |
| (...skipping 734 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6585 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n"; | 6583 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n"; |
| 6586 } | 6584 } |
| 6587 | 6585 |
| 6588 llvm::SmallBitVector TargetARM32::TypeToRegisterSet[RegARM32::RCARM32_NUM]; | 6586 llvm::SmallBitVector TargetARM32::TypeToRegisterSet[RegARM32::RCARM32_NUM]; |
| 6589 llvm::SmallBitVector | 6587 llvm::SmallBitVector |
| 6590 TargetARM32::TypeToRegisterSetUnfiltered[RegARM32::RCARM32_NUM]; | 6588 TargetARM32::TypeToRegisterSetUnfiltered[RegARM32::RCARM32_NUM]; |
| 6591 llvm::SmallBitVector TargetARM32::RegisterAliases[RegARM32::Reg_NUM]; | 6589 llvm::SmallBitVector TargetARM32::RegisterAliases[RegARM32::Reg_NUM]; |
| 6592 | 6590 |
| 6593 } // end of namespace ARM32 | 6591 } // end of namespace ARM32 |
| 6594 } // end of namespace Ice | 6592 } // end of namespace Ice |
| OLD | NEW |