Chromium Code Reviews| 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 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 150 #define X(tag, str) STATIC_ASSERT(_table1_##tag == _table2_##tag); | 150 #define X(tag, str) STATIC_ASSERT(_table1_##tag == _table2_##tag); |
| 151 ICEINSTICMP_TABLE; | 151 ICEINSTICMP_TABLE; |
| 152 #undef X | 152 #undef X |
| 153 } | 153 } |
| 154 | 154 |
| 155 // Validate the enum values in ICETYPEX8632_TABLE. | 155 // Validate the enum values in ICETYPEX8632_TABLE. |
| 156 { | 156 { |
| 157 // Define a temporary set of enum values based on low-level | 157 // Define a temporary set of enum values based on low-level |
| 158 // table entries. | 158 // table entries. |
| 159 enum _tmp_enum { | 159 enum _tmp_enum { |
| 160 #define X(tag, cvt, sdss, width) _tmp_##tag, | 160 #define X(tag, cvt, sdss, pack, width) _tmp_##tag, |
| 161 ICETYPEX8632_TABLE | 161 ICETYPEX8632_TABLE |
| 162 #undef X | 162 #undef X |
| 163 _num | 163 _num |
| 164 }; | 164 }; |
| 165 // Define a set of constants based on high-level table entries. | 165 // Define a set of constants based on high-level table entries. |
| 166 #define X(tag, size, align, elts, elty, str) \ | 166 #define X(tag, size, align, elts, elty, str) \ |
| 167 static const int _table1_##tag = tag; | 167 static const int _table1_##tag = tag; |
| 168 ICETYPE_TABLE; | 168 ICETYPE_TABLE; |
| 169 #undef X | 169 #undef X |
| 170 // Define a set of constants based on low-level table entries, | 170 // Define a set of constants based on low-level table entries, |
| 171 // and ensure the table entry keys are consistent. | 171 // and ensure the table entry keys are consistent. |
| 172 #define X(tag, cvt, sdss, width) \ | 172 #define X(tag, cvt, sdss, pack, width) \ |
| 173 static const int _table2_##tag = _tmp_##tag; \ | 173 static const int _table2_##tag = _tmp_##tag; \ |
| 174 STATIC_ASSERT(_table1_##tag == _table2_##tag); | 174 STATIC_ASSERT(_table1_##tag == _table2_##tag); |
| 175 ICETYPEX8632_TABLE; | 175 ICETYPEX8632_TABLE; |
| 176 #undef X | 176 #undef X |
| 177 // Repeat the static asserts with respect to the high-level | 177 // Repeat the static asserts with respect to the high-level |
| 178 // table entries in case the high-level table has extra entries. | 178 // table entries in case the high-level table has extra entries. |
| 179 #define X(tag, size, align, elts, elty, str) \ | 179 #define X(tag, size, align, elts, elty, str) \ |
| 180 STATIC_ASSERT(_table1_##tag == _table2_##tag); | 180 STATIC_ASSERT(_table1_##tag == _table2_##tag); |
| 181 ICETYPE_TABLE; | 181 ICETYPE_TABLE; |
| 182 #undef X | 182 #undef X |
| (...skipping 1264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1447 if (ScratchRegs[i]) | 1447 if (ScratchRegs[i]) |
| 1448 KilledRegs.push_back(Func->getTarget()->getPhysicalRegister(i)); | 1448 KilledRegs.push_back(Func->getTarget()->getPhysicalRegister(i)); |
| 1449 } | 1449 } |
| 1450 Context.insert(InstFakeKill::create(Func, KilledRegs, NewCall)); | 1450 Context.insert(InstFakeKill::create(Func, KilledRegs, NewCall)); |
| 1451 | 1451 |
| 1452 // Generate a FakeUse to keep the call live if necessary. | 1452 // Generate a FakeUse to keep the call live if necessary. |
| 1453 if (Instr->hasSideEffects() && ReturnReg) { | 1453 if (Instr->hasSideEffects() && ReturnReg) { |
| 1454 Inst *FakeUse = InstFakeUse::create(Func, ReturnReg); | 1454 Inst *FakeUse = InstFakeUse::create(Func, ReturnReg); |
| 1455 Context.insert(FakeUse); | 1455 Context.insert(FakeUse); |
| 1456 } | 1456 } |
| 1457 | 1457 |
| 1458 if (!Dest) | 1458 if (!Dest) |
| 1459 return; | 1459 return; |
| 1460 | 1460 |
| 1461 // Assign the result of the call to Dest. | 1461 // Assign the result of the call to Dest. |
| 1462 if (ReturnReg) { | 1462 if (ReturnReg) { |
| 1463 if (ReturnRegHi) { | 1463 if (ReturnRegHi) { |
| 1464 assert(Dest->getType() == IceType_i64); | 1464 assert(Dest->getType() == IceType_i64); |
| 1465 split64(Dest); | 1465 split64(Dest); |
| 1466 Variable *DestLo = Dest->getLo(); | 1466 Variable *DestLo = Dest->getLo(); |
| 1467 Variable *DestHi = Dest->getHi(); | 1467 Variable *DestHi = Dest->getHi(); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1513 if (Src0RM->getType() == IceType_i32) | 1513 if (Src0RM->getType() == IceType_i32) |
| 1514 _mov(T_Lo, Src0RM); | 1514 _mov(T_Lo, Src0RM); |
| 1515 else | 1515 else |
| 1516 _movsx(T_Lo, Src0RM); | 1516 _movsx(T_Lo, Src0RM); |
| 1517 _mov(DestLo, T_Lo); | 1517 _mov(DestLo, T_Lo); |
| 1518 Variable *T_Hi = NULL; | 1518 Variable *T_Hi = NULL; |
| 1519 Constant *Shift = Ctx->getConstantInt(IceType_i32, 31); | 1519 Constant *Shift = Ctx->getConstantInt(IceType_i32, 31); |
| 1520 _mov(T_Hi, T_Lo); | 1520 _mov(T_Hi, T_Lo); |
| 1521 _sar(T_Hi, Shift); | 1521 _sar(T_Hi, Shift); |
| 1522 _mov(DestHi, T_Hi); | 1522 _mov(DestHi, T_Hi); |
| 1523 } else if (isVectorType(Dest->getType())) { | |
| 1524 Type DestTy = Dest->getType(); | |
| 1525 if (DestTy == IceType_v16i8) { | |
| 1526 // onemask = materialize(1,1,...); dst = (src & onemask) > 0 | |
| 1527 Variable *OneMask = makeReg(DestTy); | |
|
Jim Stichnoth
2014/07/14 18:33:12
Seems to be substantial code duplication across th
wala
2014/07/15 22:52:22
Done.
| |
| 1528 Context.insert(InstFakeDef::create(Func, OneMask)); | |
| 1529 _pxor(OneMask, OneMask); | |
| 1530 Variable *MinusOne = makeReg(DestTy); | |
| 1531 Context.insert(InstFakeDef::create(Func, MinusOne)); | |
| 1532 _pcmpeq(MinusOne, MinusOne); | |
| 1533 _psub(OneMask, MinusOne); | |
| 1534 Variable *T = makeReg(DestTy); | |
| 1535 _movp(T, Src0RM); | |
| 1536 _pand(T, OneMask); | |
| 1537 Variable *Zeros = makeReg(DestTy); | |
| 1538 Context.insert(InstFakeDef::create(Func, Zeros)); | |
| 1539 _pxor(Zeros, Zeros); | |
| 1540 _pcmpgt(T, Zeros); | |
| 1541 _movp(Dest, T); | |
| 1542 } else { | |
| 1543 // width = width(elty) - 1; dest = (src << width) >> width | |
| 1544 SizeT ShiftAmount = 8 * typeWidthInBytes(typeElementType(DestTy)) - 1; | |
|
Jim Stichnoth
2014/07/14 18:33:12
Use CHAR_BIT instead of 8
wala
2014/07/15 22:52:22
Since CHAR_BIT depends on the machine the code is
Jim Stichnoth
2014/07/15 23:15:44
Good point, thanks.
| |
| 1545 Constant *ShiftConstant = Ctx->getConstantInt(IceType_i8, ShiftAmount); | |
| 1546 Variable *T = makeReg(DestTy); | |
| 1547 _movp(T, Src0RM); | |
| 1548 _psll(T, ShiftConstant); | |
| 1549 _psra(T, ShiftConstant); | |
| 1550 _movp(Dest, T); | |
| 1551 } | |
| 1523 } else { | 1552 } else { |
| 1524 // TODO: Sign-extend an i1 via "shl reg, 31; sar reg, 31", and | 1553 // TODO: Sign-extend an i1 via "shl reg, 31; sar reg, 31", and |
| 1525 // also copy to the high operand of a 64-bit variable. | 1554 // also copy to the high operand of a 64-bit variable. |
| 1526 // t1 = movsx src; dst = t1 | 1555 // t1 = movsx src; dst = t1 |
| 1527 Variable *T = makeReg(Dest->getType()); | 1556 Variable *T = makeReg(Dest->getType()); |
| 1528 _movsx(T, Src0RM); | 1557 _movsx(T, Src0RM); |
| 1529 _mov(Dest, T); | 1558 _mov(Dest, T); |
| 1530 } | 1559 } |
| 1531 break; | 1560 break; |
| 1532 } | 1561 } |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 1544 _movzx(Tmp, Src0RM); | 1573 _movzx(Tmp, Src0RM); |
| 1545 _mov(DestLo, Tmp); | 1574 _mov(DestLo, Tmp); |
| 1546 _mov(DestHi, Zero); | 1575 _mov(DestHi, Zero); |
| 1547 } else if (Src0RM->getType() == IceType_i1) { | 1576 } else if (Src0RM->getType() == IceType_i1) { |
| 1548 // t = Src0RM; t &= 1; Dest = t | 1577 // t = Src0RM; t &= 1; Dest = t |
| 1549 Operand *One = Ctx->getConstantInt(IceType_i32, 1); | 1578 Operand *One = Ctx->getConstantInt(IceType_i32, 1); |
| 1550 Variable *T = makeReg(IceType_i32); | 1579 Variable *T = makeReg(IceType_i32); |
| 1551 _movzx(T, Src0RM); | 1580 _movzx(T, Src0RM); |
| 1552 _and(T, One); | 1581 _and(T, One); |
| 1553 _mov(Dest, T); | 1582 _mov(Dest, T); |
| 1583 } else if (isVectorType(Dest->getType())) { | |
| 1584 // onemask = materialize(1,1,...); dst = src & onemask | |
| 1585 Type DestTy = Dest->getType(); | |
| 1586 Variable *OneMask = makeReg(DestTy); | |
| 1587 Context.insert(InstFakeDef::create(Func, OneMask)); | |
| 1588 _pxor(OneMask, OneMask); | |
| 1589 Variable *MinusOne = makeReg(DestTy); | |
| 1590 Context.insert(InstFakeDef::create(Func, MinusOne)); | |
| 1591 _pcmpeq(MinusOne, MinusOne); | |
| 1592 _psub(OneMask, MinusOne); | |
| 1593 Variable *T = makeReg(DestTy); | |
| 1594 _movp(T, Src0RM); | |
| 1595 _pand(T, OneMask); | |
| 1596 _movp(Dest, T); | |
| 1554 } else { | 1597 } else { |
| 1555 // t1 = movzx src; dst = t1 | 1598 // t1 = movzx src; dst = t1 |
| 1556 Variable *T = makeReg(Dest->getType()); | 1599 Variable *T = makeReg(Dest->getType()); |
| 1557 _movzx(T, Src0RM); | 1600 _movzx(T, Src0RM); |
| 1558 _mov(Dest, T); | 1601 _mov(Dest, T); |
| 1559 } | 1602 } |
| 1560 break; | 1603 break; |
| 1561 } | 1604 } |
| 1562 case InstCast::Trunc: { | 1605 case InstCast::Trunc: { |
| 1563 Operand *Src0 = Inst->getSrc(0); | 1606 if (isVectorType(Dest->getType())) { |
| 1564 if (Src0->getType() == IceType_i64) | 1607 // onemask = materialize(1,1,...); dst = src & onemask |
| 1565 Src0 = loOperand(Src0); | 1608 Operand *Src0RM = legalize(Inst->getSrc(0), Legal_Reg | Legal_Mem); |
| 1566 Operand *Src0RM = legalize(Src0, Legal_Reg | Legal_Mem); | 1609 Type Src0Ty = Src0RM->getType(); |
| 1567 // t1 = trunc Src0RM; Dest = t1 | 1610 Variable *OneMask = makeReg(Src0Ty); |
| 1568 Variable *T = NULL; | 1611 Context.insert(InstFakeDef::create(Func, OneMask)); |
| 1569 _mov(T, Src0RM); | 1612 _pxor(OneMask, OneMask); |
| 1570 _mov(Dest, T); | 1613 Variable *MinusOne = makeReg(Src0Ty); |
| 1614 Context.insert(InstFakeDef::create(Func, MinusOne)); | |
| 1615 _pcmpeq(MinusOne, MinusOne); | |
| 1616 _psub(OneMask, MinusOne); | |
| 1617 Variable *T = makeReg(Dest->getType()); | |
| 1618 _movp(T, Src0RM); | |
| 1619 _pand(T, OneMask); | |
| 1620 _movp(Dest, T); | |
| 1621 } else { | |
| 1622 Operand *Src0 = Inst->getSrc(0); | |
| 1623 if (Src0->getType() == IceType_i64) | |
| 1624 Src0 = loOperand(Src0); | |
| 1625 Operand *Src0RM = legalize(Src0, Legal_Reg | Legal_Mem); | |
| 1626 // t1 = trunc Src0RM; Dest = t1 | |
| 1627 Variable *T = NULL; | |
| 1628 _mov(T, Src0RM); | |
| 1629 _mov(Dest, T); | |
| 1630 } | |
| 1571 break; | 1631 break; |
| 1572 } | 1632 } |
| 1573 case InstCast::Fptrunc: | 1633 case InstCast::Fptrunc: |
| 1574 case InstCast::Fpext: { | 1634 case InstCast::Fpext: { |
| 1575 Operand *Src0RM = legalize(Inst->getSrc(0), Legal_Reg | Legal_Mem); | 1635 Operand *Src0RM = legalize(Inst->getSrc(0), Legal_Reg | Legal_Mem); |
| 1576 // t1 = cvt Src0RM; Dest = t1 | 1636 // t1 = cvt Src0RM; Dest = t1 |
| 1577 Variable *T = makeReg(Dest->getType()); | 1637 Variable *T = makeReg(Dest->getType()); |
| 1578 _cvt(T, Src0RM); | 1638 _cvt(T, Src0RM); |
| 1579 _mov(Dest, T); | 1639 _mov(Dest, T); |
| 1580 break; | 1640 break; |
| 1581 } | 1641 } |
| 1582 case InstCast::Fptosi: | 1642 case InstCast::Fptosi: |
| 1583 if (Dest->getType() == IceType_i64) { | 1643 if (isVectorType(Dest->getType())) { |
| 1644 assert(Dest->getType() == IceType_v4i32 && | |
| 1645 Inst->getSrc(0)->getType() == IceType_v4f32); | |
| 1646 Operand *Src0RM = legalize(Inst->getSrc(0), Legal_Reg | Legal_Mem); | |
| 1647 Variable *T = makeReg(Dest->getType()); | |
| 1648 _cvt(T, Src0RM); | |
|
Jim Stichnoth
2014/07/14 18:33:12
Looks plausible, I guess, but I'm looking forward
wala
2014/07/14 20:52:22
This is what LLVM does.
| |
| 1649 _movp(Dest, T); | |
| 1650 } else if (Dest->getType() == IceType_i64) { | |
| 1584 // Use a helper for converting floating-point values to 64-bit | 1651 // Use a helper for converting floating-point values to 64-bit |
| 1585 // integers. SSE2 appears to have no way to convert from xmm | 1652 // integers. SSE2 appears to have no way to convert from xmm |
| 1586 // registers to something like the edx:eax register pair, and | 1653 // registers to something like the edx:eax register pair, and |
| 1587 // gcc and clang both want to use x87 instructions complete with | 1654 // gcc and clang both want to use x87 instructions complete with |
| 1588 // temporary manipulation of the status word. This helper is | 1655 // temporary manipulation of the status word. This helper is |
| 1589 // not needed for x86-64. | 1656 // not needed for x86-64. |
| 1590 split64(Dest); | 1657 split64(Dest); |
| 1591 const SizeT MaxSrcs = 1; | 1658 const SizeT MaxSrcs = 1; |
| 1592 Type SrcType = Inst->getSrc(0)->getType(); | 1659 Type SrcType = Inst->getSrc(0)->getType(); |
| 1593 InstCall *Call = makeHelperCall( | 1660 InstCall *Call = makeHelperCall( |
| 1594 SrcType == IceType_f32 ? "cvtftosi64" : "cvtdtosi64", Dest, MaxSrcs); | 1661 SrcType == IceType_f32 ? "cvtftosi64" : "cvtdtosi64", Dest, MaxSrcs); |
| 1595 // TODO: Call the correct compiler-rt helper function. | 1662 // TODO: Call the correct compiler-rt helper function. |
| 1596 Call->addArg(Inst->getSrc(0)); | 1663 Call->addArg(Inst->getSrc(0)); |
| 1597 lowerCall(Call); | 1664 lowerCall(Call); |
| 1598 } else { | 1665 } else { |
| 1599 Operand *Src0RM = legalize(Inst->getSrc(0), Legal_Reg | Legal_Mem); | 1666 Operand *Src0RM = legalize(Inst->getSrc(0), Legal_Reg | Legal_Mem); |
| 1600 // t1.i32 = cvt Src0RM; t2.dest_type = t1; Dest = t2.dest_type | 1667 // t1.i32 = cvt Src0RM; t2.dest_type = t1; Dest = t2.dest_type |
| 1601 Variable *T_1 = makeReg(IceType_i32); | 1668 Variable *T_1 = makeReg(IceType_i32); |
| 1602 Variable *T_2 = makeReg(Dest->getType()); | 1669 Variable *T_2 = makeReg(Dest->getType()); |
| 1603 _cvt(T_1, Src0RM); | 1670 _cvt(T_1, Src0RM); |
| 1604 _mov(T_2, T_1); // T_1 and T_2 may have different integer types | 1671 _mov(T_2, T_1); // T_1 and T_2 may have different integer types |
| 1605 _mov(Dest, T_2); | 1672 _mov(Dest, T_2); |
| 1606 T_2->setPreferredRegister(T_1, true); | 1673 T_2->setPreferredRegister(T_1, true); |
| 1607 } | 1674 } |
| 1608 break; | 1675 break; |
| 1609 case InstCast::Fptoui: | 1676 case InstCast::Fptoui: |
| 1610 if (Dest->getType() == IceType_i64 || Dest->getType() == IceType_i32) { | 1677 if (isVectorType(Dest->getType())) { |
| 1678 assert(Dest->getType() == IceType_v4i32 && | |
| 1679 Inst->getSrc(0)->getType() == IceType_v4f32); | |
| 1680 const SizeT MaxSrcs = 1; | |
| 1681 InstCall *Call = makeHelperCall("__fptoui_v4f32", Dest, MaxSrcs); | |
|
Jim Stichnoth
2014/07/14 18:33:12
Here and elsewhere, the helper function will be pa
wala
2014/07/14 20:52:22
Such identifiers are reserved to the implementatio
Jim Stichnoth
2014/07/14 22:23:30
I wouldn't say Subzero will be the *complete* impl
wala
2014/07/15 22:52:21
Done.
All helpers have a Sz_ prefix.
| |
| 1682 Call->addArg(Inst->getSrc(0)); | |
| 1683 lowerCall(Call); | |
| 1684 } else if (Dest->getType() == IceType_i64 || | |
| 1685 Dest->getType() == IceType_i32) { | |
| 1611 // Use a helper for both x86-32 and x86-64. | 1686 // Use a helper for both x86-32 and x86-64. |
| 1612 split64(Dest); | 1687 split64(Dest); |
| 1613 const SizeT MaxSrcs = 1; | 1688 const SizeT MaxSrcs = 1; |
| 1614 Type DestType = Dest->getType(); | 1689 Type DestType = Dest->getType(); |
| 1615 Type SrcType = Inst->getSrc(0)->getType(); | 1690 Type SrcType = Inst->getSrc(0)->getType(); |
| 1616 IceString DstSubstring = (DestType == IceType_i64 ? "64" : "32"); | 1691 IceString DstSubstring = (DestType == IceType_i64 ? "64" : "32"); |
| 1617 IceString SrcSubstring = (SrcType == IceType_f32 ? "f" : "d"); | 1692 IceString SrcSubstring = (SrcType == IceType_f32 ? "f" : "d"); |
| 1618 // Possibilities are cvtftoui32, cvtdtoui32, cvtftoui64, cvtdtoui64 | 1693 // Possibilities are cvtftoui32, cvtdtoui32, cvtftoui64, cvtdtoui64 |
| 1619 IceString TargetString = "cvt" + SrcSubstring + "toui" + DstSubstring; | 1694 IceString TargetString = "cvt" + SrcSubstring + "toui" + DstSubstring; |
| 1620 // TODO: Call the correct compiler-rt helper function. | 1695 // TODO: Call the correct compiler-rt helper function. |
| 1621 InstCall *Call = makeHelperCall(TargetString, Dest, MaxSrcs); | 1696 InstCall *Call = makeHelperCall(TargetString, Dest, MaxSrcs); |
| 1622 Call->addArg(Inst->getSrc(0)); | 1697 Call->addArg(Inst->getSrc(0)); |
| 1623 lowerCall(Call); | 1698 lowerCall(Call); |
| 1624 return; | 1699 return; |
| 1625 } else { | 1700 } else { |
| 1626 Operand *Src0RM = legalize(Inst->getSrc(0), Legal_Reg | Legal_Mem); | 1701 Operand *Src0RM = legalize(Inst->getSrc(0), Legal_Reg | Legal_Mem); |
| 1627 // t1.i32 = cvt Src0RM; t2.dest_type = t1; Dest = t2.dest_type | 1702 // t1.i32 = cvt Src0RM; t2.dest_type = t1; Dest = t2.dest_type |
| 1628 Variable *T_1 = makeReg(IceType_i32); | 1703 Variable *T_1 = makeReg(IceType_i32); |
| 1629 Variable *T_2 = makeReg(Dest->getType()); | 1704 Variable *T_2 = makeReg(Dest->getType()); |
| 1630 _cvt(T_1, Src0RM); | 1705 _cvt(T_1, Src0RM); |
| 1631 _mov(T_2, T_1); // T_1 and T_2 may have different integer types | 1706 _mov(T_2, T_1); // T_1 and T_2 may have different integer types |
| 1632 _mov(Dest, T_2); | 1707 _mov(Dest, T_2); |
| 1633 T_2->setPreferredRegister(T_1, true); | 1708 T_2->setPreferredRegister(T_1, true); |
| 1634 } | 1709 } |
| 1635 break; | 1710 break; |
| 1636 case InstCast::Sitofp: | 1711 case InstCast::Sitofp: |
| 1637 if (Inst->getSrc(0)->getType() == IceType_i64) { | 1712 if (isVectorType(Dest->getType())) { |
| 1713 assert(Dest->getType() == IceType_v4f32 && | |
| 1714 Inst->getSrc(0)->getType() == IceType_v4i32); | |
| 1715 Operand *Src0RM = legalize(Inst->getSrc(0), Legal_Reg | Legal_Mem); | |
| 1716 Variable *T = makeReg(Dest->getType()); | |
| 1717 _cvt(T, Src0RM); | |
| 1718 _movp(Dest, T); | |
| 1719 } else if (Inst->getSrc(0)->getType() == IceType_i64) { | |
| 1638 // Use a helper for x86-32. | 1720 // Use a helper for x86-32. |
| 1639 const SizeT MaxSrcs = 1; | 1721 const SizeT MaxSrcs = 1; |
| 1640 Type DestType = Dest->getType(); | 1722 Type DestType = Dest->getType(); |
| 1641 InstCall *Call = makeHelperCall( | 1723 InstCall *Call = makeHelperCall( |
| 1642 DestType == IceType_f32 ? "cvtsi64tof" : "cvtsi64tod", Dest, MaxSrcs); | 1724 DestType == IceType_f32 ? "cvtsi64tof" : "cvtsi64tod", Dest, MaxSrcs); |
| 1643 // TODO: Call the correct compiler-rt helper function. | 1725 // TODO: Call the correct compiler-rt helper function. |
| 1644 Call->addArg(Inst->getSrc(0)); | 1726 Call->addArg(Inst->getSrc(0)); |
| 1645 lowerCall(Call); | 1727 lowerCall(Call); |
| 1646 return; | 1728 return; |
| 1647 } else { | 1729 } else { |
| 1648 Operand *Src0RM = legalize(Inst->getSrc(0), Legal_Reg | Legal_Mem); | 1730 Operand *Src0RM = legalize(Inst->getSrc(0), Legal_Reg | Legal_Mem); |
| 1649 // Sign-extend the operand. | 1731 // Sign-extend the operand. |
| 1650 // t1.i32 = movsx Src0RM; t2 = Cvt t1.i32; Dest = t2 | 1732 // t1.i32 = movsx Src0RM; t2 = Cvt t1.i32; Dest = t2 |
| 1651 Variable *T_1 = makeReg(IceType_i32); | 1733 Variable *T_1 = makeReg(IceType_i32); |
| 1652 Variable *T_2 = makeReg(Dest->getType()); | 1734 Variable *T_2 = makeReg(Dest->getType()); |
| 1653 if (Src0RM->getType() == IceType_i32) | 1735 if (Src0RM->getType() == IceType_i32) |
| 1654 _mov(T_1, Src0RM); | 1736 _mov(T_1, Src0RM); |
| 1655 else | 1737 else |
| 1656 _movsx(T_1, Src0RM); | 1738 _movsx(T_1, Src0RM); |
| 1657 _cvt(T_2, T_1); | 1739 _cvt(T_2, T_1); |
| 1658 _mov(Dest, T_2); | 1740 _mov(Dest, T_2); |
| 1659 } | 1741 } |
| 1660 break; | 1742 break; |
| 1661 case InstCast::Uitofp: { | 1743 case InstCast::Uitofp: { |
| 1662 Operand *Src0 = Inst->getSrc(0); | 1744 Operand *Src0 = Inst->getSrc(0); |
| 1663 if (Src0->getType() == IceType_i64 || Src0->getType() == IceType_i32) { | 1745 if (isVectorType(Src0->getType())) { |
| 1746 assert(Dest->getType() == IceType_v4f32 && | |
| 1747 Src0->getType() == IceType_v4i32); | |
| 1748 const SizeT MaxSrcs = 1; | |
| 1749 InstCall *Call = makeHelperCall("__uitofp_v4i32", Dest, MaxSrcs); | |
| 1750 Call->addArg(Src0); | |
| 1751 lowerCall(Call); | |
| 1752 } else if (Src0->getType() == IceType_i64 || | |
| 1753 Src0->getType() == IceType_i32) { | |
| 1664 // Use a helper for x86-32 and x86-64. Also use a helper for | 1754 // Use a helper for x86-32 and x86-64. Also use a helper for |
| 1665 // i32 on x86-32. | 1755 // i32 on x86-32. |
| 1666 const SizeT MaxSrcs = 1; | 1756 const SizeT MaxSrcs = 1; |
| 1667 Type DestType = Dest->getType(); | 1757 Type DestType = Dest->getType(); |
| 1668 IceString SrcSubstring = (Src0->getType() == IceType_i64 ? "64" : "32"); | 1758 IceString SrcSubstring = (Src0->getType() == IceType_i64 ? "64" : "32"); |
| 1669 IceString DstSubstring = (DestType == IceType_f32 ? "f" : "d"); | 1759 IceString DstSubstring = (DestType == IceType_f32 ? "f" : "d"); |
| 1670 // Possibilities are cvtui32tof, cvtui32tod, cvtui64tof, cvtui64tod | 1760 // Possibilities are cvtui32tof, cvtui32tod, cvtui64tof, cvtui64tod |
| 1671 IceString TargetString = "cvtui" + SrcSubstring + "to" + DstSubstring; | 1761 IceString TargetString = "cvtui" + SrcSubstring + "to" + DstSubstring; |
| 1672 // TODO: Call the correct compiler-rt helper function. | 1762 // TODO: Call the correct compiler-rt helper function. |
| 1673 InstCall *Call = makeHelperCall(TargetString, Dest, MaxSrcs); | 1763 InstCall *Call = makeHelperCall(TargetString, Dest, MaxSrcs); |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 1692 case InstCast::Bitcast: { | 1782 case InstCast::Bitcast: { |
| 1693 Operand *Src0 = Inst->getSrc(0); | 1783 Operand *Src0 = Inst->getSrc(0); |
| 1694 if (Dest->getType() == Src0->getType()) { | 1784 if (Dest->getType() == Src0->getType()) { |
| 1695 InstAssign *Assign = InstAssign::create(Func, Dest, Src0); | 1785 InstAssign *Assign = InstAssign::create(Func, Dest, Src0); |
| 1696 lowerAssign(Assign); | 1786 lowerAssign(Assign); |
| 1697 return; | 1787 return; |
| 1698 } | 1788 } |
| 1699 switch (Dest->getType()) { | 1789 switch (Dest->getType()) { |
| 1700 default: | 1790 default: |
| 1701 llvm_unreachable("Unexpected Bitcast dest type"); | 1791 llvm_unreachable("Unexpected Bitcast dest type"); |
| 1792 case IceType_i8: { | |
| 1793 assert(Src0->getType() == IceType_v8i1); | |
| 1794 InstCall *Call = makeHelperCall("__bitcast_v8i1_to_i8", Dest, 1); | |
| 1795 Call->addArg(Src0); | |
| 1796 lowerCall(Call); | |
| 1797 } break; | |
| 1798 case IceType_i16: { | |
| 1799 assert(Src0->getType() == IceType_v16i1); | |
| 1800 InstCall *Call = makeHelperCall("__bitcast_v16i1_to_i16", Dest, 1); | |
| 1801 Call->addArg(Src0); | |
| 1802 lowerCall(Call); | |
| 1803 } break; | |
| 1702 case IceType_i32: | 1804 case IceType_i32: |
| 1703 case IceType_f32: { | 1805 case IceType_f32: { |
| 1704 Operand *Src0RM = legalize(Src0, Legal_Reg | Legal_Mem); | 1806 Operand *Src0RM = legalize(Src0, Legal_Reg | Legal_Mem); |
| 1705 Type DestType = Dest->getType(); | 1807 Type DestType = Dest->getType(); |
| 1706 Type SrcType = Src0RM->getType(); | 1808 Type SrcType = Src0RM->getType(); |
| 1707 assert((DestType == IceType_i32 && SrcType == IceType_f32) || | 1809 assert((DestType == IceType_i32 && SrcType == IceType_f32) || |
| 1708 (DestType == IceType_f32 && SrcType == IceType_i32)); | 1810 (DestType == IceType_f32 && SrcType == IceType_i32)); |
| 1709 // a.i32 = bitcast b.f32 ==> | 1811 // a.i32 = bitcast b.f32 ==> |
| 1710 // t.f32 = b.f32 | 1812 // t.f32 = b.f32 |
| 1711 // s.f32 = spill t.f32 | 1813 // s.f32 = spill t.f32 |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1770 _mov(T_Lo, loOperand(Src0)); | 1872 _mov(T_Lo, loOperand(Src0)); |
| 1771 // Technically, the Spill is defined after the _store happens, but | 1873 // Technically, the Spill is defined after the _store happens, but |
| 1772 // SpillLo is considered a "use" of Spill so define Spill before it | 1874 // SpillLo is considered a "use" of Spill so define Spill before it |
| 1773 // is used. | 1875 // is used. |
| 1774 Context.insert(InstFakeDef::create(Func, Spill)); | 1876 Context.insert(InstFakeDef::create(Func, Spill)); |
| 1775 _store(T_Lo, SpillLo); | 1877 _store(T_Lo, SpillLo); |
| 1776 _mov(T_Hi, hiOperand(Src0)); | 1878 _mov(T_Hi, hiOperand(Src0)); |
| 1777 _store(T_Hi, SpillHi); | 1879 _store(T_Hi, SpillHi); |
| 1778 _movq(Dest, Spill); | 1880 _movq(Dest, Spill); |
| 1779 } break; | 1881 } break; |
| 1882 case IceType_v8i1: { | |
| 1883 assert(Src0->getType() == IceType_i8); | |
| 1884 InstCall *Call = makeHelperCall("__bitcast_i8_to_v8i1", Dest, 1); | |
| 1885 Variable *Src0AsI32 = Func->makeVariable(IceType_i32, Context.getNode()); | |
| 1886 // Arguments to functions are required to be at least 32 bits wide. | |
| 1887 lowerCast(InstCast::create(Func, InstCast::Zext, Src0AsI32, Src0)); | |
| 1888 Call->addArg(Src0AsI32); | |
| 1889 lowerCall(Call); | |
| 1890 } break; | |
| 1891 case IceType_v16i1: { | |
| 1892 assert(Src0->getType() == IceType_i16); | |
| 1893 InstCall *Call = makeHelperCall("__bitcast_i16_to_v16i1", Dest, 1); | |
| 1894 Variable *Src0AsI32 = Func->makeVariable(IceType_i32, Context.getNode()); | |
| 1895 // Arguments to functions are required to be at least 32 bits wide. | |
| 1896 lowerCast(InstCast::create(Func, InstCast::Zext, Src0AsI32, Src0)); | |
| 1897 Call->addArg(Src0AsI32); | |
| 1898 lowerCall(Call); | |
| 1899 } break; | |
| 1900 case IceType_v8i16: | |
| 1901 case IceType_v16i8: | |
| 1902 case IceType_v4i32: | |
| 1903 case IceType_v4f32: { | |
| 1904 _movp(Dest, legalizeToVar(Src0)); | |
| 1905 } break; | |
| 1780 } | 1906 } |
| 1781 break; | 1907 break; |
| 1782 } | 1908 } |
| 1783 } | 1909 } |
| 1784 } | 1910 } |
| 1785 | 1911 |
| 1786 void TargetX8632::lowerFcmp(const InstFcmp *Inst) { | 1912 void TargetX8632::lowerFcmp(const InstFcmp *Inst) { |
| 1787 Operand *Src0 = Inst->getSrc(0); | 1913 Operand *Src0 = Inst->getSrc(0); |
| 1788 Operand *Src1 = Inst->getSrc(1); | 1914 Operand *Src1 = Inst->getSrc(1); |
| 1789 Variable *Dest = Inst->getDest(); | 1915 Variable *Dest = Inst->getDest(); |
| (...skipping 1048 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2838 for (SizeT i = 0; i < Size; ++i) { | 2964 for (SizeT i = 0; i < Size; ++i) { |
| 2839 Str << "\t.byte\t" << (((unsigned)Data[i]) & 0xff) << "\n"; | 2965 Str << "\t.byte\t" << (((unsigned)Data[i]) & 0xff) << "\n"; |
| 2840 } | 2966 } |
| 2841 Str << "\t.size\t" << MangledName << ", " << Size << "\n"; | 2967 Str << "\t.size\t" << MangledName << ", " << Size << "\n"; |
| 2842 } | 2968 } |
| 2843 Str << "\t" << (IsInternal ? ".local" : ".global") << "\t" << MangledName | 2969 Str << "\t" << (IsInternal ? ".local" : ".global") << "\t" << MangledName |
| 2844 << "\n"; | 2970 << "\n"; |
| 2845 } | 2971 } |
| 2846 | 2972 |
| 2847 } // end of namespace Ice | 2973 } // end of namespace Ice |
| OLD | NEW |