aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/microblaze
diff options
context:
space:
mode:
authorAjit Agarwal <ajitkum@xilinx.com>2016-01-21 17:15:52 +0000
committerMichael Eager <eager@gcc.gnu.org>2016-01-21 17:15:52 +0000
commitb638c908a7f43892dfe69f58d83cff2ca0a5872b (patch)
treed4d457c365715aba843c07500952889c615ccf25 /gcc/config/microblaze
parent128c78a6fbc2a6c1cd827fb133331343731838aa (diff)
downloadgcc-b638c908a7f43892dfe69f58d83cff2ca0a5872b.zip
gcc-b638c908a7f43892dfe69f58d83cff2ca0a5872b.tar.gz
gcc-b638c908a7f43892dfe69f58d83cff2ca0a5872b.tar.bz2
Issue wic prefetch instruction at call site.
This optimization is enabled with microblaze target flag mxl-prefetch. From-SVN: r232683
Diffstat (limited to 'gcc/config/microblaze')
-rw-r--r--gcc/config/microblaze/microblaze.c151
-rw-r--r--gcc/config/microblaze/microblaze.md14
-rw-r--r--gcc/config/microblaze/microblaze.opt4
3 files changed, 169 insertions, 0 deletions
diff --git a/gcc/config/microblaze/microblaze.c b/gcc/config/microblaze/microblaze.c
index 4e778e7..baff67a 100644
--- a/gcc/config/microblaze/microblaze.c
+++ b/gcc/config/microblaze/microblaze.c
@@ -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;
+ }
+}
#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;
#include "gt-microblaze.h"
diff --git a/gcc/config/microblaze/microblaze.md b/gcc/config/microblaze/microblaze.md
index 287c5c9..8577623 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 039ae96..51734b4 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