diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp @@ -1620,6 +1620,10 @@ SDLoc dl(N); SDValue Chain = Strict ? N->getOperand(0) : DAG.getEntryNode(); + // TODO: Any other flags to propagate? + SDNodeFlags Flags; + Flags.setNoFPExcept(N->getFlags().hasNoFPExcept()); + // First do an SINT_TO_FP, whether the original was signed or unsigned. // When promoting partial word types to i32 we must honor the signedness, // though. @@ -1630,8 +1634,8 @@ Lo = DAG.getConstantFP(APFloat(DAG.EVTToAPFloatSemantics(NVT), APInt(NVT.getSizeInBits(), 0)), dl, NVT); if (Strict) { - Hi = DAG.getNode(ISD::STRICT_SINT_TO_FP, dl, {NVT, MVT::Other}, - {Chain, Src}); + Hi = DAG.getNode(ISD::STRICT_SINT_TO_FP, dl, + DAG.getVTList(NVT, MVT::Other), {Chain, Src}, Flags); Chain = Hi.getValue(1); } else Hi = DAG.getNode(ISD::SINT_TO_FP, dl, NVT, Src); @@ -1690,12 +1694,12 @@ break; } - // TODO: Are there fast-math-flags to propagate to this FADD? + // TODO: Are there other fast-math-flags to propagate to this FADD? SDValue NewLo = DAG.getConstantFP( APFloat(APFloat::PPCDoubleDouble(), APInt(128, Parts)), dl, MVT::ppcf128); if (Strict) { - Lo = DAG.getNode(ISD::STRICT_FADD, dl, {VT, MVT::Other}, - {Chain, Hi, NewLo}); + Lo = DAG.getNode(ISD::STRICT_FADD, dl, DAG.getVTList(VT, MVT::Other), + {Chain, Hi, NewLo}, Flags); Chain = Lo.getValue(1); ReplaceValueWith(SDValue(N, 1), Chain); } else diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp --- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -8090,14 +8090,20 @@ bool IsStrict = Op->isStrictFPOpcode(); bool IsSigned = Op.getOpcode() == ISD::FP_TO_SINT || Op.getOpcode() == ISD::STRICT_FP_TO_SINT; + + // TODO: Any other flags to propagate? + SDNodeFlags Flags; + Flags.setNoFPExcept(Op->getFlags().hasNoFPExcept()); + // For strict nodes, source is the second operand. SDValue Src = Op.getOperand(IsStrict ? 1 : 0); SDValue Chain = IsStrict ? Op.getOperand(0) : SDValue(); assert(Src.getValueType().isFloatingPoint()); if (Src.getValueType() == MVT::f32) { if (IsStrict) { - Src = DAG.getNode(ISD::STRICT_FP_EXTEND, dl, {MVT::f64, MVT::Other}, - {Chain, Src}); + Src = + DAG.getNode(ISD::STRICT_FP_EXTEND, dl, + DAG.getVTList(MVT::f64, MVT::Other), {Chain, Src}, Flags); Chain = Src.getValue(1); } else Src = DAG.getNode(ISD::FP_EXTEND, dl, MVT::f64, Src); @@ -8117,7 +8123,8 @@ } if (IsStrict) { Opc = getPPCStrictOpcode(Opc); - Conv = DAG.getNode(Opc, dl, {MVT::f64, MVT::Other}, {Chain, Src}); + Conv = DAG.getNode(Opc, dl, DAG.getVTList(MVT::f64, MVT::Other), + {Chain, Src}, Flags); } else { Conv = DAG.getNode(Opc, dl, MVT::f64, Src); } @@ -8398,6 +8405,11 @@ bool IsSigned = Op.getOpcode() == ISD::SINT_TO_FP || Op.getOpcode() == ISD::STRICT_SINT_TO_FP; SDLoc dl(Op); + + // TODO: Any other flags to propagate? + SDNodeFlags Flags; + Flags.setNoFPExcept(Op->getFlags().hasNoFPExcept()); + // If we have FCFIDS, then use it when converting to single-precision. // Otherwise, convert to double-precision and then round. bool IsSingle = Op.getValueType() == MVT::f32 && Subtarget.hasFPCVT(); @@ -8407,8 +8419,8 @@ if (Op->isStrictFPOpcode()) { if (!Chain) Chain = Op.getOperand(0); - return DAG.getNode(getPPCStrictOpcode(ConvOpc), dl, {ConvTy, MVT::Other}, - {Chain, Src}); + return DAG.getNode(getPPCStrictOpcode(ConvOpc), dl, + DAG.getVTList(ConvTy, MVT::Other), {Chain, Src}, Flags); } else return DAG.getNode(ConvOpc, dl, ConvTy, Src); } @@ -8464,6 +8476,10 @@ assert((Op.getValueType() == MVT::v2f64 || Op.getValueType() == MVT::v4f32) && "Supports conversions to v2f64/v4f32 only."); + // TODO: Any other flags to propagate? + SDNodeFlags Flags; + Flags.setNoFPExcept(Op->getFlags().hasNoFPExcept()); + bool SignedConv = Opc == ISD::SINT_TO_FP || Opc == ISD::STRICT_SINT_TO_FP; bool FourEltRes = Op.getValueType() == MVT::v4f32; @@ -8503,8 +8519,8 @@ Extend = DAG.getNode(ISD::BITCAST, dl, IntermediateVT, Arrange); if (IsStrict) - return DAG.getNode(Opc, dl, {Op.getValueType(), MVT::Other}, - {Op.getOperand(0), Extend}); + return DAG.getNode(Opc, dl, DAG.getVTList(Op.getValueType(), MVT::Other), + {Op.getOperand(0), Extend}, Flags); return DAG.getNode(Opc, dl, Op.getValueType(), Extend); } @@ -8518,6 +8534,10 @@ SDValue Src = Op.getOperand(IsStrict ? 1 : 0); SDValue Chain = IsStrict ? Op.getOperand(0) : DAG.getEntryNode(); + // TODO: Any other flags to propagate? + SDNodeFlags Flags; + Flags.setNoFPExcept(Op->getFlags().hasNoFPExcept()); + EVT InVT = Src.getValueType(); EVT OutVT = Op.getValueType(); if (OutVT.isVector() && OutVT.isFloatingPoint() && @@ -8667,8 +8687,9 @@ if (Op.getValueType() == MVT::f32 && !Subtarget.hasFPCVT()) { if (IsStrict) - FP = DAG.getNode(ISD::STRICT_FP_ROUND, dl, {MVT::f32, MVT::Other}, - {Chain, FP, DAG.getIntPtrConstant(0, dl)}); + FP = DAG.getNode(ISD::STRICT_FP_ROUND, dl, + DAG.getVTList(MVT::f32, MVT::Other), + {Chain, FP, DAG.getIntPtrConstant(0, dl)}, Flags); else FP = DAG.getNode(ISD::FP_ROUND, dl, MVT::f32, FP, DAG.getIntPtrConstant(0, dl)); @@ -8747,8 +8768,9 @@ Chain = FP.getValue(1); if (Op.getValueType() == MVT::f32 && !Subtarget.hasFPCVT()) { if (IsStrict) - FP = DAG.getNode(ISD::STRICT_FP_ROUND, dl, {MVT::f32, MVT::Other}, - {Chain, FP, DAG.getIntPtrConstant(0, dl)}); + FP = DAG.getNode(ISD::STRICT_FP_ROUND, dl, + DAG.getVTList(MVT::f32, MVT::Other), + {Chain, FP, DAG.getIntPtrConstant(0, dl)}, Flags); else FP = DAG.getNode(ISD::FP_ROUND, dl, MVT::f32, FP, DAG.getIntPtrConstant(0, dl)); diff --git a/llvm/test/CodeGen/PowerPC/fp-strict-conv-f128.ll b/llvm/test/CodeGen/PowerPC/fp-strict-conv-f128.ll --- a/llvm/test/CodeGen/PowerPC/fp-strict-conv-f128.ll +++ b/llvm/test/CodeGen/PowerPC/fp-strict-conv-f128.ll @@ -835,9 +835,9 @@ ; MIR: renamable $v{{[0-9]+}} = nofpexcept XSCVQPUDZ ; ; MIR: renamable $f{{[0-9]+}} = nofpexcept FADD -; MIR: renamable $f{{[0-9]+}} = XSCVDPSXWS +; MIR: renamable $f{{[0-9]+}} = nofpexcept XSCVDPSXWS ; MIR: renamable $f{{[0-9]+}} = nofpexcept FADD -; MIR: renamable $f{{[0-9]+}} = XSCVDPSXWS +; MIR: renamable $f{{[0-9]+}} = nofpexcept XSCVDPSXWS entry: %conv1 = tail call i32 @llvm.experimental.constrained.fptosi.i32.f128(fp128 %m, metadata !"fpexcept.ignore") #0 store volatile i32 %conv1, i32* %addr1, align 4 diff --git a/llvm/test/CodeGen/PowerPC/fp-strict-conv.ll b/llvm/test/CodeGen/PowerPC/fp-strict-conv.ll --- a/llvm/test/CodeGen/PowerPC/fp-strict-conv.ll +++ b/llvm/test/CodeGen/PowerPC/fp-strict-conv.ll @@ -6,6 +6,8 @@ ; RUN: llc -verify-machineinstrs -ppc-asm-full-reg-names -ppc-vsr-nums-as-vr \ ; RUN: < %s -mtriple=powerpc64le-unknown-linux -mcpu=pwr8 -mattr=-vsx | \ ; RUN: FileCheck %s -check-prefix=NOVSX +; RUN: llc -mtriple=powerpc64le-unknown-linux -mcpu=pwr9 < %s -simplify-mir \ +; RUN: -stop-after=machine-cp | FileCheck %s -check-prefix=MIR declare i32 @llvm.experimental.constrained.fptosi.i32.f64(double, metadata) declare i64 @llvm.experimental.constrained.fptosi.i64.f64(double, metadata) @@ -326,4 +328,86 @@ ret float %conv } +define void @fptoint_nofpexcept_f64(double %m, i32* %addr1, i64* %addr2) { +; MIR-LABEL: name: fptoint_nofpexcept_f64 +; MIR: renamable $f{{[0-9]+}} = nofpexcept XSCVDPSXWS +; MIR: renamable $f{{[0-9]+}} = nofpexcept XSCVDPUXWS +; MIR: renamable $f{{[0-9]+}} = nofpexcept XSCVDPSXDS +; MIR: renamable $f{{[0-9]+}} = nofpexcept XSCVDPUXDS +entry: + %conv1 = tail call i32 @llvm.experimental.constrained.fptosi.i32.f64(double %m, metadata !"fpexcept.ignore") #0 + %conv2 = tail call i32 @llvm.experimental.constrained.fptoui.i32.f64(double %m, metadata !"fpexcept.ignore") #0 + %conv3 = tail call i64 @llvm.experimental.constrained.fptosi.i64.f64(double %m, metadata !"fpexcept.ignore") #0 + %conv4 = tail call i64 @llvm.experimental.constrained.fptoui.i64.f64(double %m, metadata !"fpexcept.ignore") #0 + store volatile i32 %conv1, i32* %addr1, align 4 + store volatile i32 %conv2, i32* %addr1, align 4 + store volatile i64 %conv3, i64* %addr2, align 8 + store volatile i64 %conv4, i64* %addr2, align 8 + ret void +} + +define void @fptoint_nofpexcept_f32(float %m, i32* %addr1, i64* %addr2) { +; MIR-LABEL: name: fptoint_nofpexcept_f32 +; MIR: renamable $f{{[0-9]+}} = nofpexcept XSCVDPSXWS +; MIR: renamable $f{{[0-9]+}} = nofpexcept XSCVDPUXWS +; MIR: renamable $f{{[0-9]+}} = nofpexcept XSCVDPSXDS +; MIR: renamable $f{{[0-9]+}} = nofpexcept XSCVDPUXDS +entry: + %conv1 = tail call i32 @llvm.experimental.constrained.fptosi.i32.f32(float %m, metadata !"fpexcept.ignore") #0 + %conv2 = tail call i32 @llvm.experimental.constrained.fptoui.i32.f32(float %m, metadata !"fpexcept.ignore") #0 + %conv3 = tail call i64 @llvm.experimental.constrained.fptosi.i64.f32(float %m, metadata !"fpexcept.ignore") #0 + %conv4 = tail call i64 @llvm.experimental.constrained.fptoui.i64.f32(float %m, metadata !"fpexcept.ignore") #0 + store volatile i32 %conv1, i32* %addr1, align 4 + store volatile i32 %conv2, i32* %addr1, align 4 + store volatile i64 %conv3, i64* %addr2, align 8 + store volatile i64 %conv4, i64* %addr2, align 8 + ret void +} + +define void @inttofp_nofpexcept_i32(i32 %m, float* %addr1, double* %addr2) { +; MIR-LABEL: name: inttofp_nofpexcept_i32 +; MIR: renamable $f{{[0-9]+}} = nofpexcept XSCVSXDSP +; MIR: renamable $f{{[0-9]+}} = nofpexcept XSCVUXDSP +; MIR: renamable $f{{[0-9]+}} = nofpexcept XSCVSXDDP +; MIR: renamable $f{{[0-9]+}} = nofpexcept XSCVUXDDP +entry: + %conv1 = tail call float @llvm.experimental.constrained.sitofp.f32.i32(i32 %m, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0 + %conv2 = tail call float @llvm.experimental.constrained.uitofp.f32.i32(i32 %m, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0 + %conv3 = tail call double @llvm.experimental.constrained.sitofp.f64.i32(i32 %m, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0 + %conv4 = tail call double @llvm.experimental.constrained.uitofp.f64.i32(i32 %m, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0 + store volatile float %conv1, float* %addr1, align 4 + store volatile float %conv2, float* %addr1, align 4 + store volatile double %conv3, double* %addr2, align 8 + store volatile double %conv4, double* %addr2, align 8 + ret void +} + +define void @inttofp_nofpexcept_i64(i64 %m, float* %addr1, double* %addr2) { +; MIR-LABEL: name: inttofp_nofpexcept_i64 +; MIR: renamable $f{{[0-9]+}} = nofpexcept XSCVSXDSP +; MIR: renamable $f{{[0-9]+}} = nofpexcept XSCVUXDSP +; MIR: renamable $f{{[0-9]+}} = nofpexcept XSCVSXDDP +; MIR: renamable $f{{[0-9]+}} = nofpexcept XSCVUXDDP +entry: + %conv1 = tail call float @llvm.experimental.constrained.sitofp.f32.i64(i64 %m, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0 + %conv2 = tail call float @llvm.experimental.constrained.uitofp.f32.i64(i64 %m, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0 + %conv3 = tail call double @llvm.experimental.constrained.sitofp.f64.i64(i64 %m, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0 + %conv4 = tail call double @llvm.experimental.constrained.uitofp.f64.i64(i64 %m, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0 + store volatile float %conv1, float* %addr1, align 4 + store volatile float %conv2, float* %addr1, align 4 + store volatile double %conv3, double* %addr2, align 8 + store volatile double %conv4, double* %addr2, align 8 + ret void +} + +define <2 x double> @inttofp_nofpexcept_vec(<2 x i16> %m) { +; MIR-LABEL: name: inttofp_nofpexcept_vec +; MIR: renamable $v{{[0-9]+}} = nofpexcept XVCVSXDDP +entry: + %conv = tail call <2 x double> @llvm.experimental.constrained.sitofp.v2f64.v2i16(<2 x i16> %m, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0 + ret <2 x double> %conv +} + +declare <2 x double> @llvm.experimental.constrained.sitofp.v2f64.v2i16(<2 x i16>, metadata, metadata) + attributes #0 = { strictfp }