From 566be57c16be30fa2386e4badef6c1c26c150002 Mon Sep 17 00:00:00 2001 From: Joern Rennecke Date: Sun, 12 May 2013 21:59:13 +0000 Subject: [PATCH] epiphany.c (epiphany_init): Check size of NUM_MODES_FOR_MODE_SWITCHING. * config/epiphany/epiphany.c (epiphany_init): Check size of NUM_MODES_FOR_MODE_SWITCHING. (epiphany_expand_prologue): Remove CONFIG_REGNUM initial value handling code. (epiphany_optimize_mode_switching): Handle EPIPHANY_MSW_ENTITY_CONFIG. (epiphany_mode_needed, epiphany_mode_entry_exit): Likewise. (emit_set_fp_mode): Likewise. (epiphany_mode_needed) : Don't return 1 for FP_MODE_NONE. * config/epiphany/epiphany.h (NUM_MODES_FOR_MODE_SWITCHING): Add value for EPIPHANY_MSW_ENTITY_CONFIG. (EPIPHANY_MSW_ENTITY_CONFIG, EPIPHANY_MSW_ENTITY_NUM): Define. * config/epiphany/epiphany.md (save_config): New pattern. From-SVN: r198807 --- gcc/ChangeLog | 16 +++++++++ gcc/config/epiphany/epiphany.c | 75 +++++++++++++++++++---------------------- gcc/config/epiphany/epiphany.h | 7 ++-- gcc/config/epiphany/epiphany.md | 10 ++++++ 4 files changed, 65 insertions(+), 43 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4f09e5b..554ae34 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,19 @@ +2013-05-12 Joern Rennecke + + * config/epiphany/epiphany.c (epiphany_init): Check size of + NUM_MODES_FOR_MODE_SWITCHING. + (epiphany_expand_prologue): + Remove CONFIG_REGNUM initial value handling code. + (epiphany_optimize_mode_switching): Handle EPIPHANY_MSW_ENTITY_CONFIG. + (epiphany_mode_needed, epiphany_mode_entry_exit): Likewise. + (emit_set_fp_mode): Likewise. + (epiphany_mode_needed) : + Don't return 1 for FP_MODE_NONE. + * config/epiphany/epiphany.h (NUM_MODES_FOR_MODE_SWITCHING): + Add value for EPIPHANY_MSW_ENTITY_CONFIG. + (EPIPHANY_MSW_ENTITY_CONFIG, EPIPHANY_MSW_ENTITY_NUM): Define. + * config/epiphany/epiphany.md (save_config): New pattern. + 2013-05-12 Uros Bizjak * config/i386/i386.md (*zero_extendsidi2): Add *x->?r alternative. diff --git a/gcc/config/epiphany/epiphany.c b/gcc/config/epiphany/epiphany.c index 2807b3a..74192bf 100644 --- a/gcc/config/epiphany/epiphany.c +++ b/gcc/config/epiphany/epiphany.c @@ -181,6 +181,8 @@ epiphany_init (void) = { &pass_split_all_insns.pass, "mode_sw", 1, PASS_POS_INSERT_AFTER }; + static const int num_modes[] = NUM_MODES_FOR_MODE_SWITCHING; +#define N_ENTITIES ARRAY_SIZE (num_modes) epiphany_init_reg_tables (); @@ -196,6 +198,8 @@ epiphany_init (void) register_pass (&mode_sw3_info); register_pass (&insert_use_info); register_pass (&mode_sw2_info); + /* Verify that NUM_MODES_FOR_MODE_SWITCHING has one value per entity. */ + gcc_assert (N_ENTITIES == EPIPHANY_MSW_ENTITY_NUM); #if 1 /* As long as peep2_rescan is not implemented, (see http://gcc.gnu.org/ml/gcc-patches/2011-10/msg02819.html,) @@ -1773,44 +1777,6 @@ epiphany_expand_prologue (void) } frame_insn (gen_stack_adjust_add (off, mem)); } - - /* Mode switching uses get_hard_reg_initial_val after - emit_initial_value_sets, so we have to fix this up now. */ - save_config = has_hard_reg_initial_val (SImode, CONFIG_REGNUM); - if (save_config) - { - if (REG_P (save_config)) - { - if (REGNO (save_config) >= FIRST_PSEUDO_REGISTER) - gcc_assert (!df_regs_ever_live_p (REGNO (save_config))); - else - frame_move_insn (save_config, - get_hard_reg_initial_reg (save_config)); - } - else - { - rtx save_dst = save_config; - - reg = gen_rtx_REG (SImode, GPR_IP); - gcc_assert (MEM_P (save_dst)); - if (!memory_operand (save_dst, SImode)) - { - rtx addr = XEXP (save_dst, 0); - rtx reg2 = gen_rtx_REG (SImode, GPR_16); - - gcc_assert (GET_CODE (addr) == PLUS); - gcc_assert (XEXP (addr, 0) == hard_frame_pointer_rtx - || XEXP (addr, 0) == stack_pointer_rtx); - emit_move_insn (reg2, XEXP (addr, 1)); - save_dst - = replace_equiv_address (save_dst, - gen_rtx_PLUS (Pmode, XEXP (addr, 0), - reg2)); - } - emit_move_insn (reg, get_hard_reg_initial_reg (save_config)); - emit_move_insn (save_dst, reg); - } - } } void @@ -2271,6 +2237,7 @@ epiphany_optimize_mode_switching (int entity) { case EPIPHANY_MSW_ENTITY_AND: case EPIPHANY_MSW_ENTITY_OR: + case EPIPHANY_MSW_ENTITY_CONFIG: return true; case EPIPHANY_MSW_ENTITY_NEAREST: case EPIPHANY_MSW_ENTITY_TRUNC: @@ -2289,7 +2256,8 @@ epiphany_optimize_mode_switching (int entity) int epiphany_mode_priority_to_mode (int entity, unsigned priority) { - if (entity == EPIPHANY_MSW_ENTITY_AND || entity == EPIPHANY_MSW_ENTITY_OR) + if (entity == EPIPHANY_MSW_ENTITY_AND || entity == EPIPHANY_MSW_ENTITY_OR + || entity== EPIPHANY_MSW_ENTITY_CONFIG) return priority; if (priority > 3) switch (priority) @@ -2341,7 +2309,8 @@ epiphany_mode_needed (int entity, rtx insn) if (recog_memoized (insn) < 0) { if (entity == EPIPHANY_MSW_ENTITY_AND - || entity == EPIPHANY_MSW_ENTITY_OR) + || entity == EPIPHANY_MSW_ENTITY_OR + || entity == EPIPHANY_MSW_ENTITY_CONFIG) return 2; return FP_MODE_NONE; } @@ -2350,9 +2319,16 @@ epiphany_mode_needed (int entity, rtx insn) switch (entity) { case EPIPHANY_MSW_ENTITY_AND: - return mode != FP_MODE_INT ? 1 : 2; + return mode != FP_MODE_NONE && mode != FP_MODE_INT ? 1 : 2; case EPIPHANY_MSW_ENTITY_OR: return mode == FP_MODE_INT ? 1 : 2; + case EPIPHANY_MSW_ENTITY_CONFIG: + /* We must know/save config before we set it to something else. + Where we need the original value, we are fine with having it + just unchanged from the function start. + Because of the nature of the mode switching optimization, + a restore will be dominated by a clobber. */ + return mode != FP_MODE_NONE && mode != FP_MODE_CALLER ? 1 : 2; case EPIPHANY_MSW_ENTITY_ROUND_KNOWN: if (recog_memoized (insn) == CODE_FOR_set_fp_mode) mode = (enum attr_fp_mode) epiphany_mode_after (entity, mode, insn); @@ -2396,6 +2372,10 @@ epiphany_mode_entry_exit (int entity, bool exit) if (exit) return normal_mode == FP_MODE_INT ? 1 : 2; return 0; + case EPIPHANY_MSW_ENTITY_CONFIG: + if (exit) + return 2; + return normal_mode == FP_MODE_CALLER ? 0 : 1; case EPIPHANY_MSW_ENTITY_ROUND_UNKNOWN: if (normal_mode == FP_MODE_ROUND_NEAREST || normal_mode == FP_MODE_ROUND_TRUNC) @@ -2475,12 +2455,25 @@ emit_set_fp_mode (int entity, int mode, HARD_REG_SET regs_live ATTRIBUTE_UNUSED) emit_move_insn (MACHINE_FUNCTION (cfun)->or_mask, GEN_INT(0x00080000)); return; } + else if (entity == EPIPHANY_MSW_ENTITY_CONFIG) + { + /* Mode switching optimization is done after emit_initial_value_sets, + so we have to take care of CONFIG_REGNUM here. */ + gcc_assert (mode >= 0 && mode <= 2); + rtx save = get_hard_reg_initial_val (SImode, CONFIG_REGNUM); + if (mode == 1) + emit_insn (gen_save_config (save)); + return; + } fp_mode = (enum attr_fp_mode) mode; src = NULL_RTX; switch (fp_mode) { case FP_MODE_CALLER: + /* The EPIPHANY_MSW_ENTITY_CONFIG processing must come later + so that the config save gets inserted before the first use. */ + gcc_assert (entity > EPIPHANY_MSW_ENTITY_CONFIG); src = get_hard_reg_initial_val (SImode, CONFIG_REGNUM); mask = MACHINE_FUNCTION (cfun)->and_mask; break; diff --git a/gcc/config/epiphany/epiphany.h b/gcc/config/epiphany/epiphany.h index 1e5c305..bd84b5c 100644 --- a/gcc/config/epiphany/epiphany.h +++ b/gcc/config/epiphany/epiphany.h @@ -896,7 +896,8 @@ enum epiphany_function_type finally an entity that runs in a second mode switching pass to resolve FP_MODE_ROUND_UNKNOWN. */ #define NUM_MODES_FOR_MODE_SWITCHING \ - { 2, 2, FP_MODE_NONE, FP_MODE_NONE, FP_MODE_NONE, FP_MODE_NONE, FP_MODE_NONE } + { 2, 2, 2, \ + FP_MODE_NONE, FP_MODE_NONE, FP_MODE_NONE, FP_MODE_NONE, FP_MODE_NONE } #define MODE_NEEDED(ENTITY, INSN) epiphany_mode_needed((ENTITY), (INSN)) @@ -918,11 +919,13 @@ enum { EPIPHANY_MSW_ENTITY_AND, EPIPHANY_MSW_ENTITY_OR, + EPIPHANY_MSW_ENTITY_CONFIG, /* 1 means config is known or saved. */ EPIPHANY_MSW_ENTITY_NEAREST, EPIPHANY_MSW_ENTITY_TRUNC, EPIPHANY_MSW_ENTITY_ROUND_UNKNOWN, EPIPHANY_MSW_ENTITY_ROUND_KNOWN, - EPIPHANY_MSW_ENTITY_FPU_OMNIBUS + EPIPHANY_MSW_ENTITY_FPU_OMNIBUS, + EPIPHANY_MSW_ENTITY_NUM }; extern int epiphany_normal_fp_rounding; diff --git a/gcc/config/epiphany/epiphany.md b/gcc/config/epiphany/epiphany.md index 7b63ef2..1e2d2ab 100644 --- a/gcc/config/epiphany/epiphany.md +++ b/gcc/config/epiphany/epiphany.md @@ -1448,6 +1448,16 @@ [(set_attr "type" "flow") (set_attr "length" "20,4")]) +(define_insn_and_split "save_config" + [(set (match_operand:SI 0 "gpr_operand" "=r") (reg:SI CONFIG_REGNUM)) + (use (reg:SI FP_NEAREST_REGNUM)) + (use (reg:SI FP_TRUNCATE_REGNUM)) + (use (reg:SI FP_ANYFP_REGNUM))] + "" + "#" + "reload_completed" + [(set (match_dup 0) (reg:SI CONFIG_REGNUM))]) + (define_insn_and_split "set_fp_mode" [(set (reg:SI FP_NEAREST_REGNUM) (match_operand:SI 0 "set_fp_mode_operand" "rCfm")) -- 2.7.4