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> 2016-11-30 Martin Liska <mliska@suse.cz>
* cgraph.c (symbol_table::initialize): Initialize * cgraph.c (symbol_table::initialize): Initialize
...@@ -123,3 +123,4 @@ extern bool arc_legitimize_reload_address (rtx *, machine_mode, int, int); ...@@ -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 void arc_secondary_reload_conv (rtx, rtx, rtx, bool);
extern bool insn_is_tls_gd_dispatch (rtx_insn *); extern bool insn_is_tls_gd_dispatch (rtx_insn *);
extern void arc_cpu_cpp_builtins (cpp_reader *); 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) ...@@ -6504,6 +6504,58 @@ arc_invalid_within_doloop (const rtx_insn *insn)
return NULL; 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 /* The same functionality as arc_hazard. It is called in machine
reorg before any other optimization. Hence, the NOP size is taken reorg before any other optimization. Hence, the NOP size is taken
into account when doing branch shortening. */ into account when doing branch shortening. */
...@@ -6522,6 +6574,29 @@ workaround_arc_anomaly (void) ...@@ -6522,6 +6574,29 @@ workaround_arc_anomaly (void)
emit_insn_before (gen_nopv (), succ0); 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; static int arc_reorg_in_progress = 0;
......
...@@ -168,3 +168,5 @@ ...@@ -168,3 +168,5 @@
(eq_attr "type" "store") (eq_attr "type" "store")
(not (match_operand:DI 0 "" ""))) (not (match_operand:DI 0 "" "")))
"issue+dmp_write_port") "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> 2016-11-30 Janus Weil <janus@gcc.gnu.org>
PR fortran/78592 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