1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-01-31 12:41:49 +01:00

[PowerPC] Pass nofpexcept flag to custom lowered constrained ops

This is a follow-up of D86605. For strict DAG FP node, if its FP
exception behavior metadata is ignore, it should have nofpexcept flag.
But during custom lowering, this flag isn't passed down.

This is also seen on X86 target.

Reviewed By: uweigand

Differential Revision: https://reviews.llvm.org/D87390
This commit is contained in:
Qiu Chaofan 2020-09-21 10:38:00 +08:00
parent 4dabbec93d
commit d6e49b7d70
4 changed files with 128 additions and 18 deletions

View File

@ -1620,6 +1620,10 @@ void DAGTypeLegalizer::ExpandFloatRes_XINT_TO_FP(SDNode *N, SDValue &Lo,
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 @@ void DAGTypeLegalizer::ExpandFloatRes_XINT_TO_FP(SDNode *N, SDValue &Lo,
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 @@ void DAGTypeLegalizer::ExpandFloatRes_XINT_TO_FP(SDNode *N, SDValue &Lo,
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

View File

@ -8090,14 +8090,20 @@ static SDValue convertFPToInt(SDValue Op, SelectionDAG &DAG,
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 @@ static SDValue convertFPToInt(SDValue Op, SelectionDAG &DAG,
}
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 @@ static SDValue convertIntToFP(SDValue Op, SDValue Src, SelectionDAG &DAG,
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 @@ static SDValue convertIntToFP(SDValue Op, SDValue Src, SelectionDAG &DAG,
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 @@ SDValue PPCTargetLowering::LowerINT_TO_FPVector(SDValue Op, SelectionDAG &DAG,
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 @@ SDValue PPCTargetLowering::LowerINT_TO_FPVector(SDValue Op, SelectionDAG &DAG,
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 PPCTargetLowering::LowerINT_TO_FP(SDValue Op,
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 @@ SDValue PPCTargetLowering::LowerINT_TO_FP(SDValue Op,
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 @@ SDValue PPCTargetLowering::LowerINT_TO_FP(SDValue Op,
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));

View File

@ -835,9 +835,9 @@ define void @fptoint_nofpexcept(ppc_fp128 %p, fp128 %m, i32* %addr1, i64* %addr2
; 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

View File

@ -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 @@ entry:
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 }