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 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 |