[Bug tree-optimization/97555] [11 Regression] wrong code at -Os and above on x86_64-pc-linux-gnu since r11-3685

2020-10-26 Thread aldyh at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97555

Aldy Hernandez  changed:

   What|Removed |Added

 Status|NEW |RESOLVED
 Resolution|--- |FIXED

--- Comment #6 from Aldy Hernandez  ---
fixed

[Bug tree-optimization/97555] [11 Regression] wrong code at -Os and above on x86_64-pc-linux-gnu since r11-3685

2020-10-26 Thread cvs-commit at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97555

--- Comment #5 from CVS Commits  ---
The master branch has been updated by Aldy Hernandez :

https://gcc.gnu.org/g:2118438f49f0c193abe3fa3def350a8129045746

commit r11-4390-g2118438f49f0c193abe3fa3def350a8129045746
Author: Aldy Hernandez 
Date:   Mon Oct 26 17:50:37 2020 +0100

Handle signed 1-bit ranges in irange::invert.

The problem here is we are trying to add 1 to a -1 in a signed 1-bit
field and coming up with UNDEFINED because of the overflow.

Signed 1-bits are annoying because you can't really add or subtract
one, because the one is unrepresentable.  For invert() we have a
special subtract_one() function that handles 1-bit signed fields.

This patch implements the analogous add_one() function so that invert
works.

gcc/ChangeLog:

PR tree-optimization/97555
* range-op.cc (range_tests): Test 1-bit signed invert.
* value-range.cc (subtract_one): Adjust comment.
(add_one): New.
(irange::invert): Call add_one.

gcc/testsuite/ChangeLog:

* gcc.dg/pr97555.c: New test.

[Bug tree-optimization/97555] [11 Regression] wrong code at -Os and above on x86_64-pc-linux-gnu since r11-3685

2020-10-26 Thread aldyh at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97555

--- Comment #4 from Aldy Hernandez  ---
The problem here is we're trying to add 1 to a -1 in a signed 1-bit field.

Signed 1-bits are annoying because you can't really add or subtract one,
because the one is unrepresentable.  For invert() we have a special
subtract_one() function that handles 1-bit signed fields.  We need a
corresponding add_one() here.

The untested patch below should do it. 

diff --git a/gcc/range-op.cc b/gcc/range-op.cc
index ee62f103598..74ab2e57fde 100644
--- a/gcc/range-op.cc
+++ b/gcc/range-op.cc
@@ -3680,15 +3680,28 @@ range_tests ()
   // Test 1-bit signed integer union.
   // [-1,-1] U [0,0] = VARYING.
   tree one_bit_type = build_nonstandard_integer_type (1, 0);
+  tree one_bit_min = vrp_val_min (one_bit_type);
+  tree one_bit_max = vrp_val_max (one_bit_type);
   {
-tree one_bit_min = vrp_val_min (one_bit_type);
-tree one_bit_max = vrp_val_max (one_bit_type);
 int_range<2> min (one_bit_min, one_bit_min);
 int_range<2> max (one_bit_max, one_bit_max);
 max.union_ (min);
 ASSERT_TRUE (max.varying_p ());
   }

+  // Test inversion of 1-bit signed integers.
+  {
+int_range<2> min (one_bit_min, one_bit_min);
+int_range<2> max (one_bit_max, one_bit_max);
+int_range<2> t;
+t = min;
+t.invert ();
+ASSERT_TRUE (t == max);
+t = max;
+t.invert ();
+ASSERT_TRUE (t == min);
+  }
+
   // Test that NOT(255) is [0..254] in 8-bit land.
   int_range<1> not_255 (UCHAR (255), UCHAR (255), VR_ANTI_RANGE);
   ASSERT_TRUE (not_255 == int_range<1> (UCHAR (0), UCHAR (254)));
diff --git a/gcc/value-range.cc b/gcc/value-range.cc
index 7847104050c..f45a342605a 100644
--- a/gcc/value-range.cc
+++ b/gcc/value-range.cc
@@ -1772,18 +1772,29 @@ irange::irange_intersect (const irange )
 verify_range ();
 }

