Adjust testcase for O2 vectorization.

As discussed in [1], this patch add xfail/target selector to those
testcases, also make a copy of them so that they can be tested w/o
vectorization.

Newly added xfail/target selectors are used to check the vectorization
capability of continuous byte/double bytes storage, these scenarios
are exactly the part of the testcases that regressed after O2
vectorization.

[1] https://gcc.gnu.org/pipermail/gcc-patches/2021-October/581456.html.

2021-10-19  Hongtao Liu  <hongtao.liu@intel.com>
	    Kewen Lin  <linkw@linux.ibm.com>

gcc/ChangeLog

	* doc/sourcebuild.texi (Effective-Target Keywords): Document
	vect_slp_v2qi_store, vect_slp_v4qi_store, vect_slp_v8qi_store,
	vect_slp_v16qi_store, vect_slp_v2hi_store,
	vect_slp_v4hi_store, vect_slp_v2si_store, vect_slp_v4si_store.

gcc/testsuite/ChangeLog

	PR middle-end/102722
	PR middle-end/102697
	PR middle-end/102462
	PR middle-end/102706
	PR middle-end/102744
	* c-c++-common/Wstringop-overflow-2.c: Adjust testcase with new
	xfail/target selector.
	* gcc.dg/Warray-bounds-51.c: Ditto.
	* gcc.dg/Warray-parameter-3.c: Ditto.
	* gcc.dg/Wstringop-overflow-14.c: Ditto.
	* gcc.dg/Wstringop-overflow-21.c: Ditto.
	* gcc.dg/Wstringop-overflow-68.c: Ditto.
	* gcc.dg/Wstringop-overflow-76.c: Ditto.
	* gcc.dg/Warray-bounds-48.c: Ditto.
	* gcc.dg/Wzero-length-array-bounds-2.c: Ditto.
	* lib/target-supports.exp (check_vect_slp_aligned_store_usage):
	New function.
	(check_effective_target_vect_slp_v2qi_store): Ditto.
	(check_effective_target_vect_slp_v4qi_store): Ditto.
	(check_effective_target_vect_slp_v8qi_store): Ditto.
	(check_effective_target_vect_slp_v16qi_store): Ditto.
	(check_effective_target_vect_slp_v2hi_store): Ditto.
	(check_effective_target_vect_slp_v4hi_store): Ditto.
	(check_effective_target_vect_slp_v2si_store): Ditto.
	(check_effective_target_vect_slp_v4si_store): Ditto.
	* c-c++-common/Wstringop-overflow-2-novec.c: New test.
	* gcc.dg/Warray-bounds-51-novec.c: New test.
	* gcc.dg/Warray-bounds-48-novec.c: New test.
	* gcc.dg/Warray-parameter-3-novec.c: New test.
	* gcc.dg/Wstringop-overflow-14-novec.c: New test.
	* gcc.dg/Wstringop-overflow-21-novec.c: New test.
	* gcc.dg/Wstringop-overflow-76-novec.c: New test.
	* gcc.dg/Wzero-length-array-bounds-2-novec.c: New test.
This commit is contained in:
liuhongt 2021-10-14 09:31:03 +08:00
parent 19472fc3fc
commit 3c8d8c0be9
19 changed files with 967 additions and 34 deletions

View file

@ -1845,6 +1845,38 @@ Target supports loop vectorization with partial vectors and
@item vect_partial_vectors
Target supports loop vectorization with partial vectors and
@code{vect-partial-vector-usage} is nonzero.
@item vect_slp_v2qi_store
Target supports vectorization of 2-byte char stores with 2-byte aligned
address at plain @option{-O2}.
@item vect_slp_v4qi_store
Target supports vectorization of 4-byte char stores with 4-byte aligned
address at plain @option{-O2}.
@item vect_slp_v8qi_store
Target supports vectorization of 8-byte char stores with 8-byte aligned
address at plain @option{-O2}.
@item vect_slp_v16qi_store
Target supports vectorization of 16-byte char stores with 16-byte aligned
address at plain @option{-O2}.
@item vect_slp_v2hi_store
Target supports vectorization of 4-byte short stores with 4-byte aligned
address at plain @option{-O2}.
@item vect_slp_v4hi_store
Target supports vectorization of 8-byte short stores with 8-byte aligned
address at plain @option{-O2}.
@item vect_slp_v2si_store
Target supports vectorization of 8-byte int stores with 8-byte aligned
address at plain @option{-O2}.
@item vect_slp_v4si_store
Target supports vectorization of 16-byte int stores with 16-byte aligned
address at plain @option{-O2}.
@end table
@subsubsection Thread Local Storage attributes

