summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog16
-rw-r--r--gcc/config/epiphany/epiphany.c75
-rw-r--r--gcc/config/epiphany/epiphany.h7
-rw-r--r--gcc/config/epiphany/epiphany.md10
4 files changed, 65 insertions, 43 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 4f09e5b83ea..554ae342024 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,19 @@
+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>
* 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 2807b3a462b..74192bf4621 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 1e5c3056629..bd84b5c793f 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 7b63ef25da6..1e2d2ab02ed 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"))