mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-26 04:32:44 +01:00
b09ad4fef7
Summary: For some reason the order in which we call getNegatedExpression for the involved operands, after a call to isCheaperToUseNegatedFPOps, seem to matter. This patch includes a new test case in test/CodeGen/X86/fdiv.ll that crashes if we reverse the order of those calls. Before this patch that could happen depending on which compiler that were used when buildind llvm. With my GCC version (7.4.0) I got the crash, because it seems like it is using a different order for the argument evaluation compared to clang. All other users of isCheaperToUseNegatedFPOps already used this pattern with unfolded/ordered calls to getNegatedExpression, so this patch is aligning visitFDIV with the other use cases. This patch simply deals with the non-determinism for FDIV. While the underlying problem with getNegatedExpression is discussed further in D76439. Reviewers: spatel, RKSimon Reviewed By: spatel Subscribers: hiraditya, mgrang, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D76319
105 lines
3.2 KiB
LLVM
105 lines
3.2 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
|
; RUN: llc < %s -mtriple=x86_64-unknown-unknown -enable-unsafe-fp-math | FileCheck %s
|
|
|
|
define double @exact(double %x) {
|
|
; Exact division by a constant converted to multiplication.
|
|
; CHECK-LABEL: exact:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: mulsd {{.*}}(%rip), %xmm0
|
|
; CHECK-NEXT: retq
|
|
%div = fdiv double %x, 2.0
|
|
ret double %div
|
|
}
|
|
|
|
define double @inexact(double %x) {
|
|
; Inexact division by a constant converted to multiplication.
|
|
; CHECK-LABEL: inexact:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: mulsd {{.*}}(%rip), %xmm0
|
|
; CHECK-NEXT: retq
|
|
%div = fdiv double %x, 0x41DFFFFFFFC00000
|
|
ret double %div
|
|
}
|
|
|
|
define double @funky(double %x) {
|
|
; No conversion to multiplication if too funky.
|
|
; CHECK-LABEL: funky:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: xorpd %xmm1, %xmm1
|
|
; CHECK-NEXT: divsd %xmm1, %xmm0
|
|
; CHECK-NEXT: retq
|
|
%div = fdiv double %x, 0.0
|
|
ret double %div
|
|
}
|
|
|
|
define double @denormal1(double %x) {
|
|
; Don't generate multiplication by a denormal.
|
|
; CHECK-LABEL: denormal1:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: divsd {{.*}}(%rip), %xmm0
|
|
; CHECK-NEXT: retq
|
|
%div = fdiv double %x, 0x7FD0000000000001
|
|
ret double %div
|
|
}
|
|
|
|
define double @denormal2(double %x) {
|
|
; Don't generate multiplication by a denormal.
|
|
; CHECK-LABEL: denormal2:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: divsd {{.*}}(%rip), %xmm0
|
|
; CHECK-NEXT: retq
|
|
%div = fdiv double %x, 0x7FEFFFFFFFFFFFFF
|
|
ret double %div
|
|
}
|
|
|
|
; Deleting the negates does not require unsafe-fp-math.
|
|
|
|
define float @double_negative(float %x, float %y) #0 {
|
|
; CHECK-LABEL: double_negative:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: divss %xmm1, %xmm0
|
|
; CHECK-NEXT: retq
|
|
%neg1 = fsub float -0.0, %x
|
|
%neg2 = fsub float -0.0, %y
|
|
%div = fdiv float %neg1, %neg2
|
|
ret float %div
|
|
}
|
|
|
|
define <4 x float> @double_negative_vector(<4 x float> %x, <4 x float> %y) #0 {
|
|
; CHECK-LABEL: double_negative_vector:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: divps %xmm1, %xmm0
|
|
; CHECK-NEXT: retq
|
|
%neg1 = fsub <4 x float> <float -0.0, float -0.0, float -0.0, float -0.0>, %x
|
|
%neg2 = fsub <4 x float> <float -0.0, float -0.0, float -0.0, float -0.0>, %y
|
|
%div = fdiv <4 x float> %neg1, %neg2
|
|
ret <4 x float> %div
|
|
}
|
|
|
|
; This test used to fail, depending on how llc was built (e.g. using
|
|
; clang/gcc), due to order of argument evaluation not being well defined. We
|
|
; ended up hitting llvm_unreachable in getNegatedExpression when building with
|
|
; gcc. Just make sure that we get a deterministic result.
|
|
define float @fdiv_fneg_combine(float %a0, float %a1, float %a2) #0 {
|
|
; CHECK-LABEL: fdiv_fneg_combine:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: movaps %xmm0, %xmm3
|
|
; CHECK-NEXT: subss %xmm1, %xmm3
|
|
; CHECK-NEXT: subss %xmm0, %xmm1
|
|
; CHECK-NEXT: mulss %xmm2, %xmm1
|
|
; CHECK-NEXT: subss %xmm2, %xmm3
|
|
; CHECK-NEXT: divss %xmm3, %xmm1
|
|
; CHECK-NEXT: movaps %xmm1, %xmm0
|
|
; CHECK-NEXT: retq
|
|
%sub1 = fsub fast float %a0, %a1
|
|
%mul2 = fmul fast float %sub1, %a2
|
|
%neg = fneg fast float %a0
|
|
%add3 = fadd fast float %a1, %neg
|
|
%sub4 = fadd fast float %add3, %a2
|
|
%div5 = fdiv fast float %mul2, %sub4
|
|
ret float %div5
|
|
}
|
|
|
|
attributes #0 = { "unsafe-fp-math"="false" }
|
|
|