OSDN Git Service

2010-10-26 Jerry DeLisle <jvdelisle@gcc.gnu.org>
[pf3gnuchains/gcc-fork.git] / gcc / var-tracking.c
index 33061c5..c3d5077 100644 (file)
@@ -910,6 +910,16 @@ adjust_mems (rtx loc, const_rtx old_rtx, void *data)
        return use_narrower_mode (SUBREG_REG (tem), GET_MODE (tem),
                                  GET_MODE (SUBREG_REG (tem)));
       return tem;
+    case ASM_OPERANDS:
+      /* Don't do any replacements in second and following
+        ASM_OPERANDS of inline-asm with multiple sets.
+        ASM_OPERANDS_INPUT_VEC, ASM_OPERANDS_INPUT_CONSTRAINT_VEC
+        and ASM_OPERANDS_LABEL_VEC need to be equal between
+        all the ASM_OPERANDs in the insn and adjust_insn will
+        fix this up.  */
+      if (ASM_OPERANDS_OUTPUT_IDX (loc) != 0)
+       return loc;
+      break;
     default:
       break;
     }
@@ -960,7 +970,54 @@ adjust_insn (basic_block bb, rtx insn)
   note_stores (PATTERN (insn), adjust_mem_stores, &amd);
 
   amd.store = false;
-  note_uses (&PATTERN (insn), adjust_mem_uses, &amd);
+  if (GET_CODE (PATTERN (insn)) == PARALLEL
+      && asm_noperands (PATTERN (insn)) > 0
+      && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == SET)
+    {
+      rtx body, set0;
+      int i;
+
+      /* inline-asm with multiple sets is tiny bit more complicated,
+        because the 3 vectors in ASM_OPERANDS need to be shared between
+        all ASM_OPERANDS in the instruction.  adjust_mems will
+        not touch ASM_OPERANDS other than the first one, asm_noperands
+        test above needs to be called before that (otherwise it would fail)
+        and afterwards this code fixes it up.  */
+      note_uses (&PATTERN (insn), adjust_mem_uses, &amd);
+      body = PATTERN (insn);
+      set0 = XVECEXP (body, 0, 0);
+      gcc_checking_assert (GET_CODE (set0) == SET
+                          && GET_CODE (SET_SRC (set0)) == ASM_OPERANDS
+                          && ASM_OPERANDS_OUTPUT_IDX (SET_SRC (set0)) == 0);
+      for (i = 1; i < XVECLEN (body, 0); i++)
+       if (GET_CODE (XVECEXP (body, 0, i)) != SET)
+         break;
+       else
+         {
+           set = XVECEXP (body, 0, i);
+           gcc_checking_assert (GET_CODE (SET_SRC (set)) == ASM_OPERANDS
+                                && ASM_OPERANDS_OUTPUT_IDX (SET_SRC (set))
+                                   == i);
+           if (ASM_OPERANDS_INPUT_VEC (SET_SRC (set))
+               != ASM_OPERANDS_INPUT_VEC (SET_SRC (set0))
+               || ASM_OPERANDS_INPUT_CONSTRAINT_VEC (SET_SRC (set))
+                  != ASM_OPERANDS_INPUT_CONSTRAINT_VEC (SET_SRC (set0))
+               || ASM_OPERANDS_LABEL_VEC (SET_SRC (set))
+                  != ASM_OPERANDS_LABEL_VEC (SET_SRC (set0)))
+             {
+               rtx newsrc = shallow_copy_rtx (SET_SRC (set));
+               ASM_OPERANDS_INPUT_VEC (newsrc)
+                 = ASM_OPERANDS_INPUT_VEC (SET_SRC (set0));
+               ASM_OPERANDS_INPUT_CONSTRAINT_VEC (newsrc)
+                 = ASM_OPERANDS_INPUT_CONSTRAINT_VEC (SET_SRC (set0));
+               ASM_OPERANDS_LABEL_VEC (newsrc)
+                 = ASM_OPERANDS_LABEL_VEC (SET_SRC (set0));
+               validate_change (NULL_RTX, &SET_SRC (set), newsrc, true);
+             }
+         }
+    }
+  else
+    note_uses (&PATTERN (insn), adjust_mem_uses, &amd);
 
   /* For read-only MEMs containing some constant, prefer those
      constants.  */
