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