Adjust testcase for O2 vectorization.

Message ID 20211014071141.71871-1-hongtao.liu@intel.com
State New
Headers
Series Adjust testcase for O2 vectorization. |

Commit Message

Liu, Hongtao Oct. 14, 2021, 7:11 a.m. UTC
  Hi Kewen:
  Cound you help to verify if this patch fix those regressions
for rs6000 port.

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.

gcc/testsuite/ChangeLog

	PR middle-end/102722
	PR middle-end/102697
	PR middle-end/102462
	PR middle-end/102706
	* 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.
	* lib/target-supports.exp (check_vect_slp_vnqihi_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.
	* 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.
---
 .../c-c++-common/Wstringop-overflow-2-novec.c | 348 +++++++++++++++++
 .../c-c++-common/Wstringop-overflow-2.c       |  26 +-
 gcc/testsuite/gcc.dg/Warray-bounds-48-novec.c | 364 ++++++++++++++++++
 gcc/testsuite/gcc.dg/Warray-bounds-48.c       |   6 +-
 gcc/testsuite/gcc.dg/Warray-bounds-51-novec.c |  61 +++
 gcc/testsuite/gcc.dg/Warray-bounds-51.c       |   3 +-
 .../gcc.dg/Warray-parameter-3-novec.c         |  89 +++++
 gcc/testsuite/gcc.dg/Warray-parameter-3.c     |   3 +-
 .../gcc.dg/Wstringop-overflow-14-novec.c      |  56 +++
 gcc/testsuite/gcc.dg/Wstringop-overflow-14.c  |   5 +-
 .../gcc.dg/Wstringop-overflow-21-novec.c      |  59 +++
 gcc/testsuite/gcc.dg/Wstringop-overflow-21.c  |  10 +-
 gcc/testsuite/gcc.dg/Wstringop-overflow-68.c  |  17 +-
 .../gcc.dg/Wstringop-overflow-76-novec.c      | 147 +++++++
 gcc/testsuite/gcc.dg/Wstringop-overflow-76.c  |  26 +-
 gcc/testsuite/lib/target-supports.exp         | 129 +++++++
 16 files changed, 1314 insertions(+), 35 deletions(-)
 create mode 100644 gcc/testsuite/c-c++-common/Wstringop-overflow-2-novec.c
 create mode 100644 gcc/testsuite/gcc.dg/Warray-bounds-48-novec.c
 create mode 100644 gcc/testsuite/gcc.dg/Warray-bounds-51-novec.c
 create mode 100644 gcc/testsuite/gcc.dg/Warray-parameter-3-novec.c
 create mode 100644 gcc/testsuite/gcc.dg/Wstringop-overflow-14-novec.c
 create mode 100644 gcc/testsuite/gcc.dg/Wstringop-overflow-21-novec.c
 create mode 100644 gcc/testsuite/gcc.dg/Wstringop-overflow-76-novec.c
  

Comments

Bernhard Reutner-Fischer Oct. 14, 2021, 7:52 a.m. UTC | #1
On Thu, 14 Oct 2021 15:11:41 +0800
liuhongt via Gcc-patches <gcc-patches@gcc.gnu.org> wrote:

> 	* lib/target-supports.exp (check_vect_slp_vnqihi_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.

ISTM the doc bits are missing from doc/sourcebuild.texi
(Effective-Target Keywords).

thanks,
  
Kewen.Lin Oct. 14, 2021, 10:56 a.m. UTC | #2
Hi Hongtao,

on 2021/10/14 下午3:11, liuhongt wrote:
> Hi Kewen:
>   Cound you help to verify if this patch fix those regressions
> for rs6000 port.
> 

The ppc64le run just finished, there are still some regresssions:

NA->XPASS: c-c++-common/Wstringop-overflow-2.c  -Wc++-compat   (test for warnings, line 194)
NA->XPASS: c-c++-common/Wstringop-overflow-2.c  -Wc++-compat   (test for warnings, line 212)
NA->XPASS: c-c++-common/Wstringop-overflow-2.c  -Wc++-compat   (test for warnings, line 296)
NA->XPASS: c-c++-common/Wstringop-overflow-2.c  -Wc++-compat   (test for warnings, line 314)
NA->FAIL: gcc.dg/Wstringop-overflow-21-novec.c (test for excess errors)
NA->FAIL: gcc.dg/Wstringop-overflow-21-novec.c  (test for warnings, line 18)
NA->FAIL: gcc.dg/Wstringop-overflow-21-novec.c  (test for warnings, line 29)
NA->FAIL: gcc.dg/Wstringop-overflow-21-novec.c  (test for warnings, line 45)
NA->FAIL: gcc.dg/Wstringop-overflow-21-novec.c  (test for warnings, line 55)
NA->FAIL: gcc.dg/Wstringop-overflow-76-novec.c note (test for warnings, line 104)
NA->FAIL: gcc.dg/Wstringop-overflow-76-novec.c note (test for warnings, line 137)
NA->FAIL: gcc.dg/Wstringop-overflow-76-novec.c note (test for warnings, line 19)
NA->FAIL: gcc.dg/Wstringop-overflow-76-novec.c note (test for warnings, line 39)
NA->FAIL: gcc.dg/Wstringop-overflow-76-novec.c note (test for warnings, line 56)
NA->FAIL: gcc.dg/Wstringop-overflow-76-novec.c note (test for warnings, line 70)
NA->FAIL: gcc.dg/Wstringop-overflow-76-novec.c (test for excess errors)
NA->FAIL: gcc.dg/Wstringop-overflow-76-novec.c  (test for warnings, line 116)
NA->FAIL: gcc.dg/Wstringop-overflow-76-novec.c  (test for warnings, line 131)
NA->FAIL: gcc.dg/Wstringop-overflow-76-novec.c  (test for warnings, line 146)
NA->FAIL: gcc.dg/Wstringop-overflow-76-novec.c  (test for warnings, line 33)
NA->FAIL: gcc.dg/Wstringop-overflow-76-novec.c  (test for warnings, line 50)
NA->FAIL: gcc.dg/Wstringop-overflow-76-novec.c  (test for warnings, line 64)
NA->FAIL: gcc.dg/Wstringop-overflow-76-novec.c  (test for warnings, line 78)
NA->FAIL: gcc.dg/Wstringop-overflow-76-novec.c  (test for warnings, line 97)
PASS->FAIL: c-c++-common/Wstringop-overflow-2.c  -std=gnu++14 (test for excess errors)
NA->FAIL: c-c++-common/Wstringop-overflow-2.c  -std=gnu++14  (test for warnings, line 229)
NA->FAIL: c-c++-common/Wstringop-overflow-2.c  -std=gnu++14  (test for warnings, line 230)
NA->FAIL: c-c++-common/Wstringop-overflow-2.c  -std=gnu++14  (test for warnings, line 331)
NA->FAIL: c-c++-common/Wstringop-overflow-2.c  -std=gnu++14  (test for warnings, line 332)
// omitting -std=gnu++17, -std=gnu++2a, -std=gnu++98

I'll have a look and get back to you tomorrow.

BR,
Kewen

> 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.
> 
> gcc/testsuite/ChangeLog
> 
> 	PR middle-end/102722
> 	PR middle-end/102697
> 	PR middle-end/102462
> 	PR middle-end/102706
> 	* 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.
> 	* lib/target-supports.exp (check_vect_slp_vnqihi_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.
> 	* 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.
> ---
>  .../c-c++-common/Wstringop-overflow-2-novec.c | 348 +++++++++++++++++
>  .../c-c++-common/Wstringop-overflow-2.c       |  26 +-
>  gcc/testsuite/gcc.dg/Warray-bounds-48-novec.c | 364 ++++++++++++++++++
>  gcc/testsuite/gcc.dg/Warray-bounds-48.c       |   6 +-
>  gcc/testsuite/gcc.dg/Warray-bounds-51-novec.c |  61 +++
>  gcc/testsuite/gcc.dg/Warray-bounds-51.c       |   3 +-
>  .../gcc.dg/Warray-parameter-3-novec.c         |  89 +++++
>  gcc/testsuite/gcc.dg/Warray-parameter-3.c     |   3 +-
>  .../gcc.dg/Wstringop-overflow-14-novec.c      |  56 +++
>  gcc/testsuite/gcc.dg/Wstringop-overflow-14.c  |   5 +-
>  .../gcc.dg/Wstringop-overflow-21-novec.c      |  59 +++
>  gcc/testsuite/gcc.dg/Wstringop-overflow-21.c  |  10 +-
>  gcc/testsuite/gcc.dg/Wstringop-overflow-68.c  |  17 +-
>  .../gcc.dg/Wstringop-overflow-76-novec.c      | 147 +++++++
>  gcc/testsuite/gcc.dg/Wstringop-overflow-76.c  |  26 +-
>  gcc/testsuite/lib/target-supports.exp         | 129 +++++++
>  16 files changed, 1314 insertions(+), 35 deletions(-)
>  create mode 100644 gcc/testsuite/c-c++-common/Wstringop-overflow-2-novec.c
>  create mode 100644 gcc/testsuite/gcc.dg/Warray-bounds-48-novec.c
>  create mode 100644 gcc/testsuite/gcc.dg/Warray-bounds-51-novec.c
>  create mode 100644 gcc/testsuite/gcc.dg/Warray-parameter-3-novec.c
>  create mode 100644 gcc/testsuite/gcc.dg/Wstringop-overflow-14-novec.c
>  create mode 100644 gcc/testsuite/gcc.dg/Wstringop-overflow-21-novec.c
>  create mode 100644 gcc/testsuite/gcc.dg/Wstringop-overflow-76-novec.c
> 
> diff --git a/gcc/testsuite/c-c++-common/Wstringop-overflow-2-novec.c b/gcc/testsuite/c-c++-common/Wstringop-overflow-2-novec.c
> new file mode 100644
> index 00000000000..89e6a5c12c2
> --- /dev/null
> +++ b/gcc/testsuite/c-c++-common/Wstringop-overflow-2-novec.c
> @@ -0,0 +1,348 @@
> +/* PR middle-end/91458 - inconsistent warning for writing past the end
> +   of an array member
> +   { dg-do compile }
> +   { dg-options "-O2 -fno-tree-vectorize -Wall -Wno-array-bounds -fno-ipa-icf" } */
> +
> +void sink (void*);
> +
> +// Exercise flexible array members.
> +
> +struct Ax
> +{
> +  char n;
> +  char a[];                     // { dg-message "destination object" "note" }
> +};
> +
> +// Verify warning for a definition with no initializer.
> +struct Ax ax_;
> +
> +void gax_ (void)
> +{
> +  ax_.a[0] = 0;                 // { dg-warning "\\\[-Wstringop-overflow" }
> +  ax_.a[1] = 1;                 // { dg-warning "\\\[-Wstringop-overflow" }
> +  ax_.a[2] = 2;                 // { dg-warning "\\\[-Wstringop-overflow" }
> +}
> +
> +// Verify warning for access to a definition with an initializer that doesn't
> +// initialize the flexible array member.
> +struct Ax ax0 = { 0 };
> +
> +void gax0 (void)
> +{
> +  ax0.a[0] = 0;                 // { dg-warning "\\\[-Wstringop-overflow" }
> +  ax0.a[1] = 1;                 // { dg-warning "\\\[-Wstringop-overflow" }
> +  ax0.a[2] = 2;                 // { dg-warning "\\\[-Wstringop-overflow" }
> +}
> +
> +// Verify warning for access to a definition with an initializer that
> +// initializes the flexible array member to empty.
> +struct Ax ax0_ = { 0, { } };
> +
> +void gax0_ (void)
> +{
> +  ax0_.a[0] = 0;                // { dg-warning "\\\[-Wstringop-overflow" }
> +  ax0_.a[1] = 1;                // { dg-warning "\\\[-Wstringop-overflow" }
> +  ax0_.a[2] = 2;                // { dg-warning "\\\[-Wstringop-overflow" }
> +}
> +
> +// Verify warning for out-of-bounds accesses to a definition with
> +// an initializer.
> +struct Ax ax1 = { 1, { 0 } };
> +
> +void gax1 (void)
> +{
> +  ax1.a[0] = 0;
> +  ax1.a[1] = 1;                 // { dg-warning "\\\[-Wstringop-overflow" }
> +  ax1.a[2] = 2;                 // { dg-warning "\\\[-Wstringop-overflow" }
> +}
> +
> +struct Ax ax2 = { 2, { 1, 0 } };
> +
> +void gax2 (void)
> +{
> +  ax2.a[0] = 0;
> +  ax2.a[1] = 1;
> +  ax2.a[2] = 2;                 // { dg-warning "\\\[-Wstringop-overflow" }
> +}
> +
> +
> +// Verify no warning for an unknown struct object.
> +void gaxp (struct Ax *p)
> +{
> +  p->a[0] = 0;
> +  p->a[3] = 3;
> +  p->a[9] = 9;
> +}
> +
> +
> +// Verify no warning for an extern struct object whose array may be
> +// initialized to any number of elements.
> +extern struct Ax axx;
> +
> +void gaxx (void)
> +{
> +  axx.a[0] = 0;
> +  axx.a[3] = 3;
> +  axx.a[9] = 9;
> +}
> +
> +// Exercise zero-length array members.
> +
> +struct A0
> +{
> +  char n;
> +  char a[0];                    // { dg-message "destination object" "note" }
> +};
> +
> +// Verify warning for a definition with no initializer.
> +struct A0 a0_;
> +
> +void ga0_ (void)
> +{
> +  a0_.a[0] = 0;                 // { dg-warning "\\\[-Wstringop-overflow" }
> +  a0_.a[1] = 1;                 // { dg-warning "\\\[-Wstringop-overflow" }
> +  a0_.a[2] = 2;                 // { dg-warning "\\\[-Wstringop-overflow" }
> +}
> +
> +// Verify warning for access to a definition with an initializer that doesn't
> +// initialize the flexible array member.
> +struct A0 a00 = { 0 };
> +
> +void ga00 (void)
> +{
> +  a00.a[0] = 0;                 // { dg-warning "\\\[-Wstringop-overflow" }
> +  a00.a[1] = 1;                 // { dg-warning "\\\[-Wstringop-overflow" }
> +  a00.a[2] = 2;                 // { dg-warning "\\\[-Wstringop-overflow" }
> +}
> +
> +// Verify warning for access to a definition with an initializer that
> +// initializes the flexible array member to empty.
> +struct A0 a00_ = { 0, { } };
> +
> +void ga00_ (void)
> +{
> +  a00_.a[0] = 0;                // { dg-warning "\\\[-Wstringop-overflow" }
> +  a00_.a[1] = 1;                // { dg-warning "\\\[-Wstringop-overflow" }
> +  a00_.a[2] = 2;                // { dg-warning "\\\[-Wstringop-overflow" }
> +}
> +
> +// The following are rejected with
> +//   error: too many initializers for 'char [0]'
> +// A0 a01 = { 1, { 0 } };
> +// A0 a02 = { 2, { 1, 0 } };
> +
> +
> +// Verify no warning for an unknown struct object.
> +void ga0p (struct A0 *p)
> +{
> +  p->a[0] = 0;
> +  p->a[3] = 3;
> +  p->a[9] = 9;
> +}
> +
> +
> +// Verify warning for an extern struct object which (unlike a true
> +// flexible array member) may not be initialized.
> +extern struct A0 a0x;
> +
> +void ga0x (void)
> +{
> +  a0x.a[0] = 0;                 // { dg-warning "\\\[-Wstringop-overflow" }
> +  a0x.a[3] = 0;                 // { dg-warning "\\\[-Wstringop-overflow" }
> +  a0x.a[9] = 0;                 // { dg-warning "\\\[-Wstringop-overflow" }
> +}
> +
> +
> +// Exercise trailing one-element array members.
> +
> +struct A1
> +{
> +  char n;
> +  char a[1];                    // { dg-message "destination object" "note" }
> +};
> +
> +// Verify warning for a definition with no initializer.
> +struct A1 a1_;
> +
> +void ga1_ (void)
> +{
> +  a1_.a[0] = 0;
> +  a1_.a[1] = 1;                 // { dg-warning "\\\[-Wstringop-overflow" }
> +  a1_.a[2] = 2;                 // { dg-warning "\\\[-Wstringop-overflow" }
> +
> +  struct A1 a;
> +  a.a[0] = 0;
> +  a.a[1] = 1;                   // { dg-warning "\\\[-Wstringop-overflow" }
> +  a.a[2] = 2;                   // { dg-warning "\\\[-Wstringop-overflow" }
> +  sink (&a);
> +}
> +
> +// Verify warning for access to a definition with an initializer that doesn't
> +// initialize the one-element array member.
> +struct A1 a1__ = { 0 };
> +
> +void ga1__ (void)
> +{
> +  a1__.a[0] = 0;
> +  a1__.a[1] = 1;                 // { dg-warning "\\\[-Wstringop-overflow" }
> +  a1__.a[2] = 2;                 // { dg-warning "\\\[-Wstringop-overflow" }
> +
> +  struct A1 a = { 1 };
> +  a.a[0] = 0;
> +  a.a[1] = 1;                    // { dg-warning "\\\[-Wstringop-overflow" }
> +  a.a[2] = 2;                    // { dg-warning "\\\[-Wstringop-overflow" }
> +  sink (&a);
> +}
> +
> +// Verify warning for access to a definition with an initializer that
> +// initializes the one-element array member to empty.
> +struct A1 a1_0 = { 0, { } };
> +
> +void ga1_0_ (void)
> +{
> +  a1_0.a[0] = 0;
> +  a1_0.a[1] = 1;                // { dg-warning "\\\[-Wstringop-overflow" }
> +  a1_0.a[2] = 2;                // { dg-warning "\\\[-Wstringop-overflow" }
> +
> +  struct A1 a = { 1, { } };
> +  a.a[0] = 0;
> +  a.a[1] = 1;                   // { dg-warning "\\\[-Wstringop-overflow" }
> +  a.a[2] = 2;                   // { dg-warning "\\\[-Wstringop-overflow" }
> +  sink (&a);
> +}
> +
> +// Verify warning for access to a definition with an initializer that
> +// initializes the one-element array member.
> +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 } };
> +  a.a[0] = 0;
> +  a.a[1] = 1;                   // { dg-warning "\\\[-Wstringop-overflow" }
> +  a.a[2] = 2;                   // { dg-warning "\\\[-Wstringop-overflow" }
> +  sink (&a);
> +}
> +
> +
> +// Verify no warning for an unknown struct object.
> +void ga1p (struct A1 *p)
> +{
> +  p->a[0] = 0;
> +  p->a[3] = 3;
> +  p->a[9] = 9;
> +}
> +
> +
> +// Verify warning for an extern struct object.  Similar to the zero-length
> +// array case, a one-element trailing array can be initialized to at most
> +// a single element.
> +extern struct A1 a1x;
> +
> +void ga1x (void)
> +{
> +  a1x.a[0] = 0;
> +  a1x.a[3] = 3;                 // { dg-warning "\\\[-Wstringop-overflow" }
> +  a1x.a[9] = 9;                 // { dg-warning "\\\[-Wstringop-overflow" }
> +}
> +
> +// Exercise interior one-element array members (verify they're not
> +// treated as trailing.
> +
> +struct A1i
> +{
> +  char n;
> +  char a[1];                    // { dg-message "destination object" }
> +  char x;
> +};
> +
> +// Verify warning for a definition with no initializer.
> +struct A1i a1i_;
> +
> +void ga1i_ (void)
> +{
> +  a1i_.a[0] = 0;
> +  a1i_.a[1] = 1;                // { dg-warning "\\\[-Wstringop-overflow" }
> +  a1i_.a[2] = 2;                // { dg-warning "\\\[-Wstringop-overflow" }
> +
> +  struct A1i a;
> +  a.a[0] = 1;
> +  a.a[1] = 2;                   // { dg-warning "\\\[-Wstringop-overflow" }
> +  a.a[2] = 3;                   // { dg-warning "\\\[-Wstringop-overflow" }
> +  sink (&a);
> +}
> +
> +// Verify warning for access to a definition with an initializer that doesn't
> +// initialize the one-element array member.
> +struct A1i a1i__ = { 0 };
> +
> +void ga1i__ (void)
> +{
> +  a1i__.a[0] = 0;
> +  a1i__.a[1] = 1;                // { dg-warning "\\\[-Wstringop-overflow" }
> +  a1i__.a[2] = 2;                // { dg-warning "\\\[-Wstringop-overflow" }
> +
> +  struct A1i a = { 0 };
> +  a.a[0] = 0;
> +  a.a[1] = 1;                    // { dg-warning "\\\[-Wstringop-overflow" }
> +  a.a[2] = 2;                    // { dg-warning "\\\[-Wstringop-overflow" }
> +  sink (&a);
> +}
> +
> +// Verify warning for access to a definition with an initializer that
> +// initializes the one-element array member to empty.
> +struct A1 a1i_0 = { 0, { } };
> +
> +void ga1i_0_ (void)
> +{
> +  a1i_0.a[0] = 0;
> +  a1i_0.a[1] = 1;               // { dg-warning "\\\[-Wstringop-overflow" }
> +  a1i_0.a[2] = 2;               // { dg-warning "\\\[-Wstringop-overflow" }
> +
> +  struct A1 a = { 0, { } };
> +  a.a[0] = 0;
> +  a.a[1] = 1;                   // { dg-warning "\\\[-Wstringop-overflow" }
> +  a.a[2] = 2;                   // { dg-warning "\\\[-Wstringop-overflow" }
> +  sink (&a);
> +}
> +
> +// Verify warning for access to a definition with an initializer that
> +// initializes the one-element array member.
> +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" }
> +
> +  struct A1 a = { 0, { 1 } };
> +  a.a[0] = 1;
> +  a.a[1] = 2;                   // { dg-warning "\\\[-Wstringop-overflow" }
> +  a.a[2] = 3;                   // { dg-warning "\\\[-Wstringop-overflow" }
> +  sink (&a);
> +}
> +
> +
> +// Verify no warning for an unknown struct object.
> +void ga1ip (struct A1i *p)
> +{
> +  p->a[0] = 0;
> +  p->a[3] = 3;                  // { dg-warning "\\\[-Wstringop-overflow" }
> +  p->a[9] = 9;                  // { dg-warning "\\\[-Wstringop-overflow" }
> +}
> +
> +
> +// Verify no warning for an extern struct object.
> +extern struct A1i a1ix;
> +
> +void ga1ix (void)
> +{
> +  a1ix.a[0] = 0;
> +  a1ix.a[3] = 3;                 // { dg-warning "\\\[-Wstringop-overflow" }
> +  a1ix.a[9] = 9;                 // { dg-warning "\\\[-Wstringop-overflow" }
> +}
> diff --git a/gcc/testsuite/c-c++-common/Wstringop-overflow-2.c b/gcc/testsuite/c-c++-common/Wstringop-overflow-2.c
> index 7d29b5f48c7..cb687c69324 100644
> --- a/gcc/testsuite/c-c++-common/Wstringop-overflow-2.c
> +++ b/gcc/testsuite/c-c++-common/Wstringop-overflow-2.c
> @@ -189,8 +189,9 @@ void ga1__ (void)
>  
>    struct A1 a = { 1 };
>    a.a[0] = 0;
> +  // O2 vectorization regress Wstringop-overflow case (1), refer to pr102462.
>    a.a[1] = 1;                    // { dg-warning "\\\[-Wstringop-overflow" }
> -  a.a[2] = 2;                    // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { i?86-*-* x86_64-*-* } } }
> +  a.a[2] = 2;                    // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { vect_slp_v2qi_store } } }
>    sink (&a);
>  }
>  
> @@ -206,8 +207,9 @@ void ga1_0_ (void)
>  
>    struct A1 a = { 1, { } };
>    a.a[0] = 0;
> +  // O2 vectorization regress Wstringop-overflow case (1), refer to PR102462.
>    a.a[1] = 1;                   // { dg-warning "\\\[-Wstringop-overflow" }
> -  a.a[2] = 2;                   // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { i?86-*-* x86_64-*-* } } }
> +  a.a[2] = 2;                   // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { vect_slp_v2qi_store } } }
>    sink (&a);
>  }
>  
> @@ -221,10 +223,11 @@ void ga1_1 (void)
>    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-*-* } } }
> +// O2 vectorization regress Wstringop-overflow case (2), refer to PR102706
> +  struct A1 a = { 0, { 1 } };   // { dg-warning "\\\[-Wstringop-overflow" "" { target { vect_slp_v4qi_store } } }
>    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-*-* } } }
> +  a.a[1] = 1;                   // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { vect_slp_v4qi_store } } }
> +  a.a[2] = 2;                   // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { vect_slp_v4qi_store } } }
>    sink (&a);
>  }
>  
> @@ -288,8 +291,9 @@ void ga1i__ (void)
>  
>    struct A1i a = { 0 };
>    a.a[0] = 0;
> +  // O2 vectorization regress Wstringop-overflow case (1), refer to PR102462
>    a.a[1] = 1;                    // { dg-warning "\\\[-Wstringop-overflow" }
> -  a.a[2] = 2;                    // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { i?86-*-* x86_64-*-* } } }
> +  a.a[2] = 2;                    // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { vect_slp_v2qi_store } } }
>    sink (&a);
>  }
>  
> @@ -305,8 +309,9 @@ void ga1i_0_ (void)
>  
>    struct A1 a = { 0, { } };
>    a.a[0] = 0;
> +  // O2 vectorization regress Wstringop-overflow case (1), refer to PR102462
>    a.a[1] = 1;                   // { dg-warning "\\\[-Wstringop-overflow" }
> -  a.a[2] = 2;                   // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { i?86-*-* x86_64-*-* } } }
> +  a.a[2] = 2;                   // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { vect_slp_v2qi_store } } }
>    sink (&a);
>  }
>  
> @@ -320,10 +325,11 @@ void ga1i_1 (void)
>    a1i_1.a[1] = 1;               // { dg-warning "\\\[-Wstringop-overflow" }
>    a1i_1.a[2] = 2;               // { dg-warning "\\\[-Wstringop-overflow" }
>  
> -  struct A1 a = { 0, { 1 } };   // { dg-warning "\\\[-Wstringop-overflow" "" { target { i?86-*-* x86_64-*-* } } }
> +  // O2 vectorization regress Wstringop-overflow case (1), refer to PR102462
> +  struct A1 a = { 0, { 1 } };   // { dg-warning "\\\[-Wstringop-overflow" "" { target { vect_slp_v4qi_store } } }
>    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-*-* } } }
> +  a.a[1] = 2;                   // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { vect_slp_v4qi_store } } }
> +  a.a[2] = 3;                   // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { vect_slp_v4qi_store } } }
>    sink (&a);
>  }
>  
> diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-48-novec.c b/gcc/testsuite/gcc.dg/Warray-bounds-48-novec.c
> new file mode 100644
> index 00000000000..da179a2c0f5
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/Warray-bounds-48-novec.c
> @@ -0,0 +1,364 @@
> +/* PR middle-end/91647 - missing -Warray-bounds accessing a zero-length array
> +   of a declared object
> +   { dg-do "compile" }
> +   { dg-options "-O2 -Wall -fno-tree-vectorize" }
> +   { dg-require-effective-target alloca } */
> +
> +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 (struct AX *p)
> +{
> +  p->ax[0] = 0;     // { dg-warning "\\\[-Warray-bounds" }
> +  p->ax[1] = 1;     // { dg-warning "\\\[-Warray-bounds" }
> +}
> +
> +static void nowarn_ax_extern (struct AX *p)
> +{
> +  p->ax[0] = 0; p->ax[99] = 99; p->ax[999] = 999; p->ax[9999] = 9999;
> +}
> +
> +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" }
> +}
> +
> +static void warn_ax_extern_buf (struct AX *p)
> +{
> +  p->ax[0] = 9; p->ax[1] = 10; p->ax[2] = 11;
> +
> +  p->ax[3] = 12;    // { dg-warning "\\\[-Warray-bounds" }
> +  p->ax[4] = 13;    // { dg-warning "\\\[-Warray-bounds" }
> +  p->ax[5] = 14;    // { dg-warning "\\\[-Warray-bounds" }
> +}
> +
> +static void nowarn_ax_extern_bufx (struct AX *p)
> +{
> +  p->ax[0] = 0; p->ax[99] = 99; p->ax[999] = 999; p->ax[9999] = 9999;
> +}
> +
> +static void nowarn_ax_ref (struct AX *p)
> +{
> +  p->ax[0] = 0; p->ax[99] = 99; p->ax[999] = 999; p->ax[9999] = 9999;
> +}
> +
> +void test_ax (struct AX *p, unsigned n)
> +{
> +  {
> +    struct AX sax;  // { dg-message "defined here" "struct definition" }
> +    warn_ax_local (&sax);
> +    sink (&sax);
> +  }
> +
> +  {
> +    extern
> +      struct AX xsax;
> +    nowarn_ax_extern (&xsax);
> +    sink (&xsax);
> +  }
> +
> +  {
> +    /* 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);
> +  }
> +
> +  {
> +    /* Verify out-of-bounds access to the extern BUF with a known
> +       bound is diagnosed.  */
> +    extern char ax_buf_p3[sizeof (struct AX) + 3 * sizeof (int16_t)];
> +    warn_ax_extern_buf ((struct AX*) ax_buf_p3);
> +    sink (ax_buf_p3);
> +  }
> +
> +  {
> +    /* Verify that accesses to BUFX with an unknown bound are not
> +       diagnosed.  */
> +    extern char bufx[];
> +    nowarn_ax_extern_bufx ((struct AX*) bufx);
> +    sink (bufx);
> +  }
> +
> +  {
> +    /* Verify that accesses to BUFN with a runtime bound are not
> +       diagnosed.  */
> +    char bufn[n];
> +    nowarn_ax_extern_bufx ((struct AX*) bufn);
> +    sink (bufn);
> +  }
> +
> +  nowarn_ax_ref (p);
> +}
> +
> +
> +/* Exercise a zero-length trailing member array.  It's the same as above
> +   except that extern declarations with no definitions are considered to
> +   have zero elements (they can't be initialized to have any).  */
> +
> +struct A0
> +{
> +  int32_t n;
> +  int16_t a0[0];    // { dg-message "while referencing 'a0'" "member" }
> +};
> +
> +static void warn_a0_local (struct A0 *p)
> +{
> +  p->a0[0] = 0;     // { dg-warning "\\\[-Warray-bounds" }
> +  p->a0[1] = 1;     // { dg-warning "\\\[-Warray-bounds" }
> +}
> +
> +static void warn_a0_extern (struct A0 *p)
> +{
> +  p->a0[0] = 2;     // { dg-warning "\\\[-Warray-bounds" }
> +  p->a0[1] = 3;     // { dg-warning "\\\[-Warray-bounds" }
> +}
> +
> +static void warn_a0_local_buf (struct A0 *p)
> +{
> +  p->a0[0] = 4; p->a0[1] = 5;
> +
> +  p->a0[2] = 6;     // { dg-warning "\\\[-Warray-bounds" }
> +  p->a0[3] = 7;     // { dg-warning "\\\[-Warray-bounds" }
> +  p->a0[4] = 8;     // { dg-warning "\\\[-Warray-bounds" }
> +}
> +
> +static void warn_a0_extern_buf (struct A0 *p)
> +{
> +  p->a0[0] = 9; p->a0[1] = 10; p->a0[2] = 11;
> +
> +  p->a0[3] = 12;    // { dg-warning "\\\[-Warray-bounds" }
> +  p->a0[4] = 13;    // { dg-warning "\\\[-Warray-bounds" }
> +  p->a0[5] = 14;    // { dg-warning "\\\[-Warray-bounds" }
> +}
> +
> +static void nowarn_a0_extern_bufx (struct A0 *p)
> +{
> +  p->a0[0] = 0; p->a0[99] = 99; p->a0[999] = 999; p->a0[9999] = 9999;
> +}
> +
> +static void nowarn_a0_ref (struct A0 *p)
> +{
> +  p->a0[0] = 0; p->a0[99] = 99; p->a0[999] = 999; p->a0[9999] = 9999;
> +}
> +
> +void test_a0 (struct A0 *p, unsigned n)
> +{
> +  {
> +    struct A0 sa0;  // { dg-message "defined here" "struct definition" }
> +    warn_a0_local (&sa0);
> +    sink (&sa0);
> +  }
> +
> +  {
> +    extern
> +      struct A0 xsa0;  // { dg-message "defined here" "struct definition" }
> +    warn_a0_extern (&xsa0);
> +    sink (&xsa0);
> +  }
> +
> +  {
> +    /* Verify out-of-bounds access to the local BUF is diagnosed.  */
> +    char a0_buf_p2[sizeof (struct A0) + 2 * sizeof (int16_t)];
> +    warn_a0_local_buf ((struct A0*) a0_buf_p2);
> +    sink (a0_buf_p2);
> +  }
> +
> +  {
> +    /* Verify out-of-bounds access to the extern BUF with a known
> +       bound is diagnosed.  */
> +    extern char a0_buf_p3[sizeof (struct A0) + 3 * sizeof (int16_t)];
> +    warn_a0_extern_buf ((struct A0*) a0_buf_p3);
> +    sink (a0_buf_p3);
> +  }
> +
> +  {
> +    /* Verify that accesses to BUFX with an unknown bound are not
> +       diagnosed.  */
> +    extern char bufx[];
> +    nowarn_a0_extern_bufx ((struct A0*) bufx);
> +    sink (bufx);
> +  }
> +
> +  {
> +    /* Verify that accesses to BUFN with a runtime bound are not
> +       diagnosed.  */
> +    char bufn[n];
> +    nowarn_a0_extern_bufx ((struct A0*) bufn);
> +    sink (bufn);
> +  }
> +
> +  nowarn_a0_ref (p);
> +}
> +
> +
> +/* Exercise a one-element trailing member array.  It's the same as above
> +   except that it has exactly one element.  */
> +
> +struct A1
> +{
> +  int32_t n;
> +  int16_t a1[1];    // { dg-message "while referencing 'a1'" }
> +};
> +
> +static void warn_a1_local_noinit (struct A1 *p)
> +{
> +  p->a1[0] = 0;
> +  p->a1[1] = 1;     // { dg-warning "\\\[-Warray-bounds" }
> +  p->a1[2] = 2;     // { dg-warning "\\\[-Warray-bounds" }
> +}
> +
> +static void warn_a1_extern (struct A1 *p)
> +{
> +  p->a1[0] = 0;
> +  p->a1[1] = 1;     // { dg-warning "\\\[-Warray-bounds" }
> +  p->a1[2] = 2;     // { dg-warning "\\\[-Warray-bounds" }
> +}
> +
> +static void warn_a1_init (struct A1 *p)
> +{
> +  p->a1[0] = 0;
> +  p->a1[1] = 1;     // { dg-warning "\\\[-Warray-bounds" }
> +  p->a1[2] = 2;     // { dg-warning "\\\[-Warray-bounds" }
> +}
> +
> +static void warn_a1_local_buf (struct A1 *p)
> +{
> +  p->a1[0] = 0; p->a1[1] = 1; p->a1[2] = 2; p->a1[3] = 3;
> +
> +  p->a1[4] = 4;     // { dg-warning "\\\[-Warray-bounds" }
> +}
> +
> +static void warn_a1_extern_buf (struct A1 *p)
> +{
> +  p->a1[0] = 0; p->a1[1] = 1; p->a1[2] = 2; p->a1[3] = 3; p->a1[4] = 4;
> +
> +  p->a1[5] = 5;     // { dg-warning "\\\[-Warray-bounds" }
> +}
> +
> +static void nowarn_a1_extern_bufx (struct A1 *p)
> +{
> +  p->a1[0] = 0; p->a1[99] = 99; p->a1[999] = 999; p->a1[9999] = 9999;
> +}
> +
> +static void nowarn_a1_ref (struct A1 *p)
> +{
> +  p->a1[0] = 0; p->a1[99] = 99; p->a1[999] = 999; p->a1[9999] = 9999;
> +}
> +
> +void test_a1 (struct A1 *p, unsigned n)
> +{
> +  {
> +    struct A1 a1;
> +    warn_a1_local_noinit (&a1);
> +    sink (&a1);
> +  }
> +
> +  {
> +    extern struct A1 a1x;
> +    warn_a1_extern (&a1x);
> +    sink (&a1x);
> +}
> +  {
> +    struct A1 a1 = { 0, { 1 } };
> +    warn_a1_init (&a1);
> +    sink (&a1);
> +  }
> +
> +  {
> +    /* Verify out-of-bounds access to the local BUF is diagnosed.  */
> +    char buf_p2[sizeof (struct A1) + 2 * sizeof (int16_t)];
> +    warn_a1_local_buf ((struct A1*) buf_p2);
> +    sink (buf_p2);
> +  }
> +
> +  {
> +    /* Verify out-of-bounds access to the extern BUF with a known
> +       bound is diagnosed.  */
> +    extern char a1_buf_p3[sizeof (struct A1) + 3 * sizeof (int16_t)];
> +    warn_a1_extern_buf ((struct A1*) a1_buf_p3);
> +    sink (a1_buf_p3);
> +  }
> +
> +  {
> +    /* Verify that accesses to BUFX with an unknown bound are not
> +       diagnosed.  */
> +    extern char bufx[];
> +    nowarn_a1_extern_bufx ((struct A1*) bufx);
> +    sink (bufx);
> +  }
> +
> +  {
> +    /* Verify that accesses to BUFN with a runtime bound are not
> +       diagnosed.  */
> +    char bufn[n];
> +    nowarn_a1_extern_bufx ((struct A1*) bufn);
> +    sink (bufn);
> +  }
> +
> +  nowarn_a1_ref (p);
> +}
> +
> +
> +/* Exercise a two-element trailing member array.  It's treated
> +   the same as an interior array member.  */
> +
> +struct A2
> +{
> +  int32_t n;
> +  int16_t a2[2];    // { dg-message "while referencing 'a2'" }
> +};
> +
> +static void warn_a2_noinit (struct A2 *p)
> +{
> +  p->a2[0] = 0; p->a2[1] = 1;
> +
> +  p->a2[2] = 2;     // { dg-warning "\\\[-Warray-bounds" }
> +}
> +
> +static void warn_a2_init (struct A2 *p)
> +{
> +  p->a2[0] = 0; p->a2[1] = 1;
> +
> +  p->a2[2] = 2;     // { dg-warning "\\\[-Warray-bounds" }
> +  p->a2[9] = 9;     // { dg-warning "\\\[-Warray-bounds" }
> +}
> +
> +static void warn_a2_ref (struct A2 *p)
> +{
> +  p->a2[0] = 0; p->a2[1] = 1;
> +
> +  p->a2[2] = 2;     // { dg-warning "\\\[-Warray-bounds" }
> +  p->a2[9] = 9;     // { dg-warning "\\\[-Warray-bounds" }
> +}
> +
> +void test_a2 (struct A2 *p)
> +{
> +  {
> +    struct A2 a2;
> +    warn_a2_noinit (&a2);
> +    sink (&a2);
> +  }
> +
> +  {
> +    struct A2 a2 = { 0, { 1, 2 } };
> +    warn_a2_init (&a2);
> +    sink (&a2);
> +  }
> +
> +  warn_a2_ref (p);
> +}
> diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-48.c b/gcc/testsuite/gcc.dg/Warray-bounds-48.c
> index 13373d1e99e..27dd879de5c 100644
> --- a/gcc/testsuite/gcc.dg/Warray-bounds-48.c
> +++ b/gcc/testsuite/gcc.dg/Warray-bounds-48.c
> @@ -30,7 +30,8 @@ static void nowarn_ax_extern (struct AX *p)
>  
>  static void warn_ax_local_buf (struct AX *p)
>  {
> -  p->ax[0] = 4; p->ax[1] = 5;
> +  // Refer to 102706
> +  p->ax[0] = 4; p->ax[1] = 5;  // { dg-warning "\\\[-Wstringop-overflow" "" { target { vect_slp_v2hi_store &&  { ! vect_slp_v4hi_store } } } }
>  
>    p->ax[2] = 6;     // { dg-warning "\\\[-Warray-bounds" }
>    p->ax[3] = 7;     // { dg-warning "\\\[-Warray-bounds" }
> @@ -130,7 +131,8 @@ static void warn_a0_extern (struct A0 *p)
>  
>  static void warn_a0_local_buf (struct A0 *p)
>  {
> -  p->a0[0] = 4; p->a0[1] = 5;
> +  // Refer to 102706
> +  p->a0[0] = 4; p->a0[1] = 5;  // { dg-warning "\\\[-Wstringop-overflow" "" { target { vect_slp_v2hi_store && { ! vect_slp_v4hi_store } } } }
>  
>    p->a0[2] = 6;     // { dg-warning "\\\[-Warray-bounds" }
>    p->a0[3] = 7;     // { dg-warning "\\\[-Warray-bounds" }
> diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-51-novec.c b/gcc/testsuite/gcc.dg/Warray-bounds-51-novec.c
> new file mode 100644
> index 00000000000..24bc318f113
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/Warray-bounds-51-novec.c
> @@ -0,0 +1,61 @@
> +/* PR middle-end/92333 - missing variable name referencing VLA in warnings
> +   PR middle-end/82608 - missing -Warray-bounds on an out-of-bounds VLA index
> +   { dg-do compile }
> +   { dg-options "-O2 -Wall -fno-tree-vectorize" }  */
> +
> +void sink (void*);
> +
> +void test_char_vla_location (void)
> +{
> +  unsigned nelts = 7;
> +
> +  char vla[nelts];    // { dg-message "declared here|while referencing" }
> +
> +  vla[0] = __LINE__;
> +  vla[nelts] = 0;     // { dg-warning "\\\[-Warray-bounds" }
> +
> +  sink (vla);
> +}
> +
> +void test_int_vla_location (void)
> +{
> +  unsigned nelts = 7;
> +
> +  int vla[nelts];     // { dg-message "declared here|while referencing" }
> +
> +  vla[0] = __LINE__;
> +  vla[nelts] = 1;     // { dg-warning "\\\[-Warray-bounds" }
> +
> +  sink (vla);
> +}
> +
> +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;
> +  s.cvla[nelts] = 0;  // { dg-warning "\\\[-Warray-bounds" }
> +
> +  sink (&s);
> +}
> +
> +
> +void test_struct_int_vla_location (void)
> +{
> +  unsigned nelts = 7;
> +
> +  struct {
> +    int ivla[nelts];  // { dg-message "declared here|while referencing" }
> +  } s;
> +
> +  s.ivla[0] = __LINE__;
> +  s.ivla[nelts - 1] = 0;
> +  s.ivla[nelts] = 0;  // { dg-warning "\\\[-Warray-bounds" }
> +
> +  sink (&s);
> +}
> diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-51.c b/gcc/testsuite/gcc.dg/Warray-bounds-51.c
> index de60d87ab95..cc92a0fd500 100644
> --- a/gcc/testsuite/gcc.dg/Warray-bounds-51.c
> +++ b/gcc/testsuite/gcc.dg/Warray-bounds-51.c
> @@ -39,7 +39,8 @@ void test_struct_char_vla_location (void)
>    } s;
>  
>    s.cvla[0] = __LINE__;
> -  s.cvla[nelts - 1] = 0; // { dg-warning "\\\[-Wstringop-overflow" "" { target { i?86-*-* x86_64-*-* } } }
> +  // O2 vectorization regress Wstringop-overflow case (2), refer to pr102706.
> +  s.cvla[nelts - 1] = 0; // { dg-warning "\\\[-Wstringop-overflow" "" { target { vect_slp_v2qi_store } } }
>    s.cvla[nelts] = 0;  // { dg-warning "\\\[-Warray-bounds" }
>  
>    sink (&s);
> diff --git a/gcc/testsuite/gcc.dg/Warray-parameter-3-novec.c b/gcc/testsuite/gcc.dg/Warray-parameter-3-novec.c
> new file mode 100644
> index 00000000000..0c8fdd11ec9
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/Warray-parameter-3-novec.c
> @@ -0,0 +1,89 @@
> +/* PR c/50584 - No warning for passing small array to C99 static array
> +   declarator
> +   { dg-do compile }
> +   { dg-options "-Wall -Warray-parameter=1" } */
> +
> +/* Verify that at level 1 mismatches in the bounds of ordinary array
> +   parameters don't trigger -Warray-parameter.  */
> +void fax (int[]);
> +void fax (int[0]);
> +void fax (int[1]);
> +void fax (int[2]);
> +void fax (int[3]);
> +
> +/* Same as above but starting with an array with a specified bound.  */
> +void gax (int[3]);
> +void gax (int[2]);
> +void gax (int[1]);
> +void gax (int[0]);
> +void gax (int[]);
> +
> +/* Same for multidimensional arrays.  */
> +void fax_y (int[][3]);
> +void fax_y (int[0][3]);
> +void fax_y (int[1][3]);
> +void fax_y (int[2][3]);
> +void fax_y (int[3][3]);
> +
> +/* Same as above but starting with an array with a specified bound.  */
> +void gax_y (int[3][5]);
> +void gax_y (int[2][5]);
> +void gax_y (int[1][5]);
> +void gax_y (int[0][5]);
> +void gax_y (int[][5]);
> +
> +/* Exercise VLAs with a mismatch in the bound for an ordinary array.  */
> +void fvlax_y (int n, int[][n]);
> +void fvlax_y (int n, int[0][n]);
> +void fvlax_y (int n, int[1][n]);
> +void fvlax_y (int n, int[2][n]);
> +void fvlax_y (int n, int[3][n]);
> +
> +void fvlaxn_y (int n, int[][n]);
> +void fvlaxn_y (int n, int[0][n]);
> +void fvlaxn_y (int n, int[1][n]);
> +void fvlaxn_y (int n, int[2][n]);
> +void fvlaxn_y (int n, int[3][n]);
> +
> +void fvlaxx_y (int[][*]);
> +void fvlaxx_y (int[0][*]);
> +void fvlaxx_y (int[1][*]);
> +void fvlaxx_y (int[2][*]);
> +void fvlaxx_y (int[3][*]);
> +
> +/* Verify that mismatches in the bounds of array parameters declared
> +   static do trigger -Warray-parameter.  */
> +void fas1 (int[static 1]);    // { dg-message "previously declared as 'int\\\[static 1]'" }
> +void fas1 (int[static 2]);    // { dg-warning "\\\[-Warray-parameter=" }
> +
> +
> +/* Also verify that -Warray-bounds doesn't trigger for ordinary array
> +   parameters...  */
> +#pragma GCC optimize ("2,no-tree-vectorize")
> +
> +__attribute__ ((noipa)) void
> +gca3 (char a[3])
> +{
> +  a[0] = 0; a[1] = 1; a[2] = 2; a[3] = 3;
> +}
> +
> +__attribute__ ((noipa)) void
> +gia3 (int a[3])
> +{
> +  a[0] = 0; a[1] = 1; a[2] = 2; a[3] = 3;
> +}
> +
> +/* ...but does for static arrays.  */
> +__attribute__ ((noipa)) void
> +gcas3 (char a[static 3])
> +{
> +  a[0] = 0; a[1] = 1; a[2] = 2;
> +  a[3] = 3;                   // { dg-warning "\\\[-Warray-bounds" }
> +}
> +
> +__attribute__ ((noipa)) void
> +gias3 (int a[static 3])
> +{
> +  a[0] = 0; a[1] = 1; a[2] = 2;
> +  a[3] = 3;                   // { dg-warning "\\\[-Warray-bounds" }
> +}
> diff --git a/gcc/testsuite/gcc.dg/Warray-parameter-3.c b/gcc/testsuite/gcc.dg/Warray-parameter-3.c
> index e8a269c85c6..1068707973f 100644
> --- a/gcc/testsuite/gcc.dg/Warray-parameter-3.c
> +++ b/gcc/testsuite/gcc.dg/Warray-parameter-3.c
> @@ -77,7 +77,8 @@ gia3 (int a[3])
>  __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-*-* } } }
> +  // O2 vectorization regress Wstringop-overflow case (2), refer to pr102706.
> +  a[0] = 0; a[1] = 1; a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" "" { target { vect_slp_v4qi_store } } }
>    a[3] = 3;                   // { dg-warning "\\\[-Warray-bounds" }
>  }
>  
> diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-14-novec.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-14-novec.c
> new file mode 100644
> index 00000000000..c7b5479dc07
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-14-novec.c
> @@ -0,0 +1,56 @@
> +/* Test to verify that past-the-end multibyte writes via lvalues of wider
> +   types than char are diagnosed.
> +   { dg-do compile }
> +   { dg-require-effective-target int32plus }
> +   { dg-options "-O2 -fno-tree-vectorize -Wall -Wno-array-bounds" }  */
> +
> +typedef __INT16_TYPE__  int16_t;
> +typedef __INT32_TYPE__  int32_t;
> +typedef __INT64_TYPE__  int64_t;
> +typedef __SIZE_TYPE__   size_t;
> +
> +void* memcpy (void*, const void*, size_t);
> +char* strcpy (char*, const char*);
> +
> +char a4[4], a8[8], a16[16];
> +
> +const char s4[] = "1234";
> +const char t4[] = "4321";
> +
> +void test_memcpy_cond (int i)
> +{
> +  char *p = a4 + 1;
> +  const char *q = i ? s4 : t4;
> +  // On strictly aligned target the call below is left unchanged and
> +  // triggers (inaccurately) a -Warray-bounds.  The test suppresses
> +  // the warning above, which then lets -Wstringop-overrflow detect
> +  // the overflow just before expansion.
> +  // On other targets it's transformed into a store of a 4-byte integer
> +  // which is detected by -Wstringop-overrflow in the strlen pass (i.e.,
> +  // before it gets to expansion).
> +  memcpy (p, q, 4);         // { dg-warning "writing 4 bytes into a region of size 3" }
> +}
> +
> +
> +void test_int16 (void)
> +{
> +  char *p = a4 + 1;
> +  *(int16_t*)p = 0;
> +  *(int16_t*)(p + 2) = 0;   // { dg-warning "writing 2 bytes into a region of size 1" }
> +}
> +
> +
> +void test_int32 (void)
> +{
> +  char *p = a8 + 3;
> +  *(int32_t*)p = 0;
> +  *(int32_t*)(p + 2) = 0;   // { dg-warning "writing 4 bytes into a region of size 3" }
> +}
> +
> +
> +void test_int64 (void)
> +{
> +  char *p = a16 + 5;
> +  *(int64_t*)p = 0;
> +  *(int64_t*)(p + 5) = 0;   // { dg-warning "writing 8 bytes into a region of size 6" }
> +}
> diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-14.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-14.c
> index 7683084e46e..6ad9444bc27 100644
> --- a/gcc/testsuite/gcc.dg/Wstringop-overflow-14.c
> +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-14.c
> @@ -36,8 +36,9 @@ void test_memcpy_cond (int i)
>  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-*-* } } }
> +  // O2 vectorization regress Wstringop-overflow case (2), refer to pr102706.
> +  *(int16_t*)p = 0;    // { dg-warning "writing 4 bytes into a region of size 3" "" { target { vect_slp_v2hi_store } } }
> +  *(int16_t*)(p + 2) = 0;   // { dg-warning "writing 2 bytes into a region of size 1" "" { xfail { vect_slp_v2hi_store } } }
>  }
>  
>  
> diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-21-novec.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-21-novec.c
> new file mode 100644
> index 00000000000..b177543b186
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-21-novec.c
> @@ -0,0 +1,59 @@
> +/* PR middle-end/92312 - bogus -Wstringop-overflow storing into a trailing
> +   array backed by larger buffer
> +   { dg-do compile }
> +   { dg-options "-O2 -fno-tree-vectorize -Wall -Wno-array-bounds" } */
> +
> +struct S0 { char a, b[0]; };
> +
> +void sink (void*);
> +
> +void test_memset_zero_length (void)
> +{
> +  char a[3];
> +  struct S0 *p = (struct S0*)a;
> +  p->a = 0;
> +  __builtin_memset (p->b, 0, 2);
> +  sink (p);
> +
> +  __builtin_memset (p->b, 0, 3);    // { dg-warning "\\\[-Wstringop-overflow" }
> +  sink (p);
> +}
> +
> +void test_store_zero_length (int i)
> +{
> +  char a[3];
> +  struct S0 *p = (struct S0*)a;
> +  p->a = 0;
> +  p->b[0] = 0;
> +  p->b[1] = 1;                      // { dg-bogus "\\\[-Wstringop-overflow" }
> +  p->b[2] = 2;                      // { dg-warning "\\\[-Wstringop-overflow" }
> +  p->b[i] = 2;
> +  sink (p);
> +}
> +
> +
> +struct Sx { char a, b[]; };
> +
> +void test_memset_flexarray (int i)
> +{
> +  char a[3];
> +  struct Sx *p = (struct Sx*)a;
> +  p->a = 0;
> +  __builtin_memset (p->b, 0, 2);
> +  sink (p);
> +
> +  __builtin_memset (p->b, 0, 3);    // { dg-warning "\\\[-Wstringop-overflow" }
> +  sink (p);
> +}
> +
> +void test_store_flexarray (int i)
> +{
> +  char a[3];
> +  struct Sx *p = (struct Sx*)a;
> +  p->a = 0;
> +  p->b[0] = 0;
> +  p->b[1] = 1;                      // { dg-bogus "\\\[-Wstringop-overflow" }
> +  p->b[2] = 1;                      // { dg-warning "\\\[-Wstringop-overflow" }
> +  p->b[i] = 2;
> +  sink (p);
> +}
> diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-21.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-21.c
> index d88bde9c740..8d2bfe697a5 100644
> --- a/gcc/testsuite/gcc.dg/Wstringop-overflow-21.c
> +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-21.c
> @@ -23,10 +23,11 @@ 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-*-* } } }
> +  // O2 vectorization regress Wstringop-overflow case (2), refer to pr102706.
> +  p->a = 0;                         // { dg-warning "\\\[-Wstringop-overflow" "" { target { vect_slp_v4qi_store } } }
>    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[2] = 2;                      // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { vect_slp_v4qi_store } } }
>    p->b[i] = 2;
>    sink (p);
>  }
> @@ -50,10 +51,11 @@ 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-*-* } } }
> +  // O2 vectorization regress Wstringop-overflow case (2), refer to pr102706.
> +  p->a = 0;                         // { dg-warning "\\\[-Wstringop-overflow" "" { target { vect_slp_v4qi_store } } }
>    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[2] = 1;                      // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { vect_slp_v4qi_store } } }
>    p->b[i] = 2;
>    sink (p);
>  }
> diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-68.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-68.c
> index 09df0004991..04e91afb8bc 100644
> --- a/gcc/testsuite/gcc.dg/Wstringop-overflow-68.c
> +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-68.c
> @@ -58,11 +58,18 @@ void warn_comp_lit_zero (void)
>  void warn_comp_lit (void)
>  {
>    *(AC2*)a1 = Ac2;      // { dg-warning "writing 2 bytes into a region of size 1" "pr101475" { xfail *-*-* } }
> -  *(AC4*)a2 = Ac4;      // { dg-warning "writing 4 bytes into a region of size 2" "pr101475" { xfail { ! { i?86-*-* x86_64-*-* } } } }
> -  *(AC4*)a3 = Ac4;      // { dg-warning "writing 4 bytes into a region of size 3" "pr101475" { xfail { ! { i?86-*-* x86_64-*-* } } } }
> -  *(AC8*)a4 = Ac8;      // { dg-warning "writing 8 bytes into a region of size 4" "pr101475" { xfail { ! { i?86-*-* x86_64-*-* } } } }
> -  *(AC8*)a7 = Ac8;      // { dg-warning "writing 8 bytes into a region of size 7" "pr101475" { xfail { ! { i?86-*-* x86_64-*-* } } } }
> -  *(AC16*)a15 = Ac16;   // { dg-warning "writing 16 bytes into a region of size 15" "pr101475" { xfail { ! { i?86-*-* x86_64-*-* } } } }
> +  // After vectorization, below codes are optimized to
> +  // MEM <vector(4) char> [(char *)&a2] = { 0, 1, 2, 3 };
> +  // MEM <vector(4) char> [(char *)&a3] = { 0, 1, 2, 3 };
> +  // MEM <vector(8) char> [(char *)&a4] = { 0, 1, 2, 3, 4, 5, 6, 7 };
> +  // MEM <vector(8) char> [(char *)&a7] = { 0, 1, 2, 3, 4, 5, 6, 7 };
> +  // MEM <vector(16) char> [(char *)&a15] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
> +  // and warning should be expected, refer to PR102722.
> +  *(AC4*)a2 = Ac4;      // { dg-warning "writing 4 bytes into a region of size 2" "pr101475" { xfail { ! { vect_slp_v4qi_store } } } }
> +  *(AC4*)a3 = Ac4;      // { dg-warning "writing 4 bytes into a region of size 3" "pr101475" { xfail { ! { vect_slp_v4qi_store } } } }
> +  *(AC8*)a4 = Ac8;      // { dg-warning "writing 8 bytes into a region of size 4" "pr101475" { xfail { ! { vect_slp_v8qi_store } } } }
> +  *(AC8*)a7 = Ac8;      // { dg-warning "writing 8 bytes into a region of size 7" "pr101475" { xfail { ! { vect_slp_v8qi_store } } } }
> +  *(AC16*)a15 = Ac16;   // { dg-warning "writing 16 bytes into a region of size 15" "pr101475" { xfail { ! { vect_slp_v16qi_store } } } }
>  }
>  
>  void warn_aggr_decl (void)
> diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-76-novec.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-76-novec.c
> new file mode 100644
> index 00000000000..d000b587a65
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-76-novec.c
> @@ -0,0 +1,147 @@
> +/* Verify warnings and notes for MAX_EXPRs involving either pointers
> +   to distinct objects or one to a known object and the other to
> +   an unknown one.  Unlike for the same object, for unrelated objects
> +   the expected warnings and notes are the same as for MIN_EXPR: when
> +   the order of the objects in the address space cannot be determined
> +   the larger of them is assumed to be used.  (This is different for
> +   distinct struct members where the order is given.)
> +   The relational expressions are strictly invalid but that should be
> +   diagnosed by a separate warning.
> +   { dg-do compile }
> +   { dg-options "-O2 -Wno-array-bounds -fno-tree-vectorize" } */
> +
> +#define MAX(p, q) ((p) > (q) ? (p) : (q))
> +
> +/* Verify that even for MAX_EXPR and like for MIN_EXPR, the note points
> +   to the larger of the two objects and mentions the offset into it
> +   (although the offset might be better included in the warning).  */
> +extern char a3[3];
> +extern char a5[5];  // { dg-message "at offset 5 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;
> +  d[3] = 0;
> +  d[4] = 0;
> +  d[5] = 0;         // { dg-warning "writing 1 byte into a region of size 0" }
> +}
> +
> +
> +// 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 6 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;
> +  d[4] = 0;
> +  d[5] = 0;
> +  d[6] = 0;         // { dg-warning "writing 1 byte into a region of size 0" }
> +}
> +
> +
> +/* Same as above but with the first MAX_EXPR operand pointing to an unknown
> +   object.  */
> +extern char c7[7];  // { dg-message "at offset 7 into destination object 'c7' of size 7" "note" }
> +
> +void max_p_c7 (char *p, int i)
> +{
> +  char *q = c7 + i;
> +  char *d = MAX (p, q);
> +
> +  d[6] = 0;
> +  d[7] = 0;         // { dg-warning "writing 1 byte into a region of size 0" }
> +}
> +
> +
> +/* Same as above but with the second MIN_EXPR operand pointing to an unknown
> +   object.  */
> +extern char d8[8];  // { dg-message "at offset 8 into destination object 'd8' of size 8" "note" }
> +
> +void max_d8_p (char *q, int i)
> +{
> +  char *p = d8 + i;
> +  char *d = MAX (p, q);
> +
> +  d[7] = 0;
> +  d[8] = 0;         // { dg-warning "writing 1 byte into a region of size 0" }
> +}
> +
> +
> +struct A3_5
> +{
> +  char a3[3];  // { dg-message "at offset 3 into destination object 'a3' of size 3" "pr??????" { xfail *-*-* } }
> +  char a5[5];
> +};
> +
> +void max_A3_A5 (int i, struct A3_5 *pa3_5)
> +{
> +  char *p = pa3_5->a3 + i;
> +  char *q = pa3_5->a5 + i;
> +
> +  char *d = MAX (p, q);
> +  d[2] = 0;
> +  d[3] = 0;         // { dg-warning "writing 1 byte into a region of size 0" "pr??????" { xfail *-*-* } }
> +  d[4] = 0;
> +  d[5] = 0;         // { dg-warning "writing 1 byte into a region of size 0" }
> +}
> +
> +
> +struct B4_B6
> +{
> +  char b4[4];
> +  char b6[6];       // { dg-message "at offset 6 into destination object 'b6' of size 6" "note" }
> +};
> +
> +void max_B6_B4 (int i, struct B4_B6 *pb4_b6)
> +{
> +  char *p = pb4_b6->b6 + i;
> +  char *q = pb4_b6->b4 + i;
> +  char *d = MAX (p, q);
> +
> +  d[3] = 0;
> +  d[4] = 0;
> +  d[5] = 0;
> +  d[6] = 0;         // { dg-warning "writing 1 byte into a region of size 0" }
> +}
> +
> +
> +struct C7
> +{
> +  char c7[7];       // { dg-message "at offset 7 into destination object 'c7' of size 7" "note" }
> +};
> +
> +void max_p_C7 (char *p, int i, struct C7 *pc7)
> +{
> +  char *q = pc7->c7 + i;
> +  char *d = MAX (p, q);
> +
> +  d[6] = 0;
> +  d[7] = 0;         // { dg-warning "writing 1 byte into a region of size 0" }
> +}
> +
> +
> +struct D8
> +{
> +  char d8[8];       // { dg-message "at offset 8 into destination object 'd8' of size 8" "note" }
> +};
> +
> +void max_D8_p (char *q, int i, struct D8 *pd8)
> +{
> +  char *p = pd8->d8 + i;
> +  char *d = MAX (p, q);
> +
> +  d[7] = 0;
> +  d[8] = 0;         // { dg-warning "writing 1 byte into a region of size 0" }
> +}
> diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-76.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-76.c
> index 0c7b53ccc0b..037e66c2769 100644
> --- a/gcc/testsuite/gcc.dg/Wstringop-overflow-76.c
> +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-76.c
> @@ -27,10 +27,11 @@ void max_a3_a5 (int i)
>       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-*-* } } }
> +  // O2 vectorization regress Wstringop-overflow case (2), refer to pr102706.
> +  d[2] = 0;         // { dg-warning "writing 4 bytes into a region of size 3" "" { target { vect_slp_v4qi_store } } }
>    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-*-* } } }
> +  d[5] = 0;         // { dg-warning "writing 1 byte into a region of size 0" "" { xfail { vect_slp_v4qi_store } } }
>  }
>  
>  
> @@ -44,10 +45,11 @@ void max_b6_b4 (int 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-*-* } } }
> +  // O2 vectorization regress Wstringop-overflow case (2), refer to pr102706.
> +  d[3] = 0;         // { dg-warning "writing 4 bytes into a region of size 3" "" { target { vect_slp_v4qi_store } } }
>    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-*-* } } }
> +  d[6] = 0;         // { dg-warning "writing 1 byte into a region of size 0" "" { xfail { vect_slp_v4qi_store } } }
>  }
>  
>  
> @@ -82,7 +84,7 @@ void max_d8_p (char *q, int i)
>  struct A3_5
>  {
>    char a3[3];  // { dg-message "at offset 3 into destination object 'a3' of size 3" "pr??????" { xfail *-*-* } }
> -  char a5[5];  // { dg-message "at offset 5 into destination object 'a5' of size 5" "note" { xfail { i?86-*-* x86_64-*-* } } }
> +  char a5[5];  // { dg-message "at offset 5 into destination object 'a5' of size 5" "note" { xfail { vect_slp_v4qi_store } } }
>  };
>  
>  void max_A3_A5 (int i, struct A3_5 *pa3_5)
> @@ -91,18 +93,20 @@ void max_A3_A5 (int i, struct A3_5 *pa3_5)
>    char *q = pa3_5->a5 + i;
>  
>    char *d = MAX (p, q);
> -
> +  // After vectorization, below codes are vectorized to
> +  // MEM <vector(4) char> [(char *)&d + 3] = { 0, 0, 0, 0 };
> +  // refer to pr102697.
>    d[2] = 0;
>    d[3] = 0;         // { dg-warning "writing 1 byte into a region of size 0" "pr??????" { xfail *-*-* } }
>    d[4] = 0;
> -  d[5] = 0;         // { dg-warning "writing 1 byte into a region of size 0" "" { xfail { i?86-*-* x86_64-*-* } } }
> +  d[5] = 0;         // { dg-warning "writing 1 byte into a region of size 0" "" { xfail { vect_slp_v4qi_store } } }
>  }
>  
>  
>  struct B4_B6
>  {
>    char b4[4];
> -  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" { xfail { i?86-*-* x86_64-*-* } } }
> +  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" { xfail { vect_slp_v4qi_store } } }
>  };
>  
>  void max_B6_B4 (int i, struct B4_B6 *pb4_b6)
> @@ -110,11 +114,13 @@ void max_B6_B4 (int i, struct B4_B6 *pb4_b6)
>    char *p = pb4_b6->b6 + i;
>    char *q = pb4_b6->b4 + i;
>    char *d = MAX (p, q);
> -
> +  // After vectorization, below codes are vectorized to
> +  // MEM <vector(4) char> [(char *)&d + 3] = { 0, 0, 0, 0 };
> +  // refer to pr102697.
>    d[3] = 0;
>    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-*-* } } }
> +  d[6] = 0;         // { dg-warning "writing 1 byte into a region of size 0" "" { xfail { vect_slp_v4qi_store } } }
>  }
>  
>  
> diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
> index 9ebca7ac007..c30831ea91d 100644
> --- a/gcc/testsuite/lib/target-supports.exp
> +++ b/gcc/testsuite/lib/target-supports.exp
> @@ -7580,6 +7580,135 @@ proc check_effective_target_vect_element_align_preferred { } {
>  		   && [check_effective_target_vect_variable_length] }]
>  }
>  
> +# Return true if vectorization of v2qi/v4qi/v8qi/v16qi/v2hi store is enabed.
> +# Return zero if the desirable pattern isn't found.
> +# It's used by Warray-bounds/Wstringop-overflow testcases which are
> +# regressed by O2 vectorization, refer to PR102697/PR102462/PR102706
> +proc check_vect_slp_vnqihi_store_usage { pattern } {
> +    global tool
> +
> +    return [check_cached_effective_target slp_vnqihi_store_usage {
> +      set result [check_compile slp_vnqihi_store_usage assembly {
> +	  char a[16] __attribute__ ((aligned (16)));
> +	  void
> +	  foo ()
> +	  {
> +	      a[0] = 0;
> +	      a[1] = 1;
> +	      a[2] = 2;
> +	      a[3] = 3;
> +	      a[4] = 4;
> +	      a[5] = 5;
> +	      a[6] = 6;
> +	      a[7] = 7;
> +	  }
> +
> +	  void
> +	  foo1 ()
> +	  {
> +	      a[0] = 0;
> +	      a[1] = 1;
> +	      a[2] = 2;
> +	      a[3] = 3;
> +	      a[4] = 4;
> +	      a[5] = 5;
> +	      a[6] = 6;
> +	      a[7] = 7;
> +	      a[8] = 8;
> +	      a[9] = 9;
> +	      a[10] = 10;
> +	      a[11] = 11;
> +	      a[12] = 12;
> +	      a[13] = 13;
> +	      a[14] = 14;
> +	      a[15] = 15;
> +	  }
> +
> +	  void
> +	  foo2 ()
> +	  {
> +	      a[0] = 0;
> +	      a[1] = 1;
> +	      a[2] = 2;
> +	      a[3] = 3;
> +	  }
> +
> +	  void
> +	  foo3 ()
> +	  {
> +	      a[0] = 0;
> +	      a[1] = 1;
> +	  }
> +
> +	  short b[4] __attribute__((aligned(8)));
> +	  void
> +	  foo4 ()
> +	  {
> +	      b[0] = 0;
> +	      b[1] = 1;
> +	  }
> +
> +	  void
> +	  foo5 ()
> +	  {
> +	      b[0] = 0;
> +	      b[1] = 1;
> +	      b[2] = 2;
> +	      b[3] = 3;
> +	  }
> +
> +      } "-O2 -fopt-info-all" ]
> +
> +      # Get compiler emitted messages and delete generated file.
> +      set lines [lindex $result 0]
> +      set output [lindex $result 1]
> +      remote_file build delete $output
> +
> +      # Capture the vectorized info of v2qi, set it to zero if not found.
> +	if { ![regexp $pattern $lines whole val] } then {
> +	  set val 0
> +      }
> +
> +      return $val
> +    }]
> +}
> +
> +# Return the true if target support vectorization of v2qi store.
> +proc check_effective_target_vect_slp_v2qi_store { } {
> +    set pattern {add new stmt: MEM <vector\(2\) char>}
> +    return [expr { [check_vect_slp_vnqihi_store_usage $pattern ] != 0 }]
> +}
> +
> +# Return the true if target support vectorization of v4qi store.
> +proc check_effective_target_vect_slp_v4qi_store { } {
> +    set pattern {add new stmt: MEM <vector\(4\) char>}
> +    return [expr { [check_vect_slp_vnqihi_store_usage $pattern ] != 0 }]
> +}
> +
> +# Return the true if target support vectorization of v2qi store.
> +proc check_effective_target_vect_slp_v8qi_store { } {
> +    set pattern {add new stmt: MEM <vector\(8\) char>}
> +    return [expr { [check_vect_slp_vnqihi_store_usage $pattern ] != 0 }]
> +}
> +
> +# Return the true if target support vectorization of v4qi store.
> +proc check_effective_target_vect_slp_v16qi_store { } {
> +    set pattern {add new stmt: MEM <vector\(16\) char>}
> +    return [expr { [check_vect_slp_vnqihi_store_usage $pattern ] != 0 }]
> +}
> +
> +# Return the true if target support vectorization of v2hi store.
> +proc check_effective_target_vect_slp_v2hi_store { } {
> +    set pattern {add new stmt: MEM <vector\(2\) short int>}
> +    return [expr { [check_vect_slp_vnqihi_store_usage $pattern ] != 0 }]
> +}
> +
> +# Return the true if target support vectorization of v2hi store.
> +proc check_effective_target_vect_slp_v4hi_store { } {
> +    set pattern {add new stmt: MEM <vector\(4\) short int>}
> +    return [expr { [check_vect_slp_vnqihi_store_usage $pattern ] != 0 }]
> +}
> +
>  # Return 1 if we can align stack data to the preferred vector alignment.
>  
>  proc check_effective_target_vect_align_stack_vars { } {
>
  
Kewen.Lin Oct. 15, 2021, 7:11 a.m. UTC | #3
on 2021/10/14 下午6:56, Kewen.Lin via Gcc-patches wrote:
> Hi Hongtao,
> 
> on 2021/10/14 下午3:11, liuhongt wrote:
>> Hi Kewen:
>>   Cound you help to verify if this patch fix those regressions
>> for rs6000 port.
>>
> 
> The ppc64le run just finished, there are still some regresssions:
> 
> NA->XPASS: c-c++-common/Wstringop-overflow-2.c  -Wc++-compat   (test for warnings, line 194)
> NA->XPASS: c-c++-common/Wstringop-overflow-2.c  -Wc++-compat   (test for warnings, line 212)
> NA->XPASS: c-c++-common/Wstringop-overflow-2.c  -Wc++-compat   (test for warnings, line 296)
> NA->XPASS: c-c++-common/Wstringop-overflow-2.c  -Wc++-compat   (test for warnings, line 314)
> NA->FAIL: gcc.dg/Wstringop-overflow-21-novec.c (test for excess errors)
> NA->FAIL: gcc.dg/Wstringop-overflow-21-novec.c  (test for warnings, line 18)
> NA->FAIL: gcc.dg/Wstringop-overflow-21-novec.c  (test for warnings, line 29)
> NA->FAIL: gcc.dg/Wstringop-overflow-21-novec.c  (test for warnings, line 45)
> NA->FAIL: gcc.dg/Wstringop-overflow-21-novec.c  (test for warnings, line 55)
> NA->FAIL: gcc.dg/Wstringop-overflow-76-novec.c note (test for warnings, line 104)
> NA->FAIL: gcc.dg/Wstringop-overflow-76-novec.c note (test for warnings, line 137)
> NA->FAIL: gcc.dg/Wstringop-overflow-76-novec.c note (test for warnings, line 19)
> NA->FAIL: gcc.dg/Wstringop-overflow-76-novec.c note (test for warnings, line 39)
> NA->FAIL: gcc.dg/Wstringop-overflow-76-novec.c note (test for warnings, line 56)
> NA->FAIL: gcc.dg/Wstringop-overflow-76-novec.c note (test for warnings, line 70)
> NA->FAIL: gcc.dg/Wstringop-overflow-76-novec.c (test for excess errors)
> NA->FAIL: gcc.dg/Wstringop-overflow-76-novec.c  (test for warnings, line 116)
> NA->FAIL: gcc.dg/Wstringop-overflow-76-novec.c  (test for warnings, line 131)
> NA->FAIL: gcc.dg/Wstringop-overflow-76-novec.c  (test for warnings, line 146)
> NA->FAIL: gcc.dg/Wstringop-overflow-76-novec.c  (test for warnings, line 33)
> NA->FAIL: gcc.dg/Wstringop-overflow-76-novec.c  (test for warnings, line 50)
> NA->FAIL: gcc.dg/Wstringop-overflow-76-novec.c  (test for warnings, line 64)
> NA->FAIL: gcc.dg/Wstringop-overflow-76-novec.c  (test for warnings, line 78)
> NA->FAIL: gcc.dg/Wstringop-overflow-76-novec.c  (test for warnings, line 97)
> PASS->FAIL: c-c++-common/Wstringop-overflow-2.c  -std=gnu++14 (test for excess errors)
> NA->FAIL: c-c++-common/Wstringop-overflow-2.c  -std=gnu++14  (test for warnings, line 229)
> NA->FAIL: c-c++-common/Wstringop-overflow-2.c  -std=gnu++14  (test for warnings, line 230)
> NA->FAIL: c-c++-common/Wstringop-overflow-2.c  -std=gnu++14  (test for warnings, line 331)
> NA->FAIL: c-c++-common/Wstringop-overflow-2.c  -std=gnu++14  (test for warnings, line 332)
> // omitting -std=gnu++17, -std=gnu++2a, -std=gnu++98
> 
> I'll have a look and get back to you tomorrow.
> 

The failure c-c++-common/Wstringop-overflow-2.c is due to that the
current proc check_vect_slp_vnqihi_store_usage is made as "cache"
but it can vary for different input patterns.  For rs6000 the test
for v2qi fails, the cached test result makes v4qi check fail
unexpectedly (should pass).  I adjusted caching for the following users
check_effective_target_vect_slp_v*_store, also refactored a bit.
One trivial change is to add one new argument macro then we can just
compile the corresponding foo* function instead of all, hope it helps
to make the debugging outputs compact.

For the failure Wstringop-overflow-76-novec.c, there is one typo
comparing to the original Wstringop-overflow-76.c.  Guess it failed
on x86 too?  It would be surprising if it passes on x86.
As to the failure Wstringop-overflow-21-novec.c, I confirmed it's
just noise, patching typos caused this failure.

One new round ppc64le testing just finished with below diff and all
previous regressions are fixed without any new regressions.


diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-76-novec.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-76-novec.c
index d000b587a65..1132348c5f4 100644
--- a/gcc/testsuite/gcc.dg/Wstringop-overflow-76-novec.c
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-76-novec.c
@@ -82,7 +82,7 @@ void max_d8_p (char *q, int i)
 struct A3_5
 {
   char a3[3];  // { dg-message "at offset 3 into destination object 'a3' of size 3" "pr??????" { xfail *-*-* } }
-  char a5[5];
+  char a5[5];  // { dg-message "at offset 5 into destination object 'a5' of size 5" "note" }
 };

 void max_A3_A5 (int i, struct A3_5 *pa3_5)
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index 530c5769614..8736b908ec7 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -7584,12 +7584,13 @@ proc check_effective_target_vect_element_align_preferred { } {
 # Return zero if the desirable pattern isn't found.
 # It's used by Warray-bounds/Wstringop-overflow testcases which are
 # regressed by O2 vectorization, refer to PR102697/PR102462/PR102706
-proc check_vect_slp_vnqihi_store_usage { pattern } {
+proc check_vect_slp_vnqihi_store_usage { pattern macro } {
     global tool

-    return [check_cached_effective_target slp_vnqihi_store_usage {
-      set result [check_compile slp_vnqihi_store_usage assembly {
+    set result [check_compile slp_vnqihi_store_usage assembly {
 	  char a[16] __attribute__ ((aligned (16)));
+	  short b[4] __attribute__((aligned(8)));
+	  #ifdef TEST_V8QI
 	  void
 	  foo ()
 	  {
@@ -7602,7 +7603,7 @@ proc check_vect_slp_vnqihi_store_usage { pattern } {
 	      a[6] = 6;
 	      a[7] = 7;
 	  }
-
+	  #elif TEST_V16QI
 	  void
 	  foo1 ()
 	  {
@@ -7623,7 +7624,7 @@ proc check_vect_slp_vnqihi_store_usage { pattern } {
 	      a[14] = 14;
 	      a[15] = 15;
 	  }
-
+	  #elif TEST_V4QI
 	  void
 	  foo2 ()
 	  {
@@ -7632,22 +7633,21 @@ proc check_vect_slp_vnqihi_store_usage { pattern } {
 	      a[2] = 2;
 	      a[3] = 3;
 	  }
-
+	  #elif TEST_V2QI
 	  void
 	  foo3 ()
 	  {
 	      a[0] = 0;
 	      a[1] = 1;
 	  }
-
-	  short b[4] __attribute__((aligned(8)));
+	  #elif TEST_V2HI
 	  void
 	  foo4 ()
 	  {
 	      b[0] = 0;
 	      b[1] = 1;
 	  }
-
+	  #elif TEST_V4HI
 	  void
 	  foo5 ()
 	  {
@@ -7656,57 +7656,69 @@ proc check_vect_slp_vnqihi_store_usage { pattern } {
 	      b[2] = 2;
 	      b[3] = 3;
 	  }
+	  #endif

-      } "-O2 -fopt-info-all" ]
+      } "-O2 -fopt-info-all -D$macro" ]

       # Get compiler emitted messages and delete generated file.
       set lines [lindex $result 0]
       set output [lindex $result 1]
       remote_file build delete $output

-      # Capture the vectorized info of v2qi, set it to zero if not found.
-	if { ![regexp $pattern $lines whole val] } then {
-	  set val 0
+      # Check pattern exits in lines, set it to zero if not found.
+      if { [regexp $pattern $lines] } then {
+	 return 1
       }

-      return $val
-    }]
+      return 0
 }

 # Return the true if target support vectorization of v2qi store.
 proc check_effective_target_vect_slp_v2qi_store { } {
     set pattern {add new stmt: MEM <vector\(2\) char>}
-    return [expr { [check_vect_slp_vnqihi_store_usage $pattern ] != 0 }]
+    set macro "TEST_V2QI"
+    return [check_cached_effective_target vect_slp_v2qi_store {
+	    expr [check_vect_slp_vnqihi_store_usage $pattern $macro] }]
 }

 # Return the true if target support vectorization of v4qi store.
 proc check_effective_target_vect_slp_v4qi_store { } {
     set pattern {add new stmt: MEM <vector\(4\) char>}
-    return [expr { [check_vect_slp_vnqihi_store_usage $pattern ] != 0 }]
+    set macro "TEST_V4QI"
+    return [check_cached_effective_target vect_slp_v4qi_store {
+	    expr [check_vect_slp_vnqihi_store_usage $pattern $macro ] }]
 }

-# Return the true if target support vectorization of v2qi store.
+# Return the true if target support vectorization of v8qi store.
 proc check_effective_target_vect_slp_v8qi_store { } {
     set pattern {add new stmt: MEM <vector\(8\) char>}
-    return [expr { [check_vect_slp_vnqihi_store_usage $pattern ] != 0 }]
+    set macro "TEST_V8QI"
+    return [check_cached_effective_target_vect_slp_v8qi_store {
+	    expr [check_vect_slp_vnqihi_store_usage $pattern $macro ] }]
 }

-# Return the true if target support vectorization of v4qi store.
+# Return the true if target support vectorization of v16qi store.
 proc check_effective_target_vect_slp_v16qi_store { } {
     set pattern {add new stmt: MEM <vector\(16\) char>}
-    return [expr { [check_vect_slp_vnqihi_store_usage $pattern ] != 0 }]
+    set macro "TEST_V16QI"
+    return [check_cached_effective_target_vect_slp_v16qi_store {
+	    expr [check_vect_slp_vnqihi_store_usage $pattern $macro ] }]
 }

 # Return the true if target support vectorization of v2hi store.
 proc check_effective_target_vect_slp_v2hi_store { } {
     set pattern {add new stmt: MEM <vector\(2\) short int>}
-    return [expr { [check_vect_slp_vnqihi_store_usage $pattern ] != 0 }]
+    set macro "TEST_V2HI"
+    return [check_cached_effective_target_vect_slp_v2hi_store {
+	    expr [check_vect_slp_vnqihi_store_usage $pattern $macro ] }]
 }

-# Return the true if target support vectorization of v2hi store.
+# Return the true if target support vectorization of v4hi store.
 proc check_effective_target_vect_slp_v4hi_store { } {
     set pattern {add new stmt: MEM <vector\(4\) short int>}
-    return [expr { [check_vect_slp_vnqihi_store_usage $pattern ] != 0 }]
+    set macro "TEST_V4HI"
+    return [check_cached_effective_target_vect_slp_v4hi_store {
+	    expr [check_vect_slp_vnqihi_store_usage $pattern $macro ] }]
 }



BR,
Kewen
  
Martin Sebor Oct. 15, 2021, 3:37 p.m. UTC | #4
On 10/14/21 1:11 AM, liuhongt wrote:
> Hi Kewen:
>    Cound you help to verify if this patch fix those regressions
> for rs6000 port.
> 
> 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.

Just to make sure I understand what's happening with the tests:
the new -N-novec.c tests consist of just the casses xfailed due
to vectorizartion in the corresponding -N.c tests?  Or are there
some other differences (e.g., new cases in them, etc.)?  I'd
hope to eventually remove the -novec.c tests once all warnings
behave as expected with vectorization as without it (maybe
keeping just one case both ways as a sanity check).

For the target-supports selectors, I confess I don't know enough
about vectorization to find their names quite intuitive enough
to know when to use each.  For instance, for vect_slp_v4qi_store:

+# Return the true if target support vectorization of v4qi store.
+proc check_effective_target_vect_slp_v4qi_store { } {
+    set pattern {add new stmt: MEM <vector\(4\) char>}
+    return [expr { [check_vect_slp_vnqihi_store_usage $pattern ] != 0 }]
+}

When should this selector be used?  In cases involving 4-byte
char stores?  Only naturally aligned 4-bytes stores (i.e., on
a 4 byte boundary, as the check_vect_slp_vnqihi_store_usage
suggests?) Or 4-byte stores of any types (e.g., four chars
as well as two 16-bit shorts), etc.?

Hopefully once all the warnings handle vectorization we won't
need to use them, but until then it would be good to document
this in more detail in the .exp file.

Finally, thank you for adding comments to the xfailed tests
referencing the corresponding bugs!  Can you please mention
the PR in the comment in each of the new xfails?  Like so:

index 7d29b5f48c7..cb687c69324 100644
--- a/gcc/testsuite/c-c++-common/Wstringop-overflow-2.c
+++ b/gcc/testsuite/c-c++-common/Wstringop-overflow-2.c
@@ -189,8 +189,9 @@ void ga1__ (void)

    struct A1 a = { 1 };
    a.a[0] = 0;
+  // O2 vectorization regress Wstringop-overflow case (1), refer to 
pr102462.
    a.a[1] = 1;                    // { dg-warning 
"\\\[-Wstringop-overflow" }
-  a.a[2] = 2;                    // { dg-warning 
"\\\[-Wstringop-overflow" "" { xfail { i?86-*-* x86_64-*-* } } }
+  a.a[2] = 2;                    // { dg-warning 
"\\\[-Wstringop-overflow" "pr102462" { xfail { vect_slp_v2qi_store } } }
            ^^^^^^^^
            PR in dg-warning comment.

This should make it easier to deal with the XFAILs once
the warnings have improved to handle vectorization.

Martin
  
Hongtao Liu Oct. 18, 2021, 4:38 a.m. UTC | #5
On Fri, Oct 15, 2021 at 11:37 PM Martin Sebor <msebor@gmail.com> wrote:
>
> On 10/14/21 1:11 AM, liuhongt wrote:
> > Hi Kewen:
> >    Cound you help to verify if this patch fix those regressions
> > for rs6000 port.
> >
> > 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.
>
> Just to make sure I understand what's happening with the tests:
> the new -N-novec.c tests consist of just the casses xfailed due
> to vectorizartion in the corresponding -N.c tests?  Or are there
Wstringop-overflow-2-novec.c is the same as Wstringop-overflow-2.c
before O2 vectorization adjustment.
Do you want me to reduce them to only contain cases for new xfail/target?
> some other differences (e.g., new cases in them, etc.)?  I'd
> hope to eventually remove the -novec.c tests once all warnings
> behave as expected with vectorization as without it (maybe
> keeping just one case both ways as a sanity check).
>
> For the target-supports selectors, I confess I don't know enough
> about vectorization to find their names quite intuitive enough
> to know when to use each.  For instance, for vect_slp_v4qi_store:
It's 4-byte char stores with address being 4-bytes aligned.
.i.e.

>
> +# Return the true if target support vectorization of v4qi store.
> +proc check_effective_target_vect_slp_v4qi_store { } {
> +    set pattern {add new stmt: MEM <vector\(4\) char>}
> +    return [expr { [check_vect_slp_vnqihi_store_usage $pattern ] != 0 }]
> +}
>
> When should this selector be used?  In cases involving 4-byte
> char stores?  Only naturally aligned 4-bytes stores (i.e., on
> a 4 byte boundary, as the check_vect_slp_vnqihi_store_usage
> suggests?) Or 4-byte stores of any types (e.g., four chars
> as well as two 16-bit shorts), etc.?
>
> Hopefully once all the warnings handle vectorization we won't
> need to use them, but until then it would be good to document
> this in more detail in the .exp file.
>
> Finally, thank you for adding comments to the xfailed tests
> referencing the corresponding bugs!  Can you please mention
> the PR in the comment in each of the new xfails?  Like so:
>
> index 7d29b5f48c7..cb687c69324 100644
> --- a/gcc/testsuite/c-c++-common/Wstringop-overflow-2.c
> +++ b/gcc/testsuite/c-c++-common/Wstringop-overflow-2.c
> @@ -189,8 +189,9 @@ void ga1__ (void)
>
>     struct A1 a = { 1 };
>     a.a[0] = 0;
> +  // O2 vectorization regress Wstringop-overflow case (1), refer to
> pr102462.
>     a.a[1] = 1;                    // { dg-warning
> "\\\[-Wstringop-overflow" }
> -  a.a[2] = 2;                    // { dg-warning
> "\\\[-Wstringop-overflow" "" { xfail { i?86-*-* x86_64-*-* } } }
> +  a.a[2] = 2;                    // { dg-warning
> "\\\[-Wstringop-overflow" "pr102462" { xfail { vect_slp_v2qi_store } } }
>             ^^^^^^^^
>             PR in dg-warning comment.
>
> This should make it easier to deal with the XFAILs once
> the warnings have improved to handle vectorization.
Will do.
>
> Martin
  
Hongtao Liu Oct. 18, 2021, 4:47 a.m. UTC | #6
On Fri, Oct 15, 2021 at 3:11 PM Kewen.Lin via Gcc-patches
<gcc-patches@gcc.gnu.org> wrote:
>
> on 2021/10/14 下午6:56, Kewen.Lin via Gcc-patches wrote:
> > Hi Hongtao,
> >
> > on 2021/10/14 下午3:11, liuhongt wrote:
> >> Hi Kewen:
> >>   Cound you help to verify if this patch fix those regressions
> >> for rs6000 port.
> >>
> >
> > The ppc64le run just finished, there are still some regresssions:
> >
> > NA->XPASS: c-c++-common/Wstringop-overflow-2.c  -Wc++-compat   (test for warnings, line 194)
> > NA->XPASS: c-c++-common/Wstringop-overflow-2.c  -Wc++-compat   (test for warnings, line 212)
> > NA->XPASS: c-c++-common/Wstringop-overflow-2.c  -Wc++-compat   (test for warnings, line 296)
> > NA->XPASS: c-c++-common/Wstringop-overflow-2.c  -Wc++-compat   (test for warnings, line 314)
> > NA->FAIL: gcc.dg/Wstringop-overflow-21-novec.c (test for excess errors)
> > NA->FAIL: gcc.dg/Wstringop-overflow-21-novec.c  (test for warnings, line 18)
> > NA->FAIL: gcc.dg/Wstringop-overflow-21-novec.c  (test for warnings, line 29)
> > NA->FAIL: gcc.dg/Wstringop-overflow-21-novec.c  (test for warnings, line 45)
> > NA->FAIL: gcc.dg/Wstringop-overflow-21-novec.c  (test for warnings, line 55)
> > NA->FAIL: gcc.dg/Wstringop-overflow-76-novec.c note (test for warnings, line 104)
> > NA->FAIL: gcc.dg/Wstringop-overflow-76-novec.c note (test for warnings, line 137)
> > NA->FAIL: gcc.dg/Wstringop-overflow-76-novec.c note (test for warnings, line 19)
> > NA->FAIL: gcc.dg/Wstringop-overflow-76-novec.c note (test for warnings, line 39)
> > NA->FAIL: gcc.dg/Wstringop-overflow-76-novec.c note (test for warnings, line 56)
> > NA->FAIL: gcc.dg/Wstringop-overflow-76-novec.c note (test for warnings, line 70)
> > NA->FAIL: gcc.dg/Wstringop-overflow-76-novec.c (test for excess errors)
> > NA->FAIL: gcc.dg/Wstringop-overflow-76-novec.c  (test for warnings, line 116)
> > NA->FAIL: gcc.dg/Wstringop-overflow-76-novec.c  (test for warnings, line 131)
> > NA->FAIL: gcc.dg/Wstringop-overflow-76-novec.c  (test for warnings, line 146)
> > NA->FAIL: gcc.dg/Wstringop-overflow-76-novec.c  (test for warnings, line 33)
> > NA->FAIL: gcc.dg/Wstringop-overflow-76-novec.c  (test for warnings, line 50)
> > NA->FAIL: gcc.dg/Wstringop-overflow-76-novec.c  (test for warnings, line 64)
> > NA->FAIL: gcc.dg/Wstringop-overflow-76-novec.c  (test for warnings, line 78)
> > NA->FAIL: gcc.dg/Wstringop-overflow-76-novec.c  (test for warnings, line 97)
> > PASS->FAIL: c-c++-common/Wstringop-overflow-2.c  -std=gnu++14 (test for excess errors)
> > NA->FAIL: c-c++-common/Wstringop-overflow-2.c  -std=gnu++14  (test for warnings, line 229)
> > NA->FAIL: c-c++-common/Wstringop-overflow-2.c  -std=gnu++14  (test for warnings, line 230)
> > NA->FAIL: c-c++-common/Wstringop-overflow-2.c  -std=gnu++14  (test for warnings, line 331)
> > NA->FAIL: c-c++-common/Wstringop-overflow-2.c  -std=gnu++14  (test for warnings, line 332)
> > // omitting -std=gnu++17, -std=gnu++2a, -std=gnu++98
> >
> > I'll have a look and get back to you tomorrow.
> >
>
> The failure c-c++-common/Wstringop-overflow-2.c is due to that the
> current proc check_vect_slp_vnqihi_store_usage is made as "cache"
> but it can vary for different input patterns.  For rs6000 the test
> for v2qi fails, the cached test result makes v4qi check fail
> unexpectedly (should pass).  I adjusted caching for the following users
> check_effective_target_vect_slp_v*_store, also refactored a bit.
> One trivial change is to add one new argument macro then we can just
> compile the corresponding foo* function instead of all, hope it helps
> to make the debugging outputs compact.
>
> For the failure Wstringop-overflow-76-novec.c, there is one typo
> comparing to the original Wstringop-overflow-76.c.  Guess it failed
> on x86 too?  It would be surprising if it passes on x86.
> As to the failure Wstringop-overflow-21-novec.c, I confirmed it's
> just noise, patching typos caused this failure.
Thanks for the explanation for  those failures and the typo, i'll
adjust the patch.
>
> One new round ppc64le testing just finished with below diff and all
> previous regressions are fixed without any new regressions.
>
>
> diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-76-novec.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-76-novec.c
> index d000b587a65..1132348c5f4 100644
> --- a/gcc/testsuite/gcc.dg/Wstringop-overflow-76-novec.c
> +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-76-novec.c
> @@ -82,7 +82,7 @@ void max_d8_p (char *q, int i)
>  struct A3_5
>  {
>    char a3[3];  // { dg-message "at offset 3 into destination object 'a3' of size 3" "pr??????" { xfail *-*-* } }
> -  char a5[5];
> +  char a5[5];  // { dg-message "at offset 5 into destination object 'a5' of size 5" "note" }
>  };
>
>  void max_A3_A5 (int i, struct A3_5 *pa3_5)
> diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
> index 530c5769614..8736b908ec7 100644
> --- a/gcc/testsuite/lib/target-supports.exp
> +++ b/gcc/testsuite/lib/target-supports.exp
> @@ -7584,12 +7584,13 @@ proc check_effective_target_vect_element_align_preferred { } {
>  # Return zero if the desirable pattern isn't found.
>  # It's used by Warray-bounds/Wstringop-overflow testcases which are
>  # regressed by O2 vectorization, refer to PR102697/PR102462/PR102706
> -proc check_vect_slp_vnqihi_store_usage { pattern } {
> +proc check_vect_slp_vnqihi_store_usage { pattern macro } {
>      global tool
>
> -    return [check_cached_effective_target slp_vnqihi_store_usage {
> -      set result [check_compile slp_vnqihi_store_usage assembly {
> +    set result [check_compile slp_vnqihi_store_usage assembly {
>           char a[16] __attribute__ ((aligned (16)));
> +         short b[4] __attribute__((aligned(8)));
> +         #ifdef TEST_V8QI
>           void
>           foo ()
>           {
> @@ -7602,7 +7603,7 @@ proc check_vect_slp_vnqihi_store_usage { pattern } {
>               a[6] = 6;
>               a[7] = 7;
>           }
> -
> +         #elif TEST_V16QI
>           void
>           foo1 ()
>           {
> @@ -7623,7 +7624,7 @@ proc check_vect_slp_vnqihi_store_usage { pattern } {
>               a[14] = 14;
>               a[15] = 15;
>           }
> -
> +         #elif TEST_V4QI
>           void
>           foo2 ()
>           {
> @@ -7632,22 +7633,21 @@ proc check_vect_slp_vnqihi_store_usage { pattern } {
>               a[2] = 2;
>               a[3] = 3;
>           }
> -
> +         #elif TEST_V2QI
>           void
>           foo3 ()
>           {
>               a[0] = 0;
>               a[1] = 1;
>           }
> -
> -         short b[4] __attribute__((aligned(8)));
> +         #elif TEST_V2HI
>           void
>           foo4 ()
>           {
>               b[0] = 0;
>               b[1] = 1;
>           }
> -
> +         #elif TEST_V4HI
>           void
>           foo5 ()
>           {
> @@ -7656,57 +7656,69 @@ proc check_vect_slp_vnqihi_store_usage { pattern } {
>               b[2] = 2;
>               b[3] = 3;
>           }
> +         #endif
>
> -      } "-O2 -fopt-info-all" ]
> +      } "-O2 -fopt-info-all -D$macro" ]
>
>        # Get compiler emitted messages and delete generated file.
>        set lines [lindex $result 0]
>        set output [lindex $result 1]
>        remote_file build delete $output
>
> -      # Capture the vectorized info of v2qi, set it to zero if not found.
> -       if { ![regexp $pattern $lines whole val] } then {
> -         set val 0
> +      # Check pattern exits in lines, set it to zero if not found.
> +      if { [regexp $pattern $lines] } then {
> +        return 1
>        }
>
> -      return $val
> -    }]
> +      return 0
>  }
>
>  # Return the true if target support vectorization of v2qi store.
>  proc check_effective_target_vect_slp_v2qi_store { } {
>      set pattern {add new stmt: MEM <vector\(2\) char>}
> -    return [expr { [check_vect_slp_vnqihi_store_usage $pattern ] != 0 }]
> +    set macro "TEST_V2QI"
> +    return [check_cached_effective_target vect_slp_v2qi_store {
> +           expr [check_vect_slp_vnqihi_store_usage $pattern $macro] }]
>  }
>
>  # Return the true if target support vectorization of v4qi store.
>  proc check_effective_target_vect_slp_v4qi_store { } {
>      set pattern {add new stmt: MEM <vector\(4\) char>}
> -    return [expr { [check_vect_slp_vnqihi_store_usage $pattern ] != 0 }]
> +    set macro "TEST_V4QI"
> +    return [check_cached_effective_target vect_slp_v4qi_store {
> +           expr [check_vect_slp_vnqihi_store_usage $pattern $macro ] }]
>  }
>
> -# Return the true if target support vectorization of v2qi store.
> +# Return the true if target support vectorization of v8qi store.
>  proc check_effective_target_vect_slp_v8qi_store { } {
>      set pattern {add new stmt: MEM <vector\(8\) char>}
> -    return [expr { [check_vect_slp_vnqihi_store_usage $pattern ] != 0 }]
> +    set macro "TEST_V8QI"
> +    return [check_cached_effective_target_vect_slp_v8qi_store {
> +           expr [check_vect_slp_vnqihi_store_usage $pattern $macro ] }]
>  }
>
> -# Return the true if target support vectorization of v4qi store.
> +# Return the true if target support vectorization of v16qi store.
>  proc check_effective_target_vect_slp_v16qi_store { } {
>      set pattern {add new stmt: MEM <vector\(16\) char>}
> -    return [expr { [check_vect_slp_vnqihi_store_usage $pattern ] != 0 }]
> +    set macro "TEST_V16QI"
> +    return [check_cached_effective_target_vect_slp_v16qi_store {
> +           expr [check_vect_slp_vnqihi_store_usage $pattern $macro ] }]
>  }
>
>  # Return the true if target support vectorization of v2hi store.
>  proc check_effective_target_vect_slp_v2hi_store { } {
>      set pattern {add new stmt: MEM <vector\(2\) short int>}
> -    return [expr { [check_vect_slp_vnqihi_store_usage $pattern ] != 0 }]
> +    set macro "TEST_V2HI"
> +    return [check_cached_effective_target_vect_slp_v2hi_store {
> +           expr [check_vect_slp_vnqihi_store_usage $pattern $macro ] }]
>  }
>
> -# Return the true if target support vectorization of v2hi store.
> +# Return the true if target support vectorization of v4hi store.
>  proc check_effective_target_vect_slp_v4hi_store { } {
>      set pattern {add new stmt: MEM <vector\(4\) short int>}
> -    return [expr { [check_vect_slp_vnqihi_store_usage $pattern ] != 0 }]
> +    set macro "TEST_V4HI"
> +    return [check_cached_effective_target_vect_slp_v4hi_store {
> +           expr [check_vect_slp_vnqihi_store_usage $pattern $macro ] }]
>  }
>
>
>
> BR,
> Kewen
  
Martin Sebor Oct. 18, 2021, 3:11 p.m. UTC | #7
On 10/17/21 10:38 PM, Hongtao Liu wrote:
> On Fri, Oct 15, 2021 at 11:37 PM Martin Sebor <msebor@gmail.com> wrote:
>>
>> On 10/14/21 1:11 AM, liuhongt wrote:
>>> Hi Kewen:
>>>     Cound you help to verify if this patch fix those regressions
>>> for rs6000 port.
>>>
>>> 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.
>>
>> Just to make sure I understand what's happening with the tests:
>> the new -N-novec.c tests consist of just the casses xfailed due
>> to vectorizartion in the corresponding -N.c tests?  Or are there
> Wstringop-overflow-2-novec.c is the same as Wstringop-overflow-2.c
> before O2 vectorization adjustment.
> Do you want me to reduce them to only contain cases for new xfail/target?

That would be helpful, thank you.  Are the others also full
copies? (If yes, then copying just the failing cases into
the new tests would be good as well.)

>> some other differences (e.g., new cases in them, etc.)?  I'd
>> hope to eventually remove the -novec.c tests once all warnings
>> behave as expected with vectorization as without it (maybe
>> keeping just one case both ways as a sanity check).
>>
>> For the target-supports selectors, I confess I don't know enough
>> about vectorization to find their names quite intuitive enough
>> to know when to use each.  For instance, for vect_slp_v4qi_store:
> It's 4-byte char stores with address being 4-bytes aligned.
> .i.e.
> 
>>
>> +# Return the true if target support vectorization of v4qi store.
>> +proc check_effective_target_vect_slp_v4qi_store { } {
>> +    set pattern {add new stmt: MEM <vector\(4\) char>}
>> +    return [expr { [check_vect_slp_vnqihi_store_usage $pattern ] != 0 }]
>> +}
>>
>> When should this selector be used?  In cases involving 4-byte
>> char stores?  Only naturally aligned 4-bytes stores (i.e., on
>> a 4 byte boundary, as the check_vect_slp_vnqihi_store_usage
>> suggests?) Or 4-byte stores of any types (e.g., four chars
>> as well as two 16-bit shorts), etc.?
>>
>> Hopefully once all the warnings handle vectorization we won't
>> need to use them, but until then it would be good to document
>> this in more detail in the .exp file.
>>
>> Finally, thank you for adding comments to the xfailed tests
>> referencing the corresponding bugs!  Can you please mention
>> the PR in the comment in each of the new xfails?  Like so:
>>
>> index 7d29b5f48c7..cb687c69324 100644
>> --- a/gcc/testsuite/c-c++-common/Wstringop-overflow-2.c
>> +++ b/gcc/testsuite/c-c++-common/Wstringop-overflow-2.c
>> @@ -189,8 +189,9 @@ void ga1__ (void)
>>
>>      struct A1 a = { 1 };
>>      a.a[0] = 0;
>> +  // O2 vectorization regress Wstringop-overflow case (1), refer to
>> pr102462.
>>      a.a[1] = 1;                    // { dg-warning
>> "\\\[-Wstringop-overflow" }
>> -  a.a[2] = 2;                    // { dg-warning
>> "\\\[-Wstringop-overflow" "" { xfail { i?86-*-* x86_64-*-* } } }
>> +  a.a[2] = 2;                    // { dg-warning
>> "\\\[-Wstringop-overflow" "pr102462" { xfail { vect_slp_v2qi_store } } }
>>              ^^^^^^^^
>>              PR in dg-warning comment.
>>
>> This should make it easier to deal with the XFAILs once
>> the warnings have improved to handle vectorization.
> Will do.

Great, thank you!

Martin
  

Patch

diff --git a/gcc/testsuite/c-c++-common/Wstringop-overflow-2-novec.c b/gcc/testsuite/c-c++-common/Wstringop-overflow-2-novec.c
new file mode 100644
index 00000000000..89e6a5c12c2
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Wstringop-overflow-2-novec.c
@@ -0,0 +1,348 @@ 
+/* PR middle-end/91458 - inconsistent warning for writing past the end
+   of an array member
+   { dg-do compile }
+   { dg-options "-O2 -fno-tree-vectorize -Wall -Wno-array-bounds -fno-ipa-icf" } */
+
+void sink (void*);
+
+// Exercise flexible array members.
+
+struct Ax
+{
+  char n;
+  char a[];                     // { dg-message "destination object" "note" }
+};
+
+// Verify warning for a definition with no initializer.
+struct Ax ax_;
+
+void gax_ (void)
+{
+  ax_.a[0] = 0;                 // { dg-warning "\\\[-Wstringop-overflow" }
+  ax_.a[1] = 1;                 // { dg-warning "\\\[-Wstringop-overflow" }
+  ax_.a[2] = 2;                 // { dg-warning "\\\[-Wstringop-overflow" }
+}
+
+// Verify warning for access to a definition with an initializer that doesn't
+// initialize the flexible array member.
+struct Ax ax0 = { 0 };
+
+void gax0 (void)
+{
+  ax0.a[0] = 0;                 // { dg-warning "\\\[-Wstringop-overflow" }
+  ax0.a[1] = 1;                 // { dg-warning "\\\[-Wstringop-overflow" }
+  ax0.a[2] = 2;                 // { dg-warning "\\\[-Wstringop-overflow" }
+}
+
+// Verify warning for access to a definition with an initializer that
+// initializes the flexible array member to empty.
+struct Ax ax0_ = { 0, { } };
+
+void gax0_ (void)
+{
+  ax0_.a[0] = 0;                // { dg-warning "\\\[-Wstringop-overflow" }
+  ax0_.a[1] = 1;                // { dg-warning "\\\[-Wstringop-overflow" }
+  ax0_.a[2] = 2;                // { dg-warning "\\\[-Wstringop-overflow" }
+}
+
+// Verify warning for out-of-bounds accesses to a definition with
+// an initializer.
+struct Ax ax1 = { 1, { 0 } };
+
+void gax1 (void)
+{
+  ax1.a[0] = 0;
+  ax1.a[1] = 1;                 // { dg-warning "\\\[-Wstringop-overflow" }
+  ax1.a[2] = 2;                 // { dg-warning "\\\[-Wstringop-overflow" }
+}
+
+struct Ax ax2 = { 2, { 1, 0 } };
+
+void gax2 (void)
+{
+  ax2.a[0] = 0;
+  ax2.a[1] = 1;
+  ax2.a[2] = 2;                 // { dg-warning "\\\[-Wstringop-overflow" }
+}
+
+
+// Verify no warning for an unknown struct object.
+void gaxp (struct Ax *p)
+{
+  p->a[0] = 0;
+  p->a[3] = 3;
+  p->a[9] = 9;
+}
+
+
+// Verify no warning for an extern struct object whose array may be
+// initialized to any number of elements.
+extern struct Ax axx;
+
+void gaxx (void)
+{
+  axx.a[0] = 0;
+  axx.a[3] = 3;
+  axx.a[9] = 9;
+}
+
+// Exercise zero-length array members.
+
+struct A0
+{
+  char n;
+  char a[0];                    // { dg-message "destination object" "note" }
+};
+
+// Verify warning for a definition with no initializer.
+struct A0 a0_;
+
+void ga0_ (void)
+{
+  a0_.a[0] = 0;                 // { dg-warning "\\\[-Wstringop-overflow" }
+  a0_.a[1] = 1;                 // { dg-warning "\\\[-Wstringop-overflow" }
+  a0_.a[2] = 2;                 // { dg-warning "\\\[-Wstringop-overflow" }
+}
+
+// Verify warning for access to a definition with an initializer that doesn't
+// initialize the flexible array member.
+struct A0 a00 = { 0 };
+
+void ga00 (void)
+{
+  a00.a[0] = 0;                 // { dg-warning "\\\[-Wstringop-overflow" }
+  a00.a[1] = 1;                 // { dg-warning "\\\[-Wstringop-overflow" }
+  a00.a[2] = 2;                 // { dg-warning "\\\[-Wstringop-overflow" }
+}
+
+// Verify warning for access to a definition with an initializer that
+// initializes the flexible array member to empty.
+struct A0 a00_ = { 0, { } };
+
+void ga00_ (void)
+{
+  a00_.a[0] = 0;                // { dg-warning "\\\[-Wstringop-overflow" }
+  a00_.a[1] = 1;                // { dg-warning "\\\[-Wstringop-overflow" }
+  a00_.a[2] = 2;                // { dg-warning "\\\[-Wstringop-overflow" }
+}
+
+// The following are rejected with
+//   error: too many initializers for 'char [0]'
+// A0 a01 = { 1, { 0 } };
+// A0 a02 = { 2, { 1, 0 } };
+
+
+// Verify no warning for an unknown struct object.
+void ga0p (struct A0 *p)
+{
+  p->a[0] = 0;
+  p->a[3] = 3;
+  p->a[9] = 9;
+}
+
+
+// Verify warning for an extern struct object which (unlike a true
+// flexible array member) may not be initialized.
+extern struct A0 a0x;
+
+void ga0x (void)
+{
+  a0x.a[0] = 0;                 // { dg-warning "\\\[-Wstringop-overflow" }
+  a0x.a[3] = 0;                 // { dg-warning "\\\[-Wstringop-overflow" }
+  a0x.a[9] = 0;                 // { dg-warning "\\\[-Wstringop-overflow" }
+}
+
+
+// Exercise trailing one-element array members.
+
+struct A1
+{
+  char n;
+  char a[1];                    // { dg-message "destination object" "note" }
+};
+
+// Verify warning for a definition with no initializer.
+struct A1 a1_;
+
+void ga1_ (void)
+{
+  a1_.a[0] = 0;
+  a1_.a[1] = 1;                 // { dg-warning "\\\[-Wstringop-overflow" }
+  a1_.a[2] = 2;                 // { dg-warning "\\\[-Wstringop-overflow" }
+
+  struct A1 a;
+  a.a[0] = 0;
+  a.a[1] = 1;                   // { dg-warning "\\\[-Wstringop-overflow" }
+  a.a[2] = 2;                   // { dg-warning "\\\[-Wstringop-overflow" }
+  sink (&a);
+}
+
+// Verify warning for access to a definition with an initializer that doesn't
+// initialize the one-element array member.
+struct A1 a1__ = { 0 };
+
+void ga1__ (void)
+{
+  a1__.a[0] = 0;
+  a1__.a[1] = 1;                 // { dg-warning "\\\[-Wstringop-overflow" }
+  a1__.a[2] = 2;                 // { dg-warning "\\\[-Wstringop-overflow" }
+
+  struct A1 a = { 1 };
+  a.a[0] = 0;
+  a.a[1] = 1;                    // { dg-warning "\\\[-Wstringop-overflow" }
+  a.a[2] = 2;                    // { dg-warning "\\\[-Wstringop-overflow" }
+  sink (&a);
+}
+
+// Verify warning for access to a definition with an initializer that
+// initializes the one-element array member to empty.
+struct A1 a1_0 = { 0, { } };
+
+void ga1_0_ (void)
+{
+  a1_0.a[0] = 0;
+  a1_0.a[1] = 1;                // { dg-warning "\\\[-Wstringop-overflow" }
+  a1_0.a[2] = 2;                // { dg-warning "\\\[-Wstringop-overflow" }
+
+  struct A1 a = { 1, { } };
+  a.a[0] = 0;
+  a.a[1] = 1;                   // { dg-warning "\\\[-Wstringop-overflow" }
+  a.a[2] = 2;                   // { dg-warning "\\\[-Wstringop-overflow" }
+  sink (&a);
+}
+
+// Verify warning for access to a definition with an initializer that
+// initializes the one-element array member.
+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 } };
+  a.a[0] = 0;
+  a.a[1] = 1;                   // { dg-warning "\\\[-Wstringop-overflow" }
+  a.a[2] = 2;                   // { dg-warning "\\\[-Wstringop-overflow" }
+  sink (&a);
+}
+
+
+// Verify no warning for an unknown struct object.
+void ga1p (struct A1 *p)
+{
+  p->a[0] = 0;
+  p->a[3] = 3;
+  p->a[9] = 9;
+}
+
+
+// Verify warning for an extern struct object.  Similar to the zero-length
+// array case, a one-element trailing array can be initialized to at most
+// a single element.
+extern struct A1 a1x;
+
+void ga1x (void)
+{
+  a1x.a[0] = 0;
+  a1x.a[3] = 3;                 // { dg-warning "\\\[-Wstringop-overflow" }
+  a1x.a[9] = 9;                 // { dg-warning "\\\[-Wstringop-overflow" }
+}
+
+// Exercise interior one-element array members (verify they're not
+// treated as trailing.
+
+struct A1i
+{
+  char n;
+  char a[1];                    // { dg-message "destination object" }
+  char x;
+};
+
+// Verify warning for a definition with no initializer.
+struct A1i a1i_;
+
+void ga1i_ (void)
+{
+  a1i_.a[0] = 0;
+  a1i_.a[1] = 1;                // { dg-warning "\\\[-Wstringop-overflow" }
+  a1i_.a[2] = 2;                // { dg-warning "\\\[-Wstringop-overflow" }
+
+  struct A1i a;
+  a.a[0] = 1;
+  a.a[1] = 2;                   // { dg-warning "\\\[-Wstringop-overflow" }
+  a.a[2] = 3;                   // { dg-warning "\\\[-Wstringop-overflow" }
+  sink (&a);
+}
+
+// Verify warning for access to a definition with an initializer that doesn't
+// initialize the one-element array member.
+struct A1i a1i__ = { 0 };
+
+void ga1i__ (void)
+{
+  a1i__.a[0] = 0;
+  a1i__.a[1] = 1;                // { dg-warning "\\\[-Wstringop-overflow" }
+  a1i__.a[2] = 2;                // { dg-warning "\\\[-Wstringop-overflow" }
+
+  struct A1i a = { 0 };
+  a.a[0] = 0;
+  a.a[1] = 1;                    // { dg-warning "\\\[-Wstringop-overflow" }
+  a.a[2] = 2;                    // { dg-warning "\\\[-Wstringop-overflow" }
+  sink (&a);
+}
+
+// Verify warning for access to a definition with an initializer that
+// initializes the one-element array member to empty.
+struct A1 a1i_0 = { 0, { } };
+
+void ga1i_0_ (void)
+{
+  a1i_0.a[0] = 0;
+  a1i_0.a[1] = 1;               // { dg-warning "\\\[-Wstringop-overflow" }
+  a1i_0.a[2] = 2;               // { dg-warning "\\\[-Wstringop-overflow" }
+
+  struct A1 a = { 0, { } };
+  a.a[0] = 0;
+  a.a[1] = 1;                   // { dg-warning "\\\[-Wstringop-overflow" }
+  a.a[2] = 2;                   // { dg-warning "\\\[-Wstringop-overflow" }
+  sink (&a);
+}
+
+// Verify warning for access to a definition with an initializer that
+// initializes the one-element array member.
+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" }
+
+  struct A1 a = { 0, { 1 } };
+  a.a[0] = 1;
+  a.a[1] = 2;                   // { dg-warning "\\\[-Wstringop-overflow" }
+  a.a[2] = 3;                   // { dg-warning "\\\[-Wstringop-overflow" }
+  sink (&a);
+}
+
+
+// Verify no warning for an unknown struct object.
+void ga1ip (struct A1i *p)
+{
+  p->a[0] = 0;
+  p->a[3] = 3;                  // { dg-warning "\\\[-Wstringop-overflow" }
+  p->a[9] = 9;                  // { dg-warning "\\\[-Wstringop-overflow" }
+}
+
+
+// Verify no warning for an extern struct object.
+extern struct A1i a1ix;
+
+void ga1ix (void)
+{
+  a1ix.a[0] = 0;
+  a1ix.a[3] = 3;                 // { dg-warning "\\\[-Wstringop-overflow" }
+  a1ix.a[9] = 9;                 // { dg-warning "\\\[-Wstringop-overflow" }
+}
diff --git a/gcc/testsuite/c-c++-common/Wstringop-overflow-2.c b/gcc/testsuite/c-c++-common/Wstringop-overflow-2.c
index 7d29b5f48c7..cb687c69324 100644
--- a/gcc/testsuite/c-c++-common/Wstringop-overflow-2.c
+++ b/gcc/testsuite/c-c++-common/Wstringop-overflow-2.c
@@ -189,8 +189,9 @@  void ga1__ (void)
 
   struct A1 a = { 1 };
   a.a[0] = 0;
+  // O2 vectorization regress Wstringop-overflow case (1), refer to pr102462.
   a.a[1] = 1;                    // { dg-warning "\\\[-Wstringop-overflow" }
-  a.a[2] = 2;                    // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { i?86-*-* x86_64-*-* } } }
+  a.a[2] = 2;                    // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { vect_slp_v2qi_store } } }
   sink (&a);
 }
 
@@ -206,8 +207,9 @@  void ga1_0_ (void)
 
   struct A1 a = { 1, { } };
   a.a[0] = 0;
+  // O2 vectorization regress Wstringop-overflow case (1), refer to PR102462.
   a.a[1] = 1;                   // { dg-warning "\\\[-Wstringop-overflow" }
-  a.a[2] = 2;                   // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { i?86-*-* x86_64-*-* } } }
+  a.a[2] = 2;                   // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { vect_slp_v2qi_store } } }
   sink (&a);
 }
 
