[Bug middle-end/81908] [8 Regression] FAIL: gfortran.dg/alloc_comp_auto_array_2.f90 -O3 -g -m32

2017-09-13 Thread aldyh at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81908

--- Comment #9 from Aldy Hernandez  ---
Author: aldyh
Date: Wed Sep 13 17:28:29 2017
New Revision: 252570

URL: https://gcc.gnu.org/viewcvs?rev=252570=gcc=rev
Log:
PR middle-end/81908 - FAIL: gfortran.dg/alloc_comp_auto_array_2.f90 -O3 -g -m32

gcc/ChangeLog:

PR middle-end/81908
* gimple-fold.c (size_must_be_zero_p): New function.
(gimple_fold_builtin_memory_op): Call it.

gcc/testsuite/ChangeLog:

PR middle-end/81908
* gcc.dg/tree-ssa/builtins-folding-gimple-2.c: New test.
* gcc.dg/tree-ssa/builtins-folding-gimple-3.c: New test.
* gcc.dg/tree-ssa/pr81908.c: New test.

Added:
   
branches/range-gen2/gcc/testsuite/gcc.dg/tree-ssa/builtins-folding-gimple-2.c
   
branches/range-gen2/gcc/testsuite/gcc.dg/tree-ssa/builtins-folding-gimple-3.c
branches/range-gen2/gcc/testsuite/gcc.dg/tree-ssa/pr81908.c
Modified:
branches/range-gen2/gcc/ChangeLog
branches/range-gen2/gcc/gimple-fold.c
branches/range-gen2/gcc/testsuite/ChangeLog

[Bug middle-end/81908] [8 Regression] FAIL: gfortran.dg/alloc_comp_auto_array_2.f90 -O3 -g -m32

2017-08-24 Thread msebor at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81908

Martin Sebor  changed:

   What|Removed |Added

 Status|ASSIGNED|RESOLVED
 Resolution|--- |FIXED

--- Comment #8 from Martin Sebor  ---
Patch committed in r251347.

[Bug middle-end/81908] [8 Regression] FAIL: gfortran.dg/alloc_comp_auto_array_2.f90 -O3 -g -m32

2017-08-24 Thread msebor at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81908

--- Comment #7 from Martin Sebor  ---
Author: msebor
Date: Fri Aug 25 00:25:57 2017
New Revision: 251347

URL: https://gcc.gnu.org/viewcvs?rev=251347=gcc=rev
Log:
PR middle-end/81908 - FAIL: gfortran.dg/alloc_comp_auto_array_2.f90 -O3 -g -m32

gcc/ChangeLog:

PR middle-end/81908
* gimple-fold.c (size_must_be_zero_p): New function.
(gimple_fold_builtin_memory_op): Call it.

gcc/testsuite/ChangeLog:

PR middle-end/81908
* gcc.dg/tree-ssa/builtins-folding-gimple-2.c: New test.
* gcc.dg/tree-ssa/builtins-folding-gimple-3.c: New test.
* gcc.dg/tree-ssa/pr81908.c: New test.


Added:
trunk/gcc/testsuite/gcc.dg/tree-ssa/builtins-folding-gimple-2.c
trunk/gcc/testsuite/gcc.dg/tree-ssa/builtins-folding-gimple-3.c
trunk/gcc/testsuite/gcc.dg/tree-ssa/pr81908.c
Modified:
trunk/gcc/ChangeLog
trunk/gcc/gimple-fold.c
trunk/gcc/testsuite/ChangeLog

[Bug middle-end/81908] [8 Regression] FAIL: gfortran.dg/alloc_comp_auto_array_2.f90 -O3 -g -m32

2017-08-24 Thread clyon at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81908

Christophe Lyon  changed:

   What|Removed |Added

 Target|i?86-*-*|i?86-*-*
   ||arm-none-linux-gnueabihf
 CC||clyon at gcc dot gnu.org

