Hi, the second patch in the series handles MEM_REFs on LHS which are parts of a handled_component, usually a COMPONENT_REF. The failing testcase which requires it is not actually the one in the patch but it is gcc.c-torture/execute/mayalias-3.c which fails at -O1 without this change but with the third patch applied.
The mechanism is the same as in the previous patch, it also piggy-backs a store_bit_field call onto generation of movmisalign operation, if that is not available but the access would be SLOW_UNALIGNED_ACCESS. I also needed to add !mem_ref_refers_to_non_mem_p condition for the same reasons. Additionally, complex numbers and accesses to their components are already handled by the existing code (the new testcase passes on all platforms I tried and so I added it to make sure it continues to) and actually messing with it further leads to failures (of g++.dg/torture/pr34099.C at -O1). Therefore I added a condition to punt on complex modes. Thanks, Martin 2012-02-28 Martin Jambor <mjam...@suse.cz> * expr.c (expand_assignment): Handle misaligned scalar writes to memory through MEM_REFs within handled_components by calling store_bit_field. * testsuite/gcc.dg/misaligned-expand-3.c: New test. Index: src/gcc/expr.c =================================================================== --- src.orig/gcc/expr.c +++ src/gcc/expr.c @@ -4575,7 +4575,7 @@ expand_assignment (tree to, tree from, b rtx result; enum machine_mode mode; unsigned int align; - enum insn_code icode; + enum insn_code icode = (enum insn_code) 0; /* Don't crash if the lhs of the assignment was erroneous. */ if (TREE_CODE (to) == ERROR_MARK) @@ -4689,10 +4689,13 @@ expand_assignment (tree to, tree from, b mode = TYPE_MODE (TREE_TYPE (tem)); if (TREE_CODE (tem) == MEM_REF && mode != BLKmode + && !COMPLEX_MODE_P (mode) + && !mem_ref_refers_to_non_mem_p (tem) && ((align = get_object_or_type_alignment (tem)) < GET_MODE_ALIGNMENT (mode)) - && ((icode = optab_handler (movmisalign_optab, mode)) - != CODE_FOR_nothing)) + && (((icode = optab_handler (movmisalign_optab, mode)) + != CODE_FOR_nothing) + || SLOW_UNALIGNED_ACCESS (mode, align))) { misalignp = true; to_rtx = gen_reg_rtx (mode); @@ -4871,13 +4874,18 @@ expand_assignment (tree to, tree from, b if (TREE_THIS_VOLATILE (tem)) MEM_VOLATILE_P (mem) = 1; - 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 (icode != CODE_FOR_nothing) + { + 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); + } + else + store_bit_field (mem, GET_MODE_BITSIZE (mode), + 0, 0, 0, mode, to_rtx); } - if (result) preserve_temp_slots (result); free_temp_slots (); Index: src/gcc/testsuite/gcc.dg/misaligned-expand-3.c =================================================================== --- /dev/null +++ src/gcc/testsuite/gcc.dg/misaligned-expand-3.c @@ -0,0 +1,43 @@ +/* Test that expand can generate correct stores to misaligned data of complex + type even on strict alignment platforms. */ + +/* { dg-do run } */ +/* { dg-options "-O0" } */ + +extern void abort (); + +typedef _Complex float mycmplx __attribute__((aligned(1))); + +void +foo (mycmplx *p, float r, float i) +{ + __real__ *p = r; + __imag__ *p = i; +} + +#define cvr 3.2f +#define cvi 2.5f +#define NUM 8 + +struct blah +{ + char c; + mycmplx x[NUM]; +} __attribute__((packed)); + +struct blah g; + +int +main (int argc, char **argv) +{ + int k; + + for (k = 0; k < NUM; k++) + { + foo (&g.x[k], cvr, cvi); + if (__real__ g.x[k] != cvr + || __imag__ g.x[k] != cvi) + abort (); + } + return 0; +}