+2004-04-25 Paolo Bonzini <bonzini@gnu.org>
+
+ * cfglayout.c (duplicate_insn_chain): Remove references to
+ NOTE_INSN_LOOP_VTOP and NOTE_INSN_LOOP_CONT.
+ * cfgloop.h (struct loop): Remove fields vtop, cont and cont_dominator.
+ * cfgrtl.c (rtl_delete_block): Remove handling of NOTE_INSN_LOOP_CONT.
+ * final.c (final_scan_insn): Remove references to NOTE_INSN_LOOP_VTOP
+ and NOTE_INSN_LOOP_CONT.
+ * insn-notes.def (NOTE_INSN_LOOP_VTOP, NOTE_INSN_LOOP_CONT): Remove.
+ * jump.c (squeeze_notes): Remove references to NOTE_INSN_LOOP_VTOP
+ and NOTE_INSN_LOOP_CONT.
+ * loop.c (scan_loops, find_and_verify_loops, for_each_insn_in_loop,
+ check_dbra_loop, loop_dump_aux): Remove references to removed notes
+ and fields.
+ * reorg.c (mostly_true_jump): Do not rely on NOTE_INSN_LOOP_VTOPs.
+ * unroll.c (unroll_loop, copy_loop_body, loop_iterations): Remove
+ references to removed notes and fields.
+ (subtract_reg_term, ujump_to_loop_cont): Remove.
+
2004-08-25 Paolo Bonzini <bonzini@gnu.org>
- * doc/invoke.texi: Document that libcpp does not require
+ * doc/install.texi: Document that libcpp does not require
Automake any longer. Document that Automake 1.9.1 should
work everywhere.
in first BB, we may want to copy the block. */
case NOTE_INSN_PROLOGUE_END:
- case NOTE_INSN_LOOP_VTOP:
- case NOTE_INSN_LOOP_CONT:
case NOTE_INSN_LOOP_BEG:
case NOTE_INSN_LOOP_END:
/* Strip down the loop notes - we don't really want to keep
/* The following are currently used by loop.c but they are likely to
disappear as loop.c is converted to use the CFG. */
- /* Nonzero if the loop has a NOTE_INSN_LOOP_VTOP. */
- rtx vtop;
-
- /* Nonzero if the loop has a NOTE_INSN_LOOP_CONT.
- A continue statement will generate a branch to NEXT_INSN (cont). */
- rtx cont;
-
- /* The dominator of cont. */
- rtx cont_dominator;
-
/* The NOTE_INSN_LOOP_BEG. */
rtx start;
and remove the associated NOTE_INSN_EH_REGION_BEG and
NOTE_INSN_EH_REGION_END notes. */
- /* Get rid of all NOTE_INSN_LOOP_CONTs hanging before the block. */
-
- for (insn = PREV_INSN (BB_HEAD (b)); insn; insn = PREV_INSN (insn))
- {
- if (!NOTE_P (insn))
- break;
- if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_CONT)
- NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
- }
-
insn = BB_HEAD (b);
if (LABEL_P (insn))
case NOTE_INSN_DELETED:
case NOTE_INSN_LOOP_BEG:
case NOTE_INSN_LOOP_END:
- case NOTE_INSN_LOOP_CONT:
- case NOTE_INSN_LOOP_VTOP:
case NOTE_INSN_FUNCTION_END:
case NOTE_INSN_REPEATED_LINE_NUMBER:
case NOTE_INSN_EXPECTED_VALUE:
INSN_NOTE (LOOP_BEG)
INSN_NOTE (LOOP_END)
-/* Generated at the place in a loop that `continue' jumps to. */
-INSN_NOTE (LOOP_CONT)
-/* Generated at the start of a duplicated exit test. */
-INSN_NOTE (LOOP_VTOP)
-
/* This note indicates the start of the real body of the function,
i.e. the point just after all of the parms have been moved into
their homes, etc. */
&& (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END
|| NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG
|| NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG
- || NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END
- || NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_CONT
- || NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_VTOP))
+ || NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END))
{
if (insn == start)
start = next;
since in that case saving an insn makes more difference
and more registers are available. */
int threshold;
- /* Nonzero if we are scanning instructions in a sub-loop. */
- int loop_depth = 0;
int in_libcall;
loop->top = 0;
insn_count = count_insns_in_loop (loop);
if (loop_dump_stream)
- {
- fprintf (loop_dump_stream, "\nLoop from %d to %d: %d real insns.\n",
- INSN_UID (loop_start), INSN_UID (loop_end), insn_count);
- if (loop->cont)
- fprintf (loop_dump_stream, "Continue at insn %d.\n",
- INSN_UID (loop->cont));
- }
+ fprintf (loop_dump_stream, "\nLoop from %d to %d: %d real insns.\n",
+ INSN_UID (loop_start), INSN_UID (loop_end), insn_count);
/* Scan through the loop finding insns that are safe to move.
Set REGS->ARRAY[I].SET_IN_LOOP negative for the reg I being set, so that
&& NEXT_INSN (NEXT_INSN (p)) == loop_end
&& any_uncondjump_p (p)))
maybe_never = 1;
- else if (NOTE_P (p))
- {
- /* At the virtual top of a converted loop, insns are again known to
- be executed: logically, the loop begins here even though the exit
- code has been duplicated. */
- if (NOTE_LINE_NUMBER (p) == NOTE_INSN_LOOP_VTOP && loop_depth == 0)
- maybe_never = call_passed = 0;
- else if (NOTE_LINE_NUMBER (p) == NOTE_INSN_LOOP_BEG)
- loop_depth++;
- else if (NOTE_LINE_NUMBER (p) == NOTE_INSN_LOOP_END)
- loop_depth--;
- }
}
/* If one movable subsumes another, ignore that other. */
return value;
}
\f
-/* Scan a loop setting the elements `cont', `vtop', `loops_enclosed',
+/* Scan a loop setting the elements `loops_enclosed',
`has_call', `has_nonconst_call', `has_volatile', `has_tablejump',
`unknown_address_altered', `unknown_constant_address_altered', and
`num_mem_sets' in LOOP. Also, fill in the array `mems' and the
current_loop = next_loop;
break;
- case NOTE_INSN_LOOP_CONT:
- current_loop->cont = insn;
- break;
-
- case NOTE_INSN_LOOP_VTOP:
- current_loop->vtop = insn;
- break;
-
case NOTE_INSN_LOOP_END:
if (! current_loop)
abort ();
int not_every_iteration = 0;
int maybe_multiple = 0;
int past_loop_latch = 0;
- int loop_depth = 0;
rtx p;
/* If loop_scan_start points to the loop exit test, we have to be wary of
not_every_iteration = 1;
}
- else if (NOTE_P (p))
- {
- /* At the virtual top of a converted loop, insns are again known to
- be executed each iteration: logically, the loop begins here
- even though the exit code has been duplicated.
-
- Insns are also again known to be executed each iteration at
- the LOOP_CONT note. */
- if ((NOTE_LINE_NUMBER (p) == NOTE_INSN_LOOP_VTOP
- || NOTE_LINE_NUMBER (p) == NOTE_INSN_LOOP_CONT)
- && loop_depth == 0)
- not_every_iteration = 0;
- else if (NOTE_LINE_NUMBER (p) == NOTE_INSN_LOOP_BEG)
- loop_depth++;
- else if (NOTE_LINE_NUMBER (p) == NOTE_INSN_LOOP_END)
- loop_depth--;
- }
-
/* Note if we pass a loop latch. If we do, then we can not clear
NOT_EVERY_ITERATION below when we pass the last CODE_LABEL in
a loop since a jump before the last CODE_LABEL may have started
if (not_every_iteration
&& !past_loop_latch
&& LABEL_P (p)
- && no_labels_between_p (p, loop->end)
- && loop_insn_first_p (p, loop->cont))
+ && no_labels_between_p (p, loop->end))
not_every_iteration = 0;
}
}
sequence and see if we've got another comparison sequence. */
rtx jump1;
- if ((jump1 = prev_nonnote_insn (first_compare)) != loop->cont)
- if (JUMP_P (jump1))
+ if ((jump1 = prev_nonnote_insn (first_compare))
+ && JUMP_P (jump1))
return 0;
}
/* First check if we can do a vanilla loop reversal. */
if (initial_value == const0_rtx
- /* If we have a decrement_and_branch_on_count,
- prefer the NE test, since this will allow that
- instruction to be generated. Note that we must
- use a vanilla loop reversal if the biv is used to
- calculate a giv or has a non-counting use. */
-#if ! defined (HAVE_decrement_and_branch_until_zero) \
-&& defined (HAVE_decrement_and_branch_on_count)
- && (! (add_val == 1 && loop->vtop
- && (bl->biv_count == 0
- || no_use_except_counting)))
-#endif
&& GET_CODE (comparison_value) == CONST_INT
/* Now do postponed overflow checks on COMPARISON_VAL. */
&& ! (((comparison_val - add_val) ^ INTVAL (comparison_value))
nonneg = 1;
cmp_code = GE;
}
- else if (add_val == 1 && loop->vtop
- && (bl->biv_count == 0
- || no_use_except_counting))
- {
- add_adjust = 0;
- cmp_code = NE;
- }
else
return 0;
if (loop->start)
{
fprintf (file,
- ";; start %d (%d), cont dom %d (%d), cont %d (%d), vtop %d (%d), end %d (%d)\n",
+ ";; start %d (%d), end %d (%d)\n",
LOOP_BLOCK_NUM (loop->start),
LOOP_INSN_UID (loop->start),
- LOOP_BLOCK_NUM (loop->cont),
- LOOP_INSN_UID (loop->cont),
- LOOP_BLOCK_NUM (loop->cont),
- LOOP_INSN_UID (loop->cont),
- LOOP_BLOCK_NUM (loop->vtop),
- LOOP_INSN_UID (loop->vtop),
LOOP_BLOCK_NUM (loop->end),
LOOP_INSN_UID (loop->end));
fprintf (file, ";; top %d (%d), scan start %d (%d)\n",
}
}
fputs ("\n", file);
-
- /* This can happen when a marked loop appears as two nested loops,
- say from while (a || b) {}. The inner loop won't match
- the loop markers but the outer one will. */
- if (LOOP_BLOCK_NUM (loop->cont) != loop->latch->index)
- fprintf (file, ";; NOTE_INSN_LOOP_CONT not in loop latch\n");
}
}
insn = PREV_INSN (insn))
if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG)
return 2;
-
- /* If this is a jump to the test of a loop, it is likely true. We scan
- forwards from the target label. If we find a NOTE_INSN_LOOP_VTOP
- before the next real insn, we assume the branch is to the loop branch
- test. */
- for (insn = NEXT_INSN (target_label);
- insn && NOTE_P (insn);
- insn = PREV_INSN (insn))
- if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_VTOP)
- return 1;
}
/* Look at the relative rarities of the fallthrough and destination. If
static rtx fold_rtx_mult_add (rtx, rtx, rtx, enum machine_mode);
static rtx remap_split_bivs (struct loop *, rtx);
static rtx find_common_reg_term (rtx, rtx);
-static rtx subtract_reg_term (rtx, rtx);
static rtx loop_find_equiv_value (const struct loop *, rtx);
-static rtx ujump_to_loop_cont (rtx, rtx);
/* Try to unroll one loop and split induction variables in the loop.
jump to the loop condition. Make sure to delete the jump
insn, otherwise the loop body will never execute. */
- /* FIXME this actually checks for a jump to the continue point, which
- is not the same as the condition in a for loop. As a result, this
- optimization fails for most for loops. We should really use flow
- information rather than instruction pattern matching. */
- rtx ujump = ujump_to_loop_cont (loop->start, loop->cont);
-
- /* If number of iterations is exactly 1, then eliminate the compare and
- branch at the end of the loop since they will never be taken.
- Then return, since no other action is needed here. */
-
/* If the last instruction is not a BARRIER or a JUMP_INSN, then
don't do anything. */
/* Delete the jump insn. This will delete the barrier also. */
last_loop_insn = PREV_INSN (last_loop_insn);
}
-
- if (ujump && JUMP_P (last_loop_insn))
- {
-#ifdef HAVE_cc0
- rtx prev = PREV_INSN (last_loop_insn);
-#endif
- delete_related_insns (last_loop_insn);
-#ifdef HAVE_cc0
- /* The immediately preceding insn may be a compare which must be
- deleted. */
- if (only_sets_cc0_p (prev))
- delete_related_insns (prev);
-#endif
-
- delete_related_insns (ujump);
-
- /* Remove the loop notes since this is no longer a loop. */
- if (loop->vtop)
- delete_related_insns (loop->vtop);
- if (loop->cont)
- delete_related_insns (loop->cont);
- if (loop_start)
- delete_related_insns (loop_start);
- if (loop_end)
- delete_related_insns (loop_end);
-
- return;
- }
}
if (loop_info->n_iterations > 0
if (unroll_type == UNROLL_COMPLETELY)
{
/* Remove the loop notes since this is no longer a loop. */
- if (loop->vtop)
- delete_related_insns (loop->vtop);
- if (loop->cont)
- delete_related_insns (loop->cont);
if (loop_start)
delete_related_insns (loop_start);
if (loop_end)
break;
case NOTE:
- /* VTOP and CONT notes are valid only before the loop exit test.
- If placed anywhere else, loop may generate bad code. */
/* BASIC_BLOCK notes exist to stabilize basic block structures with
the associated rtl. We do not want to share the structure in
this new block. */
if (NOTE_LINE_NUMBER (insn) != NOTE_INSN_DELETED
- && NOTE_LINE_NUMBER (insn) != NOTE_INSN_DELETED_LABEL
- && NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK
- && ((NOTE_LINE_NUMBER (insn) != NOTE_INSN_LOOP_VTOP
- && NOTE_LINE_NUMBER (insn) != NOTE_INSN_LOOP_CONT)
- || (last_iteration
- && unroll_type != UNROLL_COMPLETELY)))
+ && NOTE_LINE_NUMBER (insn) != NOTE_INSN_DELETED_LABEL
+ && NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK)
copy = emit_note_copy (insn);
else
copy = 0;
{
for (insn = copy_notes_from; insn != loop_end; insn = NEXT_INSN (insn))
{
- /* VTOP notes are valid only before the loop exit test.
- If placed anywhere else, loop may generate bad code.
- Although COPY_NOTES_FROM will be at most one or two (for cc0)
- instructions before the last insn in the loop, COPY_NOTES_FROM
- can be a NOTE_INSN_LOOP_CONT note if there is no VTOP note,
- as in a do .. while loop. */
if (NOTE_P (insn)
- && ((NOTE_LINE_NUMBER (insn) != NOTE_INSN_DELETED
- && NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK
- && NOTE_LINE_NUMBER (insn) != NOTE_INSN_LOOP_VTOP
- && NOTE_LINE_NUMBER (insn) != NOTE_INSN_LOOP_CONT)))
+ && NOTE_LINE_NUMBER (insn) != NOTE_INSN_DELETED
+ && NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK)
emit_note_copy (insn);
}
}
return ret;
}
-/* Return a simplified rtx for the expression OP - REG.
-
- REG must appear in OP, and OP must be a register or the sum of a register
- and a second term.
-
- Thus, the return value must be const0_rtx or the second term.
-
- The caller is responsible for verifying that REG appears in OP and OP has
- the proper form. */
-
-static rtx
-subtract_reg_term (rtx op, rtx reg)
-{
- if (op == reg)
- return const0_rtx;
- if (GET_CODE (op) == PLUS)
- {
- if (XEXP (op, 0) == reg)
- return XEXP (op, 1);
- else if (XEXP (op, 1) == reg)
- return XEXP (op, 0);
- }
- /* OP does not contain REG as a term. */
- abort ();
-}
-
/* Find and return register term common to both expressions OP0 and
OP1 or NULL_RTX if no such term exists. Each expression must be a
REG or a PLUS of a REG. */
int increment_dir;
int unsigned_p, compare_dir, final_larger;
rtx last_loop_insn;
- rtx reg_term;
struct iv_class *bl;
loop_info->n_iterations = 0;
return 0;
}
- /* If there are multiple conditionalized loop exit tests, they may jump
- back to differing CODE_LABELs. */
- if (loop->top && loop->cont)
- {
- rtx temp = PREV_INSN (last_loop_insn);
-
- do
- {
- if (JUMP_P (temp))
- {
- /* There are some kinds of jumps we can't deal with easily. */
- if (JUMP_LABEL (temp) == 0)
- {
- if (loop_dump_stream)
- fprintf
- (loop_dump_stream,
- "Loop iterations: Jump insn has null JUMP_LABEL.\n");
- return 0;
- }
-
- if (/* Previous unrolling may have generated new insns not
- covered by the uid_luid array. */
- INSN_UID (JUMP_LABEL (temp)) < max_uid_for_loop
- /* Check if we jump back into the loop body. */
- && INSN_LUID (JUMP_LABEL (temp)) > INSN_LUID (loop->top)
- && INSN_LUID (JUMP_LABEL (temp)) < INSN_LUID (loop->cont))
- {
- if (loop_dump_stream)
- fprintf
- (loop_dump_stream,
- "Loop iterations: Loop has multiple back edges.\n");
- return 0;
- }
- }
- }
- while ((temp = PREV_INSN (temp)) != loop->cont);
- }
-
/* Find the iteration variable. If the last insn is a conditional
branch, and the insn before tests a register value, make that the
iteration variable. */
? reg1 : gen_rtx_PLUS (GET_MODE (reg1), reg1, const2);
}
}
- else if (loop->vtop && GET_CODE (reg2) == CONST_INT)
- {
- rtx temp;
-
- /* When running the loop optimizer twice, check_dbra_loop
- further obfuscates reversible loops of the form:
- for (i = init; i < init + const; i++). We often end up with
- final_value = 0, initial_value = temp, temp = temp2 - init,
- where temp2 = init + const. If the loop has a vtop we
- can replace initial_value with const. */
-
- temp = loop_find_equiv_value (loop, reg1);
-
- if (GET_CODE (temp) == MINUS && REG_P (XEXP (temp, 0)))
- {
- rtx temp2 = loop_find_equiv_value (loop, XEXP (temp, 0));
-
- if (GET_CODE (temp2) == PLUS
- && XEXP (temp2, 0) == XEXP (temp, 1))
- initial_value = XEXP (temp2, 1);
- }
- }
- }
-
- /* If have initial_value = reg + const1 and final_value = reg +
- const2, then replace initial_value with const1 and final_value
- with const2. This should be safe since we are protected by the
- initial comparison before entering the loop if we have a vtop.
- For example, a + b < a + c is not equivalent to b < c for all a
- when using modulo arithmetic.
-
- ??? Without a vtop we could still perform the optimization if we check
- the initial and final values carefully. */
- if (loop->vtop
- && (reg_term = find_common_reg_term (initial_value, final_value)))
- {
- initial_value = subtract_reg_term (initial_value, reg_term);
- final_value = subtract_reg_term (final_value, reg_term);
}
loop_info->initial_equiv_value = initial_value;
return 1;
}
-/* This routine is called when the number of iterations for the unrolled
- loop is one. The goal is to identify a loop that begins with an
- unconditional branch to the loop continuation note (or a label just after).
- In this case, the unconditional branch that starts the loop needs to be
- deleted so that we execute the single iteration. */
-
-static rtx
-ujump_to_loop_cont (rtx loop_start, rtx loop_cont)
-{
- rtx x, label, label_ref;
-
- /* See if loop start, or the next insn is an unconditional jump. */
- loop_start = next_nonnote_insn (loop_start);
-
- x = pc_set (loop_start);
- if (!x)
- return NULL_RTX;
-
- label_ref = SET_SRC (x);
- if (!label_ref)
- return NULL_RTX;
-
- /* Examine insn after loop continuation note. Return if not a label. */
- label = next_nonnote_insn (loop_cont);
- if (label == 0 || !LABEL_P (label))
- return NULL_RTX;
-
- /* Return the loop start if the branch label matches the code label. */
- if (CODE_LABEL_NUMBER (label) == CODE_LABEL_NUMBER (XEXP (label_ref, 0)))
- return loop_start;
- else
- return NULL_RTX;
-}