With a gcc build from commit 637dfcf43cf, I run into an incorrect Warray-bounds (which causes a buildbreaker when building gdb, as reported here: https://sourceware.org/pipermail/gdb/2021-September/049687.html ). Reproducer minimized from gdb/language.c: ... $ cat language.c #include <algorithm> static inline bool compare_cstrings (const char *str1, const char *str2) { return str1 < str2; } void add_set_language_command () { static const char **language_names; language_names = new const char *[6]; language_names[0] = "auto"; language_names[1] = "local"; language_names[2] = "unknown"; const char **language_names_p = language_names; /* language_names_p == &language_names[0]. */ language_names_p++; /* language_names_p == &language_names[1]. */ language_names_p++; /* language_names_p == &language_names[2]. */ language_names_p++; /* language_names_p == &language_names[3]. */ const char **sort_begin; if (0) sort_begin = &language_names[3]; else sort_begin = language_names_p; language_names[3] = ""; language_names[4] = ""; language_names[5] = nullptr; std::sort (sort_begin, &language_names[5], compare_cstrings); } ... First with gcc-11: ... $ g++-11 -x c++ -Werror -Wall -O2 -S language.c -Warray-bounds=1 $ ... Now with trunk: ... $ g++ -x c++ -Werror -Wall -O2 -S language.c -Warray-bounds=1 In file included from /home/vries/gcc_versions/devel/install/include/c++/12.0.0/algorithm:61, from language.c:1: In function ‘void std::__final_insertion_sort(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = const char**; _Compare = __gnu_cxx::__ops::_Iter_comp_iter<bool (*)(const char*, const char*)>]’, inlined from ‘void std::__sort(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = const char**; _Compare = __gnu_cxx::__ops::_Iter_comp_iter<bool (*)(const char*, const char*)>]’ at /home/vries/gcc_versions/devel/install/include/c++/12.0.0/bits/stl_algo.h:1960:31, inlined from ‘void std::sort(_RAIter, _RAIter, _Compare) [with _RAIter = const char**; _Compare = bool (*)(const char*, const char*)]’ at /home/vries/gcc_versions/devel/install/include/c++/12.0.0/bits/stl_algo.h:4868:18, inlined from ‘void add_set_language_command()’ at language.c:40:13: /home/vries/gcc_versions/devel/install/include/c++/12.0.0/bits/stl_algo.h:1869:32: error: array subscript 19 is outside array bounds of ‘void [48]’ [-Werror=array-bounds] 1869 | std::__insertion_sort(__first, __first + int(_S_threshold), __comp); | ~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ language.c: In function ‘void add_set_language_command()’: language.c:14:38: note: at offset 152 into object of size 48 allocated by ‘operator new []’ 14 | language_names = new const char *[6]; | ^ cc1plus: all warnings being treated as errors ... Now set 'if (0)' to 'if (1)': ... $ g++ -x c++ -Werror -Wall -O2 -S language.c -Warray-bounds=1 $ ... So either the warning is incorrect (for this fairly trivial example), or there's a compiler/std::sort bug and the warning is letting us known.
The problem is dead code: language_names_p_9 = &MEM <const char *> [(void *)_4 + 24B]; MEM[(const char * *)_4 + 24B] = ""; MEM[(const char * *)_4 + 32B] = ""; MEM[(const char * *)_4 + 40B] = 0B; _2 = _4 + 40; D.50907._M_comp = compare_cstrings; __comp = D.50907; if (_2 != language_names_p_9) goto <bb 3>; [53.47%] else goto <bb 12>; [46.53%] <bb 3> [local count: 574129759]: _15 = _2 - language_names_p_9; _16 = _15 /[ex] 8; ... _22 = _2 - language_names_p_9; if (_22 > 128) goto <bb 4>; [50.00%] else goto <bb 10>; [50.00%] <bb 4> [local count: 287064879]: _23 = &MEM <const char *> [(void *)_4 + 152B]; std::__insertion_sort<const char**, __gnu_cxx::__ops::_Iter_comp_iter<bool (*)(const char*, const char*)> > (language_names_p_9, _23, __comp); __comp_24 = MEM[(struct _Iter_comp_iter *)&__comp]; goto <bb 9>; [100.00%] That is _22 (and _15) should be 16. I just fixed a similar issue today (but the patch did not fix this case). I will look into fixing this one tomorrow.
(In reply to Andrew Pinski from comment #1) > The problem is dead code: > language_names_p_9 = &MEM <const char *> [(void *)_4 + 24B]; > MEM[(const char * *)_4 + 24B] = ""; > MEM[(const char * *)_4 + 32B] = ""; > MEM[(const char * *)_4 + 40B] = 0B; > _2 = _4 + 40; > D.50907._M_comp = compare_cstrings; > __comp = D.50907; > if (_2 != language_names_p_9) > goto <bb 3>; [53.47%] > else > goto <bb 12>; [46.53%] > > <bb 3> [local count: 574129759]: > _15 = _2 - language_names_p_9; > _16 = _15 /[ex] 8; > > ... > _22 = _2 - language_names_p_9; I have a (hack) patch which removes the first if statement but still does not fold _15 and _22.
Here is a short testcase: int add_set_language_command () { const char **language_names; language_names = new const char *[6]; const char **language_names_p = language_names; language_names_p++; language_names_p++; language_names_p++; return (language_names_p) - (language_names+3); } This should just return 0; Which was able to be done in GCC 4.4.7.
So how 4.4.x got the right answer at the tree level was just by accident really. VRP used SCEV which basically does a combine. Forwprop never happened of PointerPlus until 4.6. 4.5 removed the SCEV usage in VRP and removed the optimization ...
I think I have a patch which disables the proping in forwprop that creates the &MEM stuff (it is done still by forwprop just not in this location and via match instead). The waring is now gone and the code looks better too.
Created attachment 51420 [details] Patch which I am testing.
(In reply to Andrew Pinski from comment #6) > Created attachment 51420 [details] > Patch which I am testing. Note I am throwing this patch away and started to rewrite parts of tree-ssa-forwprop.c instead.
Created attachment 51424 [details] New patch THis is the new patch which I am testing. It fixes the original issue in forwprop but does not fix the FIXME of creating extra trees.
Patch submitted: https://gcc.gnu.org/pipermail/gcc-patches/2021-October/582684.html Now that PR 102238 is fixed.
Created attachment 51850 [details] Updated patch Updated patch based on the feedback, still need to add back the testcase though.
(In reply to Andrew Pinski from comment #10) > Created attachment 51850 [details] > Updated patch Note this patch is broken but I have the corrected patch which I am testing now.
New patch submitted: https://gcc.gnu.org/pipermail/gcc-patches/2021-November/585194.html
*** Bug 103377 has been marked as a duplicate of this bug. ***
The trunk branch has been updated by Andrew Pinski <pinskia@gcc.gnu.org>: https://gcc.gnu.org/g:911b633803dcbb298c98777e29fd260834c0d04a commit r12-5465-g911b633803dcbb298c98777e29fd260834c0d04a Author: Andrew Pinski <apinski@marvell.com> Date: Tue Nov 23 01:08:55 2021 +0000 Canonicalize &MEM[ssa_n, CST] to ssa_n p+ CST in fold_stmt_1 This is a new version of the patch to fix PR 102216. Instead of doing the canonicalization inside forwprop, Richi mentioned we should do it inside fold_stmt_1 and that is what this patch does. PR tree-optimization/102216 gcc/ChangeLog: * gimple-fold.c (fold_stmt_1): Add canonicalization of "&MEM[ssa_n, CST]" to "ssa_n p+ CST", note this can only be done if !in_place. gcc/testsuite/ChangeLog: * g++.dg/tree-ssa/pr102216-1.C: New test. * g++.dg/tree-ssa/pr102216-2.C: New test.
Fixed.