示例#1
0
void
set_nonzero_bits (tree name, const wide_int_ref &mask)
{
  gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name)));
  if (SSA_NAME_RANGE_INFO (name) == NULL)
    set_range_info (name, VR_RANGE,
		    TYPE_MIN_VALUE (TREE_TYPE (name)),
		    TYPE_MAX_VALUE (TREE_TYPE (name)));
  range_info_def *ri = SSA_NAME_RANGE_INFO (name);
  ri->set_nonzero_bits (mask);
}
示例#2
0
void
set_nonzero_bits (tree name, double_int mask)
{
  gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name)));
  if (SSA_NAME_RANGE_INFO (name) == NULL)
    set_range_info (name, VR_RANGE,
		    tree_to_double_int (TYPE_MIN_VALUE (TREE_TYPE (name))),
		    tree_to_double_int (TYPE_MAX_VALUE (TREE_TYPE (name))));
  range_info_def *ri = SSA_NAME_RANGE_INFO (name);
  ri->nonzero_bits
    = mask & double_int::mask (TYPE_PRECISION (TREE_TYPE (name)));
}
示例#3
0
/* Creates a duplicate of the range_info_def at RANGE_INFO for use by
   the SSA name NAME.  */
void
duplicate_ssa_name_range_info (tree name, struct range_info_def *range_info)
{
  struct range_info_def *new_range_info;

  gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name)));
  gcc_assert (!SSA_NAME_RANGE_INFO (name));

  if (!range_info)
    return;

  new_range_info = ggc_alloc_range_info_def ();
  *new_range_info = *range_info;

  SSA_NAME_RANGE_INFO (name) = new_range_info;
}
示例#4
0
enum value_range_type
get_range_info (tree name, double_int *min, double_int *max)
{
  enum value_range_type range_type;
  gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name)));
  gcc_assert (min && max);
  range_info_def *ri = SSA_NAME_RANGE_INFO (name);

  /* Return VR_VARYING for SSA_NAMEs with NULL RANGE_INFO or SSA_NAMEs
     with integral types width > 2 * HOST_BITS_PER_WIDE_INT precision.  */
  if (!ri || (GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (name)))
	      > 2 * HOST_BITS_PER_WIDE_INT))
    return VR_VARYING;

  /* If min > max, it is VR_ANTI_RANGE.  */
  if (ri->min.cmp (ri->max, TYPE_UNSIGNED (TREE_TYPE (name))) == 1)
    {
      /* VR_ANTI_RANGE ~[min, max] is encoded as [max + 1, min - 1].  */
      range_type = VR_ANTI_RANGE;
      *min = ri->max + double_int_one;
      *max = ri->min - double_int_one;
    }
  else
  {
    /* Otherwise (when min <= max), it is VR_RANGE.  */
    range_type = VR_RANGE;
    *min = ri->min;
    *max = ri->max;
  }
  return range_type;
}
示例#5
0
void
set_range_info (tree name, double_int min, double_int max)
{
  gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name)));
  range_info_def *ri = SSA_NAME_RANGE_INFO (name);

  /* Allocate if not available.  */
  if (ri == NULL)
    {
      ri = ggc_alloc_cleared_range_info_def ();
      SSA_NAME_RANGE_INFO (name) = ri;
    }

  /* Set the values.  */
  ri->min = min;
  ri->max = max;
}
示例#6
0
tree
make_ssa_name_fn (struct function *fn, tree var, gimple stmt)
{
  tree t;
  use_operand_p imm;

  gcc_assert (TREE_CODE (var) == VAR_DECL
	      || TREE_CODE (var) == PARM_DECL
	      || TREE_CODE (var) == RESULT_DECL
	      || (TYPE_P (var) && is_gimple_reg_type (var)));

  /* If our free list has an element, then use it.  */
  if (!vec_safe_is_empty (FREE_SSANAMES (fn)))
    {
      t = FREE_SSANAMES (fn)->pop ();
      if (GATHER_STATISTICS)
	ssa_name_nodes_reused++;

      /* The node was cleared out when we put it on the free list, so
	 there is no need to do so again here.  */
      gcc_assert (ssa_name (SSA_NAME_VERSION (t)) == NULL);
      (*SSANAMES (fn))[SSA_NAME_VERSION (t)] = t;
    }
  else
    {
      t = make_node (SSA_NAME);
      SSA_NAME_VERSION (t) = SSANAMES (fn)->length ();
      vec_safe_push (SSANAMES (fn), t);
      if (GATHER_STATISTICS)
	ssa_name_nodes_created++;
    }

  if (TYPE_P (var))
    {
      TREE_TYPE (t) = var;
      SET_SSA_NAME_VAR_OR_IDENTIFIER (t, NULL_TREE);
    }
  else
    {
      TREE_TYPE (t) = TREE_TYPE (var);
      SET_SSA_NAME_VAR_OR_IDENTIFIER (t, var);
    }
  SSA_NAME_DEF_STMT (t) = stmt;
  if (POINTER_TYPE_P (TREE_TYPE (t)))
    SSA_NAME_PTR_INFO (t) = NULL;
  else
    SSA_NAME_RANGE_INFO (t) = NULL;

  SSA_NAME_IN_FREE_LIST (t) = 0;
  SSA_NAME_IS_DEFAULT_DEF (t) = 0;
  imm = &(SSA_NAME_IMM_USE_NODE (t));
  imm->use = NULL;
  imm->prev = imm;
  imm->next = imm;
  imm->loc.ssa_name = t;

  return t;
}
示例#7
0
void
set_range_info (tree name, enum value_range_type range_type, double_int min,
		double_int max)
{
  gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name)));
  gcc_assert (range_type == VR_RANGE || range_type == VR_ANTI_RANGE);
  range_info_def *ri = SSA_NAME_RANGE_INFO (name);

  /* Allocate if not available.  */
  if (ri == NULL)
    {
      ri = ggc_alloc_cleared_range_info_def ();
      SSA_NAME_RANGE_INFO (name) = ri;
      ri->nonzero_bits = double_int::mask (TYPE_PRECISION (TREE_TYPE (name)));
    }

  /* Record the range type.  */
  if (SSA_NAME_RANGE_TYPE (name) != range_type)
    SSA_NAME_ANTI_RANGE_P (name) = (range_type == VR_ANTI_RANGE);

  /* Set the values.  */
  ri->min = min;
  ri->max = max;

  /* If it is a range, try to improve nonzero_bits from the min/max.  */
  if (range_type == VR_RANGE)
    {
      int prec = TYPE_PRECISION (TREE_TYPE (name));
      double_int xorv;

      min = min.zext (prec);
      max = max.zext (prec);
      xorv = min ^ max;
      if (xorv.high)
	xorv = double_int::mask (2 * HOST_BITS_PER_WIDE_INT
				 - clz_hwi (xorv.high));
      else if (xorv.low)
	xorv = double_int::mask (HOST_BITS_PER_WIDE_INT
				 - clz_hwi (xorv.low));
      ri->nonzero_bits = ri->nonzero_bits & (min | xorv);
    }
}
示例#8
0
/* Creates a duplicate of the range_info_def at RANGE_INFO of type
   RANGE_TYPE for use by the SSA name NAME.  */
