[AArch64] Cleanup logic around aarch64_final_prescan
authorKyrylo Tkachov <kyrylo.tkachov@arm.com>
Fri, 24 Oct 2014 11:30:42 +0000 (11:30 +0000)
committerKyrylo Tkachov <ktkachov@gcc.gnu.org>
Fri, 24 Oct 2014 11:30:42 +0000 (11:30 +0000)
* config/aarch64/aarch64.h (ADJUST_INSN_LENGTH): Wrap definition in
do while (0).
* config/aarch64/aarch64.c (is_mem_p): Delete.
(is_memory_op): Rename to...
(has_memory_op): ... This.  Use FOR_EACH_SUBRTX.
(dep_between_memop_and_curr): Assert that the input is a SET.
(aarch64_madd_needs_nop): Add comment.  Do not call
dep_between_memop_and_curr on NULL body.
(aarch64_final_prescan_insn): Add comment.
Include rtl-iter.h.

From-SVN: r216637

gcc/ChangeLog
gcc/config/aarch64/aarch64.c
gcc/config/aarch64/aarch64.h

index 683edcc1a53d7fca58301c7acd1f50827262fdf1..918426d7dd3504a653af83df0a7830aeea7630d1 100644 (file)
@@ -1,3 +1,16 @@
+2014-10-24  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
+
+       * config/aarch64/aarch64.h (ADJUST_INSN_LENGTH): Wrap definition in
+       do while (0).
+       * config/aarch64/aarch64.c (is_mem_p): Delete.
+       (is_memory_op): Rename to...
+       (has_memory_op): ... This.  Use FOR_EACH_SUBRTX.
+       (dep_between_memop_and_curr): Assert that the input is a SET.
+       (aarch64_madd_needs_nop): Add comment.  Do not call
+       dep_between_memop_and_curr on NULL body.
+       (aarch64_final_prescan_insn): Add comment.
+       Include rtl-iter.h.
+
 2014-10-24  Richard Biener  <rguenther@suse.de>
 
        * Makefile.in (BUILD_CPPLIB): Move $(LIBINTL) $(LIBICONV)
index b94f45086010470bd6830a41b3ca6b9129fc67f7..de53c948397a660222bde87883b233c4f2ae5048 100644 (file)
@@ -68,6 +68,7 @@
 #include "aarch64-cost-tables.h"
 #include "dumpfile.h"
 #include "builtins.h"
+#include "rtl-iter.h"
 
 /* Defined for convenience.  */
 #define POINTER_BYTES (POINTER_SIZE / BITS_PER_UNIT)
@@ -7658,17 +7659,19 @@ aarch64_mangle_type (const_tree type)
   return NULL;
 }
 
-static int
-is_mem_p (rtx *x, void *data ATTRIBUTE_UNUSED)
-{
-  return MEM_P (*x);
-}
+
+/* Return true if the rtx_insn contains a MEM RTX somewhere
+   in it.  */
 
 static bool
-is_memory_op (rtx_insn *mem_insn)
+has_memory_op (rtx_insn *mem_insn)
 {
-   rtx pattern = PATTERN (mem_insn);
-   return for_each_rtx (&pattern, is_mem_p, NULL);
+  subrtx_iterator::array_type array;
+  FOR_EACH_SUBRTX (iter, array, PATTERN (mem_insn), ALL)
+    if (MEM_P (*iter))
+      return true;
+
+  return false;
 }
 
 /* Find the first rtx_insn before insn that will generate an assembly
@@ -7718,14 +7721,13 @@ dep_between_memop_and_curr (rtx memop)
   rtx load_reg;
   int opno;
 
-  if (!memop)
-    return false;
+  gcc_assert (GET_CODE (memop) == SET);
 
   if (!REG_P (SET_DEST (memop)))
     return false;
 
   load_reg = SET_DEST (memop);
-  for (opno = 0; opno < recog_data.n_operands; opno++)
+  for (opno = 1; opno < recog_data.n_operands; opno++)
     {
       rtx operand = recog_data.operand[opno];
       if (REG_P (operand)
@@ -7736,6 +7738,12 @@ dep_between_memop_and_curr (rtx memop)
   return false;
 }
 
+
+/* When working around the Cortex-A53 erratum 835769,
+   given rtx_insn INSN, return true if it is a 64-bit multiply-accumulate
+   instruction and has a preceding memory instruction such that a NOP
+   should be inserted between them.  */
+
 bool
 aarch64_madd_needs_nop (rtx_insn* insn)
 {
@@ -7754,24 +7762,26 @@ aarch64_madd_needs_nop (rtx_insn* insn)
     return false;
 
   prev = aarch64_prev_real_insn (insn);
-  if (!prev)
+  if (!prev || !has_memory_op (prev))
     return false;
 
   body = single_set (prev);
 
   /* If the previous insn is a memory op and there is no dependency between
-     it and the madd, emit a nop between them.  If we know the previous insn is
-     a memory op but body is NULL, emit the nop to be safe, it's probably a
-     load/store pair insn.  */
-  if (is_memory_op (prev)
-      && GET_MODE (recog_data.operand[0]) == DImode
-      && (!dep_between_memop_and_curr (body)))
+     it and the DImode madd, emit a NOP between them.  If body is NULL then we
+     have a complex memory operation, probably a load/store pair.
+     Be conservative for now and emit a NOP.  */
+  if (GET_MODE (recog_data.operand[0]) == DImode
+      && (!body || !dep_between_memop_and_curr (body)))
     return true;
 
   return false;
 
 }
 
+
+/* Implement FINAL_PRESCAN_INSN.  */
+
 void
 aarch64_final_prescan_insn (rtx_insn *insn)
 {
index 11aa10b03f5500dd45d87dc8543583fc1adeec6b..749c19d89d7f30d75eee1ca8fab6c4febebbee32 100644 (file)
@@ -503,8 +503,11 @@ enum target_cpus
 /* If inserting NOP before a mult-accumulate insn remember to adjust the
    length so that conditional branching code is updated appropriately.  */
 #define ADJUST_INSN_LENGTH(insn, length)       \
-  if (aarch64_madd_needs_nop (insn))           \
-    length += 4;
+  do                                           \
+    {                                          \
+       if (aarch64_madd_needs_nop (insn))      \
+         length += 4;                          \
+    } while (0)
 
 #define FINAL_PRESCAN_INSN(INSN, OPVEC, NOPERANDS)     \
     aarch64_final_prescan_insn (INSN);                 \