[llvm] r229438 - SelectionDAG: fold (fp_to_u/sint (s/uint_to_fp)) here too
Mehdi Amini
mehdi.amini at apple.com
Mon Feb 16 13:47:59 PST 2015
Author: mehdi_amini
Date: Mon Feb 16 15:47:58 2015
New Revision: 229438
URL: http://llvm.org/viewvc/llvm-project?rev=229438&view=rev
Log:
SelectionDAG: fold (fp_to_u/sint (s/uint_to_fp)) here too
Update SPARC tests to match.
From: Fiona Glaser <fglaser at apple.com>
Added:
llvm/trunk/test/CodeGen/X86/float-conv-elim.ll
Modified:
llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
llvm/trunk/test/CodeGen/SPARC/float.ll
llvm/trunk/test/CodeGen/SPARC/fp128.ll
Modified: llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp?rev=229438&r1=229437&r2=229438&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Mon Feb 16 15:47:58 2015
@@ -7845,6 +7845,50 @@ SDValue DAGCombiner::visitUINT_TO_FP(SDN
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<ConstantFPSDNode>(N0);
@@ -7854,7 +7898,7 @@ SDValue DAGCombiner::visitFP_TO_SINT(SDN
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(SDN
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) {
Modified: llvm/trunk/test/CodeGen/SPARC/float.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/SPARC/float.ll?rev=229438&r1=229437&r2=229438&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/SPARC/float.ll (original)
+++ llvm/trunk/test/CodeGen/SPARC/float.ll Mon Feb 16 15:47:58 2015
@@ -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
}
Modified: llvm/trunk/test/CodeGen/SPARC/fp128.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/SPARC/fp128.ll?rev=229438&r1=229437&r2=229438&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/SPARC/fp128.ll (original)
+++ llvm/trunk/test/CodeGen/SPARC/fp128.ll Mon Feb 16 15:47:58 2015
@@ -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
Added: llvm/trunk/test/CodeGen/X86/float-conv-elim.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/float-conv-elim.ll?rev=229438&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/X86/float-conv-elim.ll (added)
+++ llvm/trunk/test/CodeGen/X86/float-conv-elim.ll Mon Feb 16 15:47:58 2015
@@ -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" }
+
More information about the llvm-commits
mailing list