@@ -221,10 +223,11 @@  void ga1_1 (void)
   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-*-* } } }
+// O2 vectorization regress Wstringop-overflow case (2), refer to PR102706
+  struct A1 a = { 0, { 1 } };   // { dg-warning "\\\[-Wstringop-overflow" "" { target { vect_slp_v4qi_store } } }
   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-*-* } } }
+  a.a[1] = 1;                   // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { vect_slp_v4qi_store } } }
+  a.a[2] = 2;                   // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { vect_slp_v4qi_store } } }
   sink (&a);
 }
 
@@ -288,8 +291,9 @@  void ga1i__ (void)
 
   struct A1i a = { 0 };
   a.a[0] = 0;
+  // O2 vectorization regress Wstringop-overflow case (1), refer to PR102462
   a.a[1] = 1;                    // { dg-warning "\\\[-Wstringop-overflow" }
-  a.a[2] = 2;                    // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { i?86-*-* x86_64-*-* } } }
+  a.a[2] = 2;                    // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { vect_slp_v2qi_store } } }
   sink (&a);
 }
 
@@ -305,8 +309,9 @@  void ga1i_0_ (void)
 
   struct A1 a = { 0, { } };
   a.a[0] = 0;
+  // O2 vectorization regress Wstringop-overflow case (1), refer to PR102462
   a.a[1] = 1;                   // { dg-warning "\\\[-Wstringop-overflow" }
