OSDN Git Service

gcc/ChangeLog:
[pf3gnuchains/gcc-fork.git] / gcc / var-tracking.c
index a24755f..840128c 100644 (file)
@@ -723,12 +723,25 @@ static inline bool
 dv_is_decl_p (decl_or_value dv)
 {
   if (!dv)
-    return false;
+    return true;
 
-  if (GET_CODE ((rtx)dv) == VALUE)
-    return false;
+  /* Make sure relevant codes don't overlap.  */
+  switch ((int)TREE_CODE ((tree)dv))
+    {
+    case (int)VAR_DECL:
+    case (int)PARM_DECL:
+    case (int)RESULT_DECL:
+    case (int)FUNCTION_DECL:
+    case (int)DEBUG_EXPR_DECL:
+    case (int)COMPONENT_REF:
+      return true;
 
-  return true;
+    case (int)VALUE:
+      return false;
+
+    default:
+      gcc_unreachable ();
+    }
 }
 
 /* Return true if a decl_or_value is a VALUE rtl.  */
@@ -790,21 +803,13 @@ dv_pool (decl_or_value dv)
   return dv_onepart_p (dv) ? valvar_pool : var_pool;
 }
 
-#define IS_DECL_CODE(C) ((C) == VAR_DECL || (C) == PARM_DECL \
-                        || (C) == RESULT_DECL || (C) == COMPONENT_REF)
-
-/* Check that VALUE won't ever look like a DECL.  */
-static char check_value_is_not_decl [(!IS_DECL_CODE ((enum tree_code)VALUE))
-                                    ? 1 : -1] ATTRIBUTE_UNUSED;
-
-
 /* Build a decl_or_value out of a decl.  */
 static inline decl_or_value
 dv_from_decl (tree decl)
 {
   decl_or_value dv;
-  gcc_assert (!decl || IS_DECL_CODE (TREE_CODE (decl)));
   dv = decl;
+  gcc_assert (dv_is_decl_p (dv));
   return dv;
 }
 
@@ -813,8 +818,8 @@ static inline decl_or_value
 dv_from_value (rtx value)
 {
   decl_or_value dv;
-  gcc_assert (value);
   dv = value;
+  gcc_assert (dv_is_value_p (dv));
   return dv;
 }
 
@@ -2218,7 +2223,7 @@ dataflow_set_union (dataflow_set *dst, dataflow_set *src)
 
 /* Whether the value is currently being expanded.  */
 #define VALUE_RECURSED_INTO(x) \
-  (RTL_FLAG_CHECK1 ("VALUE_RECURSED_INTO", (x), VALUE)->used)
+  (RTL_FLAG_CHECK2 ("VALUE_RECURSED_INTO", (x), VALUE, DEBUG_EXPR)->used)
 /* Whether the value is in changed_variables hash table.  */
 #define VALUE_CHANGED(x) \
   (RTL_FLAG_CHECK1 ("VALUE_CHANGED", (x), VALUE)->frame_related)
@@ -4108,6 +4113,9 @@ track_expr_p (tree expr, bool need_rtl)
   rtx decl_rtl;
   tree realdecl;
 
+  if (TREE_CODE (expr) == DEBUG_EXPR_DECL)
+    return DECL_RTL_SET_P (expr);
+
   /* If EXPR is not a parameter or a variable do not track it.  */
   if (TREE_CODE (expr) != VAR_DECL && TREE_CODE (expr) != PARM_DECL)
     return 0;
@@ -4973,8 +4981,8 @@ add_with_sets (rtx insn, struct cselib_set *sets, int n_sets)
   note_uses (&PATTERN (insn), add_uses_1, &cui);
   n2 = VTI (bb)->n_mos - 1;
 
-  /* Order the MO_USEs to be before MO_USE_NO_VARs,
-     MO_VAL_LOC and MO_VAL_USE.  */
+  /* Order the MO_USEs to be before MO_USE_NO_VARs and MO_VAL_USE, and
+     MO_VAL_LOC last.  */
   while (n1 < n2)
     {
       while (n1 < n2 && VTI (bb)->mos[n1].type == MO_USE)
@@ -4991,6 +4999,24 @@ add_with_sets (rtx insn, struct cselib_set *sets, int n_sets)
        }
     }
 
