diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 8f096c7b4b0..514bb313b4d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2015-10-09 Richard Biener + + PR target/67366 + * gimple-fold.c (optabs-query.h): Include + (gimple_fold_builtin_memory_op): Allow unaligned stores + when movmisalign_optabs are available. + 2015-10-09 Ramana Radhakrishnan PR target/67366 diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c index ee2a320c1fc..17a23d65f39 100644 --- a/gcc/gimple-fold.c +++ b/gcc/gimple-fold.c @@ -63,6 +63,8 @@ along with GCC; see the file COPYING3. If not see #include "tree-eh.h" #include "gimple-match.h" #include "gomp-constants.h" +#include "optabs-query.h" + /* Return true when DECL can be referenced from current unit. FROM_DECL (if non-null) specify constructor of variable DECL was taken from. @@ -709,7 +711,9 @@ gimple_fold_builtin_memory_op (gimple_stmt_iterator *gsi, /* If the destination pointer is not aligned we must be able to emit an unaligned store. */ && (dest_align >= GET_MODE_ALIGNMENT (TYPE_MODE (type)) - || !SLOW_UNALIGNED_ACCESS (TYPE_MODE (type), dest_align))) + || !SLOW_UNALIGNED_ACCESS (TYPE_MODE (type), dest_align) + || (optab_handler (movmisalign_optab, TYPE_MODE (type)) + != CODE_FOR_nothing))) { tree srctype = type; tree desttype = type; @@ -721,7 +725,10 @@ gimple_fold_builtin_memory_op (gimple_stmt_iterator *gsi, srcmem = tem; else if (src_align < GET_MODE_ALIGNMENT (TYPE_MODE (type)) && SLOW_UNALIGNED_ACCESS (TYPE_MODE (type), - src_align)) + src_align) + && (optab_handler (movmisalign_optab, + TYPE_MODE (type)) + == CODE_FOR_nothing)) srcmem = NULL_TREE; if (srcmem) { diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 6ce8fab1393..d7eba156ccb 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2015-10-09 Ramana Radhakrishnan + + PR target/67366 + * lib/target-supports.exp (check_effective_target_non_strict_align): + Adjust for arm*-*-*. + * gcc.target/arm/pr67366.c: New test. + 2015-10-09 Richard Biener PR tree-optimization/67891 diff --git a/gcc/testsuite/gcc.target/arm/pr67366.c b/gcc/testsuite/gcc.target/arm/pr67366.c new file mode 100644 index 00000000000..1e8b6727003 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/pr67366.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target arm_unaligned } */ +/* { dg-options "-O2" } */ + +typedef unsigned int u32; +u32 +read32 (const void* ptr) +{ + u32 v; + __builtin_memcpy (&v, ptr, sizeof(v)); + return v; +} + +/* { dg-final { scan-assembler "@ unaligned" } } */ diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp index 9057a27c6b4..4d5b0a3df61 100644 --- a/gcc/testsuite/lib/target-supports.exp +++ b/gcc/testsuite/lib/target-supports.exp @@ -6262,6 +6262,15 @@ proc check_vect_support_and_set_flags { } { # Return 1 if the target does *not* require strict alignment. proc check_effective_target_non_strict_align {} { + + # On ARM, the default is to use STRICT_ALIGNMENT, but there + # are interfaces defined for misaligned access and thus + # depending on the architecture levels unaligned access is + # available. + if [istarget "arm*-*-*"] { + return [check_effective_target_arm_unaligned] + } + return [check_no_compiler_messages non_strict_align assembly { char *y; typedef char __attribute__ ((__aligned__(__BIGGEST_ALIGNMENT__))) c;