From a1d13db591564ede383556ddca18660e3e2443ef Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Tue, 13 Apr 2004 20:31:19 +0000 Subject: 2004-04-02 Jakub Jelinek Eric Botcazou PR optimization/13424, optimization/12419 * explow.c (maybe_set_unchanging): Revert 2003-04-07 patch. * expr.c (store_constructor): When clearing aggregate because of an incomplete or mostly zero constructor, do the clearing without /u flag and then emit a blockage. * gcc.dg/20040302-1.c: New test. * gcc.c-torture/execute/20040401-1.c: New test. 2003-04-08 Glen Nakamura * gcc.c-torture/execute/20030408-1.c: New test. git-svn-id: https://gcc.gnu.org/svn/gcc/branches/gcc-3_3-rhl-branch@80655 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 9 +++ gcc/explow.c | 1 - gcc/expr.c | 42 ++++++++++++-- gcc/testsuite/ChangeLog | 10 ++++ gcc/testsuite/gcc.c-torture/execute/20040401-1.c | 74 ++++++++++++++++++++++++ gcc/testsuite/gcc.dg/20040302-1.c | 18 ++++++ 6 files changed, 148 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/gcc.c-torture/execute/20040401-1.c create mode 100644 gcc/testsuite/gcc.dg/20040302-1.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6afe21761fe..d3e0d8bd1dc 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2004-04-02 Jakub Jelinek + Eric Botcazou + + PR optimization/13424, optimization/12419 + * explow.c (maybe_set_unchanging): Revert 2003-04-07 patch. + * expr.c (store_constructor): When clearing aggregate because + of an incomplete or mostly zero constructor, do the clearing + without /u flag and then emit a blockage. + 2004-03-27 Jakub Jelinek * config/i386/i386.c (override_options): Add PTA_64BIT, set it diff --git a/gcc/explow.c b/gcc/explow.c index c66a8e765bf..bef4f90b1b4 100644 --- a/gcc/explow.c +++ b/gcc/explow.c @@ -673,7 +673,6 @@ maybe_set_unchanging (ref, t) solution, perhaps based on alias sets. */ if ((TREE_READONLY (t) && DECL_P (t) - && (TREE_STATIC (t) || ! AGGREGATE_TYPE_P (TREE_TYPE (t))) && (TREE_CODE (t) == PARM_DECL || DECL_INITIAL (t) == NULL_TREE || TREE_CONSTANT (DECL_INITIAL (t)))) diff --git a/gcc/expr.c b/gcc/expr.c index fa3d10ea2d7..c31eba65542 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -5021,14 +5021,27 @@ store_constructor (exp, target, cleared, size) { rtx xtarget = target; - if (readonly_fields_p (type)) + if (RTX_UNCHANGING_P (target)) { - xtarget = copy_rtx (xtarget); - RTX_UNCHANGING_P (xtarget) = 1; + xtarget = copy_rtx (target); + RTX_UNCHANGING_P (xtarget) = 0; } clear_storage (xtarget, GEN_INT (size)); cleared = 1; + if (RTX_UNCHANGING_P (target) || readonly_fields_p (type)) + { + /* ??? Emit a blockage to prevent the scheduler from swapping + the memory write issued above without the /u flag and + memory writes that will be issued later with it. + Note that the clearing above cannot be simply disabled + in the unsafe cases because the C front-end relies on + it to implement the semantics of constructors for + automatic objects. However, not all machine descriptions + define a blockage insn, so emit an ASM_INPUT to + act as one. */ + emit_insn (gen_rtx_ASM_INPUT (VOIDmode, "")); + } } if (! cleared) @@ -5242,9 +5255,28 @@ store_constructor (exp, target, cleared, size) if (! cleared) { if (REG_P (target)) - emit_move_insn (target, CONST0_RTX (GET_MODE (target))); + emit_move_insn (target, CONST0_RTX (GET_MODE (target))); else - clear_storage (target, GEN_INT (size)); + { + rtx xtarget = target; + + if (RTX_UNCHANGING_P (target)) + { + xtarget = copy_rtx (target); + RTX_UNCHANGING_P (xtarget) = 0; + } + + clear_storage (xtarget, GEN_INT (size)); + + if (RTX_UNCHANGING_P (target)) + { + /* ??? Emit a blockage to prevent the scheduler from + swapping the memory write issued above without the + /u flag and memory writes that will be issued later + with it. */ + emit_insn (gen_rtx_ASM_INPUT (VOIDmode, "")); + } + } } cleared = 1; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 18a65adae17..a80e7d49f8b 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,13 @@ +2004-04-02 Jakub Jelinek + Eric Botcazou + + * gcc.dg/20040302-1.c: New test. + * gcc.c-torture/execute/20040401-1.c: New test. + +2003-04-08 Glen Nakamura + + * gcc.c-torture/execute/20030408-1.c: New test. + 2004-04-01 Jakub Jelinek PR c++/14755 diff --git a/gcc/testsuite/gcc.c-torture/execute/20040401-1.c b/gcc/testsuite/gcc.c-torture/execute/20040401-1.c new file mode 100644 index 00000000000..d74afda4707 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/20040401-1.c @@ -0,0 +1,74 @@ +/* PR optimization/8634 */ + +extern void abort (void); + +struct foo { + const char a, b, c, d, e, f, g, h, i, j; +}; + +struct bar { + const char a, b, c, d, e, f, g, h, i; + char j; +}; + +int test1 () +{ + struct foo X = { a : 'A', c : 'C', e : 'E', g : 'G', i : 'I' }; + char buffer[10]; + __builtin_memcpy (buffer, &X, 10); + if (buffer[0] != 'A' || buffer[1] != '\0' + || buffer[2] != 'C' || buffer[3] != '\0' + || buffer[4] != 'E' || buffer[5] != '\0' + || buffer[6] != 'G' || buffer[7] != '\0' + || buffer[8] != 'I' || buffer[9] != '\0') + abort (); + return 0; +} + +int test2 () +{ + struct bar X = { a : 'A', c : 'C', e : 'E', g : 'G', i : 'I' }; + char buffer[10]; + __builtin_memcpy (buffer, &X, 10); + if (buffer[0] != 'A' || buffer[1] != '\0' + || buffer[2] != 'C' || buffer[3] != '\0' + || buffer[4] != 'E' || buffer[5] != '\0' + || buffer[6] != 'G' || buffer[7] != '\0' + || buffer[8] != 'I' || buffer[9] != '\0') + abort (); + return 0; +} + +int test3 () +{ + struct foo X = { .b = 'B', .d = 'D', .f = 'F', .h = 'H' , .j = 'J' }; + char buffer[10]; + __builtin_memcpy (buffer, &X, 10); + if (buffer[0] != '\0' || buffer[1] != 'B' + || buffer[2] != '\0' || buffer[3] != 'D' + || buffer[4] != '\0' || buffer[5] != 'F' + || buffer[6] != '\0' || buffer[7] != 'H' + || buffer[8] != '\0' || buffer[9] != 'J') + abort (); + return 0; +} + +int test4 () +{ + struct bar X = { .b = 'B', .d = 'D', .f = 'F', .h = 'H' , .j = 'J' }; + char buffer[10]; + __builtin_memcpy (buffer, &X, 10); + if (buffer[0] != '\0' || buffer[1] != 'B' + || buffer[2] != '\0' || buffer[3] != 'D' + || buffer[4] != '\0' || buffer[5] != 'F' + || buffer[6] != '\0' || buffer[7] != 'H' + || buffer[8] != '\0' || buffer[9] != 'J') + abort (); + return 0; +} + +int main () +{ + test1 (); test2 (); test3 (); test4 (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/20040302-1.c b/gcc/testsuite/gcc.dg/20040302-1.c new file mode 100644 index 00000000000..f6ada1f22c2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/20040302-1.c @@ -0,0 +1,18 @@ +/* PR optimization/12419 */ +/* Ensure external_const_array[0] is read just once. */ +/* { dg-do compile { target i?86-*-linux* x86_64-*-linux* } } */ +/* { dg-options "-O2" } */ +/* { dg-final { scan-assembler "external_const_array" } } */ +/* { dg-final { scan-assembler-not "external_const_array.*add\[^\\n\]*external_const_array" } } */ + +extern const int external_const_array []; +extern void foo (void); + +int +bar (void) +{ + int n = external_const_array[0]; + foo (); + n += external_const_array[0]; + return n; +} -- cgit v1.2.3