OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / var-tracking.c
index b9c6908..ab141c1 100644 (file)
@@ -1,5 +1,5 @@
 /* Variable tracking routines for the GNU compiler.
-   Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010
+   Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011
    Free Software Foundation, Inc.
 
    This file is part of GCC.
@@ -92,6 +92,7 @@
 #include "tm.h"
 #include "rtl.h"
 #include "tree.h"
+#include "tm_p.h"
 #include "hard-reg-set.h"
 #include "basic-block.h"
 #include "flags.h"
 #include "tree-flow.h"
 #include "cselib.h"
 #include "target.h"
-#include "toplev.h"
 #include "params.h"
 #include "diagnostic.h"
 #include "tree-pretty-print.h"
@@ -737,7 +737,11 @@ use_narrower_mode_test (rtx *loc, void *data)
   switch (GET_CODE (*loc))
     {
     case REG:
-      if (cselib_lookup (*loc, GET_MODE (SUBREG_REG (subreg)), 0))
+      if (cselib_lookup (*loc, GET_MODE (SUBREG_REG (subreg)), 0, VOIDmode))
+       return 1;
+      if (!validate_subreg (GET_MODE (subreg), GET_MODE (*loc),
+                           *loc, subreg_lowpart_offset (GET_MODE (subreg),
+                                                        GET_MODE (*loc))))
        return 1;
       return -1;
     case PLUS:
@@ -805,6 +809,7 @@ adjust_mems (rtx loc, const_rtx old_rtx, void *data)
               && hard_frame_pointer_adjustment != -1
               && cfa_base_rtx)
        return compute_cfa_pointer (hard_frame_pointer_adjustment);
+      gcc_checking_assert (loc != virtual_incoming_args_rtx);
       return loc;
     case MEM:
       mem = loc;
@@ -3953,8 +3958,10 @@ variable_post_merge_new_vals (void **slot, void *info)
                         subsequent rounds.  */
                      cselib_val *v;
                      gcc_assert (!cselib_lookup (node->loc,
-                                                 GET_MODE (node->loc), 0));
-                     v = cselib_lookup (node->loc, GET_MODE (node->loc), 1);
+                                                 GET_MODE (node->loc), 0,
+                                                 VOIDmode));
+                     v = cselib_lookup (node->loc, GET_MODE (node->loc), 1,
+                                        VOIDmode);
                      cselib_preserve_value (v);
                      cselib_invalidate_rtx (node->loc);
                      cval = v->val_rtx;
@@ -4104,8 +4111,9 @@ find_mem_expr_in_1pdv (tree expr, rtx val, htab_t vars)
   VALUE_RECURSED_INTO (val) = true;
 
   for (node = var->var_part[0].loc_chain; node; node = node->next)
-    if (MEM_P (node->loc) && MEM_EXPR (node->loc) == expr
-       && MEM_OFFSET (node->loc) == 0)
+    if (MEM_P (node->loc)
+       && MEM_EXPR (node->loc) == expr
+       && INT_MEM_OFFSET (node->loc) == 0)
       {
        where = node;
        break;
@@ -4168,11 +4176,10 @@ dataflow_set_preserve_mem_locs (void **slot, void *data)
        {
          for (loc = var->var_part[0].loc_chain; loc; loc = loc->next)
            {
-             /* We want to remove dying MEMs that doesn't refer to
-                DECL.  */
+             /* We want to remove dying MEMs that doesn't refer to DECL.  */
              if (GET_CODE (loc->loc) == MEM
                  && (MEM_EXPR (loc->loc) != decl
-                     || MEM_OFFSET (loc->loc))
+                     || INT_MEM_OFFSET (loc->loc) != 0)
                  && !mem_dies_at_call (loc->loc))
                break;
              /* We want to move here MEMs that do refer to DECL.  */
@@ -4216,7 +4223,7 @@ dataflow_set_preserve_mem_locs (void **slot, void *data)
 
          if (GET_CODE (loc->loc) != MEM
              || (MEM_EXPR (loc->loc) == decl
-                 && MEM_OFFSET (loc->loc) == 0)
+                 && INT_MEM_OFFSET (loc->loc) == 0)
              || !mem_dies_at_call (loc->loc))
            {
              if (old_loc != loc->loc && emit_notes)
@@ -4781,18 +4788,25 @@ find_use_val (rtx x, enum machine_mode mode, struct count_use_info *cui)
   if (cui->sets)
     {
       /* This is called after uses are set up and before stores are
-        processed bycselib, so it's safe to look up srcs, but not
+        processed by cselib, so it's safe to look up srcs, but not
         dsts.  So we look up expressions that appear in srcs or in
         dest expressions, but we search the sets array for dests of
         stores.  */
       if (cui->store_p)
        {
+         /* Some targets represent memset and memcpy patterns
+            by (set (mem:BLK ...) (reg:[QHSD]I ...)) or
+            (set (mem:BLK ...) (const_int ...)) or
+            (set (mem:BLK ...) (mem:BLK ...)).  Don't return anything
+            in that case, otherwise we end up with mode mismatches.  */
+         if (mode == BLKmode && MEM_P (x))
+           return NULL;
          for (i = 0; i < cui->n_sets; i++)
            if (cui->sets[i].dest == x)
              return cui->sets[i].src_elt;
        }
       else
-       return cselib_lookup (x, mode, 0);
+       return cselib_lookup (x, mode, 0, VOIDmode);
     }
 
   return NULL;
@@ -4821,14 +4835,15 @@ replace_expr_with_values (rtx loc)
   else if (MEM_P (loc))
     {
       cselib_val *addr = cselib_lookup (XEXP (loc, 0),
-                                       get_address_mode (loc), 0);
+                                       get_address_mode (loc), 0,
+                                       GET_MODE (loc));
       if (addr)
        return replace_equiv_address_nv (loc, addr->val_rtx);
       else
        return NULL;
     }
   else
-    return cselib_subst_to_values (loc);
+    return cselib_subst_to_values (loc, VOIDmode);
 }
 
 /* Determine what kind of micro operation to choose for a USE.  Return
@@ -4848,7 +4863,8 @@ use_type (rtx loc, struct count_use_info *cui, enum machine_mode *modep)
              rtx ploc = PAT_VAR_LOCATION_LOC (loc);
              if (! VAR_LOC_UNKNOWN_P (ploc))
                {
-                 cselib_val *val = cselib_lookup (ploc, GET_MODE (loc), 1);
+                 cselib_val *val = cselib_lookup (ploc, GET_MODE (loc), 1,
+                                                  VOIDmode);
 
                  /* ??? flag_float_store and volatile mems are never
                     given values, but we could in theory use them for
@@ -4870,7 +4886,8 @@ use_type (rtx loc, struct count_use_info *cui, enum machine_mode *modep)
              if (REG_P (loc)
                  || (find_use_val (loc, GET_MODE (loc), cui)
                      && cselib_lookup (XEXP (loc, 0),
-                                       get_address_mode (loc), 0)))
+                                       get_address_mode (loc), 0,
+                                       GET_MODE (loc))))
                return MO_VAL_SET;
            }
          else
@@ -5032,13 +5049,15 @@ add_uses (rtx *ploc, void *data)
              rtx mloc = vloc;
              enum machine_mode address_mode = get_address_mode (mloc);
              cselib_val *val
-               = cselib_lookup (XEXP (mloc, 0), address_mode, 0);
+               = cselib_lookup (XEXP (mloc, 0), address_mode, 0,
+                                GET_MODE (mloc));
 
              if (val && !cselib_preserved_value_p (val))
                {
                  micro_operation moa;
                  preserve_value (val);
-                 mloc = cselib_subst_to_values (XEXP (mloc, 0));
+                 mloc = cselib_subst_to_values (XEXP (mloc, 0),
+                                                GET_MODE (mloc));
                  moa.type = MO_VAL_USE;
                  moa.insn = cui->insn;
                  moa.u.loc = gen_rtx_CONCAT (address_mode,
@@ -5108,13 +5127,15 @@ add_uses (rtx *ploc, void *data)
              rtx mloc = oloc;
              enum machine_mode address_mode = get_address_mode (mloc);
              cselib_val *val
-               = cselib_lookup (XEXP (mloc, 0), address_mode, 0);
+               = cselib_lookup (XEXP (mloc, 0), address_mode, 0,
+                               GET_MODE (mloc));
 
              if (val && !cselib_preserved_value_p (val))
                {
                  micro_operation moa;
                  preserve_value (val);
-                 mloc = cselib_subst_to_values (XEXP (mloc, 0));
+                 mloc = cselib_subst_to_values (XEXP (mloc, 0),
+                                               GET_MODE (mloc));
                  moa.type = MO_VAL_USE;
                  moa.insn = cui->insn;
                  moa.u.loc = gen_rtx_CONCAT (address_mode,
@@ -5224,7 +5245,7 @@ reverse_op (rtx val, const_rtx expr)
   if (!SCALAR_INT_MODE_P (GET_MODE (src)) || XEXP (src, 0) == cfa_base_rtx)
     return NULL_RTX;
 
-  v = cselib_lookup (XEXP (src, 0), GET_MODE (XEXP (src, 0)), 0);
+  v = cselib_lookup (XEXP (src, 0), GET_MODE (XEXP (src, 0)), 0, VOIDmode);
   if (!v || !cselib_preserved_value_p (v))
     return NULL_RTX;
 
@@ -5345,13 +5366,15 @@ add_stores (rtx loc, const_rtx expr, void *cuip)
          rtx mloc = loc;
          enum machine_mode address_mode = get_address_mode (mloc);
          cselib_val *val = cselib_lookup (XEXP (mloc, 0),
-                                          address_mode, 0);
+                                          address_mode, 0,
+                                          GET_MODE (mloc));
 
          if (val && !cselib_preserved_value_p (val))
            {
              preserve_value (val);
              mo.type = MO_VAL_USE;
-             mloc = cselib_subst_to_values (XEXP (mloc, 0));
+             mloc = cselib_subst_to_values (XEXP (mloc, 0),
+                                            GET_MODE (mloc));
              mo.u.loc = gen_rtx_CONCAT (address_mode, val->val_rtx, mloc);
              mo.insn = cui->insn;
              if (dump_file && (dump_flags & TDF_DETAILS))
@@ -5410,7 +5433,7 @@ add_stores (rtx loc, const_rtx expr, void *cuip)
 
   if (GET_CODE (PATTERN (cui->insn)) == COND_EXEC)
     {
-      cselib_val *oval = cselib_lookup (oloc, GET_MODE (oloc), 0);
+      cselib_val *oval = cselib_lookup (oloc, GET_MODE (oloc), 0, VOIDmode);
 
       gcc_assert (oval != v);
       gcc_assert (REG_P (oloc) || MEM_P (oloc));
@@ -7095,24 +7118,6 @@ vt_expand_loc_dummy (rtx loc, htab_t vars, bool *pcur_loc_changed)
   return ret;
 }
 
-#ifdef ENABLE_RTL_CHECKING
-/* Used to verify that cur_loc_changed updating is safe.  */
-static struct pointer_map_t *emitted_notes;
-
-/* Strip REG_POINTER from REGs and MEM_POINTER from MEMs in order to
-   avoid differences in commutative operand simplification.  */
-static rtx
-strip_pointer_flags (rtx x, const_rtx old_rtx ATTRIBUTE_UNUSED,
-                    void *data ATTRIBUTE_UNUSED)
-{
-  if (REG_P (x) && REG_POINTER (x))
-    return gen_rtx_REG (GET_MODE (x), REGNO (x));
-  if (MEM_P (x) && MEM_POINTER (x))
-    return gen_rtx_MEM (GET_MODE (x), XEXP (x, 0));
-  return NULL_RTX;
-}
-#endif
-
 /* Emit the NOTE_INSN_VAR_LOCATION for variable *VARP.  DATA contains
    additional parameters: WHERE specifies whether the note shall be emitted
    before or after instruction INSN.  */
