OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / var-tracking.c
index 27bff38..c6280e2 100644 (file)
@@ -1,5 +1,5 @@
 /* Variable tracking routines for the GNU compiler.
-   Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011
+   Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011, 2012
    Free Software Foundation, Inc.
 
    This file is part of GCC.
@@ -5298,6 +5298,7 @@ reverse_op (rtx val, const_rtx expr, rtx insn)
 {
   rtx src, arg, ret;
   cselib_val *v;
+  struct elt_loc_list *l;
   enum rtx_code code;
 
   if (GET_CODE (expr) != SET)
@@ -5333,6 +5334,18 @@ reverse_op (rtx val, const_rtx expr, rtx insn)
   if (!v || !cselib_preserved_value_p (v))
     return;
 
+  /* Use canonical V to avoid creating multiple redundant expressions
+     for different VALUES equivalent to V.  */
+  v = canonical_cselib_val (v);
+
+  /* Adding a reverse op isn't useful if V already has an always valid
+     location.  Ignore ENTRY_VALUE, while it is always constant, we should
+     prefer non-ENTRY_VALUE locations whenever possible.  */
+  for (l = v->locs; l; l = l->next)
+    if (CONSTANT_P (l->loc)
+       && (GET_CODE (l->loc) != CONST || !references_value_p (l->loc, 0)))
+      return;
+
   switch (GET_CODE (src))
     {
     case NOT:
@@ -5519,7 +5532,7 @@ add_stores (rtx loc, const_rtx expr, void *cuip)
       gcc_assert (oval != v);
       gcc_assert (REG_P (oloc) || MEM_P (oloc));
 
-      if (!cselib_preserved_value_p (oval))
+      if (oval && !cselib_preserved_value_p (oval))
        {
          micro_operation moa;
 
@@ -8216,9 +8229,14 @@ emit_note_insn_var_location (void **varp, void *data)
       /* Make sure that the call related notes come first.  */
       while (NEXT_INSN (insn)
             && NOTE_P (insn)
-            && NOTE_DURING_CALL_P (insn))
+            && ((NOTE_KIND (insn) == NOTE_INSN_VAR_LOCATION
+                 && NOTE_DURING_CALL_P (insn))
+                || NOTE_KIND (insn) == NOTE_INSN_CALL_ARG_LOCATION))
        insn = NEXT_INSN (insn);
-      if (NOTE_P (insn) && NOTE_DURING_CALL_P (insn))
+      if (NOTE_P (insn)
+         && ((NOTE_KIND (insn) == NOTE_INSN_VAR_LOCATION
+              && NOTE_DURING_CALL_P (insn))
+             || NOTE_KIND (insn) == NOTE_INSN_CALL_ARG_LOCATION))
        note = emit_note_after (NOTE_INSN_VAR_LOCATION, insn);
       else
        note = emit_note_before (NOTE_INSN_VAR_LOCATION, insn);