All:

 Please find the patch for optimized usage of instruction prefetch with the 
generation of microblaze instruction "wic".
No regressions is seen in Deja GNU tests for microblaze.

[Patch,microblaze]: Optimized Instruction prefetch with the generation of wic
    instruction.
    
    The changes are made in the patch for optimized Instruction prefetch with
    the generation of wic microblaze instructions. The Wic microblaze 
instruction
    is the instruction prefetch instruction that optimizes the Instruction 
prefetch.
    The wic instruction is generated at the call site fall through path and is
    enabled with a flag mxl-prefetch. The purpose of adding the flags is that 
wic
    instruction selected for the particular FPGA design and is not enabled by
    default.
    
    ChangeLog:
    2015-07-07  Ajit Agarwal  <ajit...@xilinx.com>
    
        * config/microblaze/microblaze.c
        (get_branch_target): New.
        (insert_wic_for_ilb_runout): New.
        (insert_wic): New.
        (microblaze_machine_dependent_reorg): New.
        (TARGET_MACHINE_DEPENDENT_REORG): Define macro.
        * config/microblaze/microblaze.md
        (UNSPEC_IPREFETCH): Define.
        (iprefetch): New pattern
        * config/microblaze/microblaze.opt
        (mxl-prefetch): New flag.
    
    Signed-off-by:Ajit Agarwal ajit...@xilinx.com.

---
 gcc/config/microblaze/microblaze.c   |  139 ++++++++++++++++++++++++++++++++++
 gcc/config/microblaze/microblaze.md  |   14 ++++
 gcc/config/microblaze/microblaze.opt |    4 +
 3 files changed, 157 insertions(+), 0 deletions(-)

diff --git a/gcc/config/microblaze/microblaze.c 
b/gcc/config/microblaze/microblaze.c
index 566b78c..eea2f67 100644
--- a/gcc/config/microblaze/microblaze.c
+++ b/gcc/config/microblaze/microblaze.c
@@ -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"
diff --git a/gcc/config/microblaze/microblaze.md 
b/gcc/config/microblaze/microblaze.md
index 67e509c..0365748 100644
--- a/gcc/config/microblaze/microblaze.md
+++ b/gcc/config/microblaze/microblaze.md
@@ -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
diff --git a/gcc/config/microblaze/microblaze.opt 
b/gcc/config/microblaze/microblaze.opt
index a1447a5..10478d2 100644
--- a/gcc/config/microblaze/microblaze.opt
+++ b/gcc/config/microblaze/microblaze.opt
@@ -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
-- 
1.7.1

Thanks & Regards
Ajit

Attachment: 0001-Patch-microblaze-Optimized-Instruction-prefetch-with.patch
Description: 0001-Patch-microblaze-Optimized-Instruction-prefetch-with.patch

Reply via email to