@@ -71,6 +71,7 @@
#include "cgraph.h"
#include "builtins.h"
#include "rtl-iter.h"
+#include "cfgloop.h"
#define MICROBLAZE_VERSION_COMPARE(VA,VB) strcasecmp (VA, VB)
@@ -3593,6 +3594,141 @@ microblaze_legitimate_constant_p (machine_mode mode ATTRIBUTE_UNUSED, rtx x)
return true;
}
+static rtx
+get_branch_target (rtx branch)
+{
+ if (CALL_P (branch))
+ {
+ rtx call;
+
+ call = XVECEXP (PATTERN (branch), 0, 0);
+ if (GET_CODE (call) == SET)
+ call = SET_SRC (call);
+ if (GET_CODE (call) != CALL)
+ abort ();
+ return XEXP (XEXP (call, 0), 0);
+ }
+}
+
+/* Heuristics to identify where to insert at the
+ fall through path of the caller function. If there
+ is a call after the caller branch delay slot then
+ we dont generate the instruction prefetch instruction. */
+
+static void
+insert_wic_for_ilb_runout (rtx_insn *first)
+{
+ rtx_insn *insn, *before_4 = 0, *before_16 = 0;
+ int addr = 0, length, first_addr = -1;
+ int wic_addr0 = 128 * 4, wic_addr1 = 128 * 4;
+ int insert_lnop_after = 0;
+
+ for (insn = first; insn; insn = NEXT_INSN (insn))
+ if (INSN_P (insn))
+ {
+ if (first_addr == -1)
+ first_addr = INSN_ADDRESSES (INSN_UID (insn));
+
+ addr = INSN_ADDRESSES (INSN_UID (insn)) - first_addr;
+ length = get_attr_length (insn);
+
+ if (before_4 == 0 && addr + length >= 4 * 4)
+ before_4 = insn;
+
+ if (JUMP_P(insn))
+ return;
+ if (before_16 == 0 && addr + length >= 14 * 4)
+ before_16 = insn;
+ if (CALL_P (insn) || tablejump_p (insn, 0, 0))
+ return;
+ if (addr + length >= 32 * 4)
+ {
+ gcc_assert (before_4 && before_16);
+ if (wic_addr0 > 4 * 4)
+ {
+ insn =
+ emit_insn_before (gen_iprefetch
+ (gen_int_mode (addr, SImode)),
+ before_4);
+ recog_memoized (insn);
+ INSN_LOCATION (insn) = INSN_LOCATION (before_4);
+ INSN_ADDRESSES_NEW (insn, INSN_ADDRESSES (INSN_UID (before_4)));
+ return;
+ }
+ }
+ }
+}
+
+/* Insert instruction prefetch instruction at the fall
+ through path of the function call. */
+
+static void
+insert_wic (void)
+{
+ rtx_insn *insn;
+ int i, j;
+ basic_block bb,prev = 0;
+ rtx branch_target = 0;
+
+ shorten_branches (get_insns ());
+
+ for (i = 0; i < n_basic_blocks_for_fn (cfun) - 1; i++)
+ {
+ edge e;
+ edge_iterator ei;
+ bool simple_loop = false;
+
+ bb = BASIC_BLOCK_FOR_FN (cfun, i);
+
+ if (bb == NULL)
+ continue;
+
+ if ((prev != 0) && (prev != bb))
+ continue;
+ else
+ prev = 0;
+
+ FOR_EACH_EDGE (e, ei, bb->preds)
+ if (e->src == bb)
+ {
+ simple_loop = true;
+ prev= e->dest;
+ break;
+ }
+
+ for (insn = BB_END (bb); insn; insn = PREV_INSN (insn))
+ {
+ if (INSN_P (insn) && !simple_loop
+ && CALL_P(insn))
+ {
+ if ((branch_target = get_branch_target (insn)))
+ insert_wic_for_ilb_runout (
+ next_active_insn (next_active_insn (insn)));
+ }
+ if (insn == BB_HEAD (bb))
+ break;
+ }
+ }
+}
+
+/* The reorg function defined through the macro
+ TARGET_MACHINE_DEPENDENT_REORG. */
+
+static void
+microblaze_machine_dependent_reorg (void)
+{
+ if (TARGET_PREFETCH)
+ {
+ compute_bb_for_insn ();
+ loop_optimizer_init (AVOID_CFG_MODIFICATIONS);
+ shorten_branches (get_insns ());
+ insert_wic ();
+ loop_optimizer_finalize();
+ free_bb_for_insn ();
+ return;
+ }
+}
+
#undef TARGET_ENCODE_SECTION_INFO
#define TARGET_ENCODE_SECTION_INFO microblaze_encode_section_info
@@ -3685,6 +3821,9 @@ microblaze_legitimate_constant_p (machine_mode mode ATTRIBUTE_UNUSED, rtx x)
#undef TARGET_LEGITIMATE_CONSTANT_P
#define TARGET_LEGITIMATE_CONSTANT_P microblaze_legitimate_constant_p
+#undef TARGET_MACHINE_DEPENDENT_REORG
+#define TARGET_MACHINE_DEPENDENT_REORG microblaze_machine_dependent_reorg
+
struct gcc_target targetm = TARGET_INITIALIZER;
#include "gt-microblaze.h"
@@ -43,6 +43,9 @@
(UNSPEC_TLS 106) ;; jump table
])
+(define_c_enum "unspec" [
+ UNSPEC_IPREFETCH
+])
;;----------------------------------------------------
;; Instruction Attributes
@@ -508,6 +511,17 @@
(set_attr "mode" "SI")
(set_attr "length" "4,8")])
+(define_insn "iprefetch"
+ [(unspec [(match_operand:SI 0 "const_int_operand" "n")] UNSPEC_IPREFETCH)
+ (clobber (mem:BLK (scratch)))]
+ "TARGET_PREFETCH"
+ {
+ operands[2] = gen_rtx_REG (SImode, MB_ABI_ASM_TEMP_REGNUM);
+ return "mfs\t%2,rpc\n\twic\t%2,r0";
+ }
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")
+ (set_attr "length" "8")])
;;----------------------------------------------------------------
;; Double Precision Subtraction
@@ -123,5 +123,9 @@ mxl-mode-novectors
Target Mask(XL_MODE_NOVECTORS)
Description for mxl-mode-novectors
+mxl-prefetch
+Target Mask(PREFETCH)
+Use hardware prefetch instruction
+
mxl-mode-xilkernel
Target