OSDN Git Service

2009-11-04 Richard Guenther <rguenther@suse.de>
[pf3gnuchains/gcc-fork.git] / gcc / auto-inc-dec.c
index 8dbcecf..3b3006c 100644 (file)
@@ -1,5 +1,5 @@
 /* Discovery of auto-inc and auto-dec instructions.
-   Copyright (C) 2006, 2007 Free Software Foundation, Inc.
+   Copyright (C) 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
    Contributed by Kenneth Zadeck <zadeck@naturalbridge.com>
    
 This file is part of GCC.
@@ -40,12 +40,14 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-pass.h"
 #include "df.h"
 #include "dbgcnt.h"
+#include "target.h"
 
 /* This pass was originally removed from flow.c. However there is
    almost nothing that remains of that code.
 
    There are (4) basic forms that are matched:
 
+      (1) FORM_PRE_ADD
            a <- b + c
            ...
            *a
@@ -55,6 +57,9 @@ along with GCC; see the file COPYING3.  If not see
            a <- b
            ...
            *(a += c) pre
+
+
+      (2) FORM_PRE_INC
            a += c
            ...
            *a
@@ -62,18 +67,24 @@ along with GCC; see the file COPYING3.  If not see
         becomes
 
            *(a += c) pre
+
+
+      (3) FORM_POST_ADD
            *a
            ...
            b <- a + c
 
-          for this case to be true, b must not be assigned or used between 
-          the *a and the assignment to b.  B must also be a Pmode reg.
+          (For this case to be true, b must not be assigned or used between 
+          the *a and the assignment to b.  B must also be a Pmode reg.)
 
         becomes
 
            b <- a
            ...
            *(b += c) post
+
+
+      (4) FORM_POST_INC
            *a
            ...
            a <- a + c
@@ -99,56 +110,8 @@ along with GCC; see the file COPYING3.  If not see
   The is one special case: if a already had an offset equal to it +-
   its width and that offset is equal to -c when the increment was
   before the ref or +c if the increment was after the ref, then if we
-  can do the combination but switch the pre/post bit.
-
-        (1) FORM_PRE_ADD
-
-           a <- b + c
-           ...
-           *(a - c)
-
-        becomes
+  can do the combination but switch the pre/post bit.  */
 
-           a <- b
-           ...
-           *(a += c) post
-
-        (2) FORM_PRE_INC
-
-           a += c
-           ...
-           *(a - c)
-
-        becomes
-
-           *(a += c) post
-
-        (3) FORM_POST_ADD
-
-           *(a + c)
-           ...
-           b <- a + c
-
-          for this case to be true, b must not be assigned or used between 
-          the *a and the assignment to b. B must also be a Pmode reg.
-
-        becomes
-
-           b <- a
-           ...
-           *(b += c) pre
-
-
-        (4) FORM_POST_INC
-
-           *(a + c)
-           ...
-           a <- a + c 
-
-        becomes
-
-           *(a += c) pre
-*/
 #ifdef AUTO_INC_DEC
 
 enum form
@@ -515,14 +478,15 @@ attempt_change (rtx new_addr, rtx inc_reg)
   rtx new_mem;
   int old_cost = 0;
   int new_cost = 0;
+  bool speed = optimize_bb_for_speed_p (bb);
 
   PUT_MODE (mem_tmp, mode);
   XEXP (mem_tmp, 0) = new_addr;
 
-  old_cost = rtx_cost (mem, 0) 
-    + rtx_cost (PATTERN (inc_insn.insn), 0);
-  new_cost = rtx_cost (mem_tmp, 0);
-  
+  old_cost = (rtx_cost (mem, SET, speed)
+             + rtx_cost (PATTERN (inc_insn.insn), SET, speed));
+  new_cost = rtx_cost (mem_tmp, SET, speed);
+
   /* The first item of business is to see if this is profitable.  */
   if (old_cost < new_cost)
     {
@@ -621,8 +585,7 @@ attempt_change (rtx new_addr, rtx inc_reg)
     }
 
   /* Record that this insn has an implicit side effect.  */