-  a.a[2] = 2;                   // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { i?86-*-* x86_64-*-* } } }
+  a.a[2] = 2;                   // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { vect_slp_v2qi_store } } }
   sink (&a);
 }
 
@@ -320,10 +325,11 @@  void ga1i_1 (void)
   a1i_1.a[1] = 1;               // { dg-warning "\\\[-Wstringop-overflow" }
   a1i_1.a[2] = 2;               // { dg-warning "\\\[-Wstringop-overflow" }
 
-  struct A1 a = { 0, { 1 } };   // { dg-warning "\\\[-Wstringop-overflow" "" { target { i?86-*-* x86_64-*-* } } }
+  // O2 vectorization regress Wstringop-overflow case (1), refer to PR102462
+  struct A1 a = { 0, { 1 } };   // { dg-warning "\\\[-Wstringop-overflow" "" { target { vect_slp_v4qi_store } } }
   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-*-* } } }
+  a.a[1] = 2;                   // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { vect_slp_v4qi_store } } }
+  a.a[2] = 3;                   // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { vect_slp_v4qi_store } } }
   sink (&a);
 }
 
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-48-novec.c b/gcc/testsuite/gcc.dg/Warray-bounds-48-novec.c
new file mode 100644
index 00000000000..da179a2c0f5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Warray-bounds-48-novec.c
@@ -0,0 +1,364 @@ 
+/* PR middle-end/91647 - missing -Warray-bounds accessing a zero-length array
+   of a declared object
+   { dg-do "compile" }
+   { dg-options "-O2 -Wall -fno-tree-vectorize" }
+   { dg-require-effective-target alloca } */
+
+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 (struct AX *p)
+{
+  p->ax[0] = 0;     // { dg-warning "\\\[-Warray-bounds" }
+  p->ax[1] = 1;     // { dg-warning "\\\[-Warray-bounds" }
+}
+
+static void nowarn_ax_extern (struct AX *p)
+{
+  p->ax[0] = 0; p->ax[99] = 99; p->ax[999] = 999; p->ax[9999] = 9999;
+}
+
+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" }
+}
+
+static void warn_ax_extern_buf (struct AX *p)
+{
+  p->ax[0] = 9; p->ax[1] = 10; p->ax[2] = 11;
+
+  p->ax[3] = 12;    // { dg-warning "\\\[-Warray-bounds" }
+  p->ax[4] = 13;    // { dg-warning "\\\[-Warray-bounds" }
+  p->ax[5] = 14;    // { dg-warning "\\\[-Warray-bounds" }
+}
+
+static void nowarn_ax_extern_bufx (struct AX *p)
+{
+  p->ax[0] = 0; p->ax[99] = 99; p->ax[999] = 999; p->ax[9999] = 9999;
+}
+
+static void nowarn_ax_ref (struct AX *p)
+{
+  p->ax[0] = 0; p->ax[99] = 99; p->ax[999] = 999; p->ax[9999] = 9999;
+}
+
+void test_ax (struct AX *p, unsigned n)
+{
+  {
+    struct AX sax;  // { dg-message "defined here" "struct definition" }
+    warn_ax_local (&sax);
+    sink (&sax);
+  }
+
+  {
+    extern
+      struct AX xsax;
+    nowarn_ax_extern (&xsax);
+    sink (&xsax);
+  }
+
+  {
+    /* 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);
+  }
+
+  {
+    /* Verify out-of-bounds access to the extern BUF with a known
+       bound is diagnosed.  */
+    extern char ax_buf_p3[sizeof (struct AX) + 3 * sizeof (int16_t)];
+    warn_ax_extern_buf ((struct AX*) ax_buf_p3);
+    sink (ax_buf_p3);
+  }
+
+  {
+    /* Verify that accesses to BUFX with an unknown bound are not
+       diagnosed.  */
+    extern char bufx[];
+    nowarn_ax_extern_bufx ((struct AX*) bufx);
+    sink (bufx);
+  }
+
+  {
+    /* Verify that accesses to BUFN with a runtime bound are not
+       diagnosed.  */
+    char bufn[n];
+    nowarn_ax_extern_bufx ((struct AX*) bufn);
+    sink (bufn);
+  }
+
+  nowarn_ax_ref (p);
+}
+
+
+/* Exercise a zero-length trailing member array.  It's the same as above
+   except that extern declarations with no definitions are considered to
+   have zero elements (they can't be initialized to have any).  */
+
+struct A0
+{
+  int32_t n;
+  int16_t a0[0];    // { dg-message "while referencing 'a0'" "member" }
+};
+
+static void warn_a0_local (struct A0 *p)
+{
+  p->a0[0] = 0;     // { dg-warning "\\\[-Warray-bounds" }
+  p->a0[1] = 1;     // { dg-warning "\\\[-Warray-bounds" }
+}
+
+static void warn_a0_extern (struct A0 *p)
+{
+  p->a0[0] = 2;     // { dg-warning "\\\[-Warray-bounds" }
+  p->a0[1] = 3;     // { dg-warning "\\\[-Warray-bounds" }
+}
+
+static void warn_a0_local_buf (struct A0 *p)
+{
+  p->a0[0] = 4; p->a0[1] = 5;
+
+  p->a0[2] = 6;     // { dg-warning "\\\[-Warray-bounds" }
+  p->a0[3] = 7;     // { dg-warning "\\\[-Warray-bounds" }
+  p->a0[4] = 8;     // { dg-warning "\\\[-Warray-bounds" }
+}
+
+static void warn_a0_extern_buf (struct A0 *p)
+{
+  p->a0[0] = 9; p->a0[1] = 10; p->a0[2] = 11;
+
+  p->a0[3] = 12;    // { dg-warning "\\\[-Warray-bounds" }
+  p->a0[4] = 13;    // { dg-warning "\\\[-Warray-bounds" }
+  p->a0[5] = 14;    // { dg-warning "\\\[-Warray-bounds" }
+}
+
+static void nowarn_a0_extern_bufx (struct A0 *p)
+{
+  p->a0[0] = 0; p->a0[99] = 99; p->a0[999] = 999; p->a0[9999] = 9999;
+}
+
+static void nowarn_a0_ref (struct A0 *p)
+{
+  p->a0[0] = 0; p->a0[99] = 99; p->a0[999] = 999; p->a0[9999] = 9999;
+}
+
+void test_a0 (struct A0 *p, unsigned n)
+{
+  {
+    struct A0 sa0;  // { dg-message "defined here" "struct definition" }
+    warn_a0_local (&sa0);
+    sink (&sa0);
+  }
+
+  {
+    extern
+      struct A0 xsa0;  // { dg-message "defined here" "struct definition" }
+    warn_a0_extern (&xsa0);
+    sink (&xsa0);
+  }
+
+  {
+    /* Verify out-of-bounds access to the local BUF is diagnosed.  */
+    char a0_buf_p2[sizeof (struct A0) + 2 * sizeof (int16_t)];
+    warn_a0_local_buf ((struct A0*) a0_buf_p2);
+    sink (a0_buf_p2);
+  }
+
+  {
+    /* Verify out-of-bounds access to the extern BUF with a known
+       bound is diagnosed.  */
+    extern char a0_buf_p3[sizeof (struct A0) + 3 * sizeof (int16_t)];
+    warn_a0_extern_buf ((struct A0*) a0_buf_p3);
+    sink (a0_buf_p3);
+  }
+
+  {
+    /* Verify that accesses to BUFX with an unknown bound are not
+       diagnosed.  */
+    extern char bufx[];
+    nowarn_a0_extern_bufx ((struct A0*) bufx);
+    sink (bufx);
+  }
+
+  {
+    /* Verify that accesses to BUFN with a runtime bound are not
+       diagnosed.  */
+    char bufn[n];
+    nowarn_a0_extern_bufx ((struct A0*) bufn);
+    sink (bufn);
+  }
+
+  nowarn_a0_ref (p);
+}
+
+
+/* Exercise a one-element trailing member array.  It's the same as above
+   except that it has exactly one element.  */
+
+struct A1
+{
+  int32_t n;
+  int16_t a1[1];    // { dg-message "while referencing 'a1'" }
+};
+
+static void warn_a1_local_noinit (struct A1 *p)
+{
+  p->a1[0] = 0;
+  p->a1[1] = 1;     // { dg-warning "\\\[-Warray-bounds" }
+  p->a1[2] = 2;     // { dg-warning "\\\[-Warray-bounds" }
+}
+
+static void warn_a1_extern (struct A1 *p)
+{
+  p->a1[0] = 0;
+  p->a1[1] = 1;     // { dg-warning "\\\[-Warray-bounds" }
+  p->a1[2] = 2;     // { dg-warning "\\\[-Warray-bounds" }
+}
+
+static void warn_a1_init (struct A1 *p)
+{
+  p->a1[0] = 0;
+  p->a1[1] = 1;     // { dg-warning "\\\[-Warray-bounds" }
+  p->a1[2] = 2;     // { dg-warning "\\\[-Warray-bounds" }
+}
+
+static void warn_a1_local_buf (struct A1 *p)
+{
+  p->a1[0] = 0; p->a1[1] = 1; p->a1[2] = 2; p->a1[3] = 3;
+
+  p->a1[4] = 4;     // { dg-warning "\\\[-Warray-bounds" }
+}
+
+static void warn_a1_extern_buf (struct A1 *p)
+{
+  p->a1[0] = 0; p->a1[1] = 1; p->a1[2] = 2; p->a1[3] = 3; p->a1[4] = 4;
+
+  p->a1[5] = 5;     // { dg-warning "\\\[-Warray-bounds" }
+}
+
+static void nowarn_a1_extern_bufx (struct A1 *p)
+{
+  p->a1[0] = 0; p->a1[99] = 99; p->a1[999] = 999; p->a1[9999] = 9999;
+}
+
+static void nowarn_a1_ref (struct A1 *p)
+{
+  p->a1[0] = 0; p->a1[99] = 99; p->a1[999] = 999; p->a1[9999] = 9999;
+}
+
+void test_a1 (struct A1 *p, unsigned n)
+{
+  {
+    struct A1 a1;
+    warn_a1_local_noinit (&a1);
+    sink (&a1);
+  }
+
+  {
+    extern struct A1 a1x;
+    warn_a1_extern (&a1x);
+    sink (&a1x);
+}
+  {
+    struct A1 a1 = { 0, { 1 } };
+    warn_a1_init (&a1);
+    sink (&a1);
+  }
+
+  {
+    /* Verify out-of-bounds access to the local BUF is diagnosed.  */
+    char buf_p2[sizeof (struct A1) + 2 * sizeof (int16_t)];
+    warn_a1_local_buf ((struct A1*) buf_p2);
+    sink (buf_p2);
+  }
+
+  {
+    /* Verify out-of-bounds access to the extern BUF with a known
+       bound is diagnosed.  */
+    extern char a1_buf_p3[sizeof (struct A1) + 3 * sizeof (int16_t)];
+    warn_a1_extern_buf ((struct A1*) a1_buf_p3);
+    sink (a1_buf_p3);
+  }
+
+  {
+    /* Verify that accesses to BUFX with an unknown bound are not
+       diagnosed.  */
+    extern char bufx[];
+    nowarn_a1_extern_bufx ((struct A1*) bufx);
+    sink (bufx);
+  }
+
+  {
+    /* Verify that accesses to BUFN with a runtime bound are not
+       diagnosed.  */
+    char bufn[n];
+    nowarn_a1_extern_bufx ((struct A1*) bufn);
+    sink (bufn);
+  }
+
+  nowarn_a1_ref (p);
+}
+
+
+/* Exercise a two-element trailing member array.  It's treated
+   the same as an interior array member.  */
+
+struct A2
+{
+  int32_t n;
+  int16_t a2[2];    // { dg-message "while referencing 'a2'" }
+};
+
+static void warn_a2_noinit (struct A2 *p)
+{
+  p->a2[0] = 0; p->a2[1] = 1;
+
+  p->a2[2] = 2;     // { dg-warning "\\\[-Warray-bounds" }
+}
+
+static void warn_a2_init (struct A2 *p)
+{
+  p->a2[0] = 0; p->a2[1] = 1;
+
+  p->a2[2] = 2;     // { dg-warning "\\\[-Warray-bounds" }
+  p->a2[9] = 9;     // { dg-warning "\\\[-Warray-bounds" }
+}
+
+static void warn_a2_ref (struct A2 *p)
+{
+  p->a2[0] = 0; p->a2[1] = 1;
+
+  p->a2[2] = 2;     // { dg-warning "\\\[-Warray-bounds" }
+  p->a2[9] = 9;     // { dg-warning "\\\[-Warray-bounds" }
+}
+
+void test_a2 (struct A2 *p)
+{
+  {
+    struct A2 a2;
+    warn_a2_noinit (&a2);
+    sink (&a2);
+  }
+
+  {
+    struct A2 a2 = { 0, { 1, 2 } };
+    warn_a2_init (&a2);
+    sink (&a2);
+  }
+
+  warn_a2_ref (p);
+}
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-48.c b/gcc/testsuite/gcc.dg/Warray-bounds-48.c
index 13373d1e99e..27dd879de5c 100644
--- a/gcc/testsuite/gcc.dg/Warray-bounds-48.c
+++ b/gcc/testsuite/gcc.dg/Warray-bounds-48.c
@@ -30,7 +30,8 @@  static void nowarn_ax_extern (struct AX *p)
 
 static void warn_ax_local_buf (struct AX *p)
 {
-  p->ax[0] = 4; p->ax[1] = 5;
+  // Refer to 102706
+  p->ax[0] = 4; p->ax[1] = 5;  // { dg-warning "\\\[-Wstringop-overflow" "" { target { vect_slp_v2hi_store &&  { ! vect_slp_v4hi_store } } } }
 
   p->ax[2] = 6;     // { dg-warning "\\\[-Warray-bounds" }
   p->ax[3] = 7;     // { dg-warning "\\\[-Warray-bounds" }
@@ -130,7 +131,8 @@  static void warn_a0_extern (struct A0 *p)
 
 static void warn_a0_local_buf (struct A0 *p)
 {
-  p->a0[0] = 4; p->a0[1] = 5;
+  // Refer to 102706
+  p->a0[0] = 4; p->a0[1] = 5;  // { dg-warning "\\\[-Wstringop-overflow" "" { target { vect_slp_v2hi_store && { ! vect_slp_v4hi_store } } } }
 
   p->a0[2] = 6;     // { dg-warning "\\\[-Warray-bounds" }
   p->a0[3] = 7;     // { dg-warning "\\\[-Warray-bounds" }
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-51-novec.c b/gcc/testsuite/gcc.dg/Warray-bounds-51-novec.c
new file mode 100644
index 00000000000..24bc318f113
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Warray-bounds-51-novec.c
@@ -0,0 +1,61 @@ 
+/* PR middle-end/92333 - missing variable name referencing VLA in warnings
+   PR middle-end/82608 - missing -Warray-bounds on an out-of-bounds VLA index
+   { dg-do compile }
+   { dg-options "-O2 -Wall -fno-tree-vectorize" }  */
+
+void sink (void*);
+
+void test_char_vla_location (void)
+{
+  unsigned nelts = 7;
+
+  char vla[nelts];    // { dg-message "declared here|while referencing" }
+
+  vla[0] = __LINE__;
+  vla[nelts] = 0;     // { dg-warning "\\\[-Warray-bounds" }
+
+  sink (vla);
+}
+
+void test_int_vla_location (void)
+{
+  unsigned nelts = 7;
+
+  int vla[nelts];     // { dg-message "declared here|while referencing" }
+
+  vla[0] = __LINE__;
+  vla[nelts] = 1;     // { dg-warning "\\\[-Warray-bounds" }
+
+  sink (vla);
+}
+
+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;
+  s.cvla[nelts] = 0;  // { dg-warning "\\\[-Warray-bounds" }
+
+  sink (&s);
+}
+
+
+void test_struct_int_vla_location (void)
+{
+  unsigned nelts = 7;
+
+  struct {
+    int ivla[nelts];  // { dg-message "declared here|while referencing" }
+  } s;
+
+  s.ivla[0] = __LINE__;
+  s.ivla[nelts - 1] = 0;
+  s.ivla[nelts] = 0;  // { dg-warning "\\\[-Warray-bounds" }
+
+  sink (&s);
+}
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-51.c b/gcc/testsuite/gcc.dg/Warray-bounds-51.c
index de60d87ab95..cc92a0fd500 100644
--- a/gcc/testsuite/gcc.dg/Warray-bounds-51.c
+++ b/gcc/testsuite/gcc.dg/Warray-bounds-51.c
@@ -39,7 +39,8 @@  void test_struct_char_vla_location (void)
   } s;
 
   s.cvla[0] = __LINE__;
