epiphany.c (epiphany_init): Check size of NUM_MODES_FOR_MODE_SWITCHING.
authorJoern Rennecke <joern.rennecke@embecosm.com>
Sun, 12 May 2013 21:59:13 +0000 (21:59 +0000)
committerJoern Rennecke <amylaar@gcc.gnu.org>
Sun, 12 May 2013 21:59:13 +0000 (22:59 +0100)
* 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

gcc/ChangeLog
gcc/config/epiphany/epiphany.c
gcc/config/epiphany/epiphany.h
gcc/config/epiphany/epiphany.md

index 4f09e5b..554ae34 100644 (file)
@@ -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.
index 2807b3a..74192bf 100644 (file)
@@ -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;
index 1e5c305..bd84b5c 100644 (file)
@@ -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;
index 7b63ef2..1e2d2ab 100644 (file)
   [(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"))