Пример #1
0
void
copy_ref_info (tree new_ref, tree old_ref)
{
  tree new_ptr_base = NULL_TREE;

  gcc_assert (TREE_CODE (new_ref) == MEM_REF
	      || TREE_CODE (new_ref) == TARGET_MEM_REF);

  TREE_SIDE_EFFECTS (new_ref) = TREE_SIDE_EFFECTS (old_ref);
  TREE_THIS_VOLATILE (new_ref) = TREE_THIS_VOLATILE (old_ref);

  new_ptr_base = TREE_OPERAND (new_ref, 0);

  /* We can transfer points-to information from an old pointer
     or decl base to the new one.  */
  if (new_ptr_base
      && TREE_CODE (new_ptr_base) == SSA_NAME
      && !SSA_NAME_PTR_INFO (new_ptr_base))
    {
      tree base = get_base_address (old_ref);
      if (!base)
	;
      else if ((TREE_CODE (base) == MEM_REF
		|| TREE_CODE (base) == TARGET_MEM_REF)
	       && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME
	       && SSA_NAME_PTR_INFO (TREE_OPERAND (base, 0)))
	{
	  struct ptr_info_def *new_pi;
	  unsigned int align, misalign;

	  duplicate_ssa_name_ptr_info
	    (new_ptr_base, SSA_NAME_PTR_INFO (TREE_OPERAND (base, 0)));
	  new_pi = SSA_NAME_PTR_INFO (new_ptr_base);
	  /* We have to be careful about transferring alignment information.  */
	  if (get_ptr_info_alignment (new_pi, &align, &misalign)
	      && TREE_CODE (old_ref) == MEM_REF
	      && !(TREE_CODE (new_ref) == TARGET_MEM_REF
		   && (TMR_INDEX2 (new_ref)
		       || (TMR_STEP (new_ref)
			   && (TREE_INT_CST_LOW (TMR_STEP (new_ref))
			       < align)))))
	    {
	      unsigned int inc = (mem_ref_offset (old_ref)
				  - mem_ref_offset (new_ref)).low;
	      adjust_ptr_info_misalignment (new_pi, inc);
	    }
	  else
	    mark_ptr_info_alignment_unknown (new_pi);
	}
      else if (TREE_CODE (base) == VAR_DECL
	       || TREE_CODE (base) == PARM_DECL
	       || TREE_CODE (base) == RESULT_DECL)
	{
	  struct ptr_info_def *pi = get_ptr_info (new_ptr_base);
	  pt_solution_set_var (&pi->pt, base);
	}
    }
}
void
merge_alias_info (tree orig_name, tree new_name)
{
    tree new_sym = SSA_NAME_VAR (new_name);
    tree orig_sym = SSA_NAME_VAR (orig_name);
    var_ann_t new_ann = var_ann (new_sym);
    var_ann_t orig_ann = var_ann (orig_sym);

    /* No merging necessary when memory partitions are involved.  */
    if (factoring_name_p (new_name))
    {
        gcc_assert (!is_gimple_reg (orig_sym));
        return;
    }
    else if (factoring_name_p (orig_name))
    {
        gcc_assert (!is_gimple_reg (new_sym));
        return;
    }

    gcc_assert (POINTER_TYPE_P (TREE_TYPE (orig_name))
                && POINTER_TYPE_P (TREE_TYPE (new_name)));

#if defined ENABLE_CHECKING
    gcc_assert (useless_type_conversion_p (TREE_TYPE (orig_name),
                                           TREE_TYPE (new_name)));

    /* Check that flow-sensitive information is compatible.  Notice that
       we may not merge flow-sensitive information here.  This function
       is called when propagating equivalences dictated by the IL, like
       a copy operation P_i = Q_j, and from equivalences dictated by
       control-flow, like if (P_i == Q_j).

       In the former case, P_i and Q_j are equivalent in every block
       dominated by the assignment, so their flow-sensitive information
       is always the same.  However, in the latter case, the pointers
       P_i and Q_j are only equivalent in one of the sub-graphs out of
       the predicate, so their flow-sensitive information is not the
       same in every block dominated by the predicate.

       Since we cannot distinguish one case from another in this
       function, we can only make sure that if P_i and Q_j have
       flow-sensitive information, they should be compatible.

       As callers of merge_alias_info are supposed to call may_propagate_copy
       first, the following check is redundant.  Thus, only do it if checking
       is enabled.  */
    if (SSA_NAME_PTR_INFO (orig_name) && SSA_NAME_PTR_INFO (new_name))
    {
        struct ptr_info_def *orig_ptr_info = SSA_NAME_PTR_INFO (orig_name);
        struct ptr_info_def *new_ptr_info = SSA_NAME_PTR_INFO (new_name);

        /* Note that pointer NEW and ORIG may actually have different
        pointed-to variables (e.g., PR 18291 represented in
         testsuite/gcc.c-torture/compile/pr18291.c).  However, since
         NEW is being copy-propagated into ORIG, it must always be
         true that the pointed-to set for pointer NEW is the same, or
         a subset, of the pointed-to set for pointer ORIG.  If this
         isn't the case, we shouldn't have been able to do the
         propagation of NEW into ORIG.  */
        if (orig_ptr_info->name_mem_tag
                && new_ptr_info->name_mem_tag
                && orig_ptr_info->pt_vars
                && new_ptr_info->pt_vars)
            gcc_assert (bitmap_intersect_p (new_ptr_info->pt_vars,
                                            orig_ptr_info->pt_vars));
    }
#endif

    /* Synchronize the symbol tags.  If both pointers had a tag and they
       are different, then something has gone wrong.  Symbol tags can
       always be merged because they are flow insensitive, all the SSA
       names of the same base DECL share the same symbol tag.  */
    if (new_ann->symbol_mem_tag == NULL_TREE)
        new_ann->symbol_mem_tag = orig_ann->symbol_mem_tag;
    else if (orig_ann->symbol_mem_tag == NULL_TREE)
        orig_ann->symbol_mem_tag = new_ann->symbol_mem_tag;
    else
        gcc_assert (new_ann->symbol_mem_tag == orig_ann->symbol_mem_tag);

    /* Copy flow-sensitive alias information in case that NEW_NAME
       didn't get a NMT but was set to pt_anything for optimization
       purposes.  In case ORIG_NAME has a NMT we can safely use its
       flow-sensitive alias information as a conservative estimate.  */
    if (SSA_NAME_PTR_INFO (orig_name)
            && SSA_NAME_PTR_INFO (orig_name)->name_mem_tag
            && (!SSA_NAME_PTR_INFO (new_name)
                || !SSA_NAME_PTR_INFO (new_name)->name_mem_tag))
    {
        struct ptr_info_def *orig_ptr_info = SSA_NAME_PTR_INFO (orig_name);
        struct ptr_info_def *new_ptr_info = get_ptr_info (new_name);
        memcpy (new_ptr_info, orig_ptr_info, sizeof (struct ptr_info_def));
    }
}