8sa1-gcc/gcc/tree-ssa-loop.c
Jakub Jelinek 74bf76ed78 Makefile.in (omp-low.o): Depend on $(TARGET_H).
* Makefile.in (omp-low.o): Depend on $(TARGET_H).
	* cfgloop.h (struct loop): Add safelen, force_vect, simduid.
	* function.h (struct function): Add has_force_vect_loops and
	has_simduid_loops.
	* gimple-pretty-print.c (dump_gimple_omp_for): Handle
	GF_OMP_FOR_KIND*.
	* gimple.c (gimple_build_omp_critical): Add KIND argument and
	handle it.
	* gimple.def: Update CLAUSES comments.
	* gimple.h (enum gf_mask): Add GF_OMP_FOR_KIND_{FOR,SIMD}.
	(gimple_build_omp_for): Add argument to prototype.
	(gimple_omp_for_kind): New.
	(gimple_omp_for_set_kind): New.
	* gimplify.c (enum gimplify_omp_var_data): Add GOVD_LINEAR to
	GOVD_DATA_SHARE_CLASS.
	(enum omp_region_type): Add ORT_SIMD.
	(gimple_add_tmp_var): Handle ORT_SIMD.
	(gimplify_var_or_parm_decl): Same.
	(is_gimple_stmt): Same.
	(omp_firstprivatize_variable): Same.
	(omp_add_variable): Only use splay_tree_insert if lookup failed.
	(omp_notice_variable): Handle ORT_SIMD.
	(omp_is_private): Add SIMD argument and handle it as well as
	ORT_SIMD.
	(omp_check_private): Handle ORT_SIMD.
	(gimplify_scan_omp_clauses): Handle OMP_CLAUSE_LINEAR and
	OMP_CLAUSE_SAFELEN.
	(gimplify_adjust_omp_clauses_1): Handle GOVD_LINEAR.
	Handle OMP_CLAUSE_LASTPRIVATE.
	(gimplify_adjust_omp_clauses): Handle OMP_CLAUSE_LINEAR and
	OMP_CLAUSE_SAFELEN.
	(gimplify_omp_for): Handle OMP_SIMD and OMP_CLAUSE_LINEAR.
	(gimplify_expr): Handle OMP_SIMD.
	* internal-fn.c (expand_GOMP_SIMD_LANE): New.
	(expand_GOMP_SIMD_VF): New.
	(expand_GOMP_SIMD_LAST_LANE): New.
	* internal-fn.def (GOMP_SIMD_LANE): New.
	(GOMP_SIMD_VF): New.
	(GOMP_SIMD_LAST_LANE): New.
	* omp-low.c: Include target.h.
	(extract_omp_for_data): Handle OMP_SIMD, OMP_CLAUSE_LINEAR,
	OMP_CLAUSE_SAFELEN.
	(check_omp_nesting_restrictions): Same.
	(omp_max_vf): New.
	(lower_rec_simd_input_clauses): New.
	(lower_rec_input_clauses): Handle OMP_SIMD, GF_OMP_FOR_KIND_SIMD,
	OMP_CLAUSE_LINEAR.
	(lower_lastprivate_clauses): Handle OMP_CLAUSE_LINEAR,
	GF_OMP_FOR_KIND_SIMD, OMP_SIMD.
	(expand_omp_build_assign): New.
	(expand_omp_for_init_counts): New.
	(expand_omp_for_init_vars): New.
	(extract_omp_for_update_vars): New.
	(expand_omp_for_generic): Use expand_omp_for_{init,update}_vars
	and rewrite accordingly.
	(expand_omp_simd): New.
	(expand_omp_for): Use expand_omp_simd.
	(lower_omp_for_lastprivate): Unshare vinit when appropriate.
	(lower_omp_for): Do not lower the body.
	* tree-data-ref (get_references_in_stmt): Allow IFN_GOMP_SIMD_LANE
	in their own loops.
	* tree-flow.h (find_omp_clause): Remove prototype.
	* tree-if-conv.c (main_tree_if_conversion): Run if doing if
	conversion, forcing vectorization of the loop, or if
	flag_tree_vectorize.
	(gate_tree_if_conversion): Similarly.
	* tree-inline.c (remap_gimple_stmt): Pass for kind argument to
	gimple_build_omp_for.
	(copy_cfg_body): set has_force_vect_loops and has_simduid_loops.
	* tree-parloops (create_parallel_loop): Pass kind argument to
	gimple_build_omp_for.
	* tree-pretty-print.c (dump_omp_clause): Add cases for
	OMP_CLAUSE_UNIFORM, OMP_CLAUSE_LINEAR, OMP_CLAUSE_SAFELEN,
	OMP_CLAUSE__SIMDUID_.
	(dump_generic_node): Handle OMP_SIMD.
	* tree-ssa-ccp.c (likely_value): Handle IFN_GOMP_SIMD*.
	* tree-ssa-loop-ivcanon.c (tree_unroll_loops_completely_1): Do not
	unroll OMP_SIMD loops here.
	* tree-ssa-loop.c (gate_tree_vectorize): Run if
	has_force_vect_loops.
	* tree-vect-data-refs.c (vect_analyze_data_ref_dependence): Handle
	loop->safelen
	(vect_analyze_data_refs): Handle simd loops.
	* tree-vect-loop.c (vectorizable_live_operation): Handle
	IFN_GOMP_SIMD*.
	* tree-vect-stmts.c (vectorizable_call): Handle
	IFN_GOMP_SIMD_LANE.
	(vectorizable_store): Handle STMT_VINFO_SIMD_LANE_ACCESS_P.
	(vectorizable_load): Same.
	* tree-vectorizer.c: Include hash-table.h and
	tree-ssa-propagate.h.
	(struct simduid_to_vf): New.
	(simduid_to_vf::hash): New.
	(simduid_to-vf::equal): New.
	(struct simd_array_to_simduid): New.
	(simd_array_to_simduid::hash): New.
	(simd_array_to_simduid::equal): New.
	(adjust_simduid_builtins): New.
	(struct note_simd_array_uses_struct): New.
	(note_simd_array_uses_cb): New.
	(note_simd_array_uses): New.
	(vectorize_loops): Handle simd hints and adjust simd builtins
	accordingly.
	* tree-vectorizer.h (struct _stmt_vec_info): Add
	simd_lane_access_p field.
	(STMT_VINFO_SIMD_LANE_ACCESS_P): New macro.
	* tree.c (omp_clause_num_ops): Add entries for OMP_CLAUSE_LINEAR,
	OMP_CLAUSE_SAFELEN, OMP_CLAUSE__SIMDUID_, OMP_CLAUSE_UNIFORM.
	(omp_clause_code_name): Same.
	(walk_tree_1): Handle OMP_CLAUSE_UNIFORM, OMP_CLAUSE_SAFELEN,
	OMP_CLAUSE__SIMDUID_, OMP_CLAUSE_LINEAR.
	* tree.def (OMP_SIMD): New entry.
	* tree.h (enum omp_clause_code): Add entries for
	OMP_CLAUSE_LINEAR, OMP_CLAUSE_UNIFORM, OMP_CLAUSE_SAFELEN,
	OMP_CLAUSE__SIMDUID_.
	(OMP_CLAUSE_DECL): Adjust range for new clauses.
	(OMP_CLAUSE_LINEAR_NO_COPYIN): New.
	(OMP_CLAUSE_LINEAR_NO_COPYOUT): New.
	(OMP_CLAUSE_LINEAR_STEP): New.
	(OMP_CLAUSE_SAFELEN_EXPR): New.
	(OMP_CLAUSE__SIMDUID__DECL): New.
	(find_omp_clause): New prototype.
