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 742 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
753 split64(Var); | 753 split64(Var); |
754 return Var->getLo(); | 754 return Var->getLo(); |
755 } | 755 } |
756 if (ConstantInteger *Const = llvm::dyn_cast<ConstantInteger>(Operand)) { | 756 if (ConstantInteger *Const = llvm::dyn_cast<ConstantInteger>(Operand)) { |
757 uint64_t Mask = (1ull << 32) - 1; | 757 uint64_t Mask = (1ull << 32) - 1; |
758 return Ctx->getConstantInt(IceType_i32, Const->getValue() & Mask); | 758 return Ctx->getConstantInt(IceType_i32, Const->getValue() & Mask); |
759 } | 759 } |
760 if (OperandX8632Mem *Mem = llvm::dyn_cast<OperandX8632Mem>(Operand)) { | 760 if (OperandX8632Mem *Mem = llvm::dyn_cast<OperandX8632Mem>(Operand)) { |
761 return OperandX8632Mem::create(Func, IceType_i32, Mem->getBase(), | 761 return OperandX8632Mem::create(Func, IceType_i32, Mem->getBase(), |
762 Mem->getOffset(), Mem->getIndex(), | 762 Mem->getOffset(), Mem->getIndex(), |
763 Mem->getShift()); | 763 Mem->getShift(), Mem->getSegmentRegister()); |
764 } | 764 } |
765 llvm_unreachable("Unsupported operand type"); | 765 llvm_unreachable("Unsupported operand type"); |
766 return NULL; | 766 return NULL; |
767 } | 767 } |
768 | 768 |
769 Operand *TargetX8632::hiOperand(Operand *Operand) { | 769 Operand *TargetX8632::hiOperand(Operand *Operand) { |
770 assert(Operand->getType() == IceType_i64); | 770 assert(Operand->getType() == IceType_i64); |
771 if (Operand->getType() != IceType_i64) | 771 if (Operand->getType() != IceType_i64) |
772 return Operand; | 772 return Operand; |
773 if (Variable *Var = llvm::dyn_cast<Variable>(Operand)) { | 773 if (Variable *Var = llvm::dyn_cast<Variable>(Operand)) { |
774 split64(Var); | 774 split64(Var); |
775 return Var->getHi(); | 775 return Var->getHi(); |
776 } | 776 } |
777 if (ConstantInteger *Const = llvm::dyn_cast<ConstantInteger>(Operand)) { | 777 if (ConstantInteger *Const = llvm::dyn_cast<ConstantInteger>(Operand)) { |
778 return Ctx->getConstantInt(IceType_i32, Const->getValue() >> 32); | 778 return Ctx->getConstantInt(IceType_i32, Const->getValue() >> 32); |
779 } | 779 } |
780 if (OperandX8632Mem *Mem = llvm::dyn_cast<OperandX8632Mem>(Operand)) { | 780 if (OperandX8632Mem *Mem = llvm::dyn_cast<OperandX8632Mem>(Operand)) { |
781 Constant *Offset = Mem->getOffset(); | 781 Constant *Offset = Mem->getOffset(); |
782 if (Offset == NULL) | 782 if (Offset == NULL) |
783 Offset = Ctx->getConstantInt(IceType_i32, 4); | 783 Offset = Ctx->getConstantInt(IceType_i32, 4); |
784 else if (ConstantInteger *IntOffset = | 784 else if (ConstantInteger *IntOffset = |
785 llvm::dyn_cast<ConstantInteger>(Offset)) { | 785 llvm::dyn_cast<ConstantInteger>(Offset)) { |
786 Offset = Ctx->getConstantInt(IceType_i32, 4 + IntOffset->getValue()); | 786 Offset = Ctx->getConstantInt(IceType_i32, 4 + IntOffset->getValue()); |
787 } else if (ConstantRelocatable *SymOffset = | 787 } else if (ConstantRelocatable *SymOffset = |
788 llvm::dyn_cast<ConstantRelocatable>(Offset)) { | 788 llvm::dyn_cast<ConstantRelocatable>(Offset)) { |
789 Offset = Ctx->getConstantSym(IceType_i32, 4 + SymOffset->getOffset(), | 789 Offset = Ctx->getConstantSym(IceType_i32, 4 + SymOffset->getOffset(), |
790 SymOffset->getName()); | 790 SymOffset->getName()); |
791 } | 791 } |
792 return OperandX8632Mem::create(Func, IceType_i32, Mem->getBase(), Offset, | 792 return OperandX8632Mem::create(Func, IceType_i32, Mem->getBase(), Offset, |
793 Mem->getIndex(), Mem->getShift()); | 793 Mem->getIndex(), Mem->getShift(), |
| 794 Mem->getSegmentRegister()); |
794 } | 795 } |
795 llvm_unreachable("Unsupported operand type"); | 796 llvm_unreachable("Unsupported operand type"); |
796 return NULL; | 797 return NULL; |
797 } | 798 } |
798 | 799 |
799 llvm::SmallBitVector TargetX8632::getRegisterSet(RegSetMask Include, | 800 llvm::SmallBitVector TargetX8632::getRegisterSet(RegSetMask Include, |
800 RegSetMask Exclude) const { | 801 RegSetMask Exclude) const { |
801 llvm::SmallBitVector Registers(Reg_NUM); | 802 llvm::SmallBitVector Registers(Reg_NUM); |
802 | 803 |
803 #define X(val, init, name, name16, name8, scratch, preserved, stackptr, \ | 804 #define X(val, init, name, name16, name8, scratch, preserved, stackptr, \ |
(...skipping 955 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1759 legalize(Src0, IsSrc1ImmOrReg ? Legal_All : Legal_Reg, true); | 1760 legalize(Src0, IsSrc1ImmOrReg ? Legal_All : Legal_Reg, true); |
1760 InstX8632Label *Label = InstX8632Label::create(Func, this); | 1761 InstX8632Label *Label = InstX8632Label::create(Func, this); |
1761 _cmp(Src0New, Src1); | 1762 _cmp(Src0New, Src1); |
1762 _mov(Dest, One); | 1763 _mov(Dest, One); |
1763 _br(getIcmp32Mapping(Inst->getCondition()), Label); | 1764 _br(getIcmp32Mapping(Inst->getCondition()), Label); |
1764 Context.insert(InstFakeUse::create(Func, Dest)); | 1765 Context.insert(InstFakeUse::create(Func, Dest)); |
1765 _mov(Dest, Zero); | 1766 _mov(Dest, Zero); |
1766 Context.insert(Label); | 1767 Context.insert(Label); |
1767 } | 1768 } |
1768 | 1769 |
| 1770 void TargetX8632::lowerIntrinsicCall(const InstIntrinsicCall *Instr) { |
| 1771 switch (Instr->getIntrinsicInfo().ID) { |
| 1772 case AtomicCmpxchg: |
| 1773 case AtomicFence: |
| 1774 case AtomicFenceAll: |
| 1775 case AtomicIsLockFree: |
| 1776 case AtomicLoad: |
| 1777 case AtomicRMW: |
| 1778 case AtomicStore: |
| 1779 case Bswap: |
| 1780 case Ctlz: |
| 1781 case Ctpop: |
| 1782 case Cttz: |
| 1783 Func->setError("Unhandled intrinsic"); |
| 1784 return; |
| 1785 case Longjmp: { |
| 1786 InstCall *Call = makeHelperCall("longjmp", NULL, 2); |
| 1787 Call->addArg(Instr->getArg(0)); |
| 1788 Call->addArg(Instr->getArg(1)); |
| 1789 lowerCall(Call); |
| 1790 break; |
| 1791 } |
| 1792 case Memcpy: { |
| 1793 // In the future, we could potentially emit an inline memcpy/memset, etc. |
| 1794 // for intrinsic calls w/ a known length. |
| 1795 InstCall *Call = makeHelperCall("memcpy", NULL, 3); |
| 1796 Call->addArg(Instr->getArg(0)); |
| 1797 Call->addArg(Instr->getArg(1)); |
| 1798 Call->addArg(Instr->getArg(2)); |
| 1799 lowerCall(Call); |
| 1800 break; |
| 1801 } |
| 1802 case Memmove: { |
| 1803 InstCall *Call = makeHelperCall("memmove", NULL, 3); |
| 1804 Call->addArg(Instr->getArg(0)); |
| 1805 Call->addArg(Instr->getArg(1)); |
| 1806 Call->addArg(Instr->getArg(2)); |
| 1807 lowerCall(Call); |
| 1808 break; |
| 1809 } |
| 1810 case Memset: { |
| 1811 // The value operand needs to be extended to a stack slot size |
| 1812 // because we "push" only works for a specific operand size. |
| 1813 Operand *ValOp = Instr->getArg(1); |
| 1814 assert(ValOp->getType() == IceType_i8); |
| 1815 Variable *ValExt = makeReg(stackSlotType()); |
| 1816 _movzx(ValExt, ValOp); |
| 1817 InstCall *Call = makeHelperCall("memset", NULL, 3); |
| 1818 Call->addArg(Instr->getArg(0)); |
| 1819 Call->addArg(ValExt); |
| 1820 Call->addArg(Instr->getArg(2)); |
| 1821 lowerCall(Call); |
| 1822 break; |
| 1823 } |
| 1824 case NaClReadTP: { |
| 1825 Constant *Zero = Ctx->getConstantInt(IceType_i32, 0); |
| 1826 Operand *Src = OperandX8632Mem::create( |
| 1827 Func, IceType_i32, NULL, Zero, NULL, 0, |
| 1828 OperandX8632Mem::SegReg_GS); |
| 1829 Variable *Dest = Instr->getDest(); |
| 1830 Variable *T = NULL; |
| 1831 _mov(T, Src); |
| 1832 _mov(Dest, T); |
| 1833 break; |
| 1834 } |
| 1835 case Setjmp: { |
| 1836 InstCall *Call = makeHelperCall("setjmp", Instr->getDest(), 1); |
| 1837 Call->addArg(Instr->getArg(0)); |
| 1838 lowerCall(Call); |
| 1839 break; |
| 1840 } |
| 1841 case Sqrt: |
| 1842 case Stacksave: |
| 1843 case Stackrestore: |
| 1844 Func->setError("Unhandled intrinsic"); |
| 1845 return; |
| 1846 case Trap: |
| 1847 _ud2(); |
| 1848 break; |
| 1849 case UnknownIntrinsic: |
| 1850 Func->setError("Should not be lowering UnknownIntrinsic"); |
| 1851 return; |
| 1852 } |
| 1853 return; |
| 1854 } |
| 1855 |
1769 namespace { | 1856 namespace { |
1770 | 1857 |
1771 bool isAdd(const Inst *Inst) { | 1858 bool isAdd(const Inst *Inst) { |
1772 if (const InstArithmetic *Arith = | 1859 if (const InstArithmetic *Arith = |
1773 llvm::dyn_cast_or_null<const InstArithmetic>(Inst)) { | 1860 llvm::dyn_cast_or_null<const InstArithmetic>(Inst)) { |
1774 return (Arith->getOp() == InstArithmetic::Add); | 1861 return (Arith->getOp() == InstArithmetic::Add); |
1775 } | 1862 } |
1776 return false; | 1863 return false; |
1777 } | 1864 } |
1778 | 1865 |
1779 void computeAddressOpt(Variable *&Base, Variable *&Index, int32_t &Shift, | 1866 void computeAddressOpt(Variable *&Base, Variable *&Index, uint16_t &Shift, |
1780 int32_t &Offset) { | 1867 int32_t &Offset) { |
1781 (void)Offset; // TODO: pattern-match for non-zero offsets. | 1868 (void)Offset; // TODO: pattern-match for non-zero offsets. |
1782 if (Base == NULL) | 1869 if (Base == NULL) |
1783 return; | 1870 return; |
1784 // If the Base has more than one use or is live across multiple | 1871 // If the Base has more than one use or is live across multiple |
1785 // blocks, then don't go further. Alternatively (?), never consider | 1872 // blocks, then don't go further. Alternatively (?), never consider |
1786 // a transformation that would change a variable that is currently | 1873 // a transformation that would change a variable that is currently |
1787 // *not* live across basic block boundaries into one that *is*. | 1874 // *not* live across basic block boundaries into one that *is*. |
1788 if (Base->isMultiblockLife() /* || Base->getUseCount() > 1*/) | 1875 if (Base->isMultiblockLife() /* || Base->getUseCount() > 1*/) |
1789 return; | 1876 return; |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1950 | 2037 |
1951 InstAssign *Assign = InstAssign::create(Func, Inst->getDest(), Src0); | 2038 InstAssign *Assign = InstAssign::create(Func, Inst->getDest(), Src0); |
1952 lowerAssign(Assign); | 2039 lowerAssign(Assign); |
1953 } | 2040 } |
1954 | 2041 |
1955 void TargetX8632::doAddressOptLoad() { | 2042 void TargetX8632::doAddressOptLoad() { |
1956 Inst *Inst = *Context.getCur(); | 2043 Inst *Inst = *Context.getCur(); |
1957 Variable *Dest = Inst->getDest(); | 2044 Variable *Dest = Inst->getDest(); |
1958 Operand *Addr = Inst->getSrc(0); | 2045 Operand *Addr = Inst->getSrc(0); |
1959 Variable *Index = NULL; | 2046 Variable *Index = NULL; |
1960 int32_t Shift = 0; | 2047 uint16_t Shift = 0; |
1961 int32_t Offset = 0; // TODO: make Constant | 2048 int32_t Offset = 0; // TODO: make Constant |
| 2049 // Vanilla ICE load instructions should not use the segment registers, |
| 2050 // and computeAddressOpt only works at the level of Variables and Constants, |
| 2051 // not other OperandX8632Mem, so there should be no mention of segment |
| 2052 // registers there either. |
| 2053 const OperandX8632Mem::SegmentRegisters SegmentReg = |
| 2054 OperandX8632Mem::DefaultSegment; |
1962 Variable *Base = llvm::dyn_cast<Variable>(Addr); | 2055 Variable *Base = llvm::dyn_cast<Variable>(Addr); |
1963 computeAddressOpt(Base, Index, Shift, Offset); | 2056 computeAddressOpt(Base, Index, Shift, Offset); |
1964 if (Base && Addr != Base) { | 2057 if (Base && Addr != Base) { |
1965 Constant *OffsetOp = Ctx->getConstantInt(IceType_i32, Offset); | 2058 Constant *OffsetOp = Ctx->getConstantInt(IceType_i32, Offset); |
1966 Addr = OperandX8632Mem::create(Func, Dest->getType(), Base, OffsetOp, Index, | 2059 Addr = OperandX8632Mem::create(Func, Dest->getType(), Base, OffsetOp, Index, |
1967 Shift); | 2060 Shift, SegmentReg); |
1968 Inst->setDeleted(); | 2061 Inst->setDeleted(); |
1969 Context.insert(InstLoad::create(Func, Dest, Addr)); | 2062 Context.insert(InstLoad::create(Func, Dest, Addr)); |
1970 } | 2063 } |
1971 } | 2064 } |
1972 | 2065 |
1973 void TargetX8632::lowerPhi(const InstPhi * /*Inst*/) { | 2066 void TargetX8632::lowerPhi(const InstPhi * /*Inst*/) { |
1974 Func->setError("Phi found in regular instruction list"); | 2067 Func->setError("Phi found in regular instruction list"); |
1975 } | 2068 } |
1976 | 2069 |
1977 void TargetX8632::lowerRet(const InstRet *Inst) { | 2070 void TargetX8632::lowerRet(const InstRet *Inst) { |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2066 Value = legalize(Value, Legal_Reg | Legal_Imm, true); | 2159 Value = legalize(Value, Legal_Reg | Legal_Imm, true); |
2067 _store(Value, NewAddr); | 2160 _store(Value, NewAddr); |
2068 } | 2161 } |
2069 } | 2162 } |
2070 | 2163 |
2071 void TargetX8632::doAddressOptStore() { | 2164 void TargetX8632::doAddressOptStore() { |
2072 InstStore *Inst = llvm::cast<InstStore>(*Context.getCur()); | 2165 InstStore *Inst = llvm::cast<InstStore>(*Context.getCur()); |
2073 Operand *Data = Inst->getData(); | 2166 Operand *Data = Inst->getData(); |
2074 Operand *Addr = Inst->getAddr(); | 2167 Operand *Addr = Inst->getAddr(); |
2075 Variable *Index = NULL; | 2168 Variable *Index = NULL; |
2076 int32_t Shift = 0; | 2169 uint16_t Shift = 0; |
2077 int32_t Offset = 0; // TODO: make Constant | 2170 int32_t Offset = 0; // TODO: make Constant |
2078 Variable *Base = llvm::dyn_cast<Variable>(Addr); | 2171 Variable *Base = llvm::dyn_cast<Variable>(Addr); |
| 2172 // Vanilla ICE load instructions should not use the segment registers, |
| 2173 // and computeAddressOpt only works at the level of Variables and Constants, |
| 2174 // not other OperandX8632Mem, so there should be no mention of segment |
| 2175 // registers there either. |
| 2176 const OperandX8632Mem::SegmentRegisters SegmentReg = |
| 2177 OperandX8632Mem::DefaultSegment; |
2079 computeAddressOpt(Base, Index, Shift, Offset); | 2178 computeAddressOpt(Base, Index, Shift, Offset); |
2080 if (Base && Addr != Base) { | 2179 if (Base && Addr != Base) { |
2081 Constant *OffsetOp = Ctx->getConstantInt(IceType_i32, Offset); | 2180 Constant *OffsetOp = Ctx->getConstantInt(IceType_i32, Offset); |
2082 Addr = OperandX8632Mem::create(Func, Data->getType(), Base, OffsetOp, Index, | 2181 Addr = OperandX8632Mem::create(Func, Data->getType(), Base, OffsetOp, Index, |
2083 Shift); | 2182 Shift, SegmentReg); |
2084 Inst->setDeleted(); | 2183 Inst->setDeleted(); |
2085 Context.insert(InstStore::create(Func, Data, Addr)); | 2184 Context.insert(InstStore::create(Func, Data, Addr)); |
2086 } | 2185 } |
2087 } | 2186 } |
2088 | 2187 |
2089 void TargetX8632::lowerSwitch(const InstSwitch *Inst) { | 2188 void TargetX8632::lowerSwitch(const InstSwitch *Inst) { |
2090 // This implements the most naive possible lowering. | 2189 // This implements the most naive possible lowering. |
2091 // cmp a,val[0]; jeq label[0]; cmp a,val[1]; jeq label[1]; ... jmp default | 2190 // cmp a,val[0]; jeq label[0]; cmp a,val[1]; jeq label[1]; ... jmp default |
2092 Operand *Src0 = Inst->getComparison(); | 2191 Operand *Src0 = Inst->getComparison(); |
2093 SizeT NumCases = Inst->getNumCases(); | 2192 SizeT NumCases = Inst->getNumCases(); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2134 Variable *RegIndex = NULL; | 2233 Variable *RegIndex = NULL; |
2135 if (Base) { | 2234 if (Base) { |
2136 RegBase = legalizeToVar(Base, true); | 2235 RegBase = legalizeToVar(Base, true); |
2137 } | 2236 } |
2138 if (Index) { | 2237 if (Index) { |
2139 RegIndex = legalizeToVar(Index, true); | 2238 RegIndex = legalizeToVar(Index, true); |
2140 } | 2239 } |
2141 if (Base != RegBase || Index != RegIndex) { | 2240 if (Base != RegBase || Index != RegIndex) { |
2142 From = | 2241 From = |
2143 OperandX8632Mem::create(Func, Mem->getType(), RegBase, | 2242 OperandX8632Mem::create(Func, Mem->getType(), RegBase, |
2144 Mem->getOffset(), RegIndex, Mem->getShift()); | 2243 Mem->getOffset(), RegIndex, Mem->getShift(), |
| 2244 Mem->getSegmentRegister()); |
2145 } | 2245 } |
2146 | 2246 |
2147 if (!(Allowed & Legal_Mem)) { | 2247 if (!(Allowed & Legal_Mem)) { |
2148 Variable *Reg = makeReg(From->getType(), RegNum); | 2248 Variable *Reg = makeReg(From->getType(), RegNum); |
2149 _mov(Reg, From, RegNum); | 2249 _mov(Reg, From, RegNum); |
2150 From = Reg; | 2250 From = Reg; |
2151 } | 2251 } |
2152 return From; | 2252 return From; |
2153 } | 2253 } |
2154 if (llvm::isa<Constant>(From)) { | 2254 if (llvm::isa<Constant>(From)) { |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2261 // llvm-mc doesn't parse "dword ptr [.L$foo]". | 2361 // llvm-mc doesn't parse "dword ptr [.L$foo]". |
2262 Str << "dword ptr [L$" << IceType_f32 << "$" << getPoolEntryID() << "]"; | 2362 Str << "dword ptr [L$" << IceType_f32 << "$" << getPoolEntryID() << "]"; |
2263 } | 2363 } |
2264 | 2364 |
2265 template <> void ConstantDouble::emit(GlobalContext *Ctx) const { | 2365 template <> void ConstantDouble::emit(GlobalContext *Ctx) const { |
2266 Ostream &Str = Ctx->getStrEmit(); | 2366 Ostream &Str = Ctx->getStrEmit(); |
2267 Str << "qword ptr [L$" << IceType_f64 << "$" << getPoolEntryID() << "]"; | 2367 Str << "qword ptr [L$" << IceType_f64 << "$" << getPoolEntryID() << "]"; |
2268 } | 2368 } |
2269 | 2369 |
2270 } // end of namespace Ice | 2370 } // end of namespace Ice |
OLD | NEW |