cse.c (dump_class): New function.
authorMark Mitchell <mark@markmitchell.com>
Mon, 22 Feb 1999 13:34:33 +0000 (13:34 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Mon, 22 Feb 1999 13:34:33 +0000 (13:34 +0000)
* cse.c (dump_class): New function.
(invalidate_memory): Fix typo in comment.
* function.c (temp_slot): Add an alias set field.
(assign_stack_temp): Only reuse slots if they will have the
same alias set as before.
(combine_temp_slots): Don't combine if -fstrict-aliasing;
that's unsafe.
* rtl.c (copy_rtx): Copy all the flags (in particular,
MEM_SCALAR_P).

From-SVN: r25372

gcc/ChangeLog
gcc/cse.c
gcc/function.c
gcc/rtl.c

index 1a90b5bfc1ac917e0622471d71a205297cf242e5..321077fb4cb324f55d89426f03fb62b4f6084d17 100644 (file)
@@ -1,3 +1,15 @@
+Mon Feb 22 13:33:47 1999  Mark Mitchell  <mark@markmitchell.com>
+
+       * cse.c (dump_class): New function.
+       (invalidate_memory): Fix typo in comment.
+       * function.c (temp_slot): Add an alias set field.  
+       (assign_stack_temp): Only reuse slots if they will have the
+       same alias set as before.
+       (combine_temp_slots): Don't combine if -fstrict-aliasing;
+       that's unsafe.
+       * rtl.c (copy_rtx): Copy all the flags (in particular,
+       MEM_SCALAR_P).
+
 Mon Feb 22 14:13:23 1999  Vladimir N. Makarov  <vmakarov@cygnus.com>
 
        * configure.in (i[34567]86-*-linux-gnu*,
index 4e52bb46b0ece26dfd2bbb4dc4c5003f8cc0c117..7fa8116a6f63b3ff449a123a83fa0375e562962b 100644 (file)
--- a/gcc/cse.c
+++ b/gcc/cse.c
@@ -663,9 +663,29 @@ static void cse_check_loop_start PROTO((rtx, rtx));
 static void cse_set_around_loop        PROTO((rtx, rtx, rtx));
 static rtx cse_basic_block     PROTO((rtx, rtx, struct branch_path *, int));
 static void count_reg_usage    PROTO((rtx, int *, rtx, int));
+static void dump_class          PROTO((struct table_elt*));
 
 extern int rtx_equal_function_value_matters;
 \f
+/* Dump the expressions in the equivalence class indicated by CLASSP.
+   This function is used only for debugging.  */
+void
+dump_class (classp)
+     struct table_elt *classp;
+{
+  struct table_elt *elt;
+
+  fprintf (stderr, "Equivalence chain for ");
+  print_rtl (stderr, classp->exp);
+  fprintf (stderr, ": \n");
+  
+  for (elt = classp->first_same_value; elt; elt = elt->next_same_value)
+    {
+      print_rtl (stderr, elt->exp);
+      fprintf (stderr, "\n");
+    }
+}
+
 /* Return an estimate of the cost of computing rtx X.
    One use is in cse, to decide which expression to keep in the hash table.
    Another is in rtl generation, to pick the cheapest way to multiply.
@@ -7821,7 +7841,7 @@ cse_insn (insn, libcall_insn)
   prev_insn = insn;
 }
 \f
-/* Remove from the ahsh table all expressions that reference memory.  */
+/* Remove from the hash table all expressions that reference memory.  */
 static void
 invalidate_memory ()
 {
index 05189d9c1b9b2cd603e4122e4c0bbcaa24f58bb1..03d1e75c47a28afd7a421a92d3248f34ad119018 100644 (file)
@@ -394,6 +394,17 @@ struct temp_slot
   int align;
   /* The size, in units, of the slot.  */
   HOST_WIDE_INT size;
+  /* The alias set for the slot.  If the alias set is zero, we don't
+     know anything about the alias set of the slot.  We must only
+     reuse a slot if it is assigned an object of the same alias set.
+     Otherwise, the rest of the compiler may assume that the new use
+     of the slot cannot alias the old use of the slot, which is
+     false.  If the slot has alias set zero, then we can't reuse the
+     slot at all, since we have no idea what alias set may have been
+     imposed on the memory.  For example, if the stack slot is the
+     call frame for an inline functioned, we have no idea what alias
+     sets will be assigned to various pieces of the call frame.  */
+  int alias_set;
   /* The value of `sequence_rtl_expr' when this temporary is allocated.  */
   tree rtl_expr;
   /* Non-zero if this temporary is currently in use.  */
@@ -875,7 +886,9 @@ assign_outer_stack_local (mode, size, align, function)
    with this flag.  KEEP is 2 if we allocate a longer term temporary,
    whose lifetime is controlled by CLEANUP_POINT_EXPRs.  KEEP is 3
    if we are to allocate something at an inner level to be treated as
-   a variable in the block (e.g., a SAVE_EXPR).  */
+   a variable in the block (e.g., a SAVE_EXPR).  
+
+   TYPE is the type that will be used for the stack slot.  */
 
 static rtx
 assign_stack_temp_for_type (mode, size, keep, type)
@@ -885,6 +898,7 @@ assign_stack_temp_for_type (mode, size, keep, type)
      tree type;
 {
   int align;
+  int alias_set;
   struct temp_slot *p, *best_p = 0;
 
   /* If SIZE is -1 it means that somebody tried to allocate a temporary
@@ -892,6 +906,14 @@ assign_stack_temp_for_type (mode, size, keep, type)
   if (size == -1)
     abort ();
 
+  /* If we know the alias set for the memory that will be used, use
+     it.  If there's no TYPE, then we don't know anything about the
+     alias set for the memory.  */
+  if (type)
+    alias_set = get_alias_set (type);
+  else 
+    alias_set = 0;
+
   align = GET_MODE_ALIGNMENT (mode);
   if (mode == BLKmode)
     align = BIGGEST_ALIGNMENT;
@@ -907,6 +929,8 @@ assign_stack_temp_for_type (mode, size, keep, type)
   for (p = temp_slots; p; p = p->next)
     if (p->align >= align && p->size >= size && GET_MODE (p->slot) == mode
        && ! p->in_use
+       && (!flag_strict_aliasing
+           || (alias_set && p->alias_set == alias_set))
        && (best_p == 0 || best_p->size > p->size
            || (best_p->size == p->size && best_p->align > p->align)))
       {
@@ -924,7 +948,11 @@ assign_stack_temp_for_type (mode, size, keep, type)
       /* If there are enough aligned bytes left over, make them into a new
         temp_slot so that the extra bytes don't get wasted.  Do this only
         for BLKmode slots, so that we can be sure of the alignment.  */
-      if (GET_MODE (best_p->slot) == BLKmode)
+      if (GET_MODE (best_p->slot) == BLKmode
+         /* We can't split slots if -fstrict-aliasing because the
+            information about the alias set for the new slot will be
+            lost.  */
+         && !flag_strict_aliasing)
        {
          int alignment = best_p->align / BITS_PER_UNIT;
          HOST_WIDE_INT rounded_size = CEIL_ROUND (size, alignment);
@@ -978,6 +1006,7 @@ assign_stack_temp_for_type (mode, size, keep, type)
       p->slot = assign_stack_local (mode, size, align);
 
       p->align = align;
+      p->alias_set = alias_set;
 
       /* The following slot size computation is necessary because we don't
         know the actual size of the temporary slot until assign_stack_local
@@ -1103,6 +1132,11 @@ combine_temp_slots ()
   struct temp_slot *prev_p, *prev_q;
   int num_slots;
 
+  /* We can't combine slots, because the information about which slot
+     is in which alias set will be lost.  */
+  if (flag_strict_aliasing)
+    return;
+
   /* If there are a lot of temp slots, don't do anything unless 
      high levels of optimizaton.  */
   if (! flag_expensive_optimizations)
index 33cf0cb9132f618a6613078b671315de20e201c6..b4d870d8cc37ae626c37002a1d00bef9161f1c5c 100644 (file)
--- a/gcc/rtl.c
+++ b/gcc/rtl.c
@@ -319,11 +319,24 @@ copy_rtx (orig)
     }
 
   copy = rtx_alloc (code);
-  PUT_MODE (copy, GET_MODE (orig));
-  copy->in_struct = orig->in_struct;
-  copy->volatil = orig->volatil;
-  copy->unchanging = orig->unchanging;
-  copy->integrated = orig->integrated;
+
+  /* Copy the various flags, and other information.  We assume that
+     all fields need copying, and then clear the fields that should
+     not be copied.  That is the sensible default behavior, and forces
+     us to explicitly document why we are *not* copying a flag.  */
+  bcopy (orig, copy, sizeof (struct rtx_def) - sizeof (rtunion));
+
+  /* We do not copy the USED flag, which is used as a mark bit during
+     walks over the RTL.  */
+  copy->used = 0;
+
+  /* We do not copy JUMP, CALL, or FRAME_RELATED for INSNs.  */
+  if (GET_RTX_CLASS (code) == 'i')
+    {
+      copy->jump = 0;
+      copy->call = 0;
+      copy->frame_related = 0;
+    }
   
   format_ptr = GET_RTX_FORMAT (GET_CODE (copy));