Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // | 1 // |
| 2 // The Subzero Code Generator | 2 // The Subzero Code Generator |
| 3 // | 3 // |
| 4 // This file is distributed under the University of Illinois Open Source | 4 // This file is distributed under the University of Illinois Open Source |
| 5 // License. See LICENSE.TXT for details. | 5 // License. See LICENSE.TXT for details. |
| 6 // | 6 // |
| 7 //===----------------------------------------------------------------------===// | 7 //===----------------------------------------------------------------------===// |
| 8 /// | 8 /// |
| 9 /// \file | 9 /// \file |
| 10 /// \brief Implements the TargetLoweringMIPS32 class, which consists almost | 10 /// \brief Implements the TargetLoweringMIPS32 class, which consists almost |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 57 namespace Ice { | 57 namespace Ice { |
| 58 namespace MIPS32 { | 58 namespace MIPS32 { |
| 59 | 59 |
| 60 using llvm::isInt; | 60 using llvm::isInt; |
| 61 | 61 |
| 62 namespace { | 62 namespace { |
| 63 | 63 |
| 64 // The maximum number of arguments to pass in GPR registers. | 64 // The maximum number of arguments to pass in GPR registers. |
| 65 constexpr uint32_t MIPS32_MAX_GPR_ARG = 4; | 65 constexpr uint32_t MIPS32_MAX_GPR_ARG = 4; |
| 66 | 66 |
| 67 std::array<RegNumT, MIPS32_MAX_GPR_ARG> GPRArgInitializer; | |
| 68 std::array<RegNumT, MIPS32_MAX_GPR_ARG / 2> I64ArgInitializer; | |
| 69 | |
| 70 constexpr uint32_t MIPS32_MAX_FP_ARG = 2; | |
| 71 | |
| 72 std::array<RegNumT, MIPS32_MAX_FP_ARG> FP32ArgInitializer; | |
| 73 std::array<RegNumT, MIPS32_MAX_FP_ARG> FP64ArgInitializer; | |
| 74 | |
| 67 const char *getRegClassName(RegClass C) { | 75 const char *getRegClassName(RegClass C) { |
| 68 auto ClassNum = static_cast<RegClassMIPS32>(C); | 76 auto ClassNum = static_cast<RegClassMIPS32>(C); |
| 69 assert(ClassNum < RCMIPS32_NUM); | 77 assert(ClassNum < RCMIPS32_NUM); |
| 70 switch (ClassNum) { | 78 switch (ClassNum) { |
| 71 default: | 79 default: |
| 72 assert(C < RC_Target); | 80 assert(C < RC_Target); |
| 73 return regClassString(C); | 81 return regClassString(C); |
| 74 // Add handling of new register classes below. | 82 // Add handling of new register classes below. |
| 75 } | 83 } |
| 76 } | 84 } |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 98 RegisterAliases[RegMIPS32::val].resize(RegMIPS32::Reg_NUM); \ | 106 RegisterAliases[RegMIPS32::val].resize(RegMIPS32::Reg_NUM); \ |
| 99 for (SizeT RegAlias : alias_init) { \ | 107 for (SizeT RegAlias : alias_init) { \ |
| 100 assert(!RegisterAliases[RegMIPS32::val][RegAlias] && \ | 108 assert(!RegisterAliases[RegMIPS32::val][RegAlias] && \ |
| 101 "Duplicate alias for " #val); \ | 109 "Duplicate alias for " #val); \ |
| 102 RegisterAliases[RegMIPS32::val].set(RegAlias); \ | 110 RegisterAliases[RegMIPS32::val].set(RegAlias); \ |
| 103 } \ | 111 } \ |
| 104 RegisterAliases[RegMIPS32::val].resize(RegMIPS32::Reg_NUM); \ | 112 RegisterAliases[RegMIPS32::val].resize(RegMIPS32::Reg_NUM); \ |
| 105 assert(RegisterAliases[RegMIPS32::val][RegMIPS32::val]); | 113 assert(RegisterAliases[RegMIPS32::val][RegMIPS32::val]); |
| 106 REGMIPS32_TABLE; | 114 REGMIPS32_TABLE; |
| 107 #undef X | 115 #undef X |
| 116 | |
| 117 // TODO(mohit.bhakkad): Change these inits once we provide argument related | |
| 118 // field in register tables | |
| 119 for (size_t i = 0; i < MIPS32_MAX_GPR_ARG; i++) | |
| 120 GPRArgInitializer[i] = RegNumT::fixme(RegMIPS32::Reg_A0 + i); | |
| 121 | |
| 122 for (size_t i = 0; i < MIPS32_MAX_GPR_ARG / 2; i++) | |
| 123 I64ArgInitializer[i] = RegNumT::fixme(RegMIPS32::Reg_A0A1 + i); | |
| 124 | |
| 125 for (size_t i = 0; i < MIPS32_MAX_FP_ARG; i++) { | |
| 126 FP32ArgInitializer[i] = RegNumT::fixme(RegMIPS32::Reg_F12 + i * 2); | |
| 127 FP64ArgInitializer[i] = RegNumT::fixme(RegMIPS32::Reg_F12F13 + i); | |
| 128 } | |
| 129 | |
| 108 TypeToRegisterSet[IceType_void] = InvalidRegisters; | 130 TypeToRegisterSet[IceType_void] = InvalidRegisters; |
| 109 TypeToRegisterSet[IceType_i1] = IntegerRegisters; | 131 TypeToRegisterSet[IceType_i1] = IntegerRegisters; |
| 110 TypeToRegisterSet[IceType_i8] = IntegerRegisters; | 132 TypeToRegisterSet[IceType_i8] = IntegerRegisters; |
| 111 TypeToRegisterSet[IceType_i16] = IntegerRegisters; | 133 TypeToRegisterSet[IceType_i16] = IntegerRegisters; |
| 112 TypeToRegisterSet[IceType_i32] = IntegerRegisters; | 134 TypeToRegisterSet[IceType_i32] = IntegerRegisters; |
| 113 TypeToRegisterSet[IceType_i64] = IntegerRegisters; | 135 TypeToRegisterSet[IceType_i64] = IntegerRegisters; |
| 114 TypeToRegisterSet[IceType_f32] = Float32Registers; | 136 TypeToRegisterSet[IceType_f32] = Float32Registers; |
| 115 TypeToRegisterSet[IceType_f64] = Float64Registers; | 137 TypeToRegisterSet[IceType_f64] = Float64Registers; |
| 116 TypeToRegisterSet[IceType_v4i1] = VectorRegisters; | 138 TypeToRegisterSet[IceType_v4i1] = VectorRegisters; |
| 117 TypeToRegisterSet[IceType_v8i1] = VectorRegisters; | 139 TypeToRegisterSet[IceType_v8i1] = VectorRegisters; |
| (...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 399 return; | 421 return; |
| 400 } else { | 422 } else { |
| 401 int32_t Offset = Var->getStackOffset(); | 423 int32_t Offset = Var->getStackOffset(); |
| 402 Str << Offset; | 424 Str << Offset; |
| 403 Str << "($" << getRegName(getFrameOrStackReg(), FrameSPTy); | 425 Str << "($" << getRegName(getFrameOrStackReg(), FrameSPTy); |
| 404 Str << ")"; | 426 Str << ")"; |
| 405 } | 427 } |
| 406 UnimplementedError(getFlags()); | 428 UnimplementedError(getFlags()); |
| 407 } | 429 } |
| 408 | 430 |
| 431 TargetMIPS32::CallingConv::CallingConv() | |
| 432 : GPRegsUsed(RegMIPS32::Reg_NUM), | |
| 433 GPRArgs(GPRArgInitializer.rbegin(), GPRArgInitializer.rend()), | |
| 434 I64Args(I64ArgInitializer.rbegin(), I64ArgInitializer.rend()), | |
| 435 VFPRegsUsed(RegMIPS32::Reg_NUM), | |
| 436 FP32Args(FP32ArgInitializer.rbegin(), FP32ArgInitializer.rend()), | |
| 437 FP64Args(FP64ArgInitializer.rbegin(), FP64ArgInitializer.rend()) {} | |
| 438 | |
| 439 // In MIPS O32 abi FP argument registers can be used only if first argument is | |
| 440 // of type float/double. UseFPRegs flag is used to care of that. Also FP arg | |
| 441 // registers can be used only for first 2 arguments, so we require argument | |
| 442 // number to make register allocation decisions. | |
| 443 bool TargetMIPS32::CallingConv::argInReg(Type Ty, uint32_t ArgNo, | |
| 444 RegNumT *Reg) { | |
| 445 if (isScalarIntegerType(Ty)) | |
| 446 return argInGPR(Ty, Reg); | |
| 447 if (isScalarFloatingType(Ty)) { | |
| 448 if (ArgNo == 0) { | |
| 449 UseFPRegs = true; | |
| 450 return argInVFP(Ty, Reg); | |
| 451 } else { | |
|
Jim Stichnoth
2016/06/11 14:13:26
More "else-after-return" simplifications can be do
| |
| 452 if (UseFPRegs && ArgNo == 1) { | |
| 453 UseFPRegs = false; | |
| 454 return argInVFP(Ty, Reg); | |
| 455 } else | |
| 456 return argInGPR(Ty, Reg); | |
| 457 } | |
| 458 } | |
| 459 UnimplementedError(getFlags()); | |
| 460 return false; | |
| 461 } | |
| 462 | |
| 463 bool TargetMIPS32::CallingConv::argInGPR(Type Ty, RegNumT *Reg) { | |
| 464 CfgVector<RegNumT> *Source; | |
| 465 | |
| 466 switch (Ty) { | |
| 467 default: { | |
| 468 UnimplementedError(getFlags()); | |
| 469 return false; | |
| 470 } break; | |
| 471 case IceType_i32: | |
| 472 case IceType_f32: { | |
| 473 Source = &GPRArgs; | |
| 474 } break; | |
| 475 case IceType_i64: | |
| 476 case IceType_f64: { | |
| 477 Source = &I64Args; | |
| 478 } break; | |
| 479 } | |
| 480 | |
| 481 discardUnavailableGPRsAndTheirAliases(Source); | |
| 482 | |
| 483 if (Source->empty()) { | |
| 484 GPRegsUsed.set(); | |
| 485 return false; | |
| 486 } | |
| 487 | |
| 488 *Reg = Source->back(); | |
| 489 // Note that we don't Source->pop_back() here. This is intentional. Notice how | |
| 490 // we mark all of Reg's aliases as Used. So, for the next argument, | |
| 491 // Source->back() is marked as unavailable, and it is thus implicitly popped | |
| 492 // from the stack. | |
| 493 GPRegsUsed |= RegisterAliases[*Reg]; | |
| 494 return true; | |
| 495 } | |
| 496 | |
| 497 inline void TargetMIPS32::CallingConv::discardNextGPRAndItsAliases( | |
| 498 CfgVector<RegNumT> *Regs) { | |
| 499 GPRegsUsed |= RegisterAliases[Regs->back()]; | |
| 500 Regs->pop_back(); | |
| 501 } | |
| 502 | |
| 503 // GPR are not packed when passing parameters. Thus, a function foo(i32, i64, | |
| 504 // i32) will have the first argument in a0, the second in a2-a3, and the third | |
| 505 // on the stack. To model this behavior, whenever we pop a register from Regs, | |
| 506 // we remove all of its aliases from the pool of available GPRs. This has the | |
| 507 // effect of computing the "closure" on the GPR registers. | |
| 508 void TargetMIPS32::CallingConv::discardUnavailableGPRsAndTheirAliases( | |
| 509 CfgVector<RegNumT> *Regs) { | |
| 510 while (!Regs->empty() && GPRegsUsed[Regs->back()]) { | |
| 511 discardNextGPRAndItsAliases(Regs); | |
| 512 } | |
| 513 } | |
| 514 | |
| 515 bool TargetMIPS32::CallingConv::argInVFP(Type Ty, RegNumT *Reg) { | |
| 516 CfgVector<RegNumT> *Source; | |
| 517 | |
| 518 switch (Ty) { | |
| 519 default: { | |
| 520 UnimplementedError(getFlags()); | |
| 521 return false; | |
| 522 } break; | |
| 523 case IceType_f32: { | |
| 524 Source = &FP32Args; | |
| 525 } break; | |
| 526 case IceType_f64: { | |
| 527 Source = &FP64Args; | |
| 528 } break; | |
| 529 } | |
| 530 | |
| 531 discardUnavailableVFPRegsAndTheirAliases(Source); | |
| 532 | |
| 533 if (Source->empty()) { | |
| 534 VFPRegsUsed.set(); | |
| 535 return false; | |
| 536 } | |
| 537 | |
| 538 *Reg = Source->back(); | |
| 539 VFPRegsUsed |= RegisterAliases[*Reg]; | |
| 540 | |
| 541 // In MIPS O32 abi if fun arguments are (f32, i32) then one can not use reg_a0 | |
| 542 // for second argument even though it's free. f32 arg goes in reg_f12, i32 arg | |
| 543 // goes in reg_a1. Similarly if arguments are (f64, i32) second argument goes | |
| 544 // in reg_a3 and a0, a1 are not used. | |
| 545 Source = &GPRArgs; | |
| 546 // Discard one GPR reg for f32(4 bytes), two for f64(4 + 4 bytes) | |
| 547 discardNextGPRAndItsAliases(Source); | |
| 548 if (Ty == IceType_f64) | |
| 549 discardNextGPRAndItsAliases(Source); | |
| 550 | |
| 551 return true; | |
| 552 } | |
| 553 | |
| 554 void TargetMIPS32::CallingConv::discardUnavailableVFPRegsAndTheirAliases( | |
| 555 CfgVector<RegNumT> *Regs) { | |
| 556 while (!Regs->empty() && VFPRegsUsed[Regs->back()]) { | |
| 557 Regs->pop_back(); | |
| 558 } | |
| 559 } | |
| 560 | |
| 409 void TargetMIPS32::lowerArguments() { | 561 void TargetMIPS32::lowerArguments() { |
| 410 VarList &Args = Func->getArgs(); | 562 VarList &Args = Func->getArgs(); |
| 411 // We are only handling integer registers for now. The Mips o32 ABI is | 563 // We are only handling integer registers for now. The Mips o32 ABI is |
| 412 // somewhat complex but will be implemented in its totality through follow | 564 // somewhat complex but will be implemented in its totality through follow |
| 413 // on patches. | 565 // on patches. |
| 414 // | 566 // |
| 415 unsigned NumGPRRegsUsed = 0; | 567 unsigned NumGPRRegsUsed = 0; |
| 416 // For each register argument, replace Arg in the argument list with the | 568 // For each register argument, replace Arg in the argument list with the |
| 417 // home register. Then generate an instruction in the prolog to copy the | 569 // home register. Then generate an instruction in the prolog to copy the |
| 418 // home register to the assigned location of Arg. | 570 // home register to the assigned location of Arg. |
| (...skipping 1295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1714 Str << "\t.set\t" | 1866 Str << "\t.set\t" |
| 1715 << "nomips16\n"; | 1867 << "nomips16\n"; |
| 1716 } | 1868 } |
| 1717 | 1869 |
| 1718 SmallBitVector TargetMIPS32::TypeToRegisterSet[RCMIPS32_NUM]; | 1870 SmallBitVector TargetMIPS32::TypeToRegisterSet[RCMIPS32_NUM]; |
| 1719 SmallBitVector TargetMIPS32::TypeToRegisterSetUnfiltered[RCMIPS32_NUM]; | 1871 SmallBitVector TargetMIPS32::TypeToRegisterSetUnfiltered[RCMIPS32_NUM]; |
| 1720 SmallBitVector TargetMIPS32::RegisterAliases[RegMIPS32::Reg_NUM]; | 1872 SmallBitVector TargetMIPS32::RegisterAliases[RegMIPS32::Reg_NUM]; |
| 1721 | 1873 |
| 1722 } // end of namespace MIPS32 | 1874 } // end of namespace MIPS32 |
| 1723 } // end of namespace Ice | 1875 } // end of namespace Ice |
| OLD | NEW |