Commit ca545bb5 by Bob Manson Committed by Richard Henderson

Bob Manson <manson@charmed.cygnus.com>

Bob Manson  <manson@charmed.cygnus.com>
        * resource.c, resource.h: New files.
        * haifa-sched.c (regno_use_in): Moved to rtlanal.c.
        (split_block_insns): Moved to recog.c.
        (update_flow_info): Make public.
        * reorg.c: Moved the functions dealing with computing resource
        usage to resource.c.
        * sched.c (regno_use_in): Moved to rtlanal.c.
        (update_flow_info): Make public.
        (schedule_insns): Use split_block_insns.
        * recog.c (split_block_insns): New function.

From-SVN: r24982
parent ee0d2cf3
Fri Jan 29 21:00:56 1999 Bob Manson <manson@charmed.cygnus.com>
* resource.c, resource.h: New files.
* haifa-sched.c (regno_use_in): Moved to rtlanal.c.
(split_block_insns): Moved to recog.c.
(update_flow_info): Make public.
* reorg.c: Moved the functions dealing with computing resource
usage to resource.c.
* sched.c (regno_use_in): Moved to rtlanal.c.
(update_flow_info): Make public.
(schedule_insns): Use split_block_insns.
* recog.c (split_block_insns): New function.
Tue Feb 2 22:03:26 1999 David Edelsohn <edelsohn@mhpcc.edu> Tue Feb 2 22:03:26 1999 David Edelsohn <edelsohn@mhpcc.edu>
* rs6000/linux.h (LINK_START_DEFAULT_SPEC): Delete, unused. * rs6000/linux.h (LINK_START_DEFAULT_SPEC): Delete, unused.
......
...@@ -448,11 +448,9 @@ static void attach_deaths_insn PROTO ((rtx)); ...@@ -448,11 +448,9 @@ static void attach_deaths_insn PROTO ((rtx));
static int new_sometimes_live PROTO ((struct sometimes *, int, int)); static int new_sometimes_live PROTO ((struct sometimes *, int, int));
static void finish_sometimes_live PROTO ((struct sometimes *, int)); static void finish_sometimes_live PROTO ((struct sometimes *, int));
static int schedule_block PROTO ((int, int)); static int schedule_block PROTO ((int, int));
static rtx regno_use_in PROTO ((int, rtx));
static void split_hard_reg_notes PROTO ((rtx, rtx, rtx)); static void split_hard_reg_notes PROTO ((rtx, rtx, rtx));
static void new_insn_dead_notes PROTO ((rtx, rtx, rtx, rtx)); static void new_insn_dead_notes PROTO ((rtx, rtx, rtx, rtx));
static void update_n_sets PROTO ((rtx, int)); static void update_n_sets PROTO ((rtx, int));
static void update_flow_info PROTO ((rtx, rtx, rtx, rtx));
static char *safe_concat PROTO ((char *, char *, char *)); static char *safe_concat PROTO ((char *, char *, char *));
static int insn_issue_delay PROTO ((rtx)); static int insn_issue_delay PROTO ((rtx));
static int birthing_insn_p PROTO ((rtx)); static int birthing_insn_p PROTO ((rtx));
...@@ -765,7 +763,6 @@ static rtx group_leader PROTO ((rtx)); ...@@ -765,7 +763,6 @@ static rtx group_leader PROTO ((rtx));
static int set_priorities PROTO ((int)); static int set_priorities PROTO ((int));
static void init_rtx_vector PROTO ((rtx **, rtx *, int, int)); static void init_rtx_vector PROTO ((rtx **, rtx *, int, int));
static void schedule_region PROTO ((int)); static void schedule_region PROTO ((int));
static void split_block_insns PROTO ((int));
#endif /* INSN_SCHEDULING */ #endif /* INSN_SCHEDULING */
...@@ -7699,39 +7696,6 @@ schedule_region (rgn) ...@@ -7699,39 +7696,6 @@ schedule_region (rgn)
FREE_REG_SET (reg_pending_sets); FREE_REG_SET (reg_pending_sets);
} }
/* Subroutine of split_hard_reg_notes. Searches X for any reference to
REGNO, returning the rtx of the reference found if any. Otherwise,
returns 0. */
static rtx
regno_use_in (regno, x)
int regno;
rtx x;
{
register char *fmt;
int i, j;
rtx tem;
if (GET_CODE (x) == REG && REGNO (x) == regno)
return x;
fmt = GET_RTX_FORMAT (GET_CODE (x));
for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
{
if (fmt[i] == 'e')
{
if ((tem = regno_use_in (regno, XEXP (x, i))))
return tem;
}
else if (fmt[i] == 'E')
for (j = XVECLEN (x, i) - 1; j >= 0; j--)
if ((tem = regno_use_in (regno, XVECEXP (x, i, j))))
return tem;
}
return 0;
}
/* Subroutine of update_flow_info. Determines whether any new REG_NOTEs are /* Subroutine of update_flow_info. Determines whether any new REG_NOTEs are
needed for the hard register mentioned in the note. This can happen needed for the hard register mentioned in the note. This can happen
if the reference to the hard register in the original insn was split into if the reference to the hard register in the original insn was split into
...@@ -7918,7 +7882,7 @@ update_n_sets (x, inc) ...@@ -7918,7 +7882,7 @@ update_n_sets (x, inc)
the insns from FIRST to LAST inclusive that were created by splitting the insns from FIRST to LAST inclusive that were created by splitting
ORIG_INSN. NOTES are the original REG_NOTES. */ ORIG_INSN. NOTES are the original REG_NOTES. */
static void void
update_flow_info (notes, first, last, orig_insn) update_flow_info (notes, first, last, orig_insn)
rtx notes; rtx notes;
rtx first, last; rtx first, last;
...@@ -8409,79 +8373,6 @@ update_flow_info (notes, first, last, orig_insn) ...@@ -8409,79 +8373,6 @@ update_flow_info (notes, first, last, orig_insn)
} }
} }
/* Do the splitting of insns in the block b. */
static void
split_block_insns (b)
int b;
{
rtx insn, next;
for (insn = BLOCK_HEAD (b);; insn = next)
{
rtx set, last, first, notes;
/* Can't use `next_real_insn' because that
might go across CODE_LABELS and short-out basic blocks. */
next = NEXT_INSN (insn);
if (GET_CODE (insn) != INSN)
{
if (insn == BLOCK_END (b))
break;
continue;
}
/* Don't split no-op move insns. These should silently disappear
later in final. Splitting such insns would break the code
that handles REG_NO_CONFLICT blocks. */
set = single_set (insn);
if (set && rtx_equal_p (SET_SRC (set), SET_DEST (set)))
{
if (insn == BLOCK_END (b))
break;
/* Nops get in the way while scheduling, so delete them now if
register allocation has already been done. It is too risky
to try to do this before register allocation, and there are
unlikely to be very many nops then anyways. */
if (reload_completed)
{
PUT_CODE (insn, NOTE);
NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
NOTE_SOURCE_FILE (insn) = 0;
}
continue;
}
/* Split insns here to get max fine-grain parallelism. */
first = PREV_INSN (insn);
notes = REG_NOTES (insn);
last = try_split (PATTERN (insn), insn, 1);
if (last != insn)
{
/* try_split returns the NOTE that INSN became. */
first = NEXT_INSN (first);
update_flow_info (notes, first, last, insn);
PUT_CODE (insn, NOTE);
NOTE_SOURCE_FILE (insn) = 0;
NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
if (insn == BLOCK_HEAD (b))
BLOCK_HEAD (b) = first;
if (insn == BLOCK_END (b))
{
BLOCK_END (b) = last;
break;
}
}
if (insn == BLOCK_END (b))
break;
}
}
/* The one entry point in this file. DUMP_FILE is the dump file for /* The one entry point in this file. DUMP_FILE is the dump file for
this pass. */ this pass. */
...@@ -8535,7 +8426,7 @@ schedule_insns (dump_file) ...@@ -8535,7 +8426,7 @@ schedule_insns (dump_file)
/* do the splitting first for all blocks */ /* do the splitting first for all blocks */
for (b = 0; b < n_basic_blocks; b++) for (b = 0; b < n_basic_blocks; b++)
split_block_insns (b); split_block_insns (b, 1);
max_uid = (get_max_uid () + 1); max_uid = (get_max_uid () + 1);
......
...@@ -32,6 +32,7 @@ Boston, MA 02111-1307, USA. */ ...@@ -32,6 +32,7 @@ Boston, MA 02111-1307, USA. */
#include "flags.h" #include "flags.h"
#include "real.h" #include "real.h"
#include "toplev.h" #include "toplev.h"
#include "basic-block.h"
#ifndef STACK_PUSH_CODE #ifndef STACK_PUSH_CODE
#ifdef STACK_GROWS_DOWNWARD #ifdef STACK_GROWS_DOWNWARD
...@@ -2596,3 +2597,83 @@ reg_fits_class_p (operand, class, offset, mode) ...@@ -2596,3 +2597,83 @@ reg_fits_class_p (operand, class, offset, mode)
} }
#endif /* REGISTER_CONSTRAINTS */ #endif /* REGISTER_CONSTRAINTS */
/* Do the splitting of insns in the block B. Only try to actually split if
DO_SPLIT is true; otherwise, just remove nops. */
void
split_block_insns (b, do_split)
int b;
int do_split;
{
rtx insn, next;
for (insn = BLOCK_HEAD (b);; insn = next)
{
rtx set;
/* Can't use `next_real_insn' because that
might go across CODE_LABELS and short-out basic blocks. */
next = NEXT_INSN (insn);
if (GET_CODE (insn) != INSN)
{
if (insn == BLOCK_END (b))
break;
continue;
}
/* Don't split no-op move insns. These should silently disappear
later in final. Splitting such insns would break the code
that handles REG_NO_CONFLICT blocks. */
set = single_set (insn);
if (set && rtx_equal_p (SET_SRC (set), SET_DEST (set)))
{
if (insn == BLOCK_END (b))
break;
/* Nops get in the way while scheduling, so delete them now if
register allocation has already been done. It is too risky
to try to do this before register allocation, and there are
unlikely to be very many nops then anyways. */
if (reload_completed)
{
PUT_CODE (insn, NOTE);
NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
NOTE_SOURCE_FILE (insn) = 0;
}
continue;
}
if (do_split)
{
/* Split insns here to get max fine-grain parallelism. */
rtx first = PREV_INSN (insn);
rtx notes = REG_NOTES (insn);
rtx last = try_split (PATTERN (insn), insn, 1);
if (last != insn)
{
/* try_split returns the NOTE that INSN became. */
first = NEXT_INSN (first);
update_flow_info (notes, first, last, insn);
PUT_CODE (insn, NOTE);
NOTE_SOURCE_FILE (insn) = 0;
NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
if (insn == BLOCK_HEAD (b))
BLOCK_HEAD (b) = first;
if (insn == BLOCK_END (b))
{
BLOCK_END (b) = last;
break;
}
}
}
if (insn == BLOCK_END (b))
break;
}
}
This diff is collapsed. Click to expand it.
/* Definitions for computing resource usage of specific insns.
Copyright (C) 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
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.
GNU CC 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 Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* Macro to clear all resources. */
#define CLEAR_RESOURCE(RES) \
do { (RES)->memory = (RES)->unch_memory = (RES)->volatil = (RES)->cc = 0; \
CLEAR_HARD_REG_SET ((RES)->regs); } while (0)
/* The resources used by a given insn. */
struct resources
{
char memory; /* Insn sets or needs a memory location. */
char unch_memory; /* Insn sets of needs a "unchanging" MEM. */
char volatil; /* Insn sets or needs a volatile memory loc. */
char cc; /* Insn sets or needs the condition codes. */
HARD_REG_SET regs; /* Which registers are set or needed. */
};
extern void mark_target_live_regs PROTO((rtx, rtx, struct resources *));
extern void mark_set_resources PROTO((rtx, struct resources *, int,
int));
extern void mark_referenced_resources PROTO((rtx, struct resources *, int));
extern void clear_hashed_info_for_insn PROTO((rtx));
extern void incr_ticks_for_insn PROTO((rtx));
extern void mark_end_of_function_resources PROTO ((rtx, int));
extern void init_resource_info PROTO((rtx));
extern void free_resource_info PROTO((void));
extern rtx find_free_register PROTO((rtx, char *, int,
HARD_REG_SET *));
...@@ -342,11 +342,9 @@ static int new_sometimes_live PROTO((struct sometimes *, int, int)); ...@@ -342,11 +342,9 @@ static int new_sometimes_live PROTO((struct sometimes *, int, int));
static void finish_sometimes_live PROTO((struct sometimes *, int)); static void finish_sometimes_live PROTO((struct sometimes *, int));
static rtx reemit_notes PROTO((rtx, rtx)); static rtx reemit_notes PROTO((rtx, rtx));
static void schedule_block PROTO((int, FILE *)); static void schedule_block PROTO((int, FILE *));
static rtx regno_use_in PROTO((int, rtx));
static void split_hard_reg_notes PROTO((rtx, rtx, rtx)); static void split_hard_reg_notes PROTO((rtx, rtx, rtx));
static void new_insn_dead_notes PROTO((rtx, rtx, rtx, rtx)); static void new_insn_dead_notes PROTO((rtx, rtx, rtx, rtx));
static void update_n_sets PROTO((rtx, int)); static void update_n_sets PROTO((rtx, int));
static void update_flow_info PROTO((rtx, rtx, rtx, rtx));
/* Main entry point of this file. */ /* Main entry point of this file. */
void schedule_insns PROTO((FILE *)); void schedule_insns PROTO((FILE *));
...@@ -3533,39 +3531,6 @@ ret: ...@@ -3533,39 +3531,6 @@ ret:
return; return;
} }
/* Subroutine of split_hard_reg_notes. Searches X for any reference to
REGNO, returning the rtx of the reference found if any. Otherwise,
returns 0. */
static rtx
regno_use_in (regno, x)
int regno;
rtx x;
{
register char *fmt;
int i, j;
rtx tem;
if (GET_CODE (x) == REG && REGNO (x) == regno)
return x;
fmt = GET_RTX_FORMAT (GET_CODE (x));
for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
{
if (fmt[i] == 'e')
{
if ((tem = regno_use_in (regno, XEXP (x, i))))
return tem;
}
else if (fmt[i] == 'E')
for (j = XVECLEN (x, i) - 1; j >= 0; j--)
if ((tem = regno_use_in (regno , XVECEXP (x, i, j))))
return tem;
}
return 0;
}
/* Subroutine of update_flow_info. Determines whether any new REG_NOTEs are /* Subroutine of update_flow_info. Determines whether any new REG_NOTEs are
needed for the hard register mentioned in the note. This can happen needed for the hard register mentioned in the note. This can happen
if the reference to the hard register in the original insn was split into if the reference to the hard register in the original insn was split into
...@@ -3760,7 +3725,7 @@ update_n_sets (x, inc) ...@@ -3760,7 +3725,7 @@ update_n_sets (x, inc)
the insns from FIRST to LAST inclusive that were created by splitting the insns from FIRST to LAST inclusive that were created by splitting
ORIG_INSN. NOTES are the original REG_NOTES. */ ORIG_INSN. NOTES are the original REG_NOTES. */
static void void
update_flow_info (notes, first, last, orig_insn) update_flow_info (notes, first, last, orig_insn)
rtx notes; rtx notes;
rtx first, last; rtx first, last;
...@@ -4366,78 +4331,7 @@ schedule_insns (dump_file) ...@@ -4366,78 +4331,7 @@ schedule_insns (dump_file)
note_list = 0; note_list = 0;
for (insn = BLOCK_HEAD (b); ; insn = next) split_block_insns (b, reload_completed == 0 || ! flag_schedule_insns);
{
rtx prev;
rtx set;
/* Can't use `next_real_insn' because that
might go across CODE_LABELS and short-out basic blocks. */
next = NEXT_INSN (insn);
if (GET_CODE (insn) != INSN)
{
if (insn == BLOCK_END (b))
break;
continue;
}
/* Don't split no-op move insns. These should silently disappear
later in final. Splitting such insns would break the code
that handles REG_NO_CONFLICT blocks. */
set = single_set (insn);
if (set && rtx_equal_p (SET_SRC (set), SET_DEST (set)))
{
if (insn == BLOCK_END (b))
break;
/* Nops get in the way while scheduling, so delete them now if
register allocation has already been done. It is too risky
to try to do this before register allocation, and there are
unlikely to be very many nops then anyways. */
if (reload_completed)
{
PUT_CODE (insn, NOTE);
NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
NOTE_SOURCE_FILE (insn) = 0;
}
continue;
}
/* Split insns here to get max fine-grain parallelism. */
prev = PREV_INSN (insn);
/* It is probably not worthwhile to try to split again in the
second pass. However, if flag_schedule_insns is not set,
the first and only (if any) scheduling pass is after reload. */
if (reload_completed == 0 || ! flag_schedule_insns)
{
rtx last, first = PREV_INSN (insn);
rtx notes = REG_NOTES (insn);
last = try_split (PATTERN (insn), insn, 1);
if (last != insn)
{
/* try_split returns the NOTE that INSN became. */
first = NEXT_INSN (first);
update_flow_info (notes, first, last, insn);
PUT_CODE (insn, NOTE);
NOTE_SOURCE_FILE (insn) = 0;
NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
if (insn == BLOCK_HEAD (b))
BLOCK_HEAD (b) = first;
if (insn == BLOCK_END (b))
{
BLOCK_END (b) = last;
break;
}
}
}
if (insn == BLOCK_END (b))
break;
}
schedule_block (b, dump_file); schedule_block (b, dump_file);
......
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