#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "tm.h"
#include "tree.h"
#include "rtl.h"
#include "tm_p.h"
#include "hard-reg-set.h"
#include "basic-block.h"
#include "output.h"
#include "diagnostic.h"
#include "tree-flow.h"
#include "tree-dump.h"
#include "tree-pass.h"
#include "timevar.h"
#include "cfgloop.h"
#include "flags.h"
#include "tree-inline.h"
#include "tree-scalar-evolution.h"
struct loops *current_loops = NULL;
static struct loops *
tree_loop_optimizer_init (void)
{
struct loops *loops;
loops = loop_optimizer_init (LOOPS_NORMAL
| LOOPS_HAVE_MARKED_SINGLE_EXITS);
if (!loops)
return NULL;
rewrite_into_loop_closed_ssa (NULL, TODO_update_ssa);
return loops;
}
static bool
gate_tree_loop (void)
{
return flag_tree_loop_optimize != 0;
}
struct tree_opt_pass pass_tree_loop =
{
"loop",
gate_tree_loop,
NULL,
NULL,
NULL,
0,
TV_TREE_LOOP,
PROP_cfg,
0,
0,
TODO_ggc_collect,
TODO_dump_func | TODO_verify_ssa | TODO_ggc_collect,
0
};
static unsigned int
tree_ssa_loop_init (void)
{
current_loops = tree_loop_optimizer_init ();
if (!current_loops)
return 0;
scev_initialize (current_loops);
return 0;
}
struct tree_opt_pass pass_tree_loop_init =
{
"loopinit",
NULL,
tree_ssa_loop_init,
NULL,
NULL,
0,
TV_TREE_LOOP_INIT,
PROP_cfg,
0,
0,
0,
TODO_dump_func | TODO_verify_loops,
0
};
static unsigned int
tree_ssa_loop_im (void)
{
if (!current_loops)
return 0;
tree_ssa_lim (current_loops);
return 0;
}
static bool
gate_tree_ssa_loop_im (void)
{
return flag_tree_loop_im != 0;
}
struct tree_opt_pass pass_lim =
{
"lim",
gate_tree_ssa_loop_im,
tree_ssa_loop_im,
NULL,
NULL,
0,
TV_LIM,
PROP_cfg,
0,
0,
0,
TODO_dump_func | TODO_verify_loops,
0
};
static unsigned int
tree_ssa_loop_unswitch (void)
{
if (!current_loops)
return 0;
return tree_ssa_unswitch_loops (current_loops);
}
static bool
gate_tree_ssa_loop_unswitch (void)
{
return flag_unswitch_loops != 0;
}
struct tree_opt_pass pass_tree_unswitch =
{
"unswitch",
gate_tree_ssa_loop_unswitch,
tree_ssa_loop_unswitch,
NULL,
NULL,
0,
TV_TREE_LOOP_UNSWITCH,
PROP_cfg,
0,
0,
0,
TODO_dump_func | TODO_verify_loops,
0
};
static unsigned int
tree_vectorize (void)
{
vectorize_loops (current_loops);
return 0;
}
static bool
gate_tree_vectorize (void)
{
return flag_tree_vectorize && current_loops;
}
struct tree_opt_pass pass_vectorize =
{
"vect",
gate_tree_vectorize,
tree_vectorize,
NULL,
NULL,
0,
TV_TREE_VECTORIZATION,
PROP_cfg | PROP_ssa,
0,
0,
TODO_verify_loops,
TODO_dump_func | TODO_update_ssa,
0
};
static unsigned int
tree_linear_transform (void)
{
if (!current_loops)
return 0;
linear_transform_loops (current_loops);
return 0;
}
static bool
gate_tree_linear_transform (void)
{
return flag_tree_loop_linear != 0;
}
struct tree_opt_pass pass_linear_transform =
{
"ltrans",
gate_tree_linear_transform,
tree_linear_transform,
NULL,
NULL,
0,
TV_TREE_LINEAR_TRANSFORM,
PROP_cfg | PROP_ssa,
0,
0,
0,
TODO_dump_func | TODO_verify_loops,
0
};
static unsigned int
tree_ssa_loop_ivcanon (void)
{
if (!current_loops)
return 0;
return canonicalize_induction_variables (current_loops);
}
static bool
gate_tree_ssa_loop_ivcanon (void)
{
return flag_tree_loop_ivcanon != 0;
}
struct tree_opt_pass pass_iv_canon =
{
"ivcanon",
gate_tree_ssa_loop_ivcanon,
tree_ssa_loop_ivcanon,
NULL,
NULL,
0,
TV_TREE_LOOP_IVCANON,
PROP_cfg | PROP_ssa,
0,
0,
0,
TODO_dump_func | TODO_verify_loops,
0
};
static bool
gate_scev_const_prop (void)
{
return true;
}
struct tree_opt_pass pass_scev_cprop =
{
"sccp",
gate_scev_const_prop,
scev_const_prop,
NULL,
NULL,
0,
TV_SCEV_CONST,
PROP_cfg | PROP_ssa,
0,
0,
0,
TODO_dump_func | TODO_cleanup_cfg
| TODO_update_ssa_only_virtuals,
0
};
static unsigned int
tree_ssa_empty_loop (void)
{
if (!current_loops)
return 0;
return remove_empty_loops (current_loops);
}
struct tree_opt_pass pass_empty_loop =
{
"empty",
NULL,
tree_ssa_empty_loop,
NULL,
NULL,
0,
TV_COMPLETE_UNROLL,
PROP_cfg | PROP_ssa,
0,
0,
0,
TODO_dump_func | TODO_verify_loops,
0
};
static unsigned int
tree_ssa_loop_bounds (void)
{
if (!current_loops)
return 0;
estimate_numbers_of_iterations (current_loops);
scev_reset ();
return 0;
}
struct tree_opt_pass pass_record_bounds =
{
NULL,
NULL,
tree_ssa_loop_bounds,
NULL,
NULL,
0,
TV_TREE_LOOP_BOUNDS,
PROP_cfg | PROP_ssa,
0,
0,
0,
0,
0
};
static unsigned int
tree_complete_unroll (void)
{
if (!current_loops)
return 0;
return tree_unroll_loops_completely (current_loops,
flag_unroll_loops
|| flag_peel_loops
|| optimize >= 3);
}
static bool
gate_tree_complete_unroll (void)
{
return true;
}
struct tree_opt_pass pass_complete_unroll =
{
"cunroll",
gate_tree_complete_unroll,
tree_complete_unroll,
NULL,
NULL,
0,
TV_COMPLETE_UNROLL,
PROP_cfg | PROP_ssa,
0,
0,
0,
TODO_dump_func | TODO_verify_loops,
0
};
static unsigned int
tree_ssa_loop_prefetch (void)
{
if (!current_loops)
return 0;
return tree_ssa_prefetch_arrays (current_loops);
}
static bool
gate_tree_ssa_loop_prefetch (void)
{
return flag_prefetch_loop_arrays != 0;
}
struct tree_opt_pass pass_loop_prefetch =
{
"prefetch",
gate_tree_ssa_loop_prefetch,
tree_ssa_loop_prefetch,
NULL,
NULL,
0,
TV_TREE_PREFETCH,
PROP_cfg | PROP_ssa,
0,
0,
0,
TODO_dump_func | TODO_verify_loops,
0
};
static unsigned int
tree_ssa_loop_ivopts (void)
{
if (!current_loops)
return 0;
tree_ssa_iv_optimize (current_loops);
return 0;
}
static bool
gate_tree_ssa_loop_ivopts (void)
{
return flag_ivopts != 0;
}
struct tree_opt_pass pass_iv_optimize =
{
"ivopts",
gate_tree_ssa_loop_ivopts,
tree_ssa_loop_ivopts,
NULL,
NULL,
0,
TV_TREE_LOOP_IVOPTS,
PROP_cfg | PROP_ssa,
0,
0,
0,
TODO_dump_func
| TODO_verify_loops
| TODO_update_ssa,
0
};
static unsigned int
tree_ssa_loop_done (void)
{
if (!current_loops)
return 0;
free_numbers_of_iterations_estimates (current_loops);
scev_finalize ();
loop_optimizer_finalize (current_loops);
current_loops = NULL;
return 0;
}
struct tree_opt_pass pass_tree_loop_done =
{
"loopdone",
NULL,
tree_ssa_loop_done,
NULL,
NULL,
0,
TV_TREE_LOOP_FINI,
PROP_cfg,
0,
0,
0,
TODO_cleanup_cfg | TODO_dump_func,
0
};