llvm.org GIT mirror llvm / c12a6e6
Emit abs.s or abs.d only if -enable-no-nans-fp-math is supplied by user. Invalid operation is signaled if the operand of these instructions is NaN. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@154545 91177308-0d34-0410-b5e6-96231b3b80d8 Akira Hatanaka 8 years ago
4 changed file(s) with 117 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
146146 setOperationAction(ISD::MEMBARRIER, MVT::Other, Custom);
147147 setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Custom);
148148
149 if (!TM.Options.NoNaNsFPMath) {
150 setOperationAction(ISD::FABS, MVT::f32, Custom);
151 setOperationAction(ISD::FABS, MVT::f64, Custom);
152 }
153
149154 if (HasMips64) {
150155 setOperationAction(ISD::GlobalAddress, MVT::i64, Custom);
151156 setOperationAction(ISD::BlockAddress, MVT::i64, Custom);
733738 case ISD::SETCC: return LowerSETCC(Op, DAG);
734739 case ISD::VASTART: return LowerVASTART(Op, DAG);
735740 case ISD::FCOPYSIGN: return LowerFCOPYSIGN(Op, DAG);
741 case ISD::FABS: return LowerFABS(Op, DAG);
736742 case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG);
737743 case ISD::MEMBARRIER: return LowerMEMBARRIER(Op, DAG);
738744 case ISD::ATOMIC_FENCE: return LowerATOMIC_FENCE(Op, DAG);
18561862 return LowerFCOPYSIGN32(Op, DAG, Subtarget->hasMips32r2());
18571863 }
18581864
1865 static SDValue LowerFABS32(SDValue Op, SelectionDAG &DAG, bool HasR2) {
1866 SDValue Res, Const1 = DAG.getConstant(1, MVT::i32);
1867 DebugLoc DL = Op.getDebugLoc();
1868
1869 // If operand is of type f64, extract the upper 32-bit. Otherwise, bitcast it
1870 // to i32.
1871 SDValue X = (Op.getValueType() == MVT::f32) ?
1872 DAG.getNode(ISD::BITCAST, DL, MVT::i32, Op.getOperand(0)) :
1873 DAG.getNode(MipsISD::ExtractElementF64, DL, MVT::i32, Op.getOperand(0),
1874 Const1);
1875
1876 // Clear MSB.
1877 if (HasR2)
1878 Res = DAG.getNode(MipsISD::Ins, DL, MVT::i32,
1879 DAG.getRegister(Mips::ZERO, MVT::i32),
1880 DAG.getConstant(31, MVT::i32), Const1, X);
1881 else {
1882 SDValue SllX = DAG.getNode(ISD::SHL, DL, MVT::i32, X, Const1);
1883 Res = DAG.getNode(ISD::SRL, DL, MVT::i32, SllX, Const1);
1884 }
1885
1886 if (Op.getValueType() == MVT::f32)
1887 return DAG.getNode(ISD::BITCAST, DL, MVT::f32, Res);
1888
1889 SDValue LowX = DAG.getNode(MipsISD::ExtractElementF64, DL, MVT::i32,
1890 Op.getOperand(0), DAG.getConstant(0, MVT::i32));
1891 return DAG.getNode(MipsISD::BuildPairF64, DL, MVT::f64, LowX, Res);
1892 }
1893
1894 static SDValue LowerFABS64(SDValue Op, SelectionDAG &DAG, bool HasR2) {
1895 SDValue Res, Const1 = DAG.getConstant(1, MVT::i32);
1896 DebugLoc DL = Op.getDebugLoc();
1897
1898 // Bitcast to integer node.
1899 SDValue X = DAG.getNode(ISD::BITCAST, DL, MVT::i64, Op.getOperand(0));
1900
1901 // Clear MSB.
1902 if (HasR2)
1903 Res = DAG.getNode(MipsISD::Ins, DL, MVT::i64,
1904 DAG.getRegister(Mips::ZERO_64, MVT::i64),
1905 DAG.getConstant(63, MVT::i32), Const1, X);
1906 else {
1907 SDValue SllX = DAG.getNode(ISD::SHL, DL, MVT::i64, X, Const1);
1908 Res = DAG.getNode(ISD::SRL, DL, MVT::i64, SllX, Const1);
1909 }
1910
1911 return DAG.getNode(ISD::BITCAST, DL, MVT::f64, Res);
1912 }
1913
1914 SDValue
1915 MipsTargetLowering::LowerFABS(SDValue Op, SelectionDAG &DAG) const {
1916 if (Subtarget->hasMips64() && (Op.getValueType() == MVT::f64))
1917 return LowerFABS64(Op, DAG, Subtarget->hasMips32r2());
1918
1919 return LowerFABS32(Op, DAG, Subtarget->hasMips32r2());
1920 }
1921
18591922 SDValue MipsTargetLowering::
18601923 LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const {
18611924 // check the depth
130130 SDValue LowerSETCC(SDValue Op, SelectionDAG &DAG) const;
131131 SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG) const;
132132 SDValue LowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG) const;
133 SDValue LowerFABS(SDValue Op, SelectionDAG &DAG) const;
133134 SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const;
134135 SDValue LowerMEMBARRIER(SDValue Op, SelectionDAG& DAG) const;
135136 SDValue LowerATOMIC_FENCE(SDValue Op, SelectionDAG& DAG) const;
189189 def CVT_D64_L : FFR1<0x21, 21, "cvt", "d.l", FGR64, FGR64>;
190190 }
191191
192 let Predicates = [NoNaNsFPMath] in
192193 defm FABS : FFR1P_M<0x5, "abs", fabs>;
193194 defm FNEG : FFR1P_M<0x7, "neg", fneg>;
194195 defm FSQRT : FFR1P_M<0x4, "sqrt", fsqrt>;
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
4 ; RUN: llc < %s -march=mipsel -mcpu=mips32 -enable-no-nans-fp-math | FileCheck %s -check-prefix=NO-NAN
5
6 define float @foo0(float %a) nounwind readnone {
7 entry:
8
9 ; 32: lui $[[T0:[0-9]+]], 32767
10 ; 32: ori $[[MSK0:[0-9]+]], $[[T0]], 65535
11 ; 32: and $[[AND:[0-9]+]], ${{[0-9]+}}, $[[MSK0]]
12 ; 32: mtc1 $[[AND]], $f0
13
14 ; 32R2: ins $[[INS:[0-9]+]], $zero, 31, 1
15 ; 32R2: mtc1 $[[INS]], $f0
16
17 ; NO-NAN: abs.s
18
19 %call = tail call float @fabsf(float %a) nounwind readnone
20 ret float %call
21 }
22
23 declare float @fabsf(float) nounwind readnone
24
25 define double @foo1(double %a) nounwind readnone {
26 entry:
27
28 ; 32: lui $[[T0:[0-9]+]], 32767
29 ; 32: ori $[[MSK0:[0-9]+]], $[[T0]], 65535
30 ; 32: and $[[AND:[0-9]+]], ${{[0-9]+}}, $[[MSK0]]
31 ; 32: mtc1 $[[AND]], $f1
32
33 ; 32R2: ins $[[INS:[0-9]+]], $zero, 31, 1
34 ; 32R2: mtc1 $[[INS]], $f1
35
36 ; 64: daddiu $[[T0:[0-9]+]], $zero, 1
37 ; 64: dsll $[[T1:[0-9]+]], ${{[0-9]+}}, 63
38 ; 64: daddiu $[[MSK0:[0-9]+]], $[[T1]], -1
39 ; 64: and $[[AND:[0-9]+]], ${{[0-9]+}}, $[[MSK0]]
40 ; 64: dmtc1 $[[AND]], $f0
41
42 ; 64R2: dins $[[INS:[0-9]+]], $zero, 63, 1
43 ; 64R2: dmtc1 $[[INS]], $f0
44
45 ; NO-NAN: abs.d
46
47 %call = tail call double @fabs(double %a) nounwind readnone
48 ret double %call
49 }
50
51 declare double @fabs(double) nounwind readnone