OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / gcse.c
index b7b08f2..56c26a4 100644 (file)
@@ -159,6 +159,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "output.h"
 #include "function.h"
 #include "expr.h" 
+#include "except.h"
 #include "ggc.h"
 #include "params.h"
 
@@ -696,6 +697,7 @@ static void delete_store            PARAMS ((struct ls_expr *,
                                                 basic_block));
 static void free_store_memory          PARAMS ((void));
 static void store_motion               PARAMS ((void));
+static void free_insn_expr_list_list   PARAMS ((rtx *));
 static void clear_modify_mem_tables    PARAMS ((void));
 static void free_modify_mem_tables     PARAMS ((void));
 \f
@@ -2189,6 +2191,10 @@ hash_scan_set (pat, insn, set_p)
          && regno >= FIRST_PSEUDO_REGISTER
          /* Don't GCSE something if we can't do a reg/reg copy.  */
          && can_copy_p [GET_MODE (dest)]
+         /* GCSE commonly inserts instruction after the insn.  We can't
+            do that easily for EH_REGION notes so disable GCSE on these
+            for now.  */
+         && !find_reg_note (insn, REG_EH_REGION, NULL_RTX)
          /* Is SET_SRC something we want to gcse?  */
          && want_to_gcse_p (src)
          /* Don't CSE a nop.  */
@@ -2382,6 +2388,7 @@ canon_list_insert (dest, unused1, v_insn)
      void * v_insn;
 {
   rtx dest_addr, insn;
+  int bb;
 
   while (GET_CODE (dest) == SUBREG
       || GET_CODE (dest) == ZERO_EXTRACT
@@ -2399,12 +2406,13 @@ canon_list_insert (dest, unused1, v_insn)
   dest_addr = get_addr (XEXP (dest, 0));
   dest_addr = canon_rtx (dest_addr);
   insn = (rtx) v_insn;  
+  bb = BLOCK_NUM (insn);
 
-  canon_modify_mem_list[BLOCK_NUM (insn)] = 
-    alloc_INSN_LIST (dest_addr, canon_modify_mem_list[BLOCK_NUM (insn)]);
-  canon_modify_mem_list[BLOCK_NUM (insn)] = 
-    alloc_INSN_LIST (dest, canon_modify_mem_list[BLOCK_NUM (insn)]);
-  bitmap_set_bit (canon_modify_mem_list_set, BLOCK_NUM (insn));
+  canon_modify_mem_list[bb] = 
+    alloc_EXPR_LIST (VOIDmode, dest_addr, canon_modify_mem_list[bb]);
+  canon_modify_mem_list[bb] = 
+    alloc_EXPR_LIST (VOIDmode, dest, canon_modify_mem_list[bb]);
+  bitmap_set_bit (canon_modify_mem_list_set, bb);
 }
 
 /* Record memory modification information for INSN.  We do not actually care
@@ -2415,23 +2423,24 @@ static void
 record_last_mem_set_info (insn)
      rtx insn;
 {
+  int bb = BLOCK_NUM (insn);
+
   /* load_killed_in_block_p will handle the case of calls clobbering
      everything.  */
-  modify_mem_list[BLOCK_NUM (insn)] = 
-    alloc_INSN_LIST (insn, modify_mem_list[BLOCK_NUM (insn)]);
-  bitmap_set_bit (modify_mem_list_set, BLOCK_NUM (insn));
+  modify_mem_list[bb] = alloc_INSN_LIST (insn, modify_mem_list[bb]);
+  bitmap_set_bit (modify_mem_list_set, bb);
 
   if (GET_CODE (insn) == CALL_INSN)
     {
       /* Note that traversals of this loop (other than for free-ing)
         will break after encountering a CALL_INSN.  So, there's no
         need to insert a pair of items, as canon_list_insert does.  */
-      canon_modify_mem_list[BLOCK_NUM (insn)] = 
-        alloc_INSN_LIST (insn, canon_modify_mem_list[BLOCK_NUM (insn)]);
-      bitmap_set_bit (canon_modify_mem_list_set, BLOCK_NUM (insn));
+      canon_modify_mem_list[bb] = 
+        alloc_INSN_LIST (insn, canon_modify_mem_list[bb]);
+      bitmap_set_bit (canon_modify_mem_list_set, bb);
     }
   else
-    note_stores (PATTERN (insn), canon_list_insert, (void*) insn );
+    note_stores (PATTERN (insn), canon_list_insert, (void*) insn);
 }
 
 /* Called from compute_hash_table via note_stores to handle one
@@ -2707,6 +2716,27 @@ next_set (regno, expr)
   return expr;
 }
 
+/* Like free_INSN_LIST_list or free_EXPR_LIST_list, except that the node
+   types may be mixed.  */
+
+static void
+free_insn_expr_list_list (listp)
+     rtx *listp;
+{
+  rtx list, next;
+
+  for (list = *listp; list ; list = next)
+    {
+      next = XEXP (list, 1);
+      if (GET_CODE (list) == EXPR_LIST)
+       free_EXPR_LIST_node (list);
+      else
+       free_INSN_LIST_node (list);
+    }
+
+  *listp = NULL;
+}
+
 /* Clear canon_modify_mem_list and modify_mem_list tables.  */
 static void
 clear_modify_mem_tables ()
@@ -2714,14 +2744,13 @@ clear_modify_mem_tables ()
   int i;
 
   EXECUTE_IF_SET_IN_BITMAP
