49b8fe6c1a
Regstrapped on amd64-linux. 2015-07-18 Sebastian Pop <s.pop@samsung.com> PR middle-end/46851 PR middle-end/60340 * Makefile.in: Removed omega.o. * common.opt: Remove flag fcheck-data-deps. * doc/invoke.texi: Remove documentation for fcheck-data-deps and its associated params: omega-max-vars, omega-max-geqs, omega-max-eqs, omega-max-wild-cards, omega-hash-table-size, omega-max-keys, omega-eliminate-redundant-constraints. * doc/loop.texi: Remove all the section on Omega. * graphite-blocking.c: Include missing params.h: it used to be included through tree-data-ref.h and omega.h. * graphite-isl-ast-to-gimple.c: Same. * graphite-optimize-isl.c: Same. * graphite-sese-to-poly.c: Same. * graphite.c: Same. * omega.c: Remove. * omega.h: Remove. * params.def: Removed PARAM_OMEGA_MAX_VARS, PARAM_OMEGA_MAX_GEQS, PARAM_OMEGA_MAX_EQS, PARAM_OMEGA_MAX_WILD_CARDS, PARAM_OMEGA_HASH_TABLE_SIZE, PARAM_OMEGA_MAX_KEYS, and PARAM_OMEGA_ELIMINATE_REDUNDANT_CONSTRAINTS. * passes.def: Remove pass_check_data_deps. * tree-data-ref.c (dump_affine_function): Declare DEBUG_FUNCTION. (dump_conflict_function): Same. (dump_subscript): Same. (print_direction_vector): Same. (print_dir_vectors): Same. (print_lambda_vector): Same. (print_dist_vectors): Same. (dump_data_dependence_relation): Same. (dump_data_dependence_relations): Same. (dump_dist_dir_vectors): Same. (dump_ddrs): Same. (init_omega_eq_with_af): Removed. (omega_extract_distance_vectors): Removed. (omega_setup_subscript): Removed. (init_omega_for_ddr_1): Removed. (init_omega_for_ddr): Removed. (ddr_consistent_p): Removed. (compute_affine_dependence): Do not use omega to check data dependences. (compute_data_dependences_for_bb): Removed. (analyze_all_data_dependences): Removed. (tree_check_data_deps): Removed. * tree-data-ref.h: Do not include omega.h. (compute_data_dependences_for_bb): Removed. (tree_check_data_deps): Removed. * tree-ssa-loop.c (pass_check_data_deps): Removed. (make_pass_check_data_deps): Removed. * tree-ssa-phiopt.c: Include params.h. * tree-vect-data-refs.c: Same. * tree-vect-slp.c: Same. testsuite/ * gcc.dg/tree-ssa/pr42327.c: Removed. * g++.dg/other/pr35011.C: Removed. From-SVN: r225979
701 lines
15 KiB
C
701 lines
15 KiB
C
/* Loop optimizations over tree-ssa.
|
|
Copyright (C) 2003-2015 Free Software Foundation, Inc.
|
|
|
|
This file is part of GCC.
|
|
|
|
GCC is free software; you can redistribute it and/or modify it
|
|
under the terms of the GNU General Public License as published by the
|
|
Free Software Foundation; either version 3, or (at your option) any
|
|
later version.
|
|
|
|
GCC is distributed in the hope that it will be useful, but WITHOUT
|
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with GCC; see the file COPYING3. If not see
|
|
<http://www.gnu.org/licenses/>. */
|
|
|
|
#include "config.h"
|
|
#include "system.h"
|
|
#include "coretypes.h"
|
|
#include "backend.h"
|
|
#include "tree.h"
|
|
#include "gimple.h"
|
|
#include "hard-reg-set.h"
|
|
#include "alias.h"
|
|
#include "fold-const.h"
|
|
#include "tm_p.h"
|
|
#include "internal-fn.h"
|
|
#include "gimple-iterator.h"
|
|
#include "tree-ssa-loop-ivopts.h"
|
|
#include "tree-ssa-loop-manip.h"
|
|
#include "tree-ssa-loop-niter.h"
|
|
#include "tree-ssa-loop.h"
|
|
#include "tree-pass.h"
|
|
#include "cfgloop.h"
|
|
#include "flags.h"
|
|
#include "tree-inline.h"
|
|
#include "tree-scalar-evolution.h"
|
|
#include "diagnostic-core.h"
|
|
#include "tree-vectorizer.h"
|
|
|
|
|
|
/* A pass making sure loops are fixed up. */
|
|
|
|
namespace {
|
|
|
|
const pass_data pass_data_fix_loops =
|
|
{
|
|
GIMPLE_PASS, /* type */
|
|
"fix_loops", /* name */
|
|
OPTGROUP_LOOP, /* optinfo_flags */
|
|
TV_TREE_LOOP, /* tv_id */
|
|
PROP_cfg, /* properties_required */
|
|
0, /* properties_provided */
|
|
0, /* properties_destroyed */
|
|
0, /* todo_flags_start */
|
|
0, /* todo_flags_finish */
|
|
};
|
|
|
|
class pass_fix_loops : public gimple_opt_pass
|
|
{
|
|
public:
|
|
pass_fix_loops (gcc::context *ctxt)
|
|
: gimple_opt_pass (pass_data_fix_loops, ctxt)
|
|
{}
|
|
|
|
/* opt_pass methods: */
|
|
virtual bool gate (function *) { return flag_tree_loop_optimize; }
|
|
|
|
virtual unsigned int execute (function *fn);
|
|
}; // class pass_fix_loops
|
|
|
|
unsigned int
|
|
pass_fix_loops::execute (function *)
|
|
{
|
|
if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
|
|
{
|
|
calculate_dominance_info (CDI_DOMINATORS);
|
|
fix_loop_structure (NULL);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
} // anon namespace
|
|
|
|
gimple_opt_pass *
|
|
make_pass_fix_loops (gcc::context *ctxt)
|
|
{
|
|
return new pass_fix_loops (ctxt);
|
|
}
|
|
|
|
|
|
/* Gate for loop pass group. The group is controlled by -ftree-loop-optimize
|
|
but we also avoid running it when the IL doesn't contain any loop. */
|
|
|
|
static bool
|
|
gate_loop (function *fn)
|
|
{
|
|
if (!flag_tree_loop_optimize)
|
|
return false;
|
|
|
|
/* For -fdump-passes which runs before loop discovery print the
|
|
state of -ftree-loop-optimize. */
|
|
if (!loops_for_fn (fn))
|
|
return true;
|
|
|
|
return number_of_loops (fn) > 1;
|
|
}
|
|
|
|
/* The loop superpass. */
|
|
|
|
namespace {
|
|
|
|
const pass_data pass_data_tree_loop =
|
|
{
|
|
GIMPLE_PASS, /* type */
|
|
"loop", /* name */
|
|
OPTGROUP_LOOP, /* optinfo_flags */
|
|
TV_TREE_LOOP, /* tv_id */
|
|
PROP_cfg, /* properties_required */
|
|
0, /* properties_provided */
|
|
0, /* properties_destroyed */
|
|
0, /* todo_flags_start */
|
|
0, /* todo_flags_finish */
|
|
};
|
|
|
|
class pass_tree_loop : public gimple_opt_pass
|
|
{
|
|
public:
|
|
pass_tree_loop (gcc::context *ctxt)
|
|
: gimple_opt_pass (pass_data_tree_loop, ctxt)
|
|
{}
|
|
|
|
/* opt_pass methods: */
|
|
virtual bool gate (function *fn) { return gate_loop (fn); }
|
|
|
|
}; // class pass_tree_loop
|
|
|
|
} // anon namespace
|
|
|
|
gimple_opt_pass *
|
|
make_pass_tree_loop (gcc::context *ctxt)
|
|
{
|
|
return new pass_tree_loop (ctxt);
|
|
}
|
|
|
|
/* The no-loop superpass. */
|
|
|
|
namespace {
|
|
|
|
const pass_data pass_data_tree_no_loop =
|
|
{
|
|
GIMPLE_PASS, /* type */
|
|
"no_loop", /* name */
|
|
OPTGROUP_NONE, /* optinfo_flags */
|
|
TV_TREE_NOLOOP, /* tv_id */
|
|
PROP_cfg, /* properties_required */
|
|
0, /* properties_provided */
|
|
0, /* properties_destroyed */
|
|
0, /* todo_flags_start */
|
|
0, /* todo_flags_finish */
|
|
};
|
|
|
|
class pass_tree_no_loop : public gimple_opt_pass
|
|
{
|
|
public:
|
|
pass_tree_no_loop (gcc::context *ctxt)
|
|
: gimple_opt_pass (pass_data_tree_no_loop, ctxt)
|
|
{}
|
|
|
|
/* opt_pass methods: */
|
|
virtual bool gate (function *fn) { return !gate_loop (fn); }
|
|
|
|
}; // class pass_tree_no_loop
|
|
|
|
} // anon namespace
|
|
|
|
gimple_opt_pass *
|
|
make_pass_tree_no_loop (gcc::context *ctxt)
|
|
{
|
|
return new pass_tree_no_loop (ctxt);
|
|
}
|
|
|
|
|
|
/* Loop optimizer initialization. */
|
|
|
|
namespace {
|
|
|
|
const pass_data pass_data_tree_loop_init =
|
|
{
|
|
GIMPLE_PASS, /* type */
|
|
"loopinit", /* name */
|
|
OPTGROUP_LOOP, /* optinfo_flags */
|
|
TV_NONE, /* tv_id */
|
|
PROP_cfg, /* properties_required */
|
|
0, /* properties_provided */
|
|
0, /* properties_destroyed */
|
|
0, /* todo_flags_start */
|
|
0, /* todo_flags_finish */
|
|
};
|
|
|
|
class pass_tree_loop_init : public gimple_opt_pass
|
|
{
|
|
public:
|
|
pass_tree_loop_init (gcc::context *ctxt)
|
|
: gimple_opt_pass (pass_data_tree_loop_init, ctxt)
|
|
{}
|
|
|
|
/* opt_pass methods: */
|
|
virtual unsigned int execute (function *);
|
|
|
|
}; // class pass_tree_loop_init
|
|
|
|
unsigned int
|
|
pass_tree_loop_init::execute (function *fun ATTRIBUTE_UNUSED)
|
|
{
|
|
loop_optimizer_init (LOOPS_NORMAL
|
|
| LOOPS_HAVE_RECORDED_EXITS);
|
|
rewrite_into_loop_closed_ssa (NULL, TODO_update_ssa);
|
|
|
|
/* We might discover new loops, e.g. when turning irreducible
|
|
regions into reducible. */
|
|
scev_initialize ();
|
|
|
|
return 0;
|
|
}
|
|
|
|
} // anon namespace
|
|
|
|
gimple_opt_pass *
|
|
make_pass_tree_loop_init (gcc::context *ctxt)
|
|
{
|
|
return new pass_tree_loop_init (ctxt);
|
|
}
|
|
|
|
/* Loop autovectorization. */
|
|
|
|
namespace {
|
|
|
|
const pass_data pass_data_vectorize =
|
|
{
|
|
GIMPLE_PASS, /* type */
|
|
"vect", /* name */
|
|
OPTGROUP_LOOP | OPTGROUP_VEC, /* optinfo_flags */
|
|
TV_TREE_VECTORIZATION, /* tv_id */
|
|
( PROP_cfg | PROP_ssa ), /* properties_required */
|
|
0, /* properties_provided */
|
|
0, /* properties_destroyed */
|
|
0, /* todo_flags_start */
|
|
0, /* todo_flags_finish */
|
|
};
|
|
|
|
class pass_vectorize : public gimple_opt_pass
|
|
{
|
|
public:
|
|
pass_vectorize (gcc::context *ctxt)
|
|
: gimple_opt_pass (pass_data_vectorize, ctxt)
|
|
{}
|
|
|
|
/* opt_pass methods: */
|
|
virtual bool gate (function *fun)
|
|
{
|
|
return flag_tree_loop_vectorize || fun->has_force_vectorize_loops;
|
|
}
|
|
|
|
virtual unsigned int execute (function *);
|
|
|
|
}; // class pass_vectorize
|
|
|
|
unsigned int
|
|
pass_vectorize::execute (function *fun)
|
|
{
|
|
if (number_of_loops (fun) <= 1)
|
|
return 0;
|
|
|
|
return vectorize_loops ();
|
|
}
|
|
|
|
} // anon namespace
|
|
|
|
gimple_opt_pass *
|
|
make_pass_vectorize (gcc::context *ctxt)
|
|
{
|
|
return new pass_vectorize (ctxt);
|
|
}
|
|
|
|
/* Propagation of constants using scev. */
|
|
|
|
namespace {
|
|
|
|
const pass_data pass_data_scev_cprop =
|
|
{
|
|
GIMPLE_PASS, /* type */
|
|
"sccp", /* name */
|
|
OPTGROUP_LOOP, /* optinfo_flags */
|
|
TV_SCEV_CONST, /* tv_id */
|
|
( PROP_cfg | PROP_ssa ), /* properties_required */
|
|
0, /* properties_provided */
|
|
0, /* properties_destroyed */
|
|
0, /* todo_flags_start */
|
|
( TODO_cleanup_cfg
|
|
| TODO_update_ssa_only_virtuals ), /* todo_flags_finish */
|
|
};
|
|
|
|
class pass_scev_cprop : public gimple_opt_pass
|
|
{
|
|
public:
|
|
pass_scev_cprop (gcc::context *ctxt)
|
|
: gimple_opt_pass (pass_data_scev_cprop, ctxt)
|
|
{}
|
|
|
|
/* opt_pass methods: */
|
|
virtual bool gate (function *) { return flag_tree_scev_cprop; }
|
|
virtual unsigned int execute (function *) { return scev_const_prop (); }
|
|
|
|
}; // class pass_scev_cprop
|
|
|
|
} // anon namespace
|
|
|
|
gimple_opt_pass *
|
|
make_pass_scev_cprop (gcc::context *ctxt)
|
|
{
|
|
return new pass_scev_cprop (ctxt);
|
|
}
|
|
|
|
/* Record bounds on numbers of iterations of loops. */
|
|
|
|
namespace {
|
|
|
|
const pass_data pass_data_record_bounds =
|
|
{
|
|
GIMPLE_PASS, /* type */
|
|
"*record_bounds", /* name */
|
|
OPTGROUP_NONE, /* optinfo_flags */
|
|
TV_TREE_LOOP_BOUNDS, /* tv_id */
|
|
( PROP_cfg | PROP_ssa ), /* properties_required */
|
|
0, /* properties_provided */
|
|
0, /* properties_destroyed */
|
|
0, /* todo_flags_start */
|
|
0, /* todo_flags_finish */
|
|
};
|
|
|
|
class pass_record_bounds : public gimple_opt_pass
|
|
{
|
|
public:
|
|
pass_record_bounds (gcc::context *ctxt)
|
|
: gimple_opt_pass (pass_data_record_bounds, ctxt)
|
|
{}
|
|
|
|
/* opt_pass methods: */
|
|
virtual unsigned int execute (function *);
|
|
|
|
}; // class pass_record_bounds
|
|
|
|
unsigned int
|
|
pass_record_bounds::execute (function *fun)
|
|
{
|
|
if (number_of_loops (fun) <= 1)
|
|
return 0;
|
|
|
|
estimate_numbers_of_iterations ();
|
|
scev_reset ();
|
|
return 0;
|
|
}
|
|
|
|
} // anon namespace
|
|
|
|
gimple_opt_pass *
|
|
make_pass_record_bounds (gcc::context *ctxt)
|
|
{
|
|
return new pass_record_bounds (ctxt);
|
|
}
|
|
|
|
/* Induction variable optimizations. */
|
|
|
|
namespace {
|
|
|
|
const pass_data pass_data_iv_optimize =
|
|
{
|
|
GIMPLE_PASS, /* type */
|
|
"ivopts", /* name */
|
|
OPTGROUP_LOOP, /* optinfo_flags */
|
|
TV_TREE_LOOP_IVOPTS, /* tv_id */
|
|
( PROP_cfg | PROP_ssa ), /* properties_required */
|
|
0, /* properties_provided */
|
|
0, /* properties_destroyed */
|
|
0, /* todo_flags_start */
|
|
TODO_update_ssa, /* todo_flags_finish */
|
|
};
|
|
|
|
class pass_iv_optimize : public gimple_opt_pass
|
|
{
|
|
public:
|
|
pass_iv_optimize (gcc::context *ctxt)
|
|
: gimple_opt_pass (pass_data_iv_optimize, ctxt)
|
|
{}
|
|
|
|
/* opt_pass methods: */
|
|
virtual bool gate (function *) { return flag_ivopts != 0; }
|
|
virtual unsigned int execute (function *);
|
|
|
|
}; // class pass_iv_optimize
|
|
|
|
unsigned int
|
|
pass_iv_optimize::execute (function *fun)
|
|
{
|
|
if (number_of_loops (fun) <= 1)
|
|
return 0;
|
|
|
|
tree_ssa_iv_optimize ();
|
|
return 0;
|
|
}
|
|
|
|
} // anon namespace
|
|
|
|
gimple_opt_pass *
|
|
make_pass_iv_optimize (gcc::context *ctxt)
|
|
{
|
|
return new pass_iv_optimize (ctxt);
|
|
}
|
|
|
|
/* Loop optimizer finalization. */
|
|
|
|
static unsigned int
|
|
tree_ssa_loop_done (void)
|
|
{
|
|
free_numbers_of_iterations_estimates ();
|
|
scev_finalize ();
|
|
loop_optimizer_finalize ();
|
|
return 0;
|
|
}
|
|
|
|
namespace {
|
|
|
|
const pass_data pass_data_tree_loop_done =
|
|
{
|
|
GIMPLE_PASS, /* type */
|
|
"loopdone", /* name */
|
|
OPTGROUP_LOOP, /* optinfo_flags */
|
|
TV_NONE, /* tv_id */
|
|
PROP_cfg, /* properties_required */
|
|
0, /* properties_provided */
|
|
0, /* properties_destroyed */
|
|
0, /* todo_flags_start */
|
|
TODO_cleanup_cfg, /* todo_flags_finish */
|
|
};
|
|
|
|
class pass_tree_loop_done : public gimple_opt_pass
|
|
{
|
|
public:
|
|
pass_tree_loop_done (gcc::context *ctxt)
|
|
: gimple_opt_pass (pass_data_tree_loop_done, ctxt)
|
|
{}
|
|
|
|
/* opt_pass methods: */
|
|
virtual unsigned int execute (function *) { return tree_ssa_loop_done (); }
|
|
|
|
}; // class pass_tree_loop_done
|
|
|
|
} // anon namespace
|
|
|
|
gimple_opt_pass *
|
|
make_pass_tree_loop_done (gcc::context *ctxt)
|
|
{
|
|
return new pass_tree_loop_done (ctxt);
|
|
}
|
|
|
|
/* Calls CBCK for each index in memory reference ADDR_P. There are two
|
|
kinds situations handled; in each of these cases, the memory reference
|
|
and DATA are passed to the callback:
|
|
|
|
Access to an array: ARRAY_{RANGE_}REF (base, index). In this case we also
|
|
pass the pointer to the index to the callback.
|
|
|
|
Pointer dereference: INDIRECT_REF (addr). In this case we also pass the
|
|
pointer to addr to the callback.
|
|
|
|
If the callback returns false, the whole search stops and false is returned.
|
|
Otherwise the function returns true after traversing through the whole
|
|
reference *ADDR_P. */
|
|
|
|
bool
|
|
for_each_index (tree *addr_p, bool (*cbck) (tree, tree *, void *), void *data)
|
|
{
|
|
tree *nxt, *idx;
|
|
|
|
for (; ; addr_p = nxt)
|
|
{
|
|
switch (TREE_CODE (*addr_p))
|
|
{
|
|
case SSA_NAME:
|
|
return cbck (*addr_p, addr_p, data);
|
|
|
|
case MEM_REF:
|
|
nxt = &TREE_OPERAND (*addr_p, 0);
|
|
return cbck (*addr_p, nxt, data);
|
|
|
|
case BIT_FIELD_REF:
|
|
case VIEW_CONVERT_EXPR:
|
|
case REALPART_EXPR:
|
|
case IMAGPART_EXPR:
|
|
nxt = &TREE_OPERAND (*addr_p, 0);
|
|
break;
|
|
|
|
case COMPONENT_REF:
|
|
/* If the component has varying offset, it behaves like index
|
|
as well. */
|
|
idx = &TREE_OPERAND (*addr_p, 2);
|
|
if (*idx
|
|
&& !cbck (*addr_p, idx, data))
|
|
return false;
|
|
|
|
nxt = &TREE_OPERAND (*addr_p, 0);
|
|
break;
|
|
|
|
case ARRAY_REF:
|
|
case ARRAY_RANGE_REF:
|
|
nxt = &TREE_OPERAND (*addr_p, 0);
|
|
if (!cbck (*addr_p, &TREE_OPERAND (*addr_p, 1), data))
|
|
return false;
|
|
break;
|
|
|
|
case VAR_DECL:
|
|
case PARM_DECL:
|
|
case CONST_DECL:
|
|
case STRING_CST:
|
|
case RESULT_DECL:
|
|
case VECTOR_CST:
|
|
case COMPLEX_CST:
|
|
case INTEGER_CST:
|
|
case REAL_CST:
|
|
case FIXED_CST:
|
|
case CONSTRUCTOR:
|
|
return true;
|
|
|
|
case ADDR_EXPR:
|
|
gcc_assert (is_gimple_min_invariant (*addr_p));
|
|
return true;
|
|
|
|
case TARGET_MEM_REF:
|
|
idx = &TMR_BASE (*addr_p);
|
|
if (*idx
|
|
&& !cbck (*addr_p, idx, data))
|
|
return false;
|
|
idx = &TMR_INDEX (*addr_p);
|
|
if (*idx
|
|
&& !cbck (*addr_p, idx, data))
|
|
return false;
|
|
idx = &TMR_INDEX2 (*addr_p);
|
|
if (*idx
|
|
&& !cbck (*addr_p, idx, data))
|
|
return false;
|
|
return true;
|
|
|
|
default:
|
|
gcc_unreachable ();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/* The name and the length of the currently generated variable
|
|
for lsm. */
|
|
#define MAX_LSM_NAME_LENGTH 40
|
|
static char lsm_tmp_name[MAX_LSM_NAME_LENGTH + 1];
|
|
static int lsm_tmp_name_length;
|
|
|
|
/* Adds S to lsm_tmp_name. */
|
|
|
|
static void
|
|
lsm_tmp_name_add (const char *s)
|
|
{
|
|
int l = strlen (s) + lsm_tmp_name_length;
|
|
if (l > MAX_LSM_NAME_LENGTH)
|
|
return;
|
|
|
|
strcpy (lsm_tmp_name + lsm_tmp_name_length, s);
|
|
lsm_tmp_name_length = l;
|
|
}
|
|
|
|
/* Stores the name for temporary variable that replaces REF to
|
|
lsm_tmp_name. */
|
|
|
|
static void
|
|
gen_lsm_tmp_name (tree ref)
|
|
{
|
|
const char *name;
|
|
|
|
switch (TREE_CODE (ref))
|
|
{
|
|
case MEM_REF:
|
|
case TARGET_MEM_REF:
|
|
gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
|
|
lsm_tmp_name_add ("_");
|
|
break;
|
|
|
|
case ADDR_EXPR:
|
|
gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
|
|
break;
|
|
|
|
case BIT_FIELD_REF:
|
|
case VIEW_CONVERT_EXPR:
|
|
case ARRAY_RANGE_REF:
|
|
gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
|
|
break;
|
|
|
|
case REALPART_EXPR:
|
|
gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
|
|
lsm_tmp_name_add ("_RE");
|
|
break;
|
|
|
|
case IMAGPART_EXPR:
|
|
gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
|
|
lsm_tmp_name_add ("_IM");
|
|
break;
|
|
|
|
case COMPONENT_REF:
|
|
gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
|
|
lsm_tmp_name_add ("_");
|
|
name = get_name (TREE_OPERAND (ref, 1));
|
|
if (!name)
|
|
name = "F";
|
|
lsm_tmp_name_add (name);
|
|
break;
|
|
|
|
case ARRAY_REF:
|
|
gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
|
|
lsm_tmp_name_add ("_I");
|
|
break;
|
|
|
|
case SSA_NAME:
|
|
case VAR_DECL:
|
|
case PARM_DECL:
|
|
name = get_name (ref);
|
|
if (!name)
|
|
name = "D";
|
|
lsm_tmp_name_add (name);
|
|
break;
|
|
|
|
case STRING_CST:
|
|
lsm_tmp_name_add ("S");
|
|
break;
|
|
|
|
case RESULT_DECL:
|
|
lsm_tmp_name_add ("R");
|
|
break;
|
|
|
|
case INTEGER_CST:
|
|
/* Nothing. */
|
|
break;
|
|
|
|
default:
|
|
gcc_unreachable ();
|
|
}
|
|
}
|
|
|
|
/* Determines name for temporary variable that replaces REF.
|
|
The name is accumulated into the lsm_tmp_name variable.
|
|
N is added to the name of the temporary. */
|
|
|
|
char *
|
|
get_lsm_tmp_name (tree ref, unsigned n, const char *suffix)
|
|
{
|
|
char ns[2];
|
|
|
|
lsm_tmp_name_length = 0;
|
|
gen_lsm_tmp_name (ref);
|
|
lsm_tmp_name_add ("_lsm");
|
|
if (n < 10)
|
|
{
|
|
ns[0] = '0' + n;
|
|
ns[1] = 0;
|
|
lsm_tmp_name_add (ns);
|
|
}
|
|
return lsm_tmp_name;
|
|
if (suffix != NULL)
|
|
lsm_tmp_name_add (suffix);
|
|
}
|
|
|
|
/* Computes an estimated number of insns in LOOP, weighted by WEIGHTS. */
|
|
|
|
unsigned
|
|
tree_num_loop_insns (struct loop *loop, eni_weights *weights)
|
|
{
|
|
basic_block *body = get_loop_body (loop);
|
|
gimple_stmt_iterator gsi;
|
|
unsigned size = 0, i;
|
|
|
|
for (i = 0; i < loop->num_nodes; i++)
|
|
for (gsi = gsi_start_bb (body[i]); !gsi_end_p (gsi); gsi_next (&gsi))
|
|
size += estimate_num_insns (gsi_stmt (gsi), weights);
|
|
free (body);
|
|
|
|
return size;
|
|
}
|
|
|
|
|
|
|