-  REG_NOTES (mem_insn.insn) 
-    = alloc_EXPR_LIST (REG_INC, inc_reg, REG_NOTES (mem_insn.insn));
+  add_reg_note (mem_insn.insn, REG_INC, inc_reg);
 
   if (dump_file)
     {
@@ -636,7 +599,7 @@ attempt_change (rtx new_addr, rtx inc_reg)
 
 /* Try to combine the instruction in INC_INSN with the instruction in
    MEM_INSN.  First the form is determined using the DECISION_TABLE
-   and and the results of parsing the INC_INSN and the MEM_INSN.
+   and the results of parsing the INC_INSN and the MEM_INSN.
    Assuming the form is ok, a prototype new address is built which is
    passed to ATTEMPT_CHANGE for final processing.  */
 
@@ -651,6 +614,7 @@ try_merge (void)
   /* The width of the mem being accessed.  */
   int size = GET_MODE_SIZE (GET_MODE (mem));
   rtx last_insn = NULL;
+  enum machine_mode reg_mode = GET_MODE (inc_reg);
 
   switch (inc_insn.form)
     {
@@ -705,33 +669,33 @@ try_merge (void)
     case SIMPLE_PRE_INC:     /* ++size  */
       if (dump_file)
        fprintf (dump_file, "trying SIMPLE_PRE_INC\n");
-      return attempt_change (gen_rtx_PRE_INC (Pmode, inc_reg), inc_reg);
+      return attempt_change (gen_rtx_PRE_INC (reg_mode, inc_reg), inc_reg);
       break;
       
     case SIMPLE_POST_INC:    /* size++  */
       if (dump_file)
        fprintf (dump_file, "trying SIMPLE_POST_INC\n");
-      return attempt_change (gen_rtx_POST_INC (Pmode, inc_reg), inc_reg);
+      return attempt_change (gen_rtx_POST_INC (reg_mode, inc_reg), inc_reg);
       break;
       
     case SIMPLE_PRE_DEC:     /* --size  */
       if (dump_file)
        fprintf (dump_file, "trying SIMPLE_PRE_DEC\n");
-      return attempt_change (gen_rtx_PRE_DEC (Pmode, inc_reg), inc_reg);
+      return attempt_change (gen_rtx_PRE_DEC (reg_mode, inc_reg), inc_reg);
       break;
       
     case SIMPLE_POST_DEC:    /* size--  */
       if (dump_file)
        fprintf (dump_file, "trying SIMPLE_POST_DEC\n");
-      return attempt_change (gen_rtx_POST_DEC (Pmode, inc_reg), inc_reg);
+      return attempt_change (gen_rtx_POST_DEC (reg_mode, inc_reg), inc_reg);
       break;
       
     case DISP_PRE:           /* ++con   */
       if (dump_file)
        fprintf (dump_file, "trying DISP_PRE\n");
-      return attempt_change (gen_rtx_PRE_MODIFY (Pmode, 
+      return attempt_change (gen_rtx_PRE_MODIFY (reg_mode,
                                                 inc_reg,
-                                                gen_rtx_PLUS (Pmode,
+                                                gen_rtx_PLUS (reg_mode,
                                                               inc_reg,
                                                               inc_insn.reg1)),
                             inc_reg);
@@ -740,9 +704,9 @@ try_merge (void)
     case DISP_POST:          /* con++   */
       if (dump_file)
        fprintf (dump_file, "trying POST_DISP\n");
-      return attempt_change (gen_rtx_POST_MODIFY (Pmode,
+      return attempt_change (gen_rtx_POST_MODIFY (reg_mode,
                                                  inc_reg,
-                                                 gen_rtx_PLUS (Pmode,
+                                                 gen_rtx_PLUS (reg_mode,
                                                                inc_reg,
                                                                inc_insn.reg1)),
                             inc_reg);
@@ -751,9 +715,9 @@ try_merge (void)
     case REG_PRE:            /* ++reg   */
       if (dump_file)
        fprintf (dump_file, "trying PRE_REG\n");
-      return attempt_change (gen_rtx_PRE_MODIFY (Pmode, 
+      return attempt_change (gen_rtx_PRE_MODIFY (reg_mode,
                                                 inc_reg,
-                                                gen_rtx_PLUS (Pmode,
+                                                gen_rtx_PLUS (reg_mode,
                                                               inc_reg,
                                                               inc_insn.reg1)),
                             inc_reg);
@@ -762,9 +726,9 @@ try_merge (void)
     case REG_POST:            /* reg++   */
       if (dump_file)
        fprintf (dump_file, "trying POST_REG\n");
-      return attempt_change (gen_rtx_POST_MODIFY (Pmode, 
+      return attempt_change (gen_rtx_POST_MODIFY (reg_mode,
                                                  inc_reg,
-                                                 gen_rtx_PLUS (Pmode,
+                                                 gen_rtx_PLUS (reg_mode,
                                                                inc_reg,
                                                                inc_insn.reg1)),
                             inc_reg);
@@ -851,7 +815,7 @@ parse_add_or_inc (rtx insn, bool before_mem)
   else 
     inc_insn.form = before_mem ? FORM_PRE_ADD : FORM_POST_ADD;
 
-  if (GET_CODE (XEXP (SET_SRC (pat), 1)) == CONST_INT)
+  if (CONST_INT_P (XEXP (SET_SRC (pat), 1)))
     {
       /* Process a = b + c where c is a const.  */
       inc_insn.reg1_is_const = true;
@@ -929,7 +893,7 @@ find_address (rtx *address_of_x)
       mem_insn.reg0 = inc_insn.reg_res;
       mem_insn.reg1 = b;
       mem_insn.reg1_is_const = inc_insn.reg1_is_const;
-      if (GET_CODE (b) == CONST_INT)
+      if (CONST_INT_P (b))
        {
          /* Match with *(reg0 + reg1) where reg1 is a const. */
          HOST_WIDE_INT val = INTVAL (b);
@@ -1007,7 +971,7 @@ find_inc (bool first_try)
   rtx insn;
   basic_block bb = BASIC_BLOCK (BLOCK_NUM (mem_insn.insn));
   rtx other_insn;
-  struct df_ref **def_rec;
+  df_ref *def_rec;
 
   /* Make sure this reg appears only once in this insn.  */
   if (count_occurrences (PATTERN (mem_insn.insn), mem_insn.reg0, 1) != 1)
@@ -1053,7 +1017,7 @@ find_inc (bool first_try)
      assigned to by the mem insn.  */
   for (def_rec = DF_INSN_DEFS (mem_insn.insn); *def_rec; def_rec++)
     {
-      struct df_ref *def = *def_rec;
+      df_ref def = *def_rec;
       unsigned int regno = DF_REF_REGNO (def);
       if ((regno == REGNO (inc_insn.reg0)) 
          || (regno == REGNO (inc_insn.reg_res)))
@@ -1127,7 +1091,9 @@ find_inc (bool first_try)
                     we are going to increment the result of the add insn.
                     For this trick to be correct, the result reg of
                     the inc must be a valid addressing reg.  */
-                 if (GET_MODE (inc_insn.reg_res) != Pmode)
+                 addr_space_t as = MEM_ADDR_SPACE (*mem_insn.mem_loc);
+                 if (GET_MODE (inc_insn.reg_res)
+                     != targetm.addr_space.address_mode (as))
                    {
                      if (dump_file)
                        fprintf (dump_file, "base reg mode failure.\n");
@@ -1176,7 +1142,9 @@ find_inc (bool first_try)
        {
          /* For this trick to be correct, the result reg of the inc
             must be a valid addressing reg.  */
-         if (GET_MODE (inc_insn.reg_res) != Pmode)
+         addr_space_t as = MEM_ADDR_SPACE (*mem_insn.mem_loc);
+         if (GET_MODE (inc_insn.reg_res)
+             != targetm.addr_space.address_mode (as))
            {
              if (dump_file)
                fprintf (dump_file, "base reg mode failure.\n");
@@ -1317,7 +1285,7 @@ find_mem (rtx *address_of_x)
       mem_insn.mem_loc = address_of_x;
       mem_insn.reg0 = XEXP (XEXP (x, 0), 0);
       mem_insn.reg1 = reg1;
-      if (GET_CODE (reg1) == CONST_INT)
+      if (CONST_INT_P (reg1))
        {
          mem_insn.reg1_is_const = true;
          /* Match with *(reg0 + c) where c is a const. */
@@ -1379,7 +1347,7 @@ merge_in_block (int max_reg, basic_block bb)
       unsigned int uid = INSN_UID (insn);
       bool insn_is_add_or_inc = true;
 
-      if (!INSN_P (insn))
+      if (!NONDEBUG_INSN_P (insn))
        continue;       
 
       /* This continue is deliberate.  We do not want the uses of the
@@ -1452,14 +1420,14 @@ merge_in_block (int max_reg, basic_block bb)
       
       /* If the inc insn was merged with a mem, the inc insn is gone
         and there is noting to update.  */
-      if (DF_INSN_UID_GET(uid))
+      if (DF_INSN_UID_GET (uid))
        {
-         struct df_ref **def_rec;
-         struct df_ref **use_rec;
+         df_ref *def_rec;
+         df_ref *use_rec;
          /* Need to update next use.  */
          for (def_rec = DF_INSN_UID_DEFS (uid); *def_rec; def_rec++)
            {
-             struct df_ref *def = *def_rec;
+             df_ref def = *def_rec;
              reg_next_use[DF_REF_REGNO (def)] = NULL;
              reg_next_inc_use[DF_REF_REGNO (def)] = NULL;
              reg_next_def[DF_REF_REGNO (def)] = insn;
@@ -1467,7 +1435,7 @@ merge_in_block (int max_reg, basic_block bb)
          
          for (use_rec = DF_INSN_UID_USES (uid); *use_rec; use_rec++)
            {
-             struct df_ref *use = *use_rec;
+             df_ref use = *use_rec;
              reg_next_use[DF_REF_REGNO (use)] = insn;
              if (insn_is_add_or_inc)
                reg_next_inc_use[DF_REF_REGNO (use)] = insn;
@@ -1544,7 +1512,7 @@ struct rtl_opt_pass pass_inc_dec =
 {
  {
   RTL_PASS,
-  "auto-inc-dec",                       /* name */
+  "auto_inc_dec",                       /* name */
   gate_auto_inc_dec,                    /* gate */
   rest_of_handle_auto_inc_dec,          /* execute */
   NULL,                                 /* sub */
@@ -1559,4 +1527,3 @@ struct rtl_opt_pass pass_inc_dec =
   TODO_df_finish,                       /* todo_flags_finish */
  }
 };
-