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 1467 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1478 Target->_mov(DstFPRLo, SrcGPRHi); | 1478 Target->_mov(DstFPRLo, SrcGPRHi); |
1479 Legalized = true; | 1479 Legalized = true; |
1480 } else { | 1480 } else { |
1481 Variable *SrcGPR = Target->makeReg(IceType_f32, SRegNum); | 1481 Variable *SrcGPR = Target->makeReg(IceType_f32, SRegNum); |
1482 Variable *DstFPR = Target->makeReg(IceType_i32, DRegNum); | 1482 Variable *DstFPR = Target->makeReg(IceType_i32, DRegNum); |
1483 Target->_mov(DstFPR, SrcGPR); | 1483 Target->_mov(DstFPR, SrcGPR); |
1484 Legalized = true; | 1484 Legalized = true; |
1485 } | 1485 } |
1486 } else { | 1486 } else { |
1487 // Dest is FPR and SrcR is GPR. Use mtc1. | 1487 // Dest is FPR and SrcR is GPR. Use mtc1. |
1488 if (typeWidthInBytes(SrcR->getType()) == 8) { | 1488 if (typeWidthInBytes(Dest->getType()) == 8) { |
1489 // Split it into two mtc1 instructions | 1489 Variable *SrcGPRHi, *SrcGPRLo; |
1490 Variable *SrcGPRHi = Target->makeReg( | 1490 // SrcR could be $zero which is i32 |
1491 IceType_i32, RegMIPS32::get64PairFirstRegNum(SRegNum)); | 1491 if (SRegNum == RegMIPS32::Reg_ZERO) { |
1492 Variable *SrcGPRLo = Target->makeReg( | 1492 SrcGPRHi = Target->makeReg(IceType_i32, SRegNum); |
1493 IceType_i32, RegMIPS32::get64PairSecondRegNum(SRegNum)); | 1493 SrcGPRLo = SrcGPRHi; |
| 1494 } else { |
| 1495 // Split it into two mtc1 instructions |
| 1496 SrcGPRHi = Target->makeReg( |
| 1497 IceType_i32, RegMIPS32::get64PairFirstRegNum(SRegNum)); |
| 1498 SrcGPRLo = Target->makeReg( |
| 1499 IceType_i32, RegMIPS32::get64PairSecondRegNum(SRegNum)); |
| 1500 } |
1494 Variable *DstFPRHi = Target->makeReg( | 1501 Variable *DstFPRHi = Target->makeReg( |
1495 IceType_f32, RegMIPS32::get64PairFirstRegNum(DRegNum)); | 1502 IceType_f32, RegMIPS32::get64PairFirstRegNum(DRegNum)); |
1496 Variable *DstFPRLo = Target->makeReg( | 1503 Variable *DstFPRLo = Target->makeReg( |
1497 IceType_f32, RegMIPS32::get64PairSecondRegNum(DRegNum)); | 1504 IceType_f32, RegMIPS32::get64PairSecondRegNum(DRegNum)); |
1498 Target->_mov(DstFPRHi, SrcGPRLo); | 1505 Target->_mov(DstFPRHi, SrcGPRLo); |
1499 Target->_mov(DstFPRLo, SrcGPRHi); | 1506 Target->_mov(DstFPRLo, SrcGPRHi); |
1500 Legalized = true; | 1507 Legalized = true; |
1501 } else { | 1508 } else { |
1502 Variable *SrcGPR = Target->makeReg(IceType_i32, SRegNum); | 1509 Variable *SrcGPR = Target->makeReg(IceType_i32, SRegNum); |
1503 Variable *DstFPR = Target->makeReg(IceType_f32, DRegNum); | 1510 Variable *DstFPR = Target->makeReg(IceType_f32, DRegNum); |
(...skipping 1910 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3414 OstreamLocker L(Ctx); | 3421 OstreamLocker L(Ctx); |
3415 for (const VariableDeclaration *Var : Vars) { | 3422 for (const VariableDeclaration *Var : Vars) { |
3416 if (getFlags().matchTranslateOnly(Var->getName(), 0)) { | 3423 if (getFlags().matchTranslateOnly(Var->getName(), 0)) { |
3417 emitGlobal(*Var, SectionSuffix); | 3424 emitGlobal(*Var, SectionSuffix); |
3418 } | 3425 } |
3419 } | 3426 } |
3420 } break; | 3427 } break; |
3421 } | 3428 } |
3422 } | 3429 } |
3423 | 3430 |
| 3431 namespace { |
| 3432 template <typename T> struct ConstantPoolEmitterTraits; |
| 3433 |
| 3434 static_assert(sizeof(uint64_t) == 8, |
| 3435 "uint64_t is supposed to be 8 bytes wide."); |
| 3436 |
| 3437 // TODO(jaydeep.patil): implement the following when implementing constant |
| 3438 // randomization: |
| 3439 // * template <> struct ConstantPoolEmitterTraits<uint8_t> |
| 3440 // * template <> struct ConstantPoolEmitterTraits<uint16_t> |
| 3441 // * template <> struct ConstantPoolEmitterTraits<uint32_t> |
| 3442 template <> struct ConstantPoolEmitterTraits<float> { |
| 3443 using ConstantType = ConstantFloat; |
| 3444 static constexpr Type IceType = IceType_f32; |
| 3445 // AsmTag and TypeName can't be constexpr because llvm::StringRef is unhappy |
| 3446 // about them being constexpr. |
| 3447 static const char AsmTag[]; |
| 3448 static const char TypeName[]; |
| 3449 static uint64_t bitcastToUint64(float Value) { |
| 3450 static_assert(sizeof(Value) == sizeof(uint32_t), |
| 3451 "Float should be 4 bytes."); |
| 3452 const uint32_t IntValue = Utils::bitCopy<uint32_t>(Value); |
| 3453 return static_cast<uint64_t>(IntValue); |
| 3454 } |
| 3455 }; |
| 3456 const char ConstantPoolEmitterTraits<float>::AsmTag[] = ".word"; |
| 3457 const char ConstantPoolEmitterTraits<float>::TypeName[] = "f32"; |
| 3458 |
| 3459 template <> struct ConstantPoolEmitterTraits<double> { |
| 3460 using ConstantType = ConstantDouble; |
| 3461 static constexpr Type IceType = IceType_f64; |
| 3462 static const char AsmTag[]; |
| 3463 static const char TypeName[]; |
| 3464 static uint64_t bitcastToUint64(double Value) { |
| 3465 static_assert(sizeof(double) == sizeof(uint64_t), |
| 3466 "Double should be 8 bytes."); |
| 3467 return Utils::bitCopy<uint64_t>(Value); |
| 3468 } |
| 3469 }; |
| 3470 const char ConstantPoolEmitterTraits<double>::AsmTag[] = ".quad"; |
| 3471 const char ConstantPoolEmitterTraits<double>::TypeName[] = "f64"; |
| 3472 |
| 3473 template <typename T> |
| 3474 void emitConstant( |
| 3475 Ostream &Str, |
| 3476 const typename ConstantPoolEmitterTraits<T>::ConstantType *Const) { |
| 3477 if (!BuildDefs::dump()) |
| 3478 return; |
| 3479 using Traits = ConstantPoolEmitterTraits<T>; |
| 3480 Str << Const->getLabelName(); |
| 3481 T Value = Const->getValue(); |
| 3482 Str << ":\n\t" << Traits::AsmTag << "\t0x"; |
| 3483 Str.write_hex(Traits::bitcastToUint64(Value)); |
| 3484 Str << "\t/* " << Traits::TypeName << " " << Value << " */\n"; |
| 3485 } |
| 3486 |
| 3487 template <typename T> void emitConstantPool(GlobalContext *Ctx) { |
| 3488 if (!BuildDefs::dump()) |
| 3489 return; |
| 3490 using Traits = ConstantPoolEmitterTraits<T>; |
| 3491 static constexpr size_t MinimumAlignment = 4; |
| 3492 SizeT Align = std::max(MinimumAlignment, typeAlignInBytes(Traits::IceType)); |
| 3493 assert((Align % 4) == 0 && "Constants should be aligned"); |
| 3494 Ostream &Str = Ctx->getStrEmit(); |
| 3495 ConstantList Pool = Ctx->getConstantPool(Traits::IceType); |
| 3496 Str << "\t.section\t.rodata.cst" << Align << ",\"aM\",%progbits," << Align |
| 3497 << "\n" |
| 3498 << "\t.align\t" << (Align == 4 ? 2 : 3) << "\n"; |
| 3499 if (getFlags().getReorderPooledConstants()) { |
| 3500 // TODO(jaydeep.patil): add constant pooling. |
| 3501 UnimplementedError(getFlags()); |
| 3502 } |
| 3503 for (Constant *C : Pool) { |
| 3504 if (!C->getShouldBePooled()) { |
| 3505 continue; |
| 3506 } |
| 3507 emitConstant<T>(Str, llvm::dyn_cast<typename Traits::ConstantType>(C)); |
| 3508 } |
| 3509 } |
| 3510 } // end of anonymous namespace |
| 3511 |
3424 void TargetDataMIPS32::lowerConstants() { | 3512 void TargetDataMIPS32::lowerConstants() { |
3425 if (getFlags().getDisableTranslation()) | 3513 if (getFlags().getDisableTranslation()) |
3426 return; | 3514 return; |
| 3515 switch (getFlags().getOutFileType()) { |
| 3516 case FT_Elf: { |
| 3517 ELFObjectWriter *Writer = Ctx->getObjectWriter(); |
| 3518 Writer->writeConstantPool<ConstantFloat>(IceType_f32); |
| 3519 Writer->writeConstantPool<ConstantDouble>(IceType_f64); |
| 3520 } break; |
| 3521 case FT_Asm: |
| 3522 case FT_Iasm: { |
| 3523 OstreamLocker _(Ctx); |
| 3524 emitConstantPool<float>(Ctx); |
| 3525 emitConstantPool<double>(Ctx); |
| 3526 break; |
| 3527 } |
| 3528 } |
3427 } | 3529 } |
3428 | 3530 |
3429 void TargetDataMIPS32::lowerJumpTables() { | 3531 void TargetDataMIPS32::lowerJumpTables() { |
3430 if (getFlags().getDisableTranslation()) | 3532 if (getFlags().getDisableTranslation()) |
3431 return; | 3533 return; |
3432 } | 3534 } |
3433 | 3535 |
3434 // Helper for legalize() to emit the right code to lower an operand to a | 3536 // Helper for legalize() to emit the right code to lower an operand to a |
3435 // register of the appropriate type. | 3537 // register of the appropriate type. |
3436 Variable *TargetMIPS32::copyToReg(Operand *Src, RegNumT RegNum) { | 3538 Variable *TargetMIPS32::copyToReg(Operand *Src, RegNumT RegNum) { |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3538 Variable *TReg = makeReg(Ty, RegNum); | 3640 Variable *TReg = makeReg(Ty, RegNum); |
3539 if (LowerBits) { | 3641 if (LowerBits) { |
3540 _lui(TReg, Ctx->getConstantInt32(UpperBits)); | 3642 _lui(TReg, Ctx->getConstantInt32(UpperBits)); |
3541 _ori(Reg, TReg, LowerBits); | 3643 _ori(Reg, TReg, LowerBits); |
3542 } else { | 3644 } else { |
3543 _lui(Reg, Ctx->getConstantInt32(UpperBits)); | 3645 _lui(Reg, Ctx->getConstantInt32(UpperBits)); |
3544 } | 3646 } |
3545 } | 3647 } |
3546 return Reg; | 3648 return Reg; |
3547 } else if (isScalarFloatingType(Ty)) { | 3649 } else if (isScalarFloatingType(Ty)) { |
3548 // Load floats/doubles from literal pool. | |
3549 auto *CFrom = llvm::cast<Constant>(From); | 3650 auto *CFrom = llvm::cast<Constant>(From); |
3550 assert(CFrom->getShouldBePooled()); | 3651 Variable *TReg = makeReg(Ty); |
3551 Constant *Offset = Ctx->getConstantSym(0, CFrom->getLabelName()); | 3652 if (!CFrom->getShouldBePooled()) { |
3552 Variable *TReg1 = makeReg(getPointerType()); | 3653 // Float/Double constant 0 is not pooled. |
3553 Variable *TReg2 = makeReg(Ty); | 3654 Context.insert<InstFakeDef>(TReg); |
3554 Context.insert<InstFakeDef>(TReg2); | 3655 _mov(TReg, getZero()); |
3555 _lui(TReg1, Offset, RO_Hi); | 3656 } else { |
3556 OperandMIPS32Mem *Addr = | 3657 // Load floats/doubles from literal pool. |
3557 OperandMIPS32Mem::create(Func, Ty, TReg1, Offset); | 3658 Constant *Offset = Ctx->getConstantSym(0, CFrom->getLabelName()); |
3558 if (Ty == IceType_f32) | 3659 Variable *TReg1 = makeReg(getPointerType()); |
3559 _lwc1(TReg2, Addr, RO_Lo); | 3660 _lui(TReg1, Offset, RO_Hi); |
3560 else | 3661 OperandMIPS32Mem *Addr = |
3561 _ldc1(TReg2, Addr, RO_Lo); | 3662 OperandMIPS32Mem::create(Func, Ty, TReg1, Offset); |
3562 return copyToReg(TReg2, RegNum); | 3663 if (Ty == IceType_f32) |
| 3664 _lwc1(TReg, Addr, RO_Lo); |
| 3665 else |
| 3666 _ldc1(TReg, Addr, RO_Lo); |
| 3667 } |
| 3668 return copyToReg(TReg, RegNum); |
3563 } | 3669 } |
3564 } | 3670 } |
3565 | 3671 |
3566 if (auto *Var = llvm::dyn_cast<Variable>(From)) { | 3672 if (auto *Var = llvm::dyn_cast<Variable>(From)) { |
3567 if (Var->isRematerializable()) { | 3673 if (Var->isRematerializable()) { |
3568 if (Allowed & Legal_Rematerializable) { | 3674 if (Allowed & Legal_Rematerializable) { |
3569 return From; | 3675 return From; |
3570 } | 3676 } |
3571 | 3677 |
3572 Variable *T = makeReg(Var->getType(), RegNum); | 3678 Variable *T = makeReg(Var->getType(), RegNum); |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3667 Str << "\t.set\t" | 3773 Str << "\t.set\t" |
3668 << "nomips16\n"; | 3774 << "nomips16\n"; |
3669 } | 3775 } |
3670 | 3776 |
3671 SmallBitVector TargetMIPS32::TypeToRegisterSet[RCMIPS32_NUM]; | 3777 SmallBitVector TargetMIPS32::TypeToRegisterSet[RCMIPS32_NUM]; |
3672 SmallBitVector TargetMIPS32::TypeToRegisterSetUnfiltered[RCMIPS32_NUM]; | 3778 SmallBitVector TargetMIPS32::TypeToRegisterSetUnfiltered[RCMIPS32_NUM]; |
3673 SmallBitVector TargetMIPS32::RegisterAliases[RegMIPS32::Reg_NUM]; | 3779 SmallBitVector TargetMIPS32::RegisterAliases[RegMIPS32::Reg_NUM]; |
3674 | 3780 |
3675 } // end of namespace MIPS32 | 3781 } // end of namespace MIPS32 |
3676 } // end of namespace Ice | 3782 } // end of namespace Ice |
OLD | NEW |