Contributed by Michael Tiemann (tiemann@cygnus.com) Enhanced by,
and currently maintained by, Jim Wilson (wilson@cygnus.com)
-This file is part of GNU CC.
+This file is part of GCC.
-GNU CC is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 2, or (at your option) any
-later version.
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
-GNU CC is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING. If not, write to the Free
-the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+along with GCC; see the file COPYING. If not, write to the Free the
+Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA. */
\f
#include "config.h"
#include "recog.h"
#include "sched-int.h"
#include "params.h"
+#include "cselib.h"
extern char *reg_known_equiv_p;
extern rtx *reg_known_value;
Each insn has associated bitmaps for its dependencies. Each bitmap
has enough entries to represent a dependency on any other insn in
the insn chain. All bitmap for true dependencies cache is
- allocated then the rest two ones are also allocated. */
+ allocated then the rest two ones are also allocated. */
static sbitmap *true_dependency_cache;
static sbitmap *anti_dependency_cache;
static sbitmap *output_dependency_cache;
/* To speed up checking consistency of formed forward insn
dependencies we use the following cache. Another possible solution
could be switching off checking duplication of insns in forward
- dependencies. */
+ dependencies. */
#ifdef ENABLE_CHECKING
static sbitmap *forward_dependency_cache;
#endif
/* flow.c doesn't handle conditional lifetimes entirely correctly;
calls mess up the conditional lifetimes. */
+ /* ??? add_dependence is the wrong place to be eliding dependencies,
+ as that forgets that the condition expressions themselves may
+ be dependent. */
if (GET_CODE (insn) != CALL_INSN && GET_CODE (elem) != CALL_INSN)
{
cond1 = get_condition (insn);
cond2 = get_condition (elem);
- if (cond1 && cond2 && conditions_mutex_p (cond1, cond2))
+ if (cond1 && cond2
+ && conditions_mutex_p (cond1, cond2)
+ && !modified_in_p (cond1, elem))
return;
}
{
#ifdef INSN_SCHEDULING
/* Clear corresponding cache entry because type of the link
- may be changed. */
+ may be changed. */
if (true_dependency_cache != NULL)
{
if (REG_NOTE_KIND (link) == REG_DEP_ANTI)
#ifdef INSN_SCHEDULING
/* If we are adding a dependency to INSN's LOG_LINKs, then
- note that in the bitmap caches of dependency information. */
+ note that in the bitmap caches of dependency information. */
if (true_dependency_cache != NULL)
{
if ((int)REG_NOTE_KIND (link) == 0)
#ifdef INSN_SCHEDULING
/* If we are adding a dependency to INSN's LOG_LINKs, then note that
- in the bitmap caches of dependency information. */
+ in the bitmap caches of dependency information. */
if (true_dependency_cache != NULL)
{
if ((int)dep_type == 0)
link = alloc_INSN_LIST (insn, *insn_list);
*insn_list = link;
+ if (current_sched_info->use_cselib)
+ {
+ mem = shallow_copy_rtx (mem);
+ XEXP (mem, 0) = cselib_subst_to_values (XEXP (mem, 0));
+ }
link = alloc_EXPR_LIST (VOIDmode, mem, *mem_list);
*mem_list = link;
else if (GET_CODE (dest) == MEM)
{
/* Writing memory. */
+ rtx t = dest;
+
+ if (current_sched_info->use_cselib)
+ {
+ t = shallow_copy_rtx (dest);
+ cselib_lookup (XEXP (t, 0), Pmode, 1);
+ XEXP (t, 0) = cselib_subst_to_values (XEXP (t, 0));
+ }
if (deps->pending_lists_length > MAX_PENDING_LIST_LENGTH)
{
pending_mem = deps->pending_read_mems;
while (pending)
{
- if (anti_dependence (XEXP (pending_mem, 0), dest))
+ if (anti_dependence (XEXP (pending_mem, 0), t))
add_dependence (insn, XEXP (pending, 0), REG_DEP_ANTI);
pending = XEXP (pending, 1);
pending_mem = deps->pending_write_mems;
while (pending)
{
- if (output_dependence (XEXP (pending_mem, 0), dest))
+ if (output_dependence (XEXP (pending_mem, 0), t))
add_dependence (insn, XEXP (pending, 0), REG_DEP_OUTPUT);
pending = XEXP (pending, 1);
/* Reading memory. */
rtx u;
rtx pending, pending_mem;
+ rtx t = x;
+ if (current_sched_info->use_cselib)
+ {
+ t = shallow_copy_rtx (t);
+ cselib_lookup (XEXP (t, 0), Pmode, 1);
+ XEXP (t, 0) = cselib_subst_to_values (XEXP (t, 0));
+ }
pending = deps->pending_read_insns;
pending_mem = deps->pending_read_mems;
while (pending)
{
- if (read_dependence (XEXP (pending_mem, 0), x))
+ if (read_dependence (XEXP (pending_mem, 0), t))
add_dependence (insn, XEXP (pending, 0), REG_DEP_ANTI);
pending = XEXP (pending, 1);
while (pending)
{
if (true_dependence (XEXP (pending_mem, 0), VOIDmode,
- x, rtx_varies_p))
+ t, rtx_varies_p))
add_dependence (insn, XEXP (pending, 0), 0);
pending = XEXP (pending, 1);
/* Mark registers CLOBBERED or used by called function. */
if (GET_CODE (insn) == CALL_INSN)
- for (link = CALL_INSN_FUNCTION_USAGE (insn); link; link = XEXP (link, 1))
- {
- if (GET_CODE (XEXP (link, 0)) == CLOBBER)
- sched_analyze_1 (deps, XEXP (link, 0), insn);
- else
- sched_analyze_2 (deps, XEXP (link, 0), insn);
- }
+ {
+ for (link = CALL_INSN_FUNCTION_USAGE (insn); link; link = XEXP (link, 1))
+ {
+ if (GET_CODE (XEXP (link, 0)) == CLOBBER)
+ sched_analyze_1 (deps, XEXP (link, 0), insn);
+ else
+ sched_analyze_2 (deps, XEXP (link, 0), insn);
+ }
+ if (find_reg_note (insn, REG_SETJMP, NULL))
+ schedule_barrier_found = 1;
+ }
if (GET_CODE (insn) == JUMP_INSN)
{
if (INTVAL (XEXP (link, 0)) == NOTE_INSN_LOOP_BEG
|| INTVAL (XEXP (link, 0)) == NOTE_INSN_LOOP_END
|| INTVAL (XEXP (link, 0)) == NOTE_INSN_EH_REGION_BEG
- || INTVAL (XEXP (link, 0)) == NOTE_INSN_EH_REGION_END
- || INTVAL (XEXP (link, 0)) == NOTE_INSN_SETJMP)
+ || INTVAL (XEXP (link, 0)) == NOTE_INSN_EH_REGION_END)
schedule_barrier_found = 1;
link = XEXP (link, 1);
register rtx u;
rtx loop_notes = 0;
+ if (current_sched_info->use_cselib)
+ cselib_init ();
+
for (insn = head;; insn = NEXT_INSN (insn))
{
if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN)
past a void call (i.e. it does not explicitly set the hard
return reg). */
- /* If this call is followed by a NOTE_INSN_SETJMP, then assume that
+ /* If this call has REG_SETJMP, then assume that
all registers, not just hard registers, may be clobbered by this
call. */
/* Insn, being a CALL_INSN, magically depends on
`last_function_call' already. */
- if (NEXT_INSN (insn) && GET_CODE (NEXT_INSN (insn)) == NOTE
- && NOTE_LINE_NUMBER (NEXT_INSN (insn)) == NOTE_INSN_SETJMP)
+ if (find_reg_note (insn, REG_SETJMP, NULL))
{
for (i = 0; i < deps->max_reg; i++)
{
free_INSN_LIST_list (®_last->uses);
}
reg_pending_sets_all = 1;
-
- /* Add a pair of REG_SAVE_NOTEs which we will later
- convert back into a NOTE_INSN_SETJMP note. See
- reemit_notes for why we use a pair of NOTEs. */
- REG_NOTES (insn) = alloc_EXPR_LIST (REG_SAVE_NOTE,
- GEN_INT (0),
- REG_NOTES (insn));
- REG_NOTES (insn) = alloc_EXPR_LIST (REG_SAVE_NOTE,
- GEN_INT (NOTE_INSN_SETJMP),
- REG_NOTES (insn));
}
else
{
&& (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG
|| NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END
|| NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_BEG
- || NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_END
- || (NOTE_LINE_NUMBER (insn) == NOTE_INSN_SETJMP
- && GET_CODE (PREV_INSN (insn)) != CALL_INSN)))
+ || NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_END))
{
rtx rtx_region;
CONST_OR_PURE_CALL_P (loop_notes) = CONST_OR_PURE_CALL_P (insn);
}
+ if (current_sched_info->use_cselib)
+ cselib_process_insn (insn);
if (insn == tail)
- return;
+ {
+ if (current_sched_info->use_cselib)
+ cselib_finish ();
+ return;
+ }
}
abort ();
}