1Pull in r202422 from upstream llvm trunk (by Roman Divacky): 2 3 Lower FNEG just like FABS to fneg[ds] and fmov[ds], thus avoiding 4 expensive libcall. Also, Qp_neg is not implemented on at least 5 FreeBSD. This is also what gcc is doing. 6 7Introduced here: http://svn.freebsd.org/changeset/base/262582 8 9Index: lib/Target/Sparc/SparcISelLowering.cpp 10=================================================================== 11--- lib/Target/Sparc/SparcISelLowering.cpp 12+++ lib/Target/Sparc/SparcISelLowering.cpp 13@@ -2643,24 +2643,16 @@ static SDValue LowerF128Store(SDValue Op, Selectio 14 &OutChains[0], 2); 15 } 16 17-static SDValue LowerFNEG(SDValue Op, SelectionDAG &DAG, 18- const SparcTargetLowering &TLI, 19- bool is64Bit) { 20- if (Op.getValueType() == MVT::f64) 21- return LowerF64Op(Op, DAG, ISD::FNEG); 22- if (Op.getValueType() == MVT::f128) 23- return TLI.LowerF128Op(Op, DAG, ((is64Bit) ? "_Qp_neg" : "_Q_neg"), 1); 24- return Op; 25-} 26+static SDValue LowerFNEGorFABS(SDValue Op, SelectionDAG &DAG, bool isV9) { 27+ assert((Op.getOpcode() == ISD::FNEG || Op.getOpcode() == ISD::FABS) && "invalid"); 28 29-static SDValue LowerFABS(SDValue Op, SelectionDAG &DAG, bool isV9) { 30 if (Op.getValueType() == MVT::f64) 31- return LowerF64Op(Op, DAG, ISD::FABS); 32+ return LowerF64Op(Op, DAG, Op.getOpcode()); 33 if (Op.getValueType() != MVT::f128) 34 return Op; 35 36- // Lower fabs on f128 to fabs on f64 37- // fabs f128 => fabs f64:sub_even64, fmov f64:sub_odd64 38+ // Lower fabs/fneg on f128 to fabs/fneg on f64 39+ // fabs/fneg f128 => fabs/fneg f64:sub_even64, fmov f64:sub_odd64 40 41 SDLoc dl(Op); 42 SDValue SrcReg128 = Op.getOperand(0); 43@@ -2671,7 +2663,7 @@ static SDValue LowerF128Store(SDValue Op, Selectio 44 if (isV9) 45 Hi64 = DAG.getNode(Op.getOpcode(), dl, MVT::f64, Hi64); 46 else 47- Hi64 = LowerF64Op(Hi64, DAG, ISD::FABS); 48+ Hi64 = LowerF64Op(Hi64, DAG, Op.getOpcode()); 49 50 SDValue DstReg128 = SDValue(DAG.getMachineNode(TargetOpcode::IMPLICIT_DEF, 51 dl, MVT::f128), 0); 52@@ -2792,7 +2784,6 @@ SDValue SparcTargetLowering:: 53 LowerOperation(SDValue Op, SelectionDAG &DAG) const { 54 55 bool hasHardQuad = Subtarget->hasHardQuad(); 56- bool is64Bit = Subtarget->is64Bit(); 57 bool isV9 = Subtarget->isV9(); 58 59 switch (Op.getOpcode()) { 60@@ -2835,8 +2826,8 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) cons 61 getLibcallName(RTLIB::DIV_F128), 2); 62 case ISD::FSQRT: return LowerF128Op(Op, DAG, 63 getLibcallName(RTLIB::SQRT_F128),1); 64- case ISD::FNEG: return LowerFNEG(Op, DAG, *this, is64Bit); 65- case ISD::FABS: return LowerFABS(Op, DAG, isV9); 66+ case ISD::FABS: 67+ case ISD::FNEG: return LowerFNEGorFABS(Op, DAG, isV9); 68 case ISD::FP_EXTEND: return LowerF128_FPEXTEND(Op, DAG, *this); 69 case ISD::FP_ROUND: return LowerF128_FPROUND(Op, DAG, *this); 70 case ISD::ADDC: 71Index: test/CodeGen/SPARC/fp128.ll 72=================================================================== 73--- test/CodeGen/SPARC/fp128.ll 74+++ test/CodeGen/SPARC/fp128.ll 75@@ -232,3 +232,14 @@ entry: 76 store i32 %3, i32* %4, align 8 77 ret void 78 } 79+ 80+; SOFT-LABEL: f128_neg 81+; SOFT: fnegs 82+ 83+define void @f128_neg(fp128* noalias sret %scalar.result, fp128* byval %a) { 84+entry: 85+ %0 = load fp128* %a, align 8 86+ %1 = fsub fp128 0xL00000000000000008000000000000000, %0 87+ store fp128 %1, fp128* %scalar.result, align 8 88+ ret void 89+} 90