Commit e9472c81 by Andrew Burgess

arc: Avoid store/load pipeline hazard

ARC700 targets have a store/load pipeline hazard, if we load within 2
cycles of a store, and the load/store are at the same address, then we
pay a multi-cycle penalty.

This commit avoids this by inserting nop instructions between the store
and the load.

gcc/ChangeLog:

	* config/arc/arc-protos.h (arc_store_addr_hazard_p): Declare.
	* config/arc/arc.c (arc_store_addr_hazard_p): New function.
	(workaround_arc_anomaly): Call arc_store_addr_hazard_p for ARC700.
	* config/arc/arc700.md: Add define_bypass for store/load.

gcc/testsuite/ChangeLog:

	* gcc.target/arc/arc700-stld-hazard.c: New file.

From-SVN: r243007
parent a7da4881
2016-11-30 Claudiu Zissulescu <claziss@synopsys.com>
Andrew Burgess <andrew.burgess@embecosm.com>
* config/arc/arc-protos.h (arc_store_addr_hazard_p): Declare.
* config/arc/arc.c (arc_store_addr_hazard_p): New function.
(workaround_arc_anomaly): Call arc_store_addr_hazard_p for ARC700.
* config/arc/arc700.md: Add define_bypass for store/load.
2016-11-30 Martin Liska <mliska@suse.cz>
* cgraph.c (symbol_table::initialize): Initialize
......@@ -123,3 +123,4 @@ extern bool arc_legitimize_reload_address (rtx *, machine_mode, int, int);
extern void arc_secondary_reload_conv (rtx, rtx, rtx, bool);
extern bool insn_is_tls_gd_dispatch (rtx_insn *);
extern void arc_cpu_cpp_builtins (cpp_reader *);
extern bool arc_store_addr_hazard_p (rtx_insn *, rtx_insn *);
......@@ -6504,6 +6504,58 @@ arc_invalid_within_doloop (const rtx_insn *insn)
return NULL;
}
/* Return true if a load instruction (CONSUMER) uses the same address as a
store instruction (PRODUCER). This function is used to avoid st/ld
address hazard in ARC700 cores. */
bool
arc_store_addr_hazard_p (rtx_insn* producer, rtx_insn* consumer)
{
rtx in_set, out_set;
rtx out_addr, in_addr;
if (!producer)
return false;
if (!consumer)
return false;
/* Peel the producer and the consumer for the address. */
out_set = single_set (producer);
if (out_set)
{
out_addr = SET_DEST (out_set);
if (!out_addr)
return false;
if (GET_CODE (out_addr) == ZERO_EXTEND
|| GET_CODE (out_addr) == SIGN_EXTEND)
out_addr = XEXP (out_addr, 0);
if (!MEM_P (out_addr))
return false;
in_set = single_set (consumer);
if (in_set)
{
in_addr = SET_SRC (in_set);
if (!in_addr)
return false;
if (GET_CODE (in_addr) == ZERO_EXTEND
|| GET_CODE (in_addr) == SIGN_EXTEND)
in_addr = XEXP (in_addr, 0);
if (!MEM_P (in_addr))
return false;
/* Get rid of the MEM and check if the addresses are
equivalent. */
in_addr = XEXP (in_addr, 0);
out_addr = XEXP (out_addr, 0);
return exp_equiv_p (in_addr, out_addr, 0, true);
}
}
return false;
}
/* The same functionality as arc_hazard. It is called in machine
reorg before any other optimization. Hence, the NOP size is taken
into account when doing branch shortening. */
......@@ -6522,6 +6574,29 @@ workaround_arc_anomaly (void)
emit_insn_before (gen_nopv (), succ0);
}
}
if (TARGET_ARC700)
{
rtx_insn *succ1;
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
{
succ0 = next_real_insn (insn);
if (arc_store_addr_hazard_p (insn, succ0))
{
emit_insn_after (gen_nopv (), insn);
emit_insn_after (gen_nopv (), insn);
continue;
}
/* Avoid adding nops if the instruction between the ST and LD is
a call or jump. */
succ1 = next_real_insn (succ0);
if (succ0 && !JUMP_P (succ0) && !CALL_P (succ0)
&& arc_store_addr_hazard_p (insn, succ1))
emit_insn_after (gen_nopv (), insn);
}
}
}
static int arc_reorg_in_progress = 0;
......
......@@ -168,3 +168,5 @@
(eq_attr "type" "store")
(not (match_operand:DI 0 "" "")))
"issue+dmp_write_port")
(define_bypass 3 "data_store" "data_load" "arc_store_addr_hazard_p")
2016-11-30 Andrew Burgess <andrew.burgess@embecosm.com>
* gcc.target/arc/arc700-stld-hazard.c: New file.
2016-11-30 Janus Weil <janus@gcc.gnu.org>
PR fortran/78592
......
/* { dg-do compile } */
/* { dg-options "-mcpu=arc700" } */
volatile int a;
volatile int b;
void
foo ()
{
a = 1;
b = a;
}
/* { dg-final { scan-assembler "st r\[0-9\]+,\\\[@a\\\]\[^\n\]*\n\[ \t\]+nop_s\[^\n\]*\n\[ \t\]+nop_s\[^\n\]*\n\[ \t\]+ld r\[0-9\]+,\\\[@a\\\]" } } */
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