diff options
author | rguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2008-07-28 14:33:56 +0000 |
---|---|---|
committer | rguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2008-07-28 14:33:56 +0000 |
commit | 75a70cf95f65fe9204b15ad9aba31c571381d224 (patch) | |
tree | 2926705dd533a8904679724ab1cec40dfee45094 /gcc/tree-ssa-loop-niter.c | |
parent | d0a9db40355cf570989e2aca92ab2060df234926 (diff) | |
download | gcc-75a70cf95f65fe9204b15ad9aba31c571381d224.tar.gz |
2008-07-28 Richard Guenther <rguenther@suse.de>
Merge from gimple-tuples-branch.
* ChangeLog.tuples: ChangeLog from gimple-tuples-branch.
* gimple.def: New file.
* gsstruct.def: Likewise.
* gimple-iterator.c: Likewise.
* gimple-pretty-print.c: Likewise.
* tree-gimple.c: Removed. Merged into ...
* gimple.c: ... here. New file.
* tree-gimple.h: Removed. Merged into ...
* gimple.h: ... here. New file.
* Makefile.in: Add dependencies on GIMPLE_H and tree-iterator.h.
* configure.ac: Added support for ENABLE_GIMPLE_CHECKING and the
--enable-checking=gimple flag.
* config.in: Likewise.
* configure: Regenerated.
* tree-ssa-operands.h: Tuplified.
* tree-vrp.c: Likewise.
* tree-loop-linear.c: Likewise.
* tree-into-ssa.c: Likewise.
* tree-ssa-loop-im.c: Likewise.
* tree-dump.c: Likewise.
* tree-complex.c: Likewise.
* cgraphbuild.c: Likewise.
* tree-ssa-threadupdate.c: Likewise.
* tree-ssa-loop-niter.c: Likewise.
* tree-pretty-print.c: Likewise.
* tracer.c: Likewise.
* gengtype.c: Likewise.
* tree-loop-distribution.c: Likewise.
* tree-ssa-loop-unswitch.c: Likewise.
* cgraph.c: Likewise.
* cgraph.h: Likewise.
* tree-ssa-loop-manip.c: Likewise.
* value-prof.c: Likewise.
* tree-ssa-loop-ch.c: Likewise.
* tree-tailcall.c: Likewise.
* value-prof.h: Likewise.
* tree.c: Likewise.
* tree.h: Likewise.
* tree-pass.h: Likewise.
* ipa-cp.c: Likewise.
* tree-scalar-evolution.c: Likewise.
* tree-scalar-evolution.h: Likewise.
* target.h: Likewise.
* lambda-mat.c: Likewise.
* tree-phinodes.c: Likewise.
* diagnostic.h: Likewise.
* builtins.c: Likewise.
* tree-ssa-alias-warnings.c: Likewise.
* cfghooks.c: Likewise.
* fold-const.c: Likewise.
* cfghooks.h: Likewise.
* omp-low.c: Likewise.
* tree-ssa-dse.c: Likewise.
* ipa-reference.c: Likewise.
* tree-ssa-uncprop.c: Likewise.
* toplev.c: Likewise.
* tree-gimple.c: Likewise.
* tree-gimple.h: Likewise.
* tree-chrec.c: Likewise.
* tree-chrec.h: Likewise.
* tree-ssa-sccvn.c: Likewise.
* tree-ssa-sccvn.h: Likewise.
* cgraphunit.c: Likewise.
* tree-ssa-copyrename.c: Likewise.
* tree-ssa-ccp.c: Likewise.
* tree-ssa-loop-ivopts.c: Likewise.
* tree-nomudflap.c: Likewise.
* tree-call-cdce.c: Likewise.
* ipa-pure-const.c: Likewise.
* c-format.c: Likewise.
* tree-stdarg.c: Likewise.
* tree-ssa-math-opts.c: Likewise.
* tree-ssa-dom.c: Likewise.
* tree-nrv.c: Likewise.
* tree-ssa-propagate.c: Likewise.
* ipa-utils.c: Likewise.
* tree-ssa-propagate.h: Likewise.
* tree-ssa-alias.c: Likewise.
* gimple-low.c: Likewise.
* tree-ssa-sink.c: Likewise.
* ipa-inline.c: Likewise.
* c-semantics.c: Likewise.
* dwarf2out.c: Likewise.
* expr.c: Likewise.
* tree-ssa-loop-ivcanon.c: Likewise.
* predict.c: Likewise.
* tree-ssa-loop.c: Likewise.
* tree-parloops.c: Likewise.
* tree-ssa-address.c: Likewise.
* tree-ssa-ifcombine.c: Likewise.
* matrix-reorg.c: Likewise.
* c-decl.c: Likewise.
* tree-eh.c: Likewise.
* c-pretty-print.c: Likewise.
* lambda-trans.c: Likewise.
* function.c: Likewise.
* langhooks.c: Likewise.
* ebitmap.h: Likewise.
* tree-vectorizer.c: Likewise.
* function.h: Likewise.
* langhooks.h: Likewise.
* tree-vectorizer.h: Likewise.
* ipa-type-escape.c: Likewise.
* ipa-type-escape.h: Likewise.
* domwalk.c: Likewise.
* tree-if-conv.c: Likewise.
* profile.c: Likewise.
* domwalk.h: Likewise.
* tree-data-ref.c: Likewise.
* tree-data-ref.h: Likewise.
* tree-flow-inline.h: Likewise.
* tree-affine.c: Likewise.
* tree-vect-analyze.c: Likewise.
* c-typeck.c: Likewise.
* gimplify.c: Likewise.
* coretypes.h: Likewise.
* tree-ssa-phiopt.c: Likewise.
* calls.c: Likewise.
* tree-ssa-coalesce.c: Likewise.
* tree.def: Likewise.
* tree-dfa.c: Likewise.
* except.c: Likewise.
* except.h: Likewise.
* cfgexpand.c: Likewise.
* tree-cfgcleanup.c: Likewise.
* tree-ssa-pre.c: Likewise.
* tree-ssa-live.c: Likewise.
* tree-sra.c: Likewise.
* tree-ssa-live.h: Likewise.
* tree-predcom.c: Likewise.
* lambda.h: Likewise.
* tree-mudflap.c: Likewise.
* ipa-prop.c: Likewise.
* print-tree.c: Likewise.
* tree-ssa-copy.c: Likewise.
* ipa-prop.h: Likewise.
* tree-ssa-forwprop.c: Likewise.
* ggc-page.c: Likewise.
* c-omp.c: Likewise.
* tree-ssa-dce.c: Likewise.
* tree-vect-patterns.c: Likewise.
* tree-ssa-ter.c: Likewise.
* tree-nested.c: Likewise.
* tree-ssa.c: Likewise.
* lambda-code.c: Likewise.
* tree-ssa-loop-prefetch.c: Likewise.
* tree-inline.c: Likewise.
* tree-inline.h: Likewise.
* tree-iterator.c: Likewise.
* tree-optimize.c: Likewise.
* tree-ssa-phiprop.c: Likewise.
* tree-vect-transform.c: Likewise.
* tree-object-size.c: Likewise.
* tree-outof-ssa.c: Likewise.
* cfgloop.c: Likewise.
* system.h: Likewise.
* tree-profile.c: Likewise.
* cfgloop.h: Likewise.
* c-gimplify.c: Likewise.
* c-common.c: Likewise.
* tree-vect-generic.c: Likewise.
* tree-flow.h: Likewise.
* c-common.h: Likewise.
* basic-block.h: Likewise.
* tree-ssa-structalias.c: Likewise.
* tree-switch-conversion.c: Likewise.
* tree-ssa-structalias.h: Likewise.
* tree-cfg.c: Likewise.
* passes.c: Likewise.
* ipa-struct-reorg.c: Likewise.
* ipa-struct-reorg.h: Likewise.
* tree-ssa-reassoc.c: Likewise.
* cfgrtl.c: Likewise.
* varpool.c: Likewise.
* stmt.c: Likewise.
* tree-ssanames.c: Likewise.
* tree-ssa-threadedge.c: Likewise.
* langhooks-def.h: Likewise.
* tree-ssa-operands.c: Likewise.
* config/alpha/alpha.c: Likewise.
* config/frv/frv.c: Likewise.
* config/s390/s390.c: Likewise.
* config/m32c/m32c.c: Likewise.
* config/m32c/m32c-protos.h: Likewise.
* config/spu/spu.c: Likewise.
* config/sparc/sparc.c: Likewise.
* config/i386/i386.c: Likewise.
* config/sh/sh.c: Likewise.
* config/xtensa/xtensa.c: Likewise.
* config/stormy16/stormy16.c: Likewise.
* config/ia64/ia64.c: Likewise.
* config/rs6000/rs6000.c: Likewise.
* config/pa/pa.c: Likewise.
* config/mips/mips.c: Likewise.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@138207 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/tree-ssa-loop-niter.c')
-rw-r--r-- | gcc/tree-ssa-loop-niter.c | 382 |
1 files changed, 229 insertions, 153 deletions
diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c index 80b45c298b7..83baae7828a 100644 --- a/gcc/tree-ssa-loop-niter.c +++ b/gcc/tree-ssa-loop-niter.c @@ -368,7 +368,8 @@ bound_difference (struct loop *loop, tree x, tree y, bounds *bnds) int cnt = 0; edge e; basic_block bb; - tree cond, c0, c1; + tree c0, c1; + gimple cond; enum tree_code cmp; /* Get rid of unnecessary casts, but preserve the value of @@ -427,12 +428,10 @@ bound_difference (struct loop *loop, tree x, tree y, bounds *bnds) if (!(e->flags & (EDGE_TRUE_VALUE | EDGE_FALSE_VALUE))) continue; - cond = COND_EXPR_COND (last_stmt (e->src)); - if (!COMPARISON_CLASS_P (cond)) - continue; - c0 = TREE_OPERAND (cond, 0); - cmp = TREE_CODE (cond); - c1 = TREE_OPERAND (cond, 1); + cond = last_stmt (e->src); + c0 = gimple_cond_lhs (cond); + cmp = gimple_cond_code (cond); + c1 = gimple_cond_rhs (cond); if (e->flags & EDGE_FALSE_VALUE) cmp = invert_tree_comparison (cmp, false); @@ -1349,7 +1348,7 @@ simplify_replace_tree (tree expr, tree old, tree new_tree) || operand_equal_p (expr, old, 0)) return unshare_expr (new_tree); - if (!EXPR_P (expr) && !GIMPLE_STMT_P (expr)) + if (!EXPR_P (expr)) return expr; n = TREE_OPERAND_LENGTH (expr); @@ -1376,8 +1375,9 @@ tree expand_simple_operations (tree expr) { unsigned i, n; - tree ret = NULL_TREE, e, ee, stmt; + tree ret = NULL_TREE, e, ee, e1; enum tree_code code; + gimple stmt; if (expr == NULL_TREE) return expr; @@ -1415,17 +1415,17 @@ expand_simple_operations (tree expr) return expr; stmt = SSA_NAME_DEF_STMT (expr); - if (TREE_CODE (stmt) == PHI_NODE) + if (gimple_code (stmt) == GIMPLE_PHI) { basic_block src, dest; - if (PHI_NUM_ARGS (stmt) != 1) + if (gimple_phi_num_args (stmt) != 1) return expr; e = PHI_ARG_DEF (stmt, 0); /* Avoid propagating through loop exit phi nodes, which could break loop-closed SSA form restrictions. */ - dest = bb_for_stmt (stmt); + dest = gimple_bb (stmt); src = single_pred (dest); if (TREE_CODE (e) == SSA_NAME && src->loop_father != dest->loop_father) @@ -1433,24 +1433,44 @@ expand_simple_operations (tree expr) return expand_simple_operations (e); } - if (TREE_CODE (stmt) != GIMPLE_MODIFY_STMT) + if (gimple_code (stmt) != GIMPLE_ASSIGN) return expr; - e = GIMPLE_STMT_OPERAND (stmt, 1); - if (/* Casts are simple. */ - !CONVERT_EXPR_P (e) - /* Copies are simple. */ - && TREE_CODE (e) != SSA_NAME - /* Assignments of invariants are simple. */ - && !is_gimple_min_invariant (e) + e = gimple_assign_rhs1 (stmt); + code = gimple_assign_rhs_code (stmt); + if (get_gimple_rhs_class (code) == GIMPLE_SINGLE_RHS) + { + if (is_gimple_min_invariant (e)) + return e; + + if (code == SSA_NAME) + return expand_simple_operations (e); + + return expr; + } + + switch (code) + { + case NOP_EXPR: + case CONVERT_EXPR: + /* Casts are simple. */ + ee = expand_simple_operations (e); + return fold_build1 (code, TREE_TYPE (expr), ee); + + case PLUS_EXPR: + case MINUS_EXPR: + case POINTER_PLUS_EXPR: /* And increments and decrements by a constant are simple. */ - && !((TREE_CODE (e) == PLUS_EXPR - || TREE_CODE (e) == MINUS_EXPR - || TREE_CODE (e) == POINTER_PLUS_EXPR) - && is_gimple_min_invariant (TREE_OPERAND (e, 1)))) - return expr; + e1 = gimple_assign_rhs2 (stmt); + if (!is_gimple_min_invariant (e1)) + return expr; + + ee = expand_simple_operations (e); + return fold_build2 (code, TREE_TYPE (expr), ee, e1); - return expand_simple_operations (e); + default: + return expr; + } } /* Tries to simplify EXPR using the condition COND. Returns the simplified @@ -1585,6 +1605,7 @@ simplify_using_initial_conditions (struct loop *loop, tree expr) { edge e; basic_block bb; + gimple stmt; tree cond; int cnt = 0; @@ -1605,7 +1626,11 @@ simplify_using_initial_conditions (struct loop *loop, tree expr) if (!(e->flags & (EDGE_TRUE_VALUE | EDGE_FALSE_VALUE))) continue; - cond = COND_EXPR_COND (last_stmt (e->src)); + stmt = last_stmt (e->src); + cond = fold_build2 (gimple_cond_code (stmt), + boolean_type_node, + gimple_cond_lhs (stmt), + gimple_cond_rhs (stmt)); if (e->flags & EDGE_FALSE_VALUE) cond = invert_truthvalue (cond); expr = tree_simplify_using_condition (cond, expr); @@ -1676,9 +1701,9 @@ bool loop_only_exit_p (const struct loop *loop, const_edge exit) { basic_block *body; - block_stmt_iterator bsi; + gimple_stmt_iterator bsi; unsigned i; - tree call; + gimple call; if (exit != single_exit (loop)) return false; @@ -1686,10 +1711,13 @@ loop_only_exit_p (const struct loop *loop, const_edge exit) body = get_loop_body (loop); for (i = 0; i < loop->num_nodes; i++) { - for (bsi = bsi_start (body[0]); !bsi_end_p (bsi); bsi_next (&bsi)) + for (bsi = gsi_start_bb (body[i]); !gsi_end_p (bsi); gsi_next (&bsi)) { - call = get_call_expr_in (bsi_stmt (bsi)); - if (call && TREE_SIDE_EFFECTS (call)) + call = gsi_stmt (bsi); + if (gimple_code (call) != GIMPLE_CALL) + continue; + + if (gimple_has_side_effects (call)) { free (body); return false; @@ -1714,7 +1742,8 @@ number_of_iterations_exit (struct loop *loop, edge exit, struct tree_niter_desc *niter, bool warn) { - tree stmt, cond, type; + gimple stmt; + tree type; tree op0, op1; enum tree_code code; affine_iv iv0, iv1; @@ -1724,15 +1753,14 @@ number_of_iterations_exit (struct loop *loop, edge exit, niter->assumptions = boolean_false_node; stmt = last_stmt (exit->src); - if (!stmt || TREE_CODE (stmt) != COND_EXPR) + if (!stmt || gimple_code (stmt) != GIMPLE_COND) return false; /* We want the condition for staying inside loop. */ - cond = COND_EXPR_COND (stmt); + code = gimple_cond_code (stmt); if (exit->flags & EDGE_TRUE_VALUE) - cond = invert_truthvalue (cond); + code = invert_tree_comparison (code, false); - code = TREE_CODE (cond); switch (code) { case GT_EXPR: @@ -1746,8 +1774,8 @@ number_of_iterations_exit (struct loop *loop, edge exit, return false; } - op0 = TREE_OPERAND (cond, 0); - op1 = TREE_OPERAND (cond, 1); + op0 = gimple_cond_lhs (stmt); + op1 = gimple_cond_rhs (stmt); type = TREE_TYPE (op0); if (TREE_CODE (type) != INTEGER_TYPE @@ -1805,7 +1833,7 @@ number_of_iterations_exit (struct loop *loop, edge exit, if (warn) { const char *wording; - location_t loc = EXPR_LOCATION (stmt); + location_t loc = gimple_location (stmt); /* We can provide a more specific warning if one of the operator is constant and the other advances by +1 or -1. */ @@ -1915,36 +1943,43 @@ find_loop_niter (struct loop *loop, edge *exit) result by a chain of operations such that all but exactly one of their operands are constants. */ -static tree +static gimple chain_of_csts_start (struct loop *loop, tree x) { - tree stmt = SSA_NAME_DEF_STMT (x); + gimple stmt = SSA_NAME_DEF_STMT (x); tree use; - basic_block bb = bb_for_stmt (stmt); + basic_block bb = gimple_bb (stmt); + enum tree_code code; if (!bb || !flow_bb_inside_loop_p (loop, bb)) - return NULL_TREE; + return NULL; - if (TREE_CODE (stmt) == PHI_NODE) + if (gimple_code (stmt) == GIMPLE_PHI) { if (bb == loop->header) return stmt; - return NULL_TREE; + return NULL; } - if (TREE_CODE (stmt) != GIMPLE_MODIFY_STMT) - return NULL_TREE; + if (gimple_code (stmt) != GIMPLE_ASSIGN) + return NULL; - if (!ZERO_SSA_OPERANDS (stmt, SSA_OP_ALL_VIRTUALS)) - return NULL_TREE; - if (SINGLE_SSA_DEF_OPERAND (stmt, SSA_OP_DEF) == NULL_DEF_OPERAND_P) - return NULL_TREE; + code = gimple_assign_rhs_code (stmt); + if (gimple_references_memory_p (stmt) + /* Before alias information is computed, operand scanning marks + statements that write memory volatile. However, the statements + that only read memory are not marked, thus gimple_references_memory_p + returns false for them. */ + || TREE_CODE_CLASS (code) == tcc_reference + || TREE_CODE_CLASS (code) == tcc_declaration + || SINGLE_SSA_DEF_OPERAND (stmt, SSA_OP_DEF) == NULL_DEF_OPERAND_P) + return NULL; use = SINGLE_SSA_TREE_OPERAND (stmt, SSA_OP_USE); if (use == NULL_USE_OPERAND_P) - return NULL_TREE; + return NULL; return chain_of_csts_start (loop, use); } @@ -1957,32 +1992,32 @@ chain_of_csts_start (struct loop *loop, tree x) * the value of the phi node in the next iteration can be derived from the value in the current iteration by a chain of operations with constants. - If such phi node exists, it is returned. If X is a constant, X is returned - unchanged. Otherwise NULL_TREE is returned. */ + If such phi node exists, it is returned, otherwise NULL is returned. */ -static tree +static gimple get_base_for (struct loop *loop, tree x) { - tree phi, init, next; + gimple phi; + tree init, next; if (is_gimple_min_invariant (x)) - return x; + return NULL; phi = chain_of_csts_start (loop, x); if (!phi) - return NULL_TREE; + return NULL; init = PHI_ARG_DEF_FROM_EDGE (phi, loop_preheader_edge (loop)); next = PHI_ARG_DEF_FROM_EDGE (phi, loop_latch_edge (loop)); if (TREE_CODE (next) != SSA_NAME) - return NULL_TREE; + return NULL; if (!is_gimple_min_invariant (init)) - return NULL_TREE; + return NULL; if (chain_of_csts_start (loop, next) != phi) - return NULL_TREE; + return NULL; return phi; } @@ -1998,9 +2033,8 @@ get_base_for (struct loop *loop, tree x) static tree get_val_for (tree x, tree base) { - tree stmt, nx, val; - use_operand_p op; - ssa_op_iter iter; + gimple stmt; + tree nx, val, retval, rhs1, rhs2; gcc_assert (is_gimple_min_invariant (base)); @@ -2008,24 +2042,44 @@ get_val_for (tree x, tree base) return base; stmt = SSA_NAME_DEF_STMT (x); - if (TREE_CODE (stmt) == PHI_NODE) + if (gimple_code (stmt) == GIMPLE_PHI) return base; - FOR_EACH_SSA_USE_OPERAND (op, stmt, iter, SSA_OP_USE) - { - nx = USE_FROM_PTR (op); - val = get_val_for (nx, base); - SET_USE (op, val); - val = fold (GIMPLE_STMT_OPERAND (stmt, 1)); - SET_USE (op, nx); - /* only iterate loop once. */ - return val; + gcc_assert (is_gimple_assign (stmt)); + + /* STMT must be either an assignment of a single SSA name or an + expression involving an SSA name and a constant. Try to fold that + expression using the value for the SSA name. */ + rhs1 = gimple_assign_rhs1 (stmt); + rhs2 = gimple_assign_rhs2 (stmt); + if (TREE_CODE (rhs1) == SSA_NAME) + nx = rhs1; + else if (rhs2 && TREE_CODE (rhs2) == SSA_NAME) + nx = rhs2; + else + gcc_unreachable (); + + /* NX is now the SSA name for which we want to discover the base value. */ + val = get_val_for (nx, base); + if (rhs2) + { + /* If this is a binary expression, fold it. If folding is + not possible, return a tree expression with the RHS of STMT. */ + rhs1 = (nx == rhs1) ? val : rhs1; + rhs2 = (nx == rhs2) ? val : rhs2; + retval = fold_binary (gimple_assign_rhs_code (stmt), + gimple_expr_type (stmt), rhs1, rhs2); + if (retval == NULL_TREE) + retval= build2 (gimple_assign_rhs_code (stmt), + gimple_expr_type (stmt), rhs1, rhs2); } - - /* Should never reach here. */ - gcc_unreachable (); + else + retval = val; + + return retval; } + /* Tries to count the number of iterations of LOOP till it exits by EXIT by brute force -- i.e. by determining the value of the operands of the condition at EXIT in first few iterations of the loop (assuming that @@ -2036,20 +2090,20 @@ get_val_for (tree x, tree base) tree loop_niter_by_eval (struct loop *loop, edge exit) { - tree cond, cnd, acnd; - tree op[2], val[2], next[2], aval[2], phi[2]; + tree acnd; + tree op[2], val[2], next[2], aval[2]; + gimple phi, cond; unsigned i, j; enum tree_code cmp; cond = last_stmt (exit->src); - if (!cond || TREE_CODE (cond) != COND_EXPR) + if (!cond || gimple_code (cond) != GIMPLE_COND) return chrec_dont_know; - cnd = COND_EXPR_COND (cond); + cmp = gimple_cond_code (cond); if (exit->flags & EDGE_TRUE_VALUE) - cnd = invert_truthvalue (cnd); + cmp = invert_tree_comparison (cmp, false); - cmp = TREE_CODE (cnd); switch (cmp) { case EQ_EXPR: @@ -2058,8 +2112,8 @@ loop_niter_by_eval (struct loop *loop, edge exit) case GE_EXPR: case LT_EXPR: case LE_EXPR: - for (j = 0; j < 2; j++) - op[j] = TREE_OPERAND (cnd, j); + op[0] = gimple_cond_lhs (cond); + op[1] = gimple_cond_rhs (cond); break; default: @@ -2068,23 +2122,19 @@ loop_niter_by_eval (struct loop *loop, edge exit) for (j = 0; j < 2; j++) { - phi[j] = get_base_for (loop, op[j]); - if (!phi[j]) - return chrec_dont_know; - } - - for (j = 0; j < 2; j++) - { - if (TREE_CODE (phi[j]) == PHI_NODE) + if (is_gimple_min_invariant (op[j])) { - val[j] = PHI_ARG_DEF_FROM_EDGE (phi[j], loop_preheader_edge (loop)); - next[j] = PHI_ARG_DEF_FROM_EDGE (phi[j], loop_latch_edge (loop)); + val[j] = op[j]; + next[j] = NULL_TREE; + op[j] = NULL_TREE; } else { - val[j] = phi[j]; - next[j] = NULL_TREE; - op[j] = NULL_TREE; + phi = get_base_for (loop, op[j]); + if (!phi) + return chrec_dont_know; + val[j] = PHI_ARG_DEF_FROM_EDGE (phi, loop_preheader_edge (loop)); + next[j] = PHI_ARG_DEF_FROM_EDGE (phi, loop_latch_edge (loop)); } } @@ -2166,17 +2216,48 @@ find_loop_niter_by_eval (struct loop *loop, edge *exit) */ +static double_int derive_constant_upper_bound_ops (tree, tree, + enum tree_code, tree); + +/* Returns a constant upper bound on the value of the right-hand side of + an assignment statement STMT. */ + +static double_int +derive_constant_upper_bound_assign (gimple stmt) +{ + enum tree_code code = gimple_assign_rhs_code (stmt); + tree op0 = gimple_assign_rhs1 (stmt); + tree op1 = gimple_assign_rhs2 (stmt); + + return derive_constant_upper_bound_ops (TREE_TYPE (gimple_assign_lhs (stmt)), + op0, code, op1); +} + /* Returns a constant upper bound on the value of expression VAL. VAL is considered to be unsigned. If its type is signed, its value must be nonnegative. */ static double_int -derive_constant_upper_bound (const_tree val) +derive_constant_upper_bound (tree val) +{ + enum tree_code code; + tree op0, op1; + + extract_ops_from_tree (val, &code, &op0, &op1); + return derive_constant_upper_bound_ops (TREE_TYPE (val), op0, code, op1); +} + +/* Returns a constant upper bound on the value of expression OP0 CODE OP1, + whose type is TYPE. The expression is considered to be unsigned. If + its type is signed, its value must be nonnegative. */ + +static double_int +derive_constant_upper_bound_ops (tree type, tree op0, + enum tree_code code, tree op1) { - tree type = TREE_TYPE (val); - tree op0, op1, subtype, maxt; + tree subtype, maxt; double_int bnd, max, mmax, cst; - tree stmt; + gimple stmt; if (INTEGRAL_TYPE_P (type)) maxt = TYPE_MAX_VALUE (type); @@ -2185,13 +2266,12 @@ derive_constant_upper_bound (const_tree val) max = tree_to_double_int (maxt); - switch (TREE_CODE (val)) + switch (code) { case INTEGER_CST: - return tree_to_double_int (val); + return tree_to_double_int (op0); CASE_CONVERT: - op0 = TREE_OPERAND (val, 0); subtype = TREE_TYPE (op0); if (!TYPE_UNSIGNED (subtype) /* If TYPE is also signed, the fact that VAL is nonnegative implies @@ -2219,9 +2299,6 @@ derive_constant_upper_bound (const_tree val) case PLUS_EXPR: case POINTER_PLUS_EXPR: case MINUS_EXPR: - op0 = TREE_OPERAND (val, 0); - op1 = TREE_OPERAND (val, 1); - if (TREE_CODE (op1) != INTEGER_CST || !tree_expr_nonnegative_p (op0)) return max; @@ -2231,7 +2308,7 @@ derive_constant_upper_bound (const_tree val) of the signedness of the type. */ cst = tree_to_double_int (op1); cst = double_int_sext (cst, TYPE_PRECISION (type)); - if (TREE_CODE (val) == PLUS_EXPR) + if (code != MINUS_EXPR) cst = double_int_neg (cst); bnd = derive_constant_upper_bound (op0); @@ -2285,8 +2362,6 @@ derive_constant_upper_bound (const_tree val) case FLOOR_DIV_EXPR: case EXACT_DIV_EXPR: - op0 = TREE_OPERAND (val, 0); - op1 = TREE_OPERAND (val, 1); if (TREE_CODE (op1) != INTEGER_CST || tree_int_cst_sign_bit (op1)) return max; @@ -2295,18 +2370,17 @@ derive_constant_upper_bound (const_tree val) return double_int_udiv (bnd, tree_to_double_int (op1), FLOOR_DIV_EXPR); case BIT_AND_EXPR: - op1 = TREE_OPERAND (val, 1); if (TREE_CODE (op1) != INTEGER_CST || tree_int_cst_sign_bit (op1)) return max; return tree_to_double_int (op1); case SSA_NAME: - stmt = SSA_NAME_DEF_STMT (val); - if (TREE_CODE (stmt) != GIMPLE_MODIFY_STMT - || GIMPLE_STMT_OPERAND (stmt, 0) != val) + stmt = SSA_NAME_DEF_STMT (op0); + if (gimple_code (stmt) != GIMPLE_ASSIGN + || gimple_assign_lhs (stmt) != op0) return max; - return derive_constant_upper_bound (GIMPLE_STMT_OPERAND (stmt, 1)); + return derive_constant_upper_bound_assign (stmt); default: return max; @@ -2349,7 +2423,7 @@ record_niter_bound (struct loop *loop, double_int i_bound, bool realistic, static void record_estimate (struct loop *loop, tree bound, double_int i_bound, - tree at_stmt, bool is_exit, bool realistic, bool upper) + gimple at_stmt, bool is_exit, bool realistic, bool upper) { double_int delta; edge exit; @@ -2357,7 +2431,7 @@ record_estimate (struct loop *loop, tree bound, double_int i_bound, if (dump_file && (dump_flags & TDF_DETAILS)) { fprintf (dump_file, "Statement %s", is_exit ? "(exit)" : ""); - print_generic_expr (dump_file, at_stmt, TDF_SLIM); + print_gimple_stmt (dump_file, at_stmt, 0, TDF_SLIM); fprintf (dump_file, " is %sexecuted at most ", upper ? "" : "probably "); print_generic_expr (dump_file, bound, TDF_SLIM); @@ -2395,7 +2469,7 @@ record_estimate (struct loop *loop, tree bound, double_int i_bound, if (is_exit || (exit != NULL && dominated_by_p (CDI_DOMINATORS, - exit->src, bb_for_stmt (at_stmt)))) + exit->src, gimple_bb (at_stmt)))) delta = double_int_one; else delta = double_int_two; @@ -2415,7 +2489,7 @@ record_estimate (struct loop *loop, tree bound, double_int i_bound, UPPER is true if we are sure the induction variable does not wrap. */ static void -record_nonwrapping_iv (struct loop *loop, tree base, tree step, tree stmt, +record_nonwrapping_iv (struct loop *loop, tree base, tree step, gimple stmt, tree low, tree high, bool realistic, bool upper) { tree niter_bound, extreme, delta; @@ -2434,7 +2508,7 @@ record_nonwrapping_iv (struct loop *loop, tree base, tree step, tree stmt, fprintf (dump_file, " + "); print_generic_expr (dump_file, step, TDF_SLIM); fprintf (dump_file, " * iteration does not wrap in statement "); - print_generic_expr (dump_file, stmt, TDF_SLIM); + print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM); fprintf (dump_file, " in loop %d.\n", loop->num); } @@ -2515,7 +2589,7 @@ array_at_struct_end_p (tree ref) struct ilb_data { struct loop *loop; - tree stmt; + gimple stmt; bool reliable; }; @@ -2602,7 +2676,7 @@ idx_infer_loop_bounds (tree base, tree *idx, void *dta) STMT is guaranteed to be executed in every iteration of LOOP.*/ static void -infer_loop_bounds_from_ref (struct loop *loop, tree stmt, tree ref, +infer_loop_bounds_from_ref (struct loop *loop, gimple stmt, tree ref, bool reliable) { struct ilb_data data; @@ -2618,14 +2692,12 @@ infer_loop_bounds_from_ref (struct loop *loop, tree stmt, tree ref, executed in every iteration of LOOP. */ static void -infer_loop_bounds_from_array (struct loop *loop, tree stmt, bool reliable) +infer_loop_bounds_from_array (struct loop *loop, gimple stmt, bool reliable) { - tree call; - - if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT) + if (is_gimple_assign (stmt)) { - tree op0 = GIMPLE_STMT_OPERAND (stmt, 0); - tree op1 = GIMPLE_STMT_OPERAND (stmt, 1); + tree op0 = gimple_assign_lhs (stmt); + tree op1 = gimple_assign_rhs1 (stmt); /* For each memory access, analyze its access function and record a bound on the loop iteration domain. */ @@ -2635,17 +2707,21 @@ infer_loop_bounds_from_array (struct loop *loop, tree stmt, bool reliable) if (REFERENCE_CLASS_P (op1)) infer_loop_bounds_from_ref (loop, stmt, op1, reliable); } - - - call = get_call_expr_in (stmt); - if (call) + else if (is_gimple_call (stmt)) { - tree arg; - call_expr_arg_iterator iter; + tree arg, lhs; + unsigned i, n = gimple_call_num_args (stmt); - FOR_EACH_CALL_EXPR_ARG (arg, iter, call) - if (REFERENCE_CLASS_P (arg)) - infer_loop_bounds_from_ref (loop, stmt, arg, reliable); + lhs = gimple_call_lhs (stmt); + if (lhs && REFERENCE_CLASS_P (lhs)) + infer_loop_bounds_from_ref (loop, stmt, lhs, reliable); + + for (i = 0; i < n; i++) + { + arg = gimple_call_arg (stmt, i); + if (REFERENCE_CLASS_P (arg)) + infer_loop_bounds_from_ref (loop, stmt, arg, reliable); + } } } @@ -2653,14 +2729,14 @@ infer_loop_bounds_from_array (struct loop *loop, tree stmt, bool reliable) that signed arithmetics in STMT does not overflow. */ static void -infer_loop_bounds_from_signedness (struct loop *loop, tree stmt) +infer_loop_bounds_from_signedness (struct loop *loop, gimple stmt) { tree def, base, step, scev, type, low, high; - if (TREE_CODE (stmt) != GIMPLE_MODIFY_STMT) + if (gimple_code (stmt) != GIMPLE_ASSIGN) return; - def = GIMPLE_STMT_OPERAND (stmt, 0); + def = gimple_assign_lhs (stmt); if (TREE_CODE (def) != SSA_NAME) return; @@ -2703,7 +2779,7 @@ infer_loop_bounds_from_undefined (struct loop *loop) { unsigned i; basic_block *bbs; - block_stmt_iterator bsi; + gimple_stmt_iterator bsi; basic_block bb; bool reliable; @@ -2718,9 +2794,9 @@ infer_loop_bounds_from_undefined (struct loop *loop) # of iterations of the loop. However, we can use it as a guess. */ reliable = dominated_by_p (CDI_DOMINATORS, loop->latch, bb); - for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi)) + for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi)) { - tree stmt = bsi_stmt (bsi); + gimple stmt = gsi_stmt (bsi); infer_loop_bounds_from_array (loop, stmt, reliable); @@ -2830,9 +2906,9 @@ estimate_numbers_of_iterations (void) /* Returns true if statement S1 dominates statement S2. */ bool -stmt_dominates_stmt_p (tree s1, tree s2) +stmt_dominates_stmt_p (gimple s1, gimple s2) { - basic_block bb1 = bb_for_stmt (s1), bb2 = bb_for_stmt (s2); + basic_block bb1 = gimple_bb (s1), bb2 = gimple_bb (s2); if (!bb1 || s1 == s2) @@ -2840,10 +2916,10 @@ stmt_dominates_stmt_p (tree s1, tree s2) if (bb1 == bb2) { - block_stmt_iterator bsi; + gimple_stmt_iterator bsi; - for (bsi = bsi_start (bb1); bsi_stmt (bsi) != s2; bsi_next (&bsi)) - if (bsi_stmt (bsi) == s1) + for (bsi = gsi_start_bb (bb1); gsi_stmt (bsi) != s2; gsi_next (&bsi)) + if (gsi_stmt (bsi) == s1) return true; return false; @@ -2859,7 +2935,7 @@ stmt_dominates_stmt_p (tree s1, tree s2) statements in the loop. */ static bool -n_of_executions_at_most (tree stmt, +n_of_executions_at_most (gimple stmt, struct nb_iter_bound *niter_bound, tree niter) { @@ -2900,7 +2976,7 @@ n_of_executions_at_most (tree stmt, else { if (!stmt - || (bb_for_stmt (stmt) != bb_for_stmt (niter_bound->stmt) + || (gimple_bb (stmt) != gimple_bb (niter_bound->stmt) && !stmt_dominates_stmt_p (niter_bound->stmt, stmt))) { bound = double_int_add (bound, double_int_one); @@ -2943,7 +3019,7 @@ nowrap_type_p (tree type) bool scev_probably_wraps_p (tree base, tree step, - tree at_stmt, struct loop *loop, + gimple at_stmt, struct loop *loop, bool use_overflow_semantics) { struct nb_iter_bound *bound; |