@@ -7157,10 +7162,8 @@ emit_note_insn_var_location (void **varp, void *data)
       if (var->n_var_parts == 0)
        var->cur_loc_changed = true;
     }
-#ifndef ENABLE_RTL_CHECKING
   if (!var->cur_loc_changed)
     goto clear;
-#endif
   for (i = 0; i < var->n_var_parts; i++)
     {
       enum machine_mode mode, wider_mode;
@@ -7302,36 +7305,6 @@ emit_note_insn_var_location (void **varp, void *data)
                                      parallel, (int) initialized);
     }
 
-#ifdef ENABLE_RTL_CHECKING
-  if (note_vl)
-    {
-      void **note_slot = pointer_map_insert (emitted_notes, decl);
-      rtx pnote = (rtx) *note_slot;
-      if (!var->cur_loc_changed && (pnote || PAT_VAR_LOCATION_LOC (note_vl)))
-       {
-         rtx old_vl, new_vl;
-         gcc_assert (pnote);
-         old_vl = PAT_VAR_LOCATION_LOC (pnote);
-         new_vl = PAT_VAR_LOCATION_LOC (note_vl);
-         if (!rtx_equal_p (old_vl, new_vl))
-           {
-             /* There might be differences caused by REG_POINTER
-                differences.  REG_POINTER affects
-                swap_commutative_operands_p.  */
-             old_vl = simplify_replace_fn_rtx (old_vl, NULL_RTX,
-                                               strip_pointer_flags, NULL);
-             new_vl = simplify_replace_fn_rtx (new_vl, NULL_RTX,
-                                               strip_pointer_flags, NULL);
-             gcc_assert (rtx_equal_p (old_vl, new_vl));
-             PAT_VAR_LOCATION_LOC (note_vl) = new_vl;
-           }
-       }
-      *note_slot = (void *) note_vl;
-    }
-  if (!var->cur_loc_changed)
-    goto clear;
-#endif
-
   if (where != EMIT_NOTE_BEFORE_INSN)
     {
       note = emit_note_after (NOTE_INSN_VAR_LOCATION, insn);
@@ -7960,9 +7933,6 @@ vt_emit_notes (void)
   basic_block bb;
   dataflow_set cur;
 
-#ifdef ENABLE_RTL_CHECKING
-  emitted_notes = pointer_map_create ();
-#endif
   gcc_assert (!htab_elements (changed_variables));
 
   /* Free memory occupied by the out hash tables, as they aren't used
@@ -8022,9 +7992,6 @@ vt_emit_notes (void)
       VEC_free (rtx, heap, changed_values_stack);
     }
 
-#ifdef ENABLE_RTL_CHECKING
-  pointer_map_destroy (emitted_notes);
-#endif
   emit_notes = false;
 }
 
@@ -8055,121 +8022,139 @@ vt_get_decl_and_offset (rtx rtl, tree *declp, HOST_WIDE_INT *offsetp)
   return false;
 }
 
-/* Insert function parameters to IN and OUT sets of ENTRY_BLOCK.  */
+/* Insert function parameter PARM in IN and OUT sets of ENTRY_BLOCK.  */
 
 static void
-vt_add_function_parameters (void)
+vt_add_function_parameter (tree parm)
 {
-  tree parm;
-
-  for (parm = DECL_ARGUMENTS (current_function_decl);
-       parm; parm = DECL_CHAIN (parm))
-    {
-      rtx decl_rtl = DECL_RTL_IF_SET (parm);
-      rtx incoming = DECL_INCOMING_RTL (parm);
-      tree decl;
-      enum machine_mode mode;
-      HOST_WIDE_INT offset;
-      dataflow_set *out;
-      decl_or_value dv;
-
-      if (TREE_CODE (parm) != PARM_DECL)
-       continue;
+  rtx decl_rtl = DECL_RTL_IF_SET (parm);
+  rtx incoming = DECL_INCOMING_RTL (parm);
+  tree decl;
+  enum machine_mode mode;
+  HOST_WIDE_INT offset;
+  dataflow_set *out;
+  decl_or_value dv;
 
-      if (!DECL_NAME (parm))
-       continue;
+  if (TREE_CODE (parm) != PARM_DECL)
+    return;
 
-      if (!decl_rtl || !incoming)
-       continue;
+  if (!decl_rtl || !incoming)
+    return;
 
-      if (GET_MODE (decl_rtl) == BLKmode || GET_MODE (incoming) == BLKmode)
-       continue;
+  if (GET_MODE (decl_rtl) == BLKmode || GET_MODE (incoming) == BLKmode)
+    return;
 
-      if (!vt_get_decl_and_offset (incoming, &decl, &offset))
+  if (!vt_get_decl_and_offset (incoming, &decl, &offset))
+    {
+      if (REG_P (incoming) || MEM_P (incoming))
        {
-         if (REG_P (incoming) || MEM_P (incoming))
-           {
-             /* This means argument is passed by invisible reference.  */
-             offset = 0;
-             decl = parm;
-             incoming = gen_rtx_MEM (GET_MODE (decl_rtl), incoming);
-           }
-         else
-           {
-             if (!vt_get_decl_and_offset (decl_rtl, &decl, &offset))
-               continue;
-             offset += byte_lowpart_offset (GET_MODE (incoming),
-                                            GET_MODE (decl_rtl));
-           }
+         /* This means argument is passed by invisible reference.  */
+         offset = 0;
+         decl = parm;
+         incoming = gen_rtx_MEM (GET_MODE (decl_rtl), incoming);
        }
-
-      if (!decl)
-       continue;
-
-      if (parm != decl)
+      else
        {
-         /* Assume that DECL_RTL was a pseudo that got spilled to
-            memory.  The spill slot sharing code will force the
-            memory to reference spill_slot_decl (%sfp), so we don't
-            match above.  That's ok, the pseudo must have referenced
-            the entire parameter, so just reset OFFSET.  */
-         gcc_assert (decl == get_spill_slot_decl (false));
-         offset = 0;
+         if (!vt_get_decl_and_offset (decl_rtl, &decl, &offset))
+           return;
+         offset += byte_lowpart_offset (GET_MODE (incoming),
+                                        GET_MODE (decl_rtl));
        }
+    }
 
-      if (!track_loc_p (incoming, parm, offset, false, &mode, &offset))
-       continue;
+  if (!decl)
+    return;
 
-      out = &VTI (ENTRY_BLOCK_PTR)->out;
+  if (parm != decl)
+    {
+      /* Assume that DECL_RTL was a pseudo that got spilled to
+        memory.  The spill slot sharing code will force the
+        memory to reference spill_slot_decl (%sfp), so we don't
+        match above.  That's ok, the pseudo must have referenced
+        the entire parameter, so just reset OFFSET.  */
+      gcc_assert (decl == get_spill_slot_decl (false));
+      offset = 0;
+    }
 
-      dv = dv_from_decl (parm);
+  if (!track_loc_p (incoming, parm, offset, false, &mode, &offset))
+    return;
 
-      if (target_for_debug_bind (parm)
-         /* We can't deal with these right now, because this kind of
-            variable is single-part.  ??? We could handle parallels
-            that describe multiple locations for the same single
-            value, but ATM we don't.  */
-         && GET_CODE (incoming) != PARALLEL)
-       {
-         cselib_val *val;
+  out = &VTI (ENTRY_BLOCK_PTR)->out;
 
-         /* ??? We shouldn't ever hit this, but it may happen because
-            arguments passed by invisible reference aren't dealt with
-            above: incoming-rtl will have Pmode rather than the
-            expected mode for the type.  */
-         if (offset)
-           continue;
+  dv = dv_from_decl (parm);
 
-         val = cselib_lookup (var_lowpart (mode, incoming), mode, true);
+  if (target_for_debug_bind (parm)
+      /* We can't deal with these right now, because this kind of
+        variable is single-part.  ??? We could handle parallels
+        that describe multiple locations for the same single
+        value, but ATM we don't.  */
+      && GET_CODE (incoming) != PARALLEL)
+    {
+      cselib_val *val;
 
-         /* ??? Float-typed values in memory are not handled by
-            cselib.  */
-         if (val)
-           {
-             preserve_value (val);
-             set_variable_part (out, val->val_rtx, dv, offset,
-                                VAR_INIT_STATUS_INITIALIZED, NULL, INSERT);
-             dv = dv_from_value (val->val_rtx);
-           }
-       }
+      /* ??? We shouldn't ever hit this, but it may happen because
+        arguments passed by invisible reference aren't dealt with
+        above: incoming-rtl will have Pmode rather than the
+        expected mode for the type.  */
+      if (offset)
+       return;
 
-      if (REG_P (incoming))
-       {
-         incoming = var_lowpart (mode, incoming);
-         gcc_assert (REGNO (incoming) < FIRST_PSEUDO_REGISTER);
-         attrs_list_insert (&out->regs[REGNO (incoming)], dv, offset,
-                            incoming);
-         set_variable_part (out, incoming, dv, offset,
-                            VAR_INIT_STATUS_INITIALIZED, NULL, INSERT);
-       }
-      else if (MEM_P (incoming))
+      val = cselib_lookup (var_lowpart (mode, incoming), mode, true,
+                          VOIDmode);
+
+      /* ??? Float-typed values in memory are not handled by
+        cselib.  */
+      if (val)
        {
-         incoming = var_lowpart (mode, incoming);
-         set_variable_part (out, incoming, dv, offset,
+         preserve_value (val);
+         set_variable_part (out, val->val_rtx, dv, offset,
                             VAR_INIT_STATUS_INITIALIZED, NULL, INSERT);
+         dv = dv_from_value (val->val_rtx);
        }
     }
 
+  if (REG_P (incoming))
+    {
+      incoming = var_lowpart (mode, incoming);
+      gcc_assert (REGNO (incoming) < FIRST_PSEUDO_REGISTER);
+      attrs_list_insert (&out->regs[REGNO (incoming)], dv, offset,
+                        incoming);
+      set_variable_part (out, incoming, dv, offset,
+                        VAR_INIT_STATUS_INITIALIZED, NULL, INSERT);
+    }
+  else if (MEM_P (incoming))
+    {
+      incoming = var_lowpart (mode, incoming);
+      set_variable_part (out, incoming, dv, offset,
+                        VAR_INIT_STATUS_INITIALIZED, NULL, INSERT);
+    }
+}
+
+/* Insert function parameters to IN and OUT sets of ENTRY_BLOCK.  */
+
+static void
+vt_add_function_parameters (void)
+{
+  tree parm;
+
+  for (parm = DECL_ARGUMENTS (current_function_decl);
+       parm; parm = DECL_CHAIN (parm))
+    vt_add_function_parameter (parm);
+
+  if (DECL_HAS_VALUE_EXPR_P (DECL_RESULT (current_function_decl)))
+    {
+      tree vexpr = DECL_VALUE_EXPR (DECL_RESULT (current_function_decl));
+
+      if (TREE_CODE (vexpr) == INDIRECT_REF)
+       vexpr = TREE_OPERAND (vexpr, 0);
+
+      if (TREE_CODE (vexpr) == PARM_DECL
+         && DECL_ARTIFICIAL (vexpr)
+         && !DECL_IGNORED_P (vexpr)
+         && DECL_NAMELESS (vexpr))
+       vt_add_function_parameter (vexpr);
+    }
+
   if (MAY_HAVE_DEBUG_INSNS)
     {
       cselib_preserve_only_values ();
@@ -8229,8 +8214,13 @@ vt_init_cfa_base (void)
   if (!MAY_HAVE_DEBUG_INSNS)
     return;
 
+  /* Tell alias analysis that cfa_base_rtx should share
+     find_base_term value with stack pointer or hard frame pointer.  */
+  vt_equate_reg_base_value (cfa_base_rtx,
+                           frame_pointer_needed
+                           ? hard_frame_pointer_rtx : stack_pointer_rtx);
   val = cselib_lookup_from_insn (cfa_base_rtx, GET_MODE (cfa_base_rtx), 1,
-                                get_insns ());
+                                VOIDmode, get_insns ());
   preserve_value (val);
   cselib_preserve_cfa_base_value (val, REGNO (cfa_base_rtx));
   var_reg_decl_set (&VTI (ENTRY_BLOCK_PTR)->out, cfa_base_rtx,
@@ -8625,7 +8615,7 @@ variable_tracking_main (void)
 static bool
 gate_handle_var_tracking (void)
 {
-  return (flag_var_tracking);
+  return (flag_var_tracking && !targetm.delay_vartrack);
 }