This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch] for another problem in PR 29921


Hello,

this is a patch for the second problem exposed by fixing the assert in
set_lattice_value.  The problem is similar to the one with -0; with
HONOR_NANS = false, we fold

0 * NaN = NaN            (1)

but

0 * VARYING = 0          (2)

This causes incorrect transition from constant NaN to constant 0.  This
patch fixes the problem by treating NaN as UNDEFINED if HONOR_NANS =
false.  Obviously, this may cause misscompilations if NaN values really
appear in program compiled with flag_finite_math_only = true, but that
must be expected (since such code has undefined behavior), and cannot be
avoided as long as the equations (1) and (2) are inconsistent.

Bootstrapped & regtested on i686.

Zdenek

	PR tree-optimization/29921
	* tree-ssa-ccp.c (canonicalize_float_value): New function.
	(set_lattice_value): Use canonicalize_float_value.

	* gcc.dg/pr29921-2.c: New test.

Index: testsuite/gcc.dg/pr29921-2.c
===================================================================
*** testsuite/gcc.dg/pr29921-2.c	(revision 0)
--- testsuite/gcc.dg/pr29921-2.c	(revision 0)
***************
*** 0 ****
--- 1,27 ----
+ /* With -ffast-math, the latice value for sum2 used to change from NaN to
+    VARYING, in turn causing the lattice value of sum1 * sum2 change from
+    NaN to 0 (since sum1 is believed to be 0 at that moment, and
+    0 * VARYING = 0 with -ffast-math), which caused an ICE.  */
+ 
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -ffast-math" } */
+ 
+ int
+ foo (float *array, int end)
+ {
+   int i;
+   float sum1, sum2;
+ 
+   sum2 = 0;
+   for (i = 0; i < end; i++)
+     sum2 = sum2+array[i];
+   sum2 = 1./sum2;
+   sum1 = 0.;
+   for (i = 0; i < end; i++)
+     sum1 = sum1+array[i];
+   sum1 = sum1 * sum2;
+   if (-10.0 / sum1 < 5.E-5)
+     end = 0;
+   return end;
+ }
+ 
Index: tree-ssa-ccp.c
===================================================================
*** tree-ssa-ccp.c	(revision 119109)
--- tree-ssa-ccp.c	(working copy)
*************** set_value_varying (tree var)
*** 418,423 ****
--- 418,471 ----
    val->mem_ref = NULL_TREE;
  }
  
+ /* For float types, modify the value of VAL to make ccp work correctly
+    for non-standard values (-0, NaN):
+ 
+    If HONOR_SIGNED_ZEROS is false, and VAL = -0, we canonicalize it to 0.
+    If HONOR_NANS is false, and VAL is NaN, we canonicalize it to UNDEFINED.
+      This is to fix the following problem (see PR 29921): Suppose we have
+ 
+      x = 0.0 * y
+ 
+      and we set value of y to NaN.  This causes value of x to be set to NaN.
+      When we later determine that y is in fact VARYING, fold uses the fact
+      that HONOR_NANS is false, and we try to change the value of x to 0,
+      causing an ICE.  With HONOR_NANS being false, the real appearance of
+      NaN would cause undefined behavior, though, so claiming that y (and x)
+      are UNDEFINED initially is correct.  */
+ 
+ static void
+ canonicalize_float_value (prop_value_t *val)
+ {
+   enum machine_mode mode;
+   tree type;
+   REAL_VALUE_TYPE d;
+ 
+   if (val->lattice_val != CONSTANT
+       || TREE_CODE (val->value) != REAL_CST)
+     return;
+ 
+   d = TREE_REAL_CST (val->value);
+   type = TREE_TYPE (val->value);
+   mode = TYPE_MODE (type);
+ 
+   if (!HONOR_SIGNED_ZEROS (mode)
+       && REAL_VALUE_MINUS_ZERO (d))
+     {
+       val->value = build_real (type, dconst0);
+       return;
+     }
+ 
+   if (!HONOR_NANS (mode)
+       && REAL_VALUE_ISNAN (d))
+     {
+       val->lattice_val = UNDEFINED;
+       val->value = NULL;
+       val->mem_ref = NULL;
+       return;
+     }
+ }
+ 
  /* Set the value for variable VAR to NEW_VAL.  Return true if the new
     value is different from VAR's previous value.  */
  
*************** set_lattice_value (tree var, prop_value_
*** 426,431 ****
--- 474,481 ----
  {
    prop_value_t *old_val = get_value (var);
  
+   canonicalize_float_value (&new_val);
+ 
    /* Lattice transitions must always be monotonically increasing in
       value.  If *OLD_VAL and NEW_VAL are the same, return false to
       inform the caller that this was a non-transition.  */


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]