From d90ffcfb7d105d004cf04911a42935be03256b49 Mon Sep 17 00:00:00 2001 From: Martin Jambor Date: Fri, 8 Dec 2017 13:11:02 +0100 Subject: [PATCH] Prevent SRA from removing type changing assignment 2017-12-08 Martin Jambor PR tree-optimization/83141 * tree-sra.c (contains_vce_or_bfcref_p): Move up in the file, also test for MEM_REFs implicitely changing types with padding. Remove inline keyword. (build_accesses_from_assign): Added contains_vce_or_bfcref_p checks. testsuite/ * gcc.dg/tree-ssa/pr83141.c: New test. * gcc.dg/guality/pr54970.c: XFAIL tests querying a[0]. From-SVN: r255510 --- gcc/ChangeLog | 8 +++++ gcc/testsuite/ChangeLog | 6 ++++ gcc/testsuite/gcc.dg/guality/pr54970.c | 10 +++--- gcc/testsuite/gcc.dg/tree-ssa/pr83141.c | 37 ++++++++++++++++++++++ gcc/tree-sra.c | 54 +++++++++++++++++++++------------ 5 files changed, 91 insertions(+), 24 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr83141.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 0bc9703..8184c66 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2017-12-08 Martin Jambor + + PR tree-optimization/83141 + * tree-sra.c (contains_vce_or_bfcref_p): Move up in the file, also + test for MEM_REFs implicitely changing types with padding. Remove + inline keyword. + (build_accesses_from_assign): Added contains_vce_or_bfcref_p checks. + 2017-12-08 Jakub Jelinek * config/arc/arc.c (arc_attribute_table): Add exclusions to diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index cae9220..7d03796 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2017-12-08 Martin Jambor + + PR tree-optimization/83141 + * gcc.dg/tree-ssa/pr83141.c: New test. + * gcc.dg/guality/pr54970.c: XFAIL tests querying a[0]. + 2017-12-08 Jan Hubicka PR middle-end/83609 diff --git a/gcc/testsuite/gcc.dg/guality/pr54970.c b/gcc/testsuite/gcc.dg/guality/pr54970.c index a9b8c06..1819d02 100644 --- a/gcc/testsuite/gcc.dg/guality/pr54970.c +++ b/gcc/testsuite/gcc.dg/guality/pr54970.c @@ -24,23 +24,23 @@ main () /* { dg-final { gdb-test 25 "*p" "13" } } */ asm volatile (NOP); /* { dg-final { gdb-test 25 "*q" "12" } } */ __builtin_memcpy (&a, (int [3]) { 4, 5, 6 }, sizeof (a)); - /* { dg-final { gdb-test 31 "a\[0\]" "4" } } */ + /* { dg-final { gdb-test 31 "a\[0\]" "4" { xfail { *-*-* } } } } */ /* { dg-final { gdb-test 31 "a\[1\]" "5" } } */ /* { dg-final { gdb-test 31 "a\[2\]" "6" } } */ /* { dg-final { gdb-test 31 "*p" "6" } } */ asm volatile (NOP); /* { dg-final { gdb-test 31 "*q" "5" } } */ - *p += 20; /* { dg-final { gdb-test 36 "a\[0\]" "4" } } */ + *p += 20; /* { dg-final { gdb-test 36 "a\[0\]" "4" { xfail { *-*-* } } } } */ /* { dg-final { gdb-test 36 "a\[1\]" "5" } } */ /* { dg-final { gdb-test 36 "a\[2\]" "26" } } */ /* { dg-final { gdb-test 36 "*p" "26" } } */ asm volatile (NOP); /* { dg-final { gdb-test 36 "*q" "5" } } */ - *q += 20; /* { dg-final { gdb-test 45 "a\[0\]" "4" } } */ + *q += 20; /* { dg-final { gdb-test 45 "a\[0\]" "4" { xfail { *-*-* } } } } */ /* { dg-final { gdb-test 45 "a\[1\]" "25" } } */ /* { dg-final { gdb-test 45 "a\[2\]" "26" } } */ /* { dg-final { gdb-test 45 "*p" "26" } } */ /* { dg-final { gdb-test 45 "p\[-1\]" "25" } } */ - /* { dg-final { gdb-test 45 "p\[-2\]" "4" } } */ - /* { dg-final { gdb-test 45 "q\[-1\]" "4" } } */ + /* { dg-final { gdb-test 45 "p\[-2\]" "4" { xfail { *-*-* } } } } */ + /* { dg-final { gdb-test 45 "q\[-1\]" "4" { xfail { *-*-* } } } } */ /* { dg-final { gdb-test 45 "q\[1\]" "26" } } */ asm volatile (NOP); /* { dg-final { gdb-test 45 "*q" "25" } } */ return 0; diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr83141.c b/gcc/testsuite/gcc.dg/tree-ssa/pr83141.c new file mode 100644 index 0000000..73ea45c --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr83141.c @@ -0,0 +1,37 @@ +/* { dg-do run } */ +/* { dg-options "-O -fdump-tree-esra-details" } */ + +volatile short vs; +volatile long vl; + +struct A { short s; long i; long j; }; +struct A a, b; +void foo () +{ + struct A c; + __builtin_memcpy (&c, &b, sizeof (struct A)); + __builtin_memcpy (&a, &c, sizeof (struct A)); + + vs = c.s; + vl = c.i; + vl = c.j; +} + + +int main() +{ + if ((sizeof (short) != 2) + || (__builtin_offsetof (struct A, i) < 4)) + return 0; + + __builtin_memset (&b, 0, sizeof (struct A)); + b.s = 1; + __builtin_memcpy ((char *)&b+2, &b, 2); + foo (); + __builtin_memcpy (&a, (char *)&a+2, 2); + if (a.s != 1) + __builtin_abort (); + return 0; +} + +/* { dg-final { scan-tree-dump-not "Will attempt to totally scalarize" "esra" } } */ diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c index 866cff0..54f1c8d 100644 --- a/gcc/tree-sra.c +++ b/gcc/tree-sra.c @@ -1141,6 +1141,33 @@ contains_view_convert_expr_p (const_tree ref) return false; } +/* Return true if REF contains a VIEW_CONVERT_EXPR or a MEM_REF that performs + type conversion or a COMPONENT_REF with a bit-field field declaration. */ + +static bool +contains_vce_or_bfcref_p (const_tree ref) +{ + while (handled_component_p (ref)) + { + if (TREE_CODE (ref) == VIEW_CONVERT_EXPR + || (TREE_CODE (ref) == COMPONENT_REF + && DECL_BIT_FIELD (TREE_OPERAND (ref, 1)))) + return true; + ref = TREE_OPERAND (ref, 0); + } + + if (TREE_CODE (ref) != MEM_REF + || TREE_CODE (TREE_OPERAND (ref, 0)) != ADDR_EXPR) + return false; + + tree mem = TREE_OPERAND (TREE_OPERAND (ref, 0), 0); + if (TYPE_MAIN_VARIANT (TREE_TYPE (ref)) + != TYPE_MAIN_VARIANT (TREE_TYPE (mem))) + return true; + + return false; +} + /* Search the given tree for a declaration by skipping handled components and exclude it from the candidates. */ @@ -1339,7 +1366,14 @@ build_accesses_from_assign (gimple *stmt) racc->grp_assignment_read = 1; if (should_scalarize_away_bitmap && !gimple_has_volatile_ops (stmt) && !is_gimple_reg_type (racc->type)) - bitmap_set_bit (should_scalarize_away_bitmap, DECL_UID (racc->base)); + { + if (contains_vce_or_bfcref_p (rhs)) + bitmap_set_bit (cannot_scalarize_away_bitmap, + DECL_UID (racc->base)); + else + bitmap_set_bit (should_scalarize_away_bitmap, + DECL_UID (racc->base)); + } if (storage_order_barrier_p (lhs)) racc->grp_unscalarizable_region = 1; } @@ -3416,24 +3450,6 @@ get_repl_default_def_ssa_name (struct access *racc) return get_or_create_ssa_default_def (cfun, racc->replacement_decl); } -/* Return true if REF has an VIEW_CONVERT_EXPR or a COMPONENT_REF with a - bit-field field declaration somewhere in it. */ - -static inline bool -contains_vce_or_bfcref_p (const_tree ref) -{ - while (handled_component_p (ref)) - { - if (TREE_CODE (ref) == VIEW_CONVERT_EXPR - || (TREE_CODE (ref) == COMPONENT_REF - && DECL_BIT_FIELD (TREE_OPERAND (ref, 1)))) - return true; - ref = TREE_OPERAND (ref, 0); - } - - return false; -} - /* Examine both sides of the assignment statement pointed to by STMT, replace them with a scalare replacement if there is one and generate copying of replacements if scalarized aggregates have been used in the assignment. GSI -- 2.7.4