More fallout from enabling auto-vectorization at -O2. gcc.dg/Warray-bonds-48.c is regressing on most (but not all) of the embedded targets. Just picking one semi-randomly, iq2000-elf: Running target iq2000-sim Using /usr/share/dejagnu/baseboards/iq2000-sim.exp as board description file for target. Using /usr/share/dejagnu/config/sim.exp as generic interface file for target. Using /usr/share/dejagnu/baseboards/basic-sim.exp as board description file for target. Using /home/jlaw/jenkins/workspace/iq2000-elf/gcc/gcc/testsuite/config/default.exp as tool-and-target-specific interface file. Running /home/jlaw/jenkins/workspace/iq2000-elf/gcc/gcc/testsuite/gcc.dg/dg.exp ... FAIL: gcc.dg/Warray-bounds-48.c (test for excess errors) === gcc Summary === # of expected passes 38 # of unexpected failures 1 /home/jlaw/jenkins/workspace/iq2000-elf/iq2000-elf-obj/gcc/gcc/xgcc version 12.0.0 20211008 (experimental) (GCC) From the log file we see: FAIL: gcc.dg/Warray-bounds-48.c (test for excess errors) Excess errors: /home/jlaw/jenkins/workspace/iq2000-elf/gcc/gcc/testsuite/gcc.dg/Warray-bounds-48.c:33:12: warning: writing 4 bytes into a region of size 0 [-Wstringop-overflow=] /home/jlaw/jenkins/workspace/iq2000-elf/gcc/gcc/testsuite/gcc.dg/Warray-bounds-48.c:133:12: warning: writing 4 bytes into a region of size 0 [-Wstringop-overflow=] My very cursory examination of the test tells me this is a bogus warning. In both cases we have allocated enough space to reference array index 0 and 1. You should be able to reproduce this with a cross compiler without needing a cross assembler, library, etc.
Confirmed. The root cause is similar as in the test case in pr102462 comment 4. Here, in addition to the expected -Warray-bounds (from the vrp1 pass) for the invalid subscripts (before vectorization) the code also triggers -Wstringop-overflow (from the strlen pass) for the two valid stores to p->ax at indices 0 and 1 vectorized with the subsequent two stores. See the dumps below. Hongtao and I have been discussing the fallout of the autovectorization change in the context of the following review: https://gcc.gnu.org/pipermail/gcc-patches/2021-October/581371.html Hongtao, we could use this bug to track case (2) that you described in your reply this morning in the thread above. $ cat pr102706.c && /build/iq2000-elf/gcc-master/gcc/xgcc -B /build/iq200f/gcc-master/gcc -O2 -S -Wall -fdump-tree-vrp1=/dev/stdout -fdump-tree-strlen=/dev/stdout pr102706.c typedef __INT16_TYPE__ int16_t; typedef __INT32_TYPE__ int32_t; void sink (void*); /* Exercise a true flexible member. */ struct AX { int32_t n; int16_t ax[]; // { dg-message "while referencing 'ax'" "member" } }; static void warn_ax_local_buf (struct AX *p) { p->ax[0] = 4; p->ax[1] = 5; p->ax[2] = 6; // { dg-warning "\\\[-Warray-bounds" } p->ax[3] = 7; // { dg-warning "\\\[-Warray-bounds" } p->ax[4] = 8; // { dg-warning "\\\[-Warray-bounds" } } void g (void) { /* Verify out-of-bounds access to the local BUF is diagnosed. */ char ax_buf_p2[sizeof (struct AX) + 2 * sizeof (int16_t)]; warn_ax_local_buf ((struct AX*) ax_buf_p2); sink (ax_buf_p2); } ;; Function g (g, funcdef_no=1, decl_uid=1438, cgraph_uid=2, symbol_order=1) ;; 1 loops found ;; ;; Loop 0 ;; header 0, latch 1 ;; depth 0, outer -1 ;; nodes: 0 1 2 ;; 2 succs { 1 } Value ranges after VRP: In function 'warn_ax_local_buf', inlined from 'g' at pr102706.c:28:3: pr102706.c:18:8: warning: array subscript 2 is above array bounds of 'int16_t[]' {aka 'short int[]'} [-Warray-bounds] 18 | p->ax[2] = 6; // { dg-warning "\\\[-Warray-bounds" } | ~~~~~^~~ pr102706.c: In function 'g': pr102706.c:11:11: note: while referencing 'ax' 11 | int16_t ax[]; // { dg-message "while referencing 'ax'" "member" } | ^~ In function 'warn_ax_local_buf', inlined from 'g' at pr102706.c:28:3: pr102706.c:19:8: warning: array subscript 3 is above array bounds of 'int16_t[]' {aka 'short int[]'} [-Warray-bounds] 19 | p->ax[3] = 7; // { dg-warning "\\\[-Warray-bounds" } | ~~~~~^~~ pr102706.c: In function 'g': pr102706.c:11:11: note: while referencing 'ax' 11 | int16_t ax[]; // { dg-message "while referencing 'ax'" "member" } | ^~ In function 'warn_ax_local_buf', inlined from 'g' at pr102706.c:28:3: pr102706.c:20:8: warning: array subscript 4 is above array bounds of 'int16_t[]' {aka 'short int[]'} [-Warray-bounds] 20 | p->ax[4] = 8; // { dg-warning "\\\[-Warray-bounds" } | ~~~~~^~~ pr102706.c: In function 'g': pr102706.c:11:11: note: while referencing 'ax' 11 | int16_t ax[]; // { dg-message "while referencing 'ax'" "member" } | ^~ void g () { char ax_buf_p2[8]; <bb 2> [local count: 1073741824]: MEM[(struct AX *)&ax_buf_p2].ax[0] = 4; MEM[(struct AX *)&ax_buf_p2].ax[1] = 5; MEM[(struct AX *)&ax_buf_p2].ax[2] = 6; MEM[(struct AX *)&ax_buf_p2].ax[3] = 7; MEM[(struct AX *)&ax_buf_p2].ax[4] = 8; sink (&ax_buf_p2); ax_buf_p2 ={v} {CLOBBER}; return; } ;; Function g (g, funcdef_no=1, decl_uid=1438, cgraph_uid=2, symbol_order=1) ;; 1 loops found ;; ;; Loop 0 ;; header 0, latch 1 ;; depth 0, outer -1 ;; nodes: 0 1 2 ;; 2 succs { 1 } In function 'warn_ax_local_buf', inlined from 'g' at pr102706.c:28:3: pr102706.c:16:12: warning: writing 4 bytes into a region of size 0 [-Wstringop-overflow=] 16 | p->ax[0] = 4; p->ax[1] = 5; | ~~~~~~~~~^~~ pr102706.c: In function 'g': pr102706.c:27:8: note: at offset 8 into destination object 'ax_buf_p2' of size 8 27 | char ax_buf_p2[sizeof (struct AX) + 2 * sizeof (int16_t)]; | ^~~~~~~~~ void g () { int16_t * vectp.5; vector(2) short int * vectp_ax_buf_p2.4; char ax_buf_p2[8]; <bb 2> [local count: 1073741824]: MEM <vector(2) short int> [(short int *)&ax_buf_p2 + 4B] = { 4, 5 }; MEM <vector(2) short int> [(short int *)&ax_buf_p2 + 8B] = { 6, 7 }; MEM[(struct AX *)&ax_buf_p2].ax[4] = 8; sink (&ax_buf_p2); ax_buf_p2 ={v} {CLOBBER}; return; }
case (2): Part of accesses are inbound, part of accesses are out of bound, and after vectorization, the warning goes from out of bound line to inbound line. From Wstringop-overflow-2.c: struct A1 a1_1 = { 0, { 1 } }; void ga1_1 (void) { a1_1.a[0] = 0; a1_1.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" } a1_1.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" } struct A1 a = { 0, { 1 } }; // { dg-warning "\\\[-Wstringop-overflow" "" { target { i?86-*-* x86_64-*-* } } } a.a[0] = 0; a.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { i?86-*-* x86_64-*-* } } } a.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { i?86-*-* x86_64-*-* } } } sink (&a); } struct A1 a1i_1 = { 0, { 1 } }; void ga1i_1 (void) { a1i_1.a[0] = 0; a1i_1.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" } a1i_1.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" } // Refer to PR102462 struct A1 a = { 0, { 1 } }; // { dg-warning "\\\[-Wstringop-overflow" "" { target { i?86-*-* x86_64-*-* } } } a.a[0] = 1; a.a[1] = 2; // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { i?86-*-* x86_64-*-* } } } a.a[2] = 3; // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { i?86-*-* x86_64-*-* } } } sink (&a); }
From gcc.dg/Warray-bounds-51.c void test_struct_char_vla_location (void) { unsigned nelts = 7; struct { char cvla[nelts]; // { dg-message "declared here|while referencing" } } s; s.cvla[0] = __LINE__; s.cvla[nelts - 1] = 0; // { dg-warning "\\\[-Wstringop-overflow" "" { target { i?86-*-* x86_64-*-* } } } s.cvla[nelts] = 0; // { dg-warning "\\\[-Warray-bounds" } sink (&s); } From gcc.dg/Warray-parameter-3.c __attribute__ ((noipa)) void gcas3 (char a[static 3]) { a[0] = 0; a[1] = 1; a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" "" { target { i?86-*-* x86_64-*-* } } } a[3] = 3; // { dg-warning "\\\[-Warray-bounds" } } From gcc.dg/Wstringop-overflow-14.c void test_int16 (void) { char *p = a4 + 1; *(int16_t*)p = 0; // { dg-warning "writing 4 bytes into a region of size 3" "" { target { i?86-*-* x86_64-*-* } } } *(int16_t*)(p + 2) = 0; // { dg-warning "writing 2 bytes into a region of size 1" "" { xfail { i?86-*-* x86_64-*-* } } } } From gcc.dg/Wstringop-overflow-21.c void test_store_zero_length (int i) { char a[3]; struct S0 *p = (struct S0*)a; p->a = 0; // { dg-warning "\\\[-Wstringop-overflow" "" { target { i?86-*-* x86_64-*-* } } } p->b[0] = 0; p->b[1] = 1; // { dg-bogus "\\\[-Wstringop-overflow" } p->b[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { i?86-*-* x86_64-*-* } } } p->b[i] = 2; sink (p); } void test_store_flexarray (int i) { char a[3]; struct Sx *p = (struct Sx*)a; p->a = 0; // { dg-warning "\\\[-Wstringop-overflow" "" { target { i?86-*-* x86_64-*-* } } } p->b[0] = 0; p->b[1] = 1; // { dg-bogus "\\\[-Wstringop-overflow" } p->b[2] = 1; // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { i?86-*-* x86_64-*-* } } } p->b[i] = 2; sink (p); } From gcc.dg/Wstringop-overflow-76.c: extern char a3[3]; extern char a5[5]; // { dg-message "at offset \[^a-zA-Z\n\r\]*5\[^a-zA-Z0-9\]* into destination object 'a5' of size 5" "note" } void max_a3_a5 (int i) { char *p = a3 + i; char *q = a5 + i; /* The relational expression below is invalid and should be diagnosed by its own warning independently of -Wstringop-overflow. */ char *d = MAX (p, q); d[2] = 0; // { dg-warning "writing 4 bytes into a region of size 3" "" { target { i?86-*-* x86_64-*-* } } } d[3] = 0; d[4] = 0; d[5] = 0; // { dg-warning "writing 1 byte into a region of size 0" "" { xfail { i?86-*-* x86_64-*-* } } } } // Same as above but with the larger array as the first MAX_EXPR operand. extern char b4[4]; extern char b6[6]; // { dg-message "at offset \[^a-zA-Z\n\r\]*6\[^a-zA-Z0-9\]* into destination object 'b6' of size 6" "note" } void max_b6_b4 (int i) { char *p = b6 + i; char *q = b4 + i; char *d = MAX (p, q); d[3] = 0; // { dg-warning "writing 4 bytes into a region of size 3" "" { target { i?86-*-* x86_64-*-* } } } d[4] = 0; d[5] = 0; d[6] = 0; // { dg-warning "writing 1 byte into a region of size 0" "" { xfail { i?86-*-* x86_64-*-* } } } }
The master branch has been updated by hongtao Liu <liuhongt@gcc.gnu.org>: https://gcc.gnu.org/g:3c8d8c0be95e99dc0cba7f6fad2429243582119f commit r12-4523-g3c8d8c0be95e99dc0cba7f6fad2429243582119f Author: liuhongt <hongtao.liu@intel.com> Date: Thu Oct 14 09:31:03 2021 +0800 Adjust testcase for O2 vectorization. As discussed in [1], this patch add xfail/target selector to those testcases, also make a copy of them so that they can be tested w/o vectorization. Newly added xfail/target selectors are used to check the vectorization capability of continuous byte/double bytes storage, these scenarios are exactly the part of the testcases that regressed after O2 vectorization. [1] https://gcc.gnu.org/pipermail/gcc-patches/2021-October/581456.html. 2021-10-19 Hongtao Liu <hongtao.liu@intel.com> Kewen Lin <linkw@linux.ibm.com> gcc/ChangeLog * doc/sourcebuild.texi (Effective-Target Keywords): Document vect_slp_v2qi_store, vect_slp_v4qi_store, vect_slp_v8qi_store, vect_slp_v16qi_store, vect_slp_v2hi_store, vect_slp_v4hi_store, vect_slp_v2si_store, vect_slp_v4si_store. gcc/testsuite/ChangeLog PR middle-end/102722 PR middle-end/102697 PR middle-end/102462 PR middle-end/102706 PR middle-end/102744 * c-c++-common/Wstringop-overflow-2.c: Adjust testcase with new xfail/target selector. * gcc.dg/Warray-bounds-51.c: Ditto. * gcc.dg/Warray-parameter-3.c: Ditto. * gcc.dg/Wstringop-overflow-14.c: Ditto. * gcc.dg/Wstringop-overflow-21.c: Ditto. * gcc.dg/Wstringop-overflow-68.c: Ditto. * gcc.dg/Wstringop-overflow-76.c: Ditto. * gcc.dg/Warray-bounds-48.c: Ditto. * gcc.dg/Wzero-length-array-bounds-2.c: Ditto. * lib/target-supports.exp (check_vect_slp_aligned_store_usage): New function. (check_effective_target_vect_slp_v2qi_store): Ditto. (check_effective_target_vect_slp_v4qi_store): Ditto. (check_effective_target_vect_slp_v8qi_store): Ditto. (check_effective_target_vect_slp_v16qi_store): Ditto. (check_effective_target_vect_slp_v2hi_store): Ditto. (check_effective_target_vect_slp_v4hi_store): Ditto. (check_effective_target_vect_slp_v2si_store): Ditto. (check_effective_target_vect_slp_v4si_store): Ditto. * c-c++-common/Wstringop-overflow-2-novec.c: New test. * gcc.dg/Warray-bounds-51-novec.c: New test. * gcc.dg/Warray-bounds-48-novec.c: New test. * gcc.dg/Warray-parameter-3-novec.c: New test. * gcc.dg/Wstringop-overflow-14-novec.c: New test. * gcc.dg/Wstringop-overflow-21-novec.c: New test. * gcc.dg/Wstringop-overflow-76-novec.c: New test. * gcc.dg/Wzero-length-array-bounds-2-novec.c: New test.
The testsuite fails have been resolved.
The master branch has been updated by Alexandre Oliva <aoliva@gcc.gnu.org>: https://gcc.gnu.org/g:4505270128ef70538ea345f292e3eb85a5369eaf commit r13-4554-g4505270128ef70538ea345f292e3eb85a5369eaf Author: Alexandre Oliva <oliva@adacore.com> Date: Thu Dec 8 07:50:33 2022 -0300 [PR102706] [testsuite] -Wno-stringop-overflow vs Warray-bounds The bogus Wstringop-overflow warnings conditionally issued for Warray-bounds-48.c and -Wzero-length-array-bounds-2.c are expected under conditions that depend on the availability of certain vector patterns, but that don't seem to model the conditions under which the warnings are expected. On riscv64-elf and arm-eabi/-mcpu=cortex-r5, for example, though the Warray-bounds-48.c condition passes, we don't issue warnings. On riscv64-elf, we decide not to vectorize the assignments; on cortex-r5, we do vectorize pairs of assignments, but that doesn't yield the expected warning, even though assignments that should trigger the bogus warning are vectorized and associated with the earlier line where the bogus warning would be expected. On riscv64, for Wzero-length-array-bounds-2.c, we issue the expected warning in test_C_global_buf, but we also issue a warning for test_C_local_buf under the same conditions, that would be expected on other platforms but that is not issued on them. On arm-eabi/-mcpu=cortex-r5, the condition passes so we'd expect the warning in both functions, but we don't warn on either. Instead of further extending the effective target tests, introduced to temporarily tolerate these expected bogus warnings, so as to capture the vectorizer analyses that lead to the mismatched decisions, I'm disabling the undesired warnings for these two tests. for gcc/testsuite/ChangeLog PR tree-optimization/102706 * gcc.dg/Warray-bounds-48.c: Disable -Wstringop-overflow. * gcc.dg/Wzero-length-array-bounds-2.c: Likewise.