/* Perform doloop optimizations
- Copyright (C) 2004, 2005, 2006, 2007, 2008, 2010
- Free Software Foundation, Inc.
+ Copyright (C) 2004-2013 Free Software Foundation, Inc.
Based on code by Michael P. Hayes (m.hayes@elec.canterbury.ac.nz)
This file is part of GCC.
#include "diagnostic-core.h"
#include "tm_p.h"
#include "cfgloop.h"
-#include "output.h"
#include "params.h"
#include "target.h"
+#include "dumpfile.h"
/* This module is used to modify loops with a determinable number of
iterations to use special low-overhead looping instructions.
basic_block loop_end = desc->out_edge->src;
enum machine_mode mode;
rtx true_prob_val;
+ double_int iterations;
jump_insn = BB_END (loop_end);
/* Determine if the iteration counter will be non-negative.
Note that the maximum value loaded is iterations_max - 1. */
- if (desc->niter_max
- <= ((unsigned HOST_WIDEST_INT) 1
- << (GET_MODE_PRECISION (mode) - 1)))
+ if (max_loop_iterations (loop, &iterations)
+ && (iterations.ule (double_int_one.llshift
+ (GET_MODE_PRECISION (mode) - 1,
+ GET_MODE_PRECISION (mode)))))
nonneg = 1;
break;
{
rtx init;
unsigned level = get_loop_level (loop) + 1;
+ double_int iter;
+ rtx iter_rtx;
+
+ if (!max_loop_iterations (loop, &iter)
+ || !iter.fits_shwi ())
+ iter_rtx = const0_rtx;
+ else
+ iter_rtx = GEN_INT (iter.to_shwi());
init = gen_doloop_begin (counter_reg,
desc->const_iter ? desc->niter_expr : const0_rtx,
- GEN_INT (desc->niter_max),
- GEN_INT (level));
+ iter_rtx,
+ GEN_INT (level),
+ doloop_seq);
if (init)
{
start_sequence ();
struct niter_desc *desc;
unsigned word_mode_size;
unsigned HOST_WIDE_INT word_mode_max;
+ double_int iter;
+ int entered_at_top;
if (dump_file)
fprintf (dump_file, "Doloop: Processing loop %d.\n", loop->num);
count = copy_rtx (desc->niter_expr);
iterations = desc->const_iter ? desc->niter_expr : const0_rtx;
- iterations_max = GEN_INT (desc->niter_max);
+ if (!max_loop_iterations (loop, &iter)
+ || !iter.fits_shwi ())
+ iterations_max = const0_rtx;
+ else
+ iterations_max = GEN_INT (iter.to_shwi());
level = get_loop_level (loop) + 1;
/* Generate looping insn. If the pattern FAILs then give up trying
not like. */
start_label = block_label (desc->in_edge->dest);
doloop_reg = gen_reg_rtx (mode);
+ entered_at_top = (loop->latch == desc->in_edge->dest
+ && contains_no_active_insn_p (loop->latch));
doloop_seq = gen_doloop_end (doloop_reg, iterations, iterations_max,
- GEN_INT (level), start_label);
+ GEN_INT (level), start_label,
+ GEN_INT (entered_at_top));
word_mode_size = GET_MODE_PRECISION (word_mode);
word_mode_max
computed, we must be sure that the number of iterations fits into
the new mode. */
&& (word_mode_size >= GET_MODE_PRECISION (mode)
- || desc->niter_max <= word_mode_max))
+ || iter.ule (double_int::from_shwi (word_mode_max))))
{
if (word_mode_size > GET_MODE_PRECISION (mode))
{
}
PUT_MODE (doloop_reg, word_mode);
doloop_seq = gen_doloop_end (doloop_reg, iterations, iterations_max,
- GEN_INT (level), start_label);
+ GEN_INT (level), start_label,
+ GEN_INT (entered_at_top));
}
if (! doloop_seq)
{
iv_analysis_done ();
#ifdef ENABLE_CHECKING
- verify_dominators (CDI_DOMINATORS);
verify_loop_structure ();
#endif
}