Commit 8baff86e by Kyrylo Tkachov Committed by Kyrylo Tkachov

[AArch64] Cleanup logic around aarch64_final_prescan

	* 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
parent 1f59b315
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> 2014-10-24 Richard Biener <rguenther@suse.de>
* Makefile.in (BUILD_CPPLIB): Move $(LIBINTL) $(LIBICONV) * Makefile.in (BUILD_CPPLIB): Move $(LIBINTL) $(LIBICONV)
...@@ -68,6 +68,7 @@ ...@@ -68,6 +68,7 @@
#include "aarch64-cost-tables.h" #include "aarch64-cost-tables.h"
#include "dumpfile.h" #include "dumpfile.h"
#include "builtins.h" #include "builtins.h"
#include "rtl-iter.h"
/* Defined for convenience. */ /* Defined for convenience. */
#define POINTER_BYTES (POINTER_SIZE / BITS_PER_UNIT) #define POINTER_BYTES (POINTER_SIZE / BITS_PER_UNIT)
...@@ -7658,17 +7659,19 @@ aarch64_mangle_type (const_tree type) ...@@ -7658,17 +7659,19 @@ aarch64_mangle_type (const_tree type)
return NULL; return NULL;
} }
static int
is_mem_p (rtx *x, void *data ATTRIBUTE_UNUSED) /* Return true if the rtx_insn contains a MEM RTX somewhere
{ in it. */
return MEM_P (*x);
}
static bool static bool
is_memory_op (rtx_insn *mem_insn) has_memory_op (rtx_insn *mem_insn)
{ {
rtx pattern = PATTERN (mem_insn); subrtx_iterator::array_type array;
return for_each_rtx (&pattern, is_mem_p, NULL); 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 /* Find the first rtx_insn before insn that will generate an assembly
...@@ -7718,14 +7721,13 @@ dep_between_memop_and_curr (rtx memop) ...@@ -7718,14 +7721,13 @@ dep_between_memop_and_curr (rtx memop)
rtx load_reg; rtx load_reg;
int opno; int opno;
if (!memop) gcc_assert (GET_CODE (memop) == SET);
return false;
if (!REG_P (SET_DEST (memop))) if (!REG_P (SET_DEST (memop)))
return false; return false;
load_reg = SET_DEST (memop); 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]; rtx operand = recog_data.operand[opno];
if (REG_P (operand) if (REG_P (operand)
...@@ -7736,6 +7738,12 @@ dep_between_memop_and_curr (rtx memop) ...@@ -7736,6 +7738,12 @@ dep_between_memop_and_curr (rtx memop)
return false; 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 bool
aarch64_madd_needs_nop (rtx_insn* insn) aarch64_madd_needs_nop (rtx_insn* insn)
{ {
...@@ -7754,24 +7762,26 @@ aarch64_madd_needs_nop (rtx_insn* insn) ...@@ -7754,24 +7762,26 @@ aarch64_madd_needs_nop (rtx_insn* insn)
return false; return false;
prev = aarch64_prev_real_insn (insn); prev = aarch64_prev_real_insn (insn);
if (!prev) if (!prev || !has_memory_op (prev))
return false; return false;
body = single_set (prev); body = single_set (prev);
/* If the previous insn is a memory op and there is no dependency between /* 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 it and the DImode madd, emit a NOP between them. If body is NULL then we
a memory op but body is NULL, emit the nop to be safe, it's probably a have a complex memory operation, probably a load/store pair.
load/store pair insn. */ Be conservative for now and emit a NOP. */
if (is_memory_op (prev) if (GET_MODE (recog_data.operand[0]) == DImode
&& GET_MODE (recog_data.operand[0]) == DImode && (!body || !dep_between_memop_and_curr (body)))
&& (!dep_between_memop_and_curr (body)))
return true; return true;
return false; return false;
} }
/* Implement FINAL_PRESCAN_INSN. */
void void
aarch64_final_prescan_insn (rtx_insn *insn) aarch64_final_prescan_insn (rtx_insn *insn)
{ {
......
...@@ -503,8 +503,11 @@ enum target_cpus ...@@ -503,8 +503,11 @@ enum target_cpus
/* If inserting NOP before a mult-accumulate insn remember to adjust the /* If inserting NOP before a mult-accumulate insn remember to adjust the
length so that conditional branching code is updated appropriately. */ length so that conditional branching code is updated appropriately. */
#define ADJUST_INSN_LENGTH(insn, length) \ #define ADJUST_INSN_LENGTH(insn, length) \
if (aarch64_madd_needs_nop (insn)) \ do \
length += 4; { \
if (aarch64_madd_needs_nop (insn)) \
length += 4; \
} while (0)
#define FINAL_PRESCAN_INSN(INSN, OPVEC, NOPERANDS) \ #define FINAL_PRESCAN_INSN(INSN, OPVEC, NOPERANDS) \
aarch64_final_prescan_insn (INSN); \ aarch64_final_prescan_insn (INSN); \
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment