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 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
203 TypeToRegisterSet[IceType_void] = InvalidRegisters; | 203 TypeToRegisterSet[IceType_void] = InvalidRegisters; |
204 TypeToRegisterSet[IceType_i1] = IntegerRegistersI8; | 204 TypeToRegisterSet[IceType_i1] = IntegerRegistersI8; |
205 TypeToRegisterSet[IceType_i8] = IntegerRegistersI8; | 205 TypeToRegisterSet[IceType_i8] = IntegerRegistersI8; |
206 TypeToRegisterSet[IceType_i16] = IntegerRegisters; | 206 TypeToRegisterSet[IceType_i16] = IntegerRegisters; |
207 TypeToRegisterSet[IceType_i32] = IntegerRegisters; | 207 TypeToRegisterSet[IceType_i32] = IntegerRegisters; |
208 TypeToRegisterSet[IceType_i64] = IntegerRegisters; | 208 TypeToRegisterSet[IceType_i64] = IntegerRegisters; |
209 TypeToRegisterSet[IceType_f32] = FloatRegisters; | 209 TypeToRegisterSet[IceType_f32] = FloatRegisters; |
210 TypeToRegisterSet[IceType_f64] = FloatRegisters; | 210 TypeToRegisterSet[IceType_f64] = FloatRegisters; |
211 } | 211 } |
212 | 212 |
213 void TargetX8632::translateO2() { | |
214 GlobalContext *Context = Func->getContext(); | |
215 Ostream &Str = Context->getStrDump(); | |
216 Timer T_placePhiLoads; | |
217 Func->placePhiLoads(); | |
218 if (Func->hasError()) | |
219 return; | |
220 T_placePhiLoads.printElapsedUs(Context, "placePhiLoads()"); | |
221 Timer T_placePhiStores; | |
222 Func->placePhiStores(); | |
223 if (Func->hasError()) | |
224 return; | |
225 T_placePhiStores.printElapsedUs(Context, "placePhiStores()"); | |
226 Timer T_deletePhis; | |
227 Func->deletePhis(); | |
228 if (Func->hasError()) | |
229 return; | |
230 T_deletePhis.printElapsedUs(Context, "deletePhis()"); | |
231 Timer T_renumber1; | |
232 Func->renumberInstructions(); | |
233 if (Func->hasError()) | |
234 return; | |
235 T_renumber1.printElapsedUs(Context, "renumberInstructions()"); | |
236 if (Context->isVerbose()) | |
237 Str << "================ After Phi lowering ================\n"; | |
238 Func->dump(); | |
jvoung (off chromium)
2014/05/28 17:48:15
dump() vs isVerbose() consistency?
Jim Stichnoth
2014/05/29 01:39:46
The Cfg-level dumping should be cleaned up now.
| |
239 | |
240 Timer T_doAddressOpt; | |
241 Func->doAddressOpt(); | |
242 T_doAddressOpt.printElapsedUs(Context, "doAddressOpt()"); | |
jvoung (off chromium)
2014/05/28 17:48:15
Does doAddressOpt() depend on the instruction numb
Jim Stichnoth
2014/05/29 01:39:46
You're right. Hopefully this is cleaned up now an
| |
243 // Liveness may be incorrect after address mode optimization. | |
244 Timer T_renumber2; | |
245 Func->renumberInstructions(); | |
246 if (Func->hasError()) | |
247 return; | |
248 T_renumber2.printElapsedUs(Context, "renumberInstructions()"); | |
249 // TODO: It should be sufficient to use the fastest liveness | |
250 // calculation, i.e. Liveness_LREndLightweight. However, for | |
251 // some reason that slows down the rest of the translation. | |
252 // Investigate. | |
253 Timer T_liveness1; | |
254 Func->liveness(Liveness_LREndFull); | |
255 if (Func->hasError()) | |
256 return; | |
257 T_liveness1.printElapsedUs(Context, "liveness()"); | |
258 if (Context->isVerbose()) | |
259 Str << "================ After x86 address mode opt ================\n"; | |
260 Func->dump(); | |
261 Timer T_genCode; | |
262 Func->genCode(); | |
263 if (Func->hasError()) | |
264 return; | |
265 T_genCode.printElapsedUs(Context, "genCode()"); | |
266 Timer T_renumber3; | |
267 Func->renumberInstructions(); | |
268 if (Func->hasError()) | |
269 return; | |
270 T_renumber3.printElapsedUs(Context, "renumberInstructions()"); | |
271 Timer T_liveness2; | |
272 Func->liveness(Liveness_RangesFull); | |
273 if (Func->hasError()) | |
274 return; | |
275 T_liveness2.printElapsedUs(Context, "liveness()"); | |
276 ComputedLiveRanges = true; | |
277 if (Context->isVerbose()) | |
278 Str << "================ After initial x8632 codegen ================\n"; | |
279 Func->dump(); | |
280 | |
281 Timer T_regAlloc; | |
282 regAlloc(); | |
283 if (Func->hasError()) | |
284 return; | |
285 T_regAlloc.printElapsedUs(Context, "regAlloc()"); | |
286 if (Context->isVerbose()) | |
287 Str << "================ After linear scan regalloc ================\n"; | |
288 Func->dump(); | |
289 | |
290 Timer T_genFrame; | |
291 Func->genFrame(); | |
292 if (Func->hasError()) | |
293 return; | |
294 T_genFrame.printElapsedUs(Context, "genFrame()"); | |
295 if (Context->isVerbose()) | |
296 Str << "================ After stack frame mapping ================\n"; | |
297 Func->dump(); | |
298 } | |
299 | |
213 void TargetX8632::translateOm1() { | 300 void TargetX8632::translateOm1() { |
214 GlobalContext *Context = Func->getContext(); | 301 GlobalContext *Context = Func->getContext(); |
215 Ostream &Str = Context->getStrDump(); | 302 Ostream &Str = Context->getStrDump(); |
216 Timer T_placePhiLoads; | 303 Timer T_placePhiLoads; |
217 Func->placePhiLoads(); | 304 Func->placePhiLoads(); |
218 if (Func->hasError()) | 305 if (Func->hasError()) |
219 return; | 306 return; |
220 T_placePhiLoads.printElapsedUs(Context, "placePhiLoads()"); | 307 T_placePhiLoads.printElapsedUs(Context, "placePhiLoads()"); |
221 Timer T_placePhiStores; | 308 Timer T_placePhiStores; |
222 Func->placePhiStores(); | 309 Func->placePhiStores(); |
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
391 for (VarList::const_iterator I = Variables.begin(), E = Variables.end(); | 478 for (VarList::const_iterator I = Variables.begin(), E = Variables.end(); |
392 I != E; ++I) { | 479 I != E; ++I) { |
393 Variable *Var = *I; | 480 Variable *Var = *I; |
394 if (Var->hasReg()) { | 481 if (Var->hasReg()) { |
395 RegsUsed[Var->getRegNum()] = true; | 482 RegsUsed[Var->getRegNum()] = true; |
396 continue; | 483 continue; |
397 } | 484 } |
398 // An argument passed on the stack already has a stack slot. | 485 // An argument passed on the stack already has a stack slot. |
399 if (Var->getIsArg()) | 486 if (Var->getIsArg()) |
400 continue; | 487 continue; |
488 // An unreferenced variable doesn't need a stack slot. | |
489 if (ComputedLiveRanges && Var->getLiveRange().isEmpty()) | |
490 continue; | |
401 // A spill slot linked to a variable with a stack slot should reuse | 491 // A spill slot linked to a variable with a stack slot should reuse |
402 // that stack slot. | 492 // that stack slot. |
403 if (Var->getWeight() == RegWeight::Zero && Var->getRegisterOverlap()) { | 493 if (Var->getWeight() == RegWeight::Zero && Var->getRegisterOverlap()) { |
404 if (Variable *Linked = Var->getPreferredRegister()) { | 494 if (Variable *Linked = Var->getPreferredRegister()) { |
405 if (!Linked->hasReg()) | 495 if (!Linked->hasReg()) |
406 continue; | 496 continue; |
407 } | 497 } |
408 } | 498 } |
409 int32_t Increment = typeWidthInBytesOnStack(Var->getType()); | 499 int32_t Increment = typeWidthInBytesOnStack(Var->getType()); |
410 if (SimpleCoalescing) { | 500 if (SimpleCoalescing) { |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
476 int32_t NextStackOffset = 0; | 566 int32_t NextStackOffset = 0; |
477 for (VarList::const_iterator I = Variables.begin(), E = Variables.end(); | 567 for (VarList::const_iterator I = Variables.begin(), E = Variables.end(); |
478 I != E; ++I) { | 568 I != E; ++I) { |
479 Variable *Var = *I; | 569 Variable *Var = *I; |
480 if (Var->hasReg()) { | 570 if (Var->hasReg()) { |
481 RegsUsed[Var->getRegNum()] = true; | 571 RegsUsed[Var->getRegNum()] = true; |
482 continue; | 572 continue; |
483 } | 573 } |
484 if (Var->getIsArg()) | 574 if (Var->getIsArg()) |
485 continue; | 575 continue; |
576 if (ComputedLiveRanges && Var->getLiveRange().isEmpty()) | |
577 continue; | |
486 if (Var->getWeight() == RegWeight::Zero && Var->getRegisterOverlap()) { | 578 if (Var->getWeight() == RegWeight::Zero && Var->getRegisterOverlap()) { |
487 if (Variable *Linked = Var->getPreferredRegister()) { | 579 if (Variable *Linked = Var->getPreferredRegister()) { |
488 if (!Linked->hasReg()) { | 580 if (!Linked->hasReg()) { |
489 // TODO: Make sure Linked has already been assigned a stack | 581 // TODO: Make sure Linked has already been assigned a stack |
490 // slot. | 582 // slot. |
491 Var->setStackOffset(Linked->getStackOffset()); | 583 Var->setStackOffset(Linked->getStackOffset()); |
492 continue; | 584 continue; |
493 } | 585 } |
494 } | 586 } |
495 } | 587 } |
(...skipping 1098 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1594 _mov(Dest, NonDefault); | 1686 _mov(Dest, NonDefault); |
1595 Context.insert(Label); | 1687 Context.insert(Label); |
1596 } | 1688 } |
1597 } | 1689 } |
1598 | 1690 |
1599 void TargetX8632::lowerIcmp(const InstIcmp *Inst) { | 1691 void TargetX8632::lowerIcmp(const InstIcmp *Inst) { |
1600 Operand *Src0 = legalize(Inst->getSrc(0)); | 1692 Operand *Src0 = legalize(Inst->getSrc(0)); |
1601 Operand *Src1 = legalize(Inst->getSrc(1)); | 1693 Operand *Src1 = legalize(Inst->getSrc(1)); |
1602 Variable *Dest = Inst->getDest(); | 1694 Variable *Dest = Inst->getDest(); |
1603 | 1695 |
1696 // If Src1 is an immediate, or known to be a physical register, we can | |
1697 // allow Src0 to be a memory operand. Otherwise, Src0 must be copied into | |
1698 // a physical register. (Actually, either Src0 or Src1 can be chosen for | |
1699 // the physical register, but unfortunately we have to commit to one or | |
1700 // the other before register allocation.) | |
1701 bool IsSrc1ImmOrReg = false; | |
1702 if (llvm::isa<Constant>(Src1)) { | |
1703 IsSrc1ImmOrReg = true; | |
1704 } else if (Variable *Var = llvm::dyn_cast<Variable>(Src1)) { | |
1705 if (Var->hasReg()) | |
1706 IsSrc1ImmOrReg = true; | |
1707 } | |
1708 | |
1709 // Try to fuse a compare immediately followed by a conditional branch. This | |
1710 // is possible when the compare dest and the branch source operands are the | |
1711 // same, and are their only uses. TODO: implement this optimization for i64. | |
1712 if (InstBr *NextBr = llvm::dyn_cast_or_null<InstBr>(Context.getNextInst())) { | |
1713 if (Src0->getType() != IceType_i64 && !NextBr->isUnconditional() && | |
1714 Dest == NextBr->getSrc(0) && NextBr->isLastUse(Dest)) { | |
1715 Operand *Src0New = | |
1716 legalize(Src0, IsSrc1ImmOrReg ? Legal_All : Legal_Reg, true); | |
1717 _cmp(Src0New, Src1); | |
1718 _br(getIcmp32Mapping(Inst->getCondition()), NextBr->getTargetTrue(), | |
1719 NextBr->getTargetFalse()); | |
1720 // Skip over the following branch instruction. | |
1721 NextBr->setDeleted(); | |
1722 Context.advanceNext(); | |
1723 return; | |
1724 } | |
1725 } | |
1726 | |
1604 // a=icmp cond, b, c ==> cmp b,c; a=1; br cond,L1; FakeUse(a); a=0; L1: | 1727 // a=icmp cond, b, c ==> cmp b,c; a=1; br cond,L1; FakeUse(a); a=0; L1: |
1605 Constant *Zero = Ctx->getConstantInt(IceType_i32, 0); | 1728 Constant *Zero = Ctx->getConstantInt(IceType_i32, 0); |
1606 Constant *One = Ctx->getConstantInt(IceType_i32, 1); | 1729 Constant *One = Ctx->getConstantInt(IceType_i32, 1); |
1607 if (Src0->getType() == IceType_i64) { | 1730 if (Src0->getType() == IceType_i64) { |
1608 InstIcmp::ICond Condition = Inst->getCondition(); | 1731 InstIcmp::ICond Condition = Inst->getCondition(); |
1609 size_t Index = static_cast<size_t>(Condition); | 1732 size_t Index = static_cast<size_t>(Condition); |
1610 assert(Index < TableIcmp64Size); | 1733 assert(Index < TableIcmp64Size); |
1611 Operand *Src1LoRI = legalize(loOperand(Src1), Legal_Reg | Legal_Imm); | 1734 Operand *Src1LoRI = legalize(loOperand(Src1), Legal_Reg | Legal_Imm); |
1612 Operand *Src1HiRI = legalize(hiOperand(Src1), Legal_Reg | Legal_Imm); | 1735 Operand *Src1HiRI = legalize(hiOperand(Src1), Legal_Reg | Legal_Imm); |
1613 if (Condition == InstIcmp::Eq || Condition == InstIcmp::Ne) { | 1736 if (Condition == InstIcmp::Eq || Condition == InstIcmp::Ne) { |
(...skipping 16 matching lines...) Expand all Loading... | |
1630 _cmp(loOperand(Src0), Src1LoRI); | 1753 _cmp(loOperand(Src0), Src1LoRI); |
1631 _br(TableIcmp64[Index].C3, LabelTrue); | 1754 _br(TableIcmp64[Index].C3, LabelTrue); |
1632 Context.insert(LabelFalse); | 1755 Context.insert(LabelFalse); |
1633 Context.insert(InstFakeUse::create(Func, Dest)); | 1756 Context.insert(InstFakeUse::create(Func, Dest)); |
1634 _mov(Dest, Zero); | 1757 _mov(Dest, Zero); |
1635 Context.insert(LabelTrue); | 1758 Context.insert(LabelTrue); |
1636 } | 1759 } |
1637 return; | 1760 return; |
1638 } | 1761 } |
1639 | 1762 |
1640 // If Src1 is an immediate, or known to be a physical register, we can | |
1641 // allow Src0 to be a memory operand. Otherwise, Src0 must be copied into | |
1642 // a physical register. (Actually, either Src0 or Src1 can be chosen for | |
1643 // the physical register, but unfortunately we have to commit to one or | |
1644 // the other before register allocation.) | |
1645 bool IsSrc1ImmOrReg = false; | |
1646 if (llvm::isa<Constant>(Src1)) { | |
1647 IsSrc1ImmOrReg = true; | |
1648 } else if (Variable *Var = llvm::dyn_cast<Variable>(Src1)) { | |
1649 if (Var->hasReg()) | |
1650 IsSrc1ImmOrReg = true; | |
1651 } | |
1652 | |
1653 // cmp b, c | 1763 // cmp b, c |
1654 Operand *Src0New = | 1764 Operand *Src0New = |
1655 legalize(Src0, IsSrc1ImmOrReg ? Legal_All : Legal_Reg, true); | 1765 legalize(Src0, IsSrc1ImmOrReg ? Legal_All : Legal_Reg, true); |
1656 InstX8632Label *Label = InstX8632Label::create(Func, this); | 1766 InstX8632Label *Label = InstX8632Label::create(Func, this); |
1657 _cmp(Src0New, Src1); | 1767 _cmp(Src0New, Src1); |
1658 _mov(Dest, One); | 1768 _mov(Dest, One); |
1659 _br(getIcmp32Mapping(Inst->getCondition()), Label); | 1769 _br(getIcmp32Mapping(Inst->getCondition()), Label); |
1660 Context.insert(InstFakeUse::create(Func, Dest)); | 1770 Context.insert(InstFakeUse::create(Func, Dest)); |
1661 _mov(Dest, Zero); | 1771 _mov(Dest, Zero); |
1662 Context.insert(Label); | 1772 Context.insert(Label); |
1663 } | 1773 } |
1664 | 1774 |
1775 namespace { | |
1776 | |
1777 bool isAdd(const Inst *Inst) { | |
1778 if (const InstArithmetic *Arith = | |
1779 llvm::dyn_cast_or_null<const InstArithmetic>(Inst)) { | |
1780 return (Arith->getOp() == InstArithmetic::Add); | |
1781 } | |
1782 return false; | |
1783 } | |
1784 | |
1785 void computeAddressOpt(Cfg * /*Func*/, Variable *&Base, Variable *&Index, | |
jvoung (off chromium)
2014/05/28 17:48:15
Is this expected to change to use the Func paramet
Jim Stichnoth
2014/05/29 01:39:46
Removed. I think this was originally meant for th
| |
1786 int32_t &Shift, int32_t &Offset) { | |
1787 (void)Offset; // TODO: pattern-match for non-zero offsets. | |
1788 if (Base == NULL) | |
1789 return; | |
1790 // If the Base has more than one use or is live across multiple | |
1791 // blocks, then don't go further. Alternatively (?), never consider | |
1792 // a transformation that would change a variable that is currently | |
1793 // *not* live across basic block boundaries into one that *is*. | |
1794 if (Base->isMultiblockLife() /* || Base->getUseCount() > 1*/) | |
1795 return; | |
1796 | |
1797 while (true) { | |
1798 // Base is Base=Var ==> | |
1799 // set Base=Var | |
1800 const Inst *BaseInst = Base->getDefinition(); | |
1801 Operand *BaseOperand0 = BaseInst ? BaseInst->getSrc(0) : NULL; | |
1802 Variable *BaseVariable0 = llvm::dyn_cast_or_null<Variable>(BaseOperand0); | |
1803 if (BaseInst && llvm::isa<InstAssign>(BaseInst) && BaseVariable0 && | |
1804 // TODO: ensure BaseVariable0 stays single-BB | |
1805 true) { | |
1806 Base = BaseVariable0; | |
1807 | |
1808 continue; | |
1809 } | |
1810 | |
1811 // Index is Index=Var ==> | |
1812 // set Index=Var | |
jvoung (off chromium)
2014/05/28 17:48:15
Maybe the assignment transitivity checks could be
Jim Stichnoth
2014/05/29 01:39:46
Added a TODO (since it's actually only implemented
| |
1813 | |
1814 // Index==NULL && Base is Base=Var1+Var2 ==> | |
1815 // set Base=Var1, Index=Var2, Shift=0 | |
1816 Operand *BaseOperand1 = | |
1817 BaseInst && BaseInst->getSrcSize() >= 2 ? BaseInst->getSrc(1) : NULL; | |
1818 Variable *BaseVariable1 = llvm::dyn_cast_or_null<Variable>(BaseOperand1); | |
1819 if (Index == NULL && isAdd(BaseInst) && BaseVariable0 && BaseVariable1 && | |
1820 // TODO: ensure BaseVariable0 and BaseVariable1 stay single-BB | |
1821 true) { | |
1822 Base = BaseVariable0; | |
1823 Index = BaseVariable1; | |
1824 Shift = 0; // should already have been 0 | |
1825 continue; | |
1826 } | |
1827 | |
1828 // Index is Index=Var*Const && log2(Const)+Shift<=3 ==> | |
1829 // Index=Var, Shift+=log2(Const) | |
1830 const Inst *IndexInst = Index ? Index->getDefinition() : NULL; | |
1831 if (const InstArithmetic *ArithInst = | |
1832 llvm::dyn_cast_or_null<InstArithmetic>(IndexInst)) { | |
1833 Operand *IndexOperand0 = ArithInst->getSrc(0); | |
1834 Variable *IndexVariable0 = llvm::dyn_cast<Variable>(IndexOperand0); | |
1835 Operand *IndexOperand1 = ArithInst->getSrc(1); | |
1836 ConstantInteger *IndexConstant1 = | |
1837 llvm::dyn_cast<ConstantInteger>(IndexOperand1); | |
1838 if (ArithInst->getOp() == InstArithmetic::Mul && IndexVariable0 && | |
1839 IndexOperand1->getType() == IceType_i32 && IndexConstant1) { | |
1840 uint64_t Mult = IndexConstant1->getValue(); | |
1841 uint32_t LogMult; | |
1842 switch (Mult) { | |
1843 case 1: | |
1844 LogMult = 0; | |
1845 break; | |
1846 case 2: | |
1847 LogMult = 1; | |
1848 break; | |
1849 case 4: | |
1850 LogMult = 2; | |
1851 break; | |
1852 case 8: | |
1853 LogMult = 3; | |
1854 break; | |
1855 default: | |
1856 LogMult = 4; | |
1857 break; | |
1858 } | |
1859 if (Shift + LogMult <= 3) { | |
1860 Index = IndexVariable0; | |
1861 Shift += LogMult; | |
1862 continue; | |
1863 } | |
1864 } | |
1865 } | |
1866 | |
1867 // Index is Index=Var<<Const && Const+Shift<=3 ==> | |
1868 // Index=Var, Shift+=Const | |
1869 | |
1870 // Index is Index=Const*Var && log2(Const)+Shift<=3 ==> | |
1871 // Index=Var, Shift+=log2(Const) | |
1872 | |
1873 // Index && Shift==0 && Base is Base=Var*Const && log2(Const)+Shift<=3 ==> | |
1874 // swap(Index,Base) | |
1875 // Similar for Base=Const*Var and Base=Var<<Const | |
1876 | |
1877 // Base is Base=Var+Const ==> | |
1878 // set Base=Var, Offset+=Const | |
1879 | |
1880 // Base is Base=Const+Var ==> | |
1881 // set Base=Var, Offset+=Const | |
1882 | |
1883 // Base is Base=Var-Const ==> | |
1884 // set Base=Var, Offset-=Const | |
1885 | |
1886 // Index is Index=Var+Const ==> | |
1887 // set Index=Var, Offset+=(Const<<Shift) | |
1888 | |
1889 // Index is Index=Const+Var ==> | |
1890 // set Index=Var, Offset+=(Const<<Shift) | |
1891 | |
1892 // Index is Index=Var-Const ==> | |
1893 // set Index=Var, Offset-=(Const<<Shift) | |
1894 | |
1895 // TODO: consider overflow issues with respect to Offset. | |
1896 // TODO: handle symbolic constants. | |
1897 break; | |
1898 } | |
1899 } | |
1900 | |
1901 } // anonymous namespace | |
1902 | |
1665 void TargetX8632::lowerLoad(const InstLoad *Inst) { | 1903 void TargetX8632::lowerLoad(const InstLoad *Inst) { |
1666 // A Load instruction can be treated the same as an Assign | 1904 // A Load instruction can be treated the same as an Assign |
1667 // instruction, after the source operand is transformed into an | 1905 // instruction, after the source operand is transformed into an |
1668 // OperandX8632Mem operand. Note that the address mode | 1906 // OperandX8632Mem operand. Note that the address mode |
1669 // optimization already creates an OperandX8632Mem operand, so it | 1907 // optimization already creates an OperandX8632Mem operand, so it |
1670 // doesn't need another level of transformation. | 1908 // doesn't need another level of transformation. |
1671 Type Ty = Inst->getDest()->getType(); | 1909 Type Ty = Inst->getDest()->getType(); |
1672 Operand *Src0 = Inst->getSourceAddress(); | 1910 Operand *Src0 = Inst->getSourceAddress(); |
1673 // Address mode optimization already creates an OperandX8632Mem | 1911 // Address mode optimization already creates an OperandX8632Mem |
1674 // operand, so it doesn't need another level of transformation. | 1912 // operand, so it doesn't need another level of transformation. |
1675 if (!llvm::isa<OperandX8632Mem>(Src0)) { | 1913 if (!llvm::isa<OperandX8632Mem>(Src0)) { |
1676 Variable *Base = llvm::dyn_cast<Variable>(Src0); | 1914 Variable *Base = llvm::dyn_cast<Variable>(Src0); |
1677 Constant *Offset = llvm::dyn_cast<Constant>(Src0); | 1915 Constant *Offset = llvm::dyn_cast<Constant>(Src0); |
1678 assert(Base || Offset); | 1916 assert(Base || Offset); |
1679 Src0 = OperandX8632Mem::create(Func, Ty, Base, Offset); | 1917 Src0 = OperandX8632Mem::create(Func, Ty, Base, Offset); |
1680 } | 1918 } |
1681 | 1919 |
1920 // Fuse this load with a subsequent Arithmetic instruction in the | |
1921 // following situations: | |
1922 // a=[mem]; c=b+a ==> c=b+[mem] if last use of a and a not in b | |
1923 // a=[mem]; c=a+b ==> c=b+[mem] if commutative and above is true | |
1924 // | |
1925 // TODO: Clean up and test thoroughly. | |
1926 // | |
1927 // TODO: Why limit to Arithmetic instructions? This could probably be | |
1928 // applied to most any instruction type. Look at all source operands | |
1929 // in the following instruction, and if there is one instance of the | |
1930 // load instruction's dest variable, and that instruction ends that | |
1931 // variable's live range, then make the substitution. Deal with | |
1932 // commutativity optimization in the arithmetic instruction lowering. | |
1933 InstArithmetic *NewArith = NULL; | |
1934 if (InstArithmetic *Arith = | |
1935 llvm::dyn_cast_or_null<InstArithmetic>(Context.getNextInst())) { | |
1936 Variable *DestLoad = Inst->getDest(); | |
1937 Variable *Src0Arith = llvm::dyn_cast<Variable>(Arith->getSrc(0)); | |
1938 Variable *Src1Arith = llvm::dyn_cast<Variable>(Arith->getSrc(1)); | |
1939 if (Src1Arith == DestLoad && Arith->isLastUse(Src1Arith) && | |
1940 DestLoad != Src0Arith) { | |
1941 NewArith = InstArithmetic::create(Func, Arith->getOp(), Arith->getDest(), | |
1942 Arith->getSrc(0), Src0); | |
1943 } else if (Src0Arith == DestLoad && Arith->isCommutative() && | |
1944 Arith->isLastUse(Src0Arith) && DestLoad != Src1Arith) { | |
1945 NewArith = InstArithmetic::create(Func, Arith->getOp(), Arith->getDest(), | |
1946 Arith->getSrc(1), Src0); | |
1947 } | |
1948 if (NewArith) { | |
1949 Arith->setDeleted(); | |
1950 Context.advanceNext(); | |
1951 lowerArithmetic(NewArith); | |
1952 return; | |
1953 } | |
1954 } | |
1955 | |
1682 InstAssign *Assign = InstAssign::create(Func, Inst->getDest(), Src0); | 1956 InstAssign *Assign = InstAssign::create(Func, Inst->getDest(), Src0); |
1683 lowerAssign(Assign); | 1957 lowerAssign(Assign); |
1684 } | 1958 } |
1685 | 1959 |
1960 void TargetX8632::doAddressOptLoad() { | |
1961 Inst *Inst = *Context.getCur(); | |
1962 Variable *Dest = Inst->getDest(); | |
1963 Operand *Addr = Inst->getSrc(0); | |
1964 Variable *Index = NULL; | |
1965 int32_t Shift = 0; | |
1966 int32_t Offset = 0; // TODO: make Constant | |
1967 Variable *Base = llvm::dyn_cast<Variable>(Addr); | |
1968 computeAddressOpt(Func, Base, Index, Shift, Offset); | |
1969 if (Base && Addr != Base) { | |
1970 Constant *OffsetOp = Ctx->getConstantInt(IceType_i32, Offset); | |
1971 Addr = OperandX8632Mem::create(Func, Dest->getType(), Base, OffsetOp, Index, | |
1972 Shift); | |
1973 Inst->setDeleted(); | |
1974 Context.insert(InstLoad::create(Func, Dest, Addr)); | |
1975 } | |
1976 } | |
1977 | |
1686 void TargetX8632::lowerPhi(const InstPhi * /*Inst*/) { | 1978 void TargetX8632::lowerPhi(const InstPhi * /*Inst*/) { |
1687 Func->setError("Phi found in regular instruction list"); | 1979 Func->setError("Phi found in regular instruction list"); |
1688 } | 1980 } |
1689 | 1981 |
1690 void TargetX8632::lowerRet(const InstRet *Inst) { | 1982 void TargetX8632::lowerRet(const InstRet *Inst) { |
1691 Variable *Reg = NULL; | 1983 Variable *Reg = NULL; |
1692 if (Inst->hasRetValue()) { | 1984 if (Inst->hasRetValue()) { |
1693 Operand *Src0 = legalize(Inst->getRetValue()); | 1985 Operand *Src0 = legalize(Inst->getRetValue()); |
1694 if (Src0->getType() == IceType_i64) { | 1986 if (Src0->getType() == IceType_i64) { |
1695 Variable *eax = legalizeToVar(loOperand(Src0), false, Reg_eax); | 1987 Variable *eax = legalizeToVar(loOperand(Src0), false, Reg_eax); |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1774 Operand *ValueHi = legalize(hiOperand(Value), Legal_Reg | Legal_Imm, true); | 2066 Operand *ValueHi = legalize(hiOperand(Value), Legal_Reg | Legal_Imm, true); |
1775 Operand *ValueLo = legalize(loOperand(Value), Legal_Reg | Legal_Imm, true); | 2067 Operand *ValueLo = legalize(loOperand(Value), Legal_Reg | Legal_Imm, true); |
1776 _store(ValueHi, llvm::cast<OperandX8632Mem>(hiOperand(NewAddr))); | 2068 _store(ValueHi, llvm::cast<OperandX8632Mem>(hiOperand(NewAddr))); |
1777 _store(ValueLo, llvm::cast<OperandX8632Mem>(loOperand(NewAddr))); | 2069 _store(ValueLo, llvm::cast<OperandX8632Mem>(loOperand(NewAddr))); |
1778 } else { | 2070 } else { |
1779 Value = legalize(Value, Legal_Reg | Legal_Imm, true); | 2071 Value = legalize(Value, Legal_Reg | Legal_Imm, true); |
1780 _store(Value, NewAddr); | 2072 _store(Value, NewAddr); |
1781 } | 2073 } |
1782 } | 2074 } |
1783 | 2075 |
2076 void TargetX8632::doAddressOptStore() { | |
2077 InstStore *Inst = llvm::cast<InstStore>(*Context.getCur()); | |
2078 Operand *Data = Inst->getData(); | |
2079 Operand *Addr = Inst->getAddr(); | |
2080 Variable *Index = NULL; | |
2081 int32_t Shift = 0; | |
2082 int32_t Offset = 0; // TODO: make Constant | |
2083 Variable *Base = llvm::dyn_cast<Variable>(Addr); | |
2084 computeAddressOpt(Func, Base, Index, Shift, Offset); | |
2085 if (Base && Addr != Base) { | |
2086 Constant *OffsetOp = Ctx->getConstantInt(IceType_i32, Offset); | |
2087 Addr = OperandX8632Mem::create(Func, Data->getType(), Base, OffsetOp, Index, | |
2088 Shift); | |
2089 Inst->setDeleted(); | |
2090 Context.insert(InstStore::create(Func, Data, Addr)); | |
2091 } | |
2092 } | |
2093 | |
1784 void TargetX8632::lowerSwitch(const InstSwitch *Inst) { | 2094 void TargetX8632::lowerSwitch(const InstSwitch *Inst) { |
1785 // This implements the most naive possible lowering. | 2095 // This implements the most naive possible lowering. |
1786 // cmp a,val[0]; jeq label[0]; cmp a,val[1]; jeq label[1]; ... jmp default | 2096 // cmp a,val[0]; jeq label[0]; cmp a,val[1]; jeq label[1]; ... jmp default |
1787 Operand *Src0 = Inst->getComparison(); | 2097 Operand *Src0 = Inst->getComparison(); |
1788 SizeT NumCases = Inst->getNumCases(); | 2098 SizeT NumCases = Inst->getNumCases(); |
1789 // OK, we'll be slightly less naive by forcing Src into a physical | 2099 // OK, we'll be slightly less naive by forcing Src into a physical |
1790 // register if there are 2 or more uses. | 2100 // register if there are 2 or more uses. |
1791 if (NumCases >= 2) | 2101 if (NumCases >= 2) |
1792 Src0 = legalizeToVar(Src0, true); | 2102 Src0 = legalizeToVar(Src0, true); |
1793 else | 2103 else |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1945 } | 2255 } |
1946 assert(AvailableTypedRegisters.any()); | 2256 assert(AvailableTypedRegisters.any()); |
1947 int32_t RegNum = AvailableTypedRegisters.find_first(); | 2257 int32_t RegNum = AvailableTypedRegisters.find_first(); |
1948 Var->setRegNum(RegNum); | 2258 Var->setRegNum(RegNum); |
1949 AvailableRegisters[RegNum] = false; | 2259 AvailableRegisters[RegNum] = false; |
1950 } | 2260 } |
1951 } | 2261 } |
1952 } | 2262 } |
1953 } | 2263 } |
1954 | 2264 |
1955 template <> void ConstantFloat::emit(const Cfg *Func) const { | 2265 template <> void ConstantFloat::emit(GlobalContext *Ctx) const { |
1956 Ostream &Str = Func->getContext()->getStrEmit(); | 2266 Ostream &Str = Ctx->getStrEmit(); |
1957 // It would be better to prefix with ".L$" instead of "L$", but | 2267 // It would be better to prefix with ".L$" instead of "L$", but |
1958 // llvm-mc doesn't parse "dword ptr [.L$foo]". | 2268 // llvm-mc doesn't parse "dword ptr [.L$foo]". |
1959 Str << "dword ptr [L$" << IceType_f32 << "$" << getPoolEntryID() << "]"; | 2269 Str << "dword ptr [L$" << IceType_f32 << "$" << getPoolEntryID() << "]"; |
1960 } | 2270 } |
1961 | 2271 |
1962 template <> void ConstantDouble::emit(const Cfg *Func) const { | 2272 template <> void ConstantDouble::emit(GlobalContext *Ctx) const { |
1963 Ostream &Str = Func->getContext()->getStrEmit(); | 2273 Ostream &Str = Ctx->getStrEmit(); |
1964 Str << "qword ptr [L$" << IceType_f64 << "$" << getPoolEntryID() << "]"; | 2274 Str << "qword ptr [L$" << IceType_f64 << "$" << getPoolEntryID() << "]"; |
1965 } | 2275 } |
1966 | 2276 |
1967 } // end of namespace Ice | 2277 } // end of namespace Ice |
OLD | NEW |