Commit 5f9cd512 by Jakub Jelinek

sccvn: Handle non-byte aligned offset or size for memset (, 123, ) [PR93945]

The following is the last spot in vn_reference_lookup_3 that didn't allow
non-byte aligned offsets or sizes.  To be precise, it did allow size that
wasn't multiple of byte size and that caused a wrong-code issue on
big-endian, as the pr93945.c testcase shows, so for GCC 9 we should add
&& multiple_p (ref->size, BITS_PER_UNIT) check instead.
For the memset with SSA_NAME middle-argument, it still requires byte-aligned
offset, as we'd otherwise need to rotate the value at runtime.

2020-02-27  Jakub Jelinek  <jakub@redhat.com>

	PR tree-optimization/93582
	PR tree-optimization/93945
	* tree-ssa-sccvn.c (vn_reference_lookup_3): Handle memset with
	non-zero INTEGER_CST second argument and ref->offset or ref->size
	not a multiple of BITS_PER_UNIT.

	* gcc.dg/tree-ssa/pr93582-9.c: New test.
	* gcc.c-torture/execute/pr93945.c: New test.
parent 4fd9efc8
2020-02-27 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/93582
PR tree-optimization/93945
* tree-ssa-sccvn.c (vn_reference_lookup_3): Handle memset with
non-zero INTEGER_CST second argument and ref->offset or ref->size
not a multiple of BITS_PER_UNIT.
2020-02-27 Jonathan Wakely <jwakely@redhat.com>
* doc/install.texi (Binaries): Update description of BullFreeware.
......
2020-02-27 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/93582
PR tree-optimization/93945
* gcc.dg/tree-ssa/pr93582-9.c: New test.
* gcc.c-torture/execute/pr93945.c: New test.
2020-02-26 Marek Polacek <polacek@redhat.com>
PR c++/93789 - ICE with invalid array bounds.
......
/* PR tree-optimization/93945 */
union U { char a[8]; struct S { unsigned int b : 8, c : 13, d : 11; } e; } u;
__attribute__((noipa)) int
foo (void)
{
__builtin_memset (&u.a, 0xf4, sizeof (u.a));
return u.e.c;
}
__attribute__((noipa)) int
bar (void)
{
asm volatile ("" : : "g" (&u) : "memory");
return u.e.c;
}
__attribute__((noipa)) int
baz (void)
{
__builtin_memset (&u.a, 0xf4, sizeof (u.a));
return u.e.d;
}
__attribute__((noipa)) int
qux (void)
{
asm volatile ("" : : "g" (&u) : "memory");
return u.e.d;
}
int
main ()
{
int a = foo ();
int b = bar ();
if (a != b)
__builtin_abort ();
a = baz ();
b = qux ();
if (a != b)
__builtin_abort ();
return 0;
}
/* PR tree-optimization/93582 */
/* { dg-do compile { target int32 } } */
/* { dg-options "-O2 -fdump-tree-fre1" } */
/* { dg-final { scan-tree-dump "return 5364;" "fre1" { target le } } } */
/* { dg-final { scan-tree-dump "return 7838;" "fre1" { target be } } } */
/* { dg-final { scan-tree-dump "return 1959;" "fre1" { target le } } } */
/* { dg-final { scan-tree-dump "return 1268;" "fre1" { target be } } } */
union U { char a[8]; struct S { unsigned int b : 8, c : 13, d : 11; } e; } u;
__attribute__((noipa)) int
foo (void)
{
__builtin_memset (&u.a, 0xf4, sizeof (u.a));
return u.e.c;
}
__attribute__((noipa)) int
baz (void)
{
__builtin_memset (&u.a, 0xf4, sizeof (u.a));
return u.e.d;
}
......@@ -2386,7 +2386,7 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_,
vn_reference_t vr = data->vr;
gimple *def_stmt = SSA_NAME_DEF_STMT (vuse);
tree base = ao_ref_base (ref);
HOST_WIDE_INT offseti, maxsizei;
HOST_WIDE_INT offseti = 0, maxsizei, sizei = 0;
static vec<vn_reference_op_s> lhs_ops;
ao_ref lhs_ref;
bool lhs_ref_ok = false;
......@@ -2541,9 +2541,13 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_,
&& (integer_zerop (gimple_call_arg (def_stmt, 1))
|| ((TREE_CODE (gimple_call_arg (def_stmt, 1)) == INTEGER_CST
|| (INTEGRAL_TYPE_P (vr->type) && known_eq (ref->size, 8)))
&& CHAR_BIT == 8 && BITS_PER_UNIT == 8
&& CHAR_BIT == 8
&& BITS_PER_UNIT == 8
&& BYTES_BIG_ENDIAN == WORDS_BIG_ENDIAN
&& offset.is_constant (&offseti)
&& offseti % BITS_PER_UNIT == 0))
&& ref->size.is_constant (&sizei)
&& (offseti % BITS_PER_UNIT == 0
|| TREE_CODE (gimple_call_arg (def_stmt, 1)) == INTEGER_CST)))
&& poly_int_tree_p (gimple_call_arg (def_stmt, 2))
&& (TREE_CODE (gimple_call_arg (def_stmt, 0)) == ADDR_EXPR
|| TREE_CODE (gimple_call_arg (def_stmt, 0)) == SSA_NAME))
......@@ -2604,7 +2608,7 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_,
else
return (void *)-1;
tree len = gimple_call_arg (def_stmt, 2);
HOST_WIDE_INT leni, offset2i, offseti;
HOST_WIDE_INT leni, offset2i;
/* Sometimes the above trickery is smarter than alias analysis. Take
advantage of that. */
if (!ranges_maybe_overlap_p (offset, maxsize, offset2,
......@@ -2618,7 +2622,9 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_,
tree val;
if (integer_zerop (gimple_call_arg (def_stmt, 1)))
val = build_zero_cst (vr->type);
else if (INTEGRAL_TYPE_P (vr->type) && known_eq (ref->size, 8))
else if (INTEGRAL_TYPE_P (vr->type)
&& known_eq (ref->size, 8)
&& offseti % BITS_PER_UNIT == 0)
{
gimple_match_op res_op (gimple_match_cond::UNCOND, NOP_EXPR,
vr->type, gimple_call_arg (def_stmt, 1));
......@@ -2630,10 +2636,34 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_,
}
else
{
unsigned buflen = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (vr->type));
unsigned buflen = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (vr->type)) + 1;
if (INTEGRAL_TYPE_P (vr->type))
buflen = GET_MODE_SIZE (SCALAR_INT_TYPE_MODE (vr->type)) + 1;
unsigned char *buf = XALLOCAVEC (unsigned char, buflen);
memset (buf, TREE_INT_CST_LOW (gimple_call_arg (def_stmt, 1)),
buflen);
if (BYTES_BIG_ENDIAN)
{
unsigned int amnt
= (((unsigned HOST_WIDE_INT) offseti + sizei)
% BITS_PER_UNIT);
if (amnt)
{
shift_bytes_in_array_right (buf, buflen,
BITS_PER_UNIT - amnt);
buf++;
buflen--;
}
}
else if (offseti % BITS_PER_UNIT != 0)
{
unsigned int amnt
= BITS_PER_UNIT - ((unsigned HOST_WIDE_INT) offseti
% BITS_PER_UNIT);
shift_bytes_in_array_left (buf, buflen, amnt);
buf++;
buflen--;
}
val = native_interpret_expr (vr->type, buf, buflen);
if (!val)
return (void *)-1;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment