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 1582 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1593 assert(Src0RM->getType() == IceType_f64); | 1593 assert(Src0RM->getType() == IceType_f64); |
1594 // a.i64 = bitcast b.f64 ==> | 1594 // a.i64 = bitcast b.f64 ==> |
1595 // s.f64 = spill b.f64 | 1595 // s.f64 = spill b.f64 |
1596 // t_lo.i32 = lo(s.f64) | 1596 // t_lo.i32 = lo(s.f64) |
1597 // a_lo.i32 = t_lo.i32 | 1597 // a_lo.i32 = t_lo.i32 |
1598 // t_hi.i32 = hi(s.f64) | 1598 // t_hi.i32 = hi(s.f64) |
1599 // a_hi.i32 = t_hi.i32 | 1599 // a_hi.i32 = t_hi.i32 |
1600 Variable *Spill = Func->makeVariable(IceType_f64, Context.getNode()); | 1600 Variable *Spill = Func->makeVariable(IceType_f64, Context.getNode()); |
1601 Spill->setWeight(RegWeight::Zero); | 1601 Spill->setWeight(RegWeight::Zero); |
1602 Spill->setPreferredRegister(llvm::dyn_cast<Variable>(Src0RM), true); | 1602 Spill->setPreferredRegister(llvm::dyn_cast<Variable>(Src0RM), true); |
1603 _mov(Spill, Src0RM); | 1603 _movq(Spill, Src0RM); |
1604 | 1604 |
1605 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); | 1605 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); |
1606 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); | 1606 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); |
1607 Variable *T_Lo = makeReg(IceType_i32); | 1607 Variable *T_Lo = makeReg(IceType_i32); |
1608 Variable *T_Hi = makeReg(IceType_i32); | 1608 Variable *T_Hi = makeReg(IceType_i32); |
1609 VariableSplit *SpillLo = | 1609 VariableSplit *SpillLo = |
1610 VariableSplit::create(Func, Spill, VariableSplit::Low); | 1610 VariableSplit::create(Func, Spill, VariableSplit::Low); |
1611 VariableSplit *SpillHi = | 1611 VariableSplit *SpillHi = |
1612 VariableSplit::create(Func, Spill, VariableSplit::High); | 1612 VariableSplit::create(Func, Spill, VariableSplit::High); |
1613 | 1613 |
(...skipping 19 matching lines...) Expand all Loading... | |
1633 | 1633 |
1634 Variable *T_Lo = NULL, *T_Hi = NULL; | 1634 Variable *T_Lo = NULL, *T_Hi = NULL; |
1635 VariableSplit *SpillLo = | 1635 VariableSplit *SpillLo = |
1636 VariableSplit::create(Func, Spill, VariableSplit::Low); | 1636 VariableSplit::create(Func, Spill, VariableSplit::Low); |
1637 VariableSplit *SpillHi = | 1637 VariableSplit *SpillHi = |
1638 VariableSplit::create(Func, Spill, VariableSplit::High); | 1638 VariableSplit::create(Func, Spill, VariableSplit::High); |
1639 _mov(T_Lo, loOperand(Src0RM)); | 1639 _mov(T_Lo, loOperand(Src0RM)); |
1640 _store(T_Lo, SpillLo); | 1640 _store(T_Lo, SpillLo); |
1641 _mov(T_Hi, hiOperand(Src0RM)); | 1641 _mov(T_Hi, hiOperand(Src0RM)); |
1642 _store(T_Hi, SpillHi); | 1642 _store(T_Hi, SpillHi); |
1643 _mov(Dest, Spill); | 1643 _movq(Dest, Spill); |
1644 } break; | 1644 } break; |
1645 } | 1645 } |
1646 break; | 1646 break; |
1647 } | 1647 } |
1648 } | 1648 } |
1649 | 1649 |
1650 void TargetX8632::lowerFcmp(const InstFcmp *Inst) { | 1650 void TargetX8632::lowerFcmp(const InstFcmp *Inst) { |
1651 Operand *Src0 = Inst->getSrc(0); | 1651 Operand *Src0 = Inst->getSrc(0); |
1652 Operand *Src1 = Inst->getSrc(1); | 1652 Operand *Src1 = Inst->getSrc(1); |
1653 Variable *Dest = Inst->getDest(); | 1653 Variable *Dest = Inst->getDest(); |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1774 _mov(Dest, One); | 1774 _mov(Dest, One); |
1775 _br(getIcmp32Mapping(Inst->getCondition()), Label); | 1775 _br(getIcmp32Mapping(Inst->getCondition()), Label); |
1776 Context.insert(InstFakeUse::create(Func, Dest)); | 1776 Context.insert(InstFakeUse::create(Func, Dest)); |
1777 _mov(Dest, Zero); | 1777 _mov(Dest, Zero); |
1778 Context.insert(Label); | 1778 Context.insert(Label); |
1779 } | 1779 } |
1780 | 1780 |
1781 void TargetX8632::lowerIntrinsicCall(const InstIntrinsicCall *Instr) { | 1781 void TargetX8632::lowerIntrinsicCall(const InstIntrinsicCall *Instr) { |
1782 switch (Instr->getIntrinsicInfo().ID) { | 1782 switch (Instr->getIntrinsicInfo().ID) { |
1783 case Intrinsics::AtomicCmpxchg: | 1783 case Intrinsics::AtomicCmpxchg: |
1784 if (!Intrinsics::VerifyMemoryOrder( | |
1785 llvm::cast<ConstantInteger>(Instr->getArg(3))->getValue())) { | |
1786 Func->setError("Unexpected memory order for AtomicCmpxchg"); | |
1787 return; | |
1788 } | |
1789 // TODO(jvoung): fill it in. | |
1790 Func->setError("Unhandled intrinsic"); | |
1791 return; | |
1784 case Intrinsics::AtomicFence: | 1792 case Intrinsics::AtomicFence: |
1793 if (!Intrinsics::VerifyMemoryOrder( | |
1794 llvm::cast<ConstantInteger>(Instr->getArg(0))->getValue())) { | |
1795 Func->setError("Unexpected memory order for AtomicFence"); | |
1796 return; | |
1797 } | |
1798 _mfence(); | |
1799 return; | |
1785 case Intrinsics::AtomicFenceAll: | 1800 case Intrinsics::AtomicFenceAll: |
1786 case Intrinsics::AtomicIsLockFree: | 1801 _mfence(); |
JF
2014/06/24 01:23:29
FenceAll is meant as an equivalent to asm(:::"m"),
jvoung (off chromium)
2014/06/24 21:16:55
Added a comment, and a couple of speculative tests
| |
1787 case Intrinsics::AtomicLoad: | 1802 return; |
1803 case Intrinsics::AtomicIsLockFree: { | |
1804 Constant *One = Ctx->getConstantInt(IceType_i32, 1); | |
JF
2014/06/24 01:23:29
It would be good to explain that x86 is always loc
jvoung (off chromium)
2014/06/24 21:16:55
iOn 2014/06/24 01:23:29, JF wrote:
| |
1805 Variable *Dest = Instr->getDest(); | |
1806 _mov(Dest, One); | |
1807 return; | |
1808 } | |
1809 case Intrinsics::AtomicLoad: { | |
1810 // We require the memory address to be naturally aligned. | |
1811 // Given that is the case, then normal loads are atomic. | |
1812 if (!Intrinsics::VerifyMemoryOrder( | |
1813 llvm::cast<ConstantInteger>(Instr->getArg(1))->getValue())) { | |
1814 Func->setError("Unexpected memory ordering for AtomicLoad"); | |
1815 return; | |
1816 } | |
1817 Variable *Dest = Instr->getDest(); | |
1818 if (Dest->getType() == IceType_i64) { | |
1819 // Follow what GCC does and use a movq instead of what lowerLoad() | |
1820 // normally does (split the load into two). | |
1821 // Thus, this skips load/arithmetic op folding. Load/arithmetic folding | |
1822 // can't happen anyway, since this is x86-32 and integer arithmetic only | |
1823 // happens on 32-bit quantities. | |
1824 Variable *T = makeReg(IceType_f64); | |
1825 OperandX8632Mem *Addr = FormMemoryOperand(Instr->getArg(0), IceType_f64); | |
1826 _movq(T, Addr); | |
1827 // Then cast the bits back out of the XMM register to the i64 Dest. | |
1828 InstCast *Cast = InstCast::create(Func, InstCast::Bitcast, Dest, T); | |
1829 lowerCast(Cast); | |
1830 // Make sure that the atomic load isn't elided. | |
1831 Context.insert(InstFakeUse::create(Func, Dest->getLo())); | |
1832 Context.insert(InstFakeUse::create(Func, Dest->getHi())); | |
1833 return; | |
1834 } | |
1835 InstLoad *Load = InstLoad::create(Func, Dest, Instr->getArg(0)); | |
1836 lowerLoad(Load); | |
1837 // Make sure the atomic load isn't elided. | |
1838 Context.insert(InstFakeUse::create(Func, Dest)); | |
1839 return; | |
1840 } | |
1788 case Intrinsics::AtomicRMW: | 1841 case Intrinsics::AtomicRMW: |
1789 case Intrinsics::AtomicStore: | 1842 if (!Intrinsics::VerifyMemoryOrder( |
1843 llvm::cast<ConstantInteger>(Instr->getArg(3))->getValue())) { | |
1844 Func->setError("Unexpected memory ordering for AtomicRMW"); | |
1845 return; | |
1846 } | |
1847 lowerAtomicRMW(Instr->getDest(), | |
1848 static_cast<uint32_t>(llvm::cast<ConstantInteger>( | |
1849 Instr->getArg(0))->getValue()), | |
1850 Instr->getArg(1), Instr->getArg(2)); | |
1851 return; | |
1852 case Intrinsics::AtomicStore: { | |
1853 if (!Intrinsics::VerifyMemoryOrder( | |
1854 llvm::cast<ConstantInteger>(Instr->getArg(2))->getValue())) { | |
1855 Func->setError("Unexpected memory ordering for AtomicStore"); | |
1856 return; | |
1857 } | |
1858 // We require the memory address to be naturally aligned. | |
1859 // Given that is the case, then normal stores are atomic. | |
1860 // Add a fence after the store to make it visible. | |
1861 Operand *Value = Instr->getArg(0); | |
1862 Operand *Ptr = Instr->getArg(1); | |
1863 if (Value->getType() == IceType_i64) { | |
1864 // Use a movq instead of what lowerStore() normally does | |
1865 // (split the store into two), following what GCC does. | |
1866 // Cast the bits from int -> to an xmm register first. | |
1867 Variable *T = makeReg(IceType_f64); | |
1868 InstCast *Cast = InstCast::create(Func, InstCast::Bitcast, T, Value); | |
1869 lowerCast(Cast); | |
1870 // Then store XMM w/ a movq. | |
1871 OperandX8632Mem *Addr = FormMemoryOperand(Ptr, IceType_f64); | |
1872 _storeq(T, Addr); | |
1873 _mfence(); | |
1874 return; | |
1875 } | |
1876 InstStore *Store = InstStore::create(Func, Value, Ptr); | |
1877 lowerStore(Store); | |
1878 _mfence(); | |
1879 return; | |
1880 } | |
1790 case Intrinsics::Bswap: | 1881 case Intrinsics::Bswap: |
1791 case Intrinsics::Ctlz: | 1882 case Intrinsics::Ctlz: |
1792 case Intrinsics::Ctpop: | 1883 case Intrinsics::Ctpop: |
1793 case Intrinsics::Cttz: | 1884 case Intrinsics::Cttz: |
1885 // TODO(jvoung): fill it in. | |
1794 Func->setError("Unhandled intrinsic"); | 1886 Func->setError("Unhandled intrinsic"); |
1795 return; | 1887 return; |
1796 case Intrinsics::Longjmp: { | 1888 case Intrinsics::Longjmp: { |
1797 InstCall *Call = makeHelperCall("longjmp", NULL, 2); | 1889 InstCall *Call = makeHelperCall("longjmp", NULL, 2); |
1798 Call->addArg(Instr->getArg(0)); | 1890 Call->addArg(Instr->getArg(0)); |
1799 Call->addArg(Instr->getArg(1)); | 1891 Call->addArg(Instr->getArg(1)); |
1800 lowerCall(Call); | 1892 lowerCall(Call); |
1801 break; | 1893 return; |
1802 } | 1894 } |
1803 case Intrinsics::Memcpy: { | 1895 case Intrinsics::Memcpy: { |
1804 // In the future, we could potentially emit an inline memcpy/memset, etc. | 1896 // In the future, we could potentially emit an inline memcpy/memset, etc. |
1805 // for intrinsic calls w/ a known length. | 1897 // for intrinsic calls w/ a known length. |
1806 InstCall *Call = makeHelperCall("memcpy", NULL, 3); | 1898 InstCall *Call = makeHelperCall("memcpy", NULL, 3); |
1807 Call->addArg(Instr->getArg(0)); | 1899 Call->addArg(Instr->getArg(0)); |
1808 Call->addArg(Instr->getArg(1)); | 1900 Call->addArg(Instr->getArg(1)); |
1809 Call->addArg(Instr->getArg(2)); | 1901 Call->addArg(Instr->getArg(2)); |
1810 lowerCall(Call); | 1902 lowerCall(Call); |
1811 break; | 1903 return; |
1812 } | 1904 } |
1813 case Intrinsics::Memmove: { | 1905 case Intrinsics::Memmove: { |
1814 InstCall *Call = makeHelperCall("memmove", NULL, 3); | 1906 InstCall *Call = makeHelperCall("memmove", NULL, 3); |
1815 Call->addArg(Instr->getArg(0)); | 1907 Call->addArg(Instr->getArg(0)); |
1816 Call->addArg(Instr->getArg(1)); | 1908 Call->addArg(Instr->getArg(1)); |
1817 Call->addArg(Instr->getArg(2)); | 1909 Call->addArg(Instr->getArg(2)); |
1818 lowerCall(Call); | 1910 lowerCall(Call); |
1819 break; | 1911 return; |
1820 } | 1912 } |
1821 case Intrinsics::Memset: { | 1913 case Intrinsics::Memset: { |
1822 // The value operand needs to be extended to a stack slot size | 1914 // The value operand needs to be extended to a stack slot size |
1823 // because we "push" only works for a specific operand size. | 1915 // because we "push" only works for a specific operand size. |
1824 Operand *ValOp = Instr->getArg(1); | 1916 Operand *ValOp = Instr->getArg(1); |
1825 assert(ValOp->getType() == IceType_i8); | 1917 assert(ValOp->getType() == IceType_i8); |
1826 Variable *ValExt = makeReg(stackSlotType()); | 1918 Variable *ValExt = makeReg(stackSlotType()); |
1827 _movzx(ValExt, ValOp); | 1919 _movzx(ValExt, ValOp); |
1828 InstCall *Call = makeHelperCall("memset", NULL, 3); | 1920 InstCall *Call = makeHelperCall("memset", NULL, 3); |
1829 Call->addArg(Instr->getArg(0)); | 1921 Call->addArg(Instr->getArg(0)); |
1830 Call->addArg(ValExt); | 1922 Call->addArg(ValExt); |
1831 Call->addArg(Instr->getArg(2)); | 1923 Call->addArg(Instr->getArg(2)); |
1832 lowerCall(Call); | 1924 lowerCall(Call); |
1833 break; | 1925 return; |
1834 } | 1926 } |
1835 case Intrinsics::NaClReadTP: { | 1927 case Intrinsics::NaClReadTP: { |
1836 Constant *Zero = Ctx->getConstantInt(IceType_i32, 0); | 1928 Constant *Zero = Ctx->getConstantZero(IceType_i32); |
1837 Operand *Src = OperandX8632Mem::create(Func, IceType_i32, NULL, Zero, NULL, | 1929 Operand *Src = OperandX8632Mem::create(Func, IceType_i32, NULL, Zero, NULL, |
1838 0, OperandX8632Mem::SegReg_GS); | 1930 0, OperandX8632Mem::SegReg_GS); |
1839 Variable *Dest = Instr->getDest(); | 1931 Variable *Dest = Instr->getDest(); |
1840 Variable *T = NULL; | 1932 Variable *T = NULL; |
1841 _mov(T, Src); | 1933 _mov(T, Src); |
1842 _mov(Dest, T); | 1934 _mov(Dest, T); |
1843 break; | 1935 return; |
1844 } | 1936 } |
1845 case Intrinsics::Setjmp: { | 1937 case Intrinsics::Setjmp: { |
1846 InstCall *Call = makeHelperCall("setjmp", Instr->getDest(), 1); | 1938 InstCall *Call = makeHelperCall("setjmp", Instr->getDest(), 1); |
1847 Call->addArg(Instr->getArg(0)); | 1939 Call->addArg(Instr->getArg(0)); |
1848 lowerCall(Call); | 1940 lowerCall(Call); |
1849 break; | 1941 return; |
1850 } | 1942 } |
1851 case Intrinsics::Sqrt: | 1943 case Intrinsics::Sqrt: |
1852 case Intrinsics::Stacksave: | 1944 case Intrinsics::Stacksave: |
1853 case Intrinsics::Stackrestore: | 1945 case Intrinsics::Stackrestore: |
1946 // TODO(jvoung): fill it in. | |
1854 Func->setError("Unhandled intrinsic"); | 1947 Func->setError("Unhandled intrinsic"); |
1855 return; | 1948 return; |
1856 case Intrinsics::Trap: | 1949 case Intrinsics::Trap: |
1857 _ud2(); | 1950 _ud2(); |
1858 break; | 1951 return; |
1859 case Intrinsics::UnknownIntrinsic: | 1952 case Intrinsics::UnknownIntrinsic: |
1860 Func->setError("Should not be lowering UnknownIntrinsic"); | 1953 Func->setError("Should not be lowering UnknownIntrinsic"); |
1861 return; | 1954 return; |
1862 } | 1955 } |
1863 return; | 1956 return; |
1864 } | 1957 } |
1865 | 1958 |
1959 void TargetX8632::lowerAtomicRMW(Variable *Dest, uint32_t Operation, | |
1960 Operand *Ptr, Operand *Val) { | |
1961 switch (Operation) { | |
1962 default: | |
1963 Func->setError("Unknown AtomicRMW operation"); | |
1964 return; | |
1965 case Intrinsics::AtomicAdd: { | |
1966 if (Dest->getType() == IceType_i64) { | |
1967 // Do a nasty cmpxchg8b loop. Factor this into a function. | |
1968 // TODO(jvoung): fill it in. | |
1969 Func->setError("Unhandled AtomicRMW operation"); | |
1970 return; | |
1971 } | |
1972 OperandX8632Mem *Addr = FormMemoryOperand(Ptr, Dest->getType()); | |
1973 const bool Locked = true; | |
1974 Variable *T = NULL; | |
1975 _mov(T, Val); | |
1976 _xadd(Addr, T, Locked); | |
1977 _mov(Dest, T); | |
1978 return; | |
1979 } | |
1980 case Intrinsics::AtomicSub: { | |
1981 if (Dest->getType() == IceType_i64) { | |
1982 // Do a nasty cmpxchg8b loop. | |
1983 // TODO(jvoung): fill it in. | |
1984 Func->setError("Unhandled AtomicRMW operation"); | |
1985 return; | |
1986 } | |
1987 // Generate a memory operand from Ptr. | |
1988 // neg... | |
1989 // Then do the same as AtomicAdd. | |
1990 // TODO(jvoung): fill it in. | |
1991 Func->setError("Unhandled AtomicRMW operation"); | |
1992 return; | |
1993 } | |
1994 case Intrinsics::AtomicOr: | |
1995 case Intrinsics::AtomicAnd: | |
1996 case Intrinsics::AtomicXor: | |
1997 case Intrinsics::AtomicExchange: | |
1998 // TODO(jvoung): fill it in. | |
1999 Func->setError("Unhandled AtomicRMW operation"); | |
2000 return; | |
2001 } | |
2002 } | |
2003 | |
1866 namespace { | 2004 namespace { |
1867 | 2005 |
1868 bool isAdd(const Inst *Inst) { | 2006 bool isAdd(const Inst *Inst) { |
1869 if (const InstArithmetic *Arith = | 2007 if (const InstArithmetic *Arith = |
1870 llvm::dyn_cast_or_null<const InstArithmetic>(Inst)) { | 2008 llvm::dyn_cast_or_null<const InstArithmetic>(Inst)) { |
1871 return (Arith->getOp() == InstArithmetic::Add); | 2009 return (Arith->getOp() == InstArithmetic::Add); |
1872 } | 2010 } |
1873 return false; | 2011 return false; |
1874 } | 2012 } |
1875 | 2013 |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1992 | 2130 |
1993 } // anonymous namespace | 2131 } // anonymous namespace |
1994 | 2132 |
1995 void TargetX8632::lowerLoad(const InstLoad *Inst) { | 2133 void TargetX8632::lowerLoad(const InstLoad *Inst) { |
1996 // A Load instruction can be treated the same as an Assign | 2134 // A Load instruction can be treated the same as an Assign |
1997 // instruction, after the source operand is transformed into an | 2135 // instruction, after the source operand is transformed into an |
1998 // OperandX8632Mem operand. Note that the address mode | 2136 // OperandX8632Mem operand. Note that the address mode |
1999 // optimization already creates an OperandX8632Mem operand, so it | 2137 // optimization already creates an OperandX8632Mem operand, so it |
2000 // doesn't need another level of transformation. | 2138 // doesn't need another level of transformation. |
2001 Type Ty = Inst->getDest()->getType(); | 2139 Type Ty = Inst->getDest()->getType(); |
2002 Operand *Src0 = Inst->getSourceAddress(); | 2140 Operand *Src0 = FormMemoryOperand(Inst->getSourceAddress(), Ty); |
2003 // Address mode optimization already creates an OperandX8632Mem | |
2004 // operand, so it doesn't need another level of transformation. | |
2005 if (!llvm::isa<OperandX8632Mem>(Src0)) { | |
2006 Variable *Base = llvm::dyn_cast<Variable>(Src0); | |
2007 Constant *Offset = llvm::dyn_cast<Constant>(Src0); | |
2008 assert(Base || Offset); | |
2009 Src0 = OperandX8632Mem::create(Func, Ty, Base, Offset); | |
2010 } | |
2011 | 2141 |
2012 // Fuse this load with a subsequent Arithmetic instruction in the | 2142 // Fuse this load with a subsequent Arithmetic instruction in the |
2013 // following situations: | 2143 // following situations: |
2014 // a=[mem]; c=b+a ==> c=b+[mem] if last use of a and a not in b | 2144 // a=[mem]; c=b+a ==> c=b+[mem] if last use of a and a not in b |
2015 // a=[mem]; c=a+b ==> c=b+[mem] if commutative and above is true | 2145 // a=[mem]; c=a+b ==> c=b+[mem] if commutative and above is true |
2016 // | 2146 // |
2017 // TODO: Clean up and test thoroughly. | 2147 // TODO: Clean up and test thoroughly. |
2018 // | 2148 // |
2019 // TODO: Why limit to Arithmetic instructions? This could probably be | 2149 // TODO: Why limit to Arithmetic instructions? This could probably be |
2020 // applied to most any instruction type. Look at all source operands | 2150 // applied to most any instruction type. Look at all source operands |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2138 SrcF = legalize(SrcF, Legal_Reg | Legal_Imm, true); | 2268 SrcF = legalize(SrcF, Legal_Reg | Legal_Imm, true); |
2139 _mov(Dest, SrcF); | 2269 _mov(Dest, SrcF); |
2140 } | 2270 } |
2141 | 2271 |
2142 Context.insert(Label); | 2272 Context.insert(Label); |
2143 } | 2273 } |
2144 | 2274 |
2145 void TargetX8632::lowerStore(const InstStore *Inst) { | 2275 void TargetX8632::lowerStore(const InstStore *Inst) { |
2146 Operand *Value = Inst->getData(); | 2276 Operand *Value = Inst->getData(); |
2147 Operand *Addr = Inst->getAddr(); | 2277 Operand *Addr = Inst->getAddr(); |
2148 OperandX8632Mem *NewAddr = llvm::dyn_cast<OperandX8632Mem>(Addr); | 2278 OperandX8632Mem *NewAddr = FormMemoryOperand(Addr, Value->getType()); |
2149 // Address mode optimization already creates an OperandX8632Mem | |
2150 // operand, so it doesn't need another level of transformation. | |
2151 if (!NewAddr) { | |
2152 // The address will be either a constant (which represents a global | |
2153 // variable) or a variable, so either the Base or Offset component | |
2154 // of the OperandX8632Mem will be set. | |
2155 Variable *Base = llvm::dyn_cast<Variable>(Addr); | |
2156 Constant *Offset = llvm::dyn_cast<Constant>(Addr); | |
2157 assert(Base || Offset); | |
2158 NewAddr = OperandX8632Mem::create(Func, Value->getType(), Base, Offset); | |
2159 } | |
2160 NewAddr = llvm::cast<OperandX8632Mem>(legalize(NewAddr)); | |
2161 | 2279 |
2162 if (NewAddr->getType() == IceType_i64) { | 2280 if (NewAddr->getType() == IceType_i64) { |
2163 Value = legalize(Value); | 2281 Value = legalize(Value); |
2164 Operand *ValueHi = legalize(hiOperand(Value), Legal_Reg | Legal_Imm, true); | 2282 Operand *ValueHi = legalize(hiOperand(Value), Legal_Reg | Legal_Imm, true); |
2165 Operand *ValueLo = legalize(loOperand(Value), Legal_Reg | Legal_Imm, true); | 2283 Operand *ValueLo = legalize(loOperand(Value), Legal_Reg | Legal_Imm, true); |
2166 _store(ValueHi, llvm::cast<OperandX8632Mem>(hiOperand(NewAddr))); | 2284 _store(ValueHi, llvm::cast<OperandX8632Mem>(hiOperand(NewAddr))); |
2167 _store(ValueLo, llvm::cast<OperandX8632Mem>(loOperand(NewAddr))); | 2285 _store(ValueLo, llvm::cast<OperandX8632Mem>(loOperand(NewAddr))); |
2168 } else { | 2286 } else { |
2169 Value = legalize(Value, Legal_Reg | Legal_Imm, true); | 2287 Value = legalize(Value, Legal_Reg | Legal_Imm, true); |
2170 _store(Value, NewAddr); | 2288 _store(Value, NewAddr); |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2268 // | 2386 // |
2269 // If in the future the implementation is changed to lower undef | 2387 // If in the future the implementation is changed to lower undef |
2270 // values to uninitialized registers, a FakeDef will be needed: | 2388 // values to uninitialized registers, a FakeDef will be needed: |
2271 // Context.insert(InstFakeDef::create(Func, Reg)); | 2389 // Context.insert(InstFakeDef::create(Func, Reg)); |
2272 // This is in order to ensure that the live range of Reg is not | 2390 // This is in order to ensure that the live range of Reg is not |
2273 // overestimated. If the constant being lowered is a 64 bit value, | 2391 // overestimated. If the constant being lowered is a 64 bit value, |
2274 // then the result should be split and the lo and hi components will | 2392 // then the result should be split and the lo and hi components will |
2275 // need to go in uninitialized registers. | 2393 // need to go in uninitialized registers. |
2276 From = Ctx->getConstantZero(From->getType()); | 2394 From = Ctx->getConstantZero(From->getType()); |
2277 } | 2395 } |
2278 bool NeedsReg = !(Allowed & Legal_Imm) || | 2396 bool NeedsReg = |
2397 !(Allowed & Legal_Imm) || | |
2279 // ConstantFloat and ConstantDouble are actually memory operands. | 2398 // ConstantFloat and ConstantDouble are actually memory operands. |
2280 (!(Allowed & Legal_Mem) && (From->getType() == IceType_f32 || | 2399 (!(Allowed & Legal_Mem) && |
2281 From->getType() == IceType_f64)); | 2400 (From->getType() == IceType_f32 || From->getType() == IceType_f64)); |
2282 if (NeedsReg) { | 2401 if (NeedsReg) { |
2283 Variable *Reg = makeReg(From->getType(), RegNum); | 2402 Variable *Reg = makeReg(From->getType(), RegNum); |
2284 _mov(Reg, From); | 2403 _mov(Reg, From); |
2285 From = Reg; | 2404 From = Reg; |
2286 } | 2405 } |
2287 return From; | 2406 return From; |
2288 } | 2407 } |
2289 if (Variable *Var = llvm::dyn_cast<Variable>(From)) { | 2408 if (Variable *Var = llvm::dyn_cast<Variable>(From)) { |
2290 // We need a new physical register for the operand if: | 2409 // We need a new physical register for the operand if: |
2291 // Mem is not allowed and Var->getRegNum() is unknown, or | 2410 // Mem is not allowed and Var->getRegNum() is unknown, or |
(...skipping 12 matching lines...) Expand all Loading... | |
2304 llvm_unreachable("Unhandled operand kind in legalize()"); | 2423 llvm_unreachable("Unhandled operand kind in legalize()"); |
2305 return From; | 2424 return From; |
2306 } | 2425 } |
2307 | 2426 |
2308 // Provide a trivial wrapper to legalize() for this common usage. | 2427 // Provide a trivial wrapper to legalize() for this common usage. |
2309 Variable *TargetX8632::legalizeToVar(Operand *From, bool AllowOverlap, | 2428 Variable *TargetX8632::legalizeToVar(Operand *From, bool AllowOverlap, |
2310 int32_t RegNum) { | 2429 int32_t RegNum) { |
2311 return llvm::cast<Variable>(legalize(From, Legal_Reg, AllowOverlap, RegNum)); | 2430 return llvm::cast<Variable>(legalize(From, Legal_Reg, AllowOverlap, RegNum)); |
2312 } | 2431 } |
2313 | 2432 |
2433 OperandX8632Mem *TargetX8632::FormMemoryOperand(Operand *Operand, Type Ty) { | |
2434 OperandX8632Mem *Mem = llvm::dyn_cast<OperandX8632Mem>(Operand); | |
2435 // It may be the case that address mode optimization already creates | |
2436 // an OperandX8632Mem, so in that case it wouldn't need another level | |
2437 // of transformation. | |
2438 if (!Mem) { | |
2439 Variable *Base = llvm::dyn_cast<Variable>(Operand); | |
2440 Constant *Offset = llvm::dyn_cast<Constant>(Operand); | |
2441 assert(Base || Offset); | |
2442 Mem = OperandX8632Mem::create(Func, Ty, Base, Offset); | |
2443 } | |
2444 return llvm::cast<OperandX8632Mem>(legalize(Mem)); | |
2445 } | |
2446 | |
2314 Variable *TargetX8632::makeReg(Type Type, int32_t RegNum) { | 2447 Variable *TargetX8632::makeReg(Type Type, int32_t RegNum) { |
2315 Variable *Reg = Func->makeVariable(Type, Context.getNode()); | 2448 Variable *Reg = Func->makeVariable(Type, Context.getNode()); |
2316 if (RegNum == Variable::NoRegister) | 2449 if (RegNum == Variable::NoRegister) |
2317 Reg->setWeightInfinite(); | 2450 Reg->setWeightInfinite(); |
2318 else | 2451 else |
2319 Reg->setRegNum(RegNum); | 2452 Reg->setRegNum(RegNum); |
2320 return Reg; | 2453 return Reg; |
2321 } | 2454 } |
2322 | 2455 |
2323 void TargetX8632::postLower() { | 2456 void TargetX8632::postLower() { |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2388 // llvm-mc doesn't parse "dword ptr [.L$foo]". | 2521 // llvm-mc doesn't parse "dword ptr [.L$foo]". |
2389 Str << "dword ptr [L$" << IceType_f32 << "$" << getPoolEntryID() << "]"; | 2522 Str << "dword ptr [L$" << IceType_f32 << "$" << getPoolEntryID() << "]"; |
2390 } | 2523 } |
2391 | 2524 |
2392 template <> void ConstantDouble::emit(GlobalContext *Ctx) const { | 2525 template <> void ConstantDouble::emit(GlobalContext *Ctx) const { |
2393 Ostream &Str = Ctx->getStrEmit(); | 2526 Ostream &Str = Ctx->getStrEmit(); |
2394 Str << "qword ptr [L$" << IceType_f64 << "$" << getPoolEntryID() << "]"; | 2527 Str << "qword ptr [L$" << IceType_f64 << "$" << getPoolEntryID() << "]"; |
2395 } | 2528 } |
2396 | 2529 |
2397 } // end of namespace Ice | 2530 } // end of namespace Ice |
OLD | NEW |