From 5f9cd512c4278621435cce486dd00248ea2e821c Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Thu, 27 Feb 2020 10:12:52 +0100 Subject: [PATCH] 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 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. --- gcc/ChangeLog | 8 ++++ gcc/testsuite/ChangeLog | 7 +++ gcc/testsuite/gcc.c-torture/execute/pr93945.c | 45 +++++++++++++++++++ gcc/testsuite/gcc.dg/tree-ssa/pr93582-9.c | 23 ++++++++++ gcc/tree-ssa-sccvn.c | 42 ++++++++++++++--- 5 files changed, 119 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/gcc.c-torture/execute/pr93945.c create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr93582-9.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9665bd11dc7..38bfbb95474 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2020-02-27 Jakub Jelinek + + 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 * doc/install.texi (Binaries): Update description of BullFreeware. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 085537d977b..70897c5f94c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2020-02-27 Jakub Jelinek + + 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 PR c++/93789 - ICE with invalid array bounds. diff --git a/gcc/testsuite/gcc.c-torture/execute/pr93945.c b/gcc/testsuite/gcc.c-torture/execute/pr93945.c new file mode 100644 index 00000000000..99e455cce52 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr93945.c @@ -0,0 +1,45 @@ +/* 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; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr93582-9.c b/gcc/testsuite/gcc.dg/tree-ssa/pr93582-9.c new file mode 100644 index 00000000000..b6ad46516fd --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr93582-9.c @@ -0,0 +1,23 @@ +/* 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; +} diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c index a3fba2878f8..0487f59f13f 100644 --- a/gcc/tree-ssa-sccvn.c +++ b/gcc/tree-ssa-sccvn.c @@ -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 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; -- 2.30.2