OSDN Git Service

* var-tracking.c (vt_find_locations): Set the in_pending bitmap at
[pf3gnuchains/gcc-fork.git] / gcc / var-tracking.c
index 5293abf..6e95e50 100644 (file)
@@ -112,7 +112,7 @@ enum micro_operation_type
   MO_SET,      /* Set location.  */
   MO_CLOBBER,  /* Clobber location.  */
   MO_CALL,     /* Call insn.  */
-  MO_ADJUST    /* Adjust stack pointer. */
+  MO_ADJUST    /* Adjust stack pointer.  */
 };
 
 /* Where shall the note be emitted?  BEFORE or AFTER the instruction.  */
@@ -233,6 +233,9 @@ typedef struct variable_def
   /* The declaration of the variable.  */
   tree decl;
 
+  /* Reference count.  */
+  int refcount;
+
   /* Number of variable parts.  */
   int n_var_parts;
 
@@ -264,6 +267,9 @@ static bool emit_notes;
 /* Fake variable for stack pointer.  */
 tree frame_base_decl;
 
+/* Stack adjust caused by function prologue.  */
+static HOST_WIDE_INT frame_stack_adjust;
+
 /* Local function prototypes.  */
 static void stack_adjust_offset_pre_post (rtx, HOST_WIDE_INT *,
                                          HOST_WIDE_INT *);
@@ -285,6 +291,7 @@ static void attrs_list_copy (attrs *, attrs);
 static void attrs_list_union (attrs *, attrs);
 
 static void vars_clear (htab_t);
+static variable unshare_variable (dataflow_set *set, variable var);
 static int vars_copy_1 (void **, void *);
 static void vars_copy (htab_t, htab_t);
 static void var_reg_delete_and_set (dataflow_set *, rtx);
@@ -300,7 +307,7 @@ static int variable_union_info_cmp_pos (const void *, const void *);
 static int variable_union (void **, void *);
 static void dataflow_set_union (dataflow_set *, dataflow_set *);
 static bool variable_part_different_p (variable_part *, variable_part *);
-static bool variable_different_p (variable, variable);
+static bool variable_different_p (variable, variable, bool);
 static int dataflow_set_different_1 (void **, void *);
 static int dataflow_set_different_2 (void **, void *);
 static bool dataflow_set_different (dataflow_set *, dataflow_set *);
@@ -366,7 +373,7 @@ stack_adjust_offset_pre_post (rtx pattern, HOST_WIDE_INT *pre,
       else
        *post -= INTVAL (XEXP (src, 1));
     }