@@ -1018,9 +1075,7 @@ dv_is_value_p (decl_or_value dv)
 static inline tree
 dv_as_decl (decl_or_value dv)
 {
-#ifdef ENABLE_CHECKING
-  gcc_assert (dv_is_decl_p (dv));
-#endif
+  gcc_checking_assert (dv_is_decl_p (dv));
   return (tree) dv;
 }
 
@@ -1028,9 +1083,7 @@ dv_as_decl (decl_or_value dv)
 static inline rtx
 dv_as_value (decl_or_value dv)
 {
-#ifdef ENABLE_CHECKING
-  gcc_assert (dv_is_value_p (dv));
-#endif
+  gcc_checking_assert (dv_is_value_p (dv));
   return (rtx)dv;
 }
 
@@ -1079,9 +1132,7 @@ dv_from_decl (tree decl)
 {
   decl_or_value dv;
   dv = decl;
-#ifdef ENABLE_CHECKING
-  gcc_assert (dv_is_decl_p (dv));
-#endif
+  gcc_checking_assert (dv_is_decl_p (dv));
   return dv;
 }
 
@@ -1091,9 +1142,7 @@ dv_from_value (rtx value)
 {
   decl_or_value dv;
   dv = value;
-#ifdef ENABLE_CHECKING
-  gcc_assert (dv_is_value_p (dv));
-#endif
+  gcc_checking_assert (dv_is_value_p (dv));
   return dv;
 }
 
@@ -2125,10 +2174,8 @@ variable_union (variable src, dataflow_set *set)
              nnode->next = dnode;
              dnode = nnode;
            }
-#ifdef ENABLE_CHECKING
          else if (r == 0)
-           gcc_assert (rtx_equal_p (dnode->loc, snode->loc));
-#endif
+           gcc_checking_assert (rtx_equal_p (dnode->loc, snode->loc));
 
          if (r >= 0)
            snode = snode->next;
@@ -2492,17 +2539,13 @@ find_loc_in_1pdv (rtx loc, variable var, htab_t vars)
   if (!var)
     return NULL;
 
-#ifdef ENABLE_CHECKING
-  gcc_assert (dv_onepart_p (var->dv));
-#endif
+  gcc_checking_assert (dv_onepart_p (var->dv));
 
   if (!var->n_var_parts)
     return NULL;
 
-#ifdef ENABLE_CHECKING
-  gcc_assert (var->var_part[0].offset == 0);
-  gcc_assert (loc != dv_as_opaque (var->dv));
-#endif
+  gcc_checking_assert (var->var_part[0].offset == 0);
+  gcc_checking_assert (loc != dv_as_opaque (var->dv));
 
   loc_code = GET_CODE (loc);
   for (node = var->var_part[0].loc_chain; node; node = node->next)
@@ -2534,20 +2577,16 @@ find_loc_in_1pdv (rtx loc, variable var, htab_t vars)
          while (node->next && GET_CODE (node->next->loc) == VALUE)
            {
              node = node->next;
-#ifdef ENABLE_CHECKING
-             gcc_assert (!canon_value_cmp (node->loc,
-                                           dv_as_value (var->dv)));
-#endif
+             gcc_checking_assert (!canon_value_cmp (node->loc,
+                                                    dv_as_value (var->dv)));
              if (loc == node->loc)
                return node;
            }
          continue;
        }
 
