https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84891

Richard Biener <rguenth at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |wrong-code
             Status|UNCONFIRMED                 |NEW
   Last reconfirmed|                            |2018-03-16
                 CC|                            |jsm28 at gcc dot gnu.org,
                   |                            |rguenth at gcc dot gnu.org
          Component|c++                         |middle-end
     Ever confirmed|0                           |1

--- Comment #1 from Richard Biener <rguenth at gcc dot gnu.org> ---
We do

/* Maybe fold x * 0 to 0.  The expressions aren't the same
   when x is NaN, since x * 0 is also NaN.  Nor are they the
   same in modes with signed zeros, since multiplying a
   negative value by 0 gives -0, not +0.  */
(simplify
 (mult @0 real_zerop@1)
 (if (!HONOR_NANS (type) && !HONOR_SIGNED_ZEROS (type))
  @1))

that misses !HONOR_INFINITIES.  Not sure if that will fix the issue though.
It doesn't.

So it's tree-complex.c breaking things:

 int main() ()
 {
   complex double SR.24;
@@ -182,16 +145,18 @@
   _16 = std::char_traits<char>::length ("case INF: ");
   _17 = (long int) _16;
   std::__ostream_insert<char, std::char_traits<char> > (&cout, "case INF: ",
_17);
-  _15 = __complex__ ( Inf, 0.0) * __complex__ (0.0, 0.0);
-  MEM[(struct complex *)&D.50322] = _15;
+  _15 = COMPLEX_EXPR < Nan, 0.0>;
+  REALPART_EXPR <MEM[(struct complex *)&D.50322]> =  Nan;
+  IMAGPART_EXPR <MEM[(struct complex *)&D.50322]> = 0.0;
   _6 = std::operator<< <double, char, std::char_traits<char> > (&cout,
&D.50322);
   std::operator<< <std::char_traits<char> > (_6, "\n");
   D.50322 ={v} {CLOBBER};
   _19 = std::char_traits<char>::length ("case NAN: ");
   _20 = (long int) _19;
   std::__ostream_insert<char, std::char_traits<char> > (&cout, "case NAN: ",
_20);
-  _18 = __complex__ ( Nan, 0.0) * __complex__ (0.0, 0.0);
-  MEM[(struct complex *)&D.50338] = _18;
+  _18 = COMPLEX_EXPR < Nan, 0.0>;
+  REALPART_EXPR <MEM[(struct complex *)&D.50338]> =  Nan;
+  IMAGPART_EXPR <MEM[(struct complex *)&D.50338]> = 0.0;
   _12 = std::operator<< <double, char, std::char_traits<char> > (&cout,
&D.50338);
   std::operator<< <std::char_traits<char> > (_12, "\n");
   D.50338 ={v} {CLOBBER};
@@ -203,13 +168,6 @@

not sure why it gets it correct without -fno-signed-zeros...  ah, because of

/* Return true if T is not a zero constant.  In the case of real values,
   we're only interested in +0.0.  */

static int
some_nonzerop (tree t)
{
  int zerop = false;

  /* Operations with real or imaginary part of a complex number zero
     cannot be treated the same as operations with a real or imaginary
     operand if we care about the signs of zeros in the result.  */
  if (TREE_CODE (t) == REAL_CST && !flag_signed_zeros)
    zerop = real_identical (&TREE_REAL_CST (t), &dconst0);
  else if (TREE_CODE (t) == FIXED_CST)
    zerop = fixed_zerop (t);
  else if (TREE_CODE (t) == INTEGER_CST)
    zerop = integer_zerop (t);

  return !zerop;
}

so we "ignore" +0.0 for -fsigned-zeros completely.  The transforms
are not guarded by any other flag so we'd need to add !HONOR_NANS
and !HONOR_INFINITIES here, too it seems ...

Patch:

Index: gcc/tree-complex.c
===================================================================
--- gcc/tree-complex.c  (revision 258584)
+++ gcc/tree-complex.c  (working copy)
@@ -115,7 +115,13 @@ some_nonzerop (tree t)
   /* Operations with real or imaginary part of a complex number zero
      cannot be treated the same as operations with a real or imaginary
      operand if we care about the signs of zeros in the result.  */
-  if (TREE_CODE (t) == REAL_CST && !flag_signed_zeros)
+  if (TREE_CODE (t) == REAL_CST
+      /* Not detecting any zero as zero is the guard for invalid
+         followup transforms.  So that has to include 0.0 * NaN
+        and friends as well.  */
+      && !HONOR_SIGNED_ZEROS (t)
+      && !HONOR_NANS (t)
+      && !HONOR_INFINITIES (t))
     zerop = real_identical (&TREE_REAL_CST (t), &dconst0);
   else if (TREE_CODE (t) == FIXED_CST)
     zerop = fixed_zerop (t);

might be quite pessimizing, so it's probably better to guard the individual
"optimizations" properly... (also properly detecting positive zero as zero).

The following fixes the testcase as well:

Index: gcc/tree-complex.c
===================================================================
--- gcc/tree-complex.c  (revision 258584)
+++ gcc/tree-complex.c  (working copy)
@@ -358,8 +364,10 @@ complex_propagate::visit_stmt (gimple *s
       op1_l = find_lattice_value (gimple_assign_rhs1 (stmt));
       op2_l = find_lattice_value (gimple_assign_rhs2 (stmt));

-      /* Obviously, if either varies, so does the result.  */
-      if (op1_l == VARYING || op2_l == VARYING)
+      /* Obviously, if either varies, so does the result.  Likewise
+         if we have to honor NaNs or Infs in nonzero parts.  */
+      if (op1_l == VARYING || op2_l == VARYING
+         || HONOR_NANS (lhs) || HONOR_INFINITIES (lhs))
        new_l = VARYING;
       /* Don't prematurely promote variables if we've not yet seen
         their inputs.  */
@@ -1044,6 +1052,9 @@ expand_complex_multiplication (gimple_st
       tl = al, al = bl, bl = tl;
     }

+  if (HONOR_NANS (ar) || HONOR_INFINITIES (ar))
+    al = bl = VARYING;
+
   switch (PAIR (al, bl))
     {
     case PAIR (ONLY_REAL, ONLY_REAL):

probably the following hunk is needed as well for correctness.

@@ -1315,6 +1326,9 @@ expand_complex_division (gimple_stmt_ite
 {
   tree rr, ri;

+  if (HONOR_NANS (ar) || HONOR_INFINITIES (ar))
+    al = bl = VARYING;
+
   switch (PAIR (al, bl))
     {
     case PAIR (ONLY_REAL, ONLY_REAL):


In the end the lattice is a bit "simple", a more detailed one having
info about !NaN, !Inf in the respective components would be more
useful.  The second patch above means we preserve optimization on
plus, minus, negate, conj and equality compares - not sure if those
are correct in the presence of Nan/Inf, I didn't double-check these.
As said above the guarding against signed zero handling should be
moved down to individual optimizations as well (though I guess
none survives here?).

Joseph do you have any spare cycles checking tree-complex.c for this
issue?  Do you agree with what I said above?

Reply via email to