From: Nick Clifton Date: Fri, 21 Nov 2014 10:32:06 +0000 (+0000) Subject: rl78-real.md (movqi_from_es): New pattern. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=7bbf5a3df249f950e33a5d44bbeb71df4ac43493;p=gcc.git rl78-real.md (movqi_from_es): New pattern. * config/rl78/rl78-real.md (movqi_from_es): New pattern. * config/rl78/rl78.c (struct machine_function): Add uses_es field. (rl78_expand_prologue): Save the ES register in interrupt handlers that use it. (rl78_expand_epilogue): Restore the ES register if necessary. (rl78_start_function): Mention if the function uses the ES register. (rl78_lo16): Record the use of the ES register. (transcode_memory_rtx): Likewise. From-SVN: r217911 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3235ba0da45..f9f8ecba20c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2014-11-21 Nick Clifton + + * config/rl78/rl78-real.md (movqi_from_es): New pattern. + * config/rl78/rl78.c (struct machine_function): Add uses_es field. + (rl78_expand_prologue): Save the ES register in interrupt handlers + that use it. + (rl78_expand_epilogue): Restore the ES register if necessary. + (rl78_start_function): Mention if the function uses the ES + register. + (rl78_lo16): Record the use of the ES register. + (transcode_memory_rtx): Likewise. + 2014-11-21 Jakub Jelinek PR tree-optimization/61773 diff --git a/gcc/config/rl78/rl78-real.md b/gcc/config/rl78/rl78-real.md index 00b8c9f22ad..6fac2a3f65c 100644 --- a/gcc/config/rl78/rl78-real.md +++ b/gcc/config/rl78/rl78-real.md @@ -36,6 +36,13 @@ "mov\tes, %0" ) +(define_insn "movqi_from_es" + [(set (match_operand:QI 0 "register_operand" "=a") + (reg:QI ES_REG))] + "" + "mov\t%0, es" +) + (define_insn "movqi_cs" [(set (reg:QI CS_REG) (match_operand:QI 0 "register_operand" "a"))] diff --git a/gcc/config/rl78/rl78.c b/gcc/config/rl78/rl78.c index 86d2992c38e..c7520aaac6b 100644 --- a/gcc/config/rl78/rl78.c +++ b/gcc/config/rl78/rl78.c @@ -118,6 +118,9 @@ struct GTY(()) machine_function int virt_insns_ok; /* Set if the current function needs to clean up any trampolines. */ int trampolines_used; + /* True if the ES register is used and hence + needs to be saved inside interrupt handlers. */ + bool uses_es; }; /* This is our init_machine_status, as set in @@ -136,38 +139,36 @@ rl78_init_machine_status (void) /* This pass converts virtual instructions using virtual registers, to real instructions using real registers. Rather than run it as reorg, we reschedule it before vartrack to help with debugging. */ -namespace { - -const pass_data pass_data_rl78_devirt = -{ - RTL_PASS, /* type */ - "devirt", /* name */ - OPTGROUP_NONE, /* optinfo_flags */ - TV_MACH_DEP, /* tv_id */ - 0, /* properties_required */ - 0, /* properties_provided */ - 0, /* properties_destroyed */ - 0, /* todo_flags_start */ - 0, /* todo_flags_finish */ -}; +namespace +{ + const pass_data pass_data_rl78_devirt = + { + RTL_PASS, /* type */ + "devirt", /* name */ + OPTGROUP_NONE, /* optinfo_flags */ + TV_MACH_DEP, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + 0, /* todo_flags_finish */ + }; -class pass_rl78_devirt : public rtl_opt_pass -{ -public: - pass_rl78_devirt(gcc::context *ctxt) - : rtl_opt_pass(pass_data_rl78_devirt, ctxt) + class pass_rl78_devirt : public rtl_opt_pass { - } + public: + pass_rl78_devirt (gcc::context *ctxt) + : rtl_opt_pass (pass_data_rl78_devirt, ctxt) + { + } - /* opt_pass methods: */ - virtual unsigned int execute (function *) + /* opt_pass methods: */ + virtual unsigned int execute (function *) { rl78_reorg (); return 0; } - -}; - + }; } // anon namespace rtl_opt_pass * @@ -203,8 +204,7 @@ move_elim_pass (void) can eliminate the second SET. */ if (prev && rtx_equal_p (SET_DEST (prev), SET_SRC (set)) - && rtx_equal_p (SET_DEST (set), SET_SRC (prev)) - ) + && rtx_equal_p (SET_DEST (set), SET_SRC (prev))) { if (dump_file) fprintf (dump_file, " Delete insn %d because it is redundant\n", @@ -216,40 +216,39 @@ move_elim_pass (void) else prev = set; } - + if (dump_file) print_rtl_with_bb (dump_file, get_insns (), 0); return 0; } -namespace { - -const pass_data pass_data_rl78_move_elim = +namespace { - RTL_PASS, /* type */ - "move_elim", /* name */ - OPTGROUP_NONE, /* optinfo_flags */ - TV_MACH_DEP, /* tv_id */ - 0, /* properties_required */ - 0, /* properties_provided */ - 0, /* properties_destroyed */ - 0, /* todo_flags_start */ - 0, /* todo_flags_finish */ -}; + const pass_data pass_data_rl78_move_elim = + { + RTL_PASS, /* type */ + "move_elim", /* name */ + OPTGROUP_NONE, /* optinfo_flags */ + TV_MACH_DEP, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + 0, /* todo_flags_finish */ + }; -class pass_rl78_move_elim : public rtl_opt_pass -{ -public: - pass_rl78_move_elim(gcc::context *ctxt) - : rtl_opt_pass(pass_data_rl78_move_elim, ctxt) + class pass_rl78_move_elim : public rtl_opt_pass { - } - - /* opt_pass methods: */ - virtual unsigned int execute (function *) { return move_elim_pass (); } -}; + public: + pass_rl78_move_elim (gcc::context *ctxt) + : rtl_opt_pass (pass_data_rl78_move_elim, ctxt) + { + } + /* opt_pass methods: */ + virtual unsigned int execute (function *) { return move_elim_pass (); } + }; } // anon namespace rtl_opt_pass * @@ -832,6 +831,7 @@ rl78_far_p (rtx x) /* Return the appropriate mode for a named address pointer. */ #undef TARGET_ADDR_SPACE_POINTER_MODE #define TARGET_ADDR_SPACE_POINTER_MODE rl78_addr_space_pointer_mode + static machine_mode rl78_addr_space_pointer_mode (addr_space_t addrspace) { @@ -849,6 +849,7 @@ rl78_addr_space_pointer_mode (addr_space_t addrspace) /* Returns TRUE for valid addresses. */ #undef TARGET_VALID_POINTER_MODE #define TARGET_VALID_POINTER_MODE rl78_valid_pointer_mode + static bool rl78_valid_pointer_mode (machine_mode m) { @@ -858,6 +859,7 @@ rl78_valid_pointer_mode (machine_mode m) /* Return the appropriate mode for a named address address. */ #undef TARGET_ADDR_SPACE_ADDRESS_MODE #define TARGET_ADDR_SPACE_ADDRESS_MODE rl78_addr_space_address_mode + static machine_mode rl78_addr_space_address_mode (addr_space_t addrspace) { @@ -936,6 +938,7 @@ rl78_as_legitimate_address (machine_mode mode ATTRIBUTE_UNUSED, rtx x, /* Determine if one named address space is a subset of another. */ #undef TARGET_ADDR_SPACE_SUBSET_P #define TARGET_ADDR_SPACE_SUBSET_P rl78_addr_space_subset_p + static bool rl78_addr_space_subset_p (addr_space_t subset, addr_space_t superset) { @@ -951,6 +954,7 @@ rl78_addr_space_subset_p (addr_space_t subset, addr_space_t superset) #undef TARGET_ADDR_SPACE_CONVERT #define TARGET_ADDR_SPACE_CONVERT rl78_addr_space_convert + /* Convert from one address space to another. */ static rtx rl78_addr_space_convert (rtx op, tree from_type, tree to_type) @@ -1008,6 +1012,34 @@ rl78_mode_code_base_reg_class (machine_mode mode ATTRIBUTE_UNUSED, return V_REGS; } +/* Typical stack layout should looks like this after the function's prologue: + + | | + -- ^ + | | \ | + | | arguments saved | Increasing + | | on the stack | addresses + PARENT arg pointer -> | | / + -------------------------- ---- ------------------- + CHILD |ret | return address + -- + | | \ + | | call saved + | | registers + frame pointer -> | | / + -- + | | \ + | | local + | | variables + | | / + -- + | | \ + | | outgoing | Decreasing + | | arguments | addresses + current stack pointer -> | | / | + -------------------------- ---- ------------------ V + | | */ + /* Implements INITIAL_ELIMINATION_OFFSET. The frame layout is described in the machine_Function struct definition, above. */ int @@ -1082,7 +1114,8 @@ rl78_expand_prologue (void) { if (TARGET_G10) { - emit_move_insn (gen_rtx_REG (HImode, 0), gen_rtx_REG (HImode, i*2)); + if (i != 0) + emit_move_insn (gen_rtx_REG (HImode, 0), gen_rtx_REG (HImode, i * 2)); F (emit_insn (gen_push (gen_rtx_REG (HImode, 0)))); } else @@ -1101,6 +1134,13 @@ rl78_expand_prologue (void) if (rb != 0) emit_insn (gen_sel_rb (GEN_INT (0))); + /* Save ES register inside interrupt functions if it is used. */ + if (is_interrupt_func (cfun->decl) && cfun->machine->uses_es) + { + emit_insn (gen_movqi_from_es (gen_rtx_REG (QImode, A_REG))); + F (emit_insn (gen_push (gen_rtx_REG (HImode, AX_REG)))); + } + if (frame_pointer_needed) { F (emit_move_insn (gen_rtx_REG (HImode, AX_REG), @@ -1148,6 +1188,12 @@ rl78_expand_epilogue (void) } } + if (is_interrupt_func (cfun->decl) && cfun->machine->uses_es) + { + emit_insn (gen_pop (gen_rtx_REG (HImode, AX_REG))); + emit_insn (gen_movqi_es (gen_rtx_REG (QImode, A_REG))); + } + for (i = 15; i >= 0; i--) if (cfun->machine->need_to_push [i]) { @@ -1234,6 +1280,9 @@ rl78_start_function (FILE *file, HOST_WIDE_INT hwi_local ATTRIBUTE_UNUSED) if (cfun->machine->framesize_outgoing) fprintf (file, "\t; outgoing: %d byte%s\n", cfun->machine->framesize_outgoing, cfun->machine->framesize_outgoing == 1 ? "" : "s"); + + if (cfun->machine->uses_es) + fprintf (file, "\t; uses ES register\n"); } /* Return an RTL describing where a function return value of type RET_TYPE @@ -2170,7 +2219,7 @@ rl78_es_base (rtx addr) carefully to ensure that all the constraint information is accurate for the newly matched insn. */ static bool -insn_ok_now (rtx_insn *insn) +insn_ok_now (rtx_insn * insn) { rtx pattern = PATTERN (insn); int i; @@ -2234,7 +2283,7 @@ insn_ok_now (rtx_insn *insn) #if DEBUG_ALLOC #define WORKED fprintf (stderr, "\033[48;5;22m Worked at line %d \033[0m\n", __LINE__) #define FAILEDSOFAR fprintf (stderr, "\033[48;5;52m FAILED at line %d \033[0m\n", __LINE__) -#define FAILED fprintf (stderr, "\033[48;5;52m FAILED at line %d \033[0m\n", __LINE__), gcc_unreachable() +#define FAILED fprintf (stderr, "\033[48;5;52m FAILED at line %d \033[0m\n", __LINE__), gcc_unreachable () #define MAYBE_OK(insn) if (insn_ok_now (insn)) { WORKED; return; } else { FAILEDSOFAR; } #define MUST_BE_OK(insn) if (insn_ok_now (insn)) { WORKED; return; } FAILED #else @@ -2308,6 +2357,7 @@ rl78_lo16 (rtx addr) r = rl78_subreg (HImode, addr, SImode, 0); r = gen_es_addr (r); + cfun->machine->uses_es = true; return r; } @@ -2496,7 +2546,10 @@ transcode_memory_rtx (rtx m, rtx newbase, rtx before) debug_rtx (m); #endif if (need_es) - m = change_address (m, GET_MODE (m), gen_es_addr (base)); + { + m = change_address (m, GET_MODE (m), gen_es_addr (base)); + cfun->machine->uses_es = true; + } else m = change_address (m, GET_MODE (m), base); #if DEBUG_ALLOC @@ -2642,7 +2695,7 @@ move_to_de (int opno, rtx before) /* Devirtualize an insn of the form (SET (op) (unop (op))). */ static void -rl78_alloc_physical_registers_op1 (rtx_insn *insn) +rl78_alloc_physical_registers_op1 (rtx_insn * insn) { /* op[0] = func op[1] */ @@ -2721,7 +2774,7 @@ has_constraint (unsigned int opnum, enum constraint_num constraint) /* Devirtualize an insn of the form (SET (op) (binop (op) (op))). */ static void -rl78_alloc_physical_registers_op2 (rtx_insn *insn) +rl78_alloc_physical_registers_op2 (rtx_insn * insn) { rtx prev; rtx first; @@ -2875,7 +2928,7 @@ rl78_alloc_physical_registers_op2 (rtx_insn *insn) /* Devirtualize an insn of the form SET (PC) (MEM/REG). */ static void -rl78_alloc_physical_registers_ro1 (rtx_insn *insn) +rl78_alloc_physical_registers_ro1 (rtx_insn * insn) { OP (0) = transcode_memory_rtx (OP (0), BC, insn); @@ -2888,7 +2941,7 @@ rl78_alloc_physical_registers_ro1 (rtx_insn *insn) /* Devirtualize a compare insn. */ static void -rl78_alloc_physical_registers_cmp (rtx_insn *insn) +rl78_alloc_physical_registers_cmp (rtx_insn * insn) { int tmp_id; rtx saved_op1; @@ -2981,7 +3034,7 @@ rl78_alloc_physical_registers_cmp (rtx_insn *insn) /* Like op2, but AX = A * X. */ static void -rl78_alloc_physical_registers_umul (rtx_insn *insn) +rl78_alloc_physical_registers_umul (rtx_insn * insn) { rtx prev = prev_nonnote_nondebug_insn (insn); rtx first; @@ -3045,7 +3098,7 @@ rl78_alloc_physical_registers_umul (rtx_insn *insn) } static void -rl78_alloc_address_registers_macax (rtx_insn *insn) +rl78_alloc_address_registers_macax (rtx_insn * insn) { int which, op; bool replace_in_op0 = false;