Commit 50654f6c by Zdenek Dvorak Committed by Zdenek Dvorak

loop-iv.c: New file.

	* loop-iv.c: New file.
	* Makefile.in (loop-iv.o): New.
	* basic_block.h (FOR_BB_INSNS, FOR_BB_INSNS_REVERSE): New macros.
	* cfgloop.c (fill_sons_in_loop, get_loop_body_in_dom_order,
	num_loop_branches): New functions.
	* cfgloop.h (get_loop_body_in_dom_order, num_loop_branches,
	iv_analysis_loop_init, iv_get_reaching_def, iv_analyse, get_iv_value,
	find_simple_exit, iv_number_of_iterations, iv_analysis_done,
	get_simple_loop_desc, free_simple_loop_desc): Declare.
	(simple_loop_desc): New inline function.
	(struct rtx_iv, struct niter_desc): New.
	* cfgloopmanip.c (loopify): Specify semantics more precisely.
	* expr.c (force_operand): Handle subregs of expressions created by
	loop unroller.
	* loop-init.c (loop_optimizer_init, loop_optimizer_finalize): Move
	parts of the initialization to toplev.c
	* loop-unroll.c (loop_exit_at_end_p): New.
	(unroll_and_peel_loops): Call iv_analysis_done.
	(decide_peel_once_rolling, decide_peel_completely,
	decide_unroll_stupid, decide_unroll_constant_iterations,
	decide_unroll_runtime_iterations, decide_peel_simple,
	peel_loop_simple, unroll_loop_stupid, unroll_loop_constant_iterations,
	unroll_loop_runtime_iterations): Use new simple loop analysis.
	* loop-unswitch.c (compare_and_jump_seq): New.
	(may_unswitch_on_p): Renamed to ...
	(may_unswitch_on): Use new iv analysis.
	(reversed_condition): Export.
	(unswitch_single_loop, unswitch_loop): Use new iv analysis.
	* predict.c (estimate_probability): Use new simple loop analysis.
	* rtl.h (get_mode_bounds, reversed_condition,compare_and_jump_seq,
	canon_condition, simplify_using_condition): Declare.
	* stor-layout.c (get_mode_bounds): New.
	* toplev.c (rest_of_handle_loop2): Some parts of
	initialization/finalization moved here from loop-init.c.

