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 |