Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(162)

Side by Side Diff: src/IceTargetLoweringX8632.cpp

Issue 300563003: Subzero: Initial O2 lowering (Closed) Base URL: https://gerrit.chromium.org/gerrit/p/native_client/pnacl-subzero.git@master
Patch Set: Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698