Commit ed6cc1f5 by J"orn Rennecke Committed by Joern Rennecke

loop.c (scan_loop): Don't mark separate insns out of a libcall for moving.

gcc:
	* loop.c (scan_loop): Don't mark separate insns out of a libcall
	for moving.
	(move_movables): Abort if we see the first insn of a libcall.
gcc/testsuite
	* gcc.c-torture/execute/loop-14.c: New test.

From-SVN: r56823
parent 5aa3396c
Thu Sep 5 00:34:33 2002 J"orn Rennecke <joern.rennecke@superh.com>
* loop.c (scan_loop): Don't mark separate insns out of a libcall
for moving.
(move_movables): Abort if we see the first insn of a libcall.
2002-09-04 Richard Henderson <rth@redhat.com>
* builtin-types.def (BT_FN_FLOAT): New.
......
......@@ -633,6 +633,7 @@ scan_loop (loop, flags)
int threshold;
/* Nonzero if we are scanning instructions in a sub-loop. */
int loop_depth = 0;
int in_libcall;
loop->top = 0;
......@@ -749,11 +750,18 @@ scan_loop (loop, flags)
When MAYBE_NEVER is 0, all insns will be executed at least once
so that is not a problem. */
for (p = next_insn_in_loop (loop, loop->scan_start);
for (in_libcall = 0, p = next_insn_in_loop (loop, loop->scan_start);
p != NULL_RTX;
p = next_insn_in_loop (loop, p))
{
if (GET_CODE (p) == INSN
if (in_libcall && INSN_P (p) && find_reg_note (p, REG_RETVAL, NULL_RTX))
in_libcall--;
if (GET_CODE (p) == INSN)
{
temp = find_reg_note (p, REG_LIBCALL, NULL_RTX);
if (temp)
in_libcall++;
if (! in_libcall
&& (set = single_set (p))
&& GET_CODE (SET_DEST (set)) == REG
#ifdef PIC_OFFSET_TABLE_REG_CALL_CLOBBERED
......@@ -767,14 +775,14 @@ scan_loop (loop, flags)
rtx src = SET_SRC (set);
rtx dependencies = 0;
/* Figure out what to use as a source of this insn. If a REG_EQUIV
note is given or if a REG_EQUAL note with a constant operand is
specified, use it as the source and mark that we should move
this insn by calling emit_move_insn rather that duplicating the
insn.
/* Figure out what to use as a source of this insn. If a
REG_EQUIV note is given or if a REG_EQUAL note with a
constant operand is specified, use it as the source and
mark that we should move this insn by calling
emit_move_insn rather that duplicating the insn.
Otherwise, only use the REG_EQUAL contents if a REG_RETVAL note
is present. */
Otherwise, only use the REG_EQUAL contents if a REG_RETVAL
note is present. */
temp = find_reg_note (p, REG_EQUIV, NULL_RTX);
if (temp)
src = XEXP (temp, 0), move_insn = 1;
......@@ -793,21 +801,24 @@ scan_loop (loop, flags)
}
}
/* For parallels, add any possible uses to the depencies, as we can't move
the insn without resolving them first. */
/* For parallels, add any possible uses to the depencies, as
we can't move the insn without resolving them first. */
if (GET_CODE (PATTERN (p)) == PARALLEL)
{
for (i = 0; i < XVECLEN (PATTERN (p), 0); i++)
{
rtx x = XVECEXP (PATTERN (p), 0, i);
if (GET_CODE (x) == USE)
dependencies = gen_rtx_EXPR_LIST (VOIDmode, XEXP (x, 0), dependencies);
dependencies
= gen_rtx_EXPR_LIST (VOIDmode, XEXP (x, 0),
dependencies);
}
}
/* Don't try to optimize a register that was made
by loop-optimization for an inner loop.
We don't know its life-span, so we can't compute the benefit. */
We don't know its life-span, so we can't compute
the benefit. */
if (REGNO (SET_DEST (set)) >= max_reg_before_loop)
;
else if (/* The register is used in basic blocks other
......@@ -829,12 +840,14 @@ scan_loop (loop, flags)
/* It is unsafe to move the set.
This code used to consider it OK to move a set of a variable
which was not created by the user and not used in an exit test.
which was not created by the user and not used in an exit
test.
That behavior is incorrect and was removed. */
;
else if ((tem = loop_invariant_p (loop, src))
&& (dependencies == 0
|| (tem2 = loop_invariant_p (loop, dependencies)) != 0)
|| (tem2
= loop_invariant_p (loop, dependencies)) != 0)
&& (regs->array[REGNO (SET_DEST (set))].set_in_loop == 1
|| (tem1
= consec_sets_invariant_p
......@@ -858,10 +871,11 @@ scan_loop (loop, flags)
this can lose. The most common case of this is the address
of a function being called.
Therefore, if this register is marked as being used exactly
once if we are in a loop with calls (a "large loop"), see if
we can replace the usage of this register with the source
of this SET. If we can, delete this insn.
Therefore, if this register is marked as being used
exactly once if we are in a loop with calls
(a "large loop"), see if we can replace the usage of
this register with the source of this SET. If we can,
delete this insn.
Don't do this if P has a REG_RETVAL note or if we have
SMALL_REGISTER_CLASSES and SET_SRC is a hard register. */
......@@ -878,25 +892,29 @@ scan_loop (loop, flags)
&& ! find_reg_note (p, REG_RETVAL, NULL_RTX)
&& (! SMALL_REGISTER_CLASSES
|| (! (GET_CODE (SET_SRC (set)) == REG
&& REGNO (SET_SRC (set)) < FIRST_PSEUDO_REGISTER)))
&& (REGNO (SET_SRC (set))
< FIRST_PSEUDO_REGISTER))))
/* This test is not redundant; SET_SRC (set) might be
a call-clobbered register and the life of REGNO
might span a call. */
&& ! modified_between_p (SET_SRC (set), p,
regs->array[regno].single_usage)
&& no_labels_between_p (p, regs->array[regno].single_usage)
&& no_labels_between_p (p,
regs->array[regno].single_usage)
&& validate_replace_rtx (SET_DEST (set), SET_SRC (set),
regs->array[regno].single_usage))
{
/* Replace any usage in a REG_EQUAL note. Must copy the
new source, so that we don't get rtx sharing between the
SET_SOURCE and REG_NOTES of insn p. */
/* Replace any usage in a REG_EQUAL note. Must copy
the new source, so that we don't get rtx sharing
between the SET_SOURCE and REG_NOTES of insn p. */
REG_NOTES (regs->array[regno].single_usage)
= replace_rtx (REG_NOTES (regs->array[regno].single_usage),
SET_DEST (set), copy_rtx (SET_SRC (set)));
= (replace_rtx
(REG_NOTES (regs->array[regno].single_usage),
SET_DEST (set), copy_rtx (SET_SRC (set))));
delete_insn (p);
for (i = 0; i < (int) LOOP_REGNO_NREGS (regno, SET_DEST (set)); i++)
for (i = 0; i < LOOP_REGNO_NREGS (regno, SET_DEST (set));
i++)
regs->array[regno+i].set_in_loop = 0;
continue;
}
......@@ -908,7 +926,8 @@ scan_loop (loop, flags)
m->dependencies = dependencies;
m->set_dest = SET_DEST (set);
m->force = 0;
m->consec = regs->array[REGNO (SET_DEST (set))].set_in_loop - 1;
m->consec
= regs->array[REGNO (SET_DEST (set))].set_in_loop - 1;
m->done = 0;
m->forces = 0;
m->partial = 0;
......@@ -947,9 +966,9 @@ scan_loop (loop, flags)
/* Back up to the last insn of the consecutive group. */
p = prev_nonnote_insn (p);
/* We must now reset m->move_insn, m->is_equiv, and possibly
m->set_src to correspond to the effects of all the
insns. */
/* We must now reset m->move_insn, m->is_equiv, and
possibly m->set_src to correspond to the effects of
all the insns. */
temp = find_reg_note (p, REG_EQUIV, NULL_RTX);
if (temp)
m->set_src = XEXP (temp, 0), m->move_insn = 1;
......@@ -962,7 +981,8 @@ scan_loop (loop, flags)
m->move_insn = 0;
}
m->is_equiv = (find_reg_note (p, REG_EQUIV, NULL_RTX) != 0);
m->is_equiv
= (find_reg_note (p, REG_EQUIV, NULL_RTX) != 0);
}
}
/* If this register is always set within a STRICT_LOW_PART
......@@ -1029,13 +1049,16 @@ scan_loop (loop, flags)
m->match = 0;
m->lifetime = LOOP_REG_LIFETIME (loop, regno);
m->savings = 1;
for (i = 0; i < (int) LOOP_REGNO_NREGS (regno, SET_DEST (set)); i++)
for (i = 0;
i < (int) LOOP_REGNO_NREGS (regno, SET_DEST (set));
i++)
regs->array[regno+i].set_in_loop = -1;
/* Add M to the end of the chain MOVABLES. */
loop_movables_add (movables, m);
}
}
}
}
/* Past a call insn, we get to insns which might not be executed
because the call might exit. This matters for insns that trap.
Constant and pure call insns always return, so they don't count. */
......@@ -1905,10 +1928,10 @@ move_movables (loop, movables, threshold, insn_count)
for (count = m->consec; count >= 0; count--)
{
/* If this is the first insn of a library call sequence,
skip to the end. */
something is very wrong. */
if (GET_CODE (p) != NOTE
&& (temp = find_reg_note (p, REG_LIBCALL, NULL_RTX)))
p = XEXP (temp, 0);
abort ();
/* If this is the last insn of a libcall sequence, then
delete every insn in the sequence except the last.
......
Thu Sep 5 00:34:33 2002 J"orn Rennecke <joern.rennecke@superh.com>
* gcc.c-torture/execute/loop-14.c: New test.
2002-09-04 Jakub Jelinek <jakub@redhat.com>
* g++.dg/other/cxa-atexit1.C: New test.
......
int a3[3];
void f(int *a)
{
int i;
for (i=3; --i;)
a[i] = 42 / i;
}
int
main ()
{
f(a3);
if (a3[1] != 42 || a3[2] != 21)
abort ();
exit (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