void
duplicate_ssa_name_range_info (tree name, enum value_range_type range_type,
			       struct range_info_def *range_info)
{
  struct range_info_def *new_range_info;

  gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name)));
  gcc_assert (!SSA_NAME_RANGE_INFO (name));
  gcc_assert (!SSA_NAME_ANTI_RANGE_P (name));

  if (!range_info)
    return;

  new_range_info = ggc_alloc_range_info_def ();
  *new_range_info = *range_info;

  gcc_assert (range_type == VR_RANGE || range_type == VR_ANTI_RANGE);
  SSA_NAME_ANTI_RANGE_P (name) = (range_type == VR_ANTI_RANGE);
  SSA_NAME_RANGE_INFO (name) = new_range_info;
}
示例#9
0
void
reset_flow_sensitive_info (tree name)
{
  if (POINTER_TYPE_P (TREE_TYPE (name)))
    {
      /* points-to info is not flow-sensitive.  */
      if (SSA_NAME_PTR_INFO (name))
	mark_ptr_info_alignment_unknown (SSA_NAME_PTR_INFO (name));
    }
  else
    SSA_NAME_RANGE_INFO (name) = NULL;
}
示例#10
0
/* Creates a duplicate of the range_info_def at RANGE_INFO of type
   RANGE_TYPE for use by the SSA name NAME.  */