-#ifdef ENABLE_CHECKING
-      gcc_assert (node == var->var_part[0].loc_chain);
-      gcc_assert (!node->next);
-#endif
+      gcc_checking_assert (node == var->var_part[0].loc_chain);
+      gcc_checking_assert (!node->next);
 
       dv = dv_from_value (node->loc);
       rvar = (variable) htab_find_with_hash (vars, dv, dv_htab_hash (dv));
@@ -2615,15 +2654,11 @@ intersect_loc_chains (rtx val, location_chain *dest, struct dfset_merge *dsm,
     {
       location_chain s2node;
 
-#ifdef ENABLE_CHECKING
-      gcc_assert (dv_onepart_p (s2var->dv));
-#endif
+      gcc_checking_assert (dv_onepart_p (s2var->dv));
 
       if (s2var->n_var_parts)
        {
-#ifdef ENABLE_CHECKING
-         gcc_assert (s2var->var_part[0].offset == 0);
-#endif
+         gcc_checking_assert (s2var->var_part[0].offset == 0);
          s2node = s2var->var_part[0].loc_chain;
 
          for (; s1node && s2node;
@@ -2772,10 +2807,8 @@ loc_cmp (rtx x, rtx y)
       if (DEBUG_TEMP_UID (DEBUG_EXPR_TREE_DECL (x))
          < DEBUG_TEMP_UID (DEBUG_EXPR_TREE_DECL (y)))
        return -1;
-#ifdef ENABLE_CHECKING
-      gcc_assert (DEBUG_TEMP_UID (DEBUG_EXPR_TREE_DECL (x))
-                 > DEBUG_TEMP_UID (DEBUG_EXPR_TREE_DECL (y)));
-#endif
+      gcc_checking_assert (DEBUG_TEMP_UID (DEBUG_EXPR_TREE_DECL (x))
+                          > DEBUG_TEMP_UID (DEBUG_EXPR_TREE_DECL (y)));
       return 1;
     }
 
@@ -3535,10 +3568,9 @@ variable_merge_over_cur (variable s1var, struct dfset_merge *dsm)
       dstslot = shared_hash_find_slot_noinsert_1 (dst->vars, dv, dvhash);
       gcc_assert (*dstslot == dvar);
       canonicalize_values_star (dstslot, dst);
-#ifdef ENABLE_CHECKING
-      gcc_assert (dstslot
-                 == shared_hash_find_slot_noinsert_1 (dst->vars, dv, dvhash));
-#endif
+      gcc_checking_assert (dstslot
+                          == shared_hash_find_slot_noinsert_1 (dst->vars,
+                                                               dv, dvhash));
       dvar = (variable)*dstslot;
     }
   else
@@ -3603,11 +3635,9 @@ variable_merge_over_cur (variable s1var, struct dfset_merge *dsm)
          dstslot = shared_hash_find_slot_noinsert_1 (dst->vars, dv, dvhash);
          gcc_assert (*dstslot == dvar);
          canonicalize_values_star (dstslot, dst);
-#ifdef ENABLE_CHECKING
-         gcc_assert (dstslot
-                     == shared_hash_find_slot_noinsert_1 (dst->vars,
-                                                          dv, dvhash));
-#endif
+         gcc_checking_assert (dstslot
+                              == shared_hash_find_slot_noinsert_1 (dst->vars,
+                                                                   dv, dvhash));
          dvar = (variable)*dstslot;
        }
     }
@@ -5187,16 +5217,19 @@ reverse_op (rtx val, const_rtx expr)
     case XOR:
     case NOT:
     case NEG:
+      if (!REG_P (XEXP (src, 0)))
+       return NULL_RTX;
+      break;
     case SIGN_EXTEND:
     case ZERO_EXTEND:
+      if (!REG_P (XEXP (src, 0)) && !MEM_P (XEXP (src, 0)))
+       return NULL_RTX;
       break;
     default:
       return NULL_RTX;
     }
 
