diff options
author | James Greenhalgh <james.greenhalgh@arm.com> | 2015-12-09 13:47:19 +0000 |
---|---|---|
committer | James Greenhalgh <james.greenhalgh@arm.com> | 2015-12-09 13:47:19 +0000 |
commit | e8e929f593411ae6e9be5d1cfd70506a20968e14 (patch) | |
tree | 9d5c6037c38f9e1aad1f3b3a94c7657a04e32f77 /gcc | |
parent | dd512280cfb75a1b1d33b5759f26a96755c1862d (diff) |
[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_<mode>low): Use
zero_extract rather than truncate.
(aarch64_movdi_<mode>high): Likewise.
gcc/testsuite/
PR rtl-optimization/67609
* gcc.dg/torture/pr67609.c: New.
git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@231455 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/config/aarch64/aarch64-protos.h | 3 | ||||
-rw-r--r-- | gcc/config/aarch64/aarch64.c | 18 | ||||
-rw-r--r-- | gcc/config/aarch64/aarch64.h | 3 | ||||
-rw-r--r-- | gcc/config/aarch64/aarch64.md | 8 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/torture/pr67609.c | 33 |
7 files changed, 77 insertions, 4 deletions
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 <james.greenhalgh@arm.com> + + * 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_<mode>low): Use + zero_extract rather than truncate. + (aarch64_movdi_<mode>high): Likewise. + 2015-12-09 Jakub Jelinek <jakub@redhat.com> 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_<mode>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_<mode>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 <james.greenhalgh@arm.com> + + PR rtl-optimization/67609 + * gcc.dg/torture/pr67609.c: New. + 2015-12-09 Richard Biener <rguenther@suse.de> 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; +} |