cp/
	* cp-tree.h (CP_OMP_CLAUSE_INFO): Adjust range for new clauses.

Co-Authored-By: Aldy Hernandez <aldyh@redhat.com>

From-SVN: r202029
2013-08-27 18:38:00 +00:00

1007 lines
21 KiB
C

/* Loop optimizations over tree-ssa.
Copyright (C) 2003-2013 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 "tm.h"
#include "tree.h"
#include "tm_p.h"
#include "basic-block.h"
#include "tree-flow.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"
/* The loop superpass. */
static bool
gate_tree_loop (void)
{
return flag_tree_loop_optimize != 0;
}
namespace {
const pass_data pass_data_tree_loop =
{
GIMPLE_PASS, /* type */
"loop", /* name */
OPTGROUP_LOOP, /* optinfo_flags */
true, /* has_gate */
false, /* has_execute */
TV_TREE_LOOP, /* tv_id */
PROP_cfg, /* properties_required */
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
TODO_verify_ssa, /* 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: */
bool gate () { return gate_tree_loop (); }
}; // class pass_tree_loop
} // anon namespace
gimple_opt_pass *
make_pass_tree_loop (gcc::context *ctxt)
{
return new pass_tree_loop (ctxt);
}
/* Loop optimizer initialization. */
static unsigned int
tree_ssa_loop_init (void)
{
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 ();
if (number_of_loops (cfun) <= 1)
return 0;
return 0;
}
namespace {
const pass_data pass_data_tree_loop_init =
{
GIMPLE_PASS, /* type */
"loopinit", /* name */
OPTGROUP_LOOP, /* optinfo_flags */
false, /* has_gate */
true, /* has_execute */
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: */
unsigned int execute () { return tree_ssa_loop_init (); }
}; // class pass_tree_loop_init
} // anon namespace
gimple_opt_pass *
make_pass_tree_loop_init (gcc::context *ctxt)
{
return new pass_tree_loop_init (ctxt);
}
/* Loop invariant motion pass. */
static unsigned int
tree_ssa_loop_im (void)
{
if (number_of_loops (cfun) <= 1)
return 0;
return tree_ssa_lim ();
}
static bool
gate_tree_ssa_loop_im (void)
{
return flag_tree_loop_im != 0;
}
namespace {
const pass_data pass_data_lim =
{
GIMPLE_PASS, /* type */
"lim", /* name */
OPTGROUP_LOOP, /* optinfo_flags */
true, /* has_gate */
true, /* has_execute */
TV_LIM, /* tv_id */
PROP_cfg, /* properties_required */
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
0, /* todo_flags_finish */
};
class pass_lim : public gimple_opt_pass
{
public:
pass_lim(gcc::context *ctxt)
: gimple_opt_pass(pass_data_lim, ctxt)
{}
/* opt_pass methods: */
opt_pass * clone () { return new pass_lim (ctxt_); }
bool gate () { return gate_tree_ssa_loop_im (); }
unsigned int execute () { return tree_ssa_loop_im (); }
}; // class pass_lim
} // anon namespace
gimple_opt_pass *
make_pass_lim (gcc::context *ctxt)
{
return new pass_lim (ctxt);
}
/* Loop unswitching pass. */
static unsigned int
tree_ssa_loop_unswitch (void)
{
if (number_of_loops (cfun) <= 1)
return 0;
return tree_ssa_unswitch_loops ();
}
static bool
gate_tree_ssa_loop_unswitch (void)
{
return flag_unswitch_loops != 0;
}
namespace {
const pass_data pass_data_tree_unswitch =
{
GIMPLE_PASS, /* type */
"unswitch", /* name */
OPTGROUP_LOOP, /* optinfo_flags */
true, /* has_gate */
true, /* has_execute */
TV_TREE_LOOP_UNSWITCH, /* tv_id */
PROP_cfg, /* properties_required */
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
0, /* todo_flags_finish */
};
class pass_tree_unswitch : public gimple_opt_pass
{
public:
pass_tree_unswitch(gcc::context *ctxt)
: gimple_opt_pass(pass_data_tree_unswitch, ctxt)
{}
/* opt_pass methods: */
bool gate () { return gate_tree_ssa_loop_unswitch (); }
unsigned int execute () { return tree_ssa_loop_unswitch (); }
}; // class pass_tree_unswitch
} // anon namespace
gimple_opt_pass *
make_pass_tree_unswitch (gcc::context *ctxt)
{
return new pass_tree_unswitch (ctxt);
}
/* Predictive commoning. */
static unsigned
run_tree_predictive_commoning (void)
{
if (!current_loops)
return 0;
return tree_predictive_commoning ();
}
static bool
gate_tree_predictive_commoning (void)
{
return flag_predictive_commoning != 0;
}
namespace {
const pass_data pass_data_predcom =
{
GIMPLE_PASS, /* type */
"pcom", /* name */
OPTGROUP_LOOP, /* optinfo_flags */
true, /* has_gate */
true, /* has_execute */
TV_PREDCOM, /* tv_id */
PROP_cfg, /* properties_required */
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
TODO_update_ssa_only_virtuals, /* todo_flags_finish */
};
class pass_predcom : public gimple_opt_pass
{
public:
pass_predcom(gcc::context *ctxt)
: gimple_opt_pass(pass_data_predcom, ctxt)
{}
/* opt_pass methods: */
bool gate () { return gate_tree_predictive_commoning (); }
unsigned int execute () { return run_tree_predictive_commoning (); }
}; // class pass_predcom
} // anon namespace
gimple_opt_pass *
make_pass_predcom (gcc::context *ctxt)
{
return new pass_predcom (ctxt);
}
/* Loop autovectorization. */
static unsigned int
tree_vectorize (void)
{
if (number_of_loops (cfun) <= 1)
return 0;
return vectorize_loops ();
}
static bool
gate_tree_vectorize (void)
{
return flag_tree_vectorize || cfun->has_force_vect_loops;
}
namespace {
const pass_data pass_data_vectorize =
{
GIMPLE_PASS, /* type */
"vect", /* name */
OPTGROUP_LOOP | OPTGROUP_VEC, /* optinfo_flags */
true, /* has_gate */
true, /* has_execute */
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: */
bool gate () { return gate_tree_vectorize (); }
unsigned int execute () { return tree_vectorize (); }
}; // class pass_vectorize
} // anon namespace
gimple_opt_pass *
make_pass_vectorize (gcc::context *ctxt)
{
return new pass_vectorize (ctxt);
}
/* GRAPHITE optimizations. */
static unsigned int
graphite_transforms (void)
{
if (!current_loops)
return 0;
graphite_transform_loops ();
return 0;
}
static bool
gate_graphite_transforms (void)
{
/* Enable -fgraphite pass if any one of the graphite optimization flags
is turned on. */
if (flag_loop_block
|| flag_loop_interchange
|| flag_loop_strip_mine
|| flag_graphite_identity
|| flag_loop_parallelize_all
|| flag_loop_optimize_isl)
flag_graphite = 1;
return flag_graphite != 0;
}
namespace {
const pass_data pass_data_graphite =
{
GIMPLE_PASS, /* type */
"graphite0", /* name */
OPTGROUP_LOOP, /* optinfo_flags */
true, /* has_gate */
false, /* has_execute */
TV_GRAPHITE, /* tv_id */
( PROP_cfg | PROP_ssa ), /* properties_required */
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
0, /* todo_flags_finish */
};
class pass_graphite : public gimple_opt_pass
{
public:
pass_graphite(gcc::context *ctxt)
: gimple_opt_pass(pass_data_graphite, ctxt)
{}
/* opt_pass methods: */
bool gate () { return gate_graphite_transforms (); }
}; // class pass_graphite
} // anon namespace
gimple_opt_pass *
make_pass_graphite (gcc::context *ctxt)
{
return new pass_graphite (ctxt);
}
namespace {
const pass_data pass_data_graphite_transforms =
{
GIMPLE_PASS, /* type */
"graphite", /* name */
OPTGROUP_LOOP, /* optinfo_flags */
true, /* has_gate */
true, /* has_execute */
TV_GRAPHITE_TRANSFORMS, /* tv_id */
( PROP_cfg | PROP_ssa ), /* properties_required */
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
0, /* todo_flags_finish */
};
class pass_graphite_transforms : public gimple_opt_pass
{
public:
pass_graphite_transforms(gcc::context *ctxt)
: gimple_opt_pass(pass_data_graphite_transforms, ctxt)
{}
/* opt_pass methods: */
bool gate () { return gate_graphite_transforms (); }
unsigned int execute () { return graphite_transforms (); }
}; // class pass_graphite_transforms
} // anon namespace
gimple_opt_pass *
make_pass_graphite_transforms (gcc::context *ctxt)
{
return new pass_graphite_transforms (ctxt);
}
/* Check the correctness of the data dependence analyzers. */
static unsigned int
check_data_deps (void)
{
if (number_of_loops (cfun) <= 1)
return 0;
tree_check_data_deps ();
return 0;
}
static bool
gate_check_data_deps (void)
{
return flag_check_data_deps != 0;
}
namespace {
const pass_data pass_data_check_data_deps =
{
GIMPLE_PASS, /* type */
"ckdd", /* name */
OPTGROUP_LOOP, /* optinfo_flags */
true, /* has_gate */
true, /* has_execute */
TV_CHECK_DATA_DEPS, /* tv_id */
( PROP_cfg | PROP_ssa ), /* properties_required */
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
0, /* todo_flags_finish */
};
class pass_check_data_deps : public gimple_opt_pass
{
public:
pass_check_data_deps(gcc::context *ctxt)
: gimple_opt_pass(pass_data_check_data_deps, ctxt)
{}
/* opt_pass methods: */
bool gate () { return gate_check_data_deps (); }
unsigned int execute () { return check_data_deps (); }
}; // class pass_check_data_deps
} // anon namespace
gimple_opt_pass *
make_pass_check_data_deps (gcc::context *ctxt)
{
return new pass_check_data_deps (ctxt);
}
/* Canonical induction variable creation pass. */
static unsigned int
tree_ssa_loop_ivcanon (void)
{
if (number_of_loops (cfun) <= 1)
return 0;
return canonicalize_induction_variables ();
}
static bool
gate_tree_ssa_loop_ivcanon (void)
{
return flag_tree_loop_ivcanon != 0;
}
namespace {
const pass_data pass_data_iv_canon =
{
GIMPLE_PASS, /* type */
"ivcanon", /* name */
OPTGROUP_LOOP, /* optinfo_flags */
true, /* has_gate */
true, /* has_execute */
TV_TREE_LOOP_IVCANON, /* tv_id */
( PROP_cfg | PROP_ssa ), /* properties_required */
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
0, /* todo_flags_finish */
};
class pass_iv_canon : public gimple_opt_pass
{
public:
pass_iv_canon(gcc::context *ctxt)
: gimple_opt_pass(pass_data_iv_canon, ctxt)
{}
/* opt_pass methods: */
bool gate () { return gate_tree_ssa_loop_ivcanon (); }
unsigned int execute () { return tree_ssa_loop_ivcanon (); }
}; // class pass_iv_canon
} // anon namespace
gimple_opt_pass *
make_pass_iv_canon (gcc::context *ctxt)
{
return new pass_iv_canon (ctxt);
}
/* Propagation of constants using scev. */
static bool
gate_scev_const_prop (void)
{
return flag_tree_scev_cprop;
}
namespace {
const pass_data pass_data_scev_cprop =
{
GIMPLE_PASS, /* type */
"sccp", /* name */
OPTGROUP_LOOP, /* optinfo_flags */
true, /* has_gate */
true, /* has_execute */
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: */
bool gate () { return gate_scev_const_prop (); }
unsigned int execute () { 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. */
static unsigned int
tree_ssa_loop_bounds (void)
{
if (number_of_loops (cfun) <= 1)
return 0;
estimate_numbers_of_iterations ();
scev_reset ();
return 0;
}
namespace {
const pass_data pass_data_record_bounds =
{
GIMPLE_PASS, /* type */
"*record_bounds", /* name */
OPTGROUP_NONE, /* optinfo_flags */
false, /* has_gate */
true, /* has_execute */
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: */
unsigned int execute () { return tree_ssa_loop_bounds (); }
}; // class pass_record_bounds
} // anon namespace
gimple_opt_pass *
make_pass_record_bounds (gcc::context *ctxt)
{
return new pass_record_bounds (ctxt);
}
/* Complete unrolling of loops. */
static unsigned int
tree_complete_unroll (void)
{
if (number_of_loops (cfun) <= 1)
return 0;
return tree_unroll_loops_completely (flag_unroll_loops
|| flag_peel_loops
|| optimize >= 3, true);
}
static bool
gate_tree_complete_unroll (void)
{
return true;
}
namespace {
const pass_data pass_data_complete_unroll =
{
GIMPLE_PASS, /* type */
"cunroll", /* name */
OPTGROUP_LOOP, /* optinfo_flags */
true, /* has_gate */
true, /* has_execute */
TV_COMPLETE_UNROLL, /* tv_id */
( PROP_cfg | PROP_ssa ), /* properties_required */
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
0, /* todo_flags_finish */
};
class pass_complete_unroll : public gimple_opt_pass
{
public:
pass_complete_unroll(gcc::context *ctxt)
: gimple_opt_pass(pass_data_complete_unroll, ctxt)
{}
/* opt_pass methods: */
bool gate () { return gate_tree_complete_unroll (); }
unsigned int execute () { return tree_complete_unroll (); }
}; // class pass_complete_unroll
} // anon namespace
gimple_opt_pass *
make_pass_complete_unroll (gcc::context *ctxt)
{
return new pass_complete_unroll (ctxt);
}
/* Complete unrolling of inner loops. */
static unsigned int
tree_complete_unroll_inner (void)
{
unsigned ret = 0;
loop_optimizer_init (LOOPS_NORMAL
| LOOPS_HAVE_RECORDED_EXITS);
if (number_of_loops (cfun) > 1)
{
scev_initialize ();
ret = tree_unroll_loops_completely (optimize >= 3, false);
free_numbers_of_iterations_estimates ();
scev_finalize ();
}
loop_optimizer_finalize ();
return ret;
}
static bool
gate_tree_complete_unroll_inner (void)
{
return optimize >= 2;
}
namespace {
const pass_data pass_data_complete_unrolli =
{
GIMPLE_PASS, /* type */
"cunrolli", /* name */
OPTGROUP_LOOP, /* optinfo_flags */
true, /* has_gate */
true, /* has_execute */
TV_COMPLETE_UNROLL, /* tv_id */
( PROP_cfg | PROP_ssa ), /* properties_required */
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
TODO_verify_flow, /* todo_flags_finish */
};
class pass_complete_unrolli : public gimple_opt_pass
{
public:
pass_complete_unrolli(gcc::context *ctxt)
: gimple_opt_pass(pass_data_complete_unrolli, ctxt)
{}
/* opt_pass methods: */
bool gate () { return gate_tree_complete_unroll_inner (); }
unsigned int execute () { return tree_complete_unroll_inner (); }
}; // class pass_complete_unrolli
} // anon namespace
gimple_opt_pass *
make_pass_complete_unrolli (gcc::context *ctxt)
{
return new pass_complete_unrolli (ctxt);
}
/* Parallelization. */
static bool
gate_tree_parallelize_loops (void)
{
return flag_tree_parallelize_loops > 1;
}
static unsigned
tree_parallelize_loops (void)
{
if (number_of_loops (cfun) <= 1)
return 0;
if (parallelize_loops ())
return TODO_cleanup_cfg | TODO_rebuild_alias;
return 0;
}
namespace {
const pass_data pass_data_parallelize_loops =
{
GIMPLE_PASS, /* type */
"parloops", /* name */
OPTGROUP_LOOP, /* optinfo_flags */
true, /* has_gate */
true, /* has_execute */
TV_TREE_PARALLELIZE_LOOPS, /* tv_id */
( PROP_cfg | PROP_ssa ), /* properties_required */
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
TODO_verify_flow, /* todo_flags_finish */
};
class pass_parallelize_loops : public gimple_opt_pass
{
public:
pass_parallelize_loops(gcc::context *ctxt)
: gimple_opt_pass(pass_data_parallelize_loops, ctxt)
{}
/* opt_pass methods: */
bool gate () { return gate_tree_parallelize_loops (); }
unsigned int execute () { return tree_parallelize_loops (); }
}; // class pass_parallelize_loops
} // anon namespace
gimple_opt_pass *
make_pass_parallelize_loops (gcc::context *ctxt)
{
return new pass_parallelize_loops (ctxt);
}
/* Prefetching. */
static unsigned int
tree_ssa_loop_prefetch (void)
{
if (number_of_loops (cfun) <= 1)
return 0;
return tree_ssa_prefetch_arrays ();
}
static bool
gate_tree_ssa_loop_prefetch (void)
{
return flag_prefetch_loop_arrays > 0;
}
namespace {
const pass_data pass_data_loop_prefetch =
{
GIMPLE_PASS, /* type */
"aprefetch", /* name */
OPTGROUP_LOOP, /* optinfo_flags */
true, /* has_gate */
true, /* has_execute */
TV_TREE_PREFETCH, /* tv_id */
( PROP_cfg | PROP_ssa ), /* properties_required */
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
0, /* todo_flags_finish */
};
class pass_loop_prefetch : public gimple_opt_pass
{
public:
pass_loop_prefetch(gcc::context *ctxt)
: gimple_opt_pass(pass_data_loop_prefetch, ctxt)
{}
/* opt_pass methods: */
bool gate () { return gate_tree_ssa_loop_prefetch (); }
unsigned int execute () { return tree_ssa_loop_prefetch (); }
}; // class pass_loop_prefetch
} // anon namespace
gimple_opt_pass *
make_pass_loop_prefetch (gcc::context *ctxt)
{
return new pass_loop_prefetch (ctxt);
}
/* Induction variable optimizations. */
static unsigned int
tree_ssa_loop_ivopts (void)
{
if (number_of_loops (cfun) <= 1)
return 0;
tree_ssa_iv_optimize ();
return 0;
}
static bool
gate_tree_ssa_loop_ivopts (void)
{
return flag_ivopts != 0;
}
namespace {
const pass_data pass_data_iv_optimize =
{
GIMPLE_PASS, /* type */
"ivopts", /* name */
OPTGROUP_LOOP, /* optinfo_flags */
true, /* has_gate */
true, /* has_execute */
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: */
bool gate () { return gate_tree_ssa_loop_ivopts (); }
unsigned int execute () { return tree_ssa_loop_ivopts (); }
}; // class pass_iv_optimize
} // 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 */
false, /* has_gate */
true, /* has_execute */
TV_NONE, /* tv_id */
PROP_cfg, /* properties_required */
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
( TODO_cleanup_cfg | TODO_verify_flow ), /* 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: */
unsigned int execute () { 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);
}