-    (canon_modify_mem_list_set, 0, i,
-     free_INSN_LIST_list (modify_mem_list + i));
-  bitmap_clear (canon_modify_mem_list_set);
+    (modify_mem_list_set, 0, i, free_INSN_LIST_list (modify_mem_list + i));
+  bitmap_clear (modify_mem_list_set);
 
   EXECUTE_IF_SET_IN_BITMAP
     (canon_modify_mem_list_set, 0, i,
-     free_INSN_LIST_list (canon_modify_mem_list + i));
-  bitmap_clear (modify_mem_list_set);
+     free_insn_expr_list_list (canon_modify_mem_list + i));
+  bitmap_clear (canon_modify_mem_list_set);
 }
 
 /* Release memory used by modify_mem_list_set and canon_modify_mem_list_set.  */
@@ -3018,8 +3047,8 @@ compute_rd ()
       for (bb = 0; bb < n_basic_blocks; bb++)
        {
          sbitmap_union_of_preds (reaching_defs[bb], rd_out, bb);
-         changed |= sbitmap_union_of_diff (rd_out[bb], rd_gen[bb],
-                                           reaching_defs[bb], rd_kill[bb]);
+         changed |= sbitmap_union_of_diff_cg (rd_out[bb], rd_gen[bb],
+                                              reaching_defs[bb], rd_kill[bb]);
        }
       passes++;
     }
@@ -4609,13 +4638,23 @@ insert_insn_end_bb (expr, bb, pre)
   pat = process_insert_insn (expr);
 
   /* If the last insn is a jump, insert EXPR in front [taking care to
-     handle cc0, etc. properly].  */
+     handle cc0, etc. properly].  Similary we need to care trapping
+     instructions in presence of non-call exceptions.  */
 
-  if (GET_CODE (insn) == JUMP_INSN)
+  if (GET_CODE (insn) == JUMP_INSN
+      || (GET_CODE (insn) == INSN
+         && (bb->succ->succ_next || (bb->succ->flags & EDGE_ABNORMAL))))
     {
 #ifdef HAVE_cc0
       rtx note;
 #endif
+      /* It should always be the case that we can put these instructions
+        anywhere in the basic block with performing PRE optimizations.
+        Check this.  */
+      if (GET_CODE (insn) == INSN && pre
+         && !TEST_BIT (antloc[bb->index], expr->bitmap_index)
+          && !TEST_BIT (transp[bb->index], expr->bitmap_index))
+       abort ();
 
       /* If this is a jump table, then we can't insert stuff here.  Since
         we know the previous real insn must be the tablejump, we insert
@@ -4645,7 +4684,8 @@ insert_insn_end_bb (expr, bb, pre)
 
   /* Likewise if the last insn is a call, as will happen in the presence
      of exception handling.  */
-  else if (GET_CODE (insn) == CALL_INSN)
+  else if (GET_CODE (insn) == CALL_INSN
+          && (bb->succ->succ_next || (bb->succ->flags & EDGE_ABNORMAL)))
     {
       /* Keeping in mind SMALL_REGISTER_CLASSES and parameters in registers,
         we search backward and place the instructions before the first
@@ -5330,8 +5370,8 @@ delete_null_pointer_checks_1 (block_reg, nonnull_avin,
        {
          rtx new_jump;
 
-         new_jump = emit_jump_insn_before (gen_jump (JUMP_LABEL (last_insn)),
-                                           last_insn);
+         new_jump = emit_jump_insn_after (gen_jump (JUMP_LABEL (last_insn)),
+                                          last_insn);
          JUMP_LABEL (new_jump) = JUMP_LABEL (last_insn);
          LABEL_NUSES (JUMP_LABEL (new_jump))++;
          emit_barrier_after (new_jump);
@@ -5543,8 +5583,8 @@ compute_code_hoist_vbeinout ()
         the convergence.  */
       for (bb = n_basic_blocks - 1; bb >= 0; bb--)
        {
-         changed |= sbitmap_a_or_b_and_c (hoist_vbein[bb], antloc[bb],
-                                          hoist_vbeout[bb], transp[bb]);
+         changed |= sbitmap_a_or_b_and_c_cg (hoist_vbein[bb], antloc[bb],
+                                             hoist_vbeout[bb], transp[bb]);
          if (bb != n_basic_blocks - 1)
            sbitmap_intersection_of_succs (hoist_vbeout[bb], hoist_vbein, bb);
        }
@@ -6512,21 +6552,7 @@ store_killed_in_insn (x, insn)
     {
       /* A normal or pure call might read from pattern,
         but a const call will not.  */
-      if (CONST_OR_PURE_CALL_P (insn))
-       {
-         rtx link;
-
-         for (link = CALL_INSN_FUNCTION_USAGE (insn);
-              link;
-              link = XEXP (link, 1))
-           if (GET_CODE (XEXP (link, 0)) == USE
-               && GET_CODE (XEXP (XEXP (link, 0), 0)) == MEM
-               && GET_CODE (XEXP (XEXP (XEXP (link, 0), 0), 0)) == SCRATCH)
-             return 1;
-         return 0;
-       }
-      else
-       return 1;
+      return ! CONST_OR_PURE_CALL_P (insn) || pure_call_p (insn);
     }
   
   if (GET_CODE (PATTERN (insn)) == SET)