void
duplicate_ssa_name_range_info (tree name, enum value_range_type range_type,
			       struct range_info_def *range_info)
{
  struct range_info_def *new_range_info;

  gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name)));
  gcc_assert (!SSA_NAME_RANGE_INFO (name));
  gcc_assert (!SSA_NAME_ANTI_RANGE_P (name));

  if (!range_info)
    return;

  unsigned int precision = TYPE_PRECISION (TREE_TYPE (name));
  size_t size = (sizeof (range_info_def)
		 + trailing_wide_ints <3>::extra_size (precision));
  new_range_info = static_cast<range_info_def *> (ggc_internal_alloc (size));
  memcpy (new_range_info, range_info, size);

  gcc_assert (range_type == VR_RANGE || range_type == VR_ANTI_RANGE);
  SSA_NAME_ANTI_RANGE_P (name) = (range_type == VR_ANTI_RANGE);
  SSA_NAME_RANGE_INFO (name) = new_range_info;
}
示例#11
0
void
set_range_info (tree name, enum value_range_type range_type,
		const wide_int_ref &min, const wide_int_ref &max)
{
  gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name)));
  gcc_assert (range_type == VR_RANGE || range_type == VR_ANTI_RANGE);
  range_info_def *ri = SSA_NAME_RANGE_INFO (name);
  unsigned int precision = TYPE_PRECISION (TREE_TYPE (name));

  /* Allocate if not available.  */
  if (ri == NULL)
    {
      size_t size = (sizeof (range_info_def)
		     + trailing_wide_ints <3>::extra_size (precision));
      ri = static_cast<range_info_def *> (ggc_internal_alloc (size));
      ri->ints.set_precision (precision);
      SSA_NAME_RANGE_INFO (name) = ri;
      ri->set_nonzero_bits (wi::shwi (-1, precision));
    }

  /* Record the range type.  */
  if (SSA_NAME_RANGE_TYPE (name) != range_type)
    SSA_NAME_ANTI_RANGE_P (name) = (range_type == VR_ANTI_RANGE);

  /* Set the values.  */
  ri->set_min (min);
  ri->set_max (max);

  /* If it is a range, try to improve nonzero_bits from the min/max.  */
  if (range_type == VR_RANGE)
    {
      wide_int xorv = ri->get_min () ^ ri->get_max ();
      if (xorv != 0)
	xorv = wi::mask (precision - wi::clz (xorv), false, precision);
      ri->set_nonzero_bits (ri->get_nonzero_bits () & (ri->get_min () | xorv));
    }
}
示例#12
0
enum value_range_type
get_range_info (const_tree name, double_int *min, double_int *max)
{
  gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name)));
  gcc_assert (min && max);
  range_info_def *ri = SSA_NAME_RANGE_INFO (name);

  /* Return VR_VARYING for SSA_NAMEs with NULL RANGE_INFO or SSA_NAMEs
     with integral types width > 2 * HOST_BITS_PER_WIDE_INT precision.  */
  if (!ri || (GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (name)))
	      > 2 * HOST_BITS_PER_WIDE_INT))
    return VR_VARYING;

  *min = ri->min;
  *max = ri->max;
  return SSA_NAME_RANGE_TYPE (name);
}
示例#13
0
wide_int
get_nonzero_bits (const_tree name)
{
  unsigned int precision = TYPE_PRECISION (TREE_TYPE (name));
  if (POINTER_TYPE_P (TREE_TYPE (name)))
    {
      struct ptr_info_def *pi = SSA_NAME_PTR_INFO (name);
      if (pi && pi->align)
	return wi::shwi (-(HOST_WIDE_INT) pi->align
			 | (HOST_WIDE_INT) pi->misalign, precision);
      return wi::shwi (-1, precision);
    }

  range_info_def *ri = SSA_NAME_RANGE_INFO (name);
  if (!ri)
    return wi::shwi (-1, precision);

  return ri->get_nonzero_bits ();
}
示例#14
0
tree
duplicate_ssa_name_fn (struct function *fn, tree name, gimple stmt)
{
  tree new_name = copy_ssa_name_fn (fn, name, stmt);
  if (POINTER_TYPE_P (TREE_TYPE (name)))
    {
      struct ptr_info_def *old_ptr_info = SSA_NAME_PTR_INFO (name);

      if (old_ptr_info)
	duplicate_ssa_name_ptr_info (new_name, old_ptr_info);
    }
  else
    {
      struct range_info_def *old_range_info = SSA_NAME_RANGE_INFO (name);

      if (old_range_info)
	duplicate_ssa_name_range_info (new_name, old_range_info);
    }

  return new_name;
}
示例#15
0
double_int
get_nonzero_bits (const_tree name)
{
  if (POINTER_TYPE_P (TREE_TYPE (name)))
    {
      struct ptr_info_def *pi = SSA_NAME_PTR_INFO (name);
      if (pi && pi->align)
	{
	  double_int al = double_int::from_uhwi (pi->align - 1);
	  return ((double_int::mask (TYPE_PRECISION (TREE_TYPE (name))) & ~al)
		  | double_int::from_uhwi (pi->misalign));
	}
      return double_int_minus_one;
    }

  range_info_def *ri = SSA_NAME_RANGE_INFO (name);
  if (!ri || (GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (name)))
	      > 2 * HOST_BITS_PER_WIDE_INT))
    return double_int_minus_one;

  return ri->nonzero_bits;
}
示例#16
0
static bool
fini_copy_prop (void)
{
  unsigned i;

  /* Set the final copy-of value for each variable by traversing the
     copy-of chains.  */
  for (i = 1; i < num_ssa_names; i++)
    {
      tree var = ssa_name (i);
      if (!var
	  || !copy_of[i].value
	  || copy_of[i].value == var)
	continue;

      /* In theory the points-to solution of all members of the
         copy chain is their intersection.  For now we do not bother
	 to compute this but only make sure we do not lose points-to
	 information completely by setting the points-to solution
	 of the representative to the first solution we find if
	 it doesn't have one already.  */
      if (copy_of[i].value != var
	  && TREE_CODE (copy_of[i].value) == SSA_NAME)
	{
	  basic_block copy_of_bb
	    = gimple_bb (SSA_NAME_DEF_STMT (copy_of[i].value));
	  basic_block var_bb = gimple_bb (SSA_NAME_DEF_STMT (var));
	  if (POINTER_TYPE_P (TREE_TYPE (var))
	      && SSA_NAME_PTR_INFO (var)
	      && !SSA_NAME_PTR_INFO (copy_of[i].value))
	    {
	      duplicate_ssa_name_ptr_info (copy_of[i].value,
					   SSA_NAME_PTR_INFO (var));
	      /* Points-to information is cfg insensitive,
		 but alignment info might be cfg sensitive, if it
		 e.g. is derived from VRP derived non-zero bits.
		 So, do not copy alignment info if the two SSA_NAMEs
		 aren't defined in the same basic block.  */
	      if (var_bb != copy_of_bb)
		mark_ptr_info_alignment_unknown
				(SSA_NAME_PTR_INFO (copy_of[i].value));
	    }
	  else if (!POINTER_TYPE_P (TREE_TYPE (var))
		   && SSA_NAME_RANGE_INFO (var)
		   && !SSA_NAME_RANGE_INFO (copy_of[i].value)
		   && var_bb == copy_of_bb)
	    duplicate_ssa_name_range_info (copy_of[i].value,
					   SSA_NAME_RANGE_TYPE (var),
					   SSA_NAME_RANGE_INFO (var));
	}
    }

  bool changed = substitute_and_fold (get_value, NULL, true);
  if (changed)
    {
      free_numbers_of_iterations_estimates ();
      if (scev_initialized_p ())
	scev_reset ();
    }

  free (copy_of);

  return changed;
}