예제 #1
0
static bool
idx_analyze_ref (tree base, tree *index, void *data)
{
    struct ar_data *ar_data = data;
    tree ibase, step, stepsize;
    HOST_WIDE_INT istep, idelta = 0, imult = 1;
    affine_iv iv;

    if (TREE_CODE (base) == MISALIGNED_INDIRECT_REF
            || TREE_CODE (base) == ALIGN_INDIRECT_REF)
        return false;

    if (!simple_iv (ar_data->loop, ar_data->stmt, *index, &iv, false))
        return false;
    ibase = iv.base;
    step = iv.step;

    if (zero_p (step))
        istep = 0;
    else
    {
        if (!cst_and_fits_in_hwi (step))
            return false;
        istep = int_cst_value (step);
    }

    if (TREE_CODE (ibase) == PLUS_EXPR
            && cst_and_fits_in_hwi (TREE_OPERAND (ibase, 1)))
    {
        idelta = int_cst_value (TREE_OPERAND (ibase, 1));
        ibase = TREE_OPERAND (ibase, 0);
    }
    if (cst_and_fits_in_hwi (ibase))
    {
        idelta += int_cst_value (ibase);
        ibase = build_int_cst (TREE_TYPE (ibase), 0);
    }

    if (TREE_CODE (base) == ARRAY_REF)
    {
        stepsize = array_ref_element_size (base);
        if (!cst_and_fits_in_hwi (stepsize))
            return false;
        imult = int_cst_value (stepsize);

        istep *= imult;
        idelta *= imult;
    }

    *ar_data->step += istep;
    *ar_data->delta += idelta;
    *index = ibase;

    return true;
}
예제 #2
0
static bool
constant_after_peeling (tree op, gimple *stmt, struct loop *loop)
{
  affine_iv iv;

  if (is_gimple_min_invariant (op))
    return true;

  /* We can still fold accesses to constant arrays when index is known.  */
  if (TREE_CODE (op) != SSA_NAME)
    {
      tree base = op;

      /* First make fast look if we see constant array inside.  */
      while (handled_component_p (base))
	base = TREE_OPERAND (base, 0);
      if ((DECL_P (base)
	   && ctor_for_folding (base) != error_mark_node)
	  || CONSTANT_CLASS_P (base))
	{
	  /* If so, see if we understand all the indices.  */
	  base = op;
	  while (handled_component_p (base))
	    {
	      if (TREE_CODE (base) == ARRAY_REF
		  && !constant_after_peeling (TREE_OPERAND (base, 1), stmt, loop))
		return false;
	      base = TREE_OPERAND (base, 0);
	    }
	  return true;
	}
      return false;
    }

  /* Induction variables are constants.  */
  if (!simple_iv (loop, loop_containing_stmt (stmt), op, &iv, false))
    return false;
  if (!is_gimple_min_invariant (iv.base))
    return false;
  if (!is_gimple_min_invariant (iv.step))
    return false;
  return true;
}