[Patch AArch64] Reinstate CANNOT_CHANGE_MODE_CLASS to fix pr67609
authorJames Greenhalgh <james.greenhalgh@arm.com>
Wed, 9 Dec 2015 13:47:19 +0000 (13:47 +0000)
committerJames Greenhalgh <jgreenhalgh@gcc.gnu.org>
Wed, 9 Dec 2015 13:47:19 +0000 (13:47 +0000)
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.

From-SVN: r231455

gcc/ChangeLog
gcc/config/aarch64/aarch64-protos.h
gcc/config/aarch64/aarch64.c
gcc/config/aarch64/aarch64.h
gcc/config/aarch64/aarch64.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/torture/pr67609.c [new file with mode: 0644]

index 8526be6e85b7af2b9f0f3d25005aee2d8e50690b..56864aec60a3b17d45ff478dfcad37f0380a5f28 100644 (file)
@@ -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
index 1e0fb4e97e8144173b0e5a0b89f59973ee40e190..549a89d1f691b32efbc74359f045b5df74765f0e 100644 (file)
@@ -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 *);
index ae4cfb336a827a63a6baadefcb5646a9dbfb7523..1e1b864d86573a1f024b333be82327fa69afec16 100644 (file)
@@ -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)
 {
index 06345f0215ea190b7b089264a0039a201437ecec..e2ead511076a2192eb79b79ec0a72777f82af35c 100644 (file)
@@ -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
index d9fe1ae4593c4a174632d59080b9b6be366d81d9..dd93012039d466714082e9e445d6ddb09d52ea11 100644 (file)
 
 (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")
 
 (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")
index 687e2b2196f46365ac4c05b05e4e46fc136ebb9f..a99f32079e22185a58efcd6a6dfc2c92e802004f 100644 (file)
@@ -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 (file)
index 0000000..817857d
--- /dev/null
@@ -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;
+}