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 1528 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1539 Variable *Dest = MovInstr->getDest(); | 1539 Variable *Dest = MovInstr->getDest(); |
1540 assert(Dest != nullptr); | 1540 assert(Dest != nullptr); |
1541 const Type DestTy = Dest->getType(); | 1541 const Type DestTy = Dest->getType(); |
1542 assert(DestTy != IceType_i64); | 1542 assert(DestTy != IceType_i64); |
1543 | 1543 |
1544 Operand *Src = MovInstr->getSrc(0); | 1544 Operand *Src = MovInstr->getSrc(0); |
1545 const Type SrcTy = Src->getType(); | 1545 const Type SrcTy = Src->getType(); |
1546 (void)SrcTy; | 1546 (void)SrcTy; |
1547 assert(SrcTy != IceType_i64); | 1547 assert(SrcTy != IceType_i64); |
1548 | 1548 |
1549 if (MovInstr->isMultiDest() || MovInstr->isMultiSource()) | |
1550 return; | |
1551 | |
1552 bool Legalized = false; | 1549 bool Legalized = false; |
1553 auto *SrcR = llvm::cast<Variable>(Src); | 1550 auto *SrcR = llvm::cast<Variable>(Src); |
1554 if (Dest->hasReg() && SrcR->hasReg()) { | 1551 if (Dest->hasReg() && SrcR->hasReg()) { |
1555 // This might be a GP to/from FP move generated due to argument passing. | 1552 // This might be a GP to/from FP move generated due to argument passing. |
1556 // Use mtc1/mfc1 instead of mov.[s/d] if src and dst registers are of | 1553 // Use mtc1/mfc1 instead of mov.[s/d] if src and dst registers are of |
1557 // different types. | 1554 // different types. |
1558 const bool IsDstGPR = RegMIPS32::isGPRReg(Dest->getRegNum()); | 1555 const bool IsDstGPR = RegMIPS32::isGPRReg(Dest->getRegNum()); |
1559 const bool IsSrcGPR = RegMIPS32::isGPRReg(SrcR->getRegNum()); | 1556 const bool IsSrcGPR = RegMIPS32::isGPRReg(SrcR->getRegNum()); |
1560 const RegNumT SRegNum = SrcR->getRegNum(); | 1557 const RegNumT SRegNum = SrcR->getRegNum(); |
1561 const RegNumT DRegNum = Dest->getRegNum(); | 1558 const RegNumT DRegNum = Dest->getRegNum(); |
1562 if (IsDstGPR != IsSrcGPR) { | 1559 if (IsDstGPR != IsSrcGPR) { |
1563 if (IsDstGPR) { | 1560 if (IsDstGPR) { |
1564 // Dest is GPR and SrcR is FPR. Use mfc1. | 1561 // Dest is GPR and SrcR is FPR. Use mfc1. |
1565 if (typeWidthInBytes(Dest->getType()) == 8) { | 1562 int32_t TypeWidth = typeWidthInBytes(DestTy); |
| 1563 if (MovInstr->getDestHi() != nullptr) |
| 1564 TypeWidth += typeWidthInBytes(MovInstr->getDestHi()->getType()); |
| 1565 if (TypeWidth == 8) { |
1566 // Split it into two mfc1 instructions | 1566 // Split it into two mfc1 instructions |
1567 Variable *SrcGPRHi = Target->makeReg( | 1567 Variable *SrcGPRHi = Target->makeReg( |
1568 IceType_f32, RegMIPS32::get64PairFirstRegNum(SRegNum)); | 1568 IceType_f32, RegMIPS32::get64PairFirstRegNum(SRegNum)); |
1569 Variable *SrcGPRLo = Target->makeReg( | 1569 Variable *SrcGPRLo = Target->makeReg( |
1570 IceType_f32, RegMIPS32::get64PairSecondRegNum(SRegNum)); | 1570 IceType_f32, RegMIPS32::get64PairSecondRegNum(SRegNum)); |
1571 Variable *DstFPRHi = Target->makeReg( | 1571 Variable *DstFPRHi, *DstFPRLo; |
1572 IceType_i32, RegMIPS32::get64PairFirstRegNum(DRegNum)); | 1572 if (MovInstr->getDestHi() != nullptr && Dest != nullptr) { |
1573 Variable *DstFPRLo = Target->makeReg( | 1573 DstFPRHi = Target->makeReg(IceType_i32, |
1574 IceType_i32, RegMIPS32::get64PairSecondRegNum(DRegNum)); | 1574 MovInstr->getDestHi()->getRegNum()); |
| 1575 DstFPRLo = Target->makeReg(IceType_i32, Dest->getRegNum()); |
| 1576 } else { |
| 1577 DstFPRHi = Target->makeReg( |
| 1578 IceType_i32, RegMIPS32::get64PairFirstRegNum(DRegNum)); |
| 1579 DstFPRLo = Target->makeReg( |
| 1580 IceType_i32, RegMIPS32::get64PairSecondRegNum(DRegNum)); |
| 1581 } |
1575 Target->_mov(DstFPRHi, SrcGPRLo); | 1582 Target->_mov(DstFPRHi, SrcGPRLo); |
1576 Target->_mov(DstFPRLo, SrcGPRHi); | 1583 Target->_mov(DstFPRLo, SrcGPRHi); |
1577 Legalized = true; | 1584 Legalized = true; |
1578 } else { | 1585 } else { |
1579 Variable *SrcGPR = Target->makeReg(IceType_f32, SRegNum); | 1586 Variable *SrcGPR = Target->makeReg(IceType_f32, SRegNum); |
1580 Variable *DstFPR = Target->makeReg(IceType_i32, DRegNum); | 1587 Variable *DstFPR = Target->makeReg(IceType_i32, DRegNum); |
1581 Target->_mov(DstFPR, SrcGPR); | 1588 Target->_mov(DstFPR, SrcGPR); |
1582 Legalized = true; | 1589 Legalized = true; |
1583 } | 1590 } |
1584 } else { | 1591 } else { |
1585 // Dest is FPR and SrcR is GPR. Use mtc1. | 1592 // Dest is FPR and SrcR is GPR. Use mtc1. |
1586 if (typeWidthInBytes(Dest->getType()) == 8) { | 1593 if (typeWidthInBytes(Dest->getType()) == 8) { |
1587 Variable *SrcGPRHi, *SrcGPRLo; | 1594 Variable *SrcGPRHi, *SrcGPRLo; |
1588 // SrcR could be $zero which is i32 | 1595 // SrcR could be $zero which is i32 |
1589 if (SRegNum == RegMIPS32::Reg_ZERO) { | 1596 if (SRegNum == RegMIPS32::Reg_ZERO) { |
1590 SrcGPRHi = Target->makeReg(IceType_i32, SRegNum); | 1597 SrcGPRHi = Target->makeReg(IceType_i32, SRegNum); |
1591 SrcGPRLo = SrcGPRHi; | 1598 SrcGPRLo = SrcGPRHi; |
1592 } else { | 1599 } else { |
1593 // Split it into two mtc1 instructions | 1600 // Split it into two mtc1 instructions |
1594 SrcGPRHi = Target->makeReg( | 1601 if (MovInstr->getSrcSize() == 2) { |
1595 IceType_i32, RegMIPS32::get64PairFirstRegNum(SRegNum)); | 1602 const auto FirstReg = |
1596 SrcGPRLo = Target->makeReg( | 1603 (llvm::cast<Variable>(MovInstr->getSrc(0)))->getRegNum(); |
1597 IceType_i32, RegMIPS32::get64PairSecondRegNum(SRegNum)); | 1604 const auto SecondReg = |
| 1605 (llvm::cast<Variable>(MovInstr->getSrc(1)))->getRegNum(); |
| 1606 SrcGPRHi = Target->makeReg(IceType_i32, FirstReg); |
| 1607 SrcGPRLo = Target->makeReg(IceType_i32, SecondReg); |
| 1608 } else { |
| 1609 SrcGPRHi = Target->makeReg( |
| 1610 IceType_i32, RegMIPS32::get64PairFirstRegNum(SRegNum)); |
| 1611 SrcGPRLo = Target->makeReg( |
| 1612 IceType_i32, RegMIPS32::get64PairSecondRegNum(SRegNum)); |
| 1613 } |
1598 } | 1614 } |
1599 Variable *DstFPRHi = Target->makeReg( | 1615 Variable *DstFPRHi = Target->makeReg( |
1600 IceType_f32, RegMIPS32::get64PairFirstRegNum(DRegNum)); | 1616 IceType_f32, RegMIPS32::get64PairFirstRegNum(DRegNum)); |
1601 Variable *DstFPRLo = Target->makeReg( | 1617 Variable *DstFPRLo = Target->makeReg( |
1602 IceType_f32, RegMIPS32::get64PairSecondRegNum(DRegNum)); | 1618 IceType_f32, RegMIPS32::get64PairSecondRegNum(DRegNum)); |
1603 Target->_mov(DstFPRHi, SrcGPRLo); | 1619 Target->_mov(DstFPRHi, SrcGPRLo); |
1604 Target->_mov(DstFPRLo, SrcGPRHi); | 1620 Target->_mov(DstFPRLo, SrcGPRHi); |
1605 Legalized = true; | 1621 Legalized = true; |
1606 } else { | 1622 } else { |
1607 Variable *SrcGPR = Target->makeReg(IceType_i32, SRegNum); | 1623 Variable *SrcGPR = Target->makeReg(IceType_i32, SRegNum); |
1608 Variable *DstFPR = Target->makeReg(IceType_f32, DRegNum); | 1624 Variable *DstFPR = Target->makeReg(IceType_f32, DRegNum); |
1609 Target->_mov(DstFPR, SrcGPR); | 1625 Target->_mov(DstFPR, SrcGPR); |
1610 Legalized = true; | 1626 Legalized = true; |
1611 } | 1627 } |
1612 } | 1628 } |
1613 } | 1629 } |
1614 if (Legalized) { | 1630 if (Legalized) { |
1615 if (MovInstr->isDestRedefined()) { | 1631 if (MovInstr->isDestRedefined()) { |
1616 Target->_set_dest_redefined(); | 1632 Target->_set_dest_redefined(); |
1617 } | 1633 } |
1618 MovInstr->setDeleted(); | 1634 MovInstr->setDeleted(); |
1619 return; | 1635 return; |
1620 } | 1636 } |
1621 } | 1637 } |
1622 | 1638 |
1623 if (!Dest->hasReg()) { | 1639 if (!Dest->hasReg()) { |
1624 auto *SrcR = llvm::cast<Variable>(Src); | 1640 auto *SrcR = llvm::cast<Variable>(Src); |
1625 assert(SrcR->hasReg()); | 1641 assert(SrcR->hasReg()); |
1626 assert(!SrcR->isRematerializable()); | 1642 assert(!SrcR->isRematerializable()); |
1627 const int32_t Offset = Dest->getStackOffset(); | 1643 int32_t Offset = 0; |
| 1644 |
| 1645 if (MovInstr->getDestHi() != nullptr) |
| 1646 Offset = MovInstr->getDestHi()->getStackOffset(); |
| 1647 else |
| 1648 Offset = Dest->getStackOffset(); |
1628 | 1649 |
1629 // This is a _mov(Mem(), Variable), i.e., a store. | 1650 // This is a _mov(Mem(), Variable), i.e., a store. |
1630 auto *Base = Target->getPhysicalRegister(Target->getFrameOrStackReg()); | 1651 auto *Base = Target->getPhysicalRegister(Target->getFrameOrStackReg()); |
1631 | 1652 |
1632 OperandMIPS32Mem *Addr = OperandMIPS32Mem::create( | 1653 OperandMIPS32Mem *Addr = OperandMIPS32Mem::create( |
1633 Target->Func, DestTy, Base, | 1654 Target->Func, DestTy, Base, |
1634 llvm::cast<ConstantInteger32>(Target->Ctx->getConstantInt32(Offset))); | 1655 llvm::cast<ConstantInteger32>(Target->Ctx->getConstantInt32(Offset))); |
1635 | 1656 |
1636 // FP arguments are passed in GP reg if first argument is in GP. In this | 1657 // FP arguments are passed in GP reg if first argument is in GP. In this |
1637 // case type of the SrcR is still FP thus we need to explicitly generate sw | 1658 // case type of the SrcR is still FP thus we need to explicitly generate sw |
1638 // instead of swc1. | 1659 // instead of swc1. |
1639 const RegNumT RegNum = SrcR->getRegNum(); | 1660 const RegNumT RegNum = SrcR->getRegNum(); |
1640 const bool IsSrcGPReg = RegMIPS32::isGPRReg(SrcR->getRegNum()); | 1661 const bool IsSrcGPReg = RegMIPS32::isGPRReg(SrcR->getRegNum()); |
1641 if (SrcTy == IceType_f32 && IsSrcGPReg == true) { | 1662 if (SrcTy == IceType_f32 && IsSrcGPReg) { |
1642 Variable *SrcGPR = Target->makeReg(IceType_i32, RegNum); | 1663 Variable *SrcGPR = Target->makeReg(IceType_i32, RegNum); |
1643 Target->_sw(SrcGPR, Addr); | 1664 Target->_sw(SrcGPR, Addr); |
1644 } else if (SrcTy == IceType_f64 && IsSrcGPReg == true) { | 1665 } else if (SrcTy == IceType_f64 && IsSrcGPReg) { |
1645 Variable *SrcGPRHi = | 1666 Variable *SrcGPRHi = |
1646 Target->makeReg(IceType_i32, RegMIPS32::get64PairFirstRegNum(RegNum)); | 1667 Target->makeReg(IceType_i32, RegMIPS32::get64PairFirstRegNum(RegNum)); |
1647 Variable *SrcGPRLo = Target->makeReg( | 1668 Variable *SrcGPRLo = Target->makeReg( |
1648 IceType_i32, RegMIPS32::get64PairSecondRegNum(RegNum)); | 1669 IceType_i32, RegMIPS32::get64PairSecondRegNum(RegNum)); |
1649 OperandMIPS32Mem *AddrHi = OperandMIPS32Mem::create( | 1670 OperandMIPS32Mem *AddrHi = OperandMIPS32Mem::create( |
1650 Target->Func, DestTy, Base, | 1671 Target->Func, DestTy, Base, |
1651 llvm::cast<ConstantInteger32>( | 1672 llvm::cast<ConstantInteger32>( |
1652 Target->Ctx->getConstantInt32(Offset + 4))); | 1673 Target->Ctx->getConstantInt32(Offset + 4))); |
1653 Target->_sw(SrcGPRLo, Addr); | 1674 Target->_sw(SrcGPRLo, Addr); |
1654 Target->_sw(SrcGPRHi, AddrHi); | 1675 Target->_sw(SrcGPRHi, AddrHi); |
| 1676 } else if (DestTy == IceType_f64 && IsSrcGPReg) { |
| 1677 const auto FirstReg = |
| 1678 (llvm::cast<Variable>(MovInstr->getSrc(0)))->getRegNum(); |
| 1679 const auto SecondReg = |
| 1680 (llvm::cast<Variable>(MovInstr->getSrc(1)))->getRegNum(); |
| 1681 Variable *SrcGPRHi = Target->makeReg(IceType_i32, SecondReg); |
| 1682 Variable *SrcGPRLo = Target->makeReg(IceType_i32, FirstReg); |
| 1683 OperandMIPS32Mem *AddrHi = OperandMIPS32Mem::create( |
| 1684 Target->Func, DestTy, Base, |
| 1685 llvm::cast<ConstantInteger32>( |
| 1686 Target->Ctx->getConstantInt32(Offset + 4))); |
| 1687 Target->_sw(SrcGPRLo, Addr); |
| 1688 Target->_sw(SrcGPRHi, AddrHi); |
1655 } else { | 1689 } else { |
1656 Target->_sw(SrcR, Addr); | 1690 Target->_sw(SrcR, Addr); |
1657 } | 1691 } |
1658 | 1692 |
1659 Target->Context.insert<InstFakeDef>(Dest); | 1693 Target->Context.insert<InstFakeDef>(Dest); |
1660 Legalized = true; | 1694 Legalized = true; |
1661 } else if (auto *Var = llvm::dyn_cast<Variable>(Src)) { | 1695 } else if (auto *Var = llvm::dyn_cast<Variable>(Src)) { |
1662 if (Var->isRematerializable()) { | 1696 if (Var->isRematerializable()) { |
1663 // This is equivalent to an x86 _lea(RematOffset(%esp/%ebp), Variable). | 1697 // This is equivalent to an x86 _lea(RematOffset(%esp/%ebp), Variable). |
1664 | 1698 |
(...skipping 1440 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3105 case IceType_i8: | 3139 case IceType_i8: |
3106 assert(Src0->getType() == IceType_v8i1); | 3140 assert(Src0->getType() == IceType_v8i1); |
3107 llvm::report_fatal_error( | 3141 llvm::report_fatal_error( |
3108 "i8 to v8i1 conversion should have been prelowered."); | 3142 "i8 to v8i1 conversion should have been prelowered."); |
3109 break; | 3143 break; |
3110 case IceType_i16: | 3144 case IceType_i16: |
3111 assert(Src0->getType() == IceType_v16i1); | 3145 assert(Src0->getType() == IceType_v16i1); |
3112 llvm::report_fatal_error( | 3146 llvm::report_fatal_error( |
3113 "i16 to v16i1 conversion should have been prelowered."); | 3147 "i16 to v16i1 conversion should have been prelowered."); |
3114 break; | 3148 break; |
| 3149 case IceType_i32: |
| 3150 case IceType_f32: { |
| 3151 Variable *Src0R = legalizeToReg(Src0); |
| 3152 _mov(Dest, Src0R); |
| 3153 break; |
| 3154 } |
| 3155 case IceType_i64: { |
| 3156 assert(Src0->getType() == IceType_f64); |
| 3157 Variable *Src0R = legalizeToReg(Src0); |
| 3158 auto *Dest64 = llvm::cast<Variable64On32>(Dest); |
| 3159 _mov(Dest64, Src0R); |
| 3160 break; |
| 3161 } |
| 3162 case IceType_f64: { |
| 3163 assert(Src0->getType() == IceType_i64); |
| 3164 const uint32_t Mask = 0xFFFFFFFF; |
| 3165 if (auto *C64 = llvm::dyn_cast<ConstantInteger64>(Src0)) { |
| 3166 Variable *RegHi, *RegLo; |
| 3167 const uint64_t Value = C64->getValue(); |
| 3168 uint64_t Upper32Bits = (Value >> INT32_BITS) & Mask; |
| 3169 uint64_t Lower32Bits = Value & Mask; |
| 3170 RegLo = legalizeToReg(Ctx->getConstantInt32(Lower32Bits)); |
| 3171 RegHi = legalizeToReg(Ctx->getConstantInt32(Upper32Bits)); |
| 3172 _mov(Dest, RegHi, RegLo); |
| 3173 } else { |
| 3174 auto *Var64On32 = llvm::cast<Variable64On32>(Src0); |
| 3175 auto *RegLo = legalizeToReg(loOperand(Var64On32)); |
| 3176 auto *RegHi = legalizeToReg(hiOperand(Var64On32)); |
| 3177 _mov(Dest, RegHi, RegLo); |
| 3178 } |
| 3179 break; |
| 3180 } |
3115 case IceType_v8i1: | 3181 case IceType_v8i1: |
3116 assert(Src0->getType() == IceType_i8); | 3182 assert(Src0->getType() == IceType_i8); |
3117 llvm::report_fatal_error( | 3183 llvm::report_fatal_error( |
3118 "v8i1 to i8 conversion should have been prelowered."); | 3184 "v8i1 to i8 conversion should have been prelowered."); |
3119 break; | 3185 break; |
3120 case IceType_v16i1: | 3186 case IceType_v16i1: |
3121 assert(Src0->getType() == IceType_i16); | 3187 assert(Src0->getType() == IceType_i16); |
3122 llvm::report_fatal_error( | 3188 llvm::report_fatal_error( |
3123 "v16i1 to i16 conversion should have been prelowered."); | 3189 "v16i1 to i16 conversion should have been prelowered."); |
3124 break; | 3190 break; |
(...skipping 1809 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4934 Str << "\t.set\t" | 5000 Str << "\t.set\t" |
4935 << "nomips16\n"; | 5001 << "nomips16\n"; |
4936 } | 5002 } |
4937 | 5003 |
4938 SmallBitVector TargetMIPS32::TypeToRegisterSet[RCMIPS32_NUM]; | 5004 SmallBitVector TargetMIPS32::TypeToRegisterSet[RCMIPS32_NUM]; |
4939 SmallBitVector TargetMIPS32::TypeToRegisterSetUnfiltered[RCMIPS32_NUM]; | 5005 SmallBitVector TargetMIPS32::TypeToRegisterSetUnfiltered[RCMIPS32_NUM]; |
4940 SmallBitVector TargetMIPS32::RegisterAliases[RegMIPS32::Reg_NUM]; | 5006 SmallBitVector TargetMIPS32::RegisterAliases[RegMIPS32::Reg_NUM]; |
4941 | 5007 |
4942 } // end of namespace MIPS32 | 5008 } // end of namespace MIPS32 |
4943 } // end of namespace Ice | 5009 } // end of namespace Ice |
OLD | NEW |