OSDN Git Service

* unwind-generic.h: Fix comment typos.
[pf3gnuchains/gcc-fork.git] / gcc / dse.c
index a5244e1..2b86018 100644 (file)
--- a/gcc/dse.c
+++ b/gcc/dse.c
@@ -286,8 +286,26 @@ struct insn_info
 
   /* This field is only used for the processing of const functions.
      These functions cannot read memory, but they can read the stack
-     because that is where they may get their parms.  It is set to
-     true if the insn may contain a stack pointer based store.  */
+     because that is where they may get their parms.  We need to be
+     this conservative because, like the store motion pass, we don't
+     consider CALL_INSN_FUNCTION_USAGE when processing call insns.
+     Moreover, we need to distinguish two cases:
+     1. Before reload (register elimination), the stores related to
+       outgoing arguments are stack pointer based and thus deemed
+       of non-constant base in this pass.  This requires special
+       handling but also means that the frame pointer based stores
+       need not be killed upon encountering a const function call.
+     2. After reload, the stores related to outgoing arguments can be
+       either stack pointer or hard frame pointer based.  This means
+       that we have no other choice than also killing all the frame
+       pointer based stores upon encountering a const function call.
+     This field is set after reload for const function calls.  Having
+     this set is less severe than a wild read, it just means that all
+     the frame related stores are killed rather than all the stores.  */
+  bool frame_read;
+
+  /* This field is only used for the processing of const functions.
+     It is set if the insn may contain a stack pointer based store.  */
   bool stack_pointer_based;
 
   /* This is true if any of the sets within the store contains a
@@ -1429,7 +1447,7 @@ find_shift_sequence (rtx read_reg,
        continue;
 
       new_mode = smallest_mode_for_size (access_size * BITS_PER_UNIT,
-                                        GET_MODE_CLASS (read_mode));
+                                        MODE_INT);
       new_reg = gen_reg_rtx (new_mode);
 
       start_sequence ();
@@ -1455,9 +1473,8 @@ find_shift_sequence (rtx read_reg,
         of the arguments and could be precomputed.  It may
         not be worth doing so.  We could precompute if
         worthwhile or at least cache the results.  The result
-        technically depends on SHIFT, ACCESS_SIZE, and
-        GET_MODE_CLASS (READ_MODE).  But in practice the
-        answer will depend only on ACCESS_SIZE.  */
+        technically depends on both SHIFT and ACCESS_SIZE,
+        but in practice the answer will depend only on ACCESS_SIZE.  */
 
       if (cost > COSTS_N_INSNS (1))
        continue;
@@ -1539,7 +1556,8 @@ replace_read (store_info_t store_info, insn_info_t store_insn,
   if (!dbg_cnt (dse))
     return false;
 
-  if (GET_MODE_CLASS (read_mode) != GET_MODE_CLASS (store_mode))
+  if (GET_MODE_CLASS (read_mode) != MODE_INT
+      || GET_MODE_CLASS (store_mode) != MODE_INT)
     return false;
 
   /* To get here the read is within the boundaries of the write so
@@ -1562,7 +1580,7 @@ replace_read (store_info_t store_info, insn_info_t store_insn,
      call to get rid of the read.  */
   if (shift)
     {
-      if (access_size > UNITS_PER_WORD || FLOAT_MODE_P (store_mode))
+      if (access_size > UNITS_PER_WORD)
        return false;
 
       shift_seq = find_shift_sequence (read_reg, access_size, store_info,
@@ -1967,10 +1985,36 @@ scan_insn (bb_info_t bb_info, rtx insn)
          if (dump_file)
            fprintf (dump_file, "const call %d\n", INSN_UID (insn));
 
+         /* See the head comment of the frame_read field.  */
+         if (reload_completed)
+           insn_info->frame_read = true;
+
+         /* Loop over the active stores and remove those which are
+            killed by the const function call.  */
          while (i_ptr)
            {
-             /* Remove the stack pointer based stores.  */
+             bool remove_store = false;
+
+             /* The stack pointer based stores are always killed.  */
              if (i_ptr->stack_pointer_based)
+               remove_store = true;
+
+             /* If the frame is read, the frame related stores are killed.  */
+             else if (insn_info->frame_read)
+               {
+                 store_info_t store_info = i_ptr->store_rec;
+
+                 /* Skip the clobbers.  */
+                 while (!store_info->is_set)
+                   store_info = store_info->next;
+
+                 if (store_info->group_id >= 0
+                     && VEC_index (group_info_t, rtx_group_vec,
+                                   store_info->group_id)->frame_related)
+                   remove_store = true;
+               }
+
+             if (remove_store)
                {
                  if (dump_file)
                    dump_insn_info ("removing from active", i_ptr);
@@ -1982,6 +2026,7 @@ scan_insn (bb_info_t bb_info, rtx insn)
                }
              else
                last = i_ptr;
+
              i_ptr = i_ptr->next_local_store;
            }
        }
@@ -2491,6 +2536,18 @@ scan_reads_nospill (insn_info_t insn_info, bitmap gen, bitmap kill)
   int i;
   group_info_t group;
 
+  /* If this insn reads the frame, kill all the frame related stores.  */
+  if (insn_info->frame_read)
+    {
+      for (i = 0; VEC_iterate (group_info_t, rtx_group_vec, i, group); i++)
+       if (group->process_globally && group->frame_related)
+         {
+           if (kill)
+             bitmap_ior_into (kill, group->group_kill);
+           bitmap_and_compl_into (gen, group->group_kill); 
+         }
+    }
+
   while (read_info)
     {
       for (i = 0; VEC_iterate (group_info_t, rtx_group_vec, i, group); i++)