-  s.cvla[nelts - 1] = 0; // { dg-warning "\\\[-Wstringop-overflow" "" { target { i?86-*-* x86_64-*-* } } }
+  // O2 vectorization regress Wstringop-overflow case (2), refer to pr102706.
+  s.cvla[nelts - 1] = 0; // { dg-warning "\\\[-Wstringop-overflow" "" { target { vect_slp_v2qi_store } } }
   s.cvla[nelts] = 0;  // { dg-warning "\\\[-Warray-bounds" }
 
   sink (&s);
diff --git a/gcc/testsuite/gcc.dg/Warray-parameter-3-novec.c b/gcc/testsuite/gcc.dg/Warray-parameter-3-novec.c
new file mode 100644
index 00000000000..0c8fdd11ec9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Warray-parameter-3-novec.c
@@ -0,0 +1,89 @@ 
+/* PR c/50584 - No warning for passing small array to C99 static array
+   declarator
+   { dg-do compile }
+   { dg-options "-Wall -Warray-parameter=1" } */
+
+/* Verify that at level 1 mismatches in the bounds of ordinary array
+   parameters don't trigger -Warray-parameter.  */
+void fax (int[]);
+void fax (int[0]);
+void fax (int[1]);
+void fax (int[2]);
+void fax (int[3]);
+
+/* Same as above but starting with an array with a specified bound.  */
+void gax (int[3]);
+void gax (int[2]);
+void gax (int[1]);
+void gax (int[0]);
+void gax (int[]);
+
+/* Same for multidimensional arrays.  */
+void fax_y (int[][3]);
+void fax_y (int[0][3]);
+void fax_y (int[1][3]);
+void fax_y (int[2][3]);
+void fax_y (int[3][3]);
+
+/* Same as above but starting with an array with a specified bound.  */
+void gax_y (int[3][5]);
+void gax_y (int[2][5]);
+void gax_y (int[1][5]);
+void gax_y (int[0][5]);
+void gax_y (int[][5]);
+
+/* Exercise VLAs with a mismatch in the bound for an ordinary array.  */
+void fvlax_y (int n, int[][n]);
+void fvlax_y (int n, int[0][n]);
+void fvlax_y (int n, int[1][n]);
+void fvlax_y (int n, int[2][n]);
+void fvlax_y (int n, int[3][n]);
+
+void fvlaxn_y (int n, int[][n]);
+void fvlaxn_y (int n, int[0][n]);
+void fvlaxn_y (int n, int[1][n]);
+void fvlaxn_y (int n, int[2][n]);
+void fvlaxn_y (int n, int[3][n]);
+
+void fvlaxx_y (int[][*]);
+void fvlaxx_y (int[0][*]);
+void fvlaxx_y (int[1][*]);
+void fvlaxx_y (int[2][*]);
+void fvlaxx_y (int[3][*]);
+
+/* Verify that mismatches in the bounds of array parameters declared
+   static do trigger -Warray-parameter.  */
+void fas1 (int[static 1]);    // { dg-message "previously declared as 'int\\\[static 1]'" }
+void fas1 (int[static 2]);    // { dg-warning "\\\[-Warray-parameter=" }
+
+
+/* Also verify that -Warray-bounds doesn't trigger for ordinary array
+   parameters...  */
+#pragma GCC optimize ("2,no-tree-vectorize")
+
+__attribute__ ((noipa)) void
+gca3 (char a[3])
+{
+  a[0] = 0; a[1] = 1; a[2] = 2; a[3] = 3;
+}
+
+__attribute__ ((noipa)) void
+gia3 (int a[3])
+{
+  a[0] = 0; a[1] = 1; a[2] = 2; a[3] = 3;
+}
+
+/* ...but does for static arrays.  */
+__attribute__ ((noipa)) void
+gcas3 (char a[static 3])
+{
+  a[0] = 0; a[1] = 1; a[2] = 2;
+  a[3] = 3;                   // { dg-warning "\\\[-Warray-bounds" }
+}
+
+__attribute__ ((noipa)) void
+gias3 (int a[static 3])
+{
+  a[0] = 0; a[1] = 1; a[2] = 2;
+  a[3] = 3;                   // { dg-warning "\\\[-Warray-bounds" }
+}
diff --git a/gcc/testsuite/gcc.dg/Warray-parameter-3.c b/gcc/testsuite/gcc.dg/Warray-parameter-3.c
index e8a269c85c6..1068707973f 100644
--- a/gcc/testsuite/gcc.dg/Warray-parameter-3.c
+++ b/gcc/testsuite/gcc.dg/Warray-parameter-3.c
@@ -77,7 +77,8 @@  gia3 (int a[3])
 __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-*-* } } }
