aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2004-04-13 20:31:19 +0000
committerJakub Jelinek <jakub@redhat.com>2004-04-13 20:31:19 +0000
commita1d13db591564ede383556ddca18660e3e2443ef (patch)
treec129f714b3e896a0ae2c0dc335ef5e604feae9af
parent7c12e63ee9cc362171c2c6243ebcae35a68dad46 (diff)
2004-04-02 Jakub Jelinek <jakuB@redhat.com>
Eric Botcazou <ebotcazou@libertysurf.fr> 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 <glen@imodulo.com> * 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
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/explow.c1
-rw-r--r--gcc/expr.c42
-rw-r--r--gcc/testsuite/ChangeLog10
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/20040401-1.c74
-rw-r--r--gcc/testsuite/gcc.dg/20040302-1.c18
6 files changed, 148 insertions, 6 deletions
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 <jakuB@redhat.com>
+ Eric Botcazou <ebotcazou@libertysurf.fr>
+
+ 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 <jakub@redhat.com>
* 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 <jakuB@redhat.com>
+ Eric Botcazou <ebotcazou@libertysurf.fr>
+
+ * gcc.dg/20040302-1.c: New test.
+ * gcc.c-torture/execute/20040401-1.c: New test.
+
+2003-04-08 Glen Nakamura <glen@imodulo.com>
+
+ * gcc.c-torture/execute/20030408-1.c: New test.
+
2004-04-01 Jakub Jelinek <jakub@redhat.com>
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;
+}