--- Comment #6 from Christophe Lyon  ---
Also seen on arm-none-linux-gnueabihf targets --with-cpu=cortex-a9
--with-fpu=neon-fp16

[Bug middle-end/81908] [8 Regression] FAIL: gfortran.dg/alloc_comp_auto_array_2.f90 -O3 -g -m32

2017-08-23 Thread msebor at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81908

Martin Sebor  changed:

   What|Removed |Added

   Keywords||patch
 Status|NEW |ASSIGNED
   Assignee|unassigned at gcc dot gnu.org  |msebor at gcc dot 
gnu.org

--- Comment #5 from Martin Sebor  ---
Patch: https://gcc.gnu.org/ml/gcc-patches/2017-08/msg01394.html

[Bug middle-end/81908] [8 Regression] FAIL: gfortran.dg/alloc_comp_auto_array_2.f90 -O3 -g -m32

2017-08-22 Thread msebor at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81908

--- Comment #4 from Martin Sebor  ---
Below is a small test case that attempts to illustrate the point from comment
#3 about the same logic as for -Walloc-size-larger-than perhaps not applying
quite as well to -Wstringop-overflow.

The odds are minuscule that the argument value is valid (only zero is), and
when it is, the memcpy call is dead, so the warning is helpful for code written
by a human: the call shouldn't be made to begin with.  But the warning is not
helpful to the user when the code is generated by GCC from valid source code.

$ cat a.c && gcc -O2 -S -Wall a.c
void f (char *d, const char *s, __SIZE_TYPE__ n)
{
  if (n > 0 && n <= __SIZE_MAX__ / 2)
n = 0;

  __builtin_memcpy (d, s, n);
}
a.c: In function ‘f’:
a.c:6:3: warning: ‘__builtin_memcpy’ specified size between 9223372036854775808
and 18446744073709551615 exceeds maximum object size 9223372036854775807
[-Wstringop-overflow=]
   __builtin_memcpy (d, s, n);
   ^~

[Bug middle-end/81908] [8 Regression] FAIL: gfortran.dg/alloc_comp_auto_array_2.f90 -O3 -g -m32

2017-08-21 Thread msebor at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81908

