Index: include/llvm/CodeGen/TargetLowering.h =================================================================== --- include/llvm/CodeGen/TargetLowering.h +++ include/llvm/CodeGen/TargetLowering.h @@ -1738,6 +1738,16 @@ return false; } + /// Return true if it is more correct/profitable to use strict FP_TO_INT + /// conversion operations - canonicalizing the FP source value instead of + /// converting all cases and then selecting based on value. + /// This may be true if the target throws exceptions for out of bounds + /// conversions or has fast FP CMOV. + virtual bool shouldUseStrictFP_TO_INT(EVT FpVT, EVT IntVT, + bool IsSigned) const { + return false; + } + //===--------------------------------------------------------------------===// // TargetLowering Configuration Methods - These methods should be invoked by // the derived class constructor to configure this object for the target. Index: lib/CodeGen/SelectionDAG/TargetLowering.cpp =================================================================== --- lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -4154,24 +4154,50 @@ !isOperationLegalOrCustomOrPromote(ISD::XOR, SrcVT))) return false; - // Expand based on maximum range of FP_TO_SINT: - // True = fp_to_sint(Src) - // False = 0x8000000000000000 + fp_to_sint(Src - 0x8000000000000000) - // Result = select (Src < 0x8000000000000000), True, False - APFloat apf(DAG.EVTToAPFloatSemantics(SrcVT), - APInt::getNullValue(SrcVT.getScalarSizeInBits())); - APInt x = APInt::getSignMask(DstVT.getScalarSizeInBits()); - (void)apf.convertFromAPInt(x, false, APFloat::rmNearestTiesToEven); - - SDValue Tmp1 = DAG.getConstantFP(apf, dl, SrcVT); - SDValue Tmp2 = DAG.getSetCC(dl, SetCCVT, Src, Tmp1, ISD::SETLT); - SDValue True = DAG.getNode(ISD::FP_TO_SINT, dl, DstVT, Src); - // TODO: Should any fast-math-flags be set for the FSUB? - SDValue False = DAG.getNode(ISD::FP_TO_SINT, dl, DstVT, - DAG.getNode(ISD::FSUB, dl, SrcVT, Src, Tmp1)); - False = - DAG.getNode(ISD::XOR, dl, DstVT, False, DAG.getConstant(x, dl, DstVT)); - Result = DAG.getSelect(dl, DstVT, Tmp2, True, False); + // If the destination signmask can't be represented by the float, then we can + // just use FP_TO_SINT directly. + const fltSemantics &APFSem = DAG.EVTToAPFloatSemantics(SrcVT); + APFloat APF(APFSem, APInt::getNullValue(SrcVT.getScalarSizeInBits())); + APInt SignMask = APInt::getSignMask(DstVT.getScalarSizeInBits()); + if (APFloat::opOverflow & + APF.convertFromAPInt(SignMask, false, APFloat::rmNearestTiesToEven)) { + Result = DAG.getNode(ISD::FP_TO_SINT, dl, DstVT, Src); + return true; + } + + SDValue Cst = DAG.getConstantFP(APF, dl, SrcVT); + SDValue Sel = DAG.getSetCC(dl, SetCCVT, Src, Cst, ISD::SETLT); + + bool Strict = shouldUseStrictFP_TO_INT(SrcVT, DstVT, false); + if (Strict) { + // Expand based on maximum range of FP_TO_SINT, if the value exceeds the + // signmask then offset (f32/f64 results should then be whole integers). + // Sel = Src < 0x8000000000000000 + // Val = select Sel, Src, Src - 0x8000000000000000 + // Ofs = select Sel, 0, 0x8000000000000000 + // Result = fp_to_sint(Val) ^ Ofs + + // TODO: Should any fast-math-flags be set for the FSUB? + SDValue Val = DAG.getSelect(dl, SrcVT, Sel, Src, + DAG.getNode(ISD::FSUB, dl, SrcVT, Src, Cst)); + SDValue Ofs = DAG.getSelect(dl, DstVT, Sel, DAG.getConstant(0, dl, DstVT), + DAG.getConstant(SignMask, dl, DstVT)); + Result = DAG.getNode(ISD::XOR, dl, DstVT, + DAG.getNode(ISD::FP_TO_SINT, dl, DstVT, Val), Ofs); + } else { + // Expand based on maximum range of FP_TO_SINT: + // True = fp_to_sint(Src) + // False = 0x8000000000000000 + fp_to_sint(Src - 0x8000000000000000) + // Result = select (Src < 0x8000000000000000), True, False + + SDValue True = DAG.getNode(ISD::FP_TO_SINT, dl, DstVT, Src); + // TODO: Should any fast-math-flags be set for the FSUB? + SDValue False = DAG.getNode(ISD::FP_TO_SINT, dl, DstVT, + DAG.getNode(ISD::FSUB, dl, SrcVT, Src, Cst)); + False = DAG.getNode(ISD::XOR, dl, DstVT, False, + DAG.getConstant(SignMask, dl, DstVT)); + Result = DAG.getSelect(dl, DstVT, Sel, True, False); + } return true; } Index: lib/Target/X86/X86ISelLowering.h =================================================================== --- lib/Target/X86/X86ISelLowering.h +++ lib/Target/X86/X86ISelLowering.h @@ -1045,6 +1045,9 @@ bool decomposeMulByConstant(EVT VT, SDValue C) const override; + bool shouldUseStrictFP_TO_INT(EVT FpVT, EVT IntVT, + bool IsSigned) const override; + /// Return true if EXTRACT_SUBVECTOR is cheap for this result type /// with this index. bool isExtractSubvectorCheap(EVT ResVT, EVT SrcVT, Index: lib/Target/X86/X86ISelLowering.cpp =================================================================== --- lib/Target/X86/X86ISelLowering.cpp +++ lib/Target/X86/X86ISelLowering.cpp @@ -4773,6 +4773,12 @@ (1 - MulC).isPowerOf2() || (-(MulC + 1)).isPowerOf2(); } +bool X86TargetLowering::shouldUseStrictFP_TO_INT(EVT FpVT, EVT IntVT, + bool IsSigned) const { + // f80 UINT_TO_FP is more efficient using Strict code if FCMOV is available. + return !IsSigned && FpVT == MVT::f80 && Subtarget.hasCMov(); +} + bool X86TargetLowering::isExtractSubvectorCheap(EVT ResVT, EVT SrcVT, unsigned Index) const { if (!isOperationLegalOrCustom(ISD::EXTRACT_SUBVECTOR, ResVT)) Index: test/CodeGen/Mips/msa/f16-llvm-ir.ll =================================================================== --- test/CodeGen/Mips/msa/f16-llvm-ir.ll +++ test/CodeGen/Mips/msa/f16-llvm-ir.ll @@ -252,259 +252,58 @@ } define i32 @ffptoui() { -; MIPS32-O32-LABEL: ffptoui: -; MIPS32-O32: # %bb.0: # %entry -; MIPS32-O32-NEXT: lui $2, %hi(_gp_disp) -; MIPS32-O32-NEXT: addiu $2, $2, %lo(_gp_disp) -; MIPS32-O32-NEXT: addu $1, $2, $25 -; MIPS32-O32-NEXT: lw $2, %got(h)($1) -; MIPS32-O32-NEXT: lw $3, %got($CPI3_0)($1) -; MIPS32-O32-NEXT: lwc1 $f0, %lo($CPI3_0)($3) -; MIPS32-O32-NEXT: lh $2, 0($2) -; MIPS32-O32-NEXT: fill.h $w1, $2 -; MIPS32-O32-NEXT: fexupr.w $w1, $w1 -; MIPS32-O32-NEXT: copy_s.w $2, $w1[0] -; MIPS32-O32-NEXT: mtc1 $2, $f2 -; MIPS32-O32-NEXT: sub.s $f0, $f2, $f0 -; MIPS32-O32-NEXT: mfc1 $2, $f0 -; MIPS32-O32-NEXT: fill.w $w0, $2 -; MIPS32-O32-NEXT: fexdo.h $w0, $w0, $w0 -; MIPS32-O32-NEXT: fexupr.w $w0, $w0 -; MIPS32-O32-NEXT: fexupr.d $w0, $w0 -; MIPS32-O32-NEXT: copy_s.w $2, $w0[0] -; MIPS32-O32-NEXT: mtc1 $2, $f3 -; MIPS32-O32-NEXT: copy_s.w $2, $w0[1] -; MIPS32-O32-NEXT: mthc1 $2, $f3 -; MIPS32-O32-NEXT: trunc.w.d $f0, $f3 -; MIPS32-O32-NEXT: mfc1 $2, $f0 -; MIPS32-O32-NEXT: fexupr.d $w0, $w1 -; MIPS32-O32-NEXT: copy_s.w $3, $w0[0] -; MIPS32-O32-NEXT: mtc1 $3, $f1 -; MIPS32-O32-NEXT: copy_s.w $3, $w0[1] -; MIPS32-O32-NEXT: mthc1 $3, $f1 -; MIPS32-O32-NEXT: trunc.w.d $f0, $f1 -; MIPS32-O32-NEXT: mfc1 $3, $f0 -; MIPS32-O32-NEXT: lw $1, %got($CPI3_1)($1) -; MIPS32-O32-NEXT: addiu $1, $1, %lo($CPI3_1) -; MIPS32-O32-NEXT: lui $4, 32768 -; MIPS32-O32-NEXT: xor $2, $2, $4 -; MIPS32-O32-NEXT: lh $1, 0($1) -; MIPS32-O32-NEXT: fill.h $w0, $1 -; MIPS32-O32-NEXT: fexupr.w $w0, $w0 -; MIPS32-O32-NEXT: copy_s.w $1, $w0[0] -; MIPS32-O32-NEXT: mtc1 $1, $f0 -; MIPS32-O32-NEXT: c.olt.s $f2, $f0 -; MIPS32-O32-NEXT: jr $ra -; MIPS32-O32-NEXT: movt $2, $3, $fcc0 -; -; MIPS64R5-N32-LABEL: ffptoui: -; MIPS64R5-N32: # %bb.0: # %entry -; MIPS64R5-N32-NEXT: lui $1, %hi(%neg(%gp_rel(ffptoui))) -; MIPS64R5-N32-NEXT: addu $1, $1, $25 -; MIPS64R5-N32-NEXT: addiu $1, $1, %lo(%neg(%gp_rel(ffptoui))) -; MIPS64R5-N32-NEXT: lw $2, %got_disp(h)($1) -; MIPS64R5-N32-NEXT: lw $3, %got_page(.LCPI3_0)($1) -; MIPS64R5-N32-NEXT: lwc1 $f0, %got_ofst(.LCPI3_0)($3) -; MIPS64R5-N32-NEXT: lh $2, 0($2) -; MIPS64R5-N32-NEXT: fill.h $w1, $2 -; MIPS64R5-N32-NEXT: fexupr.w $w1, $w1 -; MIPS64R5-N32-NEXT: copy_s.w $2, $w1[0] -; MIPS64R5-N32-NEXT: mtc1 $2, $f2 -; MIPS64R5-N32-NEXT: sub.s $f0, $f2, $f0 -; MIPS64R5-N32-NEXT: mfc1 $2, $f0 -; MIPS64R5-N32-NEXT: fill.w $w0, $2 -; MIPS64R5-N32-NEXT: fexdo.h $w0, $w0, $w0 -; MIPS64R5-N32-NEXT: fexupr.w $w0, $w0 -; MIPS64R5-N32-NEXT: fexupr.d $w0, $w0 -; MIPS64R5-N32-NEXT: copy_s.d $2, $w0[0] -; MIPS64R5-N32-NEXT: dmtc1 $2, $f0 -; MIPS64R5-N32-NEXT: trunc.w.d $f0, $f0 -; MIPS64R5-N32-NEXT: mfc1 $2, $f0 -; MIPS64R5-N32-NEXT: fexupr.d $w0, $w1 -; MIPS64R5-N32-NEXT: copy_s.d $3, $w0[0] -; MIPS64R5-N32-NEXT: dmtc1 $3, $f0 -; MIPS64R5-N32-NEXT: trunc.w.d $f0, $f0 -; MIPS64R5-N32-NEXT: mfc1 $3, $f0 -; MIPS64R5-N32-NEXT: lw $1, %got_page(.LCPI3_1)($1) -; MIPS64R5-N32-NEXT: addiu $1, $1, %got_ofst(.LCPI3_1) -; MIPS64R5-N32-NEXT: lui $4, 32768 -; MIPS64R5-N32-NEXT: xor $2, $2, $4 -; MIPS64R5-N32-NEXT: lh $1, 0($1) -; MIPS64R5-N32-NEXT: fill.h $w0, $1 -; MIPS64R5-N32-NEXT: fexupr.w $w0, $w0 -; MIPS64R5-N32-NEXT: copy_s.w $1, $w0[0] -; MIPS64R5-N32-NEXT: mtc1 $1, $f0 -; MIPS64R5-N32-NEXT: c.olt.s $f2, $f0 -; MIPS64R5-N32-NEXT: jr $ra -; MIPS64R5-N32-NEXT: movt $2, $3, $fcc0 -; -; MIPS64R5-N64-LABEL: ffptoui: -; MIPS64R5-N64: # %bb.0: # %entry -; MIPS64R5-N64-NEXT: lui $1, %hi(%neg(%gp_rel(ffptoui))) -; MIPS64R5-N64-NEXT: daddu $1, $1, $25 -; MIPS64R5-N64-NEXT: daddiu $1, $1, %lo(%neg(%gp_rel(ffptoui))) -; MIPS64R5-N64-NEXT: ld $2, %got_disp(h)($1) -; MIPS64R5-N64-NEXT: ld $3, %got_page(.LCPI3_0)($1) -; MIPS64R5-N64-NEXT: lwc1 $f0, %got_ofst(.LCPI3_0)($3) -; MIPS64R5-N64-NEXT: lh $2, 0($2) -; MIPS64R5-N64-NEXT: fill.h $w1, $2 -; MIPS64R5-N64-NEXT: fexupr.w $w1, $w1 -; MIPS64R5-N64-NEXT: copy_s.w $2, $w1[0] -; MIPS64R5-N64-NEXT: mtc1 $2, $f2 -; MIPS64R5-N64-NEXT: sub.s $f0, $f2, $f0 -; MIPS64R5-N64-NEXT: mfc1 $2, $f0 -; MIPS64R5-N64-NEXT: fill.w $w0, $2 -; MIPS64R5-N64-NEXT: fexdo.h $w0, $w0, $w0 -; MIPS64R5-N64-NEXT: fexupr.w $w0, $w0 -; MIPS64R5-N64-NEXT: fexupr.d $w0, $w0 -; MIPS64R5-N64-NEXT: copy_s.d $2, $w0[0] -; MIPS64R5-N64-NEXT: dmtc1 $2, $f0 -; MIPS64R5-N64-NEXT: trunc.w.d $f0, $f0 -; MIPS64R5-N64-NEXT: mfc1 $2, $f0 -; MIPS64R5-N64-NEXT: fexupr.d $w0, $w1 -; MIPS64R5-N64-NEXT: copy_s.d $3, $w0[0] -; MIPS64R5-N64-NEXT: dmtc1 $3, $f0 -; MIPS64R5-N64-NEXT: trunc.w.d $f0, $f0 -; MIPS64R5-N64-NEXT: mfc1 $3, $f0 -; MIPS64R5-N64-NEXT: ld $1, %got_page(.LCPI3_1)($1) -; MIPS64R5-N64-NEXT: daddiu $1, $1, %got_ofst(.LCPI3_1) -; MIPS64R5-N64-NEXT: lui $4, 32768 -; MIPS64R5-N64-NEXT: xor $2, $2, $4 -; MIPS64R5-N64-NEXT: lh $1, 0($1) -; MIPS64R5-N64-NEXT: fill.h $w0, $1 -; MIPS64R5-N64-NEXT: fexupr.w $w0, $w0 -; MIPS64R5-N64-NEXT: copy_s.w $1, $w0[0] -; MIPS64R5-N64-NEXT: mtc1 $1, $f0 -; MIPS64R5-N64-NEXT: c.olt.s $f2, $f0 -; MIPS64R5-N64-NEXT: jr $ra -; MIPS64R5-N64-NEXT: movt $2, $3, $fcc0 -; -; MIPSR6-O32-LABEL: ffptoui: -; MIPSR6-O32: # %bb.0: # %entry -; MIPSR6-O32-NEXT: lui $2, %hi(_gp_disp) -; MIPSR6-O32-NEXT: addiu $2, $2, %lo(_gp_disp) -; MIPSR6-O32-NEXT: addu $1, $2, $25 -; MIPSR6-O32-NEXT: lw $2, %got(h)($1) -; MIPSR6-O32-NEXT: lw $1, %got($CPI3_0)($1) -; MIPSR6-O32-NEXT: lwc1 $f0, %lo($CPI3_0)($1) -; MIPSR6-O32-NEXT: lh $1, 0($2) -; MIPSR6-O32-NEXT: fill.h $w1, $1 -; MIPSR6-O32-NEXT: fexupr.w $w1, $w1 -; MIPSR6-O32-NEXT: copy_s.w $1, $w1[0] -; MIPSR6-O32-NEXT: mtc1 $1, $f2 -; MIPSR6-O32-NEXT: cmp.lt.s $f3, $f2, $f0 -; MIPSR6-O32-NEXT: sub.s $f0, $f2, $f0 -; MIPSR6-O32-NEXT: mfc1 $1, $f0 -; MIPSR6-O32-NEXT: fill.w $w0, $1 -; MIPSR6-O32-NEXT: fexdo.h $w0, $w0, $w0 -; MIPSR6-O32-NEXT: fexupr.w $w0, $w0 -; MIPSR6-O32-NEXT: fexupr.d $w0, $w0 -; MIPSR6-O32-NEXT: copy_s.w $1, $w0[0] -; MIPSR6-O32-NEXT: mtc1 $1, $f2 -; MIPSR6-O32-NEXT: copy_s.w $1, $w0[1] -; MIPSR6-O32-NEXT: mthc1 $1, $f2 -; MIPSR6-O32-NEXT: trunc.w.d $f0, $f2 -; MIPSR6-O32-NEXT: mfc1 $1, $f0 -; MIPSR6-O32-NEXT: fexupr.d $w0, $w1 -; MIPSR6-O32-NEXT: copy_s.w $2, $w0[0] -; MIPSR6-O32-NEXT: mtc1 $2, $f1 -; MIPSR6-O32-NEXT: copy_s.w $2, $w0[1] -; MIPSR6-O32-NEXT: mthc1 $2, $f1 -; MIPSR6-O32-NEXT: trunc.w.d $f0, $f1 -; MIPSR6-O32-NEXT: mfc1 $2, $f0 -; MIPSR6-O32-NEXT: lui $3, 32768 -; MIPSR6-O32-NEXT: xor $1, $1, $3 -; MIPSR6-O32-NEXT: mfc1 $3, $f3 -; MIPSR6-O32-NEXT: seleqz $1, $1, $3 -; MIPSR6-O32-NEXT: selnez $2, $2, $3 -; MIPSR6-O32-NEXT: jr $ra -; MIPSR6-O32-NEXT: or $2, $2, $1 +; MIPS32-LABEL: ffptoui: +; MIPS32: # %bb.0: # %entry +; MIPS32-NEXT: lui $2, %hi(_gp_disp) +; MIPS32-NEXT: addiu $2, $2, %lo(_gp_disp) +; MIPS32-NEXT: addu $1, $2, $25 +; MIPS32-NEXT: lw $1, %got(h)($1) +; MIPS32-NEXT: lh $1, 0($1) +; MIPS32-NEXT: fill.h $w0, $1 +; MIPS32-NEXT: fexupr.w $w0, $w0 +; MIPS32-NEXT: fexupr.d $w0, $w0 +; MIPS32-NEXT: copy_s.w $1, $w0[0] +; MIPS32-NEXT: mtc1 $1, $f1 +; MIPS32-NEXT: copy_s.w $1, $w0[1] +; MIPS32-NEXT: mthc1 $1, $f1 +; MIPS32-NEXT: trunc.w.d $f0, $f1 +; MIPS32-NEXT: jr $ra +; MIPS32-NEXT: mfc1 $2, $f0 ; -; MIPSR6-N32-LABEL: ffptoui: -; MIPSR6-N32: # %bb.0: # %entry -; MIPSR6-N32-NEXT: lui $1, %hi(%neg(%gp_rel(ffptoui))) -; MIPSR6-N32-NEXT: addu $1, $1, $25 -; MIPSR6-N32-NEXT: addiu $1, $1, %lo(%neg(%gp_rel(ffptoui))) -; MIPSR6-N32-NEXT: lw $2, %got_disp(h)($1) -; MIPSR6-N32-NEXT: lw $1, %got_page(.LCPI3_0)($1) -; MIPSR6-N32-NEXT: lwc1 $f0, %got_ofst(.LCPI3_0)($1) -; MIPSR6-N32-NEXT: lh $1, 0($2) -; MIPSR6-N32-NEXT: fill.h $w1, $1 -; MIPSR6-N32-NEXT: fexupr.w $w1, $w1 -; MIPSR6-N32-NEXT: copy_s.w $1, $w1[0] -; MIPSR6-N32-NEXT: mtc1 $1, $f2 -; MIPSR6-N32-NEXT: cmp.lt.s $f3, $f2, $f0 -; MIPSR6-N32-NEXT: sub.s $f0, $f2, $f0 -; MIPSR6-N32-NEXT: mfc1 $1, $f0 -; MIPSR6-N32-NEXT: fill.w $w0, $1 -; MIPSR6-N32-NEXT: fexdo.h $w0, $w0, $w0 -; MIPSR6-N32-NEXT: fexupr.w $w0, $w0 -; MIPSR6-N32-NEXT: fexupr.d $w0, $w0 -; MIPSR6-N32-NEXT: copy_s.d $1, $w0[0] -; MIPSR6-N32-NEXT: dmtc1 $1, $f0 -; MIPSR6-N32-NEXT: trunc.w.d $f0, $f0 -; MIPSR6-N32-NEXT: mfc1 $1, $f0 -; MIPSR6-N32-NEXT: fexupr.d $w0, $w1 -; MIPSR6-N32-NEXT: copy_s.d $2, $w0[0] -; MIPSR6-N32-NEXT: dmtc1 $2, $f0 -; MIPSR6-N32-NEXT: trunc.w.d $f0, $f0 -; MIPSR6-N32-NEXT: mfc1 $2, $f0 -; MIPSR6-N32-NEXT: lui $3, 32768 -; MIPSR6-N32-NEXT: xor $1, $1, $3 -; MIPSR6-N32-NEXT: mfc1 $3, $f3 -; MIPSR6-N32-NEXT: seleqz $1, $1, $3 -; MIPSR6-N32-NEXT: selnez $2, $2, $3 -; MIPSR6-N32-NEXT: jr $ra -; MIPSR6-N32-NEXT: or $2, $2, $1 +; MIPS64-N32-LABEL: ffptoui: +; MIPS64-N32: # %bb.0: # %entry +; MIPS64-N32-NEXT: lui $1, %hi(%neg(%gp_rel(ffptoui))) +; MIPS64-N32-NEXT: addu $1, $1, $25 +; MIPS64-N32-NEXT: addiu $1, $1, %lo(%neg(%gp_rel(ffptoui))) +; MIPS64-N32-NEXT: lw $1, %got_disp(h)($1) +; MIPS64-N32-NEXT: lh $1, 0($1) +; MIPS64-N32-NEXT: fill.h $w0, $1 +; MIPS64-N32-NEXT: fexupr.w $w0, $w0 +; MIPS64-N32-NEXT: fexupr.d $w0, $w0 +; MIPS64-N32-NEXT: copy_s.d $1, $w0[0] +; MIPS64-N32-NEXT: dmtc1 $1, $f0 +; MIPS64-N32-NEXT: trunc.w.d $f0, $f0 +; MIPS64-N32-NEXT: jr $ra +; MIPS64-N32-NEXT: mfc1 $2, $f0 ; -; MIPSR6-N64-LABEL: ffptoui: -; MIPSR6-N64: # %bb.0: # %entry -; MIPSR6-N64-NEXT: lui $1, %hi(%neg(%gp_rel(ffptoui))) -; MIPSR6-N64-NEXT: daddu $1, $1, $25 -; MIPSR6-N64-NEXT: daddiu $1, $1, %lo(%neg(%gp_rel(ffptoui))) -; MIPSR6-N64-NEXT: ld $2, %got_disp(h)($1) -; MIPSR6-N64-NEXT: ld $1, %got_page(.LCPI3_0)($1) -; MIPSR6-N64-NEXT: lwc1 $f0, %got_ofst(.LCPI3_0)($1) -; MIPSR6-N64-NEXT: lh $1, 0($2) -; MIPSR6-N64-NEXT: fill.h $w1, $1 -; MIPSR6-N64-NEXT: fexupr.w $w1, $w1 -; MIPSR6-N64-NEXT: copy_s.w $1, $w1[0] -; MIPSR6-N64-NEXT: mtc1 $1, $f2 -; MIPSR6-N64-NEXT: cmp.lt.s $f3, $f2, $f0 -; MIPSR6-N64-NEXT: sub.s $f0, $f2, $f0 -; MIPSR6-N64-NEXT: mfc1 $1, $f0 -; MIPSR6-N64-NEXT: fill.w $w0, $1 -; MIPSR6-N64-NEXT: fexdo.h $w0, $w0, $w0 -; MIPSR6-N64-NEXT: fexupr.w $w0, $w0 -; MIPSR6-N64-NEXT: fexupr.d $w0, $w0 -; MIPSR6-N64-NEXT: copy_s.d $1, $w0[0] -; MIPSR6-N64-NEXT: dmtc1 $1, $f0 -; MIPSR6-N64-NEXT: trunc.w.d $f0, $f0 -; MIPSR6-N64-NEXT: mfc1 $1, $f0 -; MIPSR6-N64-NEXT: fexupr.d $w0, $w1 -; MIPSR6-N64-NEXT: copy_s.d $2, $w0[0] -; MIPSR6-N64-NEXT: dmtc1 $2, $f0 -; MIPSR6-N64-NEXT: trunc.w.d $f0, $f0 -; MIPSR6-N64-NEXT: mfc1 $2, $f0 -; MIPSR6-N64-NEXT: lui $3, 32768 -; MIPSR6-N64-NEXT: xor $1, $1, $3 -; MIPSR6-N64-NEXT: mfc1 $3, $f3 -; MIPSR6-N64-NEXT: seleqz $1, $1, $3 -; MIPSR6-N64-NEXT: selnez $2, $2, $3 -; MIPSR6-N64-NEXT: jr $ra -; MIPSR6-N64-NEXT: or $2, $2, $1 +; MIPS64-N64-LABEL: ffptoui: +; MIPS64-N64: # %bb.0: # %entry +; MIPS64-N64-NEXT: lui $1, %hi(%neg(%gp_rel(ffptoui))) +; MIPS64-N64-NEXT: daddu $1, $1, $25 +; MIPS64-N64-NEXT: daddiu $1, $1, %lo(%neg(%gp_rel(ffptoui))) +; MIPS64-N64-NEXT: ld $1, %got_disp(h)($1) +; MIPS64-N64-NEXT: lh $1, 0($1) +; MIPS64-N64-NEXT: fill.h $w0, $1 +; MIPS64-N64-NEXT: fexupr.w $w0, $w0 +; MIPS64-N64-NEXT: fexupr.d $w0, $w0 +; MIPS64-N64-NEXT: copy_s.d $1, $w0[0] +; MIPS64-N64-NEXT: dmtc1 $1, $f0 +; MIPS64-N64-NEXT: trunc.w.d $f0, $f0 +; MIPS64-N64-NEXT: jr $ra +; MIPS64-N64-NEXT: mfc1 $2, $f0 entry: %0 = load half, half * @h, align 2 %1 = fptoui half %0 to i32 - - - - - - - - - ret i32 %1 } Index: test/CodeGen/X86/fp-cvt.ll =================================================================== --- test/CodeGen/X86/fp-cvt.ll +++ test/CodeGen/X86/fp-cvt.ll @@ -483,29 +483,20 @@ ; X64-X87-NEXT: flds {{.*}}(%rip) ; X64-X87-NEXT: fld %st(1) ; X64-X87-NEXT: fsub %st(1) +; X64-X87-NEXT: xorl %eax, %eax +; X64-X87-NEXT: fxch %st(1) +; X64-X87-NEXT: fucompi %st(2) +; X64-X87-NEXT: fcmovnbe %st(1), %st(0) +; X64-X87-NEXT: fstp %st(1) ; X64-X87-NEXT: fnstcw -{{[0-9]+}}(%rsp) -; X64-X87-NEXT: movzwl -{{[0-9]+}}(%rsp), %eax -; X64-X87-NEXT: movw $3199, -{{[0-9]+}}(%rsp) # imm = 0xC7F -; X64-X87-NEXT: fldcw -{{[0-9]+}}(%rsp) -; X64-X87-NEXT: movw %ax, -{{[0-9]+}}(%rsp) -; X64-X87-NEXT: fistpll -{{[0-9]+}}(%rsp) -; X64-X87-NEXT: fldcw -{{[0-9]+}}(%rsp) -; X64-X87-NEXT: fnstcw -{{[0-9]+}}(%rsp) -; X64-X87-NEXT: movzwl -{{[0-9]+}}(%rsp), %eax +; X64-X87-NEXT: movzwl -{{[0-9]+}}(%rsp), %ecx ; X64-X87-NEXT: movw $3199, -{{[0-9]+}}(%rsp) # imm = 0xC7F ; X64-X87-NEXT: fldcw -{{[0-9]+}}(%rsp) -; X64-X87-NEXT: movw %ax, -{{[0-9]+}}(%rsp) -; X64-X87-NEXT: fld %st(1) +; X64-X87-NEXT: movw %cx, -{{[0-9]+}}(%rsp) ; X64-X87-NEXT: fistpll -{{[0-9]+}}(%rsp) ; X64-X87-NEXT: fldcw -{{[0-9]+}}(%rsp) -; X64-X87-NEXT: fucompi %st(1) -; X64-X87-NEXT: fstp %st(0) -; X64-X87-NEXT: jbe .LBB10_1 -; X64-X87-NEXT: # %bb.2: -; X64-X87-NEXT: movq -{{[0-9]+}}(%rsp), %rax -; X64-X87-NEXT: retq -; X64-X87-NEXT: .LBB10_1: -; X64-X87-NEXT: movabsq $-9223372036854775808, %rax # imm = 0x8000000000000000 +; X64-X87-NEXT: setbe %al +; X64-X87-NEXT: shlq $63, %rax ; X64-X87-NEXT: xorq -{{[0-9]+}}(%rsp), %rax ; X64-X87-NEXT: retq ; @@ -515,17 +506,14 @@ ; X64-SSSE3-NEXT: flds {{.*}}(%rip) ; X64-SSSE3-NEXT: fld %st(1) ; X64-SSSE3-NEXT: fsub %st(1) +; X64-SSSE3-NEXT: xorl %eax, %eax +; X64-SSSE3-NEXT: fxch %st(1) +; X64-SSSE3-NEXT: fucompi %st(2) +; X64-SSSE3-NEXT: fcmovnbe %st(1), %st(0) +; X64-SSSE3-NEXT: fstp %st(1) ; X64-SSSE3-NEXT: fisttpll -{{[0-9]+}}(%rsp) -; X64-SSSE3-NEXT: fld %st(1) -; X64-SSSE3-NEXT: fisttpll -{{[0-9]+}}(%rsp) -; X64-SSSE3-NEXT: fucompi %st(1) -; X64-SSSE3-NEXT: fstp %st(0) -; X64-SSSE3-NEXT: jbe .LBB10_1 -; X64-SSSE3-NEXT: # %bb.2: -; X64-SSSE3-NEXT: movq -{{[0-9]+}}(%rsp), %rax -; X64-SSSE3-NEXT: retq -; X64-SSSE3-NEXT: .LBB10_1: -; X64-SSSE3-NEXT: movabsq $-9223372036854775808, %rax # imm = 0x8000000000000000 +; X64-SSSE3-NEXT: setbe %al +; X64-SSSE3-NEXT: shlq $63, %rax ; X64-SSSE3-NEXT: xorq -{{[0-9]+}}(%rsp), %rax ; X64-SSSE3-NEXT: retq %1 = fptoui x86_fp80 %a0 to i64 @@ -577,29 +565,20 @@ ; X64-X87-NEXT: flds {{.*}}(%rip) ; X64-X87-NEXT: fld %st(1) ; X64-X87-NEXT: fsub %st(1) +; X64-X87-NEXT: xorl %eax, %eax +; X64-X87-NEXT: fxch %st(1) +; X64-X87-NEXT: fucompi %st(2) +; X64-X87-NEXT: fcmovnbe %st(1), %st(0) +; X64-X87-NEXT: fstp %st(1) ; X64-X87-NEXT: fnstcw -{{[0-9]+}}(%rsp) -; X64-X87-NEXT: movzwl -{{[0-9]+}}(%rsp), %eax -; X64-X87-NEXT: movw $3199, -{{[0-9]+}}(%rsp) # imm = 0xC7F -; X64-X87-NEXT: fldcw -{{[0-9]+}}(%rsp) -; X64-X87-NEXT: movw %ax, -{{[0-9]+}}(%rsp) -; X64-X87-NEXT: fistpll -{{[0-9]+}}(%rsp) -; X64-X87-NEXT: fldcw -{{[0-9]+}}(%rsp) -; X64-X87-NEXT: fnstcw -{{[0-9]+}}(%rsp) -; X64-X87-NEXT: movzwl -{{[0-9]+}}(%rsp), %eax +; X64-X87-NEXT: movzwl -{{[0-9]+}}(%rsp), %ecx ; X64-X87-NEXT: movw $3199, -{{[0-9]+}}(%rsp) # imm = 0xC7F ; X64-X87-NEXT: fldcw -{{[0-9]+}}(%rsp) -; X64-X87-NEXT: movw %ax, -{{[0-9]+}}(%rsp) -; X64-X87-NEXT: fld %st(1) +; X64-X87-NEXT: movw %cx, -{{[0-9]+}}(%rsp) ; X64-X87-NEXT: fistpll -{{[0-9]+}}(%rsp) ; X64-X87-NEXT: fldcw -{{[0-9]+}}(%rsp) -; X64-X87-NEXT: fucompi %st(1) -; X64-X87-NEXT: fstp %st(0) -; X64-X87-NEXT: jbe .LBB11_1 -; X64-X87-NEXT: # %bb.2: -; X64-X87-NEXT: movq -{{[0-9]+}}(%rsp), %rax -; X64-X87-NEXT: retq -; X64-X87-NEXT: .LBB11_1: -; X64-X87-NEXT: movabsq $-9223372036854775808, %rax # imm = 0x8000000000000000 +; X64-X87-NEXT: setbe %al +; X64-X87-NEXT: shlq $63, %rax ; X64-X87-NEXT: xorq -{{[0-9]+}}(%rsp), %rax ; X64-X87-NEXT: retq ; @@ -609,17 +588,14 @@ ; X64-SSSE3-NEXT: flds {{.*}}(%rip) ; X64-SSSE3-NEXT: fld %st(1) ; X64-SSSE3-NEXT: fsub %st(1) +; X64-SSSE3-NEXT: xorl %eax, %eax +; X64-SSSE3-NEXT: fxch %st(1) +; X64-SSSE3-NEXT: fucompi %st(2) +; X64-SSSE3-NEXT: fcmovnbe %st(1), %st(0) +; X64-SSSE3-NEXT: fstp %st(1) ; X64-SSSE3-NEXT: fisttpll -{{[0-9]+}}(%rsp) -; X64-SSSE3-NEXT: fld %st(1) -; X64-SSSE3-NEXT: fisttpll -{{[0-9]+}}(%rsp) -; X64-SSSE3-NEXT: fucompi %st(1) -; X64-SSSE3-NEXT: fstp %st(0) -; X64-SSSE3-NEXT: jbe .LBB11_1 -; X64-SSSE3-NEXT: # %bb.2: -; X64-SSSE3-NEXT: movq -{{[0-9]+}}(%rsp), %rax -; X64-SSSE3-NEXT: retq -; X64-SSSE3-NEXT: .LBB11_1: -; X64-SSSE3-NEXT: movabsq $-9223372036854775808, %rax # imm = 0x8000000000000000 +; X64-SSSE3-NEXT: setbe %al +; X64-SSSE3-NEXT: shlq $63, %rax ; X64-SSSE3-NEXT: xorq -{{[0-9]+}}(%rsp), %rax ; X64-SSSE3-NEXT: retq %1 = load x86_fp80, x86_fp80 *%a0 Index: test/CodeGen/X86/scalar-fp-to-i64.ll =================================================================== --- test/CodeGen/X86/scalar-fp-to-i64.ll +++ test/CodeGen/X86/scalar-fp-to-i64.ll @@ -1147,25 +1147,21 @@ ; ; SSE3_64_WIN-LABEL: x_to_u64: ; SSE3_64_WIN: # %bb.0: -; SSE3_64_WIN-NEXT: subq $16, %rsp +; SSE3_64_WIN-NEXT: pushq %rax ; SSE3_64_WIN-NEXT: fldt (%rcx) ; SSE3_64_WIN-NEXT: flds __real@{{.*}}(%rip) ; SSE3_64_WIN-NEXT: fld %st(1) ; SSE3_64_WIN-NEXT: fsub %st(1) -; SSE3_64_WIN-NEXT: fisttpll {{[0-9]+}}(%rsp) -; SSE3_64_WIN-NEXT: fld %st(1) +; SSE3_64_WIN-NEXT: xorl %eax, %eax +; SSE3_64_WIN-NEXT: fxch %st(1) +; SSE3_64_WIN-NEXT: fucompi %st(2) +; SSE3_64_WIN-NEXT: fcmovnbe %st(1), %st(0) +; SSE3_64_WIN-NEXT: fstp %st(1) ; SSE3_64_WIN-NEXT: fisttpll (%rsp) -; SSE3_64_WIN-NEXT: fucompi %st(1) -; SSE3_64_WIN-NEXT: fstp %st(0) -; SSE3_64_WIN-NEXT: jbe .LBB4_1 -; SSE3_64_WIN-NEXT: # %bb.2: -; SSE3_64_WIN-NEXT: movq (%rsp), %rax -; SSE3_64_WIN-NEXT: addq $16, %rsp -; SSE3_64_WIN-NEXT: retq -; SSE3_64_WIN-NEXT: .LBB4_1: -; SSE3_64_WIN-NEXT: movabsq $-9223372036854775808, %rax # imm = 0x8000000000000000 -; SSE3_64_WIN-NEXT: xorq {{[0-9]+}}(%rsp), %rax -; SSE3_64_WIN-NEXT: addq $16, %rsp +; SSE3_64_WIN-NEXT: setbe %al +; SSE3_64_WIN-NEXT: shlq $63, %rax +; SSE3_64_WIN-NEXT: xorq (%rsp), %rax +; SSE3_64_WIN-NEXT: popq %rcx ; SSE3_64_WIN-NEXT: retq ; ; SSE3_64_LIN-LABEL: x_to_u64: @@ -1174,17 +1170,14 @@ ; SSE3_64_LIN-NEXT: flds {{.*}}(%rip) ; SSE3_64_LIN-NEXT: fld %st(1) ; SSE3_64_LIN-NEXT: fsub %st(1) +; SSE3_64_LIN-NEXT: xorl %eax, %eax +; SSE3_64_LIN-NEXT: fxch %st(1) +; SSE3_64_LIN-NEXT: fucompi %st(2) +; SSE3_64_LIN-NEXT: fcmovnbe %st(1), %st(0) +; SSE3_64_LIN-NEXT: fstp %st(1) ; SSE3_64_LIN-NEXT: fisttpll -{{[0-9]+}}(%rsp) -; SSE3_64_LIN-NEXT: fld %st(1) -; SSE3_64_LIN-NEXT: fisttpll -{{[0-9]+}}(%rsp) -; SSE3_64_LIN-NEXT: fucompi %st(1) -; SSE3_64_LIN-NEXT: fstp %st(0) -; SSE3_64_LIN-NEXT: jbe .LBB4_1 -; SSE3_64_LIN-NEXT: # %bb.2: -; SSE3_64_LIN-NEXT: movq -{{[0-9]+}}(%rsp), %rax -; SSE3_64_LIN-NEXT: retq -; SSE3_64_LIN-NEXT: .LBB4_1: -; SSE3_64_LIN-NEXT: movabsq $-9223372036854775808, %rax # imm = 0x8000000000000000 +; SSE3_64_LIN-NEXT: setbe %al +; SSE3_64_LIN-NEXT: shlq $63, %rax ; SSE3_64_LIN-NEXT: xorq -{{[0-9]+}}(%rsp), %rax ; SSE3_64_LIN-NEXT: retq ; @@ -1246,37 +1239,27 @@ ; ; SSE2_64_WIN-LABEL: x_to_u64: ; SSE2_64_WIN: # %bb.0: -; SSE2_64_WIN-NEXT: subq $24, %rsp +; SSE2_64_WIN-NEXT: subq $16, %rsp ; SSE2_64_WIN-NEXT: fldt (%rcx) ; SSE2_64_WIN-NEXT: flds __real@{{.*}}(%rip) ; SSE2_64_WIN-NEXT: fld %st(1) ; SSE2_64_WIN-NEXT: fsub %st(1) +; SSE2_64_WIN-NEXT: xorl %eax, %eax +; SSE2_64_WIN-NEXT: fxch %st(1) +; SSE2_64_WIN-NEXT: fucompi %st(2) +; SSE2_64_WIN-NEXT: fcmovnbe %st(1), %st(0) +; SSE2_64_WIN-NEXT: fstp %st(1) ; SSE2_64_WIN-NEXT: fnstcw {{[0-9]+}}(%rsp) -; SSE2_64_WIN-NEXT: movzwl {{[0-9]+}}(%rsp), %eax +; SSE2_64_WIN-NEXT: movzwl {{[0-9]+}}(%rsp), %ecx ; SSE2_64_WIN-NEXT: movw $3199, {{[0-9]+}}(%rsp) # imm = 0xC7F ; SSE2_64_WIN-NEXT: fldcw {{[0-9]+}}(%rsp) -; SSE2_64_WIN-NEXT: movw %ax, {{[0-9]+}}(%rsp) +; SSE2_64_WIN-NEXT: movw %cx, {{[0-9]+}}(%rsp) ; SSE2_64_WIN-NEXT: fistpll {{[0-9]+}}(%rsp) ; SSE2_64_WIN-NEXT: fldcw {{[0-9]+}}(%rsp) -; SSE2_64_WIN-NEXT: fnstcw {{[0-9]+}}(%rsp) -; SSE2_64_WIN-NEXT: movzwl {{[0-9]+}}(%rsp), %eax -; SSE2_64_WIN-NEXT: movw $3199, {{[0-9]+}}(%rsp) # imm = 0xC7F -; SSE2_64_WIN-NEXT: fldcw {{[0-9]+}}(%rsp) -; SSE2_64_WIN-NEXT: movw %ax, {{[0-9]+}}(%rsp) -; SSE2_64_WIN-NEXT: fld %st(1) -; SSE2_64_WIN-NEXT: fistpll {{[0-9]+}}(%rsp) -; SSE2_64_WIN-NEXT: fldcw {{[0-9]+}}(%rsp) -; SSE2_64_WIN-NEXT: fucompi %st(1) -; SSE2_64_WIN-NEXT: fstp %st(0) -; SSE2_64_WIN-NEXT: jbe .LBB4_1 -; SSE2_64_WIN-NEXT: # %bb.2: -; SSE2_64_WIN-NEXT: movq {{[0-9]+}}(%rsp), %rax -; SSE2_64_WIN-NEXT: addq $24, %rsp -; SSE2_64_WIN-NEXT: retq -; SSE2_64_WIN-NEXT: .LBB4_1: -; SSE2_64_WIN-NEXT: movabsq $-9223372036854775808, %rax # imm = 0x8000000000000000 +; SSE2_64_WIN-NEXT: setbe %al +; SSE2_64_WIN-NEXT: shlq $63, %rax ; SSE2_64_WIN-NEXT: xorq {{[0-9]+}}(%rsp), %rax -; SSE2_64_WIN-NEXT: addq $24, %rsp +; SSE2_64_WIN-NEXT: addq $16, %rsp ; SSE2_64_WIN-NEXT: retq ; ; SSE2_64_LIN-LABEL: x_to_u64: @@ -1285,29 +1268,20 @@ ; SSE2_64_LIN-NEXT: flds {{.*}}(%rip) ; SSE2_64_LIN-NEXT: fld %st(1) ; SSE2_64_LIN-NEXT: fsub %st(1) +; SSE2_64_LIN-NEXT: xorl %eax, %eax +; SSE2_64_LIN-NEXT: fxch %st(1) +; SSE2_64_LIN-NEXT: fucompi %st(2) +; SSE2_64_LIN-NEXT: fcmovnbe %st(1), %st(0) +; SSE2_64_LIN-NEXT: fstp %st(1) ; SSE2_64_LIN-NEXT: fnstcw -{{[0-9]+}}(%rsp) -; SSE2_64_LIN-NEXT: movzwl -{{[0-9]+}}(%rsp), %eax +; SSE2_64_LIN-NEXT: movzwl -{{[0-9]+}}(%rsp), %ecx ; SSE2_64_LIN-NEXT: movw $3199, -{{[0-9]+}}(%rsp) # imm = 0xC7F ; SSE2_64_LIN-NEXT: fldcw -{{[0-9]+}}(%rsp) -; SSE2_64_LIN-NEXT: movw %ax, -{{[0-9]+}}(%rsp) +; SSE2_64_LIN-NEXT: movw %cx, -{{[0-9]+}}(%rsp) ; SSE2_64_LIN-NEXT: fistpll -{{[0-9]+}}(%rsp) ; SSE2_64_LIN-NEXT: fldcw -{{[0-9]+}}(%rsp) -; SSE2_64_LIN-NEXT: fnstcw -{{[0-9]+}}(%rsp) -; SSE2_64_LIN-NEXT: movzwl -{{[0-9]+}}(%rsp), %eax -; SSE2_64_LIN-NEXT: movw $3199, -{{[0-9]+}}(%rsp) # imm = 0xC7F -; SSE2_64_LIN-NEXT: fldcw -{{[0-9]+}}(%rsp) -; SSE2_64_LIN-NEXT: movw %ax, -{{[0-9]+}}(%rsp) -; SSE2_64_LIN-NEXT: fld %st(1) -; SSE2_64_LIN-NEXT: fistpll -{{[0-9]+}}(%rsp) -; SSE2_64_LIN-NEXT: fldcw -{{[0-9]+}}(%rsp) -; SSE2_64_LIN-NEXT: fucompi %st(1) -; SSE2_64_LIN-NEXT: fstp %st(0) -; SSE2_64_LIN-NEXT: jbe .LBB4_1 -; SSE2_64_LIN-NEXT: # %bb.2: -; SSE2_64_LIN-NEXT: movq -{{[0-9]+}}(%rsp), %rax -; SSE2_64_LIN-NEXT: retq -; SSE2_64_LIN-NEXT: .LBB4_1: -; SSE2_64_LIN-NEXT: movabsq $-9223372036854775808, %rax # imm = 0x8000000000000000 +; SSE2_64_LIN-NEXT: setbe %al +; SSE2_64_LIN-NEXT: shlq $63, %rax ; SSE2_64_LIN-NEXT: xorq -{{[0-9]+}}(%rsp), %rax ; SSE2_64_LIN-NEXT: retq ;