Commit 566be57c by Joern Rennecke Committed by Joern Rennecke

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) <Handle EPIPHANY_MSW_ENTITY_AND>:
	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
parent 0f2c2331
2013-05-12 Joern Rennecke <joern.rennecke@embecosm.com>
* 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) <Handle EPIPHANY_MSW_ENTITY_AND>:
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 <ubizjak@gmail.com> 2013-05-12 Uros Bizjak <ubizjak@gmail.com>
* config/i386/i386.md (*zero_extendsidi2): Add *x->?r alternative. * config/i386/i386.md (*zero_extendsidi2): Add *x->?r alternative.
......
...@@ -181,6 +181,8 @@ epiphany_init (void) ...@@ -181,6 +181,8 @@ epiphany_init (void)
= { &pass_split_all_insns.pass, "mode_sw", = { &pass_split_all_insns.pass, "mode_sw",
1, PASS_POS_INSERT_AFTER 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 (); epiphany_init_reg_tables ();
...@@ -196,6 +198,8 @@ epiphany_init (void) ...@@ -196,6 +198,8 @@ epiphany_init (void)
register_pass (&mode_sw3_info); register_pass (&mode_sw3_info);
register_pass (&insert_use_info); register_pass (&insert_use_info);
register_pass (&mode_sw2_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, #if 1 /* As long as peep2_rescan is not implemented,
(see http://gcc.gnu.org/ml/gcc-patches/2011-10/msg02819.html,) (see http://gcc.gnu.org/ml/gcc-patches/2011-10/msg02819.html,)
...@@ -1773,44 +1777,6 @@ epiphany_expand_prologue (void) ...@@ -1773,44 +1777,6 @@ epiphany_expand_prologue (void)
} }
frame_insn (gen_stack_adjust_add (off, mem)); 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 void
...@@ -2271,6 +2237,7 @@ epiphany_optimize_mode_switching (int entity) ...@@ -2271,6 +2237,7 @@ epiphany_optimize_mode_switching (int entity)
{ {
case EPIPHANY_MSW_ENTITY_AND: case EPIPHANY_MSW_ENTITY_AND:
case EPIPHANY_MSW_ENTITY_OR: case EPIPHANY_MSW_ENTITY_OR:
case EPIPHANY_MSW_ENTITY_CONFIG:
return true; return true;
case EPIPHANY_MSW_ENTITY_NEAREST: case EPIPHANY_MSW_ENTITY_NEAREST:
case EPIPHANY_MSW_ENTITY_TRUNC: case EPIPHANY_MSW_ENTITY_TRUNC:
...@@ -2289,7 +2256,8 @@ epiphany_optimize_mode_switching (int entity) ...@@ -2289,7 +2256,8 @@ epiphany_optimize_mode_switching (int entity)
int int
epiphany_mode_priority_to_mode (int entity, unsigned priority) 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; return priority;
if (priority > 3) if (priority > 3)
switch (priority) switch (priority)
...@@ -2341,7 +2309,8 @@ epiphany_mode_needed (int entity, rtx insn) ...@@ -2341,7 +2309,8 @@ epiphany_mode_needed (int entity, rtx insn)
if (recog_memoized (insn) < 0) if (recog_memoized (insn) < 0)
{ {
if (entity == EPIPHANY_MSW_ENTITY_AND if (entity == EPIPHANY_MSW_ENTITY_AND
|| entity == EPIPHANY_MSW_ENTITY_OR) || entity == EPIPHANY_MSW_ENTITY_OR
|| entity == EPIPHANY_MSW_ENTITY_CONFIG)
return 2; return 2;
return FP_MODE_NONE; return FP_MODE_NONE;
} }
...@@ -2350,9 +2319,16 @@ epiphany_mode_needed (int entity, rtx insn) ...@@ -2350,9 +2319,16 @@ epiphany_mode_needed (int entity, rtx insn)
switch (entity) switch (entity)
{ {
case EPIPHANY_MSW_ENTITY_AND: 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: case EPIPHANY_MSW_ENTITY_OR:
return mode == FP_MODE_INT ? 1 : 2; 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: case EPIPHANY_MSW_ENTITY_ROUND_KNOWN:
if (recog_memoized (insn) == CODE_FOR_set_fp_mode) if (recog_memoized (insn) == CODE_FOR_set_fp_mode)
mode = (enum attr_fp_mode) epiphany_mode_after (entity, mode, insn); mode = (enum attr_fp_mode) epiphany_mode_after (entity, mode, insn);
...@@ -2396,6 +2372,10 @@ epiphany_mode_entry_exit (int entity, bool exit) ...@@ -2396,6 +2372,10 @@ epiphany_mode_entry_exit (int entity, bool exit)
if (exit) if (exit)
return normal_mode == FP_MODE_INT ? 1 : 2; return normal_mode == FP_MODE_INT ? 1 : 2;
return 0; 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: case EPIPHANY_MSW_ENTITY_ROUND_UNKNOWN:
if (normal_mode == FP_MODE_ROUND_NEAREST if (normal_mode == FP_MODE_ROUND_NEAREST
|| normal_mode == FP_MODE_ROUND_TRUNC) || 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) ...@@ -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)); emit_move_insn (MACHINE_FUNCTION (cfun)->or_mask, GEN_INT(0x00080000));
return; 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; fp_mode = (enum attr_fp_mode) mode;
src = NULL_RTX; src = NULL_RTX;
switch (fp_mode) switch (fp_mode)
{ {
case FP_MODE_CALLER: 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); src = get_hard_reg_initial_val (SImode, CONFIG_REGNUM);
mask = MACHINE_FUNCTION (cfun)->and_mask; mask = MACHINE_FUNCTION (cfun)->and_mask;
break; break;
......
...@@ -896,7 +896,8 @@ enum epiphany_function_type ...@@ -896,7 +896,8 @@ enum epiphany_function_type
finally an entity that runs in a second mode switching pass to finally an entity that runs in a second mode switching pass to
resolve FP_MODE_ROUND_UNKNOWN. */ resolve FP_MODE_ROUND_UNKNOWN. */
#define NUM_MODES_FOR_MODE_SWITCHING \ #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)) #define MODE_NEEDED(ENTITY, INSN) epiphany_mode_needed((ENTITY), (INSN))
...@@ -918,11 +919,13 @@ enum ...@@ -918,11 +919,13 @@ enum
{ {
EPIPHANY_MSW_ENTITY_AND, EPIPHANY_MSW_ENTITY_AND,
EPIPHANY_MSW_ENTITY_OR, EPIPHANY_MSW_ENTITY_OR,
EPIPHANY_MSW_ENTITY_CONFIG, /* 1 means config is known or saved. */
EPIPHANY_MSW_ENTITY_NEAREST, EPIPHANY_MSW_ENTITY_NEAREST,
EPIPHANY_MSW_ENTITY_TRUNC, EPIPHANY_MSW_ENTITY_TRUNC,
EPIPHANY_MSW_ENTITY_ROUND_UNKNOWN, EPIPHANY_MSW_ENTITY_ROUND_UNKNOWN,
EPIPHANY_MSW_ENTITY_ROUND_KNOWN, 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; extern int epiphany_normal_fp_rounding;
......
...@@ -1448,6 +1448,16 @@ ...@@ -1448,6 +1448,16 @@
[(set_attr "type" "flow") [(set_attr "type" "flow")
(set_attr "length" "20,4")]) (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" (define_insn_and_split "set_fp_mode"
[(set (reg:SI FP_NEAREST_REGNUM) [(set (reg:SI FP_NEAREST_REGNUM)
(match_operand:SI 0 "set_fp_mode_operand" "rCfm")) (match_operand:SI 0 "set_fp_mode_operand" "rCfm"))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment