From 2deb1d0b547ce041d64951bd7e2378b02861aa01 Mon Sep 17 00:00:00 2001 From: Mehdi Amini Date: Mon, 16 Feb 2015 21:47:58 +0000 Subject: [PATCH] SelectionDAG: fold (fp_to_u/sint (s/uint_to_fp)) here too Update SPARC tests to match. From: Fiona Glaser git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@229438 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 48 +++++++++++++++++++++++- test/CodeGen/SPARC/float.ll | 4 +- test/CodeGen/SPARC/fp128.ll | 32 +++++++++------- test/CodeGen/X86/float-conv-elim.ll | 32 ++++++++++++++++ 4 files changed, 98 insertions(+), 18 deletions(-) create mode 100644 test/CodeGen/X86/float-conv-elim.ll diff --git a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 857109119fb..c4a1a1f64b7 100644 --- a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -7845,6 +7845,50 @@ SDValue DAGCombiner::visitUINT_TO_FP(SDNode *N) { return SDValue(); } +// Fold (fp_to_{s/u}int ({s/u}int_to_fpx)) -> zext x, sext x, trunc x, or x +static SDValue FoldIntToFPToInt(SDNode *N, SelectionDAG &DAG) { + SDValue N0 = N->getOperand(0); + EVT VT = N->getValueType(0); + + if (N0.getOpcode() != ISD::UINT_TO_FP && N0.getOpcode() != ISD::SINT_TO_FP) + return SDValue(); + + SDValue Src = N0.getOperand(0); + EVT SrcVT = Src.getValueType(); + bool IsInputSigned = N0.getOpcode() == ISD::SINT_TO_FP; + bool IsOutputSigned = N->getOpcode() == ISD::FP_TO_SINT; + + // We can safely assume the conversion won't overflow the output range, + // because (for example) (uint8_t)18293.f is undefined behavior. + + // Since we can assume the conversion won't overflow, our decision as to + // whether the input will fit in the float should depend on the minimum + // of the input range and output range. + + // This means this is also safe for a signed input and unsigned output, since + // a negative input would lead to undefined behavior. + unsigned InputSize = (int)SrcVT.getScalarSizeInBits() - IsInputSigned; + unsigned OutputSize = (int)VT.getScalarSizeInBits() - IsOutputSigned; + unsigned ActualSize = std::min(InputSize, OutputSize); + const fltSemantics &sem = DAG.EVTToAPFloatSemantics(N0.getValueType()); + + // We can only fold away the float conversion if the input range can be + // represented exactly in the float range. + if (APFloat::semanticsPrecision(sem) >= ActualSize) { + if (VT.getScalarSizeInBits() > SrcVT.getScalarSizeInBits()) { + unsigned ExtOp = IsInputSigned && IsOutputSigned ? ISD::SIGN_EXTEND + : ISD::ZERO_EXTEND; + return DAG.getNode(ExtOp, SDLoc(N), VT, Src); + } + if (VT.getScalarSizeInBits() < SrcVT.getScalarSizeInBits()) + return DAG.getNode(ISD::TRUNCATE, SDLoc(N), VT, Src); + if (SrcVT == VT) + return Src; + return DAG.getNode(ISD::BITCAST, SDLoc(N), VT, Src); + } + return SDValue(); +} + SDValue DAGCombiner::visitFP_TO_SINT(SDNode *N) { SDValue N0 = N->getOperand(0); ConstantFPSDNode *N0CFP = dyn_cast(N0); @@ -7854,7 +7898,7 @@ SDValue DAGCombiner::visitFP_TO_SINT(SDNode *N) { if (N0CFP) return DAG.getNode(ISD::FP_TO_SINT, SDLoc(N), VT, N0); - return SDValue(); + return FoldIntToFPToInt(N, DAG); } SDValue DAGCombiner::visitFP_TO_UINT(SDNode *N) { @@ -7866,7 +7910,7 @@ SDValue DAGCombiner::visitFP_TO_UINT(SDNode *N) { if (N0CFP) return DAG.getNode(ISD::FP_TO_UINT, SDLoc(N), VT, N0); - return SDValue(); + return FoldIntToFPToInt(N, DAG); } SDValue DAGCombiner::visitFP_ROUND(SDNode *N) { diff --git a/test/CodeGen/SPARC/float.ll b/test/CodeGen/SPARC/float.ll index 66367042cad..d7a79cb05a8 100644 --- a/test/CodeGen/SPARC/float.ll +++ b/test/CodeGen/SPARC/float.ll @@ -154,11 +154,11 @@ entry: ; SPARC64: fitod ; SPARC64: fdtoi -define void @test_itod_dtoi(i32 %a, i32* %ptr0, double* %ptr1) { +define void @test_itod_dtoi(i32 %a, double %b, i32* %ptr0, double* %ptr1) { entry: %0 = sitofp i32 %a to double store double %0, double* %ptr1, align 8 - %1 = fptosi double %0 to i32 + %1 = fptosi double %b to i32 store i32 %1, i32* %ptr0, align 8 ret void } diff --git a/test/CodeGen/SPARC/fp128.ll b/test/CodeGen/SPARC/fp128.ll index abd89bf264e..a06112a56ba 100644 --- a/test/CodeGen/SPARC/fp128.ll +++ b/test/CodeGen/SPARC/fp128.ll @@ -182,26 +182,28 @@ entry: } ; HARD-LABEL: test_itoq_qtoi -; HARD: call _Q_lltoq -; HARD: call _Q_qtoll -; HARD: fitoq -; HARD: fqtoi +; HARD-DAG: call _Q_lltoq +; HARD-DAG: call _Q_qtoll +; HARD-DAG: fitoq +; HARD-DAG: fqtoi ; SOFT-LABEL: test_itoq_qtoi -; SOFT: call _Q_lltoq -; SOFT: call _Q_qtoll -; SOFT: call _Q_itoq -; SOFT: call _Q_qtoi +; SOFT-DAG: call _Q_lltoq +; SOFT-DAG: call _Q_qtoll +; SOFT-DAG: call _Q_itoq +; SOFT-DAG: call _Q_qtoi -define void @test_itoq_qtoi(i64 %a, i32 %b, i64* %ptr0, fp128* %ptr1) { +define void @test_itoq_qtoi(i64 %a, i32 %b, fp128* %c, fp128* %d, i64* %ptr0, fp128* %ptr1) { entry: %0 = sitofp i64 %a to fp128 store fp128 %0, fp128* %ptr1, align 8 - %1 = fptosi fp128 %0 to i64 + %cval = load fp128* %c, align 8 + %1 = fptosi fp128 %cval to i64 store i64 %1, i64* %ptr0, align 8 %2 = sitofp i32 %b to fp128 store fp128 %2, fp128* %ptr1, align 8 - %3 = fptosi fp128 %2 to i32 + %dval = load fp128* %d, align 8 + %3 = fptosi fp128 %dval to i32 %4 = bitcast i64* %ptr0 to i32* store i32 %3, i32* %4, align 8 ret void @@ -219,15 +221,17 @@ entry: ; SOFT-DAG: call _Q_utoq ; SOFT-DAG: call _Q_qtou -define void @test_utoq_qtou(i64 %a, i32 %b, i64* %ptr0, fp128* %ptr1) { +define void @test_utoq_qtou(i64 %a, i32 %b, fp128* %c, fp128* %d, i64* %ptr0, fp128* %ptr1) { entry: %0 = uitofp i64 %a to fp128 store fp128 %0, fp128* %ptr1, align 8 - %1 = fptoui fp128 %0 to i64 + %cval = load fp128* %c, align 8 + %1 = fptoui fp128 %cval to i64 store i64 %1, i64* %ptr0, align 8 %2 = uitofp i32 %b to fp128 store fp128 %2, fp128* %ptr1, align 8 - %3 = fptoui fp128 %2 to i32 + %dval = load fp128* %d, align 8 + %3 = fptoui fp128 %dval to i32 %4 = bitcast i64* %ptr0 to i32* store i32 %3, i32* %4, align 8 ret void diff --git a/test/CodeGen/X86/float-conv-elim.ll b/test/CodeGen/X86/float-conv-elim.ll new file mode 100644 index 00000000000..13dde4a799d --- /dev/null +++ b/test/CodeGen/X86/float-conv-elim.ll @@ -0,0 +1,32 @@ +; RUN: llc -mcpu=x86-64 < %s | FileCheck %s + +; Make sure the float conversion is folded away as it should be. +; CHECK-LABEL: foo +; CHECK-NOT: cvt +; CHECK: movzbl +define i32 @foo(i8 %a) #0 { + %conv = uitofp i8 %a to float + %conv1 = fptosi float %conv to i32 + ret i32 %conv1 +} + +; CHECK-LABEL: foo2 +; CHECK-NOT: cvt +; CHECK: movsbl +define i32 @foo2(i8 %a) #0 { + %conv = sitofp i8 %a to float + %conv1 = fptosi float %conv to i32 + ret i32 %conv1 +} + +; CHECK-LABEL: bar +; CHECK-NOT: cvt +; CHECK: movl +define zeroext i8 @bar(i8 zeroext %a) #0 { + %conv = uitofp i8 %a to float + %conv1 = fptoui float %conv to i8 + ret i8 %conv1 +} + +attributes #0 = { nounwind ssp uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } + -- 2.34.1