+  n2 = VTI (bb)->n_mos - 1;
+
+  while (n1 < n2)
+    {
+      while (n1 < n2 && VTI (bb)->mos[n1].type != MO_VAL_LOC)
+       n1++;
+      while (n1 < n2 && VTI (bb)->mos[n2].type == MO_VAL_LOC)
+       n2--;
+      if (n1 < n2)
+       {
+         micro_operation sw;
+
+         sw = VTI (bb)->mos[n1];
+         VTI (bb)->mos[n1] = VTI (bb)->mos[n2];
+         VTI (bb)->mos[n2] = sw;
+       }
+    }
+
   if (CALL_P (insn))
     {
       micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++;
@@ -6239,7 +6265,8 @@ check_wrap_constant (enum machine_mode mode, rtx result)
 }
 
 /* Callback for cselib_expand_value, that looks for expressions
-   holding the value in the var-tracking hash tables.  */
+   holding the value in the var-tracking hash tables.  Return X for
+   standard processing, anything else is to be used as-is.  */
 
 static rtx
 vt_expand_loc_callback (rtx x, bitmap regs, int max_depth, void *data)
@@ -6248,21 +6275,58 @@ vt_expand_loc_callback (rtx x, bitmap regs, int max_depth, void *data)
   decl_or_value dv;
   variable var;
   location_chain loc;
-  rtx result;
+  rtx result, subreg, xret;
+
+  switch (GET_CODE (x))
+    {
+    case SUBREG:
+      subreg = SUBREG_REG (x);
+
+      if (GET_CODE (SUBREG_REG (x)) != VALUE)
+       return x;
+
+      subreg = cselib_expand_value_rtx_cb (SUBREG_REG (x), regs,
+                                          max_depth - 1,
+                                          vt_expand_loc_callback, data);
+
+      if (!subreg)
+       return NULL;
 
-  gcc_assert (GET_CODE (x) == VALUE);
+      result = simplify_gen_subreg (GET_MODE (x), subreg,
+                                   GET_MODE (SUBREG_REG (x)),
+                                   SUBREG_BYTE (x));
+
+      /* Invalid SUBREGs are ok in debug info.  ??? We could try
+        alternate expansions for the VALUE as well.  */
+      if (!result && (REG_P (subreg) || MEM_P (subreg)))
+       result = gen_rtx_raw_SUBREG (GET_MODE (x), subreg, SUBREG_BYTE (x));
+
+      return result;
+
+    case DEBUG_EXPR:
+      dv = dv_from_decl (XTREE (x, 0));
+      xret = NULL;
+      break;
+
+    case VALUE:
+      dv = dv_from_value (x);
+      xret = x;
+      break;
+
+    default:
+      return x;
+    }
 
   if (VALUE_RECURSED_INTO (x))
     return NULL;
 
-  dv = dv_from_value (x);
   var = (variable) htab_find_with_hash (vars, dv, dv_htab_hash (dv));
 
   if (!var)
-    return NULL;
+    return xret;
 
   if (var->n_var_parts == 0)
-    return NULL;
+    return xret;
 
   gcc_assert (var->n_var_parts == 1);
 
@@ -6279,7 +6343,10 @@ vt_expand_loc_callback (rtx x, bitmap regs, int max_depth, void *data)
     }
 
   VALUE_RECURSED_INTO (x) = false;
-  return result;
+  if (result)
+    return result;
+  else
+    return xret;
 }
 
 /* Expand VALUEs in LOC, using VARS as well as cselib's equivalence
@@ -6329,6 +6396,9 @@ emit_note_insn_var_location (void **varp, void *data)
 
   decl = dv_as_decl (var->dv);
 
+  if (TREE_CODE (decl) == DEBUG_EXPR_DECL)
+    goto clear;
+
   gcc_assert (decl);
 
   complete = true;
@@ -7058,10 +7128,20 @@ vt_add_function_parameters (void)
 
       if (!vt_get_decl_and_offset (incoming, &decl, &offset))
        {
-         if (!vt_get_decl_and_offset (decl_rtl, &decl, &offset))
-           continue;
-         offset += byte_lowpart_offset (GET_MODE (incoming),
-                                        GET_MODE (decl_rtl));
+         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));
+           }
        }
 
       if (!decl)