| OLD | NEW |
| 1 //===- subzero/src/IceTargetLoweringX8632.cpp - x86-32 lowering -----------===// | 1 //===- subzero/src/IceTargetLoweringX8632.cpp - x86-32 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 // This file implements the TargetLoweringX8632 class, which | 10 // This file implements the TargetLoweringX8632 class, which |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 80 const size_t TableIcmp64Size = llvm::array_lengthof(TableIcmp64); | 80 const size_t TableIcmp64Size = llvm::array_lengthof(TableIcmp64); |
| 81 | 81 |
| 82 InstX8632::BrCond getIcmp32Mapping(InstIcmp::ICond Cond) { | 82 InstX8632::BrCond getIcmp32Mapping(InstIcmp::ICond Cond) { |
| 83 size_t Index = static_cast<size_t>(Cond); | 83 size_t Index = static_cast<size_t>(Cond); |
| 84 assert(Index < TableIcmp32Size); | 84 assert(Index < TableIcmp32Size); |
| 85 return TableIcmp32[Index].Mapping; | 85 return TableIcmp32[Index].Mapping; |
| 86 } | 86 } |
| 87 | 87 |
| 88 // The maximum number of arguments to pass in XMM registers | 88 // The maximum number of arguments to pass in XMM registers |
| 89 const unsigned X86_MAX_XMM_ARGS = 4; | 89 const unsigned X86_MAX_XMM_ARGS = 4; |
| 90 // The number of bits in a byte |
| 91 const unsigned X86_CHAR_BIT = 8; |
| 90 | 92 |
| 91 // In some cases, there are x-macros tables for both high-level and | 93 // In some cases, there are x-macros tables for both high-level and |
| 92 // low-level instructions/operands that use the same enum key value. | 94 // low-level instructions/operands that use the same enum key value. |
| 93 // The tables are kept separate to maintain a proper separation | 95 // The tables are kept separate to maintain a proper separation |
| 94 // between abstraction layers. There is a risk that the tables | 96 // between abstraction layers. There is a risk that the tables |
| 95 // could get out of sync if enum values are reordered or if entries | 97 // could get out of sync if enum values are reordered or if entries |
| 96 // are added or deleted. This dummy function uses static_assert to | 98 // are added or deleted. This dummy function uses static_assert to |
| 97 // ensure everything is kept in sync. | 99 // ensure everything is kept in sync. |
| 98 void xMacroIntegrityCheck() { | 100 void xMacroIntegrityCheck() { |
| 99 // Validate the enum values in FCMPX8632_TABLE. | 101 // Validate the enum values in FCMPX8632_TABLE. |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 150 #define X(tag, str) STATIC_ASSERT(_table1_##tag == _table2_##tag); | 152 #define X(tag, str) STATIC_ASSERT(_table1_##tag == _table2_##tag); |
| 151 ICEINSTICMP_TABLE; | 153 ICEINSTICMP_TABLE; |
| 152 #undef X | 154 #undef X |
| 153 } | 155 } |
| 154 | 156 |
| 155 // Validate the enum values in ICETYPEX8632_TABLE. | 157 // Validate the enum values in ICETYPEX8632_TABLE. |
| 156 { | 158 { |
| 157 // Define a temporary set of enum values based on low-level | 159 // Define a temporary set of enum values based on low-level |
| 158 // table entries. | 160 // table entries. |
| 159 enum _tmp_enum { | 161 enum _tmp_enum { |
| 160 #define X(tag, cvt, sdss, width) _tmp_##tag, | 162 #define X(tag, cvt, sdss, pack, width) _tmp_##tag, |
| 161 ICETYPEX8632_TABLE | 163 ICETYPEX8632_TABLE |
| 162 #undef X | 164 #undef X |
| 163 _num | 165 _num |
| 164 }; | 166 }; |
| 165 // Define a set of constants based on high-level table entries. | 167 // Define a set of constants based on high-level table entries. |
| 166 #define X(tag, size, align, elts, elty, str) \ | 168 #define X(tag, size, align, elts, elty, str) \ |
| 167 static const int _table1_##tag = tag; | 169 static const int _table1_##tag = tag; |
| 168 ICETYPE_TABLE; | 170 ICETYPE_TABLE; |
| 169 #undef X | 171 #undef X |
| 170 // Define a set of constants based on low-level table entries, | 172 // Define a set of constants based on low-level table entries, |
| 171 // and ensure the table entry keys are consistent. | 173 // and ensure the table entry keys are consistent. |
| 172 #define X(tag, cvt, sdss, width) \ | 174 #define X(tag, cvt, sdss, pack, width) \ |
| 173 static const int _table2_##tag = _tmp_##tag; \ | 175 static const int _table2_##tag = _tmp_##tag; \ |
| 174 STATIC_ASSERT(_table1_##tag == _table2_##tag); | 176 STATIC_ASSERT(_table1_##tag == _table2_##tag); |
| 175 ICETYPEX8632_TABLE; | 177 ICETYPEX8632_TABLE; |
| 176 #undef X | 178 #undef X |
| 177 // Repeat the static asserts with respect to the high-level | 179 // Repeat the static asserts with respect to the high-level |
| 178 // table entries in case the high-level table has extra entries. | 180 // table entries in case the high-level table has extra entries. |
| 179 #define X(tag, size, align, elts, elty, str) \ | 181 #define X(tag, size, align, elts, elty, str) \ |
| 180 STATIC_ASSERT(_table1_##tag == _table2_##tag); | 182 STATIC_ASSERT(_table1_##tag == _table2_##tag); |
| 181 ICETYPE_TABLE; | 183 ICETYPE_TABLE; |
| 182 #undef X | 184 #undef X |
| (...skipping 1383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1566 if (Src0RM->getType() == IceType_i32) | 1568 if (Src0RM->getType() == IceType_i32) |
| 1567 _mov(T_Lo, Src0RM); | 1569 _mov(T_Lo, Src0RM); |
| 1568 else | 1570 else |
| 1569 _movsx(T_Lo, Src0RM); | 1571 _movsx(T_Lo, Src0RM); |
| 1570 _mov(DestLo, T_Lo); | 1572 _mov(DestLo, T_Lo); |
| 1571 Variable *T_Hi = NULL; | 1573 Variable *T_Hi = NULL; |
| 1572 Constant *Shift = Ctx->getConstantInt(IceType_i32, 31); | 1574 Constant *Shift = Ctx->getConstantInt(IceType_i32, 31); |
| 1573 _mov(T_Hi, T_Lo); | 1575 _mov(T_Hi, T_Lo); |
| 1574 _sar(T_Hi, Shift); | 1576 _sar(T_Hi, Shift); |
| 1575 _mov(DestHi, T_Hi); | 1577 _mov(DestHi, T_Hi); |
| 1578 } else if (isVectorType(Dest->getType())) { |
| 1579 Type DestTy = Dest->getType(); |
| 1580 if (DestTy == IceType_v16i8) { |
| 1581 // onemask = materialize(1,1,...); dst = (src & onemask) > 0 |
| 1582 Variable *OneMask = makeVectorOfOnes(Dest->getType()); |
| 1583 Variable *T = makeReg(DestTy); |
| 1584 _movp(T, Src0RM); |
| 1585 _pand(T, OneMask); |
| 1586 Variable *Zeros = makeVectorOfZeros(Dest->getType()); |
| 1587 _pcmpgt(T, Zeros); |
| 1588 _movp(Dest, T); |
| 1589 } else { |
| 1590 // width = width(elty) - 1; dest = (src << width) >> width |
| 1591 SizeT ShiftAmount = |
| 1592 X86_CHAR_BIT * typeWidthInBytes(typeElementType(DestTy)) - 1; |
| 1593 Constant *ShiftConstant = Ctx->getConstantInt(IceType_i8, ShiftAmount); |
| 1594 Variable *T = makeReg(DestTy); |
| 1595 _movp(T, Src0RM); |
| 1596 _psll(T, ShiftConstant); |
| 1597 _psra(T, ShiftConstant); |
| 1598 _movp(Dest, T); |
| 1599 } |
| 1576 } else { | 1600 } else { |
| 1577 // TODO: Sign-extend an i1 via "shl reg, 31; sar reg, 31", and | 1601 // TODO: Sign-extend an i1 via "shl reg, 31; sar reg, 31", and |
| 1578 // also copy to the high operand of a 64-bit variable. | 1602 // also copy to the high operand of a 64-bit variable. |
| 1579 // t1 = movsx src; dst = t1 | 1603 // t1 = movsx src; dst = t1 |
| 1580 Variable *T = makeReg(Dest->getType()); | 1604 Variable *T = makeReg(Dest->getType()); |
| 1581 _movsx(T, Src0RM); | 1605 _movsx(T, Src0RM); |
| 1582 _mov(Dest, T); | 1606 _mov(Dest, T); |
| 1583 } | 1607 } |
| 1584 break; | 1608 break; |
| 1585 } | 1609 } |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1597 _movzx(Tmp, Src0RM); | 1621 _movzx(Tmp, Src0RM); |
| 1598 _mov(DestLo, Tmp); | 1622 _mov(DestLo, Tmp); |
| 1599 _mov(DestHi, Zero); | 1623 _mov(DestHi, Zero); |
| 1600 } else if (Src0RM->getType() == IceType_i1) { | 1624 } else if (Src0RM->getType() == IceType_i1) { |
| 1601 // t = Src0RM; t &= 1; Dest = t | 1625 // t = Src0RM; t &= 1; Dest = t |
| 1602 Operand *One = Ctx->getConstantInt(IceType_i32, 1); | 1626 Operand *One = Ctx->getConstantInt(IceType_i32, 1); |
| 1603 Variable *T = makeReg(IceType_i32); | 1627 Variable *T = makeReg(IceType_i32); |
| 1604 _movzx(T, Src0RM); | 1628 _movzx(T, Src0RM); |
| 1605 _and(T, One); | 1629 _and(T, One); |
| 1606 _mov(Dest, T); | 1630 _mov(Dest, T); |
| 1631 } else if (isVectorType(Dest->getType())) { |
| 1632 // onemask = materialize(1,1,...); dest = onemask & src |
| 1633 Type DestTy = Dest->getType(); |
| 1634 Variable *OneMask = makeVectorOfOnes(DestTy); |
| 1635 Variable *T = makeReg(DestTy); |
| 1636 _movp(T, Src0RM); |
| 1637 _pand(T, OneMask); |
| 1638 _movp(Dest, T); |
| 1607 } else { | 1639 } else { |
| 1608 // t1 = movzx src; dst = t1 | 1640 // t1 = movzx src; dst = t1 |
| 1609 Variable *T = makeReg(Dest->getType()); | 1641 Variable *T = makeReg(Dest->getType()); |
| 1610 _movzx(T, Src0RM); | 1642 _movzx(T, Src0RM); |
| 1611 _mov(Dest, T); | 1643 _mov(Dest, T); |
| 1612 } | 1644 } |
| 1613 break; | 1645 break; |
| 1614 } | 1646 } |
| 1615 case InstCast::Trunc: { | 1647 case InstCast::Trunc: { |
| 1616 Operand *Src0 = Inst->getSrc(0); | 1648 if (isVectorType(Dest->getType())) { |
| 1617 if (Src0->getType() == IceType_i64) | 1649 // onemask = materialize(1,1,...); dst = src & onemask |
| 1618 Src0 = loOperand(Src0); | 1650 Operand *Src0RM = legalize(Inst->getSrc(0), Legal_Reg | Legal_Mem); |
| 1619 Operand *Src0RM = legalize(Src0, Legal_Reg | Legal_Mem); | 1651 Type Src0Ty = Src0RM->getType(); |
| 1620 // t1 = trunc Src0RM; Dest = t1 | 1652 Variable *OneMask = makeVectorOfOnes(Src0Ty); |
| 1621 Variable *T = NULL; | 1653 Variable *T = makeReg(Dest->getType()); |
| 1622 _mov(T, Src0RM); | 1654 _movp(T, Src0RM); |
| 1623 _mov(Dest, T); | 1655 _pand(T, OneMask); |
| 1656 _movp(Dest, T); |
| 1657 } else { |
| 1658 Operand *Src0 = Inst->getSrc(0); |
| 1659 if (Src0->getType() == IceType_i64) |
| 1660 Src0 = loOperand(Src0); |
| 1661 Operand *Src0RM = legalize(Src0, Legal_Reg | Legal_Mem); |
| 1662 // t1 = trunc Src0RM; Dest = t1 |
| 1663 Variable *T = NULL; |
| 1664 _mov(T, Src0RM); |
| 1665 _mov(Dest, T); |
| 1666 } |
| 1624 break; | 1667 break; |
| 1625 } | 1668 } |
| 1626 case InstCast::Fptrunc: | 1669 case InstCast::Fptrunc: |
| 1627 case InstCast::Fpext: { | 1670 case InstCast::Fpext: { |
| 1628 Operand *Src0RM = legalize(Inst->getSrc(0), Legal_Reg | Legal_Mem); | 1671 Operand *Src0RM = legalize(Inst->getSrc(0), Legal_Reg | Legal_Mem); |
| 1629 // t1 = cvt Src0RM; Dest = t1 | 1672 // t1 = cvt Src0RM; Dest = t1 |
| 1630 Variable *T = makeReg(Dest->getType()); | 1673 Variable *T = makeReg(Dest->getType()); |
| 1631 _cvt(T, Src0RM); | 1674 _cvt(T, Src0RM); |
| 1632 _mov(Dest, T); | 1675 _mov(Dest, T); |
| 1633 break; | 1676 break; |
| 1634 } | 1677 } |
| 1635 case InstCast::Fptosi: | 1678 case InstCast::Fptosi: |
| 1636 if (Dest->getType() == IceType_i64) { | 1679 if (isVectorType(Dest->getType())) { |
| 1680 assert(Dest->getType() == IceType_v4i32 && |
| 1681 Inst->getSrc(0)->getType() == IceType_v4f32); |
| 1682 Operand *Src0RM = legalize(Inst->getSrc(0), Legal_Reg | Legal_Mem); |
| 1683 Variable *T = makeReg(Dest->getType()); |
| 1684 _cvt(T, Src0RM); |
| 1685 _movp(Dest, T); |
| 1686 } else if (Dest->getType() == IceType_i64) { |
| 1637 // Use a helper for converting floating-point values to 64-bit | 1687 // Use a helper for converting floating-point values to 64-bit |
| 1638 // integers. SSE2 appears to have no way to convert from xmm | 1688 // integers. SSE2 appears to have no way to convert from xmm |
| 1639 // registers to something like the edx:eax register pair, and | 1689 // registers to something like the edx:eax register pair, and |
| 1640 // gcc and clang both want to use x87 instructions complete with | 1690 // gcc and clang both want to use x87 instructions complete with |
| 1641 // temporary manipulation of the status word. This helper is | 1691 // temporary manipulation of the status word. This helper is |
| 1642 // not needed for x86-64. | 1692 // not needed for x86-64. |
| 1643 split64(Dest); | 1693 split64(Dest); |
| 1644 const SizeT MaxSrcs = 1; | 1694 const SizeT MaxSrcs = 1; |
| 1645 Type SrcType = Inst->getSrc(0)->getType(); | 1695 Type SrcType = Inst->getSrc(0)->getType(); |
| 1646 InstCall *Call = makeHelperCall( | 1696 InstCall *Call = makeHelperCall( |
| 1647 SrcType == IceType_f32 ? "cvtftosi64" : "cvtdtosi64", Dest, MaxSrcs); | 1697 SrcType == IceType_f32 ? "cvtftosi64" : "cvtdtosi64", Dest, MaxSrcs); |
| 1648 // TODO: Call the correct compiler-rt helper function. | 1698 // TODO: Call the correct compiler-rt helper function. |
| 1649 Call->addArg(Inst->getSrc(0)); | 1699 Call->addArg(Inst->getSrc(0)); |
| 1650 lowerCall(Call); | 1700 lowerCall(Call); |
| 1651 } else { | 1701 } else { |
| 1652 Operand *Src0RM = legalize(Inst->getSrc(0), Legal_Reg | Legal_Mem); | 1702 Operand *Src0RM = legalize(Inst->getSrc(0), Legal_Reg | Legal_Mem); |
| 1653 // t1.i32 = cvt Src0RM; t2.dest_type = t1; Dest = t2.dest_type | 1703 // t1.i32 = cvt Src0RM; t2.dest_type = t1; Dest = t2.dest_type |
| 1654 Variable *T_1 = makeReg(IceType_i32); | 1704 Variable *T_1 = makeReg(IceType_i32); |
| 1655 Variable *T_2 = makeReg(Dest->getType()); | 1705 Variable *T_2 = makeReg(Dest->getType()); |
| 1656 _cvt(T_1, Src0RM); | 1706 _cvt(T_1, Src0RM); |
| 1657 _mov(T_2, T_1); // T_1 and T_2 may have different integer types | 1707 _mov(T_2, T_1); // T_1 and T_2 may have different integer types |
| 1658 _mov(Dest, T_2); | 1708 _mov(Dest, T_2); |
| 1659 T_2->setPreferredRegister(T_1, true); | 1709 T_2->setPreferredRegister(T_1, true); |
| 1660 } | 1710 } |
| 1661 break; | 1711 break; |
| 1662 case InstCast::Fptoui: | 1712 case InstCast::Fptoui: |
| 1663 if (Dest->getType() == IceType_i64 || Dest->getType() == IceType_i32) { | 1713 if (isVectorType(Dest->getType())) { |
| 1714 assert(Dest->getType() == IceType_v4i32 && |
| 1715 Inst->getSrc(0)->getType() == IceType_v4f32); |
| 1716 const SizeT MaxSrcs = 1; |
| 1717 InstCall *Call = makeHelperCall("Sz_fptoui_v4f32", Dest, MaxSrcs); |
| 1718 Call->addArg(Inst->getSrc(0)); |
| 1719 lowerCall(Call); |
| 1720 } else if (Dest->getType() == IceType_i64 || |
| 1721 Dest->getType() == IceType_i32) { |
| 1664 // Use a helper for both x86-32 and x86-64. | 1722 // Use a helper for both x86-32 and x86-64. |
| 1665 split64(Dest); | 1723 split64(Dest); |
| 1666 const SizeT MaxSrcs = 1; | 1724 const SizeT MaxSrcs = 1; |
| 1667 Type DestType = Dest->getType(); | 1725 Type DestType = Dest->getType(); |
| 1668 Type SrcType = Inst->getSrc(0)->getType(); | 1726 Type SrcType = Inst->getSrc(0)->getType(); |
| 1669 IceString DstSubstring = (DestType == IceType_i64 ? "64" : "32"); | 1727 IceString DstSubstring = (DestType == IceType_i64 ? "64" : "32"); |
| 1670 IceString SrcSubstring = (SrcType == IceType_f32 ? "f" : "d"); | 1728 IceString SrcSubstring = (SrcType == IceType_f32 ? "f" : "d"); |
| 1671 // Possibilities are cvtftoui32, cvtdtoui32, cvtftoui64, cvtdtoui64 | 1729 // Possibilities are cvtftoui32, cvtdtoui32, cvtftoui64, cvtdtoui64 |
| 1672 IceString TargetString = "cvt" + SrcSubstring + "toui" + DstSubstring; | 1730 IceString TargetString = "cvt" + SrcSubstring + "toui" + DstSubstring; |
| 1673 // TODO: Call the correct compiler-rt helper function. | 1731 // TODO: Call the correct compiler-rt helper function. |
| 1674 InstCall *Call = makeHelperCall(TargetString, Dest, MaxSrcs); | 1732 InstCall *Call = makeHelperCall(TargetString, Dest, MaxSrcs); |
| 1675 Call->addArg(Inst->getSrc(0)); | 1733 Call->addArg(Inst->getSrc(0)); |
| 1676 lowerCall(Call); | 1734 lowerCall(Call); |
| 1677 return; | 1735 return; |
| 1678 } else { | 1736 } else { |
| 1679 Operand *Src0RM = legalize(Inst->getSrc(0), Legal_Reg | Legal_Mem); | 1737 Operand *Src0RM = legalize(Inst->getSrc(0), Legal_Reg | Legal_Mem); |
| 1680 // t1.i32 = cvt Src0RM; t2.dest_type = t1; Dest = t2.dest_type | 1738 // t1.i32 = cvt Src0RM; t2.dest_type = t1; Dest = t2.dest_type |
| 1681 Variable *T_1 = makeReg(IceType_i32); | 1739 Variable *T_1 = makeReg(IceType_i32); |
| 1682 Variable *T_2 = makeReg(Dest->getType()); | 1740 Variable *T_2 = makeReg(Dest->getType()); |
| 1683 _cvt(T_1, Src0RM); | 1741 _cvt(T_1, Src0RM); |
| 1684 _mov(T_2, T_1); // T_1 and T_2 may have different integer types | 1742 _mov(T_2, T_1); // T_1 and T_2 may have different integer types |
| 1685 _mov(Dest, T_2); | 1743 _mov(Dest, T_2); |
| 1686 T_2->setPreferredRegister(T_1, true); | 1744 T_2->setPreferredRegister(T_1, true); |
| 1687 } | 1745 } |
| 1688 break; | 1746 break; |
| 1689 case InstCast::Sitofp: | 1747 case InstCast::Sitofp: |
| 1690 if (Inst->getSrc(0)->getType() == IceType_i64) { | 1748 if (isVectorType(Dest->getType())) { |
| 1749 assert(Dest->getType() == IceType_v4f32 && |
| 1750 Inst->getSrc(0)->getType() == IceType_v4i32); |
| 1751 Operand *Src0RM = legalize(Inst->getSrc(0), Legal_Reg | Legal_Mem); |
| 1752 Variable *T = makeReg(Dest->getType()); |
| 1753 _cvt(T, Src0RM); |
| 1754 _movp(Dest, T); |
| 1755 } else if (Inst->getSrc(0)->getType() == IceType_i64) { |
| 1691 // Use a helper for x86-32. | 1756 // Use a helper for x86-32. |
| 1692 const SizeT MaxSrcs = 1; | 1757 const SizeT MaxSrcs = 1; |
| 1693 Type DestType = Dest->getType(); | 1758 Type DestType = Dest->getType(); |
| 1694 InstCall *Call = makeHelperCall( | 1759 InstCall *Call = makeHelperCall( |
| 1695 DestType == IceType_f32 ? "cvtsi64tof" : "cvtsi64tod", Dest, MaxSrcs); | 1760 DestType == IceType_f32 ? "cvtsi64tof" : "cvtsi64tod", Dest, MaxSrcs); |
| 1696 // TODO: Call the correct compiler-rt helper function. | 1761 // TODO: Call the correct compiler-rt helper function. |
| 1697 Call->addArg(Inst->getSrc(0)); | 1762 Call->addArg(Inst->getSrc(0)); |
| 1698 lowerCall(Call); | 1763 lowerCall(Call); |
| 1699 return; | 1764 return; |
| 1700 } else { | 1765 } else { |
| 1701 Operand *Src0RM = legalize(Inst->getSrc(0), Legal_Reg | Legal_Mem); | 1766 Operand *Src0RM = legalize(Inst->getSrc(0), Legal_Reg | Legal_Mem); |
| 1702 // Sign-extend the operand. | 1767 // Sign-extend the operand. |
| 1703 // t1.i32 = movsx Src0RM; t2 = Cvt t1.i32; Dest = t2 | 1768 // t1.i32 = movsx Src0RM; t2 = Cvt t1.i32; Dest = t2 |
| 1704 Variable *T_1 = makeReg(IceType_i32); | 1769 Variable *T_1 = makeReg(IceType_i32); |
| 1705 Variable *T_2 = makeReg(Dest->getType()); | 1770 Variable *T_2 = makeReg(Dest->getType()); |
| 1706 if (Src0RM->getType() == IceType_i32) | 1771 if (Src0RM->getType() == IceType_i32) |
| 1707 _mov(T_1, Src0RM); | 1772 _mov(T_1, Src0RM); |
| 1708 else | 1773 else |
| 1709 _movsx(T_1, Src0RM); | 1774 _movsx(T_1, Src0RM); |
| 1710 _cvt(T_2, T_1); | 1775 _cvt(T_2, T_1); |
| 1711 _mov(Dest, T_2); | 1776 _mov(Dest, T_2); |
| 1712 } | 1777 } |
| 1713 break; | 1778 break; |
| 1714 case InstCast::Uitofp: { | 1779 case InstCast::Uitofp: { |
| 1715 Operand *Src0 = Inst->getSrc(0); | 1780 Operand *Src0 = Inst->getSrc(0); |
| 1716 if (Src0->getType() == IceType_i64 || Src0->getType() == IceType_i32) { | 1781 if (isVectorType(Src0->getType())) { |
| 1782 assert(Dest->getType() == IceType_v4f32 && |
| 1783 Src0->getType() == IceType_v4i32); |
| 1784 const SizeT MaxSrcs = 1; |
| 1785 InstCall *Call = makeHelperCall("Sz_uitofp_v4i32", Dest, MaxSrcs); |
| 1786 Call->addArg(Src0); |
| 1787 lowerCall(Call); |
| 1788 } else if (Src0->getType() == IceType_i64 || |
| 1789 Src0->getType() == IceType_i32) { |
| 1717 // Use a helper for x86-32 and x86-64. Also use a helper for | 1790 // Use a helper for x86-32 and x86-64. Also use a helper for |
| 1718 // i32 on x86-32. | 1791 // i32 on x86-32. |
| 1719 const SizeT MaxSrcs = 1; | 1792 const SizeT MaxSrcs = 1; |
| 1720 Type DestType = Dest->getType(); | 1793 Type DestType = Dest->getType(); |
| 1721 IceString SrcSubstring = (Src0->getType() == IceType_i64 ? "64" : "32"); | 1794 IceString SrcSubstring = (Src0->getType() == IceType_i64 ? "64" : "32"); |
| 1722 IceString DstSubstring = (DestType == IceType_f32 ? "f" : "d"); | 1795 IceString DstSubstring = (DestType == IceType_f32 ? "f" : "d"); |
| 1723 // Possibilities are cvtui32tof, cvtui32tod, cvtui64tof, cvtui64tod | 1796 // Possibilities are cvtui32tof, cvtui32tod, cvtui64tof, cvtui64tod |
| 1724 IceString TargetString = "cvtui" + SrcSubstring + "to" + DstSubstring; | 1797 IceString TargetString = "cvtui" + SrcSubstring + "to" + DstSubstring; |
| 1725 // TODO: Call the correct compiler-rt helper function. | 1798 // TODO: Call the correct compiler-rt helper function. |
| 1726 InstCall *Call = makeHelperCall(TargetString, Dest, MaxSrcs); | 1799 InstCall *Call = makeHelperCall(TargetString, Dest, MaxSrcs); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1745 case InstCast::Bitcast: { | 1818 case InstCast::Bitcast: { |
| 1746 Operand *Src0 = Inst->getSrc(0); | 1819 Operand *Src0 = Inst->getSrc(0); |
| 1747 if (Dest->getType() == Src0->getType()) { | 1820 if (Dest->getType() == Src0->getType()) { |
| 1748 InstAssign *Assign = InstAssign::create(Func, Dest, Src0); | 1821 InstAssign *Assign = InstAssign::create(Func, Dest, Src0); |
| 1749 lowerAssign(Assign); | 1822 lowerAssign(Assign); |
| 1750 return; | 1823 return; |
| 1751 } | 1824 } |
| 1752 switch (Dest->getType()) { | 1825 switch (Dest->getType()) { |
| 1753 default: | 1826 default: |
| 1754 llvm_unreachable("Unexpected Bitcast dest type"); | 1827 llvm_unreachable("Unexpected Bitcast dest type"); |
| 1828 case IceType_i8: { |
| 1829 assert(Src0->getType() == IceType_v8i1); |
| 1830 InstCall *Call = makeHelperCall("Sz_bitcast_v8i1_to_i8", Dest, 1); |
| 1831 Call->addArg(Src0); |
| 1832 lowerCall(Call); |
| 1833 } break; |
| 1834 case IceType_i16: { |
| 1835 assert(Src0->getType() == IceType_v16i1); |
| 1836 InstCall *Call = makeHelperCall("Sz_bitcast_v16i1_to_i16", Dest, 1); |
| 1837 Call->addArg(Src0); |
| 1838 lowerCall(Call); |
| 1839 } break; |
| 1755 case IceType_i32: | 1840 case IceType_i32: |
| 1756 case IceType_f32: { | 1841 case IceType_f32: { |
| 1757 Operand *Src0RM = legalize(Src0, Legal_Reg | Legal_Mem); | 1842 Operand *Src0RM = legalize(Src0, Legal_Reg | Legal_Mem); |
| 1758 Type DestType = Dest->getType(); | 1843 Type DestType = Dest->getType(); |
| 1759 Type SrcType = Src0RM->getType(); | 1844 Type SrcType = Src0RM->getType(); |
| 1760 assert((DestType == IceType_i32 && SrcType == IceType_f32) || | 1845 assert((DestType == IceType_i32 && SrcType == IceType_f32) || |
| 1761 (DestType == IceType_f32 && SrcType == IceType_i32)); | 1846 (DestType == IceType_f32 && SrcType == IceType_i32)); |
| 1762 // a.i32 = bitcast b.f32 ==> | 1847 // a.i32 = bitcast b.f32 ==> |
| 1763 // t.f32 = b.f32 | 1848 // t.f32 = b.f32 |
| 1764 // s.f32 = spill t.f32 | 1849 // s.f32 = spill t.f32 |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1823 _mov(T_Lo, loOperand(Src0)); | 1908 _mov(T_Lo, loOperand(Src0)); |
| 1824 // Technically, the Spill is defined after the _store happens, but | 1909 // Technically, the Spill is defined after the _store happens, but |
| 1825 // SpillLo is considered a "use" of Spill so define Spill before it | 1910 // SpillLo is considered a "use" of Spill so define Spill before it |
| 1826 // is used. | 1911 // is used. |
| 1827 Context.insert(InstFakeDef::create(Func, Spill)); | 1912 Context.insert(InstFakeDef::create(Func, Spill)); |
| 1828 _store(T_Lo, SpillLo); | 1913 _store(T_Lo, SpillLo); |
| 1829 _mov(T_Hi, hiOperand(Src0)); | 1914 _mov(T_Hi, hiOperand(Src0)); |
| 1830 _store(T_Hi, SpillHi); | 1915 _store(T_Hi, SpillHi); |
| 1831 _movq(Dest, Spill); | 1916 _movq(Dest, Spill); |
| 1832 } break; | 1917 } break; |
| 1918 case IceType_v8i1: { |
| 1919 assert(Src0->getType() == IceType_i8); |
| 1920 InstCall *Call = makeHelperCall("Sz_bitcast_i8_to_v8i1", Dest, 1); |
| 1921 Variable *Src0AsI32 = Func->makeVariable(IceType_i32, Context.getNode()); |
| 1922 // Arguments to functions are required to be at least 32 bits wide. |
| 1923 lowerCast(InstCast::create(Func, InstCast::Zext, Src0AsI32, Src0)); |
| 1924 Call->addArg(Src0AsI32); |
| 1925 lowerCall(Call); |
| 1926 } break; |
| 1927 case IceType_v16i1: { |
| 1928 assert(Src0->getType() == IceType_i16); |
| 1929 InstCall *Call = makeHelperCall("Sz_bitcast_i16_to_v16i1", Dest, 1); |
| 1930 Variable *Src0AsI32 = Func->makeVariable(IceType_i32, Context.getNode()); |
| 1931 // Arguments to functions are required to be at least 32 bits wide. |
| 1932 lowerCast(InstCast::create(Func, InstCast::Zext, Src0AsI32, Src0)); |
| 1933 Call->addArg(Src0AsI32); |
| 1934 lowerCall(Call); |
| 1935 } break; |
| 1936 case IceType_v8i16: |
| 1937 case IceType_v16i8: |
| 1938 case IceType_v4i32: |
| 1939 case IceType_v4f32: { |
| 1940 _movp(Dest, legalizeToVar(Src0)); |
| 1941 } break; |
| 1833 } | 1942 } |
| 1834 break; | 1943 break; |
| 1835 } | 1944 } |
| 1836 } | 1945 } |
| 1837 } | 1946 } |
| 1838 | 1947 |
| 1839 void TargetX8632::lowerFcmp(const InstFcmp *Inst) { | 1948 void TargetX8632::lowerFcmp(const InstFcmp *Inst) { |
| 1840 Operand *Src0 = Inst->getSrc(0); | 1949 Operand *Src0 = Inst->getSrc(0); |
| 1841 Operand *Src1 = Inst->getSrc(1); | 1950 Operand *Src1 = Inst->getSrc(1); |
| 1842 Variable *Dest = Inst->getDest(); | 1951 Variable *Dest = Inst->getDest(); |
| (...skipping 1025 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2868 _br(Inst->getLabelDefault()); | 2977 _br(Inst->getLabelDefault()); |
| 2869 } | 2978 } |
| 2870 | 2979 |
| 2871 void TargetX8632::lowerUnreachable(const InstUnreachable * /*Inst*/) { | 2980 void TargetX8632::lowerUnreachable(const InstUnreachable * /*Inst*/) { |
| 2872 const SizeT MaxSrcs = 0; | 2981 const SizeT MaxSrcs = 0; |
| 2873 Variable *Dest = NULL; | 2982 Variable *Dest = NULL; |
| 2874 InstCall *Call = makeHelperCall("ice_unreachable", Dest, MaxSrcs); | 2983 InstCall *Call = makeHelperCall("ice_unreachable", Dest, MaxSrcs); |
| 2875 lowerCall(Call); | 2984 lowerCall(Call); |
| 2876 } | 2985 } |
| 2877 | 2986 |
| 2987 Variable *TargetX8632::makeVectorOfZeros(Type Ty, int32_t RegNum) { |
| 2988 // There is no support for loading or emitting vector constants, so |
| 2989 // this value is initialized using register operations. |
| 2990 Variable *Reg = makeReg(Ty, RegNum); |
| 2991 // Insert a FakeDef, since otherwise the live range of Reg might |
| 2992 // be overestimated. |
| 2993 Context.insert(InstFakeDef::create(Func, Reg)); |
| 2994 _pxor(Reg, Reg); |
| 2995 return Reg; |
| 2996 } |
| 2997 |
| 2998 Variable *TargetX8632::makeVectorOfOnes(Type Ty, int32_t RegNum) { |
| 2999 // There is no support for loading or emitting vector constants, so |
| 3000 // this value is initialized using register operations. |
| 3001 Variable *Dest = makeVectorOfZeros(Ty, RegNum); |
| 3002 Variable *MinusOne = makeReg(Ty); |
| 3003 // Insert a FakeDef so the live range of MinusOne is not overestimated. |
| 3004 Context.insert(InstFakeDef::create(Func, MinusOne)); |
| 3005 _pcmpeq(MinusOne, MinusOne); |
| 3006 _psub(Dest, MinusOne); |
| 3007 return Dest; |
| 3008 } |
| 3009 |
| 2878 // Helper for legalize() to emit the right code to lower an operand to a | 3010 // Helper for legalize() to emit the right code to lower an operand to a |
| 2879 // register of the appropriate type. | 3011 // register of the appropriate type. |
| 2880 Variable *TargetX8632::copyToReg(Operand *Src, int32_t RegNum) { | 3012 Variable *TargetX8632::copyToReg(Operand *Src, int32_t RegNum) { |
| 2881 Type Ty = Src->getType(); | 3013 Type Ty = Src->getType(); |
| 2882 Variable *Reg = makeReg(Ty, RegNum); | 3014 Variable *Reg = makeReg(Ty, RegNum); |
| 2883 if (isVectorType(Ty)) { | 3015 if (isVectorType(Ty)) { |
| 2884 _movp(Reg, Src); | 3016 _movp(Reg, Src); |
| 2885 } else { | 3017 } else { |
| 2886 _mov(Reg, Src); | 3018 _mov(Reg, Src); |
| 2887 } | 3019 } |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2930 // uninitialized register; however, using an uninitialized register | 3062 // uninitialized register; however, using an uninitialized register |
| 2931 // results in less predictable code. | 3063 // results in less predictable code. |
| 2932 // | 3064 // |
| 2933 // If in the future the implementation is changed to lower undef | 3065 // If in the future the implementation is changed to lower undef |
| 2934 // values to uninitialized registers, a FakeDef will be needed: | 3066 // values to uninitialized registers, a FakeDef will be needed: |
| 2935 // Context.insert(InstFakeDef::create(Func, Reg)); | 3067 // Context.insert(InstFakeDef::create(Func, Reg)); |
| 2936 // This is in order to ensure that the live range of Reg is not | 3068 // This is in order to ensure that the live range of Reg is not |
| 2937 // overestimated. If the constant being lowered is a 64 bit value, | 3069 // overestimated. If the constant being lowered is a 64 bit value, |
| 2938 // then the result should be split and the lo and hi components will | 3070 // then the result should be split and the lo and hi components will |
| 2939 // need to go in uninitialized registers. | 3071 // need to go in uninitialized registers. |
| 2940 | 3072 if (isVectorType(From->getType())) |
| 2941 if (isVectorType(From->getType())) { | 3073 return makeVectorOfZeros(From->getType()); |
| 2942 // There is no support for loading or emitting vector constants, so | 3074 From = Ctx->getConstantZero(From->getType()); |
| 2943 // undef values are instead initialized in registers. | |
| 2944 Variable *Reg = makeReg(From->getType(), RegNum); | |
| 2945 // Insert a FakeDef, since otherwise the live range of Reg might | |
| 2946 // be overestimated. | |
| 2947 Context.insert(InstFakeDef::create(Func, Reg)); | |
| 2948 _pxor(Reg, Reg); | |
| 2949 return Reg; | |
| 2950 } else { | |
| 2951 From = Ctx->getConstantZero(From->getType()); | |
| 2952 } | |
| 2953 } | 3075 } |
| 2954 // There should be no constants of vector type (other than undef). | 3076 // There should be no constants of vector type (other than undef). |
| 2955 assert(!isVectorType(From->getType())); | 3077 assert(!isVectorType(From->getType())); |
| 2956 bool NeedsReg = false; | 3078 bool NeedsReg = false; |
| 2957 if (!(Allowed & Legal_Imm)) | 3079 if (!(Allowed & Legal_Imm)) |
| 2958 // Immediate specifically not allowed | 3080 // Immediate specifically not allowed |
| 2959 NeedsReg = true; | 3081 NeedsReg = true; |
| 2960 // TODO(stichnot): LEAHACK: remove Legal_Reloc once a proper | 3082 // TODO(stichnot): LEAHACK: remove Legal_Reloc once a proper |
| 2961 // emitter is used. | 3083 // emitter is used. |
| 2962 if (!(Allowed & Legal_Reloc) && llvm::isa<ConstantRelocatable>(From)) | 3084 if (!(Allowed & Legal_Reloc) && llvm::isa<ConstantRelocatable>(From)) |
| (...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3199 for (SizeT i = 0; i < Size; ++i) { | 3321 for (SizeT i = 0; i < Size; ++i) { |
| 3200 Str << "\t.byte\t" << (((unsigned)Data[i]) & 0xff) << "\n"; | 3322 Str << "\t.byte\t" << (((unsigned)Data[i]) & 0xff) << "\n"; |
| 3201 } | 3323 } |
| 3202 Str << "\t.size\t" << MangledName << ", " << Size << "\n"; | 3324 Str << "\t.size\t" << MangledName << ", " << Size << "\n"; |
| 3203 } | 3325 } |
| 3204 Str << "\t" << (IsInternal ? ".local" : ".global") << "\t" << MangledName | 3326 Str << "\t" << (IsInternal ? ".local" : ".global") << "\t" << MangledName |
| 3205 << "\n"; | 3327 << "\n"; |
| 3206 } | 3328 } |
| 3207 | 3329 |
| 3208 } // end of namespace Ice | 3330 } // end of namespace Ice |
| OLD | NEW |