--- Comment #3 from Martin Sebor  ---
(In reply to Richard Biener from comment #1)

The code was originally designed for -Walloc-size-larger-than and does the
right thing for that warning.  The range I see is

  _248: ~[1, 2147483647]
  __builtin_memcpy (_251, _259, _248);

leaving 0 as the only valid value less than SIZE_MAX / 2 in ILP32.  Zero is not
really a valid allocation size so the code excludes it.

But the code is also used for -Wstringop-overflow and the same logic doesn't
apply equally well there.  The warning does suggest that the memcpy could be
eliminated, so as in most instances of it, the true root cause is really a
missed optimization opportunity.   In fact, this whole block must be
unreachable because if it were executed it would either attempt to allocate
more than SIZE_MAX / 2 bytes (which would fail) or allocate and write past the
end of the 1-byte block:

   [0.43%] [count: INV]:
  vect_cst__246 = { -1, 265, 1, 1 };
  _247 = ubound.2_35 * 4;
  _248 = (character(kind=4)) _247; // _248
is ~[1, 2147483647]
  _249 = MAX_EXPR <_248, 1>;   // _249
must be 1
  _251 = __builtin_malloc (_249);  // _251
= malloc(1)
  __builtin_memcpy (_251, _259, _248); // no-op
  MEM[(struct grid_index_region *)] = _251;
  MEM[(struct grid_index_region *) + 4B] = { -1, 265, 1, 1 };   //
invalid/write-past-end
  MEM[(struct grid_index_region *) + 20B] = ubound.2_35;//
invalid/write-past-end


(In reply to Richard Biener from comment #1)

get_size_range() sets the RANGE[] array to the unsigned bounds of the range of
sizes.  It can't set RANGE[0] > RANGE[1].  For example, the following must not
be diagnosed but is with the suggested cleanup in comment #2.  There may be a
way to clean up the code but the suggested patch is not sufficient (it causes
test suite regressions).

void __attribute__ ((alloc_size (1))) f (unsigned long);

void g (int n)
{
  if (n < -9 || 9 < n)
n = -9;

  f (n);
}

[Bug middle-end/81908] [8 Regression] FAIL: gfortran.dg/alloc_comp_auto_array_2.f90 -O3 -g -m32

2017-08-21 Thread rguenth at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81908

--- Comment #2 from Richard Biener  ---
Btw, the anti-ranges can be made "signed" by

  /* If we have an unsigned anti-range convert it to the respective
 signed type.  */
  if (range_type == VR_ANTI_RANGE
  && TYPE_UNSIGNED (exptype)
  && wi::les_p (max, min))
{
  std::swap (max, min);
  min = min + 1;
  max = max - 1;
  range_type = VR_RANGE;
}

simplifying the anti-range handling to just the signed case.  Then you
run into the same issue in the signed anti-range handling.

  else if (wi::les_p (min - 1, wzero))
{
  /* EXP is not in a negative-positive range.  That means EXP
 is either negative, or greater than max.  Since negative
 sizes are invalid make the range [MAX + 1, TYPE_MAX].  */
  min = max + 1;
  max = wmaxval;
}

this has to use wi::lts_p (or les_p (min, 0).

Suggested cleanup (untested):

Index: gcc/calls.c
===
--- gcc/calls.c (revision 251217)
+++ gcc/calls.c (working copy)
@@ -1279,8 +1279,9 @@ get_size_range (tree exp, tree range[2])
 }

   wide_int min, max;
+  tree exptype = TREE_TYPE (exp);
   enum value_range_type range_type
-= ((TREE_CODE (exp) == SSA_NAME && INTEGRAL_TYPE_P (TREE_TYPE (exp)))
+= ((TREE_CODE (exp) == SSA_NAME && INTEGRAL_TYPE_P (exptype))
? get_range_info (exp, , ) : VR_VARYING);

   if (range_type == VR_VARYING)
@@ -1291,49 +1292,40 @@ get_size_range (tree exp, tree range[2])
   return false;
 }

-  tree exptype = TREE_TYPE (exp);
-  unsigned expprec = TYPE_PRECISION (exptype);
-  wide_int wzero = wi::zero (expprec);
-  wide_int wmaxval = wide_int (TYPE_MAX_VALUE (exptype));
-
-  bool signed_p = !TYPE_UNSIGNED (exptype);
+  /* If we have an unsigned anti-range convert it to the respective
+ signed type.  */
+  if (range_type == VR_ANTI_RANGE
+  && TYPE_UNSIGNED (exptype)
+  && wi::les_p (max, min))
+{
+  std::swap (max, min);
+  min = min + 1;
+  max = max - 1;
+  range_type = VR_RANGE;
+}

   if (range_type == VR_ANTI_RANGE)
 {
-  if (signed_p)
+  unsigned expprec = TYPE_PRECISION (exptype);
+  wide_int wzero = wi::zero (expprec);
+  wide_int wmaxval = wi::max_value (expprec, TYPE_SIGN (exptype));
+
+  if (wi::lts_p (max, wzero))
{
- if (wi::les_p (max, wzero))
-   {
- /* EXP is not in a strictly negative range.  That means
-it must be in some (not necessarily strictly) positive
-range which includes zero.  Since in signed to unsigned
-conversions negative values end up converted to large
-positive values, and otherwise they are not valid sizes,
-the resulting range is in both cases [0, TYPE_MAX].  */
- min = wzero;
- max = wmaxval;
-   }
- else if (wi::les_p (min - 1, wzero))
-   {
- /* EXP is not in a negative-positive range.  That means EXP
-is either negative, or greater than max.  Since negative
-sizes are invalid make the range [MAX + 1, TYPE_MAX].  */
- min = max + 1;
- max = wmaxval;
-   }
- else
-   {
- max = min - 1;
- min = wzero;
-   }
+ /* EXP is not in a strictly negative range.  That means
+it must be in some (not necessarily strictly) positive
+range which includes zero.  Since in signed to unsigned
+conversions negative values end up converted to large
+positive values, and otherwise they are not valid sizes,
+the resulting range is in both cases [0, TYPE_MAX].  */
+ min = wzero;
+ max = wmaxval;
}
-  else if (wi::eq_p (wzero, min - 1))
+  else if (wi::les_p (min, wzero))
{
- /* EXP is unsigned and not in the range [1, MAX].  That means
-it's either zero or greater than MAX.  Even though 0 would
-normally be detected by -Walloc-zero set the range to
-[MAX, TYPE_MAX] so that when MAX is greater than the limit
-the whole range is diagnosed.  */
+ /* EXP is not in a negative-positive range.  That means EXP
+is either negative, or greater than max.  Since negative
+sizes are invalid make the range [MAX + 1, TYPE_MAX].  */
  min = max + 1;
  max = wmaxval;
}

[Bug middle-end/81908] [8 Regression] FAIL: gfortran.dg/alloc_comp_auto_array_2.f90 -O3 -g -m32

2017-08-21 Thread rguenth at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81908

Richard Biener  changed:

   What|Removed |Added

 Status|UNCONFIRMED |NEW
   Last reconfirmed||2017-08-21
 CC||msebor at gcc dot gnu.org
   Target Milestone|--- |8.0
 Ever confirmed|0   |1

--- Comment #1 from Richard Biener  ---
Probably caused by

  [/tmp/trunk/gcc/testsuite/gfortran.dg/alloc_comp_auto_array_2.f90:33:0] #
RANGE [-2147483648, 0] NONZERO 4294967292
  _260 = ubound.2_35 * 4;
  [/tmp/trunk/gcc/testsuite/gfortran.dg/alloc_comp_auto_array_2.f90:33:0] #
RANGE ~[1, 2147483647] NONZERO 4294967292
  _261 = (character(kind=4)) _260;
...
  __builtin_memcpy (_264, _272, _261);

where the warning machinery simply doesn't consider the valid input _261 == 0.

get_size_range runs into

  else if (wi::eq_p (wzero, min - 1))
{
  /* EXP is unsigned and not in the range [1, MAX].  That means
 it's either zero or greater than MAX.  Even though 0 would
 normally be detected by -Walloc-zero set the range to
 [MAX, TYPE_MAX] so that when MAX is greater than the limit
 the whole range is diagnosed.  */
  min = max + 1;
  max = wmaxval;

I totally detest this anti-range handling.  It's completely bogus.  For
whatever reason it _does_ want to diagnose here.

So - INVALID, working as designed?!

The comment is wrong btw,  EXP is in the range 0 U [max + 1, wmaxval].
'MAX' is used inconsistently -- nothing is bigger than 'MAX' unless
'MAX' is maximum value that is positive when interpreted signed.  But
wmaxval is unsigned.

Suggested patch:

Index: gcc/calls.c
===
--- gcc/calls.c (revision 251217)
+++ gcc/calls.c (working copy)
@@ -1327,7 +1327,8 @@ get_size_range (tree exp, tree range[2])
  min = wzero;
}
}
-  else if (wi::eq_p (wzero, min - 1))
+  else if (wi::eq_p (wzero, min - 1)
+  && wi::lts_p (max, wi::max_value (expprec, SIGNED)))
{
  /* EXP is unsigned and not in the range [1, MAX].  That means
 it's either zero or greater than MAX.  Even though 0 would

that (for this sub-case of anit-range handling) tries to preserve
anti-range ^ valid-size-range if not empty.  I think that's a must
to get false positives to a minimum.