diff options
author | Ajit Agarwal <ajitkum@xilinx.com> | 2016-01-21 17:15:52 +0000 |
---|---|---|
committer | Michael Eager <eager@gcc.gnu.org> | 2016-01-21 17:15:52 +0000 |
commit | b638c908a7f43892dfe69f58d83cff2ca0a5872b (patch) | |
tree | d4d457c365715aba843c07500952889c615ccf25 /gcc/config/microblaze | |
parent | 128c78a6fbc2a6c1cd827fb133331343731838aa (diff) | |
download | gcc-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.c | 151 | ||||
-rw-r--r-- | gcc/config/microblaze/microblaze.md | 14 | ||||
-rw-r--r-- | gcc/config/microblaze/microblaze.opt | 4 |
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 |