From: James Greenhalgh Date: Wed, 9 Dec 2015 13:47:19 +0000 (+0000) Subject: [Patch AArch64] Reinstate CANNOT_CHANGE_MODE_CLASS to fix pr67609 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=4c81f958b3f1b2a41e94d505c34b6d911502bb15;p=gcc.git [Patch AArch64] Reinstate CANNOT_CHANGE_MODE_CLASS to fix pr67609 gcc/ PR rtl-optimization/67609 * config/aarch64/aarch64-protos.h (aarch64_cannot_change_mode_class): Bring back. * config/aarch64/aarch64.c (aarch64_cannot_change_mode_class): Likewise. * config/aarch64/aarch64.h (CANNOT_CHANGE_MODE_CLASS): Likewise. * config/aarch64/aarch64.md (aarch64_movdi_low): Use zero_extract rather than truncate. (aarch64_movdi_high): Likewise. gcc/testsuite/ PR rtl-optimization/67609 * gcc.dg/torture/pr67609.c: New. From-SVN: r231455 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 8526be6e85b..56864aec60a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2015-12-09 James Greenhalgh + + * config/aarch64/aarch64-protos.h + (aarch64_cannot_change_mode_class): Bring back. + * config/aarch64/aarch64.c + (aarch64_cannot_change_mode_class): Likewise. + * config/aarch64/aarch64.h (CANNOT_CHANGE_MODE_CLASS): Likewise. + * config/aarch64/aarch64.md (aarch64_movdi_low): Use + zero_extract rather than truncate. + (aarch64_movdi_high): Likewise. + 2015-12-09 Jakub Jelinek PR tree-optimization/68786 diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h index 1e0fb4e97e8..549a89d1f69 100644 --- a/gcc/config/aarch64/aarch64-protos.h +++ b/gcc/config/aarch64/aarch64-protos.h @@ -269,6 +269,9 @@ int aarch64_get_condition_code (rtx); bool aarch64_bitmask_imm (HOST_WIDE_INT val, machine_mode); int aarch64_branch_cost (bool, bool); enum aarch64_symbol_type aarch64_classify_symbolic_expression (rtx); +bool aarch64_cannot_change_mode_class (machine_mode, + machine_mode, + enum reg_class); bool aarch64_const_vec_all_same_int_p (rtx, HOST_WIDE_INT); bool aarch64_constant_address_p (rtx); bool aarch64_expand_movmem (rtx *); diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index ae4cfb336a8..1e1b864d865 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -12712,6 +12712,24 @@ aarch64_vectorize_vec_perm_const_ok (machine_mode vmode, return ret; } +/* Implement target hook CANNOT_CHANGE_MODE_CLASS. */ +bool +aarch64_cannot_change_mode_class (machine_mode from, + machine_mode to, + enum reg_class rclass) +{ + /* We cannot allow word_mode subregs of full vector modes. + Otherwise the middle-end will assume it's ok to store to + (subreg:DI (reg:TI 100) 0) in order to modify only the low 64 bits + of the 128-bit register. However, after reload the subreg will + be dropped leaving a plain DImode store. See PR67609 for a more + detailed dicussion. In all other cases, we want to be permissive + and return false. */ + return (reg_classes_intersect_p (FP_REGS, rclass) + && GET_MODE_SIZE (to) == UNITS_PER_WORD + && GET_MODE_SIZE (from) > UNITS_PER_WORD); +} + rtx aarch64_reverse_mask (enum machine_mode mode) { diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h index 06345f0215e..e2ead511076 100644 --- a/gcc/config/aarch64/aarch64.h +++ b/gcc/config/aarch64/aarch64.h @@ -828,6 +828,9 @@ do { \ extern void __aarch64_sync_cache_range (void *, void *); \ __aarch64_sync_cache_range (beg, end) +#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \ + aarch64_cannot_change_mode_class (FROM, TO, CLASS) + #define SHIFT_COUNT_TRUNCATED !TARGET_SIMD /* Choose appropriate mode for caller saves, so we do the minimum diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index d9fe1ae4593..dd93012039d 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -4681,7 +4681,8 @@ (define_insn "aarch64_movdi_low" [(set (match_operand:DI 0 "register_operand" "=r") - (truncate:DI (match_operand:TX 1 "register_operand" "w")))] + (zero_extract:DI (match_operand:TX 1 "register_operand" "w") + (const_int 64) (const_int 0)))] "TARGET_FLOAT && (reload_completed || reload_in_progress)" "fmov\\t%x0, %d1" [(set_attr "type" "f_mrc") @@ -4690,9 +4691,8 @@ (define_insn "aarch64_movdi_high" [(set (match_operand:DI 0 "register_operand" "=r") - (truncate:DI - (lshiftrt:TX (match_operand:TX 1 "register_operand" "w") - (const_int 64))))] + (zero_extract:DI (match_operand:TX 1 "register_operand" "w") + (const_int 64) (const_int 64)))] "TARGET_FLOAT && (reload_completed || reload_in_progress)" "fmov\\t%x0, %1.d[1]" [(set_attr "type" "f_mrc") diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 687e2b2196f..a99f32079e2 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2015-12-09 James Greenhalgh + + PR rtl-optimization/67609 + * gcc.dg/torture/pr67609.c: New. + 2015-12-09 Richard Biener PR tree-optimization/68583 diff --git a/gcc/testsuite/gcc.dg/torture/pr67609.c b/gcc/testsuite/gcc.dg/torture/pr67609.c new file mode 100644 index 00000000000..817857dc52d --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr67609.c @@ -0,0 +1,33 @@ +/* { dg-do run } */ + +typedef union +{ + double v[2]; + double s __attribute__ ((vector_size (16))); +} data; + +data reg; + +void __attribute__ ((noinline)) +set_lower (double b) +{ + data stack_var; + double __attribute__ ((vector_size (16))) one = { 1.0, 1.0 }; + stack_var.s = reg.s; + stack_var.s += one; + stack_var.v[0] += b; + reg.s = stack_var.s; +} + +int +main (int argc, char ** argv) +{ + reg.v[0] = 1.0; + reg.v[1] = 1.0; + /* reg should contain { 1.0, 1.0 }. */ + set_lower (2.0); + /* reg should contain { 4.0, 2.0 }. */ + if ((int) reg.v[0] != 4 || (int) reg.v[1] != 2) + __builtin_abort (); + return 0; +}