summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoman Divacky <rdivacky@freebsd.org>2014-02-27 19:26:29 +0000
committerRoman Divacky <rdivacky@freebsd.org>2014-02-27 19:26:29 +0000
commit14551f041b36f4d224db5945e3433d384ecc6a7f (patch)
tree96ac97d421c56e6cc8d5ae0629c079d836201ef7
parent3e31a5684a48748b469ecd2227490ca2d261bb7a (diff)
downloadllvm-14551f041b36f4d224db5945e3433d384ecc6a7f.tar.gz
llvm-14551f041b36f4d224db5945e3433d384ecc6a7f.tar.bz2
llvm-14551f041b36f4d224db5945e3433d384ecc6a7f.tar.xz
Lower FNEG just like FABS to fneg[ds] and fmov[ds], thus avoiding
expensive libcall. Also, Qp_neg is not implemented on at least FreeBSD. This is also what gcc is doing. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@202422 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Target/Sparc/SparcISelLowering.cpp25
-rw-r--r--test/CodeGen/SPARC/fp128.ll11
2 files changed, 19 insertions, 17 deletions
diff --git a/lib/Target/Sparc/SparcISelLowering.cpp b/lib/Target/Sparc/SparcISelLowering.cpp
index 2ac5b7e8c2..632cc2b8b7 100644
--- a/lib/Target/Sparc/SparcISelLowering.cpp
+++ b/lib/Target/Sparc/SparcISelLowering.cpp
@@ -2648,24 +2648,16 @@ static SDValue LowerF128Store(SDValue Op, SelectionDAG &DAG) {
&OutChains[0], 2);
}
-static SDValue LowerFNEG(SDValue Op, SelectionDAG &DAG,
- const SparcTargetLowering &TLI,
- bool is64Bit) {
- if (Op.getValueType() == MVT::f64)
- return LowerF64Op(Op, DAG, ISD::FNEG);
- if (Op.getValueType() == MVT::f128)
- return TLI.LowerF128Op(Op, DAG, ((is64Bit) ? "_Qp_neg" : "_Q_neg"), 1);
- return Op;
-}
+static SDValue LowerFNEGorFABS(SDValue Op, SelectionDAG &DAG, bool isV9) {
+ assert((Op.getOpcode() == ISD::FNEG || Op.getOpcode() == ISD::FABS) && "invalid");
-static SDValue LowerFABS(SDValue Op, SelectionDAG &DAG, bool isV9) {
if (Op.getValueType() == MVT::f64)
- return LowerF64Op(Op, DAG, ISD::FABS);
+ return LowerF64Op(Op, DAG, Op.getOpcode());
if (Op.getValueType() != MVT::f128)
return Op;
- // Lower fabs on f128 to fabs on f64
- // fabs f128 => fabs f64:sub_even64, fmov f64:sub_odd64
+ // Lower fabs/fneg on f128 to fabs/fneg on f64
+ // fabs/fneg f128 => fabs/fneg f64:sub_even64, fmov f64:sub_odd64
SDLoc dl(Op);
SDValue SrcReg128 = Op.getOperand(0);
@@ -2676,7 +2668,7 @@ static SDValue LowerFABS(SDValue Op, SelectionDAG &DAG, bool isV9) {
if (isV9)
Hi64 = DAG.getNode(Op.getOpcode(), dl, MVT::f64, Hi64);
else
- Hi64 = LowerF64Op(Hi64, DAG, ISD::FABS);
+ Hi64 = LowerF64Op(Hi64, DAG, Op.getOpcode());
SDValue DstReg128 = SDValue(DAG.getMachineNode(TargetOpcode::IMPLICIT_DEF,
dl, MVT::f128), 0);
@@ -2797,7 +2789,6 @@ SDValue SparcTargetLowering::
LowerOperation(SDValue Op, SelectionDAG &DAG) const {
bool hasHardQuad = Subtarget->hasHardQuad();
- bool is64Bit = Subtarget->is64Bit();
bool isV9 = Subtarget->isV9();
switch (Op.getOpcode()) {
@@ -2840,8 +2831,8 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) const {
getLibcallName(RTLIB::DIV_F128), 2);
case ISD::FSQRT: return LowerF128Op(Op, DAG,
getLibcallName(RTLIB::SQRT_F128),1);
- case ISD::FNEG: return LowerFNEG(Op, DAG, *this, is64Bit);
- case ISD::FABS: return LowerFABS(Op, DAG, isV9);
+ case ISD::FABS:
+ case ISD::FNEG: return LowerFNEGorFABS(Op, DAG, isV9);
case ISD::FP_EXTEND: return LowerF128_FPEXTEND(Op, DAG, *this);
case ISD::FP_ROUND: return LowerF128_FPROUND(Op, DAG, *this);
case ISD::ADDC:
diff --git a/test/CodeGen/SPARC/fp128.ll b/test/CodeGen/SPARC/fp128.ll
index 37e759ff9e..abd89bf264 100644
--- a/test/CodeGen/SPARC/fp128.ll
+++ b/test/CodeGen/SPARC/fp128.ll
@@ -232,3 +232,14 @@ entry:
store i32 %3, i32* %4, align 8
ret void
}
+
+; SOFT-LABEL: f128_neg
+; SOFT: fnegs
+
+define void @f128_neg(fp128* noalias sret %scalar.result, fp128* byval %a) {
+entry:
+ %0 = load fp128* %a, align 8
+ %1 = fsub fp128 0xL00000000000000008000000000000000, %0
+ store fp128 %1, fp128* %scalar.result, align 8
+ ret void
+}