| 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 InvalidRegisters(RegARM32::Reg_NUM); | 299 llvm::SmallBitVector InvalidRegisters(RegARM32::Reg_NUM); |
| 300 for (int i = 0; i < RegARM32::Reg_NUM; ++i) { | 300 for (int i = 0; i < RegARM32::Reg_NUM; ++i) { |
| 301 const auto &Entry = RegARM32::RegTable[i]; | 301 const auto &Entry = RegARM32::RegTable[i]; |
| 302 IntegerRegisters[i] = Entry.IsInt; | 302 IntegerRegisters[i] = Entry.IsInt; |
| 303 I64PairRegisters[i] = Entry.IsI64Pair; | 303 I64PairRegisters[i] = Entry.IsI64Pair; |
| 304 Float32Registers[i] = Entry.IsFP32; | 304 Float32Registers[i] = Entry.IsFP32; |
| 305 Float64Registers[i] = Entry.IsFP64; | 305 Float64Registers[i] = Entry.IsFP64; |
| 306 VectorRegisters[i] = Entry.IsVec128; | 306 VectorRegisters[i] = Entry.IsVec128; |
| 307 RegisterAliases[i].resize(RegARM32::Reg_NUM); | 307 RegisterAliases[i].resize(RegARM32::Reg_NUM); |
| 308 for (int j = 0; j < Entry.NumAliases; ++j) { | 308 for (int j = 0; j < Entry.NumAliases; ++j) { |
| 309 assert(i == j || !RegisterAliases[i][Entry.Aliases[j]]); | 309 assert(i == j || !RegisterAliases[i][Entry.Aliases[j]]); |
| 310 RegisterAliases[i].set(Entry.Aliases[j]); | 310 RegisterAliases[i].set(Entry.Aliases[j]); |
| 311 } | 311 } |
| 312 assert(RegisterAliases[i][i]); | 312 assert(RegisterAliases[i][i]); |
| 313 if (Entry.CCArg <= 0) { | 313 if (Entry.CCArg <= 0) { |
| 314 continue; | 314 continue; |
| 315 } | 315 } |
| 316 auto RegNum = RegNumT::fromInt(i); |
| 316 if (Entry.IsGPR) { | 317 if (Entry.IsGPR) { |
| 317 GPRArgInitializer[Entry.CCArg - 1] = i; | 318 GPRArgInitializer[Entry.CCArg - 1] = RegNum; |
| 318 } else if (Entry.IsI64Pair) { | 319 } else if (Entry.IsI64Pair) { |
| 319 I64ArgInitializer[Entry.CCArg - 1] = i; | 320 I64ArgInitializer[Entry.CCArg - 1] = RegNum; |
| 320 } else if (Entry.IsFP32) { | 321 } else if (Entry.IsFP32) { |
| 321 FP32ArgInitializer[Entry.CCArg - 1] = i; | 322 FP32ArgInitializer[Entry.CCArg - 1] = RegNum; |
| 322 } else if (Entry.IsFP64) { | 323 } else if (Entry.IsFP64) { |
| 323 FP64ArgInitializer[Entry.CCArg - 1] = i; | 324 FP64ArgInitializer[Entry.CCArg - 1] = RegNum; |
| 324 } else if (Entry.IsVec128) { | 325 } else if (Entry.IsVec128) { |
| 325 Vec128ArgInitializer[Entry.CCArg - 1] = i; | 326 Vec128ArgInitializer[Entry.CCArg - 1] = RegNum; |
| 326 } | 327 } |
| 327 } | 328 } |
| 328 TypeToRegisterSet[IceType_void] = InvalidRegisters; | 329 TypeToRegisterSet[IceType_void] = InvalidRegisters; |
| 329 TypeToRegisterSet[IceType_i1] = IntegerRegisters; | 330 TypeToRegisterSet[IceType_i1] = IntegerRegisters; |
| 330 TypeToRegisterSet[IceType_i8] = IntegerRegisters; | 331 TypeToRegisterSet[IceType_i8] = IntegerRegisters; |
| 331 TypeToRegisterSet[IceType_i16] = IntegerRegisters; | 332 TypeToRegisterSet[IceType_i16] = IntegerRegisters; |
| 332 TypeToRegisterSet[IceType_i32] = IntegerRegisters; | 333 TypeToRegisterSet[IceType_i32] = IntegerRegisters; |
| 333 TypeToRegisterSet[IceType_i64] = I64PairRegisters; | 334 TypeToRegisterSet[IceType_i64] = I64PairRegisters; |
| 334 TypeToRegisterSet[IceType_f32] = Float32Registers; | 335 TypeToRegisterSet[IceType_f32] = Float32Registers; |
| 335 TypeToRegisterSet[IceType_f64] = Float64Registers; | 336 TypeToRegisterSet[IceType_f64] = Float64Registers; |
| 336 TypeToRegisterSet[IceType_v4i1] = VectorRegisters; | 337 TypeToRegisterSet[IceType_v4i1] = VectorRegisters; |
| 337 TypeToRegisterSet[IceType_v8i1] = VectorRegisters; | 338 TypeToRegisterSet[IceType_v8i1] = VectorRegisters; |
| 338 TypeToRegisterSet[IceType_v16i1] = VectorRegisters; | 339 TypeToRegisterSet[IceType_v16i1] = VectorRegisters; |
| 339 TypeToRegisterSet[IceType_v16i8] = VectorRegisters; | 340 TypeToRegisterSet[IceType_v16i8] = VectorRegisters; |
| 340 TypeToRegisterSet[IceType_v8i16] = VectorRegisters; | 341 TypeToRegisterSet[IceType_v8i16] = VectorRegisters; |
| 341 TypeToRegisterSet[IceType_v4i32] = VectorRegisters; | 342 TypeToRegisterSet[IceType_v4i32] = VectorRegisters; |
| 342 TypeToRegisterSet[IceType_v4f32] = VectorRegisters; | 343 TypeToRegisterSet[IceType_v4f32] = VectorRegisters; |
| 343 | 344 |
| 344 for (size_t i = 0; i < llvm::array_lengthof(TypeToRegisterSet); ++i) | 345 for (size_t i = 0; i < llvm::array_lengthof(TypeToRegisterSet); ++i) |
| 345 TypeToRegisterSetUnfiltered[i] = TypeToRegisterSet[i]; | 346 TypeToRegisterSetUnfiltered[i] = TypeToRegisterSet[i]; |
| 346 | 347 |
| 347 filterTypeToRegisterSet( | 348 filterTypeToRegisterSet( |
| 348 Ctx, RegARM32::Reg_NUM, TypeToRegisterSet, | 349 Ctx, RegARM32::Reg_NUM, TypeToRegisterSet, |
| 349 llvm::array_lengthof(TypeToRegisterSet), [](int32_t RegNum) -> IceString { | 350 llvm::array_lengthof(TypeToRegisterSet), [](RegNumT RegNum) -> IceString { |
| 350 // This function simply removes ", " from the register name. | 351 // This function simply removes ", " from the register name. |
| 351 IceString Name = RegARM32::getRegName(RegNum); | 352 IceString Name = RegARM32::getRegName(RegNum); |
| 352 constexpr const char RegSeparator[] = ", "; | 353 constexpr const char RegSeparator[] = ", "; |
| 353 constexpr size_t RegSeparatorWidth = | 354 constexpr size_t RegSeparatorWidth = |
| 354 llvm::array_lengthof(RegSeparator) - 1; | 355 llvm::array_lengthof(RegSeparator) - 1; |
| 355 for (size_t Pos = Name.find(RegSeparator); Pos != std::string::npos; | 356 for (size_t Pos = Name.find(RegSeparator); Pos != std::string::npos; |
| 356 Pos = Name.find(RegSeparator)) { | 357 Pos = Name.find(RegSeparator)) { |
| 357 Name.replace(Pos, RegSeparatorWidth, ""); | 358 Name.replace(Pos, RegSeparatorWidth, ""); |
| 358 } | 359 } |
| 359 return Name; | 360 return Name; |
| 360 }, getRegClassName); | 361 }, getRegClassName); |
| 361 } | 362 } |
| 362 | 363 |
| 363 namespace { | 364 namespace { |
| 364 void copyRegAllocFromInfWeightVariable64On32(const VarList &Vars) { | 365 void copyRegAllocFromInfWeightVariable64On32(const VarList &Vars) { |
| 365 for (Variable *Var : Vars) { | 366 for (Variable *Var : Vars) { |
| 366 auto *Var64 = llvm::dyn_cast<Variable64On32>(Var); | 367 auto *Var64 = llvm::dyn_cast<Variable64On32>(Var); |
| 367 if (!Var64) { | 368 if (!Var64) { |
| 368 // This is not the variable we are looking for. | 369 // This is not the variable we are looking for. |
| 369 continue; | 370 continue; |
| 370 } | 371 } |
| 371 assert(Var64->hasReg() || !Var64->mustHaveReg()); | 372 assert(Var64->hasReg() || !Var64->mustHaveReg()); |
| 372 if (!Var64->hasReg()) { | 373 if (!Var64->hasReg()) { |
| 373 continue; | 374 continue; |
| 374 } | 375 } |
| 375 SizeT FirstReg = RegARM32::getI64PairFirstGPRNum(Var->getRegNum()); | 376 auto FirstReg = |
| 377 RegNumT::fixme(RegARM32::getI64PairFirstGPRNum(Var->getRegNum())); |
| 376 // This assumes little endian. | 378 // This assumes little endian. |
| 377 Variable *Lo = Var64->getLo(); | 379 Variable *Lo = Var64->getLo(); |
| 378 Variable *Hi = Var64->getHi(); | 380 Variable *Hi = Var64->getHi(); |
| 379 assert(Lo->hasReg() == Hi->hasReg()); | 381 assert(Lo->hasReg() == Hi->hasReg()); |
| 380 if (Lo->hasReg()) { | 382 if (Lo->hasReg()) { |
| 381 continue; | 383 continue; |
| 382 } | 384 } |
| 383 Lo->setRegNum(FirstReg); | 385 Lo->setRegNum(FirstReg); |
| 384 Lo->setMustHaveReg(); | 386 Lo->setMustHaveReg(); |
| 385 Hi->setRegNum(FirstReg + 1); | 387 Hi->setRegNum(RegNumT::fixme(FirstReg + 1)); |
| 386 Hi->setMustHaveReg(); | 388 Hi->setMustHaveReg(); |
| 387 } | 389 } |
| 388 } | 390 } |
| 389 } // end of anonymous namespace | 391 } // end of anonymous namespace |
| 390 | 392 |
| 391 uint32_t TargetARM32::getCallStackArgumentsSizeBytes(const InstCall *Call) { | 393 uint32_t TargetARM32::getCallStackArgumentsSizeBytes(const InstCall *Call) { |
| 392 TargetARM32::CallingConv CC; | 394 TargetARM32::CallingConv CC; |
| 393 int32_t DummyReg; | 395 RegNumT DummyReg; |
| 394 size_t OutArgsSizeBytes = 0; | 396 size_t OutArgsSizeBytes = 0; |
| 395 for (SizeT i = 0, NumArgs = Call->getNumArgs(); i < NumArgs; ++i) { | 397 for (SizeT i = 0, NumArgs = Call->getNumArgs(); i < NumArgs; ++i) { |
| 396 Operand *Arg = legalizeUndef(Call->getArg(i)); | 398 Operand *Arg = legalizeUndef(Call->getArg(i)); |
| 397 const Type Ty = Arg->getType(); | 399 const Type Ty = Arg->getType(); |
| 398 if (isScalarIntegerType(Ty)) { | 400 if (isScalarIntegerType(Ty)) { |
| 399 if (CC.argInGPR(Ty, &DummyReg)) { | 401 if (CC.argInGPR(Ty, &DummyReg)) { |
| 400 continue; | 402 continue; |
| 401 } | 403 } |
| 402 } else { | 404 } else { |
| 403 if (CC.argInVFP(Ty, &DummyReg)) { | 405 if (CC.argInVFP(Ty, &DummyReg)) { |
| (...skipping 491 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 895 return ARM32_STACK_ALIGNMENT_BYTES; | 897 return ARM32_STACK_ALIGNMENT_BYTES; |
| 896 } | 898 } |
| 897 | 899 |
| 898 bool TargetARM32::doBranchOpt(Inst *I, const CfgNode *NextNode) { | 900 bool TargetARM32::doBranchOpt(Inst *I, const CfgNode *NextNode) { |
| 899 if (auto *Br = llvm::dyn_cast<InstARM32Br>(I)) { | 901 if (auto *Br = llvm::dyn_cast<InstARM32Br>(I)) { |
| 900 return Br->optimizeBranch(NextNode); | 902 return Br->optimizeBranch(NextNode); |
| 901 } | 903 } |
| 902 return false; | 904 return false; |
| 903 } | 905 } |
| 904 | 906 |
| 905 IceString TargetARM32::getRegName(SizeT RegNum, Type Ty) const { | 907 IceString TargetARM32::getRegName(RegNumT RegNum, Type Ty) const { |
| 906 assert(RegNum < RegARM32::Reg_NUM); | |
| 907 (void)Ty; | 908 (void)Ty; |
| 908 return RegARM32::getRegName(RegNum); | 909 return RegARM32::getRegName(RegNum); |
| 909 } | 910 } |
| 910 | 911 |
| 911 Variable *TargetARM32::getPhysicalRegister(SizeT RegNum, Type Ty) { | 912 Variable *TargetARM32::getPhysicalRegister(RegNumT RegNum, Type Ty) { |
| 912 static const Type DefaultType[] = { | 913 static const Type DefaultType[] = { |
| 913 #define X(val, encode, name, cc_arg, scratch, preserved, stackptr, frameptr, \ | 914 #define X(val, encode, name, cc_arg, scratch, preserved, stackptr, frameptr, \ |
| 914 isGPR, isInt, isI64Pair, isFP32, isFP64, isVec128, alias_init) \ | 915 isGPR, isInt, isI64Pair, isFP32, isFP64, isVec128, alias_init) \ |
| 915 (isFP32) \ | 916 (isFP32) \ |
| 916 ? IceType_f32 \ | 917 ? IceType_f32 \ |
| 917 : ((isFP64) ? IceType_f64 : ((isVec128 ? IceType_v4i32 : IceType_i32))), | 918 : ((isFP64) ? IceType_f64 : ((isVec128 ? IceType_v4i32 : IceType_i32))), |
| 918 REGARM32_TABLE | 919 REGARM32_TABLE |
| 919 #undef X | 920 #undef X |
| 920 }; | 921 }; |
| 921 | 922 |
| 922 assert(RegNum < RegARM32::Reg_NUM); | |
| 923 if (Ty == IceType_void) { | 923 if (Ty == IceType_void) { |
| 924 assert(RegNum < llvm::array_lengthof(DefaultType)); | 924 assert(unsigned(RegNum) < llvm::array_lengthof(DefaultType)); |
| 925 Ty = DefaultType[RegNum]; | 925 Ty = DefaultType[RegNum]; |
| 926 } | 926 } |
| 927 if (PhysicalRegisters[Ty].empty()) | 927 if (PhysicalRegisters[Ty].empty()) |
| 928 PhysicalRegisters[Ty].resize(RegARM32::Reg_NUM); | 928 PhysicalRegisters[Ty].resize(RegARM32::Reg_NUM); |
| 929 assert(RegNum < PhysicalRegisters[Ty].size()); | 929 assert(unsigned(RegNum) < PhysicalRegisters[Ty].size()); |
| 930 Variable *Reg = PhysicalRegisters[Ty][RegNum]; | 930 Variable *Reg = PhysicalRegisters[Ty][RegNum]; |
| 931 if (Reg == nullptr) { | 931 if (Reg == nullptr) { |
| 932 Reg = Func->makeVariable(Ty); | 932 Reg = Func->makeVariable(Ty); |
| 933 Reg->setRegNum(RegNum); | 933 Reg->setRegNum(RegNum); |
| 934 PhysicalRegisters[Ty][RegNum] = Reg; | 934 PhysicalRegisters[Ty][RegNum] = Reg; |
| 935 // Specially mark a named physical register as an "argument" so that it is | 935 // Specially mark a named physical register as an "argument" so that it is |
| 936 // considered live upon function entry. Otherwise it's possible to get | 936 // considered live upon function entry. Otherwise it's possible to get |
| 937 // liveness validation errors for saving callee-save registers. | 937 // liveness validation errors for saving callee-save registers. |
| 938 Func->addImplicitArg(Reg); | 938 Func->addImplicitArg(Reg); |
| 939 // Don't bother tracking the live range of a named physical register. | 939 // Don't bother tracking the live range of a named physical register. |
| (...skipping 16 matching lines...) Expand all Loading... |
| 956 Str << getRegName(Var->getRegNum(), Var->getType()); | 956 Str << getRegName(Var->getRegNum(), Var->getType()); |
| 957 return; | 957 return; |
| 958 } | 958 } |
| 959 if (Var->mustHaveReg()) { | 959 if (Var->mustHaveReg()) { |
| 960 llvm::report_fatal_error("Infinite-weight Variable (" + Var->getName(Func) + | 960 llvm::report_fatal_error("Infinite-weight Variable (" + Var->getName(Func) + |
| 961 ") has no register assigned - function " + | 961 ") has no register assigned - function " + |
| 962 Func->getFunctionName()); | 962 Func->getFunctionName()); |
| 963 } | 963 } |
| 964 assert(!Var->isRematerializable()); | 964 assert(!Var->isRematerializable()); |
| 965 int32_t Offset = Var->getStackOffset(); | 965 int32_t Offset = Var->getStackOffset(); |
| 966 int32_t BaseRegNum = Var->getBaseRegNum(); | 966 auto BaseRegNum = Var->getBaseRegNum(); |
| 967 if (BaseRegNum == Variable::NoRegister) { | 967 if (BaseRegNum == RegNumT::NoRegister) { |
| 968 BaseRegNum = getFrameOrStackReg(); | 968 BaseRegNum = getFrameOrStackReg(); |
| 969 } | 969 } |
| 970 const Type VarTy = Var->getType(); | 970 const Type VarTy = Var->getType(); |
| 971 Str << "[" << getRegName(BaseRegNum, VarTy); | 971 Str << "[" << getRegName(BaseRegNum, VarTy); |
| 972 if (Offset != 0) { | 972 if (Offset != 0) { |
| 973 Str << ", #" << Offset; | 973 Str << ", #" << Offset; |
| 974 } | 974 } |
| 975 Str << "]"; | 975 Str << "]"; |
| 976 } | 976 } |
| 977 | 977 |
| 978 TargetARM32::CallingConv::CallingConv() | 978 TargetARM32::CallingConv::CallingConv() |
| 979 : GPRegsUsed(RegARM32::Reg_NUM), | 979 : GPRegsUsed(RegARM32::Reg_NUM), |
| 980 GPRArgs(GPRArgInitializer.rbegin(), GPRArgInitializer.rend()), | 980 GPRArgs(GPRArgInitializer.rbegin(), GPRArgInitializer.rend()), |
| 981 I64Args(I64ArgInitializer.rbegin(), I64ArgInitializer.rend()), | 981 I64Args(I64ArgInitializer.rbegin(), I64ArgInitializer.rend()), |
| 982 VFPRegsUsed(RegARM32::Reg_NUM), | 982 VFPRegsUsed(RegARM32::Reg_NUM), |
| 983 FP32Args(FP32ArgInitializer.rbegin(), FP32ArgInitializer.rend()), | 983 FP32Args(FP32ArgInitializer.rbegin(), FP32ArgInitializer.rend()), |
| 984 FP64Args(FP64ArgInitializer.rbegin(), FP64ArgInitializer.rend()), | 984 FP64Args(FP64ArgInitializer.rbegin(), FP64ArgInitializer.rend()), |
| 985 Vec128Args(Vec128ArgInitializer.rbegin(), Vec128ArgInitializer.rend()) {} | 985 Vec128Args(Vec128ArgInitializer.rbegin(), Vec128ArgInitializer.rend()) {} |
| 986 | 986 |
| 987 bool TargetARM32::CallingConv::argInGPR(Type Ty, int32_t *Reg) { | 987 bool TargetARM32::CallingConv::argInGPR(Type Ty, RegNumT *Reg) { |
| 988 CfgVector<SizeT> *Source; | 988 CfgVector<RegNumT> *Source; |
| 989 | 989 |
| 990 switch (Ty) { | 990 switch (Ty) { |
| 991 default: { | 991 default: { |
| 992 assert(isScalarIntegerType(Ty)); | 992 assert(isScalarIntegerType(Ty)); |
| 993 Source = &GPRArgs; | 993 Source = &GPRArgs; |
| 994 } break; | 994 } break; |
| 995 case IceType_i64: { | 995 case IceType_i64: { |
| 996 Source = &I64Args; | 996 Source = &I64Args; |
| 997 } break; | 997 } break; |
| 998 } | 998 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1012 GPRegsUsed |= RegisterAliases[*Reg]; | 1012 GPRegsUsed |= RegisterAliases[*Reg]; |
| 1013 return true; | 1013 return true; |
| 1014 } | 1014 } |
| 1015 | 1015 |
| 1016 // GPR are not packed when passing parameters. Thus, a function foo(i32, i64, | 1016 // GPR are not packed when passing parameters. Thus, a function foo(i32, i64, |
| 1017 // i32) will have the first argument in r0, the second in r1-r2, and the third | 1017 // i32) will have the first argument in r0, the second in r1-r2, and the third |
| 1018 // on the stack. To model this behavior, whenever we pop a register from Regs, | 1018 // on the stack. To model this behavior, whenever we pop a register from Regs, |
| 1019 // we remove all of its aliases from the pool of available GPRs. This has the | 1019 // we remove all of its aliases from the pool of available GPRs. This has the |
| 1020 // effect of computing the "closure" on the GPR registers. | 1020 // effect of computing the "closure" on the GPR registers. |
| 1021 void TargetARM32::CallingConv::discardUnavailableGPRsAndTheirAliases( | 1021 void TargetARM32::CallingConv::discardUnavailableGPRsAndTheirAliases( |
| 1022 CfgVector<SizeT> *Regs) { | 1022 CfgVector<RegNumT> *Regs) { |
| 1023 while (!Regs->empty() && GPRegsUsed[Regs->back()]) { | 1023 while (!Regs->empty() && GPRegsUsed[Regs->back()]) { |
| 1024 GPRegsUsed |= RegisterAliases[Regs->back()]; | 1024 GPRegsUsed |= RegisterAliases[Regs->back()]; |
| 1025 Regs->pop_back(); | 1025 Regs->pop_back(); |
| 1026 } | 1026 } |
| 1027 } | 1027 } |
| 1028 | 1028 |
| 1029 bool TargetARM32::CallingConv::argInVFP(Type Ty, int32_t *Reg) { | 1029 bool TargetARM32::CallingConv::argInVFP(Type Ty, RegNumT *Reg) { |
| 1030 CfgVector<SizeT> *Source; | 1030 CfgVector<RegNumT> *Source; |
| 1031 | 1031 |
| 1032 switch (Ty) { | 1032 switch (Ty) { |
| 1033 default: { | 1033 default: { |
| 1034 assert(isVectorType(Ty)); | 1034 assert(isVectorType(Ty)); |
| 1035 Source = &Vec128Args; | 1035 Source = &Vec128Args; |
| 1036 } break; | 1036 } break; |
| 1037 case IceType_f32: { | 1037 case IceType_f32: { |
| 1038 Source = &FP32Args; | 1038 Source = &FP32Args; |
| 1039 } break; | 1039 } break; |
| 1040 case IceType_f64: { | 1040 case IceType_f64: { |
| 1041 Source = &FP64Args; | 1041 Source = &FP64Args; |
| 1042 } break; | 1042 } break; |
| 1043 } | 1043 } |
| 1044 | 1044 |
| 1045 discardUnavailableVFPRegs(Source); | 1045 discardUnavailableVFPRegs(Source); |
| 1046 | 1046 |
| 1047 if (Source->empty()) { | 1047 if (Source->empty()) { |
| 1048 VFPRegsUsed.set(); | 1048 VFPRegsUsed.set(); |
| 1049 return false; | 1049 return false; |
| 1050 } | 1050 } |
| 1051 | 1051 |
| 1052 *Reg = Source->back(); | 1052 *Reg = Source->back(); |
| 1053 VFPRegsUsed |= RegisterAliases[*Reg]; | 1053 VFPRegsUsed |= RegisterAliases[*Reg]; |
| 1054 return true; | 1054 return true; |
| 1055 } | 1055 } |
| 1056 | 1056 |
| 1057 // Arguments in VFP registers are not packed, so we don't mark the popped | 1057 // Arguments in VFP registers are not packed, so we don't mark the popped |
| 1058 // registers' aliases as unavailable. | 1058 // registers' aliases as unavailable. |
| 1059 void TargetARM32::CallingConv::discardUnavailableVFPRegs( | 1059 void TargetARM32::CallingConv::discardUnavailableVFPRegs( |
| 1060 CfgVector<SizeT> *Regs) { | 1060 CfgVector<RegNumT> *Regs) { |
| 1061 while (!Regs->empty() && VFPRegsUsed[Regs->back()]) { | 1061 while (!Regs->empty() && VFPRegsUsed[Regs->back()]) { |
| 1062 Regs->pop_back(); | 1062 Regs->pop_back(); |
| 1063 } | 1063 } |
| 1064 } | 1064 } |
| 1065 | 1065 |
| 1066 void TargetARM32::lowerArguments() { | 1066 void TargetARM32::lowerArguments() { |
| 1067 VarList &Args = Func->getArgs(); | 1067 VarList &Args = Func->getArgs(); |
| 1068 TargetARM32::CallingConv CC; | 1068 TargetARM32::CallingConv CC; |
| 1069 | 1069 |
| 1070 // For each register argument, replace Arg in the argument list with the home | 1070 // For each register argument, replace Arg in the argument list with the home |
| 1071 // register. Then generate an instruction in the prolog to copy the home | 1071 // register. Then generate an instruction in the prolog to copy the home |
| 1072 // register to the assigned location of Arg. | 1072 // register to the assigned location of Arg. |
| 1073 Context.init(Func->getEntryNode()); | 1073 Context.init(Func->getEntryNode()); |
| 1074 Context.setInsertPoint(Context.getCur()); | 1074 Context.setInsertPoint(Context.getCur()); |
| 1075 | 1075 |
| 1076 for (SizeT I = 0, E = Args.size(); I < E; ++I) { | 1076 for (SizeT I = 0, E = Args.size(); I < E; ++I) { |
| 1077 Variable *Arg = Args[I]; | 1077 Variable *Arg = Args[I]; |
| 1078 Type Ty = Arg->getType(); | 1078 Type Ty = Arg->getType(); |
| 1079 int RegNum; | 1079 RegNumT RegNum; |
| 1080 if (isScalarIntegerType(Ty)) { | 1080 if (isScalarIntegerType(Ty)) { |
| 1081 if (!CC.argInGPR(Ty, &RegNum)) { | 1081 if (!CC.argInGPR(Ty, &RegNum)) { |
| 1082 continue; | 1082 continue; |
| 1083 } | 1083 } |
| 1084 } else { | 1084 } else { |
| 1085 if (!CC.argInVFP(Ty, &RegNum)) { | 1085 if (!CC.argInVFP(Ty, &RegNum)) { |
| 1086 continue; | 1086 continue; |
| 1087 } | 1087 } |
| 1088 } | 1088 } |
| 1089 | 1089 |
| 1090 Variable *RegisterArg = Func->makeVariable(Ty); | 1090 Variable *RegisterArg = Func->makeVariable(Ty); |
| 1091 if (BuildDefs::dump()) { | 1091 if (BuildDefs::dump()) { |
| 1092 RegisterArg->setName(Func, "home_reg:" + Arg->getName(Func)); | 1092 RegisterArg->setName(Func, "home_reg:" + Arg->getName(Func)); |
| 1093 } | 1093 } |
| 1094 RegisterArg->setIsArg(); | 1094 RegisterArg->setIsArg(); |
| 1095 Arg->setIsArg(false); | 1095 Arg->setIsArg(false); |
| 1096 Args[I] = RegisterArg; | 1096 Args[I] = RegisterArg; |
| 1097 switch (Ty) { | 1097 switch (Ty) { |
| 1098 default: { RegisterArg->setRegNum(RegNum); } break; | 1098 default: { RegisterArg->setRegNum(RegNum); } break; |
| 1099 case IceType_i64: { | 1099 case IceType_i64: { |
| 1100 auto *RegisterArg64 = llvm::cast<Variable64On32>(RegisterArg); | 1100 auto *RegisterArg64 = llvm::cast<Variable64On32>(RegisterArg); |
| 1101 RegisterArg64->initHiLo(Func); | 1101 RegisterArg64->initHiLo(Func); |
| 1102 RegisterArg64->getLo()->setRegNum( | 1102 RegisterArg64->getLo()->setRegNum( |
| 1103 RegARM32::getI64PairFirstGPRNum(RegNum)); | 1103 RegNumT::fixme(RegARM32::getI64PairFirstGPRNum(RegNum))); |
| 1104 RegisterArg64->getHi()->setRegNum( | 1104 RegisterArg64->getHi()->setRegNum( |
| 1105 RegARM32::getI64PairSecondGPRNum(RegNum)); | 1105 RegNumT::fixme(RegARM32::getI64PairSecondGPRNum(RegNum))); |
| 1106 } break; | 1106 } break; |
| 1107 } | 1107 } |
| 1108 Context.insert<InstAssign>(Arg, RegisterArg); | 1108 Context.insert<InstAssign>(Arg, RegisterArg); |
| 1109 } | 1109 } |
| 1110 } | 1110 } |
| 1111 | 1111 |
| 1112 // Helper function for addProlog(). | 1112 // Helper function for addProlog(). |
| 1113 // | 1113 // |
| 1114 // This assumes Arg is an argument passed on the stack. This sets the frame | 1114 // This assumes Arg is an argument passed on the stack. This sets the frame |
| 1115 // offset for Arg and updates InArgsSizeBytes according to Arg's width. For an | 1115 // 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... |
| 1280 &PreservedSRegs)}; | 1280 &PreservedSRegs)}; |
| 1281 for (const auto &RegClass : RegClasses) { | 1281 for (const auto &RegClass : RegClasses) { |
| 1282 const uint32_t FirstRegInClass = std::get<0>(RegClass); | 1282 const uint32_t FirstRegInClass = std::get<0>(RegClass); |
| 1283 const uint32_t LastRegInClass = std::get<1>(RegClass); | 1283 const uint32_t LastRegInClass = std::get<1>(RegClass); |
| 1284 VarList *const PreservedRegsInClass = std::get<2>(RegClass); | 1284 VarList *const PreservedRegsInClass = std::get<2>(RegClass); |
| 1285 for (uint32_t Reg = FirstRegInClass; Reg <= LastRegInClass; ++Reg) { | 1285 for (uint32_t Reg = FirstRegInClass; Reg <= LastRegInClass; ++Reg) { |
| 1286 if (!ToPreserve[Reg]) { | 1286 if (!ToPreserve[Reg]) { |
| 1287 continue; | 1287 continue; |
| 1288 } | 1288 } |
| 1289 ++NumCallee; | 1289 ++NumCallee; |
| 1290 Variable *PhysicalRegister = getPhysicalRegister(Reg); | 1290 Variable *PhysicalRegister = getPhysicalRegister(RegNumT::fromInt(Reg)); |
| 1291 PreservedRegsSizeBytes += | 1291 PreservedRegsSizeBytes += |
| 1292 typeWidthInBytesOnStack(PhysicalRegister->getType()); | 1292 typeWidthInBytesOnStack(PhysicalRegister->getType()); |
| 1293 PreservedRegsInClass->push_back(PhysicalRegister); | 1293 PreservedRegsInClass->push_back(PhysicalRegister); |
| 1294 } | 1294 } |
| 1295 } | 1295 } |
| 1296 | 1296 |
| 1297 Ctx->statsUpdateRegistersSaved(NumCallee); | 1297 Ctx->statsUpdateRegistersSaved(NumCallee); |
| 1298 if (!PreservedSRegs.empty()) | 1298 if (!PreservedSRegs.empty()) |
| 1299 _push(PreservedSRegs); | 1299 _push(PreservedSRegs); |
| 1300 if (!PreservedGPRs.empty()) | 1300 if (!PreservedGPRs.empty()) |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1355 // Arg[0] is closest to the stack/frame pointer. | 1355 // Arg[0] is closest to the stack/frame pointer. |
| 1356 Variable *FramePtr = getPhysicalRegister(getFrameOrStackReg()); | 1356 Variable *FramePtr = getPhysicalRegister(getFrameOrStackReg()); |
| 1357 size_t BasicFrameOffset = PreservedRegsSizeBytes; | 1357 size_t BasicFrameOffset = PreservedRegsSizeBytes; |
| 1358 if (!UsesFramePointer) | 1358 if (!UsesFramePointer) |
| 1359 BasicFrameOffset += SpillAreaSizeBytes; | 1359 BasicFrameOffset += SpillAreaSizeBytes; |
| 1360 | 1360 |
| 1361 const VarList &Args = Func->getArgs(); | 1361 const VarList &Args = Func->getArgs(); |
| 1362 size_t InArgsSizeBytes = 0; | 1362 size_t InArgsSizeBytes = 0; |
| 1363 TargetARM32::CallingConv CC; | 1363 TargetARM32::CallingConv CC; |
| 1364 for (Variable *Arg : Args) { | 1364 for (Variable *Arg : Args) { |
| 1365 int32_t DummyReg; | 1365 RegNumT DummyReg; |
| 1366 const Type Ty = Arg->getType(); | 1366 const Type Ty = Arg->getType(); |
| 1367 | 1367 |
| 1368 // Skip arguments passed in registers. | 1368 // Skip arguments passed in registers. |
| 1369 if (isScalarIntegerType(Ty)) { | 1369 if (isScalarIntegerType(Ty)) { |
| 1370 if (CC.argInGPR(Ty, &DummyReg)) { | 1370 if (CC.argInGPR(Ty, &DummyReg)) { |
| 1371 continue; | 1371 continue; |
| 1372 } | 1372 } |
| 1373 } else { | 1373 } else { |
| 1374 if (CC.argInVFP(Ty, &DummyReg)) { | 1374 if (CC.argInVFP(Ty, &DummyReg)) { |
| 1375 continue; | 1375 continue; |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1474 | 1474 |
| 1475 RI->setDeleted(); | 1475 RI->setDeleted(); |
| 1476 } | 1476 } |
| 1477 | 1477 |
| 1478 bool TargetARM32::isLegalMemOffset(Type Ty, int32_t Offset) const { | 1478 bool TargetARM32::isLegalMemOffset(Type Ty, int32_t Offset) const { |
| 1479 constexpr bool ZeroExt = false; | 1479 constexpr bool ZeroExt = false; |
| 1480 return OperandARM32Mem::canHoldOffset(Ty, ZeroExt, Offset); | 1480 return OperandARM32Mem::canHoldOffset(Ty, ZeroExt, Offset); |
| 1481 } | 1481 } |
| 1482 | 1482 |
| 1483 Variable *TargetARM32::PostLoweringLegalizer::newBaseRegister( | 1483 Variable *TargetARM32::PostLoweringLegalizer::newBaseRegister( |
| 1484 Variable *Base, int32_t Offset, int32_t ScratchRegNum) { | 1484 Variable *Base, int32_t Offset, RegNumT ScratchRegNum) { |
| 1485 // Legalize will likely need a movw/movt combination, but if the top bits are | 1485 // Legalize will likely need a movw/movt combination, but if the top bits are |
| 1486 // all 0 from negating the offset and subtracting, we could use that instead. | 1486 // all 0 from negating the offset and subtracting, we could use that instead. |
| 1487 const bool ShouldSub = Offset != 0 && (-Offset & 0xFFFF0000) == 0; | 1487 const bool ShouldSub = Offset != 0 && (-Offset & 0xFFFF0000) == 0; |
| 1488 Variable *ScratchReg = Target->makeReg(IceType_i32, ScratchRegNum); | 1488 Variable *ScratchReg = Target->makeReg(IceType_i32, ScratchRegNum); |
| 1489 if (ShouldSub) { | 1489 if (ShouldSub) { |
| 1490 Operand *OffsetVal = | 1490 Operand *OffsetVal = |
| 1491 Target->legalize(Target->Ctx->getConstantInt32(-Offset), | 1491 Target->legalize(Target->Ctx->getConstantInt32(-Offset), |
| 1492 Legal_Reg | Legal_Flex, ScratchRegNum); | 1492 Legal_Reg | Legal_Flex, ScratchRegNum); |
| 1493 Target->_sub(ScratchReg, Base, OffsetVal); | 1493 Target->_sub(ScratchReg, Base, OffsetVal); |
| 1494 } else { | 1494 } else { |
| 1495 Operand *OffsetVal = | 1495 Operand *OffsetVal = |
| 1496 Target->legalize(Target->Ctx->getConstantInt32(Offset), | 1496 Target->legalize(Target->Ctx->getConstantInt32(Offset), |
| 1497 Legal_Reg | Legal_Flex, ScratchRegNum); | 1497 Legal_Reg | Legal_Flex, ScratchRegNum); |
| 1498 Target->_add(ScratchReg, Base, OffsetVal); | 1498 Target->_add(ScratchReg, Base, OffsetVal); |
| 1499 } | 1499 } |
| 1500 | 1500 |
| 1501 if (ScratchRegNum == Target->getReservedTmpReg()) { | 1501 if (ScratchRegNum == Target->getReservedTmpReg()) { |
| 1502 const bool BaseIsStackOrFramePtr = | 1502 const bool BaseIsStackOrFramePtr = |
| 1503 Base->getRegNum() == static_cast<int32_t>(Target->getFrameOrStackReg()); | 1503 Base->getRegNum() == Target->getFrameOrStackReg(); |
| 1504 // There is currently no code path that would trigger this assertion, so we | 1504 // There is currently no code path that would trigger this assertion, so we |
| 1505 // leave this assertion here in case it is ever violated. This is not a | 1505 // leave this assertion here in case it is ever violated. This is not a |
| 1506 // fatal error (thus the use of assert() and not llvm::report_fatal_error) | 1506 // fatal error (thus the use of assert() and not llvm::report_fatal_error) |
| 1507 // as the program compiled by subzero will still work correctly. | 1507 // as the program compiled by subzero will still work correctly. |
| 1508 assert(BaseIsStackOrFramePtr); | 1508 assert(BaseIsStackOrFramePtr); |
| 1509 // Side-effect: updates TempBase to reflect the new Temporary. | 1509 // Side-effect: updates TempBase to reflect the new Temporary. |
| 1510 if (BaseIsStackOrFramePtr) { | 1510 if (BaseIsStackOrFramePtr) { |
| 1511 TempBaseReg = ScratchReg; | 1511 TempBaseReg = ScratchReg; |
| 1512 TempBaseOffset = Offset; | 1512 TempBaseOffset = Offset; |
| 1513 } else { | 1513 } else { |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1600 MovInstr->getPredicate()); | 1600 MovInstr->getPredicate()); |
| 1601 // _str() does not have a Dest, so we add a fake-def(Dest). | 1601 // _str() does not have a Dest, so we add a fake-def(Dest). |
| 1602 Target->Context.insert<InstFakeDef>(Dest); | 1602 Target->Context.insert<InstFakeDef>(Dest); |
| 1603 Legalized = true; | 1603 Legalized = true; |
| 1604 } else if (auto *Var = llvm::dyn_cast<Variable>(Src)) { | 1604 } else if (auto *Var = llvm::dyn_cast<Variable>(Src)) { |
| 1605 if (Var->isRematerializable()) { | 1605 if (Var->isRematerializable()) { |
| 1606 // This is equivalent to an x86 _lea(RematOffset(%esp/%ebp), Variable). | 1606 // This is equivalent to an x86 _lea(RematOffset(%esp/%ebp), Variable). |
| 1607 | 1607 |
| 1608 // ExtraOffset is only needed for frame-pointer based frames as we have | 1608 // ExtraOffset is only needed for frame-pointer based frames as we have |
| 1609 // to account for spill storage. | 1609 // to account for spill storage. |
| 1610 const int32_t ExtraOffset = | 1610 const int32_t ExtraOffset = (Var->getRegNum() == Target->getFrameReg()) |
| 1611 (static_cast<SizeT>(Var->getRegNum()) == Target->getFrameReg()) | 1611 ? Target->getFrameFixedAllocaOffset() |
| 1612 ? Target->getFrameFixedAllocaOffset() | 1612 : 0; |
| 1613 : 0; | |
| 1614 | 1613 |
| 1615 const int32_t Offset = Var->getStackOffset() + ExtraOffset; | 1614 const int32_t Offset = Var->getStackOffset() + ExtraOffset; |
| 1616 Variable *Base = Target->getPhysicalRegister(Var->getRegNum()); | 1615 Variable *Base = Target->getPhysicalRegister(Var->getRegNum()); |
| 1617 Variable *T = newBaseRegister(Base, Offset, Dest->getRegNum()); | 1616 Variable *T = newBaseRegister(Base, Offset, Dest->getRegNum()); |
| 1618 Target->_mov(Dest, T); | 1617 Target->_mov(Dest, T); |
| 1619 Legalized = true; | 1618 Legalized = true; |
| 1620 } else { | 1619 } else { |
| 1621 if (!Var->hasReg()) { | 1620 if (!Var->hasReg()) { |
| 1622 // This is a _mov(Variable, Mem()), i.e., a load. | 1621 // This is a _mov(Variable, Mem()), i.e., a load. |
| 1623 const int32_t Offset = Var->getStackOffset(); | 1622 const int32_t Offset = Var->getStackOffset(); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1671 bool AllowOffsets) { | 1670 bool AllowOffsets) { |
| 1672 assert(!Mem->isRegReg() || !Mem->getIndex()->isRematerializable()); | 1671 assert(!Mem->isRegReg() || !Mem->getIndex()->isRematerializable()); |
| 1673 assert( | 1672 assert( |
| 1674 Mem->isRegReg() || | 1673 Mem->isRegReg() || |
| 1675 Target->isLegalMemOffset(Mem->getType(), Mem->getOffset()->getValue())); | 1674 Target->isLegalMemOffset(Mem->getType(), Mem->getOffset()->getValue())); |
| 1676 | 1675 |
| 1677 bool Legalized = false; | 1676 bool Legalized = false; |
| 1678 Variable *Base = Mem->getBase(); | 1677 Variable *Base = Mem->getBase(); |
| 1679 int32_t Offset = Mem->isRegReg() ? 0 : Mem->getOffset()->getValue(); | 1678 int32_t Offset = Mem->isRegReg() ? 0 : Mem->getOffset()->getValue(); |
| 1680 if (Base->isRematerializable()) { | 1679 if (Base->isRematerializable()) { |
| 1681 const int32_t ExtraOffset = | 1680 const int32_t ExtraOffset = (Base->getRegNum() == Target->getFrameReg()) |
| 1682 (static_cast<SizeT>(Base->getRegNum()) == Target->getFrameReg()) | 1681 ? Target->getFrameFixedAllocaOffset() |
| 1683 ? Target->getFrameFixedAllocaOffset() | 1682 : 0; |
| 1684 : 0; | |
| 1685 Offset += Base->getStackOffset() + ExtraOffset; | 1683 Offset += Base->getStackOffset() + ExtraOffset; |
| 1686 Base = Target->getPhysicalRegister(Base->getRegNum()); | 1684 Base = Target->getPhysicalRegister(Base->getRegNum()); |
| 1687 assert(!Base->isRematerializable()); | 1685 assert(!Base->isRematerializable()); |
| 1688 Legalized = true; | 1686 Legalized = true; |
| 1689 } | 1687 } |
| 1690 | 1688 |
| 1691 if (!Legalized && !Target->NeedSandboxing) { | 1689 if (!Legalized && !Target->NeedSandboxing) { |
| 1692 return nullptr; | 1690 return nullptr; |
| 1693 } | 1691 } |
| 1694 | 1692 |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1894 } | 1892 } |
| 1895 } | 1893 } |
| 1896 llvm::report_fatal_error("Unsupported operand type"); | 1894 llvm::report_fatal_error("Unsupported operand type"); |
| 1897 return nullptr; | 1895 return nullptr; |
| 1898 } | 1896 } |
| 1899 | 1897 |
| 1900 llvm::SmallBitVector TargetARM32::getRegisterSet(RegSetMask Include, | 1898 llvm::SmallBitVector TargetARM32::getRegisterSet(RegSetMask Include, |
| 1901 RegSetMask Exclude) const { | 1899 RegSetMask Exclude) const { |
| 1902 llvm::SmallBitVector Registers(RegARM32::Reg_NUM); | 1900 llvm::SmallBitVector Registers(RegARM32::Reg_NUM); |
| 1903 | 1901 |
| 1904 for (int32_t i = 0; i < RegARM32::Reg_NUM; ++i) { | 1902 for (uint32_t i = 0; i < RegARM32::Reg_NUM; ++i) { |
| 1905 const auto &Entry = RegARM32::RegTable[i]; | 1903 const auto &Entry = RegARM32::RegTable[i]; |
| 1906 if (Entry.Scratch && (Include & RegSet_CallerSave)) | 1904 if (Entry.Scratch && (Include & RegSet_CallerSave)) |
| 1907 Registers[i] = true; | 1905 Registers[i] = true; |
| 1908 if (Entry.Preserved && (Include & RegSet_CalleeSave)) | 1906 if (Entry.Preserved && (Include & RegSet_CalleeSave)) |
| 1909 Registers[i] = true; | 1907 Registers[i] = true; |
| 1910 if (Entry.StackPtr && (Include & RegSet_StackPointer)) | 1908 if (Entry.StackPtr && (Include & RegSet_StackPointer)) |
| 1911 Registers[i] = true; | 1909 Registers[i] = true; |
| 1912 if (Entry.FramePtr && (Include & RegSet_FramePointer)) | 1910 if (Entry.FramePtr && (Include & RegSet_FramePointer)) |
| 1913 Registers[i] = true; | 1911 Registers[i] = true; |
| 1914 if (Entry.Scratch && (Exclude & RegSet_CallerSave)) | 1912 if (Entry.Scratch && (Exclude & RegSet_CallerSave)) |
| (...skipping 1439 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3354 if (TargetHelperPreamble != ARM32HelpersPreamble.end()) { | 3352 if (TargetHelperPreamble != ARM32HelpersPreamble.end()) { |
| 3355 (this->*TargetHelperPreamble->second)(Instr); | 3353 (this->*TargetHelperPreamble->second)(Instr); |
| 3356 } | 3354 } |
| 3357 } | 3355 } |
| 3358 MaybeLeafFunc = false; | 3356 MaybeLeafFunc = false; |
| 3359 NeedsStackAlignment = true; | 3357 NeedsStackAlignment = true; |
| 3360 | 3358 |
| 3361 // Assign arguments to registers and stack. Also reserve stack. | 3359 // Assign arguments to registers and stack. Also reserve stack. |
| 3362 TargetARM32::CallingConv CC; | 3360 TargetARM32::CallingConv CC; |
| 3363 // Pair of Arg Operand -> GPR number assignments. | 3361 // Pair of Arg Operand -> GPR number assignments. |
| 3364 llvm::SmallVector<std::pair<Operand *, int32_t>, NumGPRArgs> GPRArgs; | 3362 llvm::SmallVector<std::pair<Operand *, RegNumT>, NumGPRArgs> GPRArgs; |
| 3365 llvm::SmallVector<std::pair<Operand *, int32_t>, NumFP32Args> FPArgs; | 3363 llvm::SmallVector<std::pair<Operand *, RegNumT>, NumFP32Args> FPArgs; |
| 3366 // Pair of Arg Operand -> stack offset. | 3364 // Pair of Arg Operand -> stack offset. |
| 3367 llvm::SmallVector<std::pair<Operand *, int32_t>, 8> StackArgs; | 3365 llvm::SmallVector<std::pair<Operand *, int32_t>, 8> StackArgs; |
| 3368 size_t ParameterAreaSizeBytes = 0; | 3366 size_t ParameterAreaSizeBytes = 0; |
| 3369 | 3367 |
| 3370 // Classify each argument operand according to the location where the | 3368 // Classify each argument operand according to the location where the |
| 3371 // argument is passed. | 3369 // argument is passed. |
| 3372 for (SizeT i = 0, NumArgs = Instr->getNumArgs(); i < NumArgs; ++i) { | 3370 for (SizeT i = 0, NumArgs = Instr->getNumArgs(); i < NumArgs; ++i) { |
| 3373 Operand *Arg = legalizeUndef(Instr->getArg(i)); | 3371 Operand *Arg = legalizeUndef(Instr->getArg(i)); |
| 3374 const Type Ty = Arg->getType(); | 3372 const Type Ty = Arg->getType(); |
| 3375 bool InReg = false; | 3373 bool InReg = false; |
| 3376 int32_t Reg; | 3374 RegNumT Reg; |
| 3377 if (isScalarIntegerType(Ty)) { | 3375 if (isScalarIntegerType(Ty)) { |
| 3378 InReg = CC.argInGPR(Ty, &Reg); | 3376 InReg = CC.argInGPR(Ty, &Reg); |
| 3379 } else { | 3377 } else { |
| 3380 InReg = CC.argInVFP(Ty, &Reg); | 3378 InReg = CC.argInVFP(Ty, &Reg); |
| 3381 } | 3379 } |
| 3382 | 3380 |
| 3383 if (!InReg) { | 3381 if (!InReg) { |
| 3384 ParameterAreaSizeBytes = | 3382 ParameterAreaSizeBytes = |
| 3385 applyStackAlignmentTy(ParameterAreaSizeBytes, Ty); | 3383 applyStackAlignmentTy(ParameterAreaSizeBytes, Ty); |
| 3386 StackArgs.push_back(std::make_pair(Arg, ParameterAreaSizeBytes)); | 3384 StackArgs.push_back(std::make_pair(Arg, ParameterAreaSizeBytes)); |
| 3387 ParameterAreaSizeBytes += typeWidthInBytesOnStack(Ty); | 3385 ParameterAreaSizeBytes += typeWidthInBytesOnStack(Ty); |
| 3388 continue; | 3386 continue; |
| 3389 } | 3387 } |
| 3390 | 3388 |
| 3391 if (Ty == IceType_i64) { | 3389 if (Ty == IceType_i64) { |
| 3392 Operand *Lo = loOperand(Arg); | 3390 Operand *Lo = loOperand(Arg); |
| 3393 Operand *Hi = hiOperand(Arg); | 3391 Operand *Hi = hiOperand(Arg); |
| 3394 GPRArgs.push_back( | 3392 GPRArgs.push_back(std::make_pair( |
| 3395 std::make_pair(Lo, RegARM32::getI64PairFirstGPRNum(Reg))); | 3393 Lo, RegNumT::fixme(RegARM32::getI64PairFirstGPRNum(Reg)))); |
| 3396 GPRArgs.push_back( | 3394 GPRArgs.push_back(std::make_pair( |
| 3397 std::make_pair(Hi, RegARM32::getI64PairSecondGPRNum(Reg))); | 3395 Hi, RegNumT::fixme(RegARM32::getI64PairSecondGPRNum(Reg)))); |
| 3398 } else if (isScalarIntegerType(Ty)) { | 3396 } else if (isScalarIntegerType(Ty)) { |
| 3399 GPRArgs.push_back(std::make_pair(Arg, Reg)); | 3397 GPRArgs.push_back(std::make_pair(Arg, Reg)); |
| 3400 } else { | 3398 } else { |
| 3401 FPArgs.push_back(std::make_pair(Arg, Reg)); | 3399 FPArgs.push_back(std::make_pair(Arg, Reg)); |
| 3402 } | 3400 } |
| 3403 } | 3401 } |
| 3404 | 3402 |
| 3405 // Adjust the parameter area so that the stack is aligned. It is assumed that | 3403 // Adjust the parameter area so that the stack is aligned. It is assumed that |
| 3406 // the stack is already aligned at the start of the calling sequence. | 3404 // the stack is already aligned at the start of the calling sequence. |
| 3407 ParameterAreaSizeBytes = applyStackAlignment(ParameterAreaSizeBytes); | 3405 ParameterAreaSizeBytes = applyStackAlignment(ParameterAreaSizeBytes); |
| (...skipping 2042 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5450 } | 5448 } |
| 5451 | 5449 |
| 5452 void TargetARM32::lowerUnreachable(const InstUnreachable * /*Instr*/) { | 5450 void TargetARM32::lowerUnreachable(const InstUnreachable * /*Instr*/) { |
| 5453 _trap(); | 5451 _trap(); |
| 5454 } | 5452 } |
| 5455 | 5453 |
| 5456 void TargetARM32::prelowerPhis() { | 5454 void TargetARM32::prelowerPhis() { |
| 5457 PhiLowering::prelowerPhis32Bit<TargetARM32>(this, Context.getNode(), Func); | 5455 PhiLowering::prelowerPhis32Bit<TargetARM32>(this, Context.getNode(), Func); |
| 5458 } | 5456 } |
| 5459 | 5457 |
| 5460 Variable *TargetARM32::makeVectorOfZeros(Type Ty, int32_t RegNum) { | 5458 Variable *TargetARM32::makeVectorOfZeros(Type Ty, RegNumT RegNum) { |
| 5461 Variable *Reg = makeReg(Ty, RegNum); | 5459 Variable *Reg = makeReg(Ty, RegNum); |
| 5462 Context.insert<InstFakeDef>(Reg); | 5460 Context.insert<InstFakeDef>(Reg); |
| 5463 UnimplementedError(Func->getContext()->getFlags()); | 5461 UnimplementedError(Func->getContext()->getFlags()); |
| 5464 return Reg; | 5462 return Reg; |
| 5465 } | 5463 } |
| 5466 | 5464 |
| 5467 // Helper for legalize() to emit the right code to lower an operand to a | 5465 // Helper for legalize() to emit the right code to lower an operand to a |
| 5468 // register of the appropriate type. | 5466 // register of the appropriate type. |
| 5469 Variable *TargetARM32::copyToReg(Operand *Src, int32_t RegNum) { | 5467 Variable *TargetARM32::copyToReg(Operand *Src, RegNumT RegNum) { |
| 5470 Type Ty = Src->getType(); | 5468 Type Ty = Src->getType(); |
| 5471 Variable *Reg = makeReg(Ty, RegNum); | 5469 Variable *Reg = makeReg(Ty, RegNum); |
| 5472 if (auto *Mem = llvm::dyn_cast<OperandARM32Mem>(Src)) { | 5470 if (auto *Mem = llvm::dyn_cast<OperandARM32Mem>(Src)) { |
| 5473 _ldr(Reg, Mem); | 5471 _ldr(Reg, Mem); |
| 5474 } else { | 5472 } else { |
| 5475 _mov(Reg, Src); | 5473 _mov(Reg, Src); |
| 5476 } | 5474 } |
| 5477 return Reg; | 5475 return Reg; |
| 5478 } | 5476 } |
| 5479 | 5477 |
| 5480 // TODO(jpp): remove unneeded else clauses in legalize. | 5478 // TODO(jpp): remove unneeded else clauses in legalize. |
| 5481 Operand *TargetARM32::legalize(Operand *From, LegalMask Allowed, | 5479 Operand *TargetARM32::legalize(Operand *From, LegalMask Allowed, |
| 5482 int32_t RegNum) { | 5480 RegNumT RegNum) { |
| 5483 Type Ty = From->getType(); | 5481 Type Ty = From->getType(); |
| 5484 // Assert that a physical register is allowed. To date, all calls to | 5482 // Assert that a physical register is allowed. To date, all calls to |
| 5485 // legalize() allow a physical register. Legal_Flex converts registers to the | 5483 // legalize() allow a physical register. Legal_Flex converts registers to the |
| 5486 // right type OperandARM32FlexReg as needed. | 5484 // right type OperandARM32FlexReg as needed. |
| 5487 assert(Allowed & Legal_Reg); | 5485 assert(Allowed & Legal_Reg); |
| 5488 | 5486 |
| 5489 // Copied ipsis literis from TargetX86Base<Machine>. | 5487 // Copied ipsis literis from TargetX86Base<Machine>. |
| 5490 if (RegNum == Variable::NoRegister) { | 5488 if (RegNum == RegNumT::NoRegister) { |
| 5491 if (Variable *Subst = getContext().availabilityGet(From)) { | 5489 if (Variable *Subst = getContext().availabilityGet(From)) { |
| 5492 // At this point we know there is a potential substitution available. | 5490 // At this point we know there is a potential substitution available. |
| 5493 if (!Subst->isRematerializable() && Subst->mustHaveReg() && | 5491 if (!Subst->isRematerializable() && Subst->mustHaveReg() && |
| 5494 !Subst->hasReg()) { | 5492 !Subst->hasReg()) { |
| 5495 // At this point we know the substitution will have a register. | 5493 // At this point we know the substitution will have a register. |
| 5496 if (From->getType() == Subst->getType()) { | 5494 if (From->getType() == Subst->getType()) { |
| 5497 // At this point we know the substitution's register is compatible. | 5495 // At this point we know the substitution's register is compatible. |
| 5498 return Subst; | 5496 return Subst; |
| 5499 } | 5497 } |
| 5500 } | 5498 } |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5664 } | 5662 } |
| 5665 // Check if the variable is guaranteed a physical register. This can happen | 5663 // Check if the variable is guaranteed a physical register. This can happen |
| 5666 // either when the variable is pre-colored or when it is assigned infinite | 5664 // either when the variable is pre-colored or when it is assigned infinite |
| 5667 // weight. | 5665 // weight. |
| 5668 bool MustHaveRegister = (Var->hasReg() || Var->mustHaveReg()); | 5666 bool MustHaveRegister = (Var->hasReg() || Var->mustHaveReg()); |
| 5669 // We need a new physical register for the operand if: | 5667 // We need a new physical register for the operand if: |
| 5670 // Mem is not allowed and Var isn't guaranteed a physical | 5668 // Mem is not allowed and Var isn't guaranteed a physical |
| 5671 // register, or | 5669 // register, or |
| 5672 // RegNum is required and Var->getRegNum() doesn't match. | 5670 // RegNum is required and Var->getRegNum() doesn't match. |
| 5673 if ((!(Allowed & Legal_Mem) && !MustHaveRegister) || | 5671 if ((!(Allowed & Legal_Mem) && !MustHaveRegister) || |
| 5674 (RegNum != Variable::NoRegister && RegNum != Var->getRegNum())) { | 5672 (RegNum != RegNumT::NoRegister && RegNum != Var->getRegNum())) { |
| 5675 From = copyToReg(From, RegNum); | 5673 From = copyToReg(From, RegNum); |
| 5676 } | 5674 } |
| 5677 return From; | 5675 return From; |
| 5678 } | 5676 } |
| 5679 llvm::report_fatal_error("Unhandled operand kind in legalize()"); | 5677 llvm::report_fatal_error("Unhandled operand kind in legalize()"); |
| 5680 | 5678 |
| 5681 return From; | 5679 return From; |
| 5682 } | 5680 } |
| 5683 | 5681 |
| 5684 /// Provide a trivial wrapper to legalize() for this common usage. | 5682 /// Provide a trivial wrapper to legalize() for this common usage. |
| 5685 Variable *TargetARM32::legalizeToReg(Operand *From, int32_t RegNum) { | 5683 Variable *TargetARM32::legalizeToReg(Operand *From, RegNumT RegNum) { |
| 5686 return llvm::cast<Variable>(legalize(From, Legal_Reg, RegNum)); | 5684 return llvm::cast<Variable>(legalize(From, Legal_Reg, RegNum)); |
| 5687 } | 5685 } |
| 5688 | 5686 |
| 5689 /// Legalize undef values to concrete values. | 5687 /// Legalize undef values to concrete values. |
| 5690 Operand *TargetARM32::legalizeUndef(Operand *From, int32_t RegNum) { | 5688 Operand *TargetARM32::legalizeUndef(Operand *From, RegNumT RegNum) { |
| 5691 Type Ty = From->getType(); | 5689 Type Ty = From->getType(); |
| 5692 if (llvm::isa<ConstantUndef>(From)) { | 5690 if (llvm::isa<ConstantUndef>(From)) { |
| 5693 // Lower undefs to zero. Another option is to lower undefs to an | 5691 // Lower undefs to zero. Another option is to lower undefs to an |
| 5694 // uninitialized register; however, using an uninitialized register results | 5692 // uninitialized register; however, using an uninitialized register results |
| 5695 // in less predictable code. | 5693 // in less predictable code. |
| 5696 // | 5694 // |
| 5697 // If in the future the implementation is changed to lower undef values to | 5695 // If in the future the implementation is changed to lower undef values to |
| 5698 // uninitialized registers, a FakeDef will be needed: | 5696 // uninitialized registers, a FakeDef will be needed: |
| 5699 // Context.insert(InstFakeDef::create(Func, Reg)); This is in order to | 5697 // Context.insert(InstFakeDef::create(Func, Reg)); This is in order to |
| 5700 // ensure that the live range of Reg is not overestimated. If the constant | 5698 // ensure that the live range of Reg is not overestimated. If the constant |
| (...skipping 27 matching lines...) Expand all Loading... |
| 5728 Variable64On32 *TargetARM32::makeI64RegPair() { | 5726 Variable64On32 *TargetARM32::makeI64RegPair() { |
| 5729 Variable64On32 *Reg = | 5727 Variable64On32 *Reg = |
| 5730 llvm::cast<Variable64On32>(Func->makeVariable(IceType_i64)); | 5728 llvm::cast<Variable64On32>(Func->makeVariable(IceType_i64)); |
| 5731 Reg->setMustHaveReg(); | 5729 Reg->setMustHaveReg(); |
| 5732 Reg->initHiLo(Func); | 5730 Reg->initHiLo(Func); |
| 5733 Reg->getLo()->setMustNotHaveReg(); | 5731 Reg->getLo()->setMustNotHaveReg(); |
| 5734 Reg->getHi()->setMustNotHaveReg(); | 5732 Reg->getHi()->setMustNotHaveReg(); |
| 5735 return Reg; | 5733 return Reg; |
| 5736 } | 5734 } |
| 5737 | 5735 |
| 5738 Variable *TargetARM32::makeReg(Type Type, int32_t RegNum) { | 5736 Variable *TargetARM32::makeReg(Type Type, RegNumT RegNum) { |
| 5739 // There aren't any 64-bit integer registers for ARM32. | 5737 // There aren't any 64-bit integer registers for ARM32. |
| 5740 assert(Type != IceType_i64); | 5738 assert(Type != IceType_i64); |
| 5741 assert(AllowTemporaryWithNoReg || RegNum != Variable::NoRegister); | 5739 assert(AllowTemporaryWithNoReg || RegNum != RegNumT::NoRegister); |
| 5742 Variable *Reg = Func->makeVariable(Type); | 5740 Variable *Reg = Func->makeVariable(Type); |
| 5743 if (RegNum == Variable::NoRegister) | 5741 if (RegNum == RegNumT::NoRegister) |
| 5744 Reg->setMustHaveReg(); | 5742 Reg->setMustHaveReg(); |
| 5745 else | 5743 else |
| 5746 Reg->setRegNum(RegNum); | 5744 Reg->setRegNum(RegNum); |
| 5747 return Reg; | 5745 return Reg; |
| 5748 } | 5746 } |
| 5749 | 5747 |
| 5750 void TargetARM32::alignRegisterPow2(Variable *Reg, uint32_t Align, | 5748 void TargetARM32::alignRegisterPow2(Variable *Reg, uint32_t Align, |
| 5751 int32_t TmpRegNum) { | 5749 RegNumT TmpRegNum) { |
| 5752 assert(llvm::isPowerOf2_32(Align)); | 5750 assert(llvm::isPowerOf2_32(Align)); |
| 5753 uint32_t RotateAmt; | 5751 uint32_t RotateAmt; |
| 5754 uint32_t Immed_8; | 5752 uint32_t Immed_8; |
| 5755 Operand *Mask; | 5753 Operand *Mask; |
| 5756 // Use AND or BIC to mask off the bits, depending on which immediate fits (if | 5754 // Use AND or BIC to mask off the bits, depending on which immediate fits (if |
| 5757 // it fits at all). Assume Align is usually small, in which case BIC works | 5755 // it fits at all). Assume Align is usually small, in which case BIC works |
| 5758 // better. Thus, this rounds down to the alignment. | 5756 // better. Thus, this rounds down to the alignment. |
| 5759 if (OperandARM32FlexImm::canHoldImm(Align - 1, &RotateAmt, &Immed_8)) { | 5757 if (OperandARM32FlexImm::canHoldImm(Align - 1, &RotateAmt, &Immed_8)) { |
| 5760 Mask = legalize(Ctx->getConstantInt32(Align - 1), Legal_Reg | Legal_Flex, | 5758 Mask = legalize(Ctx->getConstantInt32(Align - 1), Legal_Reg | Legal_Flex, |
| 5761 TmpRegNum); | 5759 TmpRegNum); |
| 5762 _bic(Reg, Reg, Mask); | 5760 _bic(Reg, Reg, Mask); |
| 5763 } else { | 5761 } else { |
| 5764 Mask = legalize(Ctx->getConstantInt32(-Align), Legal_Reg | Legal_Flex, | 5762 Mask = legalize(Ctx->getConstantInt32(-Align), Legal_Reg | Legal_Flex, |
| 5765 TmpRegNum); | 5763 TmpRegNum); |
| 5766 _and(Reg, Reg, Mask); | 5764 _and(Reg, Reg, Mask); |
| 5767 } | 5765 } |
| 5768 } | 5766 } |
| 5769 | 5767 |
| 5770 void TargetARM32::postLower() { | 5768 void TargetARM32::postLower() { |
| 5771 if (Ctx->getFlags().getOptLevel() == Opt_m1) | 5769 if (Ctx->getFlags().getOptLevel() == Opt_m1) |
| 5772 return; | 5770 return; |
| 5773 markRedefinitions(); | 5771 markRedefinitions(); |
| 5774 Context.availabilityUpdate(); | 5772 Context.availabilityUpdate(); |
| 5775 } | 5773 } |
| 5776 | 5774 |
| 5777 void TargetARM32::makeRandomRegisterPermutation( | 5775 void TargetARM32::makeRandomRegisterPermutation( |
| 5778 llvm::SmallVectorImpl<int32_t> &Permutation, | 5776 llvm::SmallVectorImpl<RegNumT> &Permutation, |
| 5779 const llvm::SmallBitVector &ExcludeRegisters, uint64_t Salt) const { | 5777 const llvm::SmallBitVector &ExcludeRegisters, uint64_t Salt) const { |
| 5780 (void)Permutation; | 5778 (void)Permutation; |
| 5781 (void)ExcludeRegisters; | 5779 (void)ExcludeRegisters; |
| 5782 (void)Salt; | 5780 (void)Salt; |
| 5783 UnimplementedError(Func->getContext()->getFlags()); | 5781 UnimplementedError(Func->getContext()->getFlags()); |
| 5784 } | 5782 } |
| 5785 | 5783 |
| 5786 void TargetARM32::emit(const ConstantInteger32 *C) const { | 5784 void TargetARM32::emit(const ConstantInteger32 *C) const { |
| 5787 if (!BuildDefs::dump()) | 5785 if (!BuildDefs::dump()) |
| 5788 return; | 5786 return; |
| (...skipping 734 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6523 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n"; | 6521 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n"; |
| 6524 } | 6522 } |
| 6525 | 6523 |
| 6526 llvm::SmallBitVector TargetARM32::TypeToRegisterSet[RegARM32::RCARM32_NUM]; | 6524 llvm::SmallBitVector TargetARM32::TypeToRegisterSet[RegARM32::RCARM32_NUM]; |
| 6527 llvm::SmallBitVector | 6525 llvm::SmallBitVector |
| 6528 TargetARM32::TypeToRegisterSetUnfiltered[RegARM32::RCARM32_NUM]; | 6526 TargetARM32::TypeToRegisterSetUnfiltered[RegARM32::RCARM32_NUM]; |
| 6529 llvm::SmallBitVector TargetARM32::RegisterAliases[RegARM32::Reg_NUM]; | 6527 llvm::SmallBitVector TargetARM32::RegisterAliases[RegARM32::Reg_NUM]; |
| 6530 | 6528 |
| 6531 } // end of namespace ARM32 | 6529 } // end of namespace ARM32 |
| 6532 } // end of namespace Ice | 6530 } // end of namespace Ice |
| OLD | NEW |