Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
R
riscv-gcc-1
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
lvzhengyang
riscv-gcc-1
Commits
1708fd40
Commit
1708fd40
authored
Dec 03, 2000
by
Bernd Schmidt
Committed by
Bernd Schmidt
Dec 03, 2000
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Try to separate region-specific code from generic parts in the scheuler.
From-SVN: r37973
parent
881bc7db
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
529 additions
and
322 deletions
+529
-322
gcc/ChangeLog
+27
-0
gcc/Makefile.in
+1
-1
gcc/haifa-sched.c
+429
-321
gcc/sched-int.h
+72
-0
No files found.
gcc/ChangeLog
View file @
1708fd40
2000-12-03 Bernd Schmidt <bernds@redhat.co.uk>
* sched-int.h: New file.
* Makefile.in (haifa-sched.o): Depend on it.
* haifa-sched.c: Include it.
(no_real_insns_p): New function.
(current_sched_info): New static variable.
(__inline, HAIFA_INLINE): Moved to sched-int.h.
(get_block_head_tail): Minor cleanup.
(init_ready_list, can_schedule_ready_p, new_ready, schedule_more_p,
rgn_print_insn, rgn_rank): New functions, broken out of
rank_for_schedule, schedule_insn and schedule_block, where they
are now called through function pointers in current_sched_info.
(queue_insn, schedule_insn, queue_to_ready, debug_ready_list,
print_insn): To display uid and block number, call the print_insn
function pointer in current_schedule_info.
(region_sched_info): New static variable.
(sched_target_n_insns, sched_n_insns, target_n_insns): New global
variables, moved out of schedule_block.
(schedule_block): Return void. All callers changed.
Move some of the setup code into schedule_region. Get head/tail
from current_sched_info, and update it when done.
(schedule_region): Slightly rearranged, some code moved here from
schedule_block. Call no_real_insns_p to avoid doing work for a
block that consists only of notes and labels.
(schedule_insns): Initialize current_sched_info.
2000-12-03 Neil Booth <neilb@earthling.net>
* cppmacro.c (funlike_invocation_p): Re-disable macros enabled
...
...
gcc/Makefile.in
View file @
1708fd40
...
...
@@ -1452,7 +1452,7 @@ alias.o : alias.c $(CONFIG_H) system.h $(RTL_H) flags.h hard-reg-set.h \
regmove.o
:
regmove.c $(CONFIG_H) system.h $(RTL_H) insn-config.h
\
$(RECOG_H) output.h $(REGS_H) hard-reg-set.h flags.h function.h
\
$(EXPR_H) insn-flags.h $(BASIC_BLOCK_H) toplev.h
haifa-sched.o
:
haifa-sched.c $(CONFIG_H) system.h $(RTL_H)
\
haifa-sched.o
:
haifa-sched.c $(CONFIG_H) system.h $(RTL_H)
sched-int.h
\
$(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h flags.h insn-config.h function.h
\
$(INSN_ATTR_H) toplev.h $(RECOG_H) except.h
final.o
:
final.c $(CONFIG_H) system.h $(RTL_H) $(TREE_H) flags.h intl.h
\
...
...
gcc/haifa-sched.c
View file @
1708fd40
...
...
@@ -170,6 +170,7 @@ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "except.h"
#include "toplev.h"
#include "recog.h"
#include "sched-int.h"
extern
char
*
reg_known_equiv_p
;
extern
rtx
*
reg_known_value
;
...
...
@@ -523,7 +524,7 @@ static void swap_sort PARAMS ((rtx *, int));
static
void
queue_insn
PARAMS
((
rtx
,
int
));
static
void
schedule_insn
PARAMS
((
rtx
,
struct
ready_list
*
,
int
));
static
void
find_insn_reg_weight
PARAMS
((
int
));
static
int
schedule_block
PARAMS
((
int
,
int
));
static
void
schedule_block
PARAMS
((
int
,
int
));
static
char
*
safe_concat
PARAMS
((
char
*
,
char
*
,
const
char
*
));
static
int
insn_issue_delay
PARAMS
((
rtx
));
static
void
adjust_priority
PARAMS
((
rtx
));
...
...
@@ -789,6 +790,7 @@ static void rm_redundant_line_notes PARAMS ((void));
static
void
rm_other_notes
PARAMS
((
rtx
,
rtx
));
static
rtx
reemit_notes
PARAMS
((
rtx
,
rtx
));
static
int
no_real_insns_p
PARAMS
((
rtx
,
rtx
));
static
void
get_block_head_tail
PARAMS
((
int
,
rtx
*
,
rtx
*
));
static
void
get_bb_head_tail
PARAMS
((
int
,
rtx
*
,
rtx
*
));
...
...
@@ -829,6 +831,9 @@ static void propagate_deps PARAMS ((int, struct deps *, int));
#endif
/* INSN_SCHEDULING */
/* Point to state used for the current scheduling pass. */
struct
sched_info
*
current_sched_info
;
#define SIZE_FOR_MODE(X) (GET_MODE_SIZE (GET_MODE (X)))
/* Add ELEM wrapped in an INSN_LIST with reg note kind DEP_TYPE to the
...
...
@@ -1137,13 +1142,6 @@ schedule_insns (dump_file)
{
}
#else
#ifndef __GNUC__
#define __inline
#endif
#ifndef HAIFA_INLINE
#define HAIFA_INLINE __inline
#endif
/* Computation of memory dependencies. */
...
...
@@ -4170,7 +4168,7 @@ rank_for_schedule (x, y)
rtx
tmp2
=
*
(
const
rtx
*
)
x
;
rtx
link
;
int
tmp_class
,
tmp2_class
,
depend_count1
,
depend_count2
;
int
val
,
priority_val
,
spec_val
,
prob_val
,
weight
_val
;
int
val
,
priority_val
,
weight_val
,
info
_val
;
/* Prefer insn with higher priority. */
priority_val
=
INSN_PRIORITY
(
tmp2
)
-
INSN_PRIORITY
(
tmp
);
...
...
@@ -4182,24 +4180,9 @@ rank_for_schedule (x, y)
(
weight_val
=
INSN_REG_WEIGHT
(
tmp
)
-
INSN_REG_WEIGHT
(
tmp2
)))
return
(
weight_val
);
/* Some comparison make sense in interblock scheduling only. */
if
(
INSN_BB
(
tmp
)
!=
INSN_BB
(
tmp2
))
{
/* Prefer an inblock motion on an interblock motion. */
if
((
INSN_BB
(
tmp2
)
==
target_bb
)
&&
(
INSN_BB
(
tmp
)
!=
target_bb
))
return
1
;
if
((
INSN_BB
(
tmp
)
==
target_bb
)
&&
(
INSN_BB
(
tmp2
)
!=
target_bb
))
return
-
1
;
/* Prefer a useful motion on a speculative one. */
if
((
spec_val
=
IS_SPECULATIVE_INSN
(
tmp
)
-
IS_SPECULATIVE_INSN
(
tmp2
)))
return
(
spec_val
);
/* Prefer a more probable (speculative) insn. */
prob_val
=
INSN_PROBABILITY
(
tmp2
)
-
INSN_PROBABILITY
(
tmp
);
if
(
prob_val
)
return
(
prob_val
);
}
info_val
=
(
*
current_sched_info
->
rank
)
(
tmp
,
tmp2
);
if
(
info_val
)
return
info_val
;
/* Compare insns based on their relation to the last-scheduled-insn. */
if
(
last_scheduled_insn
)
...
...
@@ -4284,10 +4267,8 @@ queue_insn (insn, n_cycles)
if
(
sched_verbose
>=
2
)
{
fprintf
(
sched_dump
,
";;
\t\t
Ready-->Q: insn %d: "
,
INSN_UID
(
insn
));
if
(
INSN_BB
(
insn
)
!=
target_bb
)
fprintf
(
sched_dump
,
"(b%d) "
,
BLOCK_NUM
(
insn
));
fprintf
(
sched_dump
,
";;
\t\t
Ready-->Q: insn %s: "
,
(
*
current_sched_info
->
print_insn
)
(
insn
,
0
));
fprintf
(
sched_dump
,
"queued for %d cycles.
\n
"
,
n_cycles
);
}
...
...
@@ -4420,24 +4401,13 @@ schedule_insn (insn, ready, clock)
{
int
effective_cost
=
INSN_TICK
(
next
)
-
clock
;
/* For speculative insns, before inserting to ready/queue,
check live, exception-free, and issue-delay. */
if
(
INSN_BB
(
next
)
!=
target_bb
&&
(
!
IS_VALID
(
INSN_BB
(
next
))
||
CANT_MOVE
(
next
)
||
(
IS_SPECULATIVE_INSN
(
next
)
&&
(
insn_issue_delay
(
next
)
>
3
||
!
check_live
(
next
,
INSN_BB
(
next
))
||
!
is_exception_free
(
next
,
INSN_BB
(
next
),
target_bb
)))))
if
(
!
(
*
current_sched_info
->
new_ready
)
(
next
))
continue
;
if
(
sched_verbose
>=
2
)
{
fprintf
(
sched_dump
,
";;
\t\t
dependences resolved: insn %d "
,
INSN_UID
(
next
));
if
(
current_nr_blocks
>
1
&&
INSN_BB
(
next
)
!=
target_bb
)
fprintf
(
sched_dump
,
"/b%d "
,
BLOCK_NUM
(
next
));
fprintf
(
sched_dump
,
";;
\t\t
dependences resolved: insn %s "
,
(
*
current_sched_info
->
print_insn
)
(
next
,
0
));
if
(
effective_cost
<
1
)
fprintf
(
sched_dump
,
"into ready
\n
"
);
...
...
@@ -4549,13 +4519,9 @@ get_block_head_tail (b, headp, tailp)
rtx
*
headp
;
rtx
*
tailp
;
{
rtx
head
;
rtx
tail
;
/* HEAD and TAIL delimit the basic block being scheduled. */
head
=
BLOCK_HEAD
(
b
);
tail
=
BLOCK_END
(
b
);
rtx
head
=
BLOCK_HEAD
(
b
);
rtx
tail
=
BLOCK_END
(
b
);
/* Don't include any notes or labels at the beginning of the
basic block, or notes at the ends of basic blocks. */
...
...
@@ -4584,6 +4550,21 @@ get_bb_head_tail (bb, headp, tailp)
get_block_head_tail
(
BB_TO_BLOCK
(
bb
),
headp
,
tailp
);
}
/* Return nonzero if there are no real insns in the range [ HEAD, TAIL ]. */
static
int
no_real_insns_p
(
head
,
tail
)
rtx
head
,
tail
;
{
while
(
head
!=
NEXT_INSN
(
tail
))
{
if
(
GET_CODE
(
head
)
!=
NOTE
&&
GET_CODE
(
head
)
!=
CODE_LABEL
)
return
0
;
head
=
NEXT_INSN
(
head
);
}
return
1
;
}
/* Delete line notes from bb. Save them so they can be later restored
(in restore_line_notes ()). */
...
...
@@ -4878,10 +4859,8 @@ queue_to_ready (ready)
q_size
-=
1
;
if
(
sched_verbose
>=
2
)
fprintf
(
sched_dump
,
";;
\t\t
Q-->Ready: insn %d: "
,
INSN_UID
(
insn
));
if
(
sched_verbose
>=
2
&&
INSN_BB
(
insn
)
!=
target_bb
)
fprintf
(
sched_dump
,
"(b%d) "
,
BLOCK_NUM
(
insn
));
fprintf
(
sched_dump
,
";;
\t\t
Q-->Ready: insn %s: "
,
(
*
current_sched_info
->
print_insn
)
(
insn
,
0
));
ready_add
(
ready
,
insn
);
if
(
sched_verbose
>=
2
)
...
...
@@ -4905,11 +4884,8 @@ queue_to_ready (ready)
q_size
-=
1
;
if
(
sched_verbose
>=
2
)
fprintf
(
sched_dump
,
";;
\t\t
Q-->Ready: insn %d: "
,
INSN_UID
(
insn
));
if
(
sched_verbose
>=
2
&&
INSN_BB
(
insn
)
!=
target_bb
)
fprintf
(
sched_dump
,
"(b%d) "
,
BLOCK_NUM
(
insn
));
fprintf
(
sched_dump
,
";;
\t\t
Q-->Ready: insn %s: "
,
(
*
current_sched_info
->
print_insn
)
(
insn
,
0
));
ready_add
(
ready
,
insn
);
if
(
sched_verbose
>=
2
)
...
...
@@ -4943,11 +4919,7 @@ debug_ready_list (ready)
p
=
ready_lastpos
(
ready
);
for
(
i
=
0
;
i
<
ready
->
n_ready
;
i
++
)
{
fprintf
(
sched_dump
,
" %d"
,
INSN_UID
(
p
[
i
]));
if
(
current_nr_blocks
>
1
&&
INSN_BB
(
p
[
i
])
!=
target_bb
)
fprintf
(
sched_dump
,
"/b%d"
,
BLOCK_NUM
(
p
[
i
]));
}
fprintf
(
sched_dump
,
" %s"
,
(
*
current_sched_info
->
print_insn
)
(
p
[
i
],
0
));
fprintf
(
sched_dump
,
"
\n
"
);
}
...
...
@@ -5655,16 +5627,16 @@ print_insn (buf, x, verbose)
case
INSN
:
print_pattern
(
t
,
PATTERN
(
x
),
verbose
);
if
(
verbose
)
sprintf
(
buf
,
"
b%d: i% 4d: %s"
,
INSN_BB
(
x
),
INSN_UID
(
x
),
t
);
sprintf
(
buf
,
"
%s: %s"
,
(
*
current_sched_info
->
print_insn
)
(
x
,
1
),
t
);
else
sprintf
(
buf
,
"%-4d %s"
,
INSN_UID
(
x
),
t
);
break
;
case
JUMP_INSN
:
print_pattern
(
t
,
PATTERN
(
x
),
verbose
);
if
(
verbose
)
sprintf
(
buf
,
"
b%d: i% 4d: jump %s"
,
INSN_BB
(
x
),
INSN_UID
(
x
),
t
);
sprintf
(
buf
,
"
%s: jump %s"
,
(
*
current_sched_info
->
print_insn
)
(
x
,
1
),
t
);
else
sprintf
(
buf
,
"%-4d %s"
,
INSN_UID
(
x
),
t
);
break
;
...
...
@@ -5678,8 +5650,7 @@ print_insn (buf, x, verbose)
else
strcpy
(
t
,
"call <...>"
);
if
(
verbose
)
sprintf
(
buf
,
"b%d: i% 4d: %s"
,
INSN_BB
(
insn
),
INSN_UID
(
insn
),
t
);
sprintf
(
buf
,
"%s: %s"
,
(
*
current_sched_info
->
print_insn
)
(
x
,
1
),
t
);
else
sprintf
(
buf
,
"%-4d %s"
,
INSN_UID
(
insn
),
t
);
break
;
...
...
@@ -5819,6 +5790,292 @@ visualize_stall_cycles (b, stalls)
sprintf
(
visual_tbl
+
strlen
(
visual_tbl
),
"
\n
"
);
}
/* The number of insns from the current block scheduled so far. */
static
int
sched_target_n_insns
;
/* The number of insns from the current block to be scheduled in total. */
static
int
target_n_insns
;
/* The number of insns from the entire region scheduled so far. */
static
int
sched_n_insns
;
/* Implementations of the sched_info functions for region scheduling. */
static
void
init_ready_list
PARAMS
((
struct
ready_list
*
));
static
int
can_schedule_ready_p
PARAMS
((
rtx
));
static
int
new_ready
PARAMS
((
rtx
));
static
int
schedule_more_p
PARAMS
((
void
));
static
const
char
*
rgn_print_insn
PARAMS
((
rtx
,
int
));
static
int
rgn_rank
PARAMS
((
rtx
,
rtx
));
/* Return nonzero if there are more insns that should be scheduled. */
static
int
schedule_more_p
()
{
return
sched_target_n_insns
<
target_n_insns
;
}
/* Add all insns that are initially ready to the ready list READY. Called
once before scheduling a set of insns. */
static
void
init_ready_list
(
ready
)
struct
ready_list
*
ready
;
{
rtx
prev_head
=
current_sched_info
->
prev_head
;
rtx
next_tail
=
current_sched_info
->
next_tail
;
int
bb_src
;
rtx
insn
;
target_n_insns
=
0
;
sched_target_n_insns
=
0
;
sched_n_insns
=
0
;
/* Print debugging information. */
if
(
sched_verbose
>=
5
)
debug_dependencies
();
/* Prepare current target block info. */
if
(
current_nr_blocks
>
1
)
{
candidate_table
=
(
candidate
*
)
xmalloc
(
current_nr_blocks
*
sizeof
(
candidate
));
bblst_last
=
0
;
/* bblst_table holds split blocks and update blocks for each block after
the current one in the region. split blocks and update blocks are
the TO blocks of region edges, so there can be at most rgn_nr_edges
of them. */
bblst_size
=
(
current_nr_blocks
-
target_bb
)
*
rgn_nr_edges
;
bblst_table
=
(
int
*
)
xmalloc
(
bblst_size
*
sizeof
(
int
));
bitlst_table_last
=
0
;
bitlst_table_size
=
rgn_nr_edges
;
bitlst_table
=
(
int
*
)
xmalloc
(
rgn_nr_edges
*
sizeof
(
int
));
compute_trg_info
(
target_bb
);
}
/* Initialize ready list with all 'ready' insns in target block.
Count number of insns in the target block being scheduled. */
for
(
insn
=
NEXT_INSN
(
prev_head
);
insn
!=
next_tail
;
insn
=
NEXT_INSN
(
insn
))
{
rtx
next
;
if
(
!
INSN_P
(
insn
))
continue
;
next
=
NEXT_INSN
(
insn
);
if
(
INSN_DEP_COUNT
(
insn
)
==
0
&&
(
SCHED_GROUP_P
(
next
)
==
0
||
!
INSN_P
(
next
)))
ready_add
(
ready
,
insn
);
if
(
!
(
SCHED_GROUP_P
(
insn
)))
target_n_insns
++
;
}
/* Add to ready list all 'ready' insns in valid source blocks.
For speculative insns, check-live, exception-free, and
issue-delay. */
for
(
bb_src
=
target_bb
+
1
;
bb_src
<
current_nr_blocks
;
bb_src
++
)
if
(
IS_VALID
(
bb_src
))
{
rtx
src_head
;
rtx
src_next_tail
;
rtx
tail
,
head
;
get_bb_head_tail
(
bb_src
,
&
head
,
&
tail
);
src_next_tail
=
NEXT_INSN
(
tail
);
src_head
=
head
;
for
(
insn
=
src_head
;
insn
!=
src_next_tail
;
insn
=
NEXT_INSN
(
insn
))
{
if
(
!
INSN_P
(
insn
))
continue
;
if
(
!
CANT_MOVE
(
insn
)
&&
(
!
IS_SPECULATIVE_INSN
(
insn
)
||
(
insn_issue_delay
(
insn
)
<=
3
&&
check_live
(
insn
,
bb_src
)
&&
is_exception_free
(
insn
,
bb_src
,
target_bb
))))
{
rtx
next
;
/* Note that we havn't squirrled away the notes for
blocks other than the current. So if this is a
speculative insn, NEXT might otherwise be a note. */
next
=
next_nonnote_insn
(
insn
);
if
(
INSN_DEP_COUNT
(
insn
)
==
0
&&
(
!
next
||
SCHED_GROUP_P
(
next
)
==
0
||
!
INSN_P
(
next
)))
ready_add
(
ready
,
insn
);
}
}
}
}
/* Called after taking INSN from the ready list. Returns nonzero if this
insn can be scheduled, nonzero if we should silently discard it. */
static
int
can_schedule_ready_p
(
insn
)
rtx
insn
;
{
/* An interblock motion? */
if
(
INSN_BB
(
insn
)
!=
target_bb
)
{
rtx
temp
;
basic_block
b1
;
if
(
IS_SPECULATIVE_INSN
(
insn
))
{
if
(
!
check_live
(
insn
,
INSN_BB
(
insn
)))
return
0
;
update_live
(
insn
,
INSN_BB
(
insn
));
/* For speculative load, mark insns fed by it. */
if
(
IS_LOAD_INSN
(
insn
)
||
FED_BY_SPEC_LOAD
(
insn
))
set_spec_fed
(
insn
);
nr_spec
++
;
}
nr_inter
++
;
/* Find the beginning of the scheduling group. */
/* ??? Ought to update basic block here, but later bits of
schedule_block assumes the original insn block is
still intact. */
temp
=
insn
;
while
(
SCHED_GROUP_P
(
temp
))
temp
=
PREV_INSN
(
temp
);
/* Update source block boundaries. */
b1
=
BLOCK_FOR_INSN
(
temp
);
if
(
temp
==
b1
->
head
&&
insn
==
b1
->
end
)
{
/* We moved all the insns in the basic block.
Emit a note after the last insn and update the
begin/end boundaries to point to the note. */
rtx
note
=
emit_note_after
(
NOTE_INSN_DELETED
,
insn
);
b1
->
head
=
note
;
b1
->
end
=
note
;
}
else
if
(
insn
==
b1
->
end
)
{
/* We took insns from the end of the basic block,
so update the end of block boundary so that it
points to the first insn we did not move. */
b1
->
end
=
PREV_INSN
(
temp
);
}
else
if
(
temp
==
b1
->
head
)
{
/* We took insns from the start of the basic block,
so update the start of block boundary so that
it points to the first insn we did not move. */
b1
->
head
=
NEXT_INSN
(
insn
);
}
}
else
{
/* In block motion. */
sched_target_n_insns
++
;
}
sched_n_insns
++
;
return
1
;
}
/* Called after INSN has all its dependencies resolved. Return nonzero
if it should be moved to the ready list or the queue, or zero if we
should silently discard it. */
static
int
new_ready
(
next
)
rtx
next
;
{
/* For speculative insns, before inserting to ready/queue,
check live, exception-free, and issue-delay. */
if
(
INSN_BB
(
next
)
!=
target_bb
&&
(
!
IS_VALID
(
INSN_BB
(
next
))
||
CANT_MOVE
(
next
)
||
(
IS_SPECULATIVE_INSN
(
next
)
&&
(
insn_issue_delay
(
next
)
>
3
||
!
check_live
(
next
,
INSN_BB
(
next
))
||
!
is_exception_free
(
next
,
INSN_BB
(
next
),
target_bb
)))))
return
0
;
return
1
;
}
/* Return a string that contains the insn uid and optionally anything else
necessary to identify this insn in an output. It's valid to use a
static buffer for this. The ALIGNED parameter should cause the string
to be formatted so that multiple output lines will line up nicely. */
static
const
char
*
rgn_print_insn
(
insn
,
aligned
)
rtx
insn
;
int
aligned
;
{
static
char
tmp
[
80
];
if
(
aligned
)
sprintf
(
tmp
,
"b%3d: i%4d"
,
INSN_BB
(
insn
),
INSN_UID
(
insn
));
else
{
sprintf
(
tmp
,
"%d"
,
INSN_UID
(
insn
));
if
(
current_nr_blocks
>
1
&&
INSN_BB
(
insn
)
!=
target_bb
)
sprintf
(
tmp
,
"/b%d "
,
INSN_BB
(
insn
));
}
return
tmp
;
}
/* Compare priority of two insns. Return a positive number if the second
insn is to be preferred for scheduling, and a negative one if the first
is to be preferred. Zero if they are equally good. */
static
int
rgn_rank
(
insn1
,
insn2
)
rtx
insn1
,
insn2
;
{
/* Some comparison make sense in interblock scheduling only. */
if
(
INSN_BB
(
insn1
)
!=
INSN_BB
(
insn2
))
{
int
spec_val
,
prob_val
;
/* Prefer an inblock motion on an interblock motion. */
if
((
INSN_BB
(
insn2
)
==
target_bb
)
&&
(
INSN_BB
(
insn1
)
!=
target_bb
))
return
1
;
if
((
INSN_BB
(
insn1
)
==
target_bb
)
&&
(
INSN_BB
(
insn2
)
!=
target_bb
))
return
-
1
;
/* Prefer a useful motion on a speculative one. */
spec_val
=
IS_SPECULATIVE_INSN
(
insn1
)
-
IS_SPECULATIVE_INSN
(
insn2
);
if
(
spec_val
)
return
spec_val
;
/* Prefer a more probable (speculative) insn. */
prob_val
=
INSN_PROBABILITY
(
insn2
)
-
INSN_PROBABILITY
(
insn1
);
if
(
prob_val
)
return
prob_val
;
}
return
0
;
}
/* Used in schedule_insns to initialize current_sched_info for scheduling
regions (or single basic blocks). */
static
struct
sched_info
region_sched_info
=
{
init_ready_list
,
can_schedule_ready_p
,
schedule_more_p
,
new_ready
,
rgn_rank
,
rgn_print_insn
,
NULL
,
NULL
,
NULL
,
NULL
,
0
};
/* move_insn1: Remove INSN from insn chain, and link it after LAST insn. */
static
rtx
...
...
@@ -5950,40 +6207,25 @@ group_leader (insn)
}
/* Use forward list scheduling to rearrange insns of block BB in region RGN,
possibly bringing insns from subsequent blocks in the same region.
Return number of insns scheduled. */
possibly bringing insns from subsequent blocks in the same region. */
static
int
static
void
schedule_block
(
bb
,
rgn_n_insns
)
int
bb
;
int
rgn_n_insns
;
{
/* Local variables. */
rtx
insn
,
last
;
rtx
last
;
struct
ready_list
ready
;
int
can_issue_more
;
/* Flow block of this bb. */
int
b
=
BB_TO_BLOCK
(
bb
);
/* target_n_insns == number of insns in b before scheduling starts.
sched_target_n_insns == how many of b's insns were scheduled.
sched_n_insns == how many insns were scheduled in b. */
int
target_n_insns
=
0
;
int
sched_target_n_insns
=
0
;
int
sched_n_insns
=
0
;
#define NEED_NOTHING 0
#define NEED_HEAD 1
#define NEED_TAIL 2
int
new_needs
;
/* Head/tail info for this block. */
rtx
prev_head
;
rtx
next_tail
;
rtx
head
;
rtx
tail
;
int
bb_src
;
rtx
prev_head
=
current_sched_info
->
prev_head
;
rtx
next_tail
=
current_sched_info
->
next_tail
;
rtx
head
=
NEXT_INSN
(
prev_head
);
rtx
tail
=
PREV_INSN
(
next_tail
);
/* We used to have code to avoid getting parameters moved from hard
argument registers into pseudos.
...
...
@@ -5991,42 +6233,9 @@ schedule_block (bb, rgn_n_insns)
However, it was removed when it proved to be of marginal benefit
and caused problems because schedule_block and compute_forward_dependences
had different notions of what the "head" insn was. */
get_bb_head_tail
(
bb
,
&
head
,
&
tail
);
/* rm_other_notes only removes notes which are _inside_ the
block---that is, it won't remove notes before the first real insn
or after the last real insn of the block. So if the first insn
has a REG_SAVE_NOTE which would otherwise be emitted before the
insn, it is redundant with the note before the start of the
block, and so we have to take it out.
FIXME: Probably the same thing should be done with REG_SAVE_NOTEs
referencing NOTE_INSN_SETJMP at the end of the block. */
if
(
INSN_P
(
head
))
{
rtx
note
;
for
(
note
=
REG_NOTES
(
head
);
note
;
note
=
XEXP
(
note
,
1
))
if
(
REG_NOTE_KIND
(
note
)
==
REG_SAVE_NOTE
)
{
if
(
INTVAL
(
XEXP
(
note
,
0
))
!=
NOTE_INSN_SETJMP
)
{
remove_note
(
head
,
note
);
note
=
XEXP
(
note
,
1
);
remove_note
(
head
,
note
);
}
else
note
=
XEXP
(
note
,
1
);
}
}
next_tail
=
NEXT_INSN
(
tail
);
prev_head
=
PREV_INSN
(
head
);
/* If the only insn left is a NOTE or a CODE_LABEL, then there is no need
to schedule this block. */
if
(
head
==
tail
&&
(
!
INSN_P
(
head
)))
return
(
sched_n_insns
);
abort
(
);
/* Debug info. */
if
(
sched_verbose
)
...
...
@@ -6043,35 +6252,6 @@ schedule_block (bb, rgn_n_insns)
init_block_visualization
();
}
/* Remove remaining note insns from the block, save them in
note_list. These notes are restored at the end of
schedule_block (). */
note_list
=
0
;
rm_other_notes
(
head
,
tail
);
target_bb
=
bb
;
/* Prepare current target block info. */
if
(
current_nr_blocks
>
1
)
{
candidate_table
=
(
candidate
*
)
xmalloc
(
current_nr_blocks
*
sizeof
(
candidate
));
bblst_last
=
0
;
/* bblst_table holds split blocks and update blocks for each block after
the current one in the region. split blocks and update blocks are
the TO blocks of region edges, so there can be at most rgn_nr_edges
of them. */
bblst_size
=
(
current_nr_blocks
-
bb
)
*
rgn_nr_edges
;
bblst_table
=
(
int
*
)
xmalloc
(
bblst_size
*
sizeof
(
int
));
bitlst_table_last
=
0
;
bitlst_table_size
=
rgn_nr_edges
;
bitlst_table
=
(
int
*
)
xmalloc
(
rgn_nr_edges
*
sizeof
(
int
));
compute_trg_info
(
bb
);
}
clear_units
();
/* Allocate the ready list. */
...
...
@@ -6080,69 +6260,7 @@ schedule_block (bb, rgn_n_insns)
ready
.
vec
=
(
rtx
*
)
xmalloc
(
ready
.
veclen
*
sizeof
(
rtx
));
ready
.
n_ready
=
0
;
/* Print debugging information. */
if
(
sched_verbose
>=
5
)
debug_dependencies
();
/* Initialize ready list with all 'ready' insns in target block.
Count number of insns in the target block being scheduled. */
for
(
insn
=
head
;
insn
!=
next_tail
;
insn
=
NEXT_INSN
(
insn
))
{
rtx
next
;
if
(
!
INSN_P
(
insn
))
continue
;
next
=
NEXT_INSN
(
insn
);
if
(
INSN_DEP_COUNT
(
insn
)
==
0
&&
(
SCHED_GROUP_P
(
next
)
==
0
||
!
INSN_P
(
next
)))
ready_add
(
&
ready
,
insn
);
if
(
!
(
SCHED_GROUP_P
(
insn
)))
target_n_insns
++
;
}
/* Add to ready list all 'ready' insns in valid source blocks.
For speculative insns, check-live, exception-free, and
issue-delay. */
for
(
bb_src
=
bb
+
1
;
bb_src
<
current_nr_blocks
;
bb_src
++
)
if
(
IS_VALID
(
bb_src
))
{
rtx
src_head
;
rtx
src_next_tail
;
rtx
tail
,
head
;
get_bb_head_tail
(
bb_src
,
&
head
,
&
tail
);
src_next_tail
=
NEXT_INSN
(
tail
);
src_head
=
head
;
if
(
head
==
tail
&&
(
!
INSN_P
(
head
)))
continue
;
for
(
insn
=
src_head
;
insn
!=
src_next_tail
;
insn
=
NEXT_INSN
(
insn
))
{
if
(
!
INSN_P
(
insn
))
continue
;
if
(
!
CANT_MOVE
(
insn
)
&&
(
!
IS_SPECULATIVE_INSN
(
insn
)
||
(
insn_issue_delay
(
insn
)
<=
3
&&
check_live
(
insn
,
bb_src
)
&&
is_exception_free
(
insn
,
bb_src
,
target_bb
))))
{
rtx
next
;
/* Note that we havn't squirrled away the notes for
blocks other than the current. So if this is a
speculative insn, NEXT might otherwise be a note. */
next
=
next_nonnote_insn
(
insn
);
if
(
INSN_DEP_COUNT
(
insn
)
==
0
&&
(
!
next
||
SCHED_GROUP_P
(
next
)
==
0
||
!
INSN_P
(
next
)))
ready_add
(
&
ready
,
insn
);
}
}
}
(
*
current_sched_info
->
init_ready_list
)
(
&
ready
);
#ifdef MD_SCHED_INIT
MD_SCHED_INIT
(
sched_dump
,
sched_verbose
);
...
...
@@ -6151,7 +6269,8 @@ schedule_block (bb, rgn_n_insns)
/* No insns scheduled in this block yet. */
last_scheduled_insn
=
0
;
/* Q_SIZE is the total number of insns in the queue. */
/* Initialize INSN_QUEUE. Q_SIZE is the total number of insns in the
queue. */
q_ptr
=
0
;
q_size
=
0
;
last_clock_var
=
0
;
...
...
@@ -6163,14 +6282,8 @@ schedule_block (bb, rgn_n_insns)
/* We start inserting insns after PREV_HEAD. */
last
=
prev_head
;
/* Initialize INSN_QUEUE, LIST and NEW_NEEDS. */
new_needs
=
(
NEXT_INSN
(
prev_head
)
==
BLOCK_HEAD
(
b
)
?
NEED_HEAD
:
NEED_NOTHING
);
if
(
PREV_INSN
(
next_tail
)
==
BLOCK_END
(
b
))
new_needs
|=
NEED_TAIL
;
/* Loop until all the insns in BB are scheduled. */
while
(
sched_target_n_insns
<
target_n_insns
)
while
(
(
*
current_sched_info
->
schedule_more_p
)
()
)
{
clock_var
++
;
...
...
@@ -6220,70 +6333,11 @@ schedule_block (bb, rgn_n_insns)
continue
;
}
/* An interblock motion? */
if
(
INSN_BB
(
insn
)
!=
target_bb
)
{
rtx
temp
;
basic_block
b1
;
if
(
IS_SPECULATIVE_INSN
(
insn
))
{
if
(
!
check_live
(
insn
,
INSN_BB
(
insn
)))
continue
;
update_live
(
insn
,
INSN_BB
(
insn
));
/* For speculative load, mark insns fed by it. */
if
(
IS_LOAD_INSN
(
insn
)
||
FED_BY_SPEC_LOAD
(
insn
))
set_spec_fed
(
insn
);
nr_spec
++
;
}
nr_inter
++
;
/* Find the beginning of the scheduling group. */
/* ??? Ought to update basic block here, but later bits of
schedule_block assumes the original insn block is
still intact. */
temp
=
insn
;
while
(
SCHED_GROUP_P
(
temp
))
temp
=
PREV_INSN
(
temp
);
/* Update source block boundaries. */
b1
=
BLOCK_FOR_INSN
(
temp
);
if
(
temp
==
b1
->
head
&&
insn
==
b1
->
end
)
{
/* We moved all the insns in the basic block.
Emit a note after the last insn and update the
begin/end boundaries to point to the note. */
rtx
note
=
emit_note_after
(
NOTE_INSN_DELETED
,
insn
);
b1
->
head
=
note
;
b1
->
end
=
note
;
}
else
if
(
insn
==
b1
->
end
)
{
/* We took insns from the end of the basic block,
so update the end of block boundary so that it
points to the first insn we did not move. */
b1
->
end
=
PREV_INSN
(
temp
);
}
else
if
(
temp
==
b1
->
head
)
{
/* We took insns from the start of the basic block,
so update the start of block boundary so that
it points to the first insn we did not move. */
b1
->
head
=
NEXT_INSN
(
insn
);
}
}
else
{
/* In block motion. */
sched_target_n_insns
++
;
}
if
(
!
(
*
current_sched_info
->
can_schedule_ready_p
)
(
insn
))
goto
next
;
last_scheduled_insn
=
insn
;
last
=
move_insn
(
insn
,
last
);
sched_n_insns
++
;
#ifdef MD_SCHED_VARIABLE_ISSUE
MD_SCHED_VARIABLE_ISSUE
(
sched_dump
,
sched_verbose
,
insn
,
...
...
@@ -6294,6 +6348,7 @@ schedule_block (bb, rgn_n_insns)
schedule_insn
(
insn
,
&
ready
,
clock_var
);
next
:
/* Close this block after scheduling its jump. */
if
(
GET_CODE
(
last_scheduled_insn
)
==
JUMP_INSN
)
break
;
...
...
@@ -6314,8 +6369,7 @@ schedule_block (bb, rgn_n_insns)
/* Sanity check -- queue must be empty now. Meaningless if region has
multiple bbs. */
if
(
current_nr_blocks
>
1
)
if
(
!
flag_schedule_interblock
&&
q_size
!=
0
)
if
(
current_sched_info
->
queue_must_finish_empty
&&
q_size
!=
0
)
abort
();
/* Update head/tail boundaries. */
...
...
@@ -6341,32 +6395,21 @@ schedule_block (bb, rgn_n_insns)
head
=
note_head
;
}
/* Update target block boundaries. */
if
(
new_needs
&
NEED_HEAD
)
BLOCK_HEAD
(
b
)
=
head
;
if
(
new_needs
&
NEED_TAIL
)
BLOCK_END
(
b
)
=
tail
;
/* Debugging. */
if
(
sched_verbose
)
{
fprintf
(
sched_dump
,
";; total time = %d
\n
;; new
basic block
head = %d
\n
"
,
clock_var
,
INSN_UID
(
BLOCK_HEAD
(
b
)
));
fprintf
(
sched_dump
,
";; new
basic block end
= %d
\n\n
"
,
INSN_UID
(
BLOCK_END
(
b
)
));
fprintf
(
sched_dump
,
";; total time = %d
\n
;; new head = %d
\n
"
,
clock_var
,
INSN_UID
(
head
));
fprintf
(
sched_dump
,
";; new
tail
= %d
\n\n
"
,
INSN_UID
(
tail
));
}
/* Clean up. */
if
(
current_nr_blocks
>
1
)
{
free
(
candidate_table
);
free
(
bblst_table
);
free
(
bitlst_table
);
}
current_sched_info
->
head
=
head
;
current_sched_info
->
tail
=
tail
;
free
(
ready
.
vec
);
return
(
sched_n_insns
)
;
return
1
;
}
/* Print the bit-set of registers, S, callable from debugger. */
...
...
@@ -6869,7 +6912,6 @@ set_priorities (bb)
n_insn
=
0
;
for
(
insn
=
tail
;
insn
!=
prev_head
;
insn
=
PREV_INSN
(
insn
))
{
if
(
GET_CODE
(
insn
)
==
NOTE
)
continue
;
...
...
@@ -6921,17 +6963,9 @@ schedule_region (rgn)
compute_forward_dependences
(
head
,
tail
);
}
/*
Delete line notes and s
et priorities. */
/*
S
et priorities. */
for
(
bb
=
0
;
bb
<
current_nr_blocks
;
bb
++
)
{
if
(
write_symbols
!=
NO_DEBUG
)
{
save_line_notes
(
bb
);
rm_line_notes
(
bb
);
}
rgn_n_insns
+=
set_priorities
(
bb
);
}
rgn_n_insns
+=
set_priorities
(
bb
);
/* Compute interblock info: probabilities, split-edges, dominators, etc. */
if
(
current_nr_blocks
>
1
)
...
...
@@ -6979,7 +7013,79 @@ schedule_region (rgn)
/* Now we can schedule all blocks. */
for
(
bb
=
0
;
bb
<
current_nr_blocks
;
bb
++
)
sched_rgn_n_insns
+=
schedule_block
(
bb
,
rgn_n_insns
);
{
rtx
head
,
tail
;
int
b
=
BB_TO_BLOCK
(
bb
);
get_block_head_tail
(
b
,
&
head
,
&
tail
);
if
(
no_real_insns_p
(
head
,
tail
))
continue
;
current_sched_info
->
prev_head
=
PREV_INSN
(
head
);
current_sched_info
->
next_tail
=
NEXT_INSN
(
tail
);
if
(
write_symbols
!=
NO_DEBUG
)
{
save_line_notes
(
bb
);
rm_line_notes
(
bb
);
}
/* rm_other_notes only removes notes which are _inside_ the
block---that is, it won't remove notes before the first real insn
or after the last real insn of the block. So if the first insn
has a REG_SAVE_NOTE which would otherwise be emitted before the
insn, it is redundant with the note before the start of the
block, and so we have to take it out.
FIXME: Probably the same thing should be done with REG_SAVE_NOTEs
referencing NOTE_INSN_SETJMP at the end of the block. */
if
(
INSN_P
(
head
))
{
rtx
note
;
for
(
note
=
REG_NOTES
(
head
);
note
;
note
=
XEXP
(
note
,
1
))
if
(
REG_NOTE_KIND
(
note
)
==
REG_SAVE_NOTE
)
{
if
(
INTVAL
(
XEXP
(
note
,
0
))
!=
NOTE_INSN_SETJMP
)
{
remove_note
(
head
,
note
);
note
=
XEXP
(
note
,
1
);
remove_note
(
head
,
note
);
}
else
note
=
XEXP
(
note
,
1
);
}
}
/* Remove remaining note insns from the block, save them in
note_list. These notes are restored at the end of
schedule_block (). */
note_list
=
0
;
rm_other_notes
(
head
,
tail
);
target_bb
=
bb
;
current_sched_info
->
queue_must_finish_empty
=
current_nr_blocks
>
1
&&
!
flag_schedule_interblock
;
schedule_block
(
bb
,
rgn_n_insns
);
sched_rgn_n_insns
+=
sched_n_insns
;
/* Update target block boundaries. */
if
(
head
==
BLOCK_HEAD
(
b
))
BLOCK_HEAD
(
b
)
=
current_sched_info
->
head
;
if
(
tail
==
BLOCK_END
(
b
))
BLOCK_END
(
b
)
=
current_sched_info
->
tail
;
/* Clean up. */
if
(
current_nr_blocks
>
1
)
{
free
(
candidate_table
);
free
(
bblst_table
);
free
(
bitlst_table
);
}
}
/* Sanity check: verify that all region insns were scheduled. */
if
(
sched_rgn_n_insns
!=
rgn_n_insns
)
...
...
@@ -7240,6 +7346,8 @@ schedule_insns (dump_file)
init_regions
();
current_sched_info
=
&
region_sched_info
;
/* Schedule every region in the subroutine. */
for
(
rgn
=
0
;
rgn
<
nr_regions
;
rgn
++
)
schedule_region
(
rgn
);
...
...
gcc/sched-int.h
0 → 100644
View file @
1708fd40
/* Instruction scheduling pass. This file contains definitions used
internally in the scheduler.
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998,
1999, 2000 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
the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA. */
/* Forward declaration. */
struct
ready_list
;
/* This structure holds some state of the current scheduling pass, and
contains some function pointers that abstract out some of the non-generic
functionality from functions such as schedule_block or schedule_insn.
There is one global variable, current_sched_info, which points to the
sched_info structure currently in use. */
struct
sched_info
{
/* Add all insns that are initially ready to the ready list. Called once
before scheduling a set of insns. */
void
(
*
init_ready_list
)
PARAMS
((
struct
ready_list
*
));
/* Called after taking an insn from the ready list. Returns nonzero if
this insn can be scheduled, nonzero if we should silently discard it. */
int
(
*
can_schedule_ready_p
)
PARAMS
((
rtx
));
/* Return nonzero if there are more insns that should be scheduled. */
int
(
*
schedule_more_p
)
PARAMS
((
void
));
/* Called after an insn has all its dependencies resolved. Return nonzero
if it should be moved to the ready list or the queue, or zero if we
should silently discard it. */
int
(
*
new_ready
)
PARAMS
((
rtx
));
/* Compare priority of two insns. Return a positive number if the second
insn is to be preferred for scheduling, and a negative one if the first
is to be preferred. Zero if they are equally good. */
int
(
*
rank
)
PARAMS
((
rtx
,
rtx
));
/* Return a string that contains the insn uid and optionally anything else
necessary to identify this insn in an output. It's valid to use a
static buffer for this. The ALIGNED parameter should cause the string
to be formatted so that multiple output lines will line up nicely. */
const
char
*
(
*
print_insn
)
PARAMS
((
rtx
,
int
));
/* The boundaries of the set of insns to be scheduled. */
rtx
prev_head
,
next_tail
;
/* Filled in after the schedule is finished; the first and last scheduled
insns. */
rtx
head
,
tail
;
/* If nonzero, enables an additional sanity check in schedule_block. */
int
queue_must_finish_empty
;
};
#ifndef __GNUC__
#define __inline
#endif
#ifndef HAIFA_INLINE
#define HAIFA_INLINE __inline
#endif
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment