llvm.org GIT mirror llvm / 056c51e
Fix bugs in lowering of FCOPYSIGN nodes. - FCOPYSIGN nodes that have operands of different types were not handled. - Different code was generated depending on the endianness of the target. Additionally, code is added that emits INS and EXT instructions, if they are supported by target (they are R2 instructions). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@154540 91177308-0d34-0410-b5e6-96231b3b80d8 Akira Hatanaka 8 years ago
3 changed file(s) with 186 addition(s) and 98 deletion(s). Raw diff Collapse all Expand all
17551755 MachinePointerInfo(SV), false, false, 0);
17561756 }
17571757
1758 // Called if the size of integer registers is large enough to hold the whole
1759 // floating point number.
1760 static SDValue LowerFCOPYSIGNLargeIntReg(SDValue Op, SelectionDAG &DAG) {
1761 // FIXME: Use ext/ins instructions if target architecture is Mips32r2.
1762 EVT ValTy = Op.getValueType();
1763 EVT IntValTy = MVT::getIntegerVT(ValTy.getSizeInBits());
1764 uint64_t Mask = (uint64_t)1 << (ValTy.getSizeInBits() - 1);
1765 DebugLoc dl = Op.getDebugLoc();
1766 SDValue Op0 = DAG.getNode(ISD::BITCAST, dl, IntValTy, Op.getOperand(0));
1767 SDValue Op1 = DAG.getNode(ISD::BITCAST, dl, IntValTy, Op.getOperand(1));
1768 SDValue And0 = DAG.getNode(ISD::AND, dl, IntValTy, Op0,
1769 DAG.getConstant(Mask - 1, IntValTy));
1770 SDValue And1 = DAG.getNode(ISD::AND, dl, IntValTy, Op1,
1771 DAG.getConstant(Mask, IntValTy));
1772 SDValue Result = DAG.getNode(ISD::OR, dl, IntValTy, And0, And1);
1773 return DAG.getNode(ISD::BITCAST, dl, ValTy, Result);
1774 }
1775
1776 // Called if the size of integer registers is not large enough to hold the whole
1777 // floating point number (e.g. f64 & 32-bit integer register).
1778 static SDValue
1779 LowerFCOPYSIGNSmallIntReg(SDValue Op, SelectionDAG &DAG, bool isLittle) {
1780 // FIXME:
1781 // Use ext/ins instructions if target architecture is Mips32r2.
1782 // Eliminate redundant mfc1 and mtc1 instructions.
1783 unsigned LoIdx = 0, HiIdx = 1;
1784
1785 if (!isLittle)
1786 std::swap(LoIdx, HiIdx);
1787
1788 DebugLoc dl = Op.getDebugLoc();
1789 SDValue Word0 = DAG.getNode(MipsISD::ExtractElementF64, dl, MVT::i32,
1790 Op.getOperand(0),
1791 DAG.getConstant(LoIdx, MVT::i32));
1792 SDValue Hi0 = DAG.getNode(MipsISD::ExtractElementF64, dl, MVT::i32,
1793 Op.getOperand(0), DAG.getConstant(HiIdx, MVT::i32));
1794 SDValue Hi1 = DAG.getNode(MipsISD::ExtractElementF64, dl, MVT::i32,
1795 Op.getOperand(1), DAG.getConstant(HiIdx, MVT::i32));
1796 SDValue And0 = DAG.getNode(ISD::AND, dl, MVT::i32, Hi0,
1797 DAG.getConstant(0x7fffffff, MVT::i32));
1798 SDValue And1 = DAG.getNode(ISD::AND, dl, MVT::i32, Hi1,
1799 DAG.getConstant(0x80000000, MVT::i32));
1800 SDValue Word1 = DAG.getNode(ISD::OR, dl, MVT::i32, And0, And1);
1801
1802 if (!isLittle)
1803 std::swap(Word0, Word1);
1804
1805 return DAG.getNode(MipsISD::BuildPairF64, dl, MVT::f64, Word0, Word1);
1758 static SDValue LowerFCOPYSIGN32(SDValue Op, SelectionDAG &DAG, bool HasR2) {
1759 EVT TyX = Op.getOperand(0).getValueType();
1760 EVT TyY = Op.getOperand(1).getValueType();
1761 SDValue Const1 = DAG.getConstant(1, MVT::i32);
1762 SDValue Const31 = DAG.getConstant(31, MVT::i32);
1763 DebugLoc DL = Op.getDebugLoc();
1764 SDValue Res;
1765
1766 // If operand is of type f64, extract the upper 32-bit. Otherwise, bitcast it
1767 // to i32.
1768 SDValue X = (TyX == MVT::f32) ?
1769 DAG.getNode(ISD::BITCAST, DL, MVT::i32, Op.getOperand(0)) :
1770 DAG.getNode(MipsISD::ExtractElementF64, DL, MVT::i32, Op.getOperand(0),
1771 Const1);
1772 SDValue Y = (TyY == MVT::f32) ?
1773 DAG.getNode(ISD::BITCAST, DL, MVT::i32, Op.getOperand(1)) :
1774 DAG.getNode(MipsISD::ExtractElementF64, DL, MVT::i32, Op.getOperand(1),
1775 Const1);
1776
1777 if (HasR2) {
1778 // ext E, Y, 31, 1 ; extract bit31 of Y
1779 // ins X, E, 31, 1 ; insert extracted bit at bit31 of X
1780 SDValue E = DAG.getNode(MipsISD::Ext, DL, MVT::i32, Y, Const31, Const1);
1781 Res = DAG.getNode(MipsISD::Ins, DL, MVT::i32, E, Const31, Const1, X);
1782 } else {
1783 // sll SllX, X, 1
1784 // srl SrlX, SllX, 1
1785 // srl SrlY, Y, 31
1786 // sll SllY, SrlX, 31
1787 // or Or, SrlX, SllY
1788 SDValue SllX = DAG.getNode(ISD::SHL, DL, MVT::i32, X, Const1);
1789 SDValue SrlX = DAG.getNode(ISD::SRL, DL, MVT::i32, SllX, Const1);
1790 SDValue SrlY = DAG.getNode(ISD::SRL, DL, MVT::i32, Y, Const31);
1791 SDValue SllY = DAG.getNode(ISD::SHL, DL, MVT::i32, SrlY, Const31);
1792 Res = DAG.getNode(ISD::OR, DL, MVT::i32, SrlX, SllY);
1793 }
1794
1795 if (TyX == MVT::f32)
1796 return DAG.getNode(ISD::BITCAST, DL, Op.getOperand(0).getValueType(), Res);
1797
1798 SDValue LowX = DAG.getNode(MipsISD::ExtractElementF64, DL, MVT::i32,
1799 Op.getOperand(0), DAG.getConstant(0, MVT::i32));
1800 return DAG.getNode(MipsISD::BuildPairF64, DL, MVT::f64, LowX, Res);
1801 }
1802
1803 static SDValue LowerFCOPYSIGN64(SDValue Op, SelectionDAG &DAG, bool HasR2) {
1804 unsigned WidthX = Op.getOperand(0).getValueSizeInBits();
1805 unsigned WidthY = Op.getOperand(1).getValueSizeInBits();
1806 EVT TyX = MVT::getIntegerVT(WidthX), TyY = MVT::getIntegerVT(WidthY);
1807 SDValue Const1 = DAG.getConstant(1, MVT::i32);
1808 DebugLoc DL = Op.getDebugLoc();
1809
1810 // Bitcast to integer nodes.
1811 SDValue X = DAG.getNode(ISD::BITCAST, DL, TyX, Op.getOperand(0));
1812 SDValue Y = DAG.getNode(ISD::BITCAST, DL, TyY, Op.getOperand(1));
1813
1814 if (HasR2) {
1815 // ext E, Y, width(Y) - 1, 1 ; extract bit width(Y)-1 of Y
1816 // ins X, E, width(X) - 1, 1 ; insert extracted bit at bit width(X)-1 of X
1817 SDValue E = DAG.getNode(MipsISD::Ext, DL, TyY, Y,
1818 DAG.getConstant(WidthY - 1, MVT::i32), Const1);
1819
1820 if (WidthX > WidthY)
1821 E = DAG.getNode(ISD::ZERO_EXTEND, DL, TyX, E);
1822 else if (WidthY > WidthX)
1823 E = DAG.getNode(ISD::TRUNCATE, DL, TyX, E);
1824
1825 SDValue I = DAG.getNode(MipsISD::Ins, DL, TyX, E,
1826 DAG.getConstant(WidthX - 1, MVT::i32), Const1, X);
1827 return DAG.getNode(ISD::BITCAST, DL, Op.getOperand(0).getValueType(), I);
1828 }
1829
1830 // (d)sll SllX, X, 1
1831 // (d)srl SrlX, SllX, 1
1832 // (d)srl SrlY, Y, width(Y)-1
1833 // (d)sll SllY, SrlX, width(Y)-1
1834 // or Or, SrlX, SllY
1835 SDValue SllX = DAG.getNode(ISD::SHL, DL, TyX, X, Const1);
1836 SDValue SrlX = DAG.getNode(ISD::SRL, DL, TyX, SllX, Const1);
1837 SDValue SrlY = DAG.getNode(ISD::SRL, DL, TyY, Y,
1838 DAG.getConstant(WidthY - 1, MVT::i32));
1839
1840 if (WidthX > WidthY)
1841 SrlY = DAG.getNode(ISD::ZERO_EXTEND, DL, TyX, SrlY);
1842 else if (WidthY > WidthX)
1843 SrlY = DAG.getNode(ISD::TRUNCATE, DL, TyX, SrlY);
1844
1845 SDValue SllY = DAG.getNode(ISD::SHL, DL, TyX, SrlY,
1846 DAG.getConstant(WidthX - 1, MVT::i32));
1847 SDValue Or = DAG.getNode(ISD::OR, DL, TyX, SrlX, SllY);
1848 return DAG.getNode(ISD::BITCAST, DL, Op.getOperand(0).getValueType(), Or);
18061849 }
18071850
18081851 SDValue
18091852 MipsTargetLowering::LowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG) const {
1810 EVT Ty = Op.getValueType();
1811
1812 assert(Ty == MVT::f32 || Ty == MVT::f64);
1813
1814 if (Ty == MVT::f32 || HasMips64)
1815 return LowerFCOPYSIGNLargeIntReg(Op, DAG);
1816
1817 return LowerFCOPYSIGNSmallIntReg(Op, DAG, Subtarget->isLittle());
1853 if (Subtarget->hasMips64())
1854 return LowerFCOPYSIGN64(Op, DAG, Subtarget->hasMips32r2());
1855
1856 return LowerFCOPYSIGN32(Op, DAG, Subtarget->hasMips32r2());
18181857 }
18191858
18201859 SDValue MipsTargetLowering::
0 ; RUN: llc < %s -march=mips64el -mcpu=mips64 -mattr=n64 | FileCheck %s -check-prefix=64
1 ; RUN: llc < %s -march=mips64el -mcpu=mips64r2 -mattr=n64 | FileCheck %s -check-prefix=64R2
2
3 declare double @copysign(double, double) nounwind readnone
4
5 declare float @copysignf(float, float) nounwind readnone
6
7 define float @func2(float %d, double %f) nounwind readnone {
8 entry:
9 ; 64: func2
10 ; 64: lui $[[T0:[0-9]+]], 32767
11 ; 64: ori $[[MSK0:[0-9]+]], $[[T0]], 65535
12 ; 64: and $[[AND0:[0-9]+]], ${{[0-9]+}}, $[[MSK0]]
13 ; 64: dsrl ${{[0-9]+}}, ${{[0-9]+}}, 63
14 ; 64: sll $[[SLL:[0-9]+]], ${{[0-9]+}}, 31
15 ; 64: or $[[OR:[0-9]+]], $[[AND0]], $[[SLL]]
16 ; 64: mtc1 $[[OR]], $f0
17
18 ; 64R2: dext ${{[0-9]+}}, ${{[0-9]+}}, 63, 1
19 ; 64R2: ins $[[INS:[0-9]+]], ${{[0-9]+}}, 31, 1
20 ; 64R2: mtc1 $[[INS]], $f0
21
22 %add = fadd float %d, 1.000000e+00
23 %conv = fptrunc double %f to float
24 %call = tail call float @copysignf(float %add, float %conv) nounwind readnone
25 ret float %call
26 }
27
28 define double @func3(double %d, float %f) nounwind readnone {
29 entry:
30
31 ; 64: daddiu $[[T0:[0-9]+]], $zero, 1
32 ; 64: dsll $[[T1:[0-9]+]], $[[T0]], 63
33 ; 64: daddiu $[[MSK0:[0-9]+]], $[[T1]], -1
34 ; 64: and $[[AND0:[0-9]+]], ${{[0-9]+}}, $[[MSK0]]
35 ; 64: srl ${{[0-9]+}}, ${{[0-9]+}}, 31
36 ; 64: dsll $[[DSLL:[0-9]+]], ${{[0-9]+}}, 63
37 ; 64: or $[[OR:[0-9]+]], $[[AND0]], $[[DSLL]]
38 ; 64: dmtc1 $[[OR]], $f0
39
40 ; 64R2: ext ${{[0-9]+}}, ${{[0-9]+}}, 31, 1
41 ; 64R2: dins $[[INS:[0-9]+]], ${{[0-9]+}}, 63, 1
42 ; 64R2: dmtc1 $[[INS]], $f0
43
44 %add = fadd double %d, 1.000000e+00
45 %conv = fpext float %f to double
46 %call = tail call double @copysign(double %add, double %conv) nounwind readnone
47 ret double %call
48 }
49
None ; RUN: llc < %s -march=mipsel | FileCheck %s -check-prefix=MIPS32-EL
1 ; RUN: llc < %s -march=mips | FileCheck %s -check-prefix=MIPS32-EB
2 ; RUN: llc < %s -march=mips64el -mcpu=mips64 -mattr=n64 | FileCheck %s -check-prefix=MIPS64
0 ; RUN: llc < %s -march=mipsel -mcpu=mips32 | FileCheck %s -check-prefix=32
1 ; RUN: llc < %s -march=mipsel -mcpu=mips32r2 | FileCheck %s -check-prefix=32R2
2 ; RUN: llc < %s -march=mips64el -mcpu=mips64 -mattr=n64 | FileCheck %s -check-prefix=64
3 ; RUN: llc < %s -march=mips64el -mcpu=mips64r2 -mattr=n64 | FileCheck %s -check-prefix=64R2
34
45 define double @func0(double %d0, double %d1) nounwind readnone {
56 entry:
6 ; MIPS32-EL: func0:
7 ; MIPS32-EL: mfc1 $[[HI0:[0-9]+]], $f15
8 ; MIPS32-EL: lui $[[MSK1:[0-9]+]], 32768
9 ; MIPS32-EL: and $[[AND1:[0-9]+]], $[[HI0]], $[[MSK1]]
10 ; MIPS32-EL: lui $[[T0:[0-9]+]], 32767
11 ; MIPS32-EL: ori $[[MSK0:[0-9]+]], $[[T0]], 65535
12 ; MIPS32-EL: mfc1 $[[HI1:[0-9]+]], $f13
13 ; MIPS32-EL: and $[[AND0:[0-9]+]], $[[HI1]], $[[MSK0]]
14 ; MIPS32-EL: or $[[OR:[0-9]+]], $[[AND0]], $[[AND1]]
15 ; MIPS32-EL: mfc1 $[[LO0:[0-9]+]], $f12
16 ; MIPS32-EL: mtc1 $[[LO0]], $f0
17 ; MIPS32-EL: mtc1 $[[OR]], $f1
187 ;
19 ; MIPS32-EB: mfc1 $[[HI1:[0-9]+]], $f14
20 ; MIPS32-EB: lui $[[MSK1:[0-9]+]], 32768
21 ; MIPS32-EB: and $[[AND1:[0-9]+]], $[[HI1]], $[[MSK1]]
22 ; MIPS32-EB: lui $[[T0:[0-9]+]], 32767
23 ; MIPS32-EB: ori $[[MSK0:[0-9]+]], $[[T0]], 65535
24 ; MIPS32-EB: mfc1 $[[HI0:[0-9]+]], $f12
25 ; MIPS32-EB: and $[[AND0:[0-9]+]], $[[HI0]], $[[MSK0]]
26 ; MIPS32-EB: or $[[OR:[0-9]+]], $[[AND0]], $[[AND1]]
27 ; MIPS32-EB: mfc1 $[[LO0:[0-9]+]], $f13
28 ; MIPS32-EB: mtc1 $[[OR]], $f0
29 ; MIPS32-EB: mtc1 $[[LO0]], $f1
8 ; 32: lui $[[MSK1:[0-9]+]], 32768
9 ; 32: and $[[AND1:[0-9]+]], ${{[0-9]+}}, $[[MSK1]]
10 ; 32: lui $[[T0:[0-9]+]], 32767
11 ; 32: ori $[[MSK0:[0-9]+]], $[[T0]], 65535
12 ; 32: and $[[AND0:[0-9]+]], ${{[0-9]+}}, $[[MSK0]]
13 ; 32: or $[[OR:[0-9]+]], $[[AND0]], $[[AND1]]
14 ; 32: mtc1 $[[OR]], $f1
3015
31 ; MIPS64: dmfc1 $[[R0:[0-9]+]], $f13
32 ; MIPS64: and $[[R1:[0-9]+]], $[[R0]], ${{[0-9]+}}
33 ; MIPS64: dmfc1 $[[R2:[0-9]+]], $f12
34 ; MIPS64: and $[[R3:[0-9]+]], $[[R2]], ${{[0-9]+}}
35 ; MIPS64: or $[[R4:[0-9]+]], $[[R3]], $[[R1]]
36 ; MIPS64: dmtc1 $[[R4]], $f0
16 ; 32R2: ext $[[EXT:[0-9]+]], ${{[0-9]+}}, 31, 1
17 ; 32R2: ins $[[INS:[0-9]+]], $[[EXT]], 31, 1
18 ; 32R2: mtc1 $[[INS]], $f1
19
20 ; 64: daddiu $[[T0:[0-9]+]], $zero, 1
21 ; 64: dsll $[[MSK1:[0-9]+]], $[[T0]], 63
22 ; 64: and $[[AND1:[0-9]+]], ${{[0-9]+}}, $[[MSK1]]
23 ; 64: daddiu $[[MSK0:[0-9]+]], $[[MSK1]], -1
24 ; 64: and $[[AND0:[0-9]+]], ${{[0-9]+}}, $[[MSK0]]
25 ; 64: or $[[OR:[0-9]+]], $[[AND0]], $[[AND1]]
26 ; 64: dmtc1 $[[OR]], $f0
27
28 ; 64R2: dext $[[EXT:[0-9]+]], ${{[0-9]+}}, 63, 1
29 ; 64R2: dins $[[INS:[0-9]+]], $[[EXT]], 63, 1
30 ; 64R2: dmtc1 $[[INS]], $f0
31
3732 %call = tail call double @copysign(double %d0, double %d1) nounwind readnone
3833 ret double %call
3934 }
4237
4338 define float @func1(float %f0, float %f1) nounwind readnone {
4439 entry:
45 ; MIPS32-EL: func1:
46 ; MIPS32-EL: mfc1 $[[ARG1:[0-9]+]], $f14
47 ; MIPS32-EL: lui $[[MSK1:[0-9]+]], 32768
48 ; MIPS32-EL: and $[[T3:[0-9]+]], $[[ARG1]], $[[MSK1]]
49 ; MIPS32-EL: lui $[[T0:[0-9]+]], 32767
50 ; MIPS32-EL: ori $[[MSK0:[0-9]+]], $[[T0]], 65535
51 ; MIPS32-EL: mfc1 $[[ARG0:[0-9]+]], $f12
52 ; MIPS32-EL: and $[[T2:[0-9]+]], $[[ARG0]], $[[MSK0]]
53 ; MIPS32-EL: or $[[T4:[0-9]+]], $[[T2]], $[[T3]]
54 ; MIPS32-EL: mtc1 $[[T4]], $f0
40
41 ; 32: lui $[[MSK1:[0-9]+]], 32768
42 ; 32: and $[[AND1:[0-9]+]], ${{[0-9]+}}, $[[MSK1]]
43 ; 32: lui $[[T0:[0-9]+]], 32767
44 ; 32: ori $[[MSK0:[0-9]+]], $[[T0]], 65535
45 ; 32: and $[[AND0:[0-9]+]], ${{[0-9]+}}, $[[MSK0]]
46 ; 32: or $[[OR:[0-9]+]], $[[AND0]], $[[AND1]]
47 ; 32: mtc1 $[[OR]], $f0
48
49 ; 32R2: ext $[[EXT:[0-9]+]], ${{[0-9]+}}, 31, 1
50 ; 32R2: ins $[[INS:[0-9]+]], $[[EXT]], 31, 1
51 ; 32R2: mtc1 $[[INS]], $f0
52
5553 %call = tail call float @copysignf(float %f0, float %f1) nounwind readnone
5654 ret float %call
5755 }
5856
5957 declare float @copysignf(float, float) nounwind readnone
58