+  // O2 vectorization regress Wstringop-overflow case (2), refer to pr102706.
+  a[0] = 0; a[1] = 1; a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" "" { target { vect_slp_v4qi_store } } }
   a[3] = 3;                   // { dg-warning "\\\[-Warray-bounds" }
 }
 
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-14-novec.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-14-novec.c
new file mode 100644
index 00000000000..c7b5479dc07
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-14-novec.c
@@ -0,0 +1,56 @@ 
+/* Test to verify that past-the-end multibyte writes via lvalues of wider
+   types than char are diagnosed.
+   { dg-do compile }
+   { dg-require-effective-target int32plus }
+   { dg-options "-O2 -fno-tree-vectorize -Wall -Wno-array-bounds" }  */
+
+typedef __INT16_TYPE__  int16_t;
+typedef __INT32_TYPE__  int32_t;
+typedef __INT64_TYPE__  int64_t;
+typedef __SIZE_TYPE__   size_t;
+
+void* memcpy (void*, const void*, size_t);
+char* strcpy (char*, const char*);
+
+char a4[4], a8[8], a16[16];
+
+const char s4[] = "1234";
+const char t4[] = "4321";
+
+void test_memcpy_cond (int i)
+{
+  char *p = a4 + 1;
+  const char *q = i ? s4 : t4;
+  // On strictly aligned target the call below is left unchanged and
+  // triggers (inaccurately) a -Warray-bounds.  The test suppresses
+  // the warning above, which then lets -Wstringop-overrflow detect
+  // the overflow just before expansion.
+  // On other targets it's transformed into a store of a 4-byte integer
+  // which is detected by -Wstringop-overrflow in the strlen pass (i.e.,
+  // before it gets to expansion).
+  memcpy (p, q, 4);         // { dg-warning "writing 4 bytes into a region of size 3" }
+}
+
+
+void test_int16 (void)
+{
+  char *p = a4 + 1;
+  *(int16_t*)p = 0;
+  *(int16_t*)(p + 2) = 0;   // { dg-warning "writing 2 bytes into a region of size 1" }
+}
+
+
+void test_int32 (void)
+{
+  char *p = a8 + 3;
+  *(int32_t*)p = 0;
+  *(int32_t*)(p + 2) = 0;   // { dg-warning "writing 4 bytes into a region of size 3" }
+}
+
+
+void test_int64 (void)
+{
+  char *p = a16 + 5;
+  *(int64_t*)p = 0;
+  *(int64_t*)(p + 5) = 0;   // { dg-warning "writing 8 bytes into a region of size 6" }
+}
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-14.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-14.c
index 7683084e46e..6ad9444bc27 100644
--- a/gcc/testsuite/gcc.dg/Wstringop-overflow-14.c
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-14.c
@@ -36,8 +36,9 @@  void test_memcpy_cond (int i)
 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-*-* } } }
