[Bug middle-end/81908] [8 Regression] FAIL: gfortran.dg/alloc_comp_auto_array_2.f90 -O3 -g -m32
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
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
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
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
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
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
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
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
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.