aboutsummaryrefslogtreecommitdiffstats
path: root/main/gcc/pr57748.patch
diff options
context:
space:
mode:
Diffstat (limited to 'main/gcc/pr57748.patch')
-rw-r--r--main/gcc/pr57748.patch295
1 files changed, 295 insertions, 0 deletions
diff --git a/main/gcc/pr57748.patch b/main/gcc/pr57748.patch
new file mode 100644
index 0000000000..23a87ba705
--- /dev/null
+++ b/main/gcc/pr57748.patch
@@ -0,0 +1,295 @@
+http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57748
+(comment #36, attachment 30782)
+
+--- a/gcc/expr.c 2013-08-06 00:09:45.000000000 +0200
++++ b/gcc/expr.c 2013-09-10 08:23:09.570951685 +0200
+@@ -4691,8 +4691,6 @@ expand_assignment (tree to, tree from, b
+ int unsignedp;
+ int volatilep = 0;
+ tree tem;
+- bool misalignp;
+- rtx mem = NULL_RTX;
+
+ push_temp_slots ();
+ tem = get_inner_reference (to, &bitsize, &bitpos, &offset, &mode1,
+@@ -4702,40 +4700,7 @@ expand_assignment (tree to, tree from, b
+ && DECL_BIT_FIELD_TYPE (TREE_OPERAND (to, 1)))
+ get_bit_range (&bitregion_start, &bitregion_end, to, &bitpos, &offset);
+
+- /* If we are going to use store_bit_field and extract_bit_field,
+- make sure to_rtx will be safe for multiple use. */
+- mode = TYPE_MODE (TREE_TYPE (tem));
+- if (TREE_CODE (tem) == MEM_REF
+- && mode != BLKmode
+- && ((align = get_object_alignment (tem))
+- < GET_MODE_ALIGNMENT (mode))
+- && ((icode = optab_handler (movmisalign_optab, mode))
+- != CODE_FOR_nothing))
+- {
+- struct expand_operand ops[2];
+-
+- misalignp = true;
+- to_rtx = gen_reg_rtx (mode);
+- mem = expand_expr (tem, NULL_RTX, VOIDmode, EXPAND_WRITE);
+-
+- /* If the misaligned store doesn't overwrite all bits, perform
+- rmw cycle on MEM. */
+- if (bitsize != GET_MODE_BITSIZE (mode))
+- {
+- create_input_operand (&ops[0], to_rtx, mode);
+- create_fixed_operand (&ops[1], mem);
+- /* The movmisalign<mode> pattern cannot fail, else the assignment
+- would silently be omitted. */
+- expand_insn (icode, 2, ops);
+-
+- mem = copy_rtx (mem);
+- }
+- }
+- else
+- {
+- misalignp = false;
+- to_rtx = expand_expr (tem, NULL_RTX, VOIDmode, EXPAND_WRITE);
+- }
++ to_rtx = expand_expr (tem, NULL_RTX, VOIDmode, EXPAND_WRITE);
+
+ /* If the bitfield is volatile, we want to access it in the
+ field's mode, not the computed mode.
+@@ -4773,6 +4738,8 @@ expand_assignment (tree to, tree from, b
+ if (MEM_P (to_rtx)
+ && GET_MODE (to_rtx) == BLKmode
+ && GET_MODE (XEXP (to_rtx, 0)) != VOIDmode
++ && bitregion_start == 0
++ && bitregion_end == 0
+ && bitsize > 0
+ && (bitpos % bitsize) == 0
+ && (bitsize % GET_MODE_ALIGNMENT (mode1)) == 0
+@@ -4874,17 +4841,6 @@ expand_assignment (tree to, tree from, b
+ get_alias_set (to), nontemporal);
+ }
+
+- if (misalignp)
+- {
+- struct expand_operand ops[2];
+-
+- create_fixed_operand (&ops[0], mem);
+- create_input_operand (&ops[1], to_rtx, mode);
+- /* The movmisalign<mode> pattern cannot fail, else the assignment
+- would silently be omitted. */
+- expand_insn (icode, 2, ops);
+- }
+-
+ if (result)
+ preserve_temp_slots (result);
+ pop_temp_slots ();
+@@ -9905,7 +9861,7 @@ expand_expr_real_1 (tree exp, rtx target
+ && modifier != EXPAND_STACK_PARM
+ ? target : NULL_RTX),
+ VOIDmode,
+- modifier == EXPAND_SUM ? EXPAND_NORMAL : modifier);
++ EXPAND_MEMORY);
+
+ /* If the bitfield is volatile, we want to access it in the
+ field's mode, not the computed mode.
+--- a/gcc/testsuite/gcc.dg/torture/pr57748-1.c 1970-01-01 01:00:00.000000000 +0100
++++ b/gcc/testsuite/gcc.dg/torture/pr57748-1.c 2013-09-06 08:38:03.718686940 +0200
+@@ -0,0 +1,49 @@
++/* PR middle-end/57748 */
++/* { dg-do run } */
++/* ICE in expand_assignment:
++ misalignp == true, !MEM_P (to_rtx), offset != 0,
++ => gcc_assert (TREE_CODE (offset) == INTEGER_CST) */
++
++#include <stdlib.h>
++
++extern void abort (void);
++
++typedef long long V
++ __attribute__ ((vector_size (2 * sizeof (long long)), may_alias));
++
++typedef struct S { V a; V b[0]; } P __attribute__((aligned (1)));
++
++struct __attribute__((packed)) T { char c; P s; };
++
++void __attribute__((noinline, noclone))
++check (struct T *t)
++{
++ if (t->s.b[0][0] != 3 || t->s.b[0][1] != 4)
++ abort ();
++}
++
++int __attribute__((noinline, noclone))
++get_i (void)
++{
++ return 0;
++}
++
++void __attribute__((noinline, noclone))
++foo (P *p)
++{
++ V a = { 3, 4 };
++ int i = get_i ();
++ p->b[i] = a;
++}
++
++int
++main ()
++{
++ struct T *t = (struct T *) calloc (128, 1);
++
++ foo (&t->s);
++ check (t);
++
++ free (t);
++ return 0;
++}
+--- a/gcc/testsuite/gcc.dg/torture/pr57748-2.c 1970-01-01 01:00:00.000000000 +0100
++++ b/gcc/testsuite/gcc.dg/torture/pr57748-2.c 2013-09-06 08:38:03.718686940 +0200
+@@ -0,0 +1,43 @@
++/* PR middle-end/57748 */
++/* { dg-do run } */
++/* wrong code in expand_assignment:
++ misalignp == true, !MEM_P (to_rtx),
++ offset == 0, bitpos >= GET_MODE_PRECISION,
++ => result = NULL. */
++
++#include <stdlib.h>
++
++extern void abort (void);
++
++typedef long long V
++ __attribute__ ((vector_size (2 * sizeof (long long)), may_alias));
++
++typedef struct S { V a; V b[0]; } P __attribute__((aligned (1)));
++
++struct __attribute__((packed)) T { char c; P s; };
++
++void __attribute__((noinline, noclone))
++check (struct T *t)
++{
++ if (t->s.b[0][0] != 3 || t->s.b[0][1] != 4)
++ abort ();
++}
++
++void __attribute__((noinline, noclone))
++foo (P *p)
++{
++ V a = { 3, 4 };
++ p->b[0] = a;
++}
++
++int
++main ()
++{
++ struct T *t = (struct T *) calloc (128, 1);
++
++ foo (&t->s);
++ check (t);
++
++ free (t);
++ return 0;
++}
+--- a/gcc/testsuite/gcc.dg/torture/pr57748-3.c 1970-01-01 01:00:00.000000000 +0100
++++ b/gcc/testsuite/gcc.dg/torture/pr57748-3.c 2013-09-09 09:54:28.937891452 +0200
+@@ -0,0 +1,49 @@
++/* PR middle-end/57748 */
++/* { dg-do run } */
++/* { dg-final { scan-assembler-not "movdqu" } } */
++/* data store race in expand_assignment:
++ misalignp == true, !MEM_P (to_rtx),
++ offset == 0, bitsize < GET_MODE_BITSIZE,
++ => rmw cycle on MEM. */
++
++#include <stdlib.h>
++
++typedef long long V
++ __attribute__ ((vector_size (2 * sizeof (long long)), may_alias));
++
++union x
++{
++ long long a;
++ float b;
++} __attribute__((aligned (1)));
++
++struct s
++{
++ union x xx[0];
++ V x;
++} __attribute__((packed));
++
++void __attribute__((noinline, noclone))
++check (union x *xx)
++{
++ if (xx[0].b != 3.14F || xx[1].a != 0x123456789ABCDEF)
++ abort ();
++}
++
++void __attribute__((noinline, noclone))
++foo (struct s * x)
++{
++ x->xx[0].a = -1;
++ x->xx[0].b = 3.14F;
++ x->x[1] = 0x123456789ABCDEF;
++}
++
++struct s ss;
++
++int
++main ()
++{
++ foo (&ss);
++ check (ss.xx);
++ return 0;
++}
+--- a/gcc/testsuite/gcc.dg/torture/pr57748-4.c 1970-01-01 01:00:00.000000000 +0100
++++ b/gcc/testsuite/gcc.dg/torture/pr57748-4.c 2013-09-10 08:36:37.182962269 +0200
+@@ -0,0 +1,50 @@
++/* PR middle-end/57748 */
++/* { dg-do run } */
++/* { dg-final { scan-assembler-not "movdqu" } } */
++/* wrong code in expand_expr_real_1:
++ read whole structure instead of only one member. */
++
++#include <stdlib.h>
++
++typedef long long V
++ __attribute__ ((vector_size (2 * sizeof (long long)), may_alias));
++
++union x
++{
++ long long a;
++ float b;
++} __attribute__((aligned (1)));
++
++struct s
++{
++ union x xx[0];
++ V x;
++} __attribute__((packed));
++
++void __attribute__((noinline, noclone))
++check (struct s *x)
++{
++ if (x->xx[0].b != 3.14F || x->xx[1].a != 0x123456789ABCDEF)
++ abort ();
++ if (x->xx[2].b != 3.14F || x->xx[3].a != 0x123456789ABCDEF)
++ abort ();
++}
++
++void __attribute__((noinline, noclone))
++foo (struct s * x)
++{
++ x->xx[0].a = -1;
++ x->xx[0].b = 3.14F;
++ x->x[1] = 0x123456789ABCDEF;
++}
++
++struct s ss[2];
++
++int
++main ()
++{
++ foo (ss);
++ foo (ss+1);
++ check (ss);
++ return 0;
++}