Richard Biener writes: > On Sun, Jan 25, 2015 at 3:25 PM, Mikael Pettersson <mikpeli...@gmail.com> > wrote: > > This backports the fixes for PR middle-end/57748, a wrong-code and ICE > > regression, to the 4.8 branch. > > > > Tested extensively on x86_64, powerpc64, sparc64, ARMv{5,7}, and m68k. > > > > Ok for 4.8? > > Ok - I assume you have checked that all relevant patches in this area have > been backported already?
I'm not aware of any dependencies for this PR to patches other than the two being backported here (r202778 and r206437). I've now re-tested 4.8 vanilla on x86_64 and ARM, and this combined patch is enough to fix this PR's test cases. Thanks, /Mikael > Thanks, > Richard. > > > (I don't have commit rights.) > > > > /Mikael > > > > gcc/ > > > > 2015-01-25 Mikael Pettersson <mikpeli...@gmail.com> > > > > Backport from mainline > > > > 2013-09-20 Bernd Edlinger <bernd.edlin...@hotmail.de> > > > > PR middle-end/57748 > > * expr.c (expand_assignment): Remove misalignp code path. > > > > 2014-01-08 Bernd Edlinger <bernd.edlin...@hotmail.de> > > > > PR middle-end/57748 > > * expr.h (expand_expr_real, expand_expr_real_1): Add new parameter > > inner_reference_p. > > (expand_expr, expand_normal): Adjust. > > * expr.c (expand_expr_real, expand_expr_real_1): Add new parameter > > inner_reference_p. Use inner_reference_p to expand inner > > references. > > (store_expr): Adjust. > > * cfgexpand.c (expand_call_stmt): Adjust. > > > > gcc/testsuite/ > > > > 2015-01-25 Mikael Pettersson <mikpeli...@gmail.com> > > > > Backport from mainline > > > > 2013-09-20 Bernd Edlinger <bernd.edlin...@hotmail.de> > > > > PR middle-end/57748 > > * gcc.dg/torture/pr57748-1.c: New test. > > * gcc.dg/torture/pr57748-2.c: New test. > > > > 2014-01-08 Bernd Edlinger <bernd.edlin...@hotmail.de> > > > > PR middle-end/57748 > > * gcc.dg/torture/pr57748-3.c: New test. > > * gcc.dg/torture/pr57748-4.c: New test. > > > > diff -rupN gcc-4.8-20150122/gcc/cfgexpand.c > > gcc-4.8-20150122.pr57748/gcc/cfgexpand.c > > --- gcc-4.8-20150122/gcc/cfgexpand.c 2014-01-07 17:49:22.000000000 +0100 > > +++ gcc-4.8-20150122.pr57748/gcc/cfgexpand.c 2015-01-25 > > 15:00:35.240949368 +0100 > > @@ -2111,7 +2111,7 @@ expand_call_stmt (gimple stmt) > > if (lhs) > > expand_assignment (lhs, exp, false); > > else > > - expand_expr_real_1 (exp, const0_rtx, VOIDmode, EXPAND_NORMAL, NULL); > > + expand_expr (exp, const0_rtx, VOIDmode, EXPAND_NORMAL); > > > > mark_transaction_restart_calls (stmt); > > } > > diff -rupN gcc-4.8-20150122/gcc/expr.c gcc-4.8-20150122.pr57748/gcc/expr.c > > --- gcc-4.8-20150122/gcc/expr.c 2014-11-28 18:06:23.000000000 +0100 > > +++ gcc-4.8-20150122.pr57748/gcc/expr.c 2015-01-25 15:00:35.240949368 +0100 > > @@ -4708,8 +4708,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, > > @@ -4728,40 +4726,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. > > @@ -4900,17 +4865,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 (); > > @@ -5262,7 +5216,7 @@ store_expr (tree exp, rtx target, int ca > > temp = expand_expr_real (exp, tmp_target, GET_MODE (target), > > (call_param_p > > ? EXPAND_STACK_PARM : EXPAND_NORMAL), > > - &alt_rtl); > > + &alt_rtl, false); > > } > > > > /* If TEMP is a VOIDmode constant and the mode of the type of EXP is not > > @@ -7881,11 +7835,21 @@ expand_constructor (tree exp, rtx target > > address, and ALT_RTL is non-NULL, then *ALT_RTL is set to the > > DECL_RTL of the VAR_DECL. *ALT_RTL is also set if EXP is a > > COMPOUND_EXPR whose second argument is such a VAR_DECL, and so on > > - recursively. */ > > + recursively. > > + > > + If INNER_REFERENCE_P is true, we are expanding an inner reference. > > + In this case, we don't adjust a returned MEM rtx that wouldn't be > > + sufficiently aligned for its mode; instead, it's up to the caller > > + to deal with it afterwards. This is used to make sure that unaligned > > + base objects for which out-of-bounds accesses are supported, for > > + example record types with trailing arrays, aren't realigned behind > > + the back of the caller. > > + The normal operating mode is to pass FALSE for this parameter. */ > > > > rtx > > expand_expr_real (tree exp, rtx target, enum machine_mode tmode, > > - enum expand_modifier modifier, rtx *alt_rtl) > > + enum expand_modifier modifier, rtx *alt_rtl, > > + bool inner_reference_p) > > { > > rtx ret; > > > > @@ -7897,7 +7861,8 @@ expand_expr_real (tree exp, rtx target, > > return ret ? ret : const0_rtx; > > } > > > > - ret = expand_expr_real_1 (exp, target, tmode, modifier, alt_rtl); > > + ret = expand_expr_real_1 (exp, target, tmode, modifier, alt_rtl, > > + inner_reference_p); > > return ret; > > } > > > > @@ -9190,7 +9155,8 @@ expand_expr_real_2 (sepops ops, rtx targ > > > > rtx > > expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, > > - enum expand_modifier modifier, rtx *alt_rtl) > > + enum expand_modifier modifier, rtx *alt_rtl, > > + bool inner_reference_p) > > { > > rtx op0, op1, temp, decl_rtl; > > tree type; > > @@ -9336,7 +9302,7 @@ expand_expr_real_1 (tree exp, rtx target > > > > set_curr_insn_location (gimple_location (g)); > > r = expand_expr_real (gimple_assign_rhs_to_tree (g), target, > > - tmode, modifier, NULL); > > + tmode, modifier, NULL, inner_reference_p); > > set_curr_insn_location (saved_loc); > > if (REG_P (r) && !REG_EXPR (r)) > > set_reg_attrs_for_decl_rtl (SSA_NAME_VAR (exp), r); > > @@ -9557,7 +9523,8 @@ expand_expr_real_1 (tree exp, rtx target > > case SAVE_EXPR: > > { > > tree val = treeop0; > > - rtx ret = expand_expr_real_1 (val, target, tmode, modifier, > > alt_rtl); > > + rtx ret = expand_expr_real_1 (val, target, tmode, modifier, > > alt_rtl, > > + inner_reference_p); > > > > if (!SAVE_EXPR_RESOLVED_P (exp)) > > { > > @@ -9706,6 +9673,7 @@ expand_expr_real_1 (tree exp, rtx target > > MEM_VOLATILE_P (temp) = 1; > > if (modifier != EXPAND_WRITE > > && modifier != EXPAND_MEMORY > > + && !inner_reference_p > > && mode != BLKmode > > && align < GET_MODE_ALIGNMENT (mode)) > > { > > @@ -9940,18 +9908,19 @@ expand_expr_real_1 (tree exp, rtx target > > computation, since it will need a temporary and TARGET is known > > to have to do. This occurs in unchecked conversion in Ada. */ > > orig_op0 = op0 > > - = expand_expr (tem, > > - (TREE_CODE (TREE_TYPE (tem)) == UNION_TYPE > > - && COMPLETE_TYPE_P (TREE_TYPE (tem)) > > - && (TREE_CODE (TYPE_SIZE (TREE_TYPE (tem))) > > - != INTEGER_CST) > > - && modifier != EXPAND_STACK_PARM > > - ? target : NULL_RTX), > > - VOIDmode, > > - (modifier == EXPAND_INITIALIZER > > - || modifier == EXPAND_CONST_ADDRESS > > - || modifier == EXPAND_STACK_PARM) > > - ? modifier : EXPAND_NORMAL); > > + = expand_expr_real (tem, > > + (TREE_CODE (TREE_TYPE (tem)) == UNION_TYPE > > + && COMPLETE_TYPE_P (TREE_TYPE (tem)) > > + && (TREE_CODE (TYPE_SIZE (TREE_TYPE (tem))) > > + != INTEGER_CST) > > + && modifier != EXPAND_STACK_PARM > > + ? target : NULL_RTX), > > + VOIDmode, > > + (modifier == EXPAND_INITIALIZER > > + || modifier == EXPAND_CONST_ADDRESS > > + || modifier == EXPAND_STACK_PARM) > > + ? modifier : EXPAND_NORMAL, > > + NULL, true); > > > > > > /* If the bitfield is volatile, we want to access it in the > > @@ -10302,17 +10271,18 @@ expand_expr_real_1 (tree exp, rtx target > > { > > /* See the normal_inner_ref case for the rationale. */ > > orig_op0 > > - = expand_expr (tem, > > - (TREE_CODE (TREE_TYPE (tem)) == UNION_TYPE > > - && (TREE_CODE (TYPE_SIZE (TREE_TYPE (tem))) > > - != INTEGER_CST) > > - && modifier != EXPAND_STACK_PARM > > - ? target : NULL_RTX), > > - VOIDmode, > > - (modifier == EXPAND_INITIALIZER > > - || modifier == EXPAND_CONST_ADDRESS > > - || modifier == EXPAND_STACK_PARM) > > - ? modifier : EXPAND_NORMAL); > > + = expand_expr_real (tem, > > + (TREE_CODE (TREE_TYPE (tem)) == > > UNION_TYPE > > + && (TREE_CODE (TYPE_SIZE (TREE_TYPE > > (tem))) > > + != INTEGER_CST) > > + && modifier != EXPAND_STACK_PARM > > + ? target : NULL_RTX), > > + VOIDmode, > > + (modifier == EXPAND_INITIALIZER > > + || modifier == EXPAND_CONST_ADDRESS > > + || modifier == EXPAND_STACK_PARM) > > + ? modifier : EXPAND_NORMAL, > > + NULL, true); > > > > if (MEM_P (orig_op0)) > > { > > @@ -10339,8 +10309,8 @@ expand_expr_real_1 (tree exp, rtx target > > } > > > > if (!op0) > > - op0 = expand_expr (treeop0, > > - NULL_RTX, VOIDmode, modifier); > > + op0 = expand_expr_real (treeop0, NULL_RTX, VOIDmode, modifier, > > + NULL, inner_reference_p); > > > > /* If the input and output modes are both the same, we are done. */ > > if (mode == GET_MODE (op0)) > > @@ -10407,50 +10377,53 @@ expand_expr_real_1 (tree exp, rtx target > > op0 = copy_rtx (op0); > > set_mem_align (op0, MAX (MEM_ALIGN (op0), TYPE_ALIGN > > (type))); > > } > > - else if (mode != BLKmode > > - && MEM_ALIGN (op0) < GET_MODE_ALIGNMENT (mode) > > - /* If the target does have special handling for > > unaligned > > - loads of mode then use them. */ > > - && ((icode = optab_handler (movmisalign_optab, mode)) > > - != CODE_FOR_nothing)) > > - { > > - rtx reg, insn; > > - > > - op0 = adjust_address (op0, mode, 0); > > - /* We've already validated the memory, and we're creating a > > - new pseudo destination. The predicates really can't > > - fail. */ > > - reg = gen_reg_rtx (mode); > > - > > - /* Nor can the insn generator. */ > > - insn = GEN_FCN (icode) (reg, op0); > > - emit_insn (insn); > > - return reg; > > - } > > - else if (STRICT_ALIGNMENT > > + else if (modifier != EXPAND_WRITE > > + && modifier != EXPAND_MEMORY > > + && !inner_reference_p > > && mode != BLKmode > > && MEM_ALIGN (op0) < GET_MODE_ALIGNMENT (mode)) > > { > > - tree inner_type = TREE_TYPE (treeop0); > > - HOST_WIDE_INT temp_size > > - = MAX (int_size_in_bytes (inner_type), > > - (HOST_WIDE_INT) GET_MODE_SIZE (mode)); > > - rtx new_rtx > > - = assign_stack_temp_for_type (mode, temp_size, type); > > - rtx new_with_op0_mode > > - = adjust_address (new_rtx, GET_MODE (op0), 0); > > - > > - gcc_assert (!TREE_ADDRESSABLE (exp)); > > - > > - if (GET_MODE (op0) == BLKmode) > > - emit_block_move (new_with_op0_mode, op0, > > - GEN_INT (GET_MODE_SIZE (mode)), > > - (modifier == EXPAND_STACK_PARM > > - ? BLOCK_OP_CALL_PARM : BLOCK_OP_NORMAL)); > > - else > > - emit_move_insn (new_with_op0_mode, op0); > > + /* If the target does have special handling for unaligned > > + loads of mode then use them. */ > > + if ((icode = optab_handler (movmisalign_optab, mode)) > > + != CODE_FOR_nothing) > > + { > > + rtx reg, insn; > > > > - op0 = new_rtx; > > + op0 = adjust_address (op0, mode, 0); > > + /* We've already validated the memory, and we're > > creating a > > + new pseudo destination. The predicates really can't > > + fail. */ > > + reg = gen_reg_rtx (mode); > > + > > + /* Nor can the insn generator. */ > > + insn = GEN_FCN (icode) (reg, op0); > > + emit_insn (insn); > > + return reg; > > + } > > + else if (STRICT_ALIGNMENT) > > + { > > + tree inner_type = TREE_TYPE (treeop0); > > + HOST_WIDE_INT temp_size > > + = MAX (int_size_in_bytes (inner_type), > > + (HOST_WIDE_INT) GET_MODE_SIZE (mode)); > > + rtx new_rtx > > + = assign_stack_temp_for_type (mode, temp_size, type); > > + rtx new_with_op0_mode > > + = adjust_address (new_rtx, GET_MODE (op0), 0); > > + > > + gcc_assert (!TREE_ADDRESSABLE (exp)); > > + > > + if (GET_MODE (op0) == BLKmode) > > + emit_block_move (new_with_op0_mode, op0, > > + GEN_INT (GET_MODE_SIZE (mode)), > > + (modifier == EXPAND_STACK_PARM > > + ? BLOCK_OP_CALL_PARM : > > BLOCK_OP_NORMAL)); > > + else > > + emit_move_insn (new_with_op0_mode, op0); > > + > > + op0 = new_rtx; > > + } > > } > > > > op0 = adjust_address (op0, mode, 0); > > @@ -10550,7 +10523,7 @@ expand_expr_real_1 (tree exp, rtx target > > /* WITH_SIZE_EXPR expands to its first argument. The caller should > > have pulled out the size to use in whatever context it needed. */ > > return expand_expr_real (treeop0, original_target, tmode, > > - modifier, alt_rtl); > > + modifier, alt_rtl, inner_reference_p); > > > > default: > > return expand_expr_real_2 (&ops, target, tmode, modifier); > > diff -rupN gcc-4.8-20150122/gcc/expr.h gcc-4.8-20150122.pr57748/gcc/expr.h > > --- gcc-4.8-20150122/gcc/expr.h 2014-04-04 16:09:23.000000000 +0200 > > +++ gcc-4.8-20150122.pr57748/gcc/expr.h 2015-01-25 15:00:35.240949368 +0100 > > @@ -41,7 +41,8 @@ along with GCC; see the file COPYING3. > > is a constant that is not a legitimate address. > > EXPAND_WRITE means we are only going to write to the resulting rtx. > > EXPAND_MEMORY means we are interested in a memory result, even if > > - the memory is constant and we could have propagated a constant value. > > */ > > + the memory is constant and we could have propagated a constant value, > > + or the memory is unaligned on a STRICT_ALIGNMENT target. */ > > enum expand_modifier {EXPAND_NORMAL = 0, EXPAND_STACK_PARM, EXPAND_SUM, > > EXPAND_CONST_ADDRESS, EXPAND_INITIALIZER, > > EXPAND_WRITE, > > EXPAND_MEMORY}; > > @@ -428,9 +429,9 @@ extern rtx force_operand (rtx, rtx); > > > > /* Work horses for expand_expr. */ > > extern rtx expand_expr_real (tree, rtx, enum machine_mode, > > - enum expand_modifier, rtx *); > > + enum expand_modifier, rtx *, bool); > > extern rtx expand_expr_real_1 (tree, rtx, enum machine_mode, > > - enum expand_modifier, rtx *); > > + enum expand_modifier, rtx *, bool); > > extern rtx expand_expr_real_2 (sepops, rtx, enum machine_mode, > > enum expand_modifier); > > > > @@ -441,13 +442,13 @@ static inline rtx > > expand_expr (tree exp, rtx target, enum machine_mode mode, > > enum expand_modifier modifier) > > { > > - return expand_expr_real (exp, target, mode, modifier, NULL); > > + return expand_expr_real (exp, target, mode, modifier, NULL, false); > > } > > > > static inline rtx > > expand_normal (tree exp) > > { > > - return expand_expr_real (exp, NULL_RTX, VOIDmode, EXPAND_NORMAL, NULL); > > + return expand_expr_real (exp, NULL_RTX, VOIDmode, EXPAND_NORMAL, NULL, > > false); > > } > > > > /* At the start of a function, record that we have no previously-pushed > > diff -rupN gcc-4.8-20150122/gcc/testsuite/gcc.dg/torture/pr57748-1.c > > gcc-4.8-20150122.pr57748/gcc/testsuite/gcc.dg/torture/pr57748-1.c > > --- gcc-4.8-20150122/gcc/testsuite/gcc.dg/torture/pr57748-1.c 1970-01-01 > > 01:00:00.000000000 +0100 > > +++ gcc-4.8-20150122.pr57748/gcc/testsuite/gcc.dg/torture/pr57748-1.c > > 2015-01-25 15:00:32.660962074 +0100 > > @@ -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; > > +} > > diff -rupN gcc-4.8-20150122/gcc/testsuite/gcc.dg/torture/pr57748-2.c > > gcc-4.8-20150122.pr57748/gcc/testsuite/gcc.dg/torture/pr57748-2.c > > --- gcc-4.8-20150122/gcc/testsuite/gcc.dg/torture/pr57748-2.c 1970-01-01 > > 01:00:00.000000000 +0100 > > +++ gcc-4.8-20150122.pr57748/gcc/testsuite/gcc.dg/torture/pr57748-2.c > > 2015-01-25 15:00:32.660962074 +0100 > > @@ -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; > > +} > > diff -rupN gcc-4.8-20150122/gcc/testsuite/gcc.dg/torture/pr57748-3.c > > gcc-4.8-20150122.pr57748/gcc/testsuite/gcc.dg/torture/pr57748-3.c > > --- gcc-4.8-20150122/gcc/testsuite/gcc.dg/torture/pr57748-3.c 1970-01-01 > > 01:00:00.000000000 +0100 > > +++ gcc-4.8-20150122.pr57748/gcc/testsuite/gcc.dg/torture/pr57748-3.c > > 2015-01-25 15:00:35.240949368 +0100 > > @@ -0,0 +1,40 @@ > > +/* PR middle-end/57748 */ > > +/* { dg-do run } */ > > +/* wrong code in expand_expr_real_1. */ > > + > > +#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 (P *p) > > +{ > > + if (p->b[0][0] != 3 || p->b[0][1] != 4) > > + abort (); > > +} > > + > > +void __attribute__((noinline, noclone)) > > +foo (struct T *t) > > +{ > > + V a = { 3, 4 }; > > + t->s.b[0] = a; > > +} > > + > > +int > > +main () > > +{ > > + struct T *t = (struct T *) calloc (128, 1); > > + > > + foo (t); > > + check (&t->s); > > + > > + free (t); > > + return 0; > > +} > > diff -rupN gcc-4.8-20150122/gcc/testsuite/gcc.dg/torture/pr57748-4.c > > gcc-4.8-20150122.pr57748/gcc/testsuite/gcc.dg/torture/pr57748-4.c > > --- gcc-4.8-20150122/gcc/testsuite/gcc.dg/torture/pr57748-4.c 1970-01-01 > > 01:00:00.000000000 +0100 > > +++ gcc-4.8-20150122.pr57748/gcc/testsuite/gcc.dg/torture/pr57748-4.c > > 2015-01-25 15:00:35.240949368 +0100 > > @@ -0,0 +1,40 @@ > > +/* PR middle-end/57748 */ > > +/* { dg-do run } */ > > +/* wrong code in expand_expr_real_1. */ > > + > > +#include <stdlib.h> > > + > > +extern void abort (void); > > + > > +typedef long long V > > + __attribute__ ((vector_size (2 * sizeof (long long)), may_alias)); > > + > > +typedef struct S { V b[1]; } P __attribute__((aligned (1))); > > + > > +struct __attribute__((packed)) T { char c; P s; }; > > + > > +void __attribute__((noinline, noclone)) > > +check (P *p) > > +{ > > + if (p->b[1][0] != 3 || p->b[1][1] != 4) > > + abort (); > > +} > > + > > +void __attribute__((noinline, noclone)) > > +foo (struct T *t) > > +{ > > + V a = { 3, 4 }; > > + t->s.b[1] = a; > > +} > > + > > +int > > +main () > > +{ > > + struct T *t = (struct T *) calloc (128, 1); > > + > > + foo (t); > > + check (&t->s); > > + > > + free (t); > > + return 0; > > +} --