diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index a897fb562e7b..9558cb8ee004 100644 --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -10904,6 +10904,14 @@ SDValue DAGCombiner::visitFCOPYSIGN(SDNode *N) { static SDValue foldFPToIntToFP(SDNode *N, SelectionDAG &DAG, const TargetLowering &TLI) { + // This optimization is guarded by a function attribute because it may produce + // unexpected results. Ie, programs may be relying on the platform-specific + // undefined behavior when the float-to-int conversion overflows. + const Function &F = DAG.getMachineFunction().getFunction(); + Attribute CastWorkaround = F.getFnAttribute("fp-cast-overflow-workaround"); + if (CastWorkaround.getValueAsString().equals("true")) + return SDValue(); + // We only do this if the target has legal ftrunc. Otherwise, we'd likely be // replacing casts with a libcall. EVT VT = N->getValueType(0); diff --git a/llvm/test/CodeGen/X86/ftrunc.ll b/llvm/test/CodeGen/X86/ftrunc.ll index 02abc45d8518..356de29e5914 100644 --- a/llvm/test/CodeGen/X86/ftrunc.ll +++ b/llvm/test/CodeGen/X86/ftrunc.ll @@ -356,7 +356,7 @@ define <4 x double> @trunc_signed_v4f64(<4 x double> %x) nounwind { ret <4 x double> %r } -; FIXME: The attribute name is subject to change, but the fold may be +; The attribute name is subject to change, but the fold may be ; guarded to allow existing code to continue working based on its ; assumptions of float->int overflow. @@ -371,12 +371,17 @@ define float @trunc_unsigned_f32_disable_via_attr(float %x) #1 { ; ; SSE41-LABEL: trunc_unsigned_f32_disable_via_attr: ; SSE41: # %bb.0: -; SSE41-NEXT: roundss $11, %xmm0, %xmm0 +; SSE41-NEXT: cvttss2si %xmm0, %rax +; SSE41-NEXT: movl %eax, %eax +; SSE41-NEXT: xorps %xmm0, %xmm0 +; SSE41-NEXT: cvtsi2ssq %rax, %xmm0 ; SSE41-NEXT: retq ; ; AVX1-LABEL: trunc_unsigned_f32_disable_via_attr: ; AVX1: # %bb.0: -; AVX1-NEXT: vroundss $11, %xmm0, %xmm0, %xmm0 +; AVX1-NEXT: vcvttss2si %xmm0, %rax +; AVX1-NEXT: movl %eax, %eax +; AVX1-NEXT: vcvtsi2ssq %rax, %xmm1, %xmm0 ; AVX1-NEXT: retq %i = fptoui float %x to i32 %r = uitofp i32 %i to float @@ -393,12 +398,15 @@ define double @trunc_signed_f64_disable_via_attr(double %x) #1 { ; ; SSE41-LABEL: trunc_signed_f64_disable_via_attr: ; SSE41: # %bb.0: -; SSE41-NEXT: roundsd $11, %xmm0, %xmm0 +; SSE41-NEXT: cvttsd2si %xmm0, %rax +; SSE41-NEXT: xorps %xmm0, %xmm0 +; SSE41-NEXT: cvtsi2sdq %rax, %xmm0 ; SSE41-NEXT: retq ; ; AVX1-LABEL: trunc_signed_f64_disable_via_attr: ; AVX1: # %bb.0: -; AVX1-NEXT: vroundsd $11, %xmm0, %xmm0, %xmm0 +; AVX1-NEXT: vcvttsd2si %xmm0, %rax +; AVX1-NEXT: vcvtsi2sdq %rax, %xmm1, %xmm0 ; AVX1-NEXT: retq %i = fptosi double %x to i64 %r = sitofp i64 %i to double