Issue wic prefetch instruction at call site.
authorAjit Agarwal <ajitkum@xilinx.com>
Thu, 21 Jan 2016 17:15:52 +0000 (17:15 +0000)
committerMichael Eager <eager@gcc.gnu.org>
Thu, 21 Jan 2016 17:15:52 +0000 (17:15 +0000)
This optimization is enabled with  microblaze target flag mxl-prefetch.

From-SVN: r232683

gcc/ChangeLog
gcc/config/microblaze/microblaze.c
gcc/config/microblaze/microblaze.md
gcc/config/microblaze/microblaze.opt

index a275bfd6898c5b5f14f29a298240fdee7f3dfd1d..c72db017bae0ac62ec233e8508b22dd14156a752 100644 (file)
@@ -1,3 +1,17 @@
+2016-01-21  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.
+
 2016-01-21  Ajit Agarwal  <ajitkum@xilinx.com>
 
        * config/microblaze/microblaze.h
index 4e778e7d7624fe8d7a1a8f8c9b58a50b99f9f671..baff67a89c9f76f8295ffc626926c398b78f130c 100644 (file)
@@ -43,6 +43,9 @@
 #include "output.h"
 #include "builtins.h"
 #include "rtl-iter.h"
+#include "cfgloop.h"
+#include "insn-addr.h"
+#include "cfgrtl.h"
 
 /* This file should be included last.  */
 #include "target-def.h"
@@ -3607,6 +3610,151 @@ 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.
+
+   Scan up to 32 instructions after the call and checks
+   for the JUMP and call instruction . If there is a call
+   or JUMP instruction in the range of 32 instruction "wic"
+   instruction wont be generated. Otherwise insert the "wic"
+   instruction in the fall through of the call instruction
+   four instruction after the call. before_4 is used for
+   the position to insert "wic" instructions. before_16 is
+   used to check for call and JUMP instruction for first
+   15 insns.  */
+
+static void
+insert_wic_for_ilb_runout (rtx_insn *first)
+{
+  rtx_insn *insn;
+  rtx_insn *before_4 = 0;
+  rtx_insn *before_16 = 0;
+  int addr_offset = 0;
+  int length;
+  int wic_addr0 = 128 * 4;
+  int wic_addr1 = 128 * 4;
+
+  int first_addr = INSN_ADDRESSES (INSN_UID (first));
+
+  for (insn = first; insn; insn = NEXT_INSN (insn))
+    if (INSN_P (insn))
+      {
+        addr_offset = INSN_ADDRESSES (INSN_UID (insn)) - first_addr;
+        length = get_attr_length (insn);
+        if (before_4 == 0 && addr_offset + length >= 4 * 4)
+          before_4 = insn;
+
+        if (JUMP_P(insn))
+          return;
+        if (before_16 == 0 && addr_offset + length >= 14 * 4)
+          before_16 = insn;
+        if (CALL_P (insn) || tablejump_p (insn, 0, 0))
+          return;
+        if (addr_offset + length >= 32 * 4)
+          {
+            gcc_assert (before_4 && before_16);
+            if (wic_addr0 > 4 * 4)
+              {
+                insn =
+                  emit_insn_before (gen_iprefetch
+                                    (gen_int_mode (addr_offset, 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;
+    }
+}
 \f
 #undef TARGET_ENCODE_SECTION_INFO
 #define TARGET_ENCODE_SECTION_INFO      microblaze_encode_section_info
@@ -3699,6 +3847,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;
 \f
 #include "gt-microblaze.h"
index 287c5c97a9961e823bfa1212a52e5a9d79d4a92f..85776237c1ada892da7f00352c3bdfc82ead59e0 100644 (file)
@@ -43,6 +43,9 @@
   (UNSPEC_TLS           106)    ;; jump table
 ])
 
+(define_c_enum "unspec" [
+  UNSPEC_IPREFETCH
+])
 
 ;;----------------------------------------------------
 ;; Instruction Attributes
   (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
index 039ae96c8501caa532048047c7b517e7efbf372c..51734b4ed8fce7cd665b7a72ae8639e8fc7300a9 100644 (file)
@@ -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