-  else if (GET_CODE (dest) == MEM)
+  else if (MEM_P (dest))
     {
       /* (set (mem (pre_dec (reg sp))) (foo)) */
       src = XEXP (dest, 0);
@@ -470,7 +477,7 @@ bb_stack_adjust_offset (basic_block bb)
        offset += VTI (bb)->mos[i].u.adjust;
       else if (VTI (bb)->mos[i].type != MO_CALL)
        {
-         if (GET_CODE (VTI (bb)->mos[i].u.loc) == MEM)
+         if (MEM_P (VTI (bb)->mos[i].u.loc))
            {
              VTI (bb)->mos[i].u.loc
                = adjust_stack_reference (VTI (bb)->mos[i].u.loc, -offset);
@@ -480,7 +487,7 @@ bb_stack_adjust_offset (basic_block bb)
   VTI (bb)->out.stack_adjust = offset;
 }
 
-/* Compute stack adjustment caused by function prolog.  */
+/* Compute stack adjustment caused by function prologue.  */
 
 static HOST_WIDE_INT
 prologue_stack_adjust (void)
@@ -496,7 +503,7 @@ prologue_stack_adjust (void)
   end = NEXT_INSN (BB_END (bb));
   for (insn = BB_HEAD (bb); insn != end; insn = NEXT_INSN (insn))
     {
-      if (GET_CODE (insn) == NOTE
+      if (NOTE_P (insn)
          && NOTE_LINE_NUMBER (insn) == NOTE_INSN_PROLOGUE_END)
        break;
 
@@ -524,7 +531,7 @@ vt_stack_adjustments (void)
 
   /* Initialize entry block.  */
   VTI (ENTRY_BLOCK_PTR)->visited = true;
-  VTI (ENTRY_BLOCK_PTR)->out.stack_adjust = 0;
+  VTI (ENTRY_BLOCK_PTR)->out.stack_adjust = frame_stack_adjust;
 
   /* Allocate stack for back-tracking up CFG.  */
   stack = xmalloc ((n_basic_blocks + 1) * sizeof (edge));
@@ -586,6 +593,9 @@ adjust_stack_reference (rtx mem, HOST_WIDE_INT adjustment)
   rtx adjusted_mem;
   rtx tmp;
 
+  if (adjustment == 0)
+    return mem;
+
   adjusted_mem = copy_rtx (mem);
   XEXP (adjusted_mem, 0) = replace_rtx (XEXP (adjusted_mem, 0),
                                        stack_pointer_rtx,
@@ -629,6 +639,15 @@ variable_htab_free (void *elem)
   variable var = (variable) elem;
   location_chain node, next;
 
+#ifdef ENABLE_CHECKING
+  if (var->refcount <= 0)
+    abort ();
+#endif
+
+  var->refcount--;
+  if (var->refcount > 0)
+    return;
+
   for (i = 0; i < var->n_var_parts; i++)
     {
       for (node = var->var_part[i].loc_chain; node; node = next)
@@ -732,31 +751,29 @@ vars_clear (htab_t vars)
   htab_empty (vars);
 }
 
-/* Copy one variable from *SLOT to hash table DATA.  */
+/* Return a copy of a variable VAR and insert it to dataflow set SET.  */
 
-static int
-vars_copy_1 (void **slot, void *data)
+static variable
+unshare_variable (dataflow_set *set, variable var)
 {
-  htab_t dst = (htab_t) data;
-  variable src, *dstp, var;
+  void **slot;
+  variable new_var;
   int i;
 
-  src = *(variable *) slot;
-  dstp = (variable *) htab_find_slot_with_hash (dst, src->decl,
-                                               VARIABLE_HASH_VAL (src->decl),
-                                               INSERT);
-  var = pool_alloc (var_pool);
-  var->decl = src->decl;
-  var->n_var_parts = src->n_var_parts;
-  *dstp = (void *) var;
+  new_var = pool_alloc (var_pool);
+  new_var->decl = var->decl;
+  new_var->refcount = 1;
+  var->refcount--;
+  new_var->n_var_parts = var->n_var_parts;
 
   for (i = 0; i < var->n_var_parts; i++)
     {
-      location_chain last, node;
+      location_chain node;
+      location_chain *nextp;
 
-      var->var_part[i].offset = src->var_part[i].offset;
-      last = NULL;
-      for (node = src->var_part[i].loc_chain; node; node = node->next)
+      new_var->var_part[i].offset = var->var_part[i].offset;
+      nextp = &new_var->var_part[i].loc_chain;
+      for (node = var->var_part[i].loc_chain; node; node = node->next)
        {
          location_chain new_lc;
 
@@ -764,21 +781,42 @@ vars_copy_1 (void **slot, void *data)
          new_lc->next = NULL;
          new_lc->loc = node->loc;
 
-         if (last)
-           last->next = new_lc;
-         else
-           var->var_part[i].loc_chain = new_lc;
-         last = new_lc;
+         *nextp = new_lc;
+         nextp = &new_lc->next;
        }
 
       /* We are at the basic block boundary when copying variable description
         so set the CUR_LOC to be the first element of the chain.  */
-      if (var->var_part[i].loc_chain)
-       var->var_part[i].cur_loc = var->var_part[i].loc_chain->loc;
+      if (new_var->var_part[i].loc_chain)
+       new_var->var_part[i].cur_loc = new_var->var_part[i].loc_chain->loc;
       else
-       var->var_part[i].cur_loc = NULL;
+       new_var->var_part[i].cur_loc = NULL;
     }
 
+  slot = htab_find_slot_with_hash (set->vars, new_var->decl,
+                                  VARIABLE_HASH_VAL (new_var->decl),
+                                  INSERT);
+  *slot = new_var;
+  return new_var;
+}
+
+/* Add a variable from *SLOT to hash table DATA and increase its reference
+   count.  */
+
+static int
+vars_copy_1 (void **slot, void *data)
+{
+  htab_t dst = (htab_t) data;
+  variable src, *dstp;
+
+  src = *(variable *) slot;
+  src->refcount++;
+
+  dstp = (variable *) htab_find_slot_with_hash (dst, src->decl,
+                                               VARIABLE_HASH_VAL (src->decl),
+                                               INSERT);
+  *dstp = src;
+
   /* Continue traversing the hash table.  */
   return 1;
 }
@@ -798,33 +836,29 @@ vars_copy (htab_t dst, htab_t src)
 static void
 var_reg_delete_and_set (dataflow_set *set, rtx loc)
 {
-  attrs *reg = &set->regs[REGNO (loc)];
   tree decl = REG_EXPR (loc);
   HOST_WIDE_INT offset = REG_OFFSET (loc);
-  attrs node, prev, next;
+  attrs node, next;
+  attrs *nextp;
 
-  prev = NULL;
-  for (node = *reg; node; node = next)
+  nextp = &set->regs[REGNO (loc)];
+  for (node = *nextp; node; node = next)
     {
       next = node->next;
       if (node->decl != decl || node->offset != offset)
        {
          delete_variable_part (set, node->loc, node->decl, node->offset);
-
-         if (prev)
-           prev->next = next;
-         else
-           *reg = next;
          pool_free (attrs_pool, node);
+         *nextp = next;
        }
       else
        {
          node->loc = loc;
-         prev = node;
+         nextp = &node->next;
        }
     }
-  if (*reg == NULL)
-    attrs_list_insert (reg, decl, offset, loc);
+  if (set->regs[REGNO (loc)] == NULL)
+    attrs_list_insert (&set->regs[REGNO (loc)], decl, offset, loc);
   set_variable_part (set, loc, decl, offset);
 }
 
@@ -978,9 +1012,37 @@ variable_union (void **slot, void *data)
                                                INSERT);
   if (!*dstp)
     {
-      *dstp = dst = pool_alloc (var_pool);
-      dst->decl = src->decl;
-      dst->n_var_parts = 0;
+      src->refcount++;
+
+      /* If CUR_LOC of some variable part is not the first element of
+        the location chain we are going to change it so we have to make
+        a copy of the variable.  */
+      for (k = 0; k < src->n_var_parts; k++)
+       {
+         if (src->var_part[k].loc_chain)
+           {
+#ifdef ENABLE_CHECKING
+             if (src->var_part[k].cur_loc == NULL)
+               abort ();
+#endif
+             if (src->var_part[k].cur_loc != src->var_part[k].loc_chain->loc)
+               break;
+           }
+#ifdef ENABLE_CHECKING
+         else
+           {
+             if (src->var_part[k].cur_loc != NULL)
+               abort ();
+           }
+#endif
+       }
+      if (k < src->n_var_parts)
+       unshare_variable (set, src);
+      else
+       *dstp = src;
+
+      /* Continue traversing the hash table.  */
+      return 1;
     }
   else
     dst = *dstp;
@@ -1004,10 +1066,8 @@ variable_union (void **slot, void *data)
       else
        j++;
     }
-  if (i < src->n_var_parts)
-    k += src->n_var_parts - i;
-  if (j < dst->n_var_parts)
-    k += dst->n_var_parts - j;
+  k += src->n_var_parts - i;
+  k += dst->n_var_parts - j;
 #ifdef ENABLE_CHECKING
   /* We track only variables whose size is <= MAX_VAR_PARTS bytes
      thus there are at most MAX_VAR_PARTS different offsets.  */
@@ -1015,13 +1075,16 @@ variable_union (void **slot, void *data)
     abort ();
 #endif
 
+  if (dst->refcount > 1 && dst->n_var_parts != k)
+    dst = unshare_variable (set, dst);
+
   i = src->n_var_parts - 1;
   j = dst->n_var_parts - 1;
   dst->n_var_parts = k;
 
   for (k--; k >= 0; k--)
     {
-      location_chain node;
+      location_chain node, node2;
 
       if (i >= 0 && j >= 0
          && src->var_part[i].offset == dst->var_part[j].offset)
@@ -1032,7 +1095,26 @@ variable_union (void **slot, void *data)
          int dst_l, src_l;
          int ii, jj, n;
          struct variable_union_info *vui;
-         
+
+         /* If DST is shared compare the location chains.
+            If they are different we will modify the chain in DST with
+            high probability so make a copy of DST.  */
+         if (dst->refcount > 1)
+           {
+             for (node = src->var_part[i].loc_chain,
+                  node2 = dst->var_part[j].loc_chain; node && node2;
+                  node = node->next, node2 = node2->next)
+               {
+                 if (!((REG_P (node2->loc)
+                        && REG_P (node->loc)
+                        && REGNO (node2->loc) == REGNO (node->loc))
+                       || rtx_equal_p (node2->loc, node->loc)))
+                   break;
+               }
+             if (node || node2)
+               dst = unshare_variable (set, dst);
+           }
+
          src_l = 0;
          for (node = src->var_part[i].loc_chain; node; node = node->next)
            src_l++;
@@ -1060,8 +1142,8 @@ variable_union (void **slot, void *data)
              /* Find location from NODE.  */
              for (jj = 0; jj < dst_l; jj++)
                {
-                 if ((GET_CODE (vui[jj].lc->loc) == REG
-                      && GET_CODE (node->loc) == REG
+                 if ((REG_P (vui[jj].lc->loc)
+                      && REG_P (node->loc)
                       && REGNO (vui[jj].lc->loc) == REGNO (node->loc))
                      || rtx_equal_p (vui[jj].lc->loc, node->loc))
                    {
@@ -1112,9 +1194,10 @@ variable_union (void **slot, void *data)
                && src->var_part[i].offset > dst->var_part[j].offset)
               || j < 0)
        {
-         location_chain last = NULL;
+         location_chain *nextp;
 
          /* Copy the chain from SRC.  */
+         nextp = &dst->var_part[k].loc_chain;
          for (node = src->var_part[i].loc_chain; node; node = node->next)
            {
              location_chain new_lc;
@@ -1123,11 +1206,8 @@ variable_union (void **slot, void *data)
              new_lc->next = NULL;
              new_lc->loc = node->loc;
 
-             if (last)
-               last->next = new_lc;
-             else
-               dst->var_part[k].loc_chain = new_lc;
-             last = new_lc;
+             *nextp = new_lc;
+             nextp = &new_lc->next;
            }
 
          dst->var_part[k].offset = src->var_part[i].offset;
@@ -1172,7 +1252,7 @@ variable_part_different_p (variable_part *vp1, variable_part *vp2)
     {
       for (lc2 = vp2->loc_chain; lc2; lc2 = lc2->next)
        {
-         if (GET_CODE (lc1->loc) == REG && GET_CODE (lc2->loc) == REG)
+         if (REG_P (lc1->loc) && REG_P (lc2->loc))
            {
              if (REGNO (lc1->loc) == REGNO (lc2->loc))
                break;
@@ -1186,15 +1266,19 @@ variable_part_different_p (variable_part *vp1, variable_part *vp2)
   return false;
 }
 
-/* Return true if variables VAR1 and VAR2 are different (only the first
-   location in the list of locations is checked for each offset,
-   i.e. when true is returned a note should be emitted).  */
+/* Return true if variables VAR1 and VAR2 are different.
+   If COMPARE_CURRENT_LOCATION is true compare also the cur_loc of each
+   variable part.  */
 
 static bool
-variable_different_p (variable var1, variable var2)
+variable_different_p (variable var1, variable var2,
+                     bool compare_current_location)
 {
   int i;
 
+  if (var1 == var2)
+    return false;
+
   if (var1->n_var_parts != var2->n_var_parts)
     return true;
 
@@ -1202,6 +1286,16 @@ variable_different_p (variable var1, variable var2)
     {
       if (var1->var_part[i].offset != var2->var_part[i].offset)
        return true;
+      if (compare_current_location)
+       {
+         if (!((REG_P (var1->var_part[i].cur_loc)
+                && REG_P (var2->var_part[i].cur_loc)
+                && (REGNO (var1->var_part[i].cur_loc)
+                    == REGNO (var2->var_part[i].cur_loc)))
+               || rtx_equal_p (var1->var_part[i].cur_loc,
+                               var2->var_part[i].cur_loc)))
+           return true;
+       }
       if (variable_part_different_p (&var1->var_part[i], &var2->var_part[i]))
        return true;
       if (variable_part_different_p (&var2->var_part[i], &var1->var_part[i]))
@@ -1220,21 +1314,21 @@ dataflow_set_different_1 (void **slot, void *data)
   variable var1, var2;
 
   var1 = *(variable *) slot;
-  var2 = (variable) htab_find_with_hash (htab, var1->decl,
-                                        VARIABLE_HASH_VAL (var1->decl));
+  var2 = htab_find_with_hash (htab, var1->decl,
+                             VARIABLE_HASH_VAL (var1->decl));
   if (!var2)
     {
       dataflow_set_different_value = true;
 
-      /* Stop traversing the hash table.   */
+      /* Stop traversing the hash table.  */
       return 0;
     }
 
-  if (variable_different_p (var1, var2))
+  if (variable_different_p (var1, var2, false))
     {
       dataflow_set_different_value = true;
 
-      /* Stop traversing the hash table.   */
+      /* Stop traversing the hash table.  */
       return 0;
     }
 
@@ -1252,20 +1346,20 @@ dataflow_set_different_2 (void **slot, void *data)
   variable var1, var2;
 
   var1 = *(variable *) slot;
-  var2 = (variable) htab_find_with_hash (htab, var1->decl,
-                                        VARIABLE_HASH_VAL (var1->decl));
+  var2 = htab_find_with_hash (htab, var1->decl,
+                             VARIABLE_HASH_VAL (var1->decl));
   if (!var2)
     {
       dataflow_set_different_value = true;
 
-      /* Stop traversing the hash table.   */
+      /* Stop traversing the hash table.  */
       return 0;
     }
 
 #ifdef ENABLE_CHECKING
   /* If both variables are defined they have been already checked for
      equivalence.  */
-  if (variable_different_p (var1, var2))
+  if (variable_different_p (var1, var2, false))
     abort ();
 #endif
 
@@ -1361,6 +1455,10 @@ track_expr_p (tree expr)
   if (!decl_rtl)
     return 0;
 
+  /* Do not track EXPR if it should be ignored for debugging purposes.  */
+  if (DECL_IGNORED_P (expr))
+    return 0;
+
   /* Do not track global variables until we are able to emit correct location
      list for them.  */
   if (TREE_STATIC (expr))
@@ -1374,13 +1472,13 @@ track_expr_p (tree expr)
      extern char **_dl_argv_internal __attribute__ ((alias ("_dl_argv")));
      char **_dl_argv;
   */
-  if (GET_CODE (decl_rtl) == MEM
+  if (MEM_P (decl_rtl)
       && contains_symbol_ref (XEXP (decl_rtl, 0)))
     return 0;
 
   /* If RTX is a memory it should not be very large (because it would be
      an array or struct).  */
-  if (GET_CODE (decl_rtl) == MEM)
+  if (MEM_P (decl_rtl))
     {
       /* Do not track structures and arrays.  */
       if (GET_MODE (decl_rtl) == BLKmode)
@@ -1401,7 +1499,7 @@ count_uses (rtx *loc, void *insn)
 {
   basic_block bb = BLOCK_FOR_INSN ((rtx) insn);
 
-  if (GET_CODE (*loc) == REG)
+  if (REG_P (*loc))
     {
 #ifdef ENABLE_CHECKING
        if (REGNO (*loc) >= FIRST_PSEUDO_REGISTER)
@@ -1409,7 +1507,7 @@ count_uses (rtx *loc, void *insn)
 #endif
        VTI (bb)->n_mos++;
     }
-  else if (GET_CODE (*loc) == MEM
+  else if (MEM_P (*loc)
           && MEM_EXPR (*loc)
           && track_expr_p (MEM_EXPR (*loc)))
     {
@@ -1442,7 +1540,7 @@ count_stores (rtx loc, rtx expr ATTRIBUTE_UNUSED, void *insn)
 static int
 add_uses (rtx *loc, void *insn)
 {
-  if (GET_CODE (*loc) == REG)
+  if (REG_P (*loc))
     {
       basic_block bb = BLOCK_FOR_INSN ((rtx) insn);
       micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++;
@@ -1452,7 +1550,7 @@ add_uses (rtx *loc, void *insn)
       mo->u.loc = *loc;
       mo->insn = (rtx) insn;
     }
-  else if (GET_CODE (*loc) == MEM
+  else if (MEM_P (*loc)
           && MEM_EXPR (*loc)
           && track_expr_p (MEM_EXPR (*loc)))
     {
@@ -1482,7 +1580,7 @@ add_uses_1 (rtx *x, void *insn)
 static void
 add_stores (rtx loc, rtx expr, void *insn)
 {
-  if (GET_CODE (loc) == REG)
+  if (REG_P (loc))
     {
       basic_block bb = BLOCK_FOR_INSN ((rtx) insn);
       micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++;
@@ -1493,7 +1591,7 @@ add_stores (rtx loc, rtx expr, void *insn)
       mo->u.loc = loc;
       mo->insn = (rtx) insn;
     }
-  else if (GET_CODE (loc) == MEM
+  else if (MEM_P (loc)
           && MEM_EXPR (loc)
           && track_expr_p (MEM_EXPR (loc)))
     {
@@ -1537,9 +1635,9 @@ compute_bb_dataflow (basic_block bb)
            {
              rtx loc = VTI (bb)->mos[i].u.loc;
 
-             if (GET_CODE (loc) == REG)
+             if (REG_P (loc))
                var_reg_delete_and_set (out, loc);
-             else if (GET_CODE (loc) == MEM)
+             else if (MEM_P (loc))
                var_mem_delete_and_set (out, loc);
            }
            break;
@@ -1549,9 +1647,9 @@ compute_bb_dataflow (basic_block bb)
            {
              rtx loc = VTI (bb)->mos[i].u.loc;
 
-             if (GET_CODE (loc) == REG)
+             if (REG_P (loc))
                var_reg_delete (out, loc);
-             else if (GET_CODE (loc) == MEM)
+             else if (MEM_P (loc))
                var_mem_delete (out, loc);
            }
            break;
@@ -1561,9 +1659,8 @@ compute_bb_dataflow (basic_block bb)
              rtx base;
 
              out->stack_adjust += VTI (bb)->mos[i].u.adjust;
-             base = gen_rtx_MEM (Pmode,
-                                 gen_rtx_PLUS (Pmode, stack_pointer_rtx,
-                                               GEN_INT (out->stack_adjust)));
+             base = gen_rtx_MEM (Pmode, plus_constant (stack_pointer_rtx,
+                                                       out->stack_adjust));
              set_frame_base_location (out, base);
            }
            break;
@@ -1590,8 +1687,8 @@ vt_find_locations (void)
 
   /* Compute reverse completion order of depth first search of the CFG
      so that the data-flow runs faster.  */
-  rc_order = (int *) xmalloc (n_basic_blocks * sizeof (int));
-  bb_order = (int *) xmalloc (last_basic_block * sizeof (int));
+  rc_order = xmalloc (n_basic_blocks * sizeof (int));
+  bb_order = xmalloc (last_basic_block * sizeof (int));
   flow_depth_first_order_compute (NULL, rc_order);
   for (i = 0; i < n_basic_blocks; i++)
     bb_order[rc_order[i]] = i;
@@ -1603,13 +1700,10 @@ vt_find_locations (void)
   in_worklist = sbitmap_alloc (last_basic_block);
   in_pending = sbitmap_alloc (last_basic_block);
   sbitmap_zero (in_worklist);
-  sbitmap_zero (in_pending);
 
   FOR_EACH_BB (bb)
-    {
-      fibheap_insert (pending, bb_order[bb->index], bb);
-      SET_BIT (in_pending, bb->index);
-    }
+    fibheap_insert (pending, bb_order[bb->index], bb);
+  sbitmap_ones (in_pending);
 
   while (!fibheap_empty (pending))
     {
@@ -1689,11 +1783,11 @@ dump_attrs_list (attrs list)
 {
   for (; list; list = list->next)
     {
-      print_mem_expr (rtl_dump_file, list->decl);
-      fprintf (rtl_dump_file, "+");
-      fprintf (rtl_dump_file, HOST_WIDE_INT_PRINT_DEC, list->offset);
+      print_mem_expr (dump_file, list->decl);
+      fprintf (dump_file, "+");
+      fprintf (dump_file, HOST_WIDE_INT_PRINT_DEC, list->offset);
     }
-  fprintf (rtl_dump_file, "\n");
+  fprintf (dump_file, "\n");
 }
 
 /* Print the information about variable *SLOT to dump file.  */
@@ -1705,16 +1799,16 @@ dump_variable (void **slot, void *data ATTRIBUTE_UNUSED)
   int i;
   location_chain node;
 
-  fprintf (rtl_dump_file, "  name: %s\n",
+  fprintf (dump_file, "  name: %s\n",
           IDENTIFIER_POINTER (DECL_NAME (var->decl)));
   for (i = 0; i < var->n_var_parts; i++)
     {
-      fprintf (rtl_dump_file, "    offset %ld\n",
+      fprintf (dump_file, "    offset %ld\n",
               (long) var->var_part[i].offset);
       for (node = var->var_part[i].loc_chain; node; node = node->next)
        {
-         fprintf (rtl_dump_file, "      ");
-         print_rtl_single (rtl_dump_file, node->loc);
+         fprintf (dump_file, "      ");
+         print_rtl_single (dump_file, node->loc);
        }
     }
 
@@ -1729,7 +1823,7 @@ dump_vars (htab_t vars)
 {
   if (htab_elements (vars) > 0)
     {
-      fprintf (rtl_dump_file, "Variables:\n");
+      fprintf (dump_file, "Variables:\n");
       htab_traverse (vars, dump_variable, NULL);
     }
 }
@@ -1741,19 +1835,19 @@ dump_dataflow_set (dataflow_set *set)
 {
   int i;
 
-  fprintf (rtl_dump_file, "Stack adjustment: ");
-  fprintf (rtl_dump_file, HOST_WIDE_INT_PRINT_DEC, set->stack_adjust);
-  fprintf (rtl_dump_file, "\n");
+  fprintf (dump_file, "Stack adjustment: ");
+  fprintf (dump_file, HOST_WIDE_INT_PRINT_DEC, set->stack_adjust);
+  fprintf (dump_file, "\n");
   for (i = 1; i < FIRST_PSEUDO_REGISTER; i++)
     {
       if (set->regs[i])
        {
-         fprintf (rtl_dump_file, "Reg %d:", i);
+         fprintf (dump_file, "Reg %d:", i);
          dump_attrs_list (set->regs[i]);
        }
     }
   dump_vars (set->vars);
-  fprintf (rtl_dump_file, "\n");
+  fprintf (dump_file, "\n");
 }
 
 /* Print the IN and OUT sets for each basic block to dump file.  */
@@ -1765,10 +1859,10 @@ dump_dataflow_sets (void)
 
   FOR_EACH_BB (bb)
     {
-      fprintf (rtl_dump_file, "\nBasic block %d:\n", bb->index);
-      fprintf (rtl_dump_file, "IN:\n");
+      fprintf (dump_file, "\nBasic block %d:\n", bb->index);
+      fprintf (dump_file, "IN:\n");
       dump_dataflow_set (&VTI (bb)->in);
-      fprintf (rtl_dump_file, "OUT:\n");
+      fprintf (dump_file, "OUT:\n");
       dump_dataflow_set (&VTI (bb)->out);
     }
 }
@@ -1795,6 +1889,7 @@ variable_was_changed (variable var, htab_t htab)
 
          empty_var = pool_alloc (var_pool);
          empty_var->decl = var->decl;
+         empty_var->refcount = 1;
          empty_var->n_var_parts = 0;
          *slot = empty_var;
 
@@ -1825,9 +1920,8 @@ variable_was_changed (variable var, htab_t htab)
 }
 
 /* Set the location of frame_base_decl to LOC in dataflow set SET.  This
-   function expects that
-   frame_base_decl has already one location for offset 0 in the variable table.
- */
+   function expects that frame_base_decl has already one location for offset 0
+   in the variable table.  */
 
 static void
 set_frame_base_location (dataflow_set *set, rtx loc)
@@ -1847,7 +1941,12 @@ set_frame_base_location (dataflow_set *set, rtx loc)
     abort ();
 #endif
 
+  /* If frame_base_decl is shared unshare it first.  */
+  if (var->refcount > 1)
+    var = unshare_variable (set, var);
+
   var->var_part[0].loc_chain->loc = loc;
+  var->var_part[0].cur_loc = loc;
   variable_was_changed (var, set->vars);
 }
 
@@ -1859,7 +1958,8 @@ static void
 set_variable_part (dataflow_set *set, rtx loc, tree decl, HOST_WIDE_INT offset)
 {
   int pos, low, high;
-  location_chain node, prev, next;
+  location_chain node, next;
+  location_chain *nextp;
   variable var;
   void **slot;
   
@@ -1870,6 +1970,7 @@ set_variable_part (dataflow_set *set, rtx loc, tree decl, HOST_WIDE_INT offset)
       /* Create new variable information.  */
       var = pool_alloc (var_pool);
       var->decl = decl;
+      var->refcount = 1;
       var->n_var_parts = 1;
       var->var_part[0].offset = offset;
       var->var_part[0].loc_chain = NULL;
@@ -1894,9 +1995,33 @@ set_variable_part (dataflow_set *set, rtx loc, tree decl, HOST_WIDE_INT offset)
        }
       pos = low;
 
-      if (pos == var->n_var_parts || var->var_part[pos].offset != offset)
+      if (pos < var->n_var_parts && var->var_part[pos].offset == offset)
        {
-         /* We have not find the location part, new one will be created.  */
+         node = var->var_part[pos].loc_chain;
+
+         if (node
+             && ((REG_P (node->loc) && REG_P (loc)
+                  && REGNO (node->loc) == REGNO (loc))
+                 || rtx_equal_p (node->loc, loc)))
+           {
+             /* LOC is in the beginning of the chain so we have nothing
+                to do.  */
+             return;
+           }
+         else
+           {
+             /* We have to make a copy of a shared variable.  */
+             if (var->refcount > 1)
+               var = unshare_variable (set, var);
+           }
+       }
+      else
+       {
+         /* We have not found the location part, new one will be created.  */
+
+         /* We have to make a copy of the shared variable.  */
+         if (var->refcount > 1)
+           var = unshare_variable (set, var);
 
 #ifdef ENABLE_CHECKING
          /* We track only variables whose size is <= MAX_VAR_PARTS bytes
@@ -1917,24 +2042,21 @@ set_variable_part (dataflow_set *set, rtx loc, tree decl, HOST_WIDE_INT offset)
        }
     }
 
-  /* Delete the location from list.  */
-  prev = NULL;
+  /* Delete the location from the list.  */
+  nextp = &var->var_part[pos].loc_chain;
   for (node = var->var_part[pos].loc_chain; node; node = next)
     {
       next = node->next;
-      if ((GET_CODE (node->loc) == REG && GET_CODE (loc) == REG
+      if ((REG_P (node->loc) && REG_P (loc)
           && REGNO (node->loc) == REGNO (loc))
          || rtx_equal_p (node->loc, loc))
        {
-         if (prev)
-           prev->next = next;
-         else
-           var->var_part[pos].loc_chain = next;
          pool_free (loc_chain_pool, node);
+         *nextp = next;
          break;
        }
       else
-       prev = node;
+       nextp = &node->next;
     }
 
   /* Add the location to the beginning.  */
@@ -1983,35 +2105,50 @@ delete_variable_part (dataflow_set *set, rtx loc, tree decl,
 
       if (pos < var->n_var_parts && var->var_part[pos].offset == offset)
        {
-         location_chain node, prev, next;
+         location_chain node, next;
+         location_chain *nextp;
          bool changed;
 
+         if (var->refcount > 1)
+           {
+             /* If the variable contains the location part we have to
+                make a copy of the variable.  */
+             for (node = var->var_part[pos].loc_chain; node;
+                  node = node->next)
+               {
+                 if ((REG_P (node->loc) && REG_P (loc)
+                      && REGNO (node->loc) == REGNO (loc))
+                     || rtx_equal_p (node->loc, loc))
+                   {
+                     var = unshare_variable (set, var);
+                     break;
+                   }
+               }
+           }
+
          /* Delete the location part.  */
-         prev = NULL;
-         for (node = var->var_part[pos].loc_chain; node; node = next)
+         nextp = &var->var_part[pos].loc_chain;
+         for (node = *nextp; node; node = next)
            {
              next = node->next;
-             if ((GET_CODE (node->loc) == REG && GET_CODE (loc) == REG
+             if ((REG_P (node->loc) && REG_P (loc)
                   && REGNO (node->loc) == REGNO (loc))
                  || rtx_equal_p (node->loc, loc))
                {
-                 if (prev)
-                   prev->next = next;
-                 else
-                   var->var_part[pos].loc_chain = next;
                  pool_free (loc_chain_pool, node);
+                 *nextp = next;
                  break;
                }
              else
-               prev = node;
+               nextp = &node->next;
            }
 
          /* If we have deleted the location which was last emitted
             we have to emit new location so add the variable to set
             of changed variables.  */
          if (var->var_part[pos].cur_loc
-             && ((GET_CODE (loc) == REG
-                  && GET_CODE (var->var_part[pos].cur_loc) == REG
+             && ((REG_P (loc)
+                  && REG_P (var->var_part[pos].cur_loc)
                   && REGNO (loc) == REGNO (var->var_part[pos].cur_loc))
                  || rtx_equal_p (loc, var->var_part[pos].cur_loc)))
            {
@@ -2147,8 +2284,8 @@ emit_notes_for_differences_1 (void **slot, void *data)
   variable old_var, new_var;
 
   old_var = *(variable *) slot;
-  new_var = (variable) htab_find_with_hash (new_vars, old_var->decl,
-                                           VARIABLE_HASH_VAL (old_var->decl));
+  new_var = htab_find_with_hash (new_vars, old_var->decl,
+                                VARIABLE_HASH_VAL (old_var->decl));
 
   if (!new_var)
     {
@@ -2157,10 +2294,11 @@ emit_notes_for_differences_1 (void **slot, void *data)
 
       empty_var = pool_alloc (var_pool);
       empty_var->decl = old_var->decl;
+      empty_var->refcount = 1;
       empty_var->n_var_parts = 0;
       variable_was_changed (empty_var, NULL);
     }
-  else if (variable_different_p (old_var, new_var))
+  else if (variable_different_p (old_var, new_var, true))
     {
       variable_was_changed (new_var, NULL);
     }
@@ -2179,8 +2317,8 @@ emit_notes_for_differences_2 (void **slot, void *data)
   variable old_var, new_var;
 
   new_var = *(variable *) slot;
-  old_var = (variable) htab_find_with_hash (old_vars, new_var->decl,
-                                           VARIABLE_HASH_VAL (new_var->decl));
+  old_var = htab_find_with_hash (old_vars, new_var->decl,
+                                VARIABLE_HASH_VAL (new_var->decl));
   if (!old_var)
     {
       /* Variable has appeared.  */
@@ -2238,7 +2376,7 @@ emit_notes_in_bb (basic_block bb)
            {
              rtx loc = VTI (bb)->mos[i].u.loc;
 
-             if (GET_CODE (loc) == REG)
+             if (REG_P (loc))
                var_reg_delete_and_set (&set, loc);
              else
                var_mem_delete_and_set (&set, loc);
@@ -2255,7 +2393,7 @@ emit_notes_in_bb (basic_block bb)
            {
              rtx loc = VTI (bb)->mos[i].u.loc;
 
-             if (GET_CODE (loc) == REG)
+             if (REG_P (loc))
                var_reg_delete (&set, loc);
              else
                var_mem_delete (&set, loc);
@@ -2272,9 +2410,8 @@ emit_notes_in_bb (basic_block bb)
              rtx base;
 
              set.stack_adjust += VTI (bb)->mos[i].u.adjust;
-             base = gen_rtx_MEM (Pmode,
-                                 gen_rtx_PLUS (Pmode, stack_pointer_rtx,
-                                               GEN_INT (set.stack_adjust)));
+             base = gen_rtx_MEM (Pmode, plus_constant (stack_pointer_rtx,
+                                                       set.stack_adjust));
              set_frame_base_location (&set, base);
              emit_notes_for_changes (insn, EMIT_NOTE_AFTER_INSN);
            }
@@ -2326,7 +2463,7 @@ vt_emit_notes (void)
 static bool
 vt_get_decl_and_offset (rtx rtl, tree *declp, HOST_WIDE_INT *offsetp)
 {
-  if (GET_CODE (rtl) == REG)
+  if (REG_P (rtl))
     {
       if (REG_ATTRS (rtl))
        {
@@ -2335,7 +2472,7 @@ vt_get_decl_and_offset (rtx rtl, tree *declp, HOST_WIDE_INT *offsetp)
          return true;
        }
     }
-  else if (GET_CODE (rtl) == MEM)
+  else if (MEM_P (rtl))
     {
       if (MEM_ATTRS (rtl))
        {
@@ -2353,11 +2490,7 @@ static void
 vt_add_function_parameters (void)
 {
   tree parm;
-  HOST_WIDE_INT stack_adjust = 0;
   
-  if (!frame_pointer_needed)
-    stack_adjust = prologue_stack_adjust ();
-
   for (parm = DECL_ARGUMENTS (current_function_decl);
        parm; parm = TREE_CHAIN (parm))
     {
@@ -2365,7 +2498,7 @@ vt_add_function_parameters (void)
       rtx incoming = DECL_INCOMING_RTL (parm);
       tree decl;
       HOST_WIDE_INT offset;
-      dataflow_set *in, *out;
+      dataflow_set *out;
 
       if (TREE_CODE (parm) != PARM_DECL)
        continue;
@@ -2392,27 +2525,20 @@ vt_add_function_parameters (void)
 #endif
 
       incoming = eliminate_regs (incoming, 0, NULL_RTX);
-      if (!frame_pointer_needed && GET_CODE (incoming) == MEM)
-       incoming = adjust_stack_reference (incoming, -stack_adjust);
-      in = &VTI (ENTRY_BLOCK_PTR)->in;
       out = &VTI (ENTRY_BLOCK_PTR)->out;
 
-      if (GET_CODE (incoming) == REG)
+      if (REG_P (incoming))
        {
 #ifdef ENABLE_CHECKING
          if (REGNO (incoming) >= FIRST_PSEUDO_REGISTER)
            abort ();
 #endif
-         attrs_list_insert (&in->regs[REGNO (incoming)],
-                            parm, offset, incoming);
          attrs_list_insert (&out->regs[REGNO (incoming)],
                             parm, offset, incoming);
-         set_variable_part (in, incoming, parm, offset);
          set_variable_part (out, incoming, parm, offset);
        }
-      else if (GET_CODE (incoming) == MEM)
+      else if (MEM_P (incoming))
        {
-         set_variable_part (in, incoming, parm, offset);
          set_variable_part (out, incoming, parm, offset);
        }
     }
@@ -2450,7 +2576,7 @@ vt_initialize (void)
                }
              note_uses (&PATTERN (insn), count_uses_1, insn);
              note_stores (PATTERN (insn), count_stores, insn);
-             if (GET_CODE (insn) == CALL_INSN)
+             if (CALL_P (insn))
                VTI (bb)->n_mos++;
            }
        }
@@ -2500,7 +2626,7 @@ vt_initialize (void)
                    }
                }
 
-             if (GET_CODE (insn) == CALL_INSN)
+             if (CALL_P (insn))
                {
                  micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++;
 
@@ -2571,8 +2697,9 @@ vt_initialize (void)
       DECL_ARTIFICIAL (frame_base_decl) = 1;
 
       /* Set its initial "location".  */
-      base = gen_rtx_MEM (Pmode, stack_pointer_rtx);
-      set_variable_part (&VTI (ENTRY_BLOCK_PTR)->in, base, frame_base_decl, 0);
+      frame_stack_adjust = -prologue_stack_adjust ();
+      base = gen_rtx_MEM (Pmode, plus_constant (stack_pointer_rtx,
+                                               frame_stack_adjust));
       set_variable_part (&VTI (ENTRY_BLOCK_PTR)->out, base, frame_base_decl, 0);
     }
   else
@@ -2627,10 +2754,10 @@ variable_tracking_main (void)
   vt_find_locations ();
   vt_emit_notes ();
 
-  if (rtl_dump_file)
+  if (dump_file)
     {
       dump_dataflow_sets ();
-      dump_flow_info (rtl_dump_file);
+      dump_flow_info (dump_file);
     }
 
   vt_finalize ();