-  if (!REG_P (XEXP (src, 0))
-      || !SCALAR_INT_MODE_P (GET_MODE (src))
-      || XEXP (src, 0) == cfa_base_rtx)
+  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);
@@ -5698,7 +5731,7 @@ compute_bb_dataflow (basic_block bb)
   dataflow_set_copy (&old_out, out);
   dataflow_set_copy (out, in);
 
-  for (i = 0; VEC_iterate (micro_operation, VTI (bb)->mos, i, mo); i++)
+  FOR_EACH_VEC_ELT (micro_operation, VTI (bb)->mos, i, mo)
     {
       rtx insn = mo->insn;
 
@@ -7043,7 +7076,7 @@ vt_expand_loc (rtx loc, htab_t vars)
   data.vars = vars;
   data.dummy = false;
   data.cur_loc_changed = false;
-  loc = cselib_expand_value_rtx_cb (loc, scratch_regs, 5,
+  loc = cselib_expand_value_rtx_cb (loc, scratch_regs, 8,
                                    vt_expand_loc_callback, &data);
 
   if (loc && MEM_P (loc))
@@ -7064,7 +7097,7 @@ vt_expand_loc_dummy (rtx loc, htab_t vars, bool *pcur_loc_changed)
   data.vars = vars;
   data.dummy = true;
   data.cur_loc_changed = false;
-  ret = cselib_dummy_expand_value_rtx_cb (loc, scratch_regs, 5,
+  ret = cselib_dummy_expand_value_rtx_cb (loc, scratch_regs, 8,
                                          vt_expand_loc_callback, &data);
   *pcur_loc_changed = data.cur_loc_changed;
   return ret;
@@ -7073,6 +7106,19 @@ vt_expand_loc_dummy (rtx loc, htab_t vars, bool *pcur_loc_changed)
 #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
@@ -7271,9 +7317,22 @@ emit_note_insn_var_location (void **varp, void *data)
       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);
-         gcc_assert (rtx_equal_p (PAT_VAR_LOCATION_LOC (pnote),
-                                  PAT_VAR_LOCATION_LOC (note_vl)));
+         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;
     }
@@ -7623,7 +7682,7 @@ emit_notes_in_bb (basic_block bb, dataflow_set *set)
   dataflow_set_clear (set);
   dataflow_set_copy (set, &VTI (bb)->in);
 
-  for (i = 0; VEC_iterate (micro_operation, VTI (bb)->mos, i, mo); i++)
+  FOR_EACH_VEC_ELT (micro_operation, VTI (bb)->mos, i, mo)
     {
       rtx insn = mo->insn;
 
@@ -7918,7 +7977,7 @@ vt_emit_notes (void)
       unsigned int i;
       rtx val;
 
-      for (i = 0; VEC_iterate (rtx, preserved_values, i, val); i++)
+      FOR_EACH_VEC_ELT (rtx, preserved_values, i, val)
        add_cselib_value_chains (dv_from_value (val));
       changed_variables_stack = VEC_alloc (variable, heap, 40);
       changed_values_stack = VEC_alloc (rtx, heap, 40);
@@ -7948,7 +8007,7 @@ vt_emit_notes (void)
       unsigned int i;
       rtx val;
 
-      for (i = 0; VEC_iterate (rtx, preserved_values, i, val); i++)
+      FOR_EACH_VEC_ELT (rtx, preserved_values, i, val)
        remove_cselib_value_chains (dv_from_value (val));
       gcc_assert (htab_elements (value_chains) == 0);
     }
@@ -8002,7 +8061,7 @@ vt_add_function_parameters (void)
   tree parm;
 
   for (parm = DECL_ARGUMENTS (current_function_decl);
-       parm; parm = TREE_CHAIN (parm))
+       parm; parm = DECL_CHAIN (parm))
     {
       rtx decl_rtl = DECL_RTL_IF_SET (parm);
       rtx incoming = DECL_INCOMING_RTL (parm);