On Mon, Oct 17, 2022 at 08:21:01AM +0200, Aldy Hernandez wrote:
> +// Set VALUE to its next real value, or INF if the operation overflows.
> +
> +inline void
> +frange_nextafter (enum machine_mode mode,
> +               REAL_VALUE_TYPE &value,
> +               const REAL_VALUE_TYPE &inf)
> +{
> +  const real_format *fmt = REAL_MODE_FORMAT (mode);
> +  REAL_VALUE_TYPE tmp;
> +  bool overflow = real_nextafter (&tmp, fmt, &value, &inf);
> +  if (overflow)
> +    value = inf;
> +  else
> +    value = tmp;

Please change the above 5 lines to just
  real_nextafter (&tmp, fmt, &value, &inf);
  value = tmp;
What real_nextafter returns isn't bool whether it overflowed, but
a bool whether some exception should be raised for the nextafter,
which can be either an overflow (in that case tmp will be already set
to infinity of the right sign:
          if (REAL_EXP (r) > fmt->emax)
            {
              get_inf (r, x->sign);
              return true;
            }
or underflow to zero:
  if (REAL_EXP (r) <= fmt->emin - fmt->p)
    {
      get_zero (r, x->sign);
      return true;
    }
or when the result is subnormal:
  return r->cl == rvc_zero || REAL_EXP (r) < fmt->emin;
But we shouldn't care about exceptions, we aren't emitting code, just
estimating floating point range, and +-inf, or +-0, or subnormal
are the right answers.

Just for playing with this, I've tried:
--- range-op-float.cc.jj        2022-11-02 10:06:02.620960861 +0100
+++ range-op-float.cc   2022-11-04 19:49:14.188075070 +0100
@@ -1815,6 +1815,20 @@ frange_float (const char *lb, const char
   return frange (type, min, max);
 }
 
+inline void                                                                    
                                                                                
                    
+frange_nextafter (enum machine_mode mode,                                      
                                                                                
                    
+                 REAL_VALUE_TYPE &value,                                       
                                                                                
                      
+                 const REAL_VALUE_TYPE &inf)                                   
                                                                                
                      
+{                                                                              
                                                                                
                    
+  const real_format *fmt = REAL_MODE_FORMAT (mode);                            
                                                                                
                    
+  REAL_VALUE_TYPE tmp;                                                         
                                                                                
                    
+  bool overflow = real_nextafter (&tmp, fmt, &value, &inf);                    
                                                                                
                    
+  if (overflow)                                                                
                                                                                
                    
+    value = inf;                                                               
                                                                                
                    
+  else                                                                         
                                                                                
                    
+   value = tmp;                                                                
                                                                                
                   
+}                                                                              
                                                                                
                    
+
 void
 range_op_float_tests ()
 {
@@ -1833,6 +1847,30 @@ range_op_float_tests ()
   r1 = frange_float ("-1", "-0");
   r1.update_nan (false);
   ASSERT_EQ (r, r1);
+
+  if (MODE_COMPOSITE_P (TYPE_MODE (long_double_type_node)))
+    {
+      enum machine_mode mode = TYPE_MODE (long_double_type_node);
+      REAL_VALUE_TYPE result = dconst0;
+      {
+       REAL_VALUE_TYPE tmp;
+       real_convert (&tmp, DFmode, &result);
+       frange_nextafter (DFmode, tmp, dconstinf);
+       real_convert (&result, mode, &tmp);
+      }
+      for (int i = 0; i < 108; ++i)
+       {
+         char buf[1024], buf2[1024];
+         REAL_VALUE_TYPE tmp, tmp2;
+         real_convert (&tmp, DFmode, &result);
+         frange_nextafter (DFmode, tmp, dconstinf);
+         real_convert (&tmp2, mode, &tmp);
+         real_to_hexadecimal (buf, &result, 1024, 0, 1);
+         real_to_hexadecimal (buf2, &tmp2, 1024, 0, 1);
+         fprintf (stderr, "%d %d %s %s\n", i, real_isdenormal (&result), buf, 
buf2);
+         real_arithmetic (&result, MULT_EXPR, &result, &dconst2);
+       }
+    }
 }
 
 } // namespace selftest

  
in cross to powerpc64le-linux and I get:
0 0 0x0.8p-1073 0x0.8p-1072
1 0 0x0.8p-1072 0x0.cp-1072
2 0 0x0.8p-1071 0x0.ap-1071
3 0 0x0.8p-1070 0x0.9p-1070
4 0 0x0.8p-1069 0x0.88p-1069
5 0 0x0.8p-1068 0x0.84p-1068
6 0 0x0.8p-1067 0x0.82p-1067
7 0 0x0.8p-1066 0x0.81p-1066
8 0 0x0.8p-1065 0x0.808p-1065
9 0 0x0.8p-1064 0x0.804p-1064
10 0 0x0.8p-1063 0x0.802p-1063
11 0 0x0.8p-1062 0x0.801p-1062
12 0 0x0.8p-1061 0x0.8008p-1061
13 0 0x0.8p-1060 0x0.8004p-1060
14 0 0x0.8p-1059 0x0.8002p-1059
15 0 0x0.8p-1058 0x0.8001p-1058
16 0 0x0.8p-1057 0x0.80008p-1057
17 0 0x0.8p-1056 0x0.80004p-1056
18 0 0x0.8p-1055 0x0.80002p-1055
19 0 0x0.8p-1054 0x0.80001p-1054
20 0 0x0.8p-1053 0x0.800008p-1053
21 0 0x0.8p-1052 0x0.800004p-1052
22 0 0x0.8p-1051 0x0.800002p-1051
23 0 0x0.8p-1050 0x0.800001p-1050
24 0 0x0.8p-1049 0x0.8000008p-1049
25 0 0x0.8p-1048 0x0.8000004p-1048
26 0 0x0.8p-1047 0x0.8000002p-1047
27 0 0x0.8p-1046 0x0.8000001p-1046
28 0 0x0.8p-1045 0x0.80000008p-1045
29 0 0x0.8p-1044 0x0.80000004p-1044
30 0 0x0.8p-1043 0x0.80000002p-1043
31 0 0x0.8p-1042 0x0.80000001p-1042
32 0 0x0.8p-1041 0x0.800000008p-1041
33 0 0x0.8p-1040 0x0.800000004p-1040
34 0 0x0.8p-1039 0x0.800000002p-1039
35 0 0x0.8p-1038 0x0.800000001p-1038
36 0 0x0.8p-1037 0x0.8000000008p-1037
37 0 0x0.8p-1036 0x0.8000000004p-1036
38 0 0x0.8p-1035 0x0.8000000002p-1035
39 0 0x0.8p-1034 0x0.8000000001p-1034
40 0 0x0.8p-1033 0x0.80000000008p-1033
41 0 0x0.8p-1032 0x0.80000000004p-1032
42 0 0x0.8p-1031 0x0.80000000002p-1031
43 0 0x0.8p-1030 0x0.80000000001p-1030
44 0 0x0.8p-1029 0x0.800000000008p-1029
45 0 0x0.8p-1028 0x0.800000000004p-1028
46 0 0x0.8p-1027 0x0.800000000002p-1027
47 0 0x0.8p-1026 0x0.800000000001p-1026
48 0 0x0.8p-1025 0x0.8000000000008p-1025
49 0 0x0.8p-1024 0x0.8000000000004p-1024
50 0 0x0.8p-1023 0x0.8000000000002p-1023
51 0 0x0.8p-1022 0x0.8000000000001p-1022
52 0 0x0.8p-1021 0x0.80000000000008p-1021
53 0 0x0.8p-1020 0x0.80000000000008p-1020
54 0 0x0.8p-1019 0x0.80000000000008p-1019
55 0 0x0.8p-1018 0x0.80000000000008p-1018
56 0 0x0.8p-1017 0x0.80000000000008p-1017
57 0 0x0.8p-1016 0x0.80000000000008p-1016
58 0 0x0.8p-1015 0x0.80000000000008p-1015
59 0 0x0.8p-1014 0x0.80000000000008p-1014
60 0 0x0.8p-1013 0x0.80000000000008p-1013
61 0 0x0.8p-1012 0x0.80000000000008p-1012
62 0 0x0.8p-1011 0x0.80000000000008p-1011
63 0 0x0.8p-1010 0x0.80000000000008p-1010
64 0 0x0.8p-1009 0x0.80000000000008p-1009
65 0 0x0.8p-1008 0x0.80000000000008p-1008
66 0 0x0.8p-1007 0x0.80000000000008p-1007
67 0 0x0.8p-1006 0x0.80000000000008p-1006
68 0 0x0.8p-1005 0x0.80000000000008p-1005
69 0 0x0.8p-1004 0x0.80000000000008p-1004
70 0 0x0.8p-1003 0x0.80000000000008p-1003
71 0 0x0.8p-1002 0x0.80000000000008p-1002
72 0 0x0.8p-1001 0x0.80000000000008p-1001
73 0 0x0.8p-1000 0x0.80000000000008p-1000
74 0 0x0.8p-999 0x0.80000000000008p-999
75 0 0x0.8p-998 0x0.80000000000008p-998
76 0 0x0.8p-997 0x0.80000000000008p-997
77 0 0x0.8p-996 0x0.80000000000008p-996
78 0 0x0.8p-995 0x0.80000000000008p-995
79 0 0x0.8p-994 0x0.80000000000008p-994
80 0 0x0.8p-993 0x0.80000000000008p-993
81 0 0x0.8p-992 0x0.80000000000008p-992
82 0 0x0.8p-991 0x0.80000000000008p-991
83 0 0x0.8p-990 0x0.80000000000008p-990
84 0 0x0.8p-989 0x0.80000000000008p-989
85 0 0x0.8p-988 0x0.80000000000008p-988
86 0 0x0.8p-987 0x0.80000000000008p-987
87 0 0x0.8p-986 0x0.80000000000008p-986
88 0 0x0.8p-985 0x0.80000000000008p-985
89 0 0x0.8p-984 0x0.80000000000008p-984
90 0 0x0.8p-983 0x0.80000000000008p-983
91 0 0x0.8p-982 0x0.80000000000008p-982
92 0 0x0.8p-981 0x0.80000000000008p-981
93 0 0x0.8p-980 0x0.80000000000008p-980
94 0 0x0.8p-979 0x0.80000000000008p-979
95 0 0x0.8p-978 0x0.80000000000008p-978
96 0 0x0.8p-977 0x0.80000000000008p-977
97 0 0x0.8p-976 0x0.80000000000008p-976
98 0 0x0.8p-975 0x0.80000000000008p-975
99 0 0x0.8p-974 0x0.80000000000008p-974
100 0 0x0.8p-973 0x0.80000000000008p-973
101 0 0x0.8p-972 0x0.80000000000008p-972
102 0 0x0.8p-971 0x0.80000000000008p-971
103 0 0x0.8p-970 0x0.80000000000008p-970
104 0 0x0.8p-969 0x0.80000000000008p-969
105 0 0x0.8p-968 0x0.80000000000008p-968
106 0 0x0.8p-967 0x0.80000000000008p-967
107 0 0x0.8p-966 0x0.80000000000008p-966

One thing that is clear is that real_isdenormal is never true for these
(but then a question is if flush_denormals_to_zero actually works).

        Jakub

Reply via email to