#include "config.h"
#include "system.h"
#include "coretypes.h"
-#include "tm.h"
-#include "ggc.h"
-#include "tree.h"
-#include "basic-block.h"
-#include "tree-pretty-print.h"
#include "gimple-pretty-print.h"
#include "tree-flow.h"
-#include "tree-dump.h"
-#include "timevar.h"
#include "cfgloop.h"
#include "tree-chrec.h"
#include "tree-scalar-evolution.h"
#include "tree-pass.h"
-#include "flags.h"
#include "params.h"
static tree analyze_scalar_evolution_1 (struct loop *, tree, tree);
if (is_gimple_min_invariant (chrec))
return false;
- if (TREE_CODE (chrec) == VAR_DECL
- || TREE_CODE (chrec) == PARM_DECL
- || TREE_CODE (chrec) == FUNCTION_DECL
- || TREE_CODE (chrec) == LABEL_DECL
- || TREE_CODE (chrec) == RESULT_DECL
- || TREE_CODE (chrec) == FIELD_DECL)
- return true;
-
if (TREE_CODE (chrec) == SSA_NAME)
{
- gimple def = SSA_NAME_DEF_STMT (chrec);
- struct loop *def_loop = loop_containing_stmt (def);
- struct loop *loop = get_loop (loop_nb);
+ gimple def;
+ loop_p def_loop, loop;
+
+ if (SSA_NAME_IS_DEFAULT_DEF (chrec))
+ return false;
+
+ def = SSA_NAME_DEF_STMT (chrec);
+ def_loop = loop_containing_stmt (def);
+ loop = get_loop (loop_nb);
if (def_loop == NULL)
return false;
return t_false;
/* Give up if the path is longer than the MAX that we allow. */
- if (limit > PARAM_VALUE (PARAM_SCEV_MAX_EXPR_SIZE))
+ if (limit > PARAM_VALUE (PARAM_SCEV_MAX_EXPR_COMPLEXITY))
return t_dont_know;
def_loop = loop_containing_stmt (def);
return chrec_convert (type, analyze_scalar_evolution (loop, rhs1),
at_stmt);
}
-
- return chrec_dont_know;
}
switch (code)
{
+ case ADDR_EXPR:
+ /* Handle &MEM[ptr + CST] which is equivalent to POINTER_PLUS_EXPR. */
+ if (TREE_CODE (TREE_OPERAND (rhs1, 0)) != MEM_REF)
+ {
+ res = chrec_dont_know;
+ break;
+ }
+
+ rhs2 = TREE_OPERAND (TREE_OPERAND (rhs1, 0), 1);
+ rhs1 = TREE_OPERAND (TREE_OPERAND (rhs1, 0), 0);
+ /* Fall through. */
+
case POINTER_PLUS_EXPR:
chrec1 = analyze_scalar_evolution (loop, rhs1);
chrec2 = analyze_scalar_evolution (loop, rhs2);
struct loop *def_loop,
tree ev)
{
+ bool val;
tree res;
+
if (def_loop == wrto_loop)
return ev;
def_loop = superloop_at_depth (def_loop, loop_depth (wrto_loop) + 1);
res = compute_overall_effect_of_inner_loop (def_loop, ev);
+ if (no_evolution_in_loop_p (res, wrto_loop->num, &val) && val)
+ return res;
+
return analyze_scalar_evolution_1 (wrto_loop, res, chrec_not_analyzed_yet);
}
/* Analyze all the parameters of the chrec, between INSTANTIATE_BELOW
and EVOLUTION_LOOP, that were left under a symbolic form.
+ "CHREC" is an array reference to be instantiated.
+
+ CACHE is the cache of already instantiated values.
+
+ FOLD_CONVERSIONS should be set to true when the conversions that
+ may wrap in signed/pointer type are folded, as long as the value of
+ the chrec is preserved.
+
+ SIZE_EXPR is used for computing the size of the expression to be
+ instantiated, and to stop if it exceeds some limit. */
+
+static tree
+instantiate_array_ref (basic_block instantiate_below,
+ struct loop *evolution_loop, tree chrec,
+ bool fold_conversions, htab_t cache, int size_expr)
+{
+ tree res;
+ tree index = TREE_OPERAND (chrec, 1);
+ tree op1 = instantiate_scev_r (instantiate_below, evolution_loop, index,
+ fold_conversions, cache, size_expr);
+
+ if (op1 == chrec_dont_know)
+ return chrec_dont_know;
+
+ if (chrec && op1 == index)
+ return chrec;
+
+ res = unshare_expr (chrec);
+ TREE_OPERAND (res, 1) = op1;
+ return res;
+}
+
+/* Analyze all the parameters of the chrec, between INSTANTIATE_BELOW
+ and EVOLUTION_LOOP, that were left under a symbolic form.
+
"CHREC" that stands for a convert expression "(TYPE) OP" is to be
instantiated.
if (size_expr++ > PARAM_VALUE (PARAM_SCEV_MAX_EXPR_SIZE))
return chrec_dont_know;
- if (automatically_generated_chrec_p (chrec)
+ if (chrec == NULL_TREE
+ || automatically_generated_chrec_p (chrec)
|| is_gimple_min_invariant (chrec))
return chrec;
case SCEV_KNOWN:
return chrec_known;
+ case ARRAY_REF:
+ return instantiate_array_ref (instantiate_below, evolution_loop, chrec,
+ fold_conversions, cache, size_expr);
+
default:
break;
}