View file

@ -0,0 +1,126 @@
/* 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 trailing one-element array members.
struct A1
{
char n;
char a[1]; // { dg-message "destination object" "note" }
};
// 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);
}
// 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 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);
}

View file

@ -190,7 +190,7 @@ void ga1__ (void)
struct A1 a = { 1 };
a.a[0] = 0;
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 } } }
sink (&a);
}
@ -207,7 +207,7 @@ void ga1_0_ (void)
struct A1 a = { 1, { } };
a.a[0] = 0;
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 } } }
sink (&a);
}
@ -221,10 +221,10 @@ 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-*-* } } }
struct A1 a = { 0, { 1 } }; // { dg-warning "\\\[-Wstringop-overflow" "pr102706" { 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);
}
@ -289,7 +289,7 @@ void ga1i__ (void)
struct A1i a = { 0 };
a.a[0] = 0;
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 } } }
sink (&a);
}
@ -306,7 +306,7 @@ void ga1i_0_ (void)
struct A1 a = { 0, { } };
a.a[0] = 0;
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 } } }
sink (&a);
}
@ -320,10 +320,10 @@ 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-*-* } } }
struct A1 a = { 0, { 1 } }; // { dg-warning "\\\[-Wstringop-overflow" "pr102462" { 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" "pr102462" { xfail { vect_slp_v4qi_store } } }
a.a[2] = 3; // { dg-warning "\\\[-Wstringop-overflow" "pr102462" { xfail { vect_slp_v4qi_store } } }
sink (&a);
}

View file

@ -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);
}

View file

@ -30,7 +30,7 @@ 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;
p->ax[0] = 4; p->ax[1] = 5; // { dg-warning "\\\[-Wstringop-overflow" "pr102706" { 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 +130,7 @@ 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;
p->a0[0] = 4; p->a0[1] = 5; // { dg-warning "\\\[-Wstringop-overflow" "pr102706" { 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" }

View file

@ -0,0 +1,21 @@
/* 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_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);
}

View file

@ -39,7 +39,7 @@ 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-*-* } } }
s.cvla[nelts - 1] = 0; // { dg-warning "\\\[-Wstringop-overflow" "pr102706" { target { vect_slp_v2qi_store } } }
s.cvla[nelts] = 0; // { dg-warning "\\\[-Warray-bounds" }
sink (&s);

View file

@ -0,0 +1,16 @@
/* PR c/50584 - No warning for passing small array to C99 static array
declarator
{ dg-do compile }
{ dg-options "-Wall -Warray-parameter=1" } */
/* Also verify that -Warray-bounds doesn't trigger for ordinary array
parameters... */
#pragma GCC optimize ("2,no-tree-vectorize")
/* ...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" }
}

View file

@ -77,7 +77,7 @@ 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-*-* } } }
a[0] = 0; a[1] = 1; a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" "pr102706" { target { vect_slp_v4qi_store } } }
a[3] = 3; // { dg-warning "\\\[-Warray-bounds" }
}

View file

@ -0,0 +1,16 @@
/* 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;
char a4[4], a8[8], a16[16];
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" }
}

View file

@ -36,8 +36,8 @@ 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-*-* } } }
*(int16_t*)p = 0; // { dg-warning "writing 4 bytes into a region of size 3" "pr102706" { target { vect_slp_v2hi_store } } }
*(int16_t*)(p + 2) = 0; // { dg-warning "writing 2 bytes into a region of size 1" "pr102706" { xfail { vect_slp_v2hi_store } } }
}

View file

@ -0,0 +1,34 @@
/* 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_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_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);
}

View file

@ -23,10 +23,10 @@ void test_store_zero_length (int i)
{
char a[3];
struct S0 *p = (struct S0*)a;
p->a = 0; // { dg-warning "\\\[-Wstringop-overflow" "" { target { i?86-*-* x86_64-*-* } } }
p->a = 0; // { dg-warning "\\\[-Wstringop-overflow" "pr102706" { 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" "pr102706" { xfail { vect_slp_v4qi_store } } }
p->b[i] = 2;
sink (p);
}
@ -50,10 +50,10 @@ void test_store_flexarray (int i)
{
char a[3];
struct Sx *p = (struct Sx*)a;
p->a = 0; // { dg-warning "\\\[-Wstringop-overflow" "" { target { i?86-*-* x86_64-*-* } } }
p->a = 0; // { dg-warning "\\\[-Wstringop-overflow" "pr102706" { 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" "pr102706" { xfail { vect_slp_v4qi_store } } }
p->b[i] = 2;
sink (p);
}

View file

@ -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)

View file

@ -0,0 +1,88 @@
/* 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" }
}
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" }
};
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" }
}

View file

@ -27,10 +27,10 @@ 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-*-* } } }
d[2] = 0; // { dg-warning "writing 4 bytes into a region of size 3" "pr102706" { 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" "pr102706" { xfail { vect_slp_v4qi_store } } }
}
@ -44,10 +44,10 @@ 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-*-* } } }
d[3] = 0; // { dg-warning "writing 4 bytes into a region of size 3" "pr102706" { 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" "pr102706" { xfail { vect_slp_v4qi_store } } }
}
@ -82,7 +82,8 @@ 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-*-* } } }
// refer to pr102697 for xfail
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)
@ -95,14 +96,15 @@ void max_A3_A5 (int i, struct A3_5 *pa3_5)
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" "pr102697" { 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-*-* } } }
// refer to pr102697 for xfail
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)
@ -114,7 +116,7 @@ void max_B6_B4 (int i, struct B4_B6 *pb4_b6)
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" "pr102697" { xfail { vect_slp_v4qi_store } } }
}

View file

@ -0,0 +1,45 @@
/* Test to verify that -Wzero-length-bounds and not -Warray-bounds is
issued for accesses to interior zero-length array members that are
within the bounds of the enclosing struct.
{ dg-do compile }
{ dg-options "-O2 -Wall -fno-tree-vectorize" } */
void sink (void*);
struct A { int i; };
struct B { int j; struct A a[0]; };
struct C
{
struct B b1;
struct B b2;
};
char cbuf1[1 * sizeof (struct C)];
char cbuf2[2 * sizeof (struct C)] = { };
void test_C_global_buf (void)
{
struct C *p = (struct C*)&cbuf1;
p->b1.a[-1].i = 0; // { dg-warning "\\\[-Warray-bounds" }
p->b1.a[ 0].i = 0; // { dg-warning "\\\[-Wzero-length-bounds" }
p->b1.a[ 1].i = 0; // { dg-warning "\\\[-Warray-bounds" }
sink (p);
p->b2.a[ 0].i = 0; // { dg-warning "\\\[-Warray-bounds" }
p->b2.a[ 1].i = 0; // { dg-warning "\\\[-Warray-bounds" }
sink (p);
p = (struct C*)&cbuf2;
p->b1.a[-1].i = 0; // { dg-warning "\\\[-Warray-bounds" }
p->b1.a[ 0].i = 0; // { dg-warning "\\\[-Wzero-length-bounds" }
p->b1.a[ 1].i = 0; // { dg-warning "\\\[-Wzero-length-bounds" }
sink (p);
p->b2.a[ 0].i = 0;
p->b2.a[ 1].i = 0;
p->b2.a[ 2].i = 0; // { dg-warning "\\\[-Warray-bounds" }
p->b2.a[ 3].i = 0; // { dg-warning "\\\[-Warray-bounds" }
sink (p);
}

