diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/expr.c | 34 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/misaligned-expand-1.c | 41 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/misaligned-expand-3.c | 43 |
5 files changed, 114 insertions, 14 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7f14c96..d517881 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2012-03-16 Martin Jambor <mjambor@suse.cz> + + * expr.c (expand_expr_real_1): handle misaligned scalar reads from + memory through MEM_REFs by calling extract_bit_field. + 2012-03-16 Richard Guenther <rguenther@suse.de> * fold-const.c (native_interpret_expr): Also support POINTER_TYPE @@ -9347,21 +9347,27 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, MEM_VOLATILE_P (temp) = 1; if (modifier != EXPAND_WRITE && mode != BLKmode - && align < GET_MODE_ALIGNMENT (mode) - /* If the target does not have special handling for unaligned - loads of mode then it can use regular moves for them. */ - && ((icode = optab_handler (movmisalign_optab, mode)) - != CODE_FOR_nothing)) + && align < GET_MODE_ALIGNMENT (mode)) { - struct expand_operand ops[2]; - - /* We've already validated the memory, and we're creating a - new pseudo destination. The predicates really can't fail, - nor can the generator. */ - create_output_operand (&ops[0], NULL_RTX, mode); - create_fixed_operand (&ops[1], temp); - expand_insn (icode, 2, ops); - return ops[0].value; + if ((icode = optab_handler (movmisalign_optab, mode)) + != CODE_FOR_nothing) + { + struct expand_operand ops[2]; + + /* We've already validated the memory, and we're creating a + new pseudo destination. The predicates really can't fail, + nor can the generator. */ + create_output_operand (&ops[0], NULL_RTX, mode); + create_fixed_operand (&ops[1], temp); + expand_insn (icode, 2, ops); + return ops[0].value; + } + else if (SLOW_UNALIGNED_ACCESS (mode, align)) + temp = extract_bit_field (temp, GET_MODE_BITSIZE (mode), + 0, TYPE_UNSIGNED (TREE_TYPE (exp)), + true, (modifier == EXPAND_STACK_PARM + ? NULL_RTX : target), + mode, mode); } return temp; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index ba1e455..ab3261e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2012-03-16 Martin Jambor <mjambor@suse.cz> + + * gcc.dg/misaligned-expand-1.c: New test. + * gcc.dg/misaligned-expand-3.c: Likewise. + 2012-03-16 Richard Guenther <rguenther@suse.de> Kai Tietz <ktietz@redhat.com> diff --git a/gcc/testsuite/gcc.dg/misaligned-expand-1.c b/gcc/testsuite/gcc.dg/misaligned-expand-1.c new file mode 100644 index 0000000..38ac4d6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/misaligned-expand-1.c @@ -0,0 +1,41 @@ +/* Test that expand can generate correct loads of misaligned data even on + strict alignment platforms. */ + +/* { dg-do run } */ +/* { dg-options "-O0" } */ + +extern void abort (); + +typedef unsigned int myint __attribute__((aligned(1))); + +unsigned int +foo (myint *p) +{ + return *p; +} + +#define cst 0xdeadbeef +#define NUM 8 + +struct blah +{ + char c; + myint i[NUM]; +}; + +struct blah g; + +int +main (int argc, char **argv) +{ + int i, k; + for (k = 0; k < NUM; k++) + { + g.i[k] = cst; + i = foo (&g.i[k]); + + if (i != cst) + abort (); + } + return 0; +} diff --git a/gcc/testsuite/gcc.dg/misaligned-expand-3.c b/gcc/testsuite/gcc.dg/misaligned-expand-3.c new file mode 100644 index 0000000..5b1c7e7 --- /dev/null +++ b/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; +} |