From-SVN: r77951
parent cc7ce44e
2004-02-17 Zdenek Dvorak <rakdver@atrey.karlin.mff.cuni.cz>
* loop-iv.c: New file.
* Makefile.in (loop-iv.o): New.
* basic_block.h (FOR_BB_INSNS, FOR_BB_INSNS_REVERSE): New macros.
* cfgloop.c (fill_sons_in_loop, get_loop_body_in_dom_order,
num_loop_branches): New functions.
* cfgloop.h (get_loop_body_in_dom_order, num_loop_branches,
iv_analysis_loop_init, iv_get_reaching_def, iv_analyse, get_iv_value,
find_simple_exit, iv_number_of_iterations, iv_analysis_done,
get_simple_loop_desc, free_simple_loop_desc): Declare.
(simple_loop_desc): New inline function.
(struct rtx_iv, struct niter_desc): New.
* cfgloopmanip.c (loopify): Specify semantics more precisely.
* expr.c (force_operand): Handle subregs of expressions created by
loop unroller.
* loop-init.c (loop_optimizer_init, loop_optimizer_finalize): Move
parts of the initialization to toplev.c
* loop-unroll.c (loop_exit_at_end_p): New.
(unroll_and_peel_loops): Call iv_analysis_done.
(decide_peel_once_rolling, decide_peel_completely,
decide_unroll_stupid, decide_unroll_constant_iterations,
decide_unroll_runtime_iterations, decide_peel_simple,
peel_loop_simple, unroll_loop_stupid, unroll_loop_constant_iterations,
unroll_loop_runtime_iterations): Use new simple loop analysis.
* loop-unswitch.c (compare_and_jump_seq): New.
(may_unswitch_on_p): Renamed to ...
(may_unswitch_on): Use new iv analysis.
(reversed_condition): Export.
(unswitch_single_loop, unswitch_loop): Use new iv analysis.
* predict.c (estimate_probability): Use new simple loop analysis.
* rtl.h (get_mode_bounds, reversed_condition,compare_and_jump_seq,
canon_condition, simplify_using_condition): Declare.
* stor-layout.c (get_mode_bounds): New.
* toplev.c (rest_of_handle_loop2): Some parts of
initialization/finalization moved here from loop-init.c.
2004-02-17 Kazu Hirata <kazu@cs.umass.edu> 2004-02-17 Kazu Hirata <kazu@cs.umass.edu>
* config/h8300/h8300.h (FIXED_REGISTERS): Add the soft frame * config/h8300/h8300.h (FIXED_REGISTERS): Add the soft frame
......
...@@ -848,7 +848,7 @@ OBJS-common = \ ...@@ -848,7 +848,7 @@ OBJS-common = \
cfgloopanal.o cfgloopmanip.o loop-init.o loop-unswitch.o loop-unroll.o \ cfgloopanal.o cfgloopmanip.o loop-init.o loop-unswitch.o loop-unroll.o \
cfgrtl.o combine.o conflict.o convert.o coverage.o cse.o cselib.o \ cfgrtl.o combine.o conflict.o convert.o coverage.o cse.o cselib.o \
dbxout.o debug.o df.o diagnostic.o dojump.o doloop.o dominance.o \ dbxout.o debug.o df.o diagnostic.o dojump.o doloop.o dominance.o \
dwarf2asm.o dwarf2out.o emit-rtl.o except.o explow.o \ dwarf2asm.o dwarf2out.o emit-rtl.o except.o explow.o loop-iv.o \
expmed.o expr.o final.o flow.o fold-const.o function.o gcse.o \ expmed.o expr.o final.o flow.o fold-const.o function.o gcse.o \
genrtl.o ggc-common.o global.o graph.o gtype-desc.o \ genrtl.o ggc-common.o global.o graph.o gtype-desc.o \
haifa-sched.o hooks.o ifcvt.o insn-attrtab.o insn-emit.o insn-modes.o \ haifa-sched.o hooks.o ifcvt.o insn-attrtab.o insn-emit.o insn-modes.o \
...@@ -1719,6 +1719,8 @@ cfgloop.o : cfgloop.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) coretypes.h $(TM_H) \ ...@@ -1719,6 +1719,8 @@ cfgloop.o : cfgloop.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) coretypes.h $(TM_H) \
$(BASIC_BLOCK_H) hard-reg-set.h cfgloop.h flags.h $(BASIC_BLOCK_H) hard-reg-set.h cfgloop.h flags.h
cfgloopanal.o : cfgloopanal.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) \ cfgloopanal.o : cfgloopanal.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) \
$(BASIC_BLOCK_H) hard-reg-set.h cfgloop.h $(EXPR_H) coretypes.h $(TM_H) $(BASIC_BLOCK_H) hard-reg-set.h cfgloop.h $(EXPR_H) coretypes.h $(TM_H)
loop-iv.o : loop-iv.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(GGC_H) \
$(BASIC_BLOCK_H) hard-reg-set.h cfgloop.h $(EXPR_H) coretypes.h $(TM_H)
cfgloopmanip.o : cfgloopmanip.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) \ cfgloopmanip.o : cfgloopmanip.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) \
$(BASIC_BLOCK_H) hard-reg-set.h cfgloop.h cfglayout.h output.h coretypes.h $(TM_H) $(BASIC_BLOCK_H) hard-reg-set.h cfgloop.h cfglayout.h output.h coretypes.h $(TM_H)
loop-init.o : loop-init.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) \ loop-init.o : loop-init.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) \
......
...@@ -288,6 +288,17 @@ extern varray_type basic_block_info; ...@@ -288,6 +288,17 @@ extern varray_type basic_block_info;
#define FOR_EACH_BB_REVERSE(BB) \ #define FOR_EACH_BB_REVERSE(BB) \
FOR_BB_BETWEEN (BB, EXIT_BLOCK_PTR->prev_bb, ENTRY_BLOCK_PTR, prev_bb) FOR_BB_BETWEEN (BB, EXIT_BLOCK_PTR->prev_bb, ENTRY_BLOCK_PTR, prev_bb)
/* For iterating over insns in basic block. */
#define FOR_BB_INSNS(BB, INSN) \
for ((INSN) = BB_HEAD (BB); \
(INSN) != NEXT_INSN (BB_END (BB)); \
(INSN) = NEXT_INSN (INSN))
#define FOR_BB_INSNS_REVERSE(BB, INSN) \
for ((INSN) = BB_END (BB); \
(INSN) != PREV_INSN (BB_HEAD (BB)); \
(INSN) = PREV_INSN (INSN))
/* Cycles through _all_ basic blocks, even the fake ones (entry and /* Cycles through _all_ basic blocks, even the fake ones (entry and
exit block). */ exit block). */
......
...@@ -959,6 +959,62 @@ get_loop_body (const struct loop *loop) ...@@ -959,6 +959,62 @@ get_loop_body (const struct loop *loop)
return tovisit; return tovisit;
} }
/* Fills dominance descendants inside LOOP of the basic block BB into
array TOVISIT from index *TV. */
static void
fill_sons_in_loop (const struct loop *loop, basic_block bb,
basic_block *tovisit, int *tv)
{
basic_block son, postpone = NULL;
tovisit[(*tv)++] = bb;
for (son = first_dom_son (CDI_DOMINATORS, bb);
son;
son = next_dom_son (CDI_DOMINATORS, son))
{
if (!flow_bb_inside_loop_p (loop, son))
continue;
if (dominated_by_p (CDI_DOMINATORS, loop->latch, son))
{
postpone = son;
continue;
}
fill_sons_in_loop (loop, son, tovisit, tv);
}
if (postpone)
fill_sons_in_loop (loop, postpone, tovisit, tv);
}
/* Gets body of a LOOP (that must be different from the outermost loop)
sorted by dominance relation. Additionally, if a basic block s dominates
the latch, then only blocks dominated by s are be after it. */
basic_block *
get_loop_body_in_dom_order (const struct loop *loop)
{
basic_block *tovisit;
int tv;
if (!loop->num_nodes)
abort ();
tovisit = xcalloc (loop->num_nodes, sizeof (basic_block));
if (loop->latch == EXIT_BLOCK_PTR)
abort ();
tv = 0;
fill_sons_in_loop (loop, loop->header, tovisit, &tv);
if (tv != (int) loop->num_nodes)
abort ();
return tovisit;
}
/* Gets exit edges of a LOOP, returning their number in N_EDGES. */ /* Gets exit edges of a LOOP, returning their number in N_EDGES. */
edge * edge *
get_loop_exit_edges (const struct loop *loop, unsigned int *n_edges) get_loop_exit_edges (const struct loop *loop, unsigned int *n_edges)
...@@ -988,6 +1044,27 @@ get_loop_exit_edges (const struct loop *loop, unsigned int *n_edges) ...@@ -988,6 +1044,27 @@ get_loop_exit_edges (const struct loop *loop, unsigned int *n_edges)
return edges; return edges;
} }
/* Counts the number of conditional branches inside LOOP. */
unsigned
num_loop_branches (const struct loop *loop)
{
unsigned i, n;
basic_block * body;
if (loop->latch == EXIT_BLOCK_PTR)
abort ();
body = get_loop_body (loop);
n = 0;
for (i = 0; i < loop->num_nodes; i++)
if (body[i]->succ && body[i]->succ->succ_next)
n++;
free (body);
return n;
}
/* Adds basic block BB to LOOP. */ /* Adds basic block BB to LOOP. */
void void
add_bb_to_loop (basic_block bb, struct loop *loop) add_bb_to_loop (basic_block bb, struct loop *loop)
......
...@@ -278,7 +278,9 @@ extern int average_num_loop_insns (struct loop *); ...@@ -278,7 +278,9 @@ extern int average_num_loop_insns (struct loop *);
/* Loops & cfg manipulation. */ /* Loops & cfg manipulation. */
extern basic_block *get_loop_body (const struct loop *); extern basic_block *get_loop_body (const struct loop *);
extern basic_block *get_loop_body_in_dom_order (const struct loop *);
extern edge *get_loop_exit_edges (const struct loop *, unsigned *); extern edge *get_loop_exit_edges (const struct loop *, unsigned *);
extern unsigned num_loop_branches (const struct loop *);
extern edge loop_preheader_edge (const struct loop *); extern edge loop_preheader_edge (const struct loop *);
extern edge loop_latch_edge (const struct loop *); extern edge loop_latch_edge (const struct loop *);
...@@ -322,6 +324,114 @@ extern void unloop (struct loops *, struct loop *); ...@@ -322,6 +324,114 @@ extern void unloop (struct loops *, struct loop *);
extern bool remove_path (struct loops *, edge); extern bool remove_path (struct loops *, edge);
extern edge split_loop_bb (basic_block, rtx); extern edge split_loop_bb (basic_block, rtx);
/* Induction variable analysis. */
/* The description of induction variable. The things are a bit complicated
due to need to handle subregs and extends. The value of the object described
by it can be obtained as follows (all computations are done in extend_mode):
Value in i-th iteration is
delta + mult * extend_{extend_mode} (subreg_{mode} (base + i * step)).
If first_special is true, the value in the first iteration is
delta + mult * base
If extend = NIL, first_special must be false, delta 0, mult 1 and value is
subreg_{mode} (base + i * step)
The get_iv_value function can be used to obtain these expressions.
??? Add a third mode field that would specify the mode in that inner
computation is done, which would enable it to be different from the
outer one? */
struct rtx_iv
{
/* Its base and step (mode of base and step is supposed to be extend_mode,
see the description above). */
rtx base, step;
/* The type of extend applied to it (SIGN_EXTEND, ZERO_EXTEND or NIL). */
enum rtx_code extend;
/* Operations applied in the extended mode. */
rtx delta, mult;
/* The mode it is extended to. */
enum machine_mode extend_mode;
/* The mode the variable iterates in. */
enum machine_mode mode;
/* Whether we have already filled the remaining fields. */
unsigned analysed : 1;
/* Whether the first iteration needs to be handled specially. */
unsigned first_special : 1;
};
/* This should replace struct loop_desc. We keep this just so that we are
able to compare the results. */
struct niter_desc
{
/* The edge out of the loop. */
edge out_edge;
/* The other edge leading from the condition. */
edge in_edge;
/* True if we are able to say anything about number of iterations of the
loop. */
bool simple_p;
/* True if the loop iterates the constant number of times. */
bool const_iter;
/* Number of iterations if constant. */
unsigned HOST_WIDEST_INT niter;
/* Upper bound on the number of iterations. */
unsigned HOST_WIDEST_INT niter_max;
/* Assumptions under that the rest of the information is valid. */
rtx assumptions;
/* Assumptions under that the loop ends before reaching the latch,
even if value of niter_expr says otherwise. */
rtx noloop_assumptions;
/* Condition under that the loop is infinite. */
rtx infinite;
/* Whether the comparison is signed. */
bool signed_p;
/* The mode in that niter_expr should be computed. */
enum machine_mode mode;
/* The number of iterations of the loop. */
rtx niter_expr;
};
extern void iv_analysis_loop_init (struct loop *);
extern rtx iv_get_reaching_def (rtx, rtx);
extern bool iv_analyse (rtx, rtx, struct rtx_iv *);
extern rtx get_iv_value (struct rtx_iv *, rtx);
extern void find_simple_exit (struct loop *, struct niter_desc *);
extern void iv_number_of_iterations (struct loop *, rtx, rtx,
struct niter_desc *);
extern void iv_analysis_done (void);
extern struct niter_desc *get_simple_loop_desc (struct loop *loop);
extern void free_simple_loop_desc (struct loop *loop);
static inline struct niter_desc *
simple_loop_desc (struct loop *loop)
{
return loop->aux;
}
/* Loop optimizer initialization. */ /* Loop optimizer initialization. */
extern struct loops *loop_optimizer_init (FILE *); extern struct loops *loop_optimizer_init (FILE *);
extern void loop_optimizer_finalize (struct loops *, FILE *); extern void loop_optimizer_finalize (struct loops *, FILE *);
......
...@@ -480,11 +480,13 @@ scale_loop_frequencies (struct loop *loop, int num, int den) ...@@ -480,11 +480,13 @@ scale_loop_frequencies (struct loop *loop, int num, int den)
accordingly. Everything between them plus LATCH_EDGE destination must accordingly. Everything between them plus LATCH_EDGE destination must
be dominated by HEADER_EDGE destination, and back-reachable from be dominated by HEADER_EDGE destination, and back-reachable from
LATCH_EDGE source. HEADER_EDGE is redirected to basic block SWITCH_BB, LATCH_EDGE source. HEADER_EDGE is redirected to basic block SWITCH_BB,
SWITCH_BB->succ to original destination of LATCH_EDGE and FALLTHRU_EDGE (SWITCH_BB) to original destination of HEADER_EDGE and
SWITCH_BB->succ->succ_next to original destination of HEADER_EDGE. BRANCH_EDGE (SWITCH_BB) to original destination of LATCH_EDGE.
Returns newly created loop. */ Returns newly created loop. */
struct loop * struct loop *
loopify (struct loops *loops, edge latch_edge, edge header_edge, basic_block switch_bb) loopify (struct loops *loops, edge latch_edge, edge header_edge,
basic_block switch_bb)
{ {
basic_block succ_bb = latch_edge->dest; basic_block succ_bb = latch_edge->dest;
basic_block pred_bb = header_edge->src; basic_block pred_bb = header_edge->src;
...@@ -509,13 +511,15 @@ loopify (struct loops *loops, edge latch_edge, edge header_edge, basic_block swi ...@@ -509,13 +511,15 @@ loopify (struct loops *loops, edge latch_edge, edge header_edge, basic_block swi
/* Redirect edges. */ /* Redirect edges. */
loop_redirect_edge (latch_edge, loop->header); loop_redirect_edge (latch_edge, loop->header);
loop_redirect_edge (BRANCH_EDGE (switch_bb), succ_bb);
loop_redirect_edge (header_edge, switch_bb); loop_redirect_edge (header_edge, switch_bb);
loop_redirect_edge (switch_bb->succ->succ_next, loop->header); loop_redirect_edge (FALLTHRU_EDGE (switch_bb), loop->header);
loop_redirect_edge (switch_bb->succ, succ_bb);
/* Update dominators. */ /* Update dominators. */
set_immediate_dominator (CDI_DOMINATORS, switch_bb, pred_bb); set_immediate_dominator (CDI_DOMINATORS, switch_bb, pred_bb);
set_immediate_dominator (CDI_DOMINATORS, loop->header, switch_bb); set_immediate_dominator (CDI_DOMINATORS, loop->header, switch_bb);
set_immediate_dominator (CDI_DOMINATORS, succ_bb, switch_bb); set_immediate_dominator (CDI_DOMINATORS, succ_bb, switch_bb);
/* Compute new loop. */ /* Compute new loop. */
......
...@@ -5588,6 +5588,20 @@ force_operand (rtx value, rtx target) ...@@ -5588,6 +5588,20 @@ force_operand (rtx value, rtx target)
rtx subtarget = get_subtarget (target); rtx subtarget = get_subtarget (target);
enum rtx_code code = GET_CODE (value); enum rtx_code code = GET_CODE (value);
/* Check for subreg applied to an expression produced by loop optimizer. */
if (code == SUBREG
&& GET_CODE (SUBREG_REG (value)) != REG
&& GET_CODE (SUBREG_REG (value)) != MEM)
{
value = simplify_gen_subreg (GET_MODE (value),
force_reg (GET_MODE (SUBREG_REG (value)),
force_operand (SUBREG_REG (value),
NULL_RTX)),
GET_MODE (SUBREG_REG (value)),
SUBREG_BYTE (value));
code = GET_CODE (value);
}
/* Check for a PIC address load. */ /* Check for a PIC address load. */
if ((code == PLUS || code == MINUS) if ((code == PLUS || code == MINUS)
&& XEXP (value, 0) == pic_offset_table_rtx && XEXP (value, 0) == pic_offset_table_rtx
......
...@@ -36,9 +36,6 @@ loop_optimizer_init (FILE *dumpfile) ...@@ -36,9 +36,6 @@ loop_optimizer_init (FILE *dumpfile)
struct loops *loops = xcalloc (1, sizeof (struct loops)); struct loops *loops = xcalloc (1, sizeof (struct loops));
edge e; edge e;
/* Initialize structures for layout changes. */
cfg_layout_initialize ();
/* Avoid annoying special cases of edges going to exit /* Avoid annoying special cases of edges going to exit
block. */ block. */
for (e = EXIT_BLOCK_PTR->pred; e; e = e->pred_next) for (e = EXIT_BLOCK_PTR->pred; e; e = e->pred_next)
...@@ -49,18 +46,11 @@ loop_optimizer_init (FILE *dumpfile) ...@@ -49,18 +46,11 @@ loop_optimizer_init (FILE *dumpfile)
if (flow_loops_find (loops, LOOP_TREE) <= 1) if (flow_loops_find (loops, LOOP_TREE) <= 1)
{ {
basic_block bb;
/* No loops. */ /* No loops. */
flow_loops_free (loops); flow_loops_free (loops);
free_dominance_info (CDI_DOMINATORS); free_dominance_info (CDI_DOMINATORS);
free (loops); free (loops);
/* Make chain. */
FOR_EACH_BB (bb)
if (bb->next_bb != EXIT_BLOCK_PTR)
bb->rbi->next = bb->next_bb;
cfg_layout_finalize ();
return NULL; return NULL;
} }
...@@ -94,13 +84,14 @@ loop_optimizer_init (FILE *dumpfile) ...@@ -94,13 +84,14 @@ loop_optimizer_init (FILE *dumpfile)
void void
loop_optimizer_finalize (struct loops *loops, FILE *dumpfile) loop_optimizer_finalize (struct loops *loops, FILE *dumpfile)
{ {
basic_block bb; unsigned i;
/* Finalize layout changes. */ if (!loops)
/* Make chain. */ return;
FOR_EACH_BB (bb)
if (bb->next_bb != EXIT_BLOCK_PTR) for (i = 1; i < loops->num; i++)
bb->rbi->next = bb->next_bb; if (loops->parray[i])
free_simple_loop_desc (loops->parray[i]);
/* Another dump. */ /* Another dump. */
flow_loops_dump (loops, dumpfile, NULL, 1); flow_loops_dump (loops, dumpfile, NULL, 1);
...@@ -110,9 +101,6 @@ loop_optimizer_finalize (struct loops *loops, FILE *dumpfile) ...@@ -110,9 +101,6 @@ loop_optimizer_finalize (struct loops *loops, FILE *dumpfile)
free_dominance_info (CDI_DOMINATORS); free_dominance_info (CDI_DOMINATORS);
free (loops); free (loops);
/* Finalize changes. */
cfg_layout_finalize ();
/* Checking. */ /* Checking. */
#ifdef ENABLE_CHECKING #ifdef ENABLE_CHECKING
verify_flow_info (); verify_flow_info ();
......
This diff is collapsed. Click to expand it.
...@@ -406,13 +406,16 @@ estimate_probability (struct loops *loops_info) ...@@ -406,13 +406,16 @@ estimate_probability (struct loops *loops_info)
unsigned j; unsigned j;
int exits; int exits;
struct loop *loop = loops_info->parray[i]; struct loop *loop = loops_info->parray[i];
struct loop_desc desc; struct niter_desc desc;
unsigned HOST_WIDE_INT niter; unsigned HOST_WIDE_INT niter;
flow_loop_scan (loop, LOOP_EXIT_EDGES); flow_loop_scan (loop, LOOP_EXIT_EDGES);
exits = loop->num_exits; exits = loop->num_exits;
if (simple_loop_p (loop, &desc) && desc.const_iter) iv_analysis_loop_init (loop);
find_simple_exit (loop, &desc);
if (desc.simple_p && desc.const_iter)
{ {
int prob; int prob;
niter = desc.niter + 1; niter = desc.niter + 1;
...@@ -472,6 +475,8 @@ estimate_probability (struct loops *loops_info) ...@@ -472,6 +475,8 @@ estimate_probability (struct loops *loops_info)
free (bbs); free (bbs);
} }
iv_analysis_done ();
/* Attempt to predict conditional jumps using a number of heuristics. */ /* Attempt to predict conditional jumps using a number of heuristics. */
FOR_EACH_BB (bb) FOR_EACH_BB (bb)
{ {
......
...@@ -2361,4 +2361,15 @@ extern void tracer (void); ...@@ -2361,4 +2361,15 @@ extern void tracer (void);
/* In var-tracking.c */ /* In var-tracking.c */
extern void variable_tracking_main (void); extern void variable_tracking_main (void);
/* In stor-layout.c. */
extern void get_mode_bounds (enum machine_mode, int, rtx *, rtx *);
/* In loop-unswitch.c */
extern rtx reversed_condition (rtx);
extern rtx compare_and_jump_seq (rtx, rtx, enum rtx_code, rtx, int, rtx);
/* In loop-iv.c */
extern rtx canon_condition (rtx);
extern void simplify_using_condition (rtx, rtx *, struct bitmap_head_def *);
#endif /* ! GCC_RTL_H */ #endif /* ! GCC_RTL_H */
...@@ -2118,4 +2118,27 @@ get_best_mode (int bitsize, int bitpos, unsigned int align, ...@@ -2118,4 +2118,27 @@ get_best_mode (int bitsize, int bitpos, unsigned int align,
return mode; return mode;
} }
/* Gets minimal and maximal values for MODE (signed or unsigned depending on
SIGN). */
void
get_mode_bounds (enum machine_mode mode, int sign, rtx *mmin, rtx *mmax)
{
int size = GET_MODE_BITSIZE (mode);
if (size > HOST_BITS_PER_WIDE_INT)
abort ();
if (sign)
{
*mmin = GEN_INT (-((unsigned HOST_WIDE_INT) 1 << (size - 1)));
*mmax = GEN_INT (((unsigned HOST_WIDE_INT) 1 << (size - 1)) - 1);
}
else
{
*mmin = const0_rtx;
*mmax = GEN_INT (((unsigned HOST_WIDE_INT) 1 << (size - 1) << 1) - 1);
}
}
#include "gt-stor-layout.h" #include "gt-stor-layout.h"
...@@ -3034,11 +3034,16 @@ static void ...@@ -3034,11 +3034,16 @@ static void
rest_of_handle_loop2 (tree decl, rtx insns) rest_of_handle_loop2 (tree decl, rtx insns)
{ {
struct loops *loops; struct loops *loops;
basic_block bb;
timevar_push (TV_LOOP); timevar_push (TV_LOOP);
open_dump_file (DFI_loop2, decl); open_dump_file (DFI_loop2, decl);
if (rtl_dump_file) if (rtl_dump_file)
dump_flow_info (rtl_dump_file); dump_flow_info (rtl_dump_file);
/* Initialize structures for layout changes. */
cfg_layout_initialize ();
loops = loop_optimizer_init (rtl_dump_file); loops = loop_optimizer_init (rtl_dump_file);
if (loops) if (loops)
...@@ -3056,6 +3061,12 @@ rest_of_handle_loop2 (tree decl, rtx insns) ...@@ -3056,6 +3061,12 @@ rest_of_handle_loop2 (tree decl, rtx insns)
loop_optimizer_finalize (loops, rtl_dump_file); loop_optimizer_finalize (loops, rtl_dump_file);
} }
/* Finalize layout changes. */
FOR_EACH_BB (bb)
if (bb->next_bb != EXIT_BLOCK_PTR)
bb->rbi->next = bb->next_bb;
cfg_layout_finalize ();
cleanup_cfg (CLEANUP_EXPENSIVE); cleanup_cfg (CLEANUP_EXPENSIVE);
delete_trivially_dead_insns (insns, max_reg_num ()); delete_trivially_dead_insns (insns, max_reg_num ());
reg_scan (insns, max_reg_num (), 0); reg_scan (insns, max_reg_num (), 0);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment