mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 11:13:28 +01:00
611aa86281
As discussed in the commit thread for rGa253a2a and D73978, we can do more undef folding for FP ops. The nnan and ninf fast-math-flags specify that if an operand is the disallowed value, the result is poison, so we can produce an undef result. But this doesn't work as expected (the undef operand cases remain) because of a Flags propagation problem in SelectionDAGBuilder. I've added DAGCombiner calls to enable these for the other cases because we've shown in other patches that (because of the limited way that SDAG iterates), it is possible to miss simplifications like this if they are done only at node creation time. Several potential follow-ups to expand on this patch are possible. Differential Revision: https://reviews.llvm.org/D75576
213 lines
5.3 KiB
LLVM
213 lines
5.3 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
|
; RUN: llc < %s -mtriple=aarch64-- | FileCheck %s
|
|
|
|
; https://bugs.llvm.org/show_bug.cgi?id=41668
|
|
|
|
define double @constant_fold_fdiv_by_zero(double* %p) {
|
|
; CHECK-LABEL: constant_fold_fdiv_by_zero:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: mov x8, #9218868437227405312
|
|
; CHECK-NEXT: fmov d0, x8
|
|
; CHECK-NEXT: ret
|
|
%r = fdiv double 4.940660e-324, 0.0
|
|
ret double %r
|
|
}
|
|
|
|
; frem by 0.0 --> NaN
|
|
|
|
define double @constant_fold_frem_by_zero(double* %p) {
|
|
; CHECK-LABEL: constant_fold_frem_by_zero:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: mov x8, #9221120237041090560
|
|
; CHECK-NEXT: fmov d0, x8
|
|
; CHECK-NEXT: ret
|
|
%r = frem double 4.940660e-324, 0.0
|
|
ret double %r
|
|
}
|
|
|
|
; Inf * 0.0 --> NaN
|
|
|
|
define double @constant_fold_fmul_nan(double* %p) {
|
|
; CHECK-LABEL: constant_fold_fmul_nan:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: mov x8, #9221120237041090560
|
|
; CHECK-NEXT: fmov d0, x8
|
|
; CHECK-NEXT: ret
|
|
%r = fmul double 0x7ff0000000000000, 0.0
|
|
ret double %r
|
|
}
|
|
|
|
; Inf + -Inf --> NaN
|
|
|
|
define double @constant_fold_fadd_nan(double* %p) {
|
|
; CHECK-LABEL: constant_fold_fadd_nan:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: mov x8, #9221120237041090560
|
|
; CHECK-NEXT: fmov d0, x8
|
|
; CHECK-NEXT: ret
|
|
%r = fadd double 0x7ff0000000000000, 0xfff0000000000000
|
|
ret double %r
|
|
}
|
|
|
|
; Inf - Inf --> NaN
|
|
|
|
define double @constant_fold_fsub_nan(double* %p) {
|
|
; CHECK-LABEL: constant_fold_fsub_nan:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: mov x8, #9221120237041090560
|
|
; CHECK-NEXT: fmov d0, x8
|
|
; CHECK-NEXT: ret
|
|
%r = fsub double 0x7ff0000000000000, 0x7ff0000000000000
|
|
ret double %r
|
|
}
|
|
|
|
; Inf * 0.0 + ? --> NaN
|
|
|
|
define double @constant_fold_fma_nan(double* %p) {
|
|
; CHECK-LABEL: constant_fold_fma_nan:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: mov x8, #9221120237041090560
|
|
; CHECK-NEXT: fmov d0, x8
|
|
; CHECK-NEXT: ret
|
|
%r = call double @llvm.fma.f64(double 0x7ff0000000000000, double 0.0, double 42.0)
|
|
ret double %r
|
|
}
|
|
|
|
define double @fdiv_nnan_nan_op0(double %x) {
|
|
; CHECK-LABEL: fdiv_nnan_nan_op0:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: ret
|
|
%r = fdiv nnan double 0xfff8000000000000, %x
|
|
ret double %r
|
|
}
|
|
|
|
define double @fmul_nnan_nan_op1(double %x) {
|
|
; CHECK-LABEL: fmul_nnan_nan_op1:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: ret
|
|
%r = fmul nnan double %x, 0x7ff8000000000000
|
|
ret double %r
|
|
}
|
|
|
|
; Negative test - nan is ok.
|
|
; TODO: Should simplify to nan.
|
|
|
|
define double @fdiv_ninf_nan_op0(double %x) {
|
|
; CHECK-LABEL: fdiv_ninf_nan_op0:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: mov x8, #-2251799813685248
|
|
; CHECK-NEXT: fmov d1, x8
|
|
; CHECK-NEXT: fdiv d0, d1, d0
|
|
; CHECK-NEXT: ret
|
|
%r = fdiv ninf double 0xfff8000000000000, %x
|
|
ret double %r
|
|
}
|
|
|
|
; Negative test - nan is ok.
|
|
; TODO: Should simplify to nan.
|
|
|
|
define double @fadd_ninf_nan_op1(double %x) {
|
|
; CHECK-LABEL: fadd_ninf_nan_op1:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: mov x8, #9221120237041090560
|
|
; CHECK-NEXT: fmov d1, x8
|
|
; CHECK-NEXT: fadd d0, d0, d1
|
|
; CHECK-NEXT: ret
|
|
%r = fadd ninf double %x, 0x7ff8000000000000
|
|
ret double %r
|
|
}
|
|
|
|
define double @fdiv_ninf_inf_op0(double %x) {
|
|
; CHECK-LABEL: fdiv_ninf_inf_op0:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: ret
|
|
%r = fdiv ninf double 0x7ff0000000000000, %x
|
|
ret double %r
|
|
}
|
|
|
|
define double @fadd_ninf_inf_op1(double %x) {
|
|
; CHECK-LABEL: fadd_ninf_inf_op1:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: ret
|
|
%r = fadd ninf double %x, 0xfff0000000000000
|
|
ret double %r
|
|
}
|
|
|
|
; Negative test - inf is ok.
|
|
; TODO: Should simplify to inf.
|
|
|
|
define double @fsub_nnan_inf_op0(double %x) {
|
|
; CHECK-LABEL: fsub_nnan_inf_op0:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: mov x8, #9218868437227405312
|
|
; CHECK-NEXT: fmov d1, x8
|
|
; CHECK-NEXT: fsub d0, d1, d0
|
|
; CHECK-NEXT: ret
|
|
%r = fsub nnan double 0x7ff0000000000000, %x
|
|
ret double %r
|
|
}
|
|
|
|
; Negative test - inf is ok.
|
|
; TODO: Should simplify to -inf.
|
|
|
|
define double @fmul_nnan_inf_op1(double %x) {
|
|
; CHECK-LABEL: fmul_nnan_inf_op1:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: mov x8, #-4503599627370496
|
|
; CHECK-NEXT: fmov d1, x8
|
|
; CHECK-NEXT: fmul d0, d0, d1
|
|
; CHECK-NEXT: ret
|
|
%r = fmul nnan double %x, 0xfff0000000000000
|
|
ret double %r
|
|
}
|
|
|
|
; TODO: Should simplify to undef
|
|
|
|
define double @fdiv_nnan_undef_op0(double %x) {
|
|
; CHECK-LABEL: fdiv_nnan_undef_op0:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: mov x8, #9221120237041090560
|
|
; CHECK-NEXT: fmov d0, x8
|
|
; CHECK-NEXT: ret
|
|
%r = fdiv nnan double undef, %x
|
|
ret double %r
|
|
}
|
|
|
|
; TODO: Should simplify to undef
|
|
|
|
define double @fdiv_nnan_undef_op1(double %x) {
|
|
; CHECK-LABEL: fdiv_nnan_undef_op1:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: mov x8, #9221120237041090560
|
|
; CHECK-NEXT: fmov d0, x8
|
|
; CHECK-NEXT: ret
|
|
%r = fdiv nnan double %x, undef
|
|
ret double %r
|
|
}
|
|
|
|
; TODO: Should simplify to undef
|
|
|
|
define double @fdiv_ninf_undef_op0(double %x) {
|
|
; CHECK-LABEL: fdiv_ninf_undef_op0:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: mov x8, #9221120237041090560
|
|
; CHECK-NEXT: fmov d0, x8
|
|
; CHECK-NEXT: ret
|
|
%r = fdiv ninf double undef, %x
|
|
ret double %r
|
|
}
|
|
|
|
; TODO: Should simplify to undef
|
|
|
|
define double @fdiv_ninf_undef_op1(double %x) {
|
|
; CHECK-LABEL: fdiv_ninf_undef_op1:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: mov x8, #9221120237041090560
|
|
; CHECK-NEXT: fmov d0, x8
|
|
; CHECK-NEXT: ret
|
|
%r = fdiv ninf double %x, undef
|
|
ret double %r
|
|
}
|
|
|
|
declare double @llvm.fma.f64(double, double, double)
|