diff options
author | Jakub Jelinek <jakub@redhat.com> | 2007-11-20 11:36:03 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2007-11-20 11:36:03 +0100 |
commit | 7ef249e59f5763183e110ad98531645f3030a82c (patch) | |
tree | 0c4dfd8db5db25e7f3e83f89dc36db48d511e3fa | |
parent | cae85ca91aadc601f13f814bbc6527f54293d843 (diff) | |
download | gcc-7ef249e59f5763183e110ad98531645f3030a82c.zip gcc-7ef249e59f5763183e110ad98531645f3030a82c.tar.gz gcc-7ef249e59f5763183e110ad98531645f3030a82c.tar.bz2 |
re PR c/34146 (Inefficient code with compound literals inside a CONSTRUCTO)
PR c/34146
* c-gimplify.c (optimize_compound_literals_in_ctor): New function.
(c_gimplify_expr): Use it.
PR c/34146
* gcc.dg/tree-ssa/pr34146.c: New test.
PR testsuite/33978
* gcc.dg/tree-ssa/pr33723.c: Adjust scan pattern to make it less
dependent on target settings like move_by_pieces etc.
From-SVN: r130311
-rw-r--r-- | gcc/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/c-gimplify.c | 53 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/pr33723.c | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/pr34146.c | 53 |
5 files changed, 120 insertions, 3 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7b39d8b..5625617 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2007-11-20 Jakub Jelinek <jakub@redhat.com> + + PR c/34146 + * c-gimplify.c (optimize_compound_literals_in_ctor): New function. + (c_gimplify_expr): Use it. + 2007-11-20 Ben Elliston <bje@au.ibm.com> * config/spu/spu_mfcio.h: Fix typo. diff --git a/gcc/c-gimplify.c b/gcc/c-gimplify.c index a1ee27b..12292a7 100644 --- a/gcc/c-gimplify.c +++ b/gcc/c-gimplify.c @@ -208,6 +208,47 @@ gimplify_compound_literal_expr (tree *expr_p, tree *pre_p) return GS_OK; } +/* Optimize embedded COMPOUND_LITERAL_EXPRs within a CONSTRUCTOR, + return a new CONSTRUCTOR if something changed. */ + +static tree +optimize_compound_literals_in_ctor (tree orig_ctor) +{ + tree ctor = orig_ctor; + VEC(constructor_elt,gc) *elts = CONSTRUCTOR_ELTS (ctor); + unsigned int idx, num = VEC_length (constructor_elt, elts); + + for (idx = 0; idx < num; idx++) + { + tree value = VEC_index (constructor_elt, elts, idx)->value; + tree newval = value; + if (TREE_CODE (value) == CONSTRUCTOR) + newval = optimize_compound_literals_in_ctor (value); + else if (TREE_CODE (value) == COMPOUND_LITERAL_EXPR) + { + tree decl_s = COMPOUND_LITERAL_EXPR_DECL_STMT (value); + tree decl = DECL_EXPR_DECL (decl_s); + tree init = DECL_INITIAL (decl); + + if (!TREE_ADDRESSABLE (value) + && !TREE_ADDRESSABLE (decl) + && init) + newval = init; + } + if (newval == value) + continue; + + if (ctor == orig_ctor) + { + ctor = copy_node (orig_ctor); + CONSTRUCTOR_ELTS (ctor) = VEC_copy (constructor_elt, gc, elts); + elts = CONSTRUCTOR_ELTS (ctor); + } + VEC_index (constructor_elt, elts, idx)->value = newval; + } + return ctor; +} + /* Do C-specific gimplification. Args are as for gimplify_expr. */ int @@ -254,6 +295,18 @@ c_gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p ATTRIBUTE_UNUSED) return GS_OK; } } + else if (TREE_CODE (TREE_OPERAND (*expr_p, 1)) == CONSTRUCTOR) + { + tree ctor + = optimize_compound_literals_in_ctor (TREE_OPERAND (*expr_p, 1)); + + if (ctor != TREE_OPERAND (*expr_p, 1)) + { + *expr_p = copy_node (*expr_p); + TREE_OPERAND (*expr_p, 1) = ctor; + return GS_OK; + } + } return GS_UNHANDLED; default: diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index cd4b067..c01f3ae 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,12 @@ 2007-11-20 Jakub Jelinek <jakub@redhat.com> + PR c/34146 + * gcc.dg/tree-ssa/pr34146.c: New test. + + PR testsuite/33978 + * gcc.dg/tree-ssa/pr33723.c: Adjust scan pattern to make it less + dependent on target settings like move_by_pieces etc. + PR c++/28879 * g++.dg/template/vla2.C: New test. diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr33723.c b/gcc/testsuite/gcc.dg/tree-ssa/pr33723.c index 6c07682..32a3aad 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/pr33723.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr33723.c @@ -68,7 +68,5 @@ baz3 (void) test (&t); } -/* { dg-final { scan-tree-dump-times "t = {}" 3 "gimple"} } */ -/* { dg-final { scan-tree-dump-times "t.f.f1 = 1" 4 "gimple"} } */ -/* { dg-final { scan-tree-dump-times "t.f.f8 = 8" 4 "gimple"} } */ +/* { dg-final { scan-tree-dump-not "t = D" "gimple"} } */ /* { dg-final { cleanup-tree-dump "gimple" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr34146.c b/gcc/testsuite/gcc.dg/tree-ssa/pr34146.c new file mode 100644 index 0000000..99fdeb5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr34146.c @@ -0,0 +1,53 @@ +/* PR c/34146 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-gimple" } */ + +struct A +{ + int f1, f2, f3; +}; + +struct B +{ + struct A g1, g2; +}; + +struct C +{ + struct B h1, h2; +}; + +typedef union +{ + struct C c; + char s[4]; + long int a; +} T; + +void +foo (void) +{ + T t = { { { { 0, 0, 0 }, { 0, 0, 0 } }, { { 0, 0, 0 }, { 0, 0, 0 } } } }; + test (&t); +} + +void +bar (void) +{ + T t = { { { { 0, 0, 0 }, (struct A) { 0, 0, 0 } }, + (struct B) { (struct A) { 0, 0, 0 }, { 0, 0, 0 } } } }; + test (&t); +} + +void +baz (void) +{ + T t = { { { { 0, 0, 0 }, (struct A) { 1, 1, 1 } }, + (struct B) { (struct A) { 0, 0, 0 }, { 1, 1, 1 } } } }; + test (&t); +} + +/* { dg-final { scan-tree-dump-not "t = D" "gimple"} } */ +/* { dg-final { scan-tree-dump-not "t\.c\.h\[12\] = D" "gimple"} } */ +/* { dg-final { scan-tree-dump-not "\.g\[12\] = D" "gimple"} } */ +/* { dg-final { cleanup-tree-dump "gimple" } } */ |