+  // O2 vectorization regress Wstringop-overflow case (2), refer to pr102706.
+  *(int16_t*)p = 0;    // { dg-warning "writing 4 bytes into a region of size 3" "" { target { vect_slp_v2hi_store } } }
+  *(int16_t*)(p + 2) = 0;   // { dg-warning "writing 2 bytes into a region of size 1" "" { xfail { vect_slp_v2hi_store } } }
 }
 
 
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-21-novec.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-21-novec.c
new file mode 100644
index 00000000000..b177543b186
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-21-novec.c
@@ -0,0 +1,59 @@ 
+/* PR middle-end/92312 - bogus -Wstringop-overflow storing into a trailing
+   array backed by larger buffer
+   { dg-do compile }
+   { dg-options "-O2 -fno-tree-vectorize -Wall -Wno-array-bounds" } */
+
+struct S0 { char a, b[0]; };
+
+void sink (void*);
+
+void test_memset_zero_length (void)
+{
+  char a[3];
+  struct S0 *p = (struct S0*)a;
+  p->a = 0;
+  __builtin_memset (p->b, 0, 2);
+  sink (p);
+
+  __builtin_memset (p->b, 0, 3);    // { dg-warning "\\\[-Wstringop-overflow" }
+  sink (p);
+}
+
+void test_store_zero_length (int i)
+{
+  char a[3];
+  struct S0 *p = (struct S0*)a;
+  p->a = 0;
+  p->b[0] = 0;
+  p->b[1] = 1;                      // { dg-bogus "\\\[-Wstringop-overflow" }
+  p->b[2] = 2;                      // { dg-warning "\\\[-Wstringop-overflow" }
+  p->b[i] = 2;
+  sink (p);
+}
+
+
+struct Sx { char a, b[]; };
+
+void test_memset_flexarray (int i)
+{
+  char a[3];
+  struct Sx *p = (struct Sx*)a;
+  p->a = 0;
+  __builtin_memset (p->b, 0, 2);
+  sink (p);
+
+  __builtin_memset (p->b, 0, 3);    // { dg-warning "\\\[-Wstringop-overflow" }
+  sink (p);
+}
+
+void test_store_flexarray (int i)
+{
+  char a[3];
+  struct Sx *p = (struct Sx*)a;
+  p->a = 0;
+  p->b[0] = 0;
+  p->b[1] = 1;                      // { dg-bogus "\\\[-Wstringop-overflow" }
+  p->b[2] = 1;                      // { dg-warning "\\\[-Wstringop-overflow" }
+  p->b[i] = 2;
+  sink (p);
+}
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-21.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-21.c
index d88bde9c740..8d2bfe697a5 100644
--- a/gcc/testsuite/gcc.dg/Wstringop-overflow-21.c
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-21.c
@@ -23,10 +23,11 @@  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-*-* } } }
+  // O2 vectorization regress Wstringop-overflow case (2), refer to pr102706.
+  p->a = 0;                         // { dg-warning "\\\[-Wstringop-overflow" "" { target { vect_slp_v4qi_store } } }
   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[2] = 2;                      // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { vect_slp_v4qi_store } } }
   p->b[i] = 2;
   sink (p);
 }
@@ -50,10 +51,11 @@  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-*-* } } }
+  // O2 vectorization regress Wstringop-overflow case (2), refer to pr102706.
+  p->a = 0;                         // { dg-warning "\\\[-Wstringop-overflow" "" { target { vect_slp_v4qi_store } } }
   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[2] = 1;                      // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { vect_slp_v4qi_store } } }
   p->b[i] = 2;
   sink (p);
 }
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-68.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-68.c
index 09df0004991..04e91afb8bc 100644
--- a/gcc/testsuite/gcc.dg/Wstringop-overflow-68.c
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-68.c
@@ -58,11 +58,18 @@  void warn_comp_lit_zero (void)
 void warn_comp_lit (void)
 {
   *(AC2*)a1 = Ac2;      // { dg-warning "writing 2 bytes into a region of size 1" "pr101475" { xfail *-*-* } }
-  *(AC4*)a2 = Ac4;      // { dg-warning "writing 4 bytes into a region of size 2" "pr101475" { xfail { ! { i?86-*-* x86_64-*-* } } } }
-  *(AC4*)a3 = Ac4;      // { dg-warning "writing 4 bytes into a region of size 3" "pr101475" { xfail { ! { i?86-*-* x86_64-*-* } } } }
-  *(AC8*)a4 = Ac8;      // { dg-warning "writing 8 bytes into a region of size 4" "pr101475" { xfail { ! { i?86-*-* x86_64-*-* } } } }
-  *(AC8*)a7 = Ac8;      // { dg-warning "writing 8 bytes into a region of size 7" "pr101475" { xfail { ! { i?86-*-* x86_64-*-* } } } }
-  *(AC16*)a15 = Ac16;   // { dg-warning "writing 16 bytes into a region of size 15" "pr101475" { xfail { ! { i?86-*-* x86_64-*-* } } } }
+  // After vectorization, below codes are optimized to
+  // MEM <vector(4) char> [(char *)&a2] = { 0, 1, 2, 3 };
+  // MEM <vector(4) char> [(char *)&a3] = { 0, 1, 2, 3 };
+  // MEM <vector(8) char> [(char *)&a4] = { 0, 1, 2, 3, 4, 5, 6, 7 };
+  // MEM <vector(8) char> [(char *)&a7] = { 0, 1, 2, 3, 4, 5, 6, 7 };
+  // MEM <vector(16) char> [(char *)&a15] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
+  // and warning should be expected, refer to PR102722.
+  *(AC4*)a2 = Ac4;      // { dg-warning "writing 4 bytes into a region of size 2" "pr101475" { xfail { ! { vect_slp_v4qi_store } } } }
+  *(AC4*)a3 = Ac4;      // { dg-warning "writing 4 bytes into a region of size 3" "pr101475" { xfail { ! { vect_slp_v4qi_store } } } }
+  *(AC8*)a4 = Ac8;      // { dg-warning "writing 8 bytes into a region of size 4" "pr101475" { xfail { ! { vect_slp_v8qi_store } } } }
+  *(AC8*)a7 = Ac8;      // { dg-warning "writing 8 bytes into a region of size 7" "pr101475" { xfail { ! { vect_slp_v8qi_store } } } }
+  *(AC16*)a15 = Ac16;   // { dg-warning "writing 16 bytes into a region of size 15" "pr101475" { xfail { ! { vect_slp_v16qi_store } } } }
 }
 
 void warn_aggr_decl (void)
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-76-novec.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-76-novec.c
new file mode 100644
index 00000000000..d000b587a65
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-76-novec.c
@@ -0,0 +1,147 @@ 
+/* Verify warnings and notes for MAX_EXPRs involving either pointers
+   to distinct objects or one to a known object and the other to
+   an unknown one.  Unlike for the same object, for unrelated objects
+   the expected warnings and notes are the same as for MIN_EXPR: when
+   the order of the objects in the address space cannot be determined
+   the larger of them is assumed to be used.  (This is different for
+   distinct struct members where the order is given.)
+   The relational expressions are strictly invalid but that should be
+   diagnosed by a separate warning.
+   { dg-do compile }
+   { dg-options "-O2 -Wno-array-bounds -fno-tree-vectorize" } */
+
+#define MAX(p, q) ((p) > (q) ? (p) : (q))
+
+/* Verify that even for MAX_EXPR and like for MIN_EXPR, the note points
+   to the larger of the two objects and mentions the offset into it
+   (although the offset might be better included in the warning).  */
+extern char a3[3];
+extern char a5[5];  // { dg-message "at offset 5 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;
+  d[3] = 0;
+  d[4] = 0;
+  d[5] = 0;         // { dg-warning "writing 1 byte into a region of size 0" }
+}
+
+
+// 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 6 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;
+  d[4] = 0;
+  d[5] = 0;
+  d[6] = 0;         // { dg-warning "writing 1 byte into a region of size 0" }
+}
+
+
+/* Same as above but with the first MAX_EXPR operand pointing to an unknown
+   object.  */
+extern char c7[7];  // { dg-message "at offset 7 into destination object 'c7' of size 7" "note" }
+
+void max_p_c7 (char *p, int i)
+{
+  char *q = c7 + i;
+  char *d = MAX (p, q);
+
+  d[6] = 0;
+  d[7] = 0;         // { dg-warning "writing 1 byte into a region of size 0" }
+}
+
+
+/* Same as above but with the second MIN_EXPR operand pointing to an unknown
+   object.  */
+extern char d8[8];  // { dg-message "at offset 8 into destination object 'd8' of size 8" "note" }
+
+void max_d8_p (char *q, int i)
+{
+  char *p = d8 + i;
+  char *d = MAX (p, q);
+
+  d[7] = 0;
+  d[8] = 0;         // { dg-warning "writing 1 byte into a region of size 0" }
+}
+
+
+struct A3_5
+{
+  char a3[3];  // { dg-message "at offset 3 into destination object 'a3' of size 3" "pr??????" { xfail *-*-* } }
+  char a5[5];
+};
+
+void max_A3_A5 (int i, struct A3_5 *pa3_5)
+{
+  char *p = pa3_5->a3 + i;
+  char *q = pa3_5->a5 + i;
+
+  char *d = MAX (p, q);
+  d[2] = 0;
+  d[3] = 0;         // { dg-warning "writing 1 byte into a region of size 0" "pr??????" { xfail *-*-* } }
+  d[4] = 0;
+  d[5] = 0;         // { dg-warning "writing 1 byte into a region of size 0" }
+}
+
+
+struct B4_B6
+{
+  char b4[4];
+  char b6[6];       // { dg-message "at offset 6 into destination object 'b6' of size 6" "note" }
+};
+
+void max_B6_B4 (int i, struct B4_B6 *pb4_b6)
+{
+  char *p = pb4_b6->b6 + i;
+  char *q = pb4_b6->b4 + i;
+  char *d = MAX (p, q);
+
+  d[3] = 0;
+  d[4] = 0;
+  d[5] = 0;
+  d[6] = 0;         // { dg-warning "writing 1 byte into a region of size 0" }
+}
+
+
+struct C7
+{
+  char c7[7];       // { dg-message "at offset 7 into destination object 'c7' of size 7" "note" }
+};
+
+void max_p_C7 (char *p, int i, struct C7 *pc7)
+{
+  char *q = pc7->c7 + i;
+  char *d = MAX (p, q);
+
+  d[6] = 0;
+  d[7] = 0;         // { dg-warning "writing 1 byte into a region of size 0" }
+}
+
+
+struct D8
+{
+  char d8[8];       // { dg-message "at offset 8 into destination object 'd8' of size 8" "note" }
+};
+
+void max_D8_p (char *q, int i, struct D8 *pd8)
+{
+  char *p = pd8->d8 + i;
+  char *d = MAX (p, q);
+
+  d[7] = 0;
+  d[8] = 0;         // { dg-warning "writing 1 byte into a region of size 0" }
+}
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-76.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-76.c
index 0c7b53ccc0b..037e66c2769 100644
--- a/gcc/testsuite/gcc.dg/Wstringop-overflow-76.c
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-76.c
@@ -27,10 +27,11 @@  void max_a3_a5 (int i)
      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-*-* } } }
+  // O2 vectorization regress Wstringop-overflow case (2), refer to pr102706.
+  d[2] = 0;         // { dg-warning "writing 4 bytes into a region of size 3" "" { target { vect_slp_v4qi_store } } }
   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-*-* } } }
+  d[5] = 0;         // { dg-warning "writing 1 byte into a region of size 0" "" { xfail { vect_slp_v4qi_store } } }
 }
 
 
@@ -44,10 +45,11 @@  void max_b6_b4 (int 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-*-* } } }
+  // O2 vectorization regress Wstringop-overflow case (2), refer to pr102706.
+  d[3] = 0;         // { dg-warning "writing 4 bytes into a region of size 3" "" { target { vect_slp_v4qi_store } } }
   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-*-* } } }
+  d[6] = 0;         // { dg-warning "writing 1 byte into a region of size 0" "" { xfail { vect_slp_v4qi_store } } }
 }
 
 
@@ -82,7 +84,7 @@  void max_d8_p (char *q, int i)
 struct A3_5
 {
   char a3[3];  // { dg-message "at offset 3 into destination object 'a3' of size 3" "pr??????" { xfail *-*-* } }
-  char a5[5];  // { dg-message "at offset 5 into destination object 'a5' of size 5" "note" { xfail { i?86-*-* x86_64-*-* } } }
+  char a5[5];  // { dg-message "at offset 5 into destination object 'a5' of size 5" "note" { xfail { vect_slp_v4qi_store } } }
 };
 
 void max_A3_A5 (int i, struct A3_5 *pa3_5)
@@ -91,18 +93,20 @@  void max_A3_A5 (int i, struct A3_5 *pa3_5)
   char *q = pa3_5->a5 + i;
 
   char *d = MAX (p, q);
-
+  // After vectorization, below codes are vectorized to
+  // MEM <vector(4) char> [(char *)&d + 3] = { 0, 0, 0, 0 };
+  // refer to pr102697.
   d[2] = 0;
   d[3] = 0;         // { dg-warning "writing 1 byte into a region of size 0" "pr??????" { xfail *-*-* } }
   d[4] = 0;
-  d[5] = 0;         // { dg-warning "writing 1 byte into a region of size 0" "" { xfail { i?86-*-* x86_64-*-* } } }
+  d[5] = 0;         // { dg-warning "writing 1 byte into a region of size 0" "" { xfail { vect_slp_v4qi_store } } }
 }
 
 
 struct B4_B6
 {
   char b4[4];
-  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" { xfail { i?86-*-* x86_64-*-* } } }
+  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" { xfail { vect_slp_v4qi_store } } }
 };
 
 void max_B6_B4 (int i, struct B4_B6 *pb4_b6)
@@ -110,11 +114,13 @@  void max_B6_B4 (int i, struct B4_B6 *pb4_b6)
   char *p = pb4_b6->b6 + i;
   char *q = pb4_b6->b4 + i;
   char *d = MAX (p, q);
-
+  // After vectorization, below codes are vectorized to
+  // MEM <vector(4) char> [(char *)&d + 3] = { 0, 0, 0, 0 };
+  // refer to pr102697.
   d[3] = 0;
   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-*-* } } }
+  d[6] = 0;         // { dg-warning "writing 1 byte into a region of size 0" "" { xfail { vect_slp_v4qi_store } } }
 }
 
 
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index 9ebca7ac007..c30831ea91d 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -7580,6 +7580,135 @@  proc check_effective_target_vect_element_align_preferred { } {
 		   && [check_effective_target_vect_variable_length] }]
 }
 
+# Return true if vectorization of v2qi/v4qi/v8qi/v16qi/v2hi store is enabed.
+# Return zero if the desirable pattern isn't found.
+# It's used by Warray-bounds/Wstringop-overflow testcases which are
+# regressed by O2 vectorization, refer to PR102697/PR102462/PR102706
+proc check_vect_slp_vnqihi_store_usage { pattern } {
+    global tool
+
+    return [check_cached_effective_target slp_vnqihi_store_usage {
+      set result [check_compile slp_vnqihi_store_usage assembly {
+	  char a[16] __attribute__ ((aligned (16)));
+	  void
+	  foo ()
+	  {
+	      a[0] = 0;
+	      a[1] = 1;
+	      a[2] = 2;
+	      a[3] = 3;
+	      a[4] = 4;
+	      a[5] = 5;
+	      a[6] = 6;
+	      a[7] = 7;
+	  }
+
+	  void
+	  foo1 ()
+	  {
+	      a[0] = 0;
+	      a[1] = 1;
+	      a[2] = 2;
+	      a[3] = 3;
+	      a[4] = 4;
+	      a[5] = 5;
+	      a[6] = 6;
+	      a[7] = 7;
+	      a[8] = 8;
+	      a[9] = 9;
+	      a[10] = 10;
+	      a[11] = 11;
+	      a[12] = 12;
+	      a[13] = 13;
+	      a[14] = 14;
+	      a[15] = 15;
+	  }
+
+	  void
+	  foo2 ()
+	  {
+	      a[0] = 0;
+	      a[1] = 1;
+	      a[2] = 2;
+	      a[3] = 3;
+	  }
+
+	  void
+	  foo3 ()
+	  {
+	      a[0] = 0;
+	      a[1] = 1;
+	  }
+
+	  short b[4] __attribute__((aligned(8)));
+	  void
+	  foo4 ()
+	  {
+	      b[0] = 0;
+	      b[1] = 1;
+	  }
+
+	  void
+	  foo5 ()
+	  {
+	      b[0] = 0;
+	      b[1] = 1;
+	      b[2] = 2;
+	      b[3] = 3;
+	  }
+
+      } "-O2 -fopt-info-all" ]
+
+      # Get compiler emitted messages and delete generated file.
+      set lines [lindex $result 0]
+      set output [lindex $result 1]
+      remote_file build delete $output
+
+      # Capture the vectorized info of v2qi, set it to zero if not found.
+	if { ![regexp $pattern $lines whole val] } then {
+	  set val 0
+      }
+
+      return $val
+    }]
+}
+
+# Return the true if target support vectorization of v2qi store.
+proc check_effective_target_vect_slp_v2qi_store { } {
+    set pattern {add new stmt: MEM <vector\(2\) char>}
+    return [expr { [check_vect_slp_vnqihi_store_usage $pattern ] != 0 }]
+}
+
+# Return the true if target support vectorization of v4qi store.
+proc check_effective_target_vect_slp_v4qi_store { } {
+    set pattern {add new stmt: MEM <vector\(4\) char>}
+    return [expr { [check_vect_slp_vnqihi_store_usage $pattern ] != 0 }]
+}
+
+# Return the true if target support vectorization of v2qi store.
+proc check_effective_target_vect_slp_v8qi_store { } {
+    set pattern {add new stmt: MEM <vector\(8\) char>}
+    return [expr { [check_vect_slp_vnqihi_store_usage $pattern ] != 0 }]
+}
+
+# Return the true if target support vectorization of v4qi store.
+proc check_effective_target_vect_slp_v16qi_store { } {
+    set pattern {add new stmt: MEM <vector\(16\) char>}
+    return [expr { [check_vect_slp_vnqihi_store_usage $pattern ] != 0 }]
+}
+
+# Return the true if target support vectorization of v2hi store.
+proc check_effective_target_vect_slp_v2hi_store { } {
+    set pattern {add new stmt: MEM <vector\(2\) short int>}
+    return [expr { [check_vect_slp_vnqihi_store_usage $pattern ] != 0 }]
+}
+
+# Return the true if target support vectorization of v2hi store.
+proc check_effective_target_vect_slp_v4hi_store { } {
+    set pattern {add new stmt: MEM <vector\(4\) short int>}
+    return [expr { [check_vect_slp_vnqihi_store_usage $pattern ] != 0 }]
+}
+
 # Return 1 if we can align stack data to the preferred vector alignment.
 
 proc check_effective_target_vect_align_stack_vars { } {