+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
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. */
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;