From 2a58659170c337930b131e6cf04d5cae6310b43c Mon Sep 17 00:00:00 2001 From: James Greenhalgh Date: Tue, 12 Jan 2016 14:04:26 +0000 Subject: [PATCH] Backport: [Patch AArch64] Reinstate CANNOT_CHANGE_MODE_CLASS to fix pr67609 gcc/ Backport from mainline. 2015-12-09 James Greenhalgh PR rtl-optimization/67609 * config/aarch64/aarch64.c (aarch64_cannot_change_mode_class): Don't permit word_mode subregs of full vector modes. * config/aarch64/aarch64.md (aarch64_movdi_low): Use zero_extract rather than truncate. (aarch64_movdi_high): Likewise. gcc/testsuite/ Backport from mainline. 2015-12-09 James Greenhalgh PR rtl-optimization/67609 * gcc.dg/torture/pr67609.c: New. From-SVN: r232270 --- gcc/ChangeLog | 13 ++++++++++ gcc/config/aarch64/aarch64.c | 12 ++++++++++ gcc/config/aarch64/aarch64.md | 8 +++---- gcc/testsuite/ChangeLog | 8 +++++++ gcc/testsuite/gcc.dg/torture/pr67609.c | 33 ++++++++++++++++++++++++++ 5 files changed, 70 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/torture/pr67609.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9d1a44181220..ddecc2257381 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2016-01-12 James Greenhalgh + + Backport from mainline. + 2015-12-09 James Greenhalgh + + PR rtl-optimization/67609 + * config/aarch64/aarch64.c + (aarch64_cannot_change_mode_class): Don't permit word_mode + subregs of full vector modes. + * config/aarch64/aarch64.md (aarch64_movdi_low): Use + zero_extract rather than truncate. + (aarch64_movdi_high): Likewise. + 2016-01-11 John David Anglin * config/pa/pa.c (pa_emit_move_sequence): Handle floating point diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index 81539975e3c8..5ca38b6f7972 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -8405,6 +8405,18 @@ aarch64_cannot_change_mode_class (enum machine_mode from, enum 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 some other cases we can be permissive and + return false. */ + if (reg_classes_intersect_p (FP_REGS, rclass) + && GET_MODE_SIZE (to) == UNITS_PER_WORD + && GET_MODE_SIZE (from) > UNITS_PER_WORD) + return true; + /* Full-reg subregs are allowed on general regs or any class if they are the same size. */ if (GET_MODE_SIZE (from) == GET_MODE_SIZE (to) diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index 24bb029bd70b..d6c6b1e38dc3 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -3454,7 +3454,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)))] "reload_completed || reload_in_progress" "fmov\\t%x0, %d1" [(set_attr "type" "f_mrc") @@ -3463,9 +3464,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)))] "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 cce93ed356c8..fd5de3e05f7d 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2016-01-12 James Greenhalgh + + Backport from mainline. + 2015-12-09 James Greenhalgh + + PR rtl-optimization/67609 + * gcc.dg/torture/pr67609.c: New. + 2016-01-11 Martin Jambor PR ipa/66616 diff --git a/gcc/testsuite/gcc.dg/torture/pr67609.c b/gcc/testsuite/gcc.dg/torture/pr67609.c new file mode 100644 index 000000000000..817857dc52d5 --- /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; +} -- 2.47.2