|
1 |
| -//@ compile-flags: -Zmir-opt-level=0 -Znext-solver |
2 | 1 | //@ run-pass
|
| 2 | +//@ revisions: opt noopt ctfe |
| 3 | +//@[opt] compile-flags: -O |
| 4 | +//@[noopt] compile-flags: -Zmir-opt-level=0 |
3 | 5 | // ignore-tidy-linelength
|
4 | 6 |
|
5 | 7 | // This tests the float classification functions, for regular runtime code and for const evaluation.
|
|
8 | 10 | #![feature(f128_const)]
|
9 | 11 | #![feature(const_float_classify)]
|
10 | 12 |
|
11 |
| -use std::hint::black_box; |
12 | 13 | use std::num::FpCategory::*;
|
13 | 14 |
|
14 |
| -macro_rules! both_assert { |
| 15 | +#[cfg(not(ctfe))] |
| 16 | +use std::hint::black_box; |
| 17 | +#[cfg(ctfe)] |
| 18 | +#[allow(unused)] |
| 19 | +const fn black_box<T>(x: T) -> T { x } |
| 20 | + |
| 21 | +#[cfg(not(ctfe))] |
| 22 | +macro_rules! assert_test { |
| 23 | + ($a:expr, NonDet) => { |
| 24 | + { |
| 25 | + // Compute `a`, but do not compare with anything as the result is non-deterministic. |
| 26 | + let _val = $a; |
| 27 | + } |
| 28 | + }; |
| 29 | + ($a:expr, $b:ident) => { |
| 30 | + { |
| 31 | + // Let-bind to avoid promotion. |
| 32 | + // No black_box here! That can mask x87 failures. |
| 33 | + let a = $a; |
| 34 | + let b = $b; |
| 35 | + assert_eq!(a, b, "{} produces wrong result", stringify!($a)); |
| 36 | + } |
| 37 | + }; |
| 38 | +} |
| 39 | +#[cfg(ctfe)] |
| 40 | +macro_rules! assert_test { |
15 | 41 | ($a:expr, NonDet) => {
|
16 | 42 | {
|
17 | 43 | // Compute `a`, but do not compare with anything as the result is non-deterministic.
|
18 | 44 | const _: () = { let _val = $a; };
|
19 |
| - // `black_box` prevents promotion, and MIR opts are disabled above, so this is truly |
20 |
| - // going through LLVM. |
21 |
| - let _val = black_box($a); |
22 | 45 | }
|
23 | 46 | };
|
24 | 47 | ($a:expr, $b:ident) => {
|
25 | 48 | {
|
26 | 49 | const _: () = assert!(matches!($a, $b));
|
27 |
| - assert!(black_box($a) == black_box($b)); |
28 | 50 | }
|
29 | 51 | };
|
30 | 52 | }
|
31 | 53 |
|
32 | 54 | macro_rules! suite {
|
33 |
| - ( $tyname:ident: $( $tt:tt )* ) => { |
| 55 | + ( $tyname:ident => $( $tt:tt )* ) => { |
34 | 56 | fn f32() {
|
| 57 | + #[allow(unused)] |
35 | 58 | type $tyname = f32;
|
36 |
| - suite_inner!(f32 $($tt)*); |
| 59 | + suite_inner!(f32 => $($tt)*); |
37 | 60 | }
|
38 | 61 |
|
39 | 62 | fn f64() {
|
| 63 | + #[allow(unused)] |
40 | 64 | type $tyname = f64;
|
41 |
| - suite_inner!(f64 $($tt)*); |
| 65 | + suite_inner!(f64 => $($tt)*); |
42 | 66 | }
|
43 | 67 | }
|
44 | 68 | }
|
45 | 69 |
|
46 | 70 | macro_rules! suite_inner {
|
47 | 71 | (
|
48 |
| - $ty:ident [$( $fn:ident ),*] |
49 |
| - $val:expr => [$($out:ident),*] |
| 72 | + $ty:ident => [$( $fn:ident ),*]: |
| 73 | + $(@cfg: $attr:meta)? |
| 74 | + $val:expr => [$($out:ident),*], |
50 | 75 |
|
51 | 76 | $( $tail:tt )*
|
52 | 77 | ) => {
|
53 |
| - $( both_assert!($ty::$fn($val), $out); )* |
54 |
| - suite_inner!($ty [$($fn),*] $($tail)*) |
| 78 | + $(#[cfg($attr)])? |
| 79 | + { |
| 80 | + // No black_box here! That can mask x87 failures. |
| 81 | + $( assert_test!($ty::$fn($val), $out); )* |
| 82 | + } |
| 83 | + suite_inner!($ty => [$($fn),*]: $($tail)*) |
55 | 84 | };
|
56 | 85 |
|
57 |
| - ( $ty:ident [$( $fn:ident ),*]) => {}; |
| 86 | + ( $ty:ident => [$( $fn:ident ),*]:) => {}; |
58 | 87 | }
|
59 | 88 |
|
60 | 89 | // The result of the `is_sign` methods are not checked for correctness, since we do not
|
61 | 90 | // guarantee anything about the signedness of NaNs. See
|
62 | 91 | // https://rust-lang.github.io/rfcs/3514-float-semantics.html.
|
63 | 92 |
|
64 |
| -suite! { T: // type alias for the type we are testing |
65 |
| - [ classify, is_nan, is_infinite, is_finite, is_normal, is_sign_positive, is_sign_negative] |
66 |
| - -0.0 / 0.0 => [ Nan, true, false, false, false, NonDet, NonDet] |
67 |
| - 0.0 / 0.0 => [ Nan, true, false, false, false, NonDet, NonDet] |
68 |
| - 1.0 => [ Normal, false, false, true, true, true, false] |
69 |
| - -1.0 => [ Normal, false, false, true, true, false, true] |
70 |
| - 0.0 => [ Zero, false, false, true, false, true, false] |
71 |
| - -0.0 => [ Zero, false, false, true, false, false, true] |
72 |
| - 1.0 / 0.0 => [ Infinite, false, true, false, false, true, false] |
73 |
| - -1.0 / 0.0 => [ Infinite, false, true, false, false, false, true] |
74 |
| - 1.0 / T::MAX => [Subnormal, false, false, true, false, true, false] |
75 |
| - -1.0 / T::MAX => [Subnormal, false, false, true, false, false, true] |
| 93 | +suite! { T => // type alias for the type we are testing |
| 94 | + [ classify, is_nan, is_infinite, is_finite, is_normal, is_sign_positive, is_sign_negative]: |
| 95 | + black_box(0.0) / black_box(0.0) => |
| 96 | + [ Nan, true, false, false, false, NonDet, NonDet], |
| 97 | + black_box(0.0) / black_box(-0.0) => |
| 98 | + [ Nan, true, false, false, false, NonDet, NonDet], |
| 99 | + black_box(0.0) * black_box(T::INFINITY) => |
| 100 | + [ Nan, true, false, false, false, NonDet, NonDet], |
| 101 | + black_box(0.0) * black_box(T::NEG_INFINITY) => |
| 102 | + [ Nan, true, false, false, false, NonDet, NonDet], |
| 103 | + 1.0 => [ Normal, false, false, true, true, true, false], |
| 104 | + -1.0 => [ Normal, false, false, true, true, false, true], |
| 105 | + 0.0 => [ Zero, false, false, true, false, true, false], |
| 106 | + -0.0 => [ Zero, false, false, true, false, false, true], |
| 107 | + 1.0 / black_box(0.0) => |
| 108 | + [ Infinite, false, true, false, false, true, false], |
| 109 | + -1.0 / black_box(0.0) => |
| 110 | + [ Infinite, false, true, false, false, false, true], |
| 111 | + 2.0 * black_box(T::MAX) => |
| 112 | + [ Infinite, false, true, false, false, true, false], |
| 113 | + -2.0 * black_box(T::MAX) => |
| 114 | + [ Infinite, false, true, false, false, false, true], |
| 115 | + 1.0 / black_box(T::MAX) => |
| 116 | + [Subnormal, false, false, true, false, true, false], |
| 117 | + -1.0 / black_box(T::MAX) => |
| 118 | + [Subnormal, false, false, true, false, false, true], |
| 119 | + // This specific expression causes trouble on x87 due to |
| 120 | + // <https://github.com/rust-lang/rust/issues/114479>. |
| 121 | + @cfg: not(all(target_arch = "x86", not(target_feature = "sse2"))) |
| 122 | + { let x = black_box(T::MAX); x * x } => |
| 123 | + [ Infinite, false, true, false, false, true, false], |
76 | 124 | }
|
77 | 125 |
|
78 | 126 | fn main() {
|
|
0 commit comments