#include "expr.h"
#include "hashtab.h"
#include "recog.h"
-#include "varray.h"
/* This pass performs loop unrolling and peeling. We only perform these
optimizations on innermost loops (with single exception) because
XEXP (XEXP (single_set, loc[0]), loc[1]). */
};
-DEF_VEC_P(rtx);
-DEF_VEC_ALLOC_P(rtx,heap);
-
/* Information about accumulators to expand. */
struct var_to_expand
if (desc->noloop_assumptions)
RESET_BIT (wont_exit, 1);
- remove_edges = xcalloc (npeel, sizeof (edge));
+ remove_edges = XCNEWVEC (edge, npeel);
n_remove_edges = 0;
if (flag_split_ivs_in_unroller)
wont_exit = sbitmap_alloc (max_unroll + 1);
sbitmap_ones (wont_exit);
- remove_edges = xcalloc (max_unroll + exit_mod + 1, sizeof (edge));
+ remove_edges = XCNEWVEC (edge, max_unroll + exit_mod + 1);
n_remove_edges = 0;
if (flag_split_ivs_in_unroller
|| flag_variable_expansion_in_unroller)
opt_info = analyze_insns_in_loop (loop);
/* Remember blocks whose dominators will have to be updated. */
- dom_bbs = xcalloc (n_basic_blocks, sizeof (basic_block));
+ dom_bbs = XCNEWVEC (basic_block, n_basic_blocks);
n_dom_bbs = 0;
body = get_loop_body (loop);
/* Precondition the loop. */
loop_split_edge_with (loop_preheader_edge (loop), init_code);
- remove_edges = xcalloc (max_unroll + n_peel + 1, sizeof (edge));
+ remove_edges = XCNEWVEC (edge, max_unroll + n_peel + 1);
n_remove_edges = 0;
wont_exit = sbitmap_alloc (max_unroll + 2);
";; Unrolled loop %d times, counting # of iterations "
"in runtime, %i insns\n",
max_unroll, num_loop_insns (loop));
+
+ if (dom_bbs)
+ free (dom_bbs);
}
/* Decide whether to simply peel LOOP and how much. */
&& GET_CODE (src) != MINUS
&& GET_CODE (src) != MULT)
return NULL;
-
+
+ /* Hmm, this is a bit paradoxical. We know that INSN is a valid insn
+ in MD. But if there is no optab to generate the insn, we can not
+ perform the variable expansion. This can happen if an MD provides
+ an insn but not a named pattern to generate it, for example to avoid
+ producing code that needs additional mode switches like for x87/mmx.
+
+ So we check have_insn_for which looks for an optab for the operation
+ in SRC. If it doesn't exist, we can't perform the expansion even
+ though INSN is valid. */
+ if (!have_insn_for (GET_CODE (src), GET_MODE (src)))
+ return NULL;
+
if (!XEXP (src, 0))
return NULL;
return NULL;
/* Record the accumulator to expand. */
- ves = xmalloc (sizeof (struct var_to_expand));
+ ves = XNEW (struct var_to_expand);
ves->insn = insn;
ves->var_expansions = VEC_alloc (rtx, heap, 1);
ves->reg = copy_rtx (dest);
if (!biv_p (insn, dest))
return NULL;
- ok = iv_analyze (insn, dest, &iv);
- gcc_assert (ok);
+ ok = iv_analyze_result (insn, dest, &iv);
+
+ /* This used to be an assert under the assumption that if biv_p returns
+ true that iv_analyze_result must also return true. However, that
+ assumption is not strictly correct as evidenced by pr25569.
+
+ Returning NULL when iv_analyze_result returns false is safe and
+ avoids the problems in pr25569 until the iv_analyze_* routines
+ can be fixed, which is apparently hard and time consuming
+ according to their author. */
+ if (! ok)
+ return NULL;
if (iv.step == const0_rtx
|| iv.mode != iv.extend_mode)
return NULL;
/* Record the insn to split. */
- ivts = xmalloc (sizeof (struct iv_to_split));
+ ivts = XNEW (struct iv_to_split);
ivts->insn = insn;
ivts->base_var = NULL_RTX;
ivts->step = iv.step;
{
basic_block *body, bb;
unsigned i, num_edges = 0;
- struct opt_info *opt_info = xcalloc (1, sizeof (struct opt_info));
+ struct opt_info *opt_info = XCNEW (struct opt_info);
rtx insn;
struct iv_to_split *ivts = NULL;
struct var_to_expand *ves = NULL;
if (ivts)
{
-#ifdef ENABLE_CHECKING
- gcc_assert (rtx_equal_p (PATTERN (insn), PATTERN (orig_insn)));
-#endif
+ gcc_assert (GET_CODE (PATTERN (insn))
+ == GET_CODE (PATTERN (orig_insn)));
if (!delta)
insert_base_initialization (ivts, insn);
ves = htab_find (opt_info->insns_with_var_to_expand, &ve_templ);
if (ves)
{
-#ifdef ENABLE_CHECKING
- gcc_assert (rtx_equal_p (PATTERN (insn), PATTERN (orig_insn)));
-#endif
+ gcc_assert (GET_CODE (PATTERN (insn))
+ == GET_CODE (PATTERN (orig_insn)));
expand_var_during_unrolling (ves, insn);
}
}