View file

@ -87,7 +87,7 @@ void test_C_global_buf (void)
p->b1.a[ 1].i = 0; // { dg-warning "\\\[-Wzero-length-bounds" }
sink (p);
p->b2.a[ 0].i = 0;
p->b2.a[ 0].i = 0; // { dg-warning "\\\[-Wstringop-overflow" "pr102706" { target { vect_slp_v2si_store && { ! vect_slp_v4si_store } } } }
p->b2.a[ 1].i = 0;
p->b2.a[ 2].i = 0; // { dg-warning "\\\[-Warray-bounds" }
p->b2.a[ 3].i = 0; // { dg-warning "\\\[-Warray-bounds" }

View file

@ -7580,6 +7580,188 @@ 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_aligned_store_usage { pattern macro } {
global tool
set result [check_compile slp_aligned_store_usage assembly {
char a[16] __attribute__ ((aligned (16)));
short b[4] __attribute__((aligned(8)));
int c[4] __attribute__((aligned(16)));
#ifdef TEST_V8QI
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;
}
#elif TEST_V16QI
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;
}
#elif TEST_V4QI
void
foo2 ()
{
a[0] = 0;
a[1] = 1;
a[2] = 2;
a[3] = 3;
}
#elif TEST_V2QI
void
foo3 ()
{
a[0] = 0;
a[1] = 1;
}
#elif TEST_V2HI
void
foo4 ()
{
b[0] = 0;
b[1] = 1;
}
#elif TEST_V4HI
void
foo5 ()
{
b[0] = 0;
b[1] = 1;
b[2] = 2;
b[3] = 3;
}
#elif TEST_V2SI
void
foo6 ()
{
c[0] = 0;
c[1] = 1;
}
#elif TEST_V4SI
void
foo7 ()
{
c[0] = 0;
c[1] = 1;
c[2] = 2;
c[3] = 3;
}
#endif
} "-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
# Check pattern exits in lines, set it to zero if not found.
if { [regexp $pattern $lines] } then {
return 1
}
return 0
}
# Return the true if target support vectorization of 2-byte char stores
# with 2-byte aligned address at plain O2.
proc check_effective_target_vect_slp_v2qi_store { } {
set pattern {add new stmt: MEM <vector\(2\) char>}
set macro "TEST_V2QI"
return [check_cached_effective_target vect_slp_v2qi_store {
expr [check_vect_slp_aligned_store_usage $pattern $macro] }]
}
# Return the true if target support vectorization of 4-byte char stores
# with 4-byte aligned address at plain O2.
proc check_effective_target_vect_slp_v4qi_store { } {
set pattern {add new stmt: MEM <vector\(4\) char>}
set macro "TEST_V4QI"
return [check_cached_effective_target vect_slp_v4qi_store {
expr [check_vect_slp_aligned_store_usage $pattern $macro ] }]
}
# Return the true if target support vectorization of 8-byte char stores
# with 8-byte aligned address at plain O2.
proc check_effective_target_vect_slp_v8qi_store { } {
set pattern {add new stmt: MEM <vector\(8\) char>}
set macro "TEST_V8QI"
return [check_cached_effective_target vect_slp_v8qi_store {
expr [check_vect_slp_aligned_store_usage $pattern $macro ] }]
}
# Return the true if target support vectorization of 16-byte char stores
# with 16-byte aligned address at plain O2.
proc check_effective_target_vect_slp_v16qi_store { } {
set pattern {add new stmt: MEM <vector\(16\) char>}
set macro "TEST_V16QI"
return [check_cached_effective_target vect_slp_v16qi_store {
expr [check_vect_slp_aligned_store_usage $pattern $macro ] }]
}
# Return the true if target support vectorization of 4-byte short stores
# with 4-byte aligned address at plain O2.
proc check_effective_target_vect_slp_v2hi_store { } {
set pattern {add new stmt: MEM <vector\(2\) short int>}
set macro "TEST_V2HI"
return [check_cached_effective_target vect_slp_v2hi_store {
expr [check_vect_slp_aligned_store_usage $pattern $macro ] }]
}
# Return the true if target support vectorization of 8-byte short stores
# with 8-byte aligned address at plain O2.
proc check_effective_target_vect_slp_v4hi_store { } {
set pattern {add new stmt: MEM <vector\(4\) short int>}
set macro "TEST_V4HI"
return [check_cached_effective_target vect_slp_v4hi_store {
expr [check_vect_slp_aligned_store_usage $pattern $macro ] }]
}
# Return the true if target support vectorization of 8-byte int stores
# with 8-byte aligned address at plain O2.
proc check_effective_target_vect_slp_v2si_store { } {
set pattern {add new stmt: MEM <vector\(2\) int>}
set macro "TEST_V2SI"
return [check_cached_effective_target vect_slp_v2si_store {
expr [check_vect_slp_aligned_store_usage $pattern $macro ] }]
}
# Return the true if target support vectorization of 16-byte int stores
# with 16-byte aligned address at plain O2.
proc check_effective_target_vect_slp_v4si_store { } {
set pattern {add new stmt: MEM <vector\(4\) int>}
set macro "TEST_V4SI"
return [check_cached_effective_target vect_slp_v4si_store {
expr [check_vect_slp_aligned_store_usage $pattern $macro ] }]
}
# Return 1 if we can align stack data to the preferred vector alignment.
proc check_effective_target_vect_align_stack_vars { } {