+// Signed 1-bits are strange.  You can't subtract 1, because you can't
+// represent the number 1.  This works around that for the invert routine.
+
 static wide_int inline
 subtract_one (const wide_int , tree type, wi::overflow_type )
 {
-  // A signed 1-bit bit-field, has a range of [-1,0] so subtracting +1
-  // overflows, since +1 is unrepresentable.  This is why we have an
-  // addition of -1 here.
   if (TYPE_SIGN (type) == SIGNED)
-return wi::add (x, -1 , SIGNED, );
+return wi::add (x, -1, SIGNED, );
   else
 return wi::sub (x, 1, UNSIGNED, );
 }

+// The analogous function for adding 1.
+
+static wide_int inline
+add_one (const wide_int , tree type, wi::overflow_type )
+{
+  if (TYPE_SIGN (type) == SIGNED)
+return wi::sub (x, -1, SIGNED, );
+  else
+return wi::add (x, 1, TYPE_SIGN (type), );
+}
+
 /* Return the inverse of a range.  */

 void
@@ -1881,7 +1892,7 @@ irange::invert ()
   // set the overflow bit.
   if (type_max != wi::to_wide (orig_range.m_base[i]))
 {
-  tmp = wi::add (wi::to_wide (orig_range.m_base[i]), 1, sign, );
+  tmp = add_one (wi::to_wide (orig_range.m_base[i]), ttype, ovf);
   m_base[nitems++] = wide_int_to_tree (ttype, tmp);
   m_base[nitems++] = wide_int_to_tree (ttype, type_max);
   if (ovf)

[Bug tree-optimization/97555] [11 Regression] wrong code at -Os and above on x86_64-pc-linux-gnu since r11-3685

2020-10-26 Thread aldyh at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97555

Aldy Hernandez  changed:

   What|Removed |Added

   Assignee|unassigned at gcc dot gnu.org  |aldyh at gcc dot gnu.org

--- Comment #3 from Aldy Hernandez  ---
Mine.  Thanks for the analysis.

[Bug tree-optimization/97555] [11 Regression] wrong code at -Os and above on x86_64-pc-linux-gnu since r11-3685

2020-10-26 Thread amacleod at redhat dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97555

--- Comment #2 from Andrew Macleod  ---
   :
  f.0_1 = f;
  _2 = 1 % f.0_1;
  h_24 = (char) _2;
  _3 = _2;
  c = _3;
  _4 = b.a;
  _5 = (int) _4;
  _6 = ~_5;
  f = _6;
  if (_4 != -1)
goto ; [INV]
  else
goto ; [INV]

when calculating the outgoing_range_p() of edge 3->4,
we know that then range is  != -1. 

operator_not_equal::op1_range
calculates the range on the true side as:

 if (wi::eq_p (op2.lower_bound(), op2.upper_bound()))
{
  r = op2;
  r.invert ();
}
538   r = op2;
(gdb) p op2.dump(stderr)
 [-1, -1]$12 = void
(gdb) n
539   r.invert ();
(gdb) p r.dump(stderr)
 [-1, -1]$13 = void
(gdb) n
543   break;
(gdb) p r.dump(stderr)
UNDEFINED$14 = void

when we invert the range   [-1, -1]
we should get   [0, 0]
but instead its returning UNDEFINED.

which when the post dominated merge happens in bb5, we are unioning [-1,-1] and
undefined, producing [-1, -1] ofr the range of _4..
if we were unioning [-1, -1] and [0, 0] like we we are suppose to get, we'd get
VARYING, and the statement would not be incorrectly folded.


You can put a breakpoint in operator_not_equal::op1_range and it should be the
first time it is hit.

[Bug tree-optimization/97555] [11 Regression] wrong code at -Os and above on x86_64-pc-linux-gnu since r11-3685

2020-10-24 Thread jakub at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97555

Jakub Jelinek  changed:

   What|Removed |Added

   Last reconfirmed||2020-10-24
   Target Milestone|--- |11.0
 Ever confirmed|0   |1
Summary|wrong code at -Os and above |[11 Regression] wrong code
   |on x86_64-pc-linux-gnu  |at -Os and above on
   ||x86_64-pc-linux-gnu since
   ||r11-3685
 Status|UNCONFIRMED |NEW
 CC||aldyh at gcc dot gnu.org,
   ||amacleod at redhat dot com,
   ||jakub at gcc dot gnu.org
   Priority|P3  |P1

--- Comment #1 from Jakub Jelinek  ---
Started with r11-3685-gfcae5121154d1c3382b056bcc2c563cedac28e74