diff mbox

[microblaze] : Optimized Instruction prefetch with the generation of wic

Message ID 37378DC5BCD0EE48BA4B082E0B55DFAA41F425B5@XAP-PVEXMBX02.xlnx.xilinx.com
State New
Headers show

Commit Message

Ajit Kumar Agarwal July 7, 2015, 2:12 p.m. UTC
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  <ajitkum@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 ajitkum@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 mbox

Patch

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