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
c62c2659
Commit
c62c2659
authored
Dec 03, 2000
by
Bernd Schmidt
Committed by
Bernd Schmidt
Dec 03, 2000
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Move scheduling visualization code to separate file.
From-SVN: r37974
parent
1708fd40
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
970 additions
and
901 deletions
+970
-901
gcc/ChangeLog
+21
-0
gcc/Makefile.in
+3
-1
gcc/haifa-sched.c
+17
-900
gcc/sched-vis.c
+929
-0
No files found.
gcc/ChangeLog
View file @
c62c2659
2000-12-03 Bernd Schmidt <bernds@redhat.co.uk>
* Makefile.in (OBJS): Add sched-vis.o.
(sched-vis.o): New rule.
* haifa-sched.c (get_unit_last_insn): New function.
(sched_dump, insn_unit, actual_hazard_this_instance): No longer
static.
(schedule_block): Call visualize_alloc and visualize_free. Delete
spurious return statement.
(init_target_units, insn_print_units, get_visual_tbl_length,
init_block_visualization, print_block_visualization, safe_concat,
visualize_scheduled_inns, visualize_no_unit, visualize_stall_cycles,
print_exp, print_value, print_pattern, print_insn, target_units,
MAX_VISUAL_LINES, INSN_LEN, n_visual_lines, visual_tbl,
n_vis_no_unit, vis_no_unit): Move scheduling visualization
functions/variables...
* sched-vis.c: ...here. New file.
(visualize_alloc, visualize_free): New functions.
(visualize_scheduled_insns, visualize_stall_cycles,
print_block_visualization): Lose basic block argument. All callers
changed.
(visualize_scheduled_insns): Use new function get_unit_last_insn.
* sched-int.h: New file.
* Makefile.in (haifa-sched.o): Depend on it.
* haifa-sched.c: Include it.
...
...
gcc/Makefile.in
View file @
c62c2659
...
...
@@ -737,7 +737,7 @@ OBJS = diagnostic.o version.o tree.o print-tree.o stor-layout.o fold-const.o \
mbchar.o splay-tree.o graph.o sbitmap.o resource.o hash.o predict.o
\
lists.o ggc-common.o
$(GGC)
stringpool.o simplify-rtx.o ssa.o bb-reorder.o
\
sibcall.o conflict.o timevar.o ifcvt.o dominance.o dependence.o dce.o
\
hashtab.o
sched-vis.o
hashtab.o
BACKEND
=
toplev.o libbackend.a
...
...
@@ -1455,6 +1455,8 @@ regmove.o : regmove.c $(CONFIG_H) system.h $(RTL_H) insn-config.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
sched-vis.o
:
sched-vis.c $(CONFIG_H) system.h $(RTL_H) sched-int.h
\
$(INSN_ATTR_H) $(REGS_H)
final.o
:
final.c $(CONFIG_H) system.h $(RTL_H) $(TREE_H) flags.h intl.h
\
$(REGS_H) $(RECOG_H) conditions.h insn-config.h $(INSN_ATTR_H) function.h
\
real.h output.h hard-reg-set.h insn-flags.h insn-codes.h gstab.h except.h
\
...
...
gcc/haifa-sched.c
View file @
c62c2659
...
...
@@ -177,15 +177,6 @@ extern rtx *reg_known_value;
#ifdef INSN_SCHEDULING
/* target_units bitmask has 1 for each unit in the cpu. It should be
possible to compute this variable from the machine description.
But currently it is computed by examining the insn list. Since
this is only needed for visualization, it seems an acceptable
solution. (For understanding the mapping of bits to units, see
definition of function_units[] in "insn-attrtab.c".) */
static
int
target_units
=
0
;
/* issue_rate is the number of insns that can be scheduled in the same
machine cycle. It can be defined in the config/mach/mach.h file,
otherwise we set it to 1. */
...
...
@@ -216,7 +207,7 @@ static int nr_inter, nr_spec;
/* Debugging file. All printouts are sent to dump, which is always set,
either to stderr, or to the dump listing file (-dRS). */
static
FILE
*
sched_dump
=
0
;
FILE
*
sched_dump
=
0
;
/* Highest uid before scheduling. */
static
int
old_max_uid
;
...
...
@@ -502,10 +493,8 @@ static void add_dependence PARAMS ((rtx, rtx, enum reg_note));
static
void
remove_dependence
PARAMS
((
rtx
,
rtx
));
static
rtx
find_insn_list
PARAMS
((
rtx
,
rtx
));
static
void
set_sched_group_p
PARAMS
((
rtx
));
static
int
insn_unit
PARAMS
((
rtx
));
static
unsigned
int
blockage_range
PARAMS
((
int
,
rtx
));
static
void
clear_units
PARAMS
((
void
));
static
int
actual_hazard_this_instance
PARAMS
((
int
,
int
,
rtx
,
int
,
int
));
static
void
schedule_unit
PARAMS
((
int
,
rtx
,
int
));
static
int
actual_hazard
PARAMS
((
int
,
rtx
,
int
,
int
));
static
int
potential_hazard
PARAMS
((
int
,
rtx
,
int
));
...
...
@@ -525,7 +514,6 @@ 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
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
));
...
...
@@ -802,18 +790,6 @@ static rtx ready_remove_first PARAMS ((struct ready_list *));
static
void
queue_to_ready
PARAMS
((
struct
ready_list
*
));
static
void
debug_ready_list
PARAMS
((
struct
ready_list
*
));
static
void
init_target_units
PARAMS
((
void
));
static
void
insn_print_units
PARAMS
((
rtx
));
static
int
get_visual_tbl_length
PARAMS
((
void
));
static
void
init_block_visualization
PARAMS
((
void
));
static
void
print_block_visualization
PARAMS
((
int
,
const
char
*
));
static
void
visualize_scheduled_insns
PARAMS
((
int
,
int
));
static
void
visualize_no_unit
PARAMS
((
rtx
));
static
void
visualize_stall_cycles
PARAMS
((
int
,
int
));
static
void
print_exp
PARAMS
((
char
*
,
rtx
,
int
));
static
void
print_value
PARAMS
((
char
*
,
rtx
,
int
));
static
void
print_pattern
PARAMS
((
char
*
,
rtx
,
int
));
static
void
print_insn
PARAMS
((
char
*
,
rtx
,
int
));
void
debug_reg_vector
PARAMS
((
regset
));
static
rtx
move_insn1
PARAMS
((
rtx
,
rtx
));
...
...
@@ -2914,7 +2890,7 @@ find_insn_mem_list (insn, x, list, list1)
mask if the value is negative. A function unit index is the
non-negative encoding. */
HAIFA_INLINE
static
int
HAIFA_INLINE
int
insn_unit
(
insn
)
rtx
insn
;
{
...
...
@@ -2986,6 +2962,15 @@ static int unit_tick[FUNCTION_UNITS_SIZE * MAX_MULTIPLICITY];
that remain to use the unit. */
static
int
unit_n_insns
[
FUNCTION_UNITS_SIZE
];
/* Access the unit_last_insn array. Used by the visualization code. */
rtx
get_unit_last_insn
(
instance
)
int
instance
;
{
return
unit_last_insn
[
instance
];
}
/* Reset the function unit state to the null state. */
static
void
...
...
@@ -3028,7 +3013,7 @@ insn_issue_delay (insn)
instance INSTANCE at time CLOCK if the previous actual hazard cost
was COST. */
HAIFA_INLINE
static
int
HAIFA_INLINE
int
actual_hazard_this_instance
(
unit
,
instance
,
insn
,
clock
,
cost
)
int
unit
,
instance
,
clock
,
cost
;
rtx
insn
;
...
...
@@ -4899,7 +4884,7 @@ queue_to_ready (ready)
}
if
(
sched_verbose
&&
stalls
)
visualize_stall_cycles
(
BB_TO_BLOCK
(
target_bb
),
stalls
);
visualize_stall_cycles
(
stalls
);
q_ptr
=
NEXT_Q_AFTER
(
q_ptr
,
stalls
);
clock_var
+=
stalls
;
}
...
...
@@ -4923,873 +4908,6 @@ debug_ready_list (ready)
fprintf
(
sched_dump
,
"
\n
"
);
}
/* Print names of units on which insn can/should execute, for debugging. */
static
void
insn_print_units
(
insn
)
rtx
insn
;
{
int
i
;
int
unit
=
insn_unit
(
insn
);
if
(
unit
==
-
1
)
fprintf
(
sched_dump
,
"none"
);
else
if
(
unit
>=
0
)
fprintf
(
sched_dump
,
"%s"
,
function_units
[
unit
].
name
);
else
{
fprintf
(
sched_dump
,
"["
);
for
(
i
=
0
,
unit
=
~
unit
;
unit
;
i
++
,
unit
>>=
1
)
if
(
unit
&
1
)
{
fprintf
(
sched_dump
,
"%s"
,
function_units
[
i
].
name
);
if
(
unit
!=
1
)
fprintf
(
sched_dump
,
" "
);
}
fprintf
(
sched_dump
,
"]"
);
}
}
/* MAX_VISUAL_LINES is the maximum number of lines in visualization table
of a basic block. If more lines are needed, table is splitted to two.
n_visual_lines is the number of lines printed so far for a block.
visual_tbl contains the block visualization info.
vis_no_unit holds insns in a cycle that are not mapped to any unit. */
#define MAX_VISUAL_LINES 100
#define INSN_LEN 30
int
n_visual_lines
;
char
*
visual_tbl
;
int
n_vis_no_unit
;
rtx
vis_no_unit
[
10
];
/* Finds units that are in use in this fuction. Required only
for visualization. */
static
void
init_target_units
()
{
rtx
insn
;
int
unit
;
for
(
insn
=
get_last_insn
();
insn
;
insn
=
PREV_INSN
(
insn
))
{
if
(
!
INSN_P
(
insn
))
continue
;
unit
=
insn_unit
(
insn
);
if
(
unit
<
0
)
target_units
|=
~
unit
;
else
target_units
|=
(
1
<<
unit
);
}
}
/* Return the length of the visualization table. */
static
int
get_visual_tbl_length
()
{
int
unit
,
i
;
int
n
,
n1
;
char
*
s
;
/* Compute length of one field in line. */
s
=
(
char
*
)
alloca
(
INSN_LEN
+
6
);
sprintf
(
s
,
" %33s"
,
"uname"
);
n1
=
strlen
(
s
);
/* Compute length of one line. */
n
=
strlen
(
";; "
);
n
+=
n1
;
for
(
unit
=
0
;
unit
<
FUNCTION_UNITS_SIZE
;
unit
++
)
if
(
function_units
[
unit
].
bitmask
&
target_units
)
for
(
i
=
0
;
i
<
function_units
[
unit
].
multiplicity
;
i
++
)
n
+=
n1
;
n
+=
n1
;
n
+=
strlen
(
"
\n
"
)
+
2
;
/* Compute length of visualization string. */
return
(
MAX_VISUAL_LINES
*
n
);
}
/* Init block visualization debugging info. */
static
void
init_block_visualization
()
{
strcpy
(
visual_tbl
,
""
);
n_visual_lines
=
0
;
n_vis_no_unit
=
0
;
}
#define BUF_LEN 2048
static
char
*
safe_concat
(
buf
,
cur
,
str
)
char
*
buf
;
char
*
cur
;
const
char
*
str
;
{
char
*
end
=
buf
+
BUF_LEN
-
2
;
/* Leave room for null. */
int
c
;
if
(
cur
>
end
)
{
*
end
=
'\0'
;
return
end
;
}
while
(
cur
<
end
&&
(
c
=
*
str
++
)
!=
'\0'
)
*
cur
++
=
c
;
*
cur
=
'\0'
;
return
cur
;
}
/* This recognizes rtx, I classified as expressions. These are always
represent some action on values or results of other expression, that
may be stored in objects representing values. */
static
void
print_exp
(
buf
,
x
,
verbose
)
char
*
buf
;
rtx
x
;
int
verbose
;
{
char
tmp
[
BUF_LEN
];
const
char
*
st
[
4
];
char
*
cur
=
buf
;
const
char
*
fun
=
(
char
*
)
0
;
const
char
*
sep
;
rtx
op
[
4
];
int
i
;
for
(
i
=
0
;
i
<
4
;
i
++
)
{
st
[
i
]
=
(
char
*
)
0
;
op
[
i
]
=
NULL_RTX
;
}
switch
(
GET_CODE
(
x
))
{
case
PLUS
:
op
[
0
]
=
XEXP
(
x
,
0
);
if
(
GET_CODE
(
XEXP
(
x
,
1
))
==
CONST_INT
&&
INTVAL
(
XEXP
(
x
,
1
))
<
0
)
{
st
[
1
]
=
"-"
;
op
[
1
]
=
GEN_INT
(
-
INTVAL
(
XEXP
(
x
,
1
)));
}
else
{
st
[
1
]
=
"+"
;
op
[
1
]
=
XEXP
(
x
,
1
);
}
break
;
case
LO_SUM
:
op
[
0
]
=
XEXP
(
x
,
0
);
st
[
1
]
=
"+low("
;
op
[
1
]
=
XEXP
(
x
,
1
);
st
[
2
]
=
")"
;
break
;
case
MINUS
:
op
[
0
]
=
XEXP
(
x
,
0
);
st
[
1
]
=
"-"
;
op
[
1
]
=
XEXP
(
x
,
1
);
break
;
case
COMPARE
:
fun
=
"cmp"
;
op
[
0
]
=
XEXP
(
x
,
0
);
op
[
1
]
=
XEXP
(
x
,
1
);
break
;
case
NEG
:
st
[
0
]
=
"-"
;
op
[
0
]
=
XEXP
(
x
,
0
);
break
;
case
MULT
:
op
[
0
]
=
XEXP
(
x
,
0
);
st
[
1
]
=
"*"
;
op
[
1
]
=
XEXP
(
x
,
1
);
break
;
case
DIV
:
op
[
0
]
=
XEXP
(
x
,
0
);
st
[
1
]
=
"/"
;
op
[
1
]
=
XEXP
(
x
,
1
);
break
;
case
UDIV
:
fun
=
"udiv"
;
op
[
0
]
=
XEXP
(
x
,
0
);
op
[
1
]
=
XEXP
(
x
,
1
);
break
;
case
MOD
:
op
[
0
]
=
XEXP
(
x
,
0
);
st
[
1
]
=
"%"
;
op
[
1
]
=
XEXP
(
x
,
1
);
break
;
case
UMOD
:
fun
=
"umod"
;
op
[
0
]
=
XEXP
(
x
,
0
);
op
[
1
]
=
XEXP
(
x
,
1
);
break
;
case
SMIN
:
fun
=
"smin"
;
op
[
0
]
=
XEXP
(
x
,
0
);
op
[
1
]
=
XEXP
(
x
,
1
);
break
;
case
SMAX
:
fun
=
"smax"
;
op
[
0
]
=
XEXP
(
x
,
0
);
op
[
1
]
=
XEXP
(
x
,
1
);
break
;
case
UMIN
:
fun
=
"umin"
;
op
[
0
]
=
XEXP
(
x
,
0
);
op
[
1
]
=
XEXP
(
x
,
1
);
break
;
case
UMAX
:
fun
=
"umax"
;
op
[
0
]
=
XEXP
(
x
,
0
);
op
[
1
]
=
XEXP
(
x
,
1
);
break
;
case
NOT
:
st
[
0
]
=
"!"
;
op
[
0
]
=
XEXP
(
x
,
0
);
break
;
case
AND
:
op
[
0
]
=
XEXP
(
x
,
0
);
st
[
1
]
=
"&"
;
op
[
1
]
=
XEXP
(
x
,
1
);
break
;
case
IOR
:
op
[
0
]
=
XEXP
(
x
,
0
);
st
[
1
]
=
"|"
;
op
[
1
]
=
XEXP
(
x
,
1
);
break
;
case
XOR
:
op
[
0
]
=
XEXP
(
x
,
0
);
st
[
1
]
=
"^"
;
op
[
1
]
=
XEXP
(
x
,
1
);
break
;
case
ASHIFT
:
op
[
0
]
=
XEXP
(
x
,
0
);
st
[
1
]
=
"<<"
;
op
[
1
]
=
XEXP
(
x
,
1
);
break
;
case
LSHIFTRT
:
op
[
0
]
=
XEXP
(
x
,
0
);
st
[
1
]
=
" 0>>"
;
op
[
1
]
=
XEXP
(
x
,
1
);
break
;
case
ASHIFTRT
:
op
[
0
]
=
XEXP
(
x
,
0
);
st
[
1
]
=
">>"
;
op
[
1
]
=
XEXP
(
x
,
1
);
break
;
case
ROTATE
:
op
[
0
]
=
XEXP
(
x
,
0
);
st
[
1
]
=
"<-<"
;
op
[
1
]
=
XEXP
(
x
,
1
);
break
;
case
ROTATERT
:
op
[
0
]
=
XEXP
(
x
,
0
);
st
[
1
]
=
">->"
;
op
[
1
]
=
XEXP
(
x
,
1
);
break
;
case
ABS
:
fun
=
"abs"
;
op
[
0
]
=
XEXP
(
x
,
0
);
break
;
case
SQRT
:
fun
=
"sqrt"
;
op
[
0
]
=
XEXP
(
x
,
0
);
break
;
case
FFS
:
fun
=
"ffs"
;
op
[
0
]
=
XEXP
(
x
,
0
);
break
;
case
EQ
:
op
[
0
]
=
XEXP
(
x
,
0
);
st
[
1
]
=
"=="
;
op
[
1
]
=
XEXP
(
x
,
1
);
break
;
case
NE
:
op
[
0
]
=
XEXP
(
x
,
0
);
st
[
1
]
=
"!="
;
op
[
1
]
=
XEXP
(
x
,
1
);
break
;
case
GT
:
op
[
0
]
=
XEXP
(
x
,
0
);
st
[
1
]
=
">"
;
op
[
1
]
=
XEXP
(
x
,
1
);
break
;
case
GTU
:
fun
=
"gtu"
;
op
[
0
]
=
XEXP
(
x
,
0
);
op
[
1
]
=
XEXP
(
x
,
1
);
break
;
case
LT
:
op
[
0
]
=
XEXP
(
x
,
0
);
st
[
1
]
=
"<"
;
op
[
1
]
=
XEXP
(
x
,
1
);
break
;
case
LTU
:
fun
=
"ltu"
;
op
[
0
]
=
XEXP
(
x
,
0
);
op
[
1
]
=
XEXP
(
x
,
1
);
break
;
case
GE
:
op
[
0
]
=
XEXP
(
x
,
0
);
st
[
1
]
=
">="
;
op
[
1
]
=
XEXP
(
x
,
1
);
break
;
case
GEU
:
fun
=
"geu"
;
op
[
0
]
=
XEXP
(
x
,
0
);
op
[
1
]
=
XEXP
(
x
,
1
);
break
;
case
LE
:
op
[
0
]
=
XEXP
(
x
,
0
);
st
[
1
]
=
"<="
;
op
[
1
]
=
XEXP
(
x
,
1
);
break
;
case
LEU
:
fun
=
"leu"
;
op
[
0
]
=
XEXP
(
x
,
0
);
op
[
1
]
=
XEXP
(
x
,
1
);
break
;
case
SIGN_EXTRACT
:
fun
=
(
verbose
)
?
"sign_extract"
:
"sxt"
;
op
[
0
]
=
XEXP
(
x
,
0
);
op
[
1
]
=
XEXP
(
x
,
1
);
op
[
2
]
=
XEXP
(
x
,
2
);
break
;
case
ZERO_EXTRACT
:
fun
=
(
verbose
)
?
"zero_extract"
:
"zxt"
;
op
[
0
]
=
XEXP
(
x
,
0
);
op
[
1
]
=
XEXP
(
x
,
1
);
op
[
2
]
=
XEXP
(
x
,
2
);
break
;
case
SIGN_EXTEND
:
fun
=
(
verbose
)
?
"sign_extend"
:
"sxn"
;
op
[
0
]
=
XEXP
(
x
,
0
);
break
;
case
ZERO_EXTEND
:
fun
=
(
verbose
)
?
"zero_extend"
:
"zxn"
;
op
[
0
]
=
XEXP
(
x
,
0
);
break
;
case
FLOAT_EXTEND
:
fun
=
(
verbose
)
?
"float_extend"
:
"fxn"
;
op
[
0
]
=
XEXP
(
x
,
0
);
break
;
case
TRUNCATE
:
fun
=
(
verbose
)
?
"trunc"
:
"trn"
;
op
[
0
]
=
XEXP
(
x
,
0
);
break
;
case
FLOAT_TRUNCATE
:
fun
=
(
verbose
)
?
"float_trunc"
:
"ftr"
;
op
[
0
]
=
XEXP
(
x
,
0
);
break
;
case
FLOAT
:
fun
=
(
verbose
)
?
"float"
:
"flt"
;
op
[
0
]
=
XEXP
(
x
,
0
);
break
;
case
UNSIGNED_FLOAT
:
fun
=
(
verbose
)
?
"uns_float"
:
"ufl"
;
op
[
0
]
=
XEXP
(
x
,
0
);
break
;
case
FIX
:
fun
=
"fix"
;
op
[
0
]
=
XEXP
(
x
,
0
);
break
;
case
UNSIGNED_FIX
:
fun
=
(
verbose
)
?
"uns_fix"
:
"ufx"
;
op
[
0
]
=
XEXP
(
x
,
0
);
break
;
case
PRE_DEC
:
st
[
0
]
=
"--"
;
op
[
0
]
=
XEXP
(
x
,
0
);
break
;
case
PRE_INC
:
st
[
0
]
=
"++"
;
op
[
0
]
=
XEXP
(
x
,
0
);
break
;
case
POST_DEC
:
op
[
0
]
=
XEXP
(
x
,
0
);
st
[
1
]
=
"--"
;
break
;
case
POST_INC
:
op
[
0
]
=
XEXP
(
x
,
0
);
st
[
1
]
=
"++"
;
break
;
case
CALL
:
st
[
0
]
=
"call "
;
op
[
0
]
=
XEXP
(
x
,
0
);
if
(
verbose
)
{
st
[
1
]
=
" argc:"
;
op
[
1
]
=
XEXP
(
x
,
1
);
}
break
;
case
IF_THEN_ELSE
:
st
[
0
]
=
"{("
;
op
[
0
]
=
XEXP
(
x
,
0
);
st
[
1
]
=
")?"
;
op
[
1
]
=
XEXP
(
x
,
1
);
st
[
2
]
=
":"
;
op
[
2
]
=
XEXP
(
x
,
2
);
st
[
3
]
=
"}"
;
break
;
case
TRAP_IF
:
fun
=
"trap_if"
;
op
[
0
]
=
TRAP_CONDITION
(
x
);
break
;
case
UNSPEC
:
case
UNSPEC_VOLATILE
:
{
cur
=
safe_concat
(
buf
,
cur
,
"unspec"
);
if
(
GET_CODE
(
x
)
==
UNSPEC_VOLATILE
)
cur
=
safe_concat
(
buf
,
cur
,
"/v"
);
cur
=
safe_concat
(
buf
,
cur
,
"["
);
sep
=
""
;
for
(
i
=
0
;
i
<
XVECLEN
(
x
,
0
);
i
++
)
{
print_pattern
(
tmp
,
XVECEXP
(
x
,
0
,
i
),
verbose
);
cur
=
safe_concat
(
buf
,
cur
,
sep
);
cur
=
safe_concat
(
buf
,
cur
,
tmp
);
sep
=
","
;
}
cur
=
safe_concat
(
buf
,
cur
,
"] "
);
sprintf
(
tmp
,
"%d"
,
XINT
(
x
,
1
));
cur
=
safe_concat
(
buf
,
cur
,
tmp
);
}
break
;
default
:
/* If (verbose) debug_rtx (x); */
st
[
0
]
=
GET_RTX_NAME
(
GET_CODE
(
x
));
break
;
}
/* Print this as a function? */
if
(
fun
)
{
cur
=
safe_concat
(
buf
,
cur
,
fun
);
cur
=
safe_concat
(
buf
,
cur
,
"("
);
}
for
(
i
=
0
;
i
<
4
;
i
++
)
{
if
(
st
[
i
])
cur
=
safe_concat
(
buf
,
cur
,
st
[
i
]);
if
(
op
[
i
])
{
if
(
fun
&&
i
!=
0
)
cur
=
safe_concat
(
buf
,
cur
,
","
);
print_value
(
tmp
,
op
[
i
],
verbose
);
cur
=
safe_concat
(
buf
,
cur
,
tmp
);
}
}
if
(
fun
)
cur
=
safe_concat
(
buf
,
cur
,
")"
);
}
/* print_exp */
/* Prints rtxes, I customly classified as values. They're constants,
registers, labels, symbols and memory accesses. */
static
void
print_value
(
buf
,
x
,
verbose
)
char
*
buf
;
rtx
x
;
int
verbose
;
{
char
t
[
BUF_LEN
];
char
*
cur
=
buf
;
switch
(
GET_CODE
(
x
))
{
case
CONST_INT
:
sprintf
(
t
,
HOST_WIDE_INT_PRINT_HEX
,
INTVAL
(
x
));
cur
=
safe_concat
(
buf
,
cur
,
t
);
break
;
case
CONST_DOUBLE
:
sprintf
(
t
,
"<0x%lx,0x%lx>"
,
(
long
)
XWINT
(
x
,
2
),
(
long
)
XWINT
(
x
,
3
));
cur
=
safe_concat
(
buf
,
cur
,
t
);
break
;
case
CONST_STRING
:
cur
=
safe_concat
(
buf
,
cur
,
"
\"
"
);
cur
=
safe_concat
(
buf
,
cur
,
XSTR
(
x
,
0
));
cur
=
safe_concat
(
buf
,
cur
,
"
\"
"
);
break
;
case
SYMBOL_REF
:
cur
=
safe_concat
(
buf
,
cur
,
"`"
);
cur
=
safe_concat
(
buf
,
cur
,
XSTR
(
x
,
0
));
cur
=
safe_concat
(
buf
,
cur
,
"'"
);
break
;
case
LABEL_REF
:
sprintf
(
t
,
"L%d"
,
INSN_UID
(
XEXP
(
x
,
0
)));
cur
=
safe_concat
(
buf
,
cur
,
t
);
break
;
case
CONST
:
print_value
(
t
,
XEXP
(
x
,
0
),
verbose
);
cur
=
safe_concat
(
buf
,
cur
,
"const("
);
cur
=
safe_concat
(
buf
,
cur
,
t
);
cur
=
safe_concat
(
buf
,
cur
,
")"
);
break
;
case
HIGH
:
print_value
(
t
,
XEXP
(
x
,
0
),
verbose
);
cur
=
safe_concat
(
buf
,
cur
,
"high("
);
cur
=
safe_concat
(
buf
,
cur
,
t
);
cur
=
safe_concat
(
buf
,
cur
,
")"
);
break
;
case
REG
:
if
(
REGNO
(
x
)
<
FIRST_PSEUDO_REGISTER
)
{
int
c
=
reg_names
[
REGNO
(
x
)][
0
];
if
(
c
>=
'0'
&&
c
<=
'9'
)
cur
=
safe_concat
(
buf
,
cur
,
"%"
);
cur
=
safe_concat
(
buf
,
cur
,
reg_names
[
REGNO
(
x
)]);
}
else
{
sprintf
(
t
,
"r%d"
,
REGNO
(
x
));
cur
=
safe_concat
(
buf
,
cur
,
t
);
}
break
;
case
SUBREG
:
print_value
(
t
,
SUBREG_REG
(
x
),
verbose
);
cur
=
safe_concat
(
buf
,
cur
,
t
);
sprintf
(
t
,
"#%d"
,
SUBREG_WORD
(
x
));
cur
=
safe_concat
(
buf
,
cur
,
t
);
break
;
case
SCRATCH
:
cur
=
safe_concat
(
buf
,
cur
,
"scratch"
);
break
;
case
CC0
:
cur
=
safe_concat
(
buf
,
cur
,
"cc0"
);
break
;
case
PC
:
cur
=
safe_concat
(
buf
,
cur
,
"pc"
);
break
;
case
MEM
:
print_value
(
t
,
XEXP
(
x
,
0
),
verbose
);
cur
=
safe_concat
(
buf
,
cur
,
"["
);
cur
=
safe_concat
(
buf
,
cur
,
t
);
cur
=
safe_concat
(
buf
,
cur
,
"]"
);
break
;
default
:
print_exp
(
t
,
x
,
verbose
);
cur
=
safe_concat
(
buf
,
cur
,
t
);
break
;
}
}
/* print_value */
/* The next step in insn detalization, its pattern recognition. */
static
void
print_pattern
(
buf
,
x
,
verbose
)
char
*
buf
;
rtx
x
;
int
verbose
;
{
char
t1
[
BUF_LEN
],
t2
[
BUF_LEN
],
t3
[
BUF_LEN
];
switch
(
GET_CODE
(
x
))
{
case
SET
:
print_value
(
t1
,
SET_DEST
(
x
),
verbose
);
print_value
(
t2
,
SET_SRC
(
x
),
verbose
);
sprintf
(
buf
,
"%s=%s"
,
t1
,
t2
);
break
;
case
RETURN
:
sprintf
(
buf
,
"return"
);
break
;
case
CALL
:
print_exp
(
buf
,
x
,
verbose
);
break
;
case
CLOBBER
:
print_value
(
t1
,
XEXP
(
x
,
0
),
verbose
);
sprintf
(
buf
,
"clobber %s"
,
t1
);
break
;
case
USE
:
print_value
(
t1
,
XEXP
(
x
,
0
),
verbose
);
sprintf
(
buf
,
"use %s"
,
t1
);
break
;
case
COND_EXEC
:
if
(
GET_CODE
(
COND_EXEC_TEST
(
x
))
==
NE
&&
XEXP
(
COND_EXEC_TEST
(
x
),
1
)
==
const0_rtx
)
print_value
(
t1
,
XEXP
(
COND_EXEC_TEST
(
x
),
0
),
verbose
);
else
if
(
GET_CODE
(
COND_EXEC_TEST
(
x
))
==
EQ
&&
XEXP
(
COND_EXEC_TEST
(
x
),
1
)
==
const0_rtx
)
{
t1
[
0
]
=
'!'
;
print_value
(
t1
+
1
,
XEXP
(
COND_EXEC_TEST
(
x
),
0
),
verbose
);
}
else
print_value
(
t1
,
COND_EXEC_TEST
(
x
),
verbose
);
print_pattern
(
t2
,
COND_EXEC_CODE
(
x
),
verbose
);
sprintf
(
buf
,
"(%s) %s"
,
t1
,
t2
);
break
;
case
PARALLEL
:
{
int
i
;
sprintf
(
t1
,
"{"
);
for
(
i
=
0
;
i
<
XVECLEN
(
x
,
0
);
i
++
)
{
print_pattern
(
t2
,
XVECEXP
(
x
,
0
,
i
),
verbose
);
sprintf
(
t3
,
"%s%s;"
,
t1
,
t2
);
strcpy
(
t1
,
t3
);
}
sprintf
(
buf
,
"%s}"
,
t1
);
}
break
;
case
SEQUENCE
:
{
int
i
;
sprintf
(
t1
,
"%%{"
);
for
(
i
=
0
;
i
<
XVECLEN
(
x
,
0
);
i
++
)
{
print_insn
(
t2
,
XVECEXP
(
x
,
0
,
i
),
verbose
);
sprintf
(
t3
,
"%s%s;"
,
t1
,
t2
);
strcpy
(
t1
,
t3
);
}
sprintf
(
buf
,
"%s%%}"
,
t1
);
}
break
;
case
ASM_INPUT
:
sprintf
(
buf
,
"asm {%s}"
,
XSTR
(
x
,
0
));
break
;
case
ADDR_VEC
:
break
;
case
ADDR_DIFF_VEC
:
print_value
(
buf
,
XEXP
(
x
,
0
),
verbose
);
break
;
case
TRAP_IF
:
print_value
(
t1
,
TRAP_CONDITION
(
x
),
verbose
);
sprintf
(
buf
,
"trap_if %s"
,
t1
);
break
;
case
UNSPEC
:
{
int
i
;
sprintf
(
t1
,
"unspec{"
);
for
(
i
=
0
;
i
<
XVECLEN
(
x
,
0
);
i
++
)
{
print_pattern
(
t2
,
XVECEXP
(
x
,
0
,
i
),
verbose
);
sprintf
(
t3
,
"%s%s;"
,
t1
,
t2
);
strcpy
(
t1
,
t3
);
}
sprintf
(
buf
,
"%s}"
,
t1
);
}
break
;
case
UNSPEC_VOLATILE
:
{
int
i
;
sprintf
(
t1
,
"unspec/v{"
);
for
(
i
=
0
;
i
<
XVECLEN
(
x
,
0
);
i
++
)
{
print_pattern
(
t2
,
XVECEXP
(
x
,
0
,
i
),
verbose
);
sprintf
(
t3
,
"%s%s;"
,
t1
,
t2
);
strcpy
(
t1
,
t3
);
}
sprintf
(
buf
,
"%s}"
,
t1
);
}
break
;
default
:
print_value
(
buf
,
x
,
verbose
);
}
}
/* print_pattern */
/* This is the main function in rtl visualization mechanism. It
accepts an rtx and tries to recognize it as an insn, then prints it
properly in human readable form, resembling assembler mnemonics.
For every insn it prints its UID and BB the insn belongs too.
(Probably the last "option" should be extended somehow, since it
depends now on sched.c inner variables ...) */
static
void
print_insn
(
buf
,
x
,
verbose
)
char
*
buf
;
rtx
x
;
int
verbose
;
{
char
t
[
BUF_LEN
];
rtx
insn
=
x
;
switch
(
GET_CODE
(
x
))
{
case
INSN
:
print_pattern
(
t
,
PATTERN
(
x
),
verbose
);
if
(
verbose
)
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
,
"%s: jump %s"
,
(
*
current_sched_info
->
print_insn
)
(
x
,
1
),
t
);
else
sprintf
(
buf
,
"%-4d %s"
,
INSN_UID
(
x
),
t
);
break
;
case
CALL_INSN
:
x
=
PATTERN
(
insn
);
if
(
GET_CODE
(
x
)
==
PARALLEL
)
{
x
=
XVECEXP
(
x
,
0
,
0
);
print_pattern
(
t
,
x
,
verbose
);
}
else
strcpy
(
t
,
"call <...>"
);
if
(
verbose
)
sprintf
(
buf
,
"%s: %s"
,
(
*
current_sched_info
->
print_insn
)
(
x
,
1
),
t
);
else
sprintf
(
buf
,
"%-4d %s"
,
INSN_UID
(
insn
),
t
);
break
;
case
CODE_LABEL
:
sprintf
(
buf
,
"L%d:"
,
INSN_UID
(
x
));
break
;
case
BARRIER
:
sprintf
(
buf
,
"i% 4d: barrier"
,
INSN_UID
(
x
));
break
;
case
NOTE
:
if
(
NOTE_LINE_NUMBER
(
x
)
>
0
)
sprintf
(
buf
,
"%4d note
\"
%s
\"
%d"
,
INSN_UID
(
x
),
NOTE_SOURCE_FILE
(
x
),
NOTE_LINE_NUMBER
(
x
));
else
sprintf
(
buf
,
"%4d %s"
,
INSN_UID
(
x
),
GET_NOTE_INSN_NAME
(
NOTE_LINE_NUMBER
(
x
)));
break
;
default
:
if
(
verbose
)
{
sprintf
(
buf
,
"Not an INSN at all
\n
"
);
debug_rtx
(
x
);
}
else
sprintf
(
buf
,
"i%-4d <What?>"
,
INSN_UID
(
x
));
}
}
/* print_insn */
/* Print visualization debugging info. */
static
void
print_block_visualization
(
b
,
s
)
int
b
;
const
char
*
s
;
{
int
unit
,
i
;
/* Print header. */
fprintf
(
sched_dump
,
"
\n
;; ==================== scheduling visualization for block %d %s
\n
"
,
b
,
s
);
/* Print names of units. */
fprintf
(
sched_dump
,
";; %-8s"
,
"clock"
);
for
(
unit
=
0
;
unit
<
FUNCTION_UNITS_SIZE
;
unit
++
)
if
(
function_units
[
unit
].
bitmask
&
target_units
)
for
(
i
=
0
;
i
<
function_units
[
unit
].
multiplicity
;
i
++
)
fprintf
(
sched_dump
,
" %-33s"
,
function_units
[
unit
].
name
);
fprintf
(
sched_dump
,
" %-8s
\n
"
,
"no-unit"
);
fprintf
(
sched_dump
,
";; %-8s"
,
"====="
);
for
(
unit
=
0
;
unit
<
FUNCTION_UNITS_SIZE
;
unit
++
)
if
(
function_units
[
unit
].
bitmask
&
target_units
)
for
(
i
=
0
;
i
<
function_units
[
unit
].
multiplicity
;
i
++
)
fprintf
(
sched_dump
,
" %-33s"
,
"=============================="
);
fprintf
(
sched_dump
,
" %-8s
\n
"
,
"======="
);
/* Print insns in each cycle. */
fprintf
(
sched_dump
,
"%s
\n
"
,
visual_tbl
);
}
/* Print insns in the 'no_unit' column of visualization. */
static
void
visualize_no_unit
(
insn
)
rtx
insn
;
{
vis_no_unit
[
n_vis_no_unit
]
=
insn
;
n_vis_no_unit
++
;
}
/* Print insns scheduled in clock, for visualization. */
static
void
visualize_scheduled_insns
(
b
,
clock
)
int
b
,
clock
;
{
int
i
,
unit
;
/* If no more room, split table into two. */
if
(
n_visual_lines
>=
MAX_VISUAL_LINES
)
{
print_block_visualization
(
b
,
"(incomplete)"
);
init_block_visualization
();
}
n_visual_lines
++
;
sprintf
(
visual_tbl
+
strlen
(
visual_tbl
),
";; %-8d"
,
clock
);
for
(
unit
=
0
;
unit
<
FUNCTION_UNITS_SIZE
;
unit
++
)
if
(
function_units
[
unit
].
bitmask
&
target_units
)
for
(
i
=
0
;
i
<
function_units
[
unit
].
multiplicity
;
i
++
)
{
int
instance
=
unit
+
i
*
FUNCTION_UNITS_SIZE
;
rtx
insn
=
unit_last_insn
[
instance
];
/* Print insns that still keep the unit busy. */
if
(
insn
&&
actual_hazard_this_instance
(
unit
,
instance
,
insn
,
clock
,
0
))
{
char
str
[
BUF_LEN
];
print_insn
(
str
,
insn
,
0
);
str
[
INSN_LEN
]
=
'\0'
;
sprintf
(
visual_tbl
+
strlen
(
visual_tbl
),
" %-33s"
,
str
);
}
else
sprintf
(
visual_tbl
+
strlen
(
visual_tbl
),
" %-33s"
,
"------------------------------"
);
}
/* Print insns that are not assigned to any unit. */
for
(
i
=
0
;
i
<
n_vis_no_unit
;
i
++
)
sprintf
(
visual_tbl
+
strlen
(
visual_tbl
),
" %-8d"
,
INSN_UID
(
vis_no_unit
[
i
]));
n_vis_no_unit
=
0
;
sprintf
(
visual_tbl
+
strlen
(
visual_tbl
),
"
\n
"
);
}
/* Print stalled cycles. */
static
void
visualize_stall_cycles
(
b
,
stalls
)
int
b
,
stalls
;
{
int
i
;
/* If no more room, split table into two. */
if
(
n_visual_lines
>=
MAX_VISUAL_LINES
)
{
print_block_visualization
(
b
,
"(incomplete)"
);
init_block_visualization
();
}
n_visual_lines
++
;
sprintf
(
visual_tbl
+
strlen
(
visual_tbl
),
";; "
);
for
(
i
=
0
;
i
<
stalls
;
i
++
)
sprintf
(
visual_tbl
+
strlen
(
visual_tbl
),
"."
);
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. */
...
...
@@ -6248,7 +5366,7 @@ schedule_block (bb, rgn_n_insns)
fprintf
(
sched_dump
,
";; ======================================================
\n
"
);
fprintf
(
sched_dump
,
"
\n
"
);
visual
_tbl
=
(
char
*
)
alloca
(
get_visual_tbl_length
()
);
visual
ize_alloc
(
);
init_block_visualization
();
}
...
...
@@ -6356,7 +5474,7 @@ schedule_block (bb, rgn_n_insns)
/* Debug info. */
if
(
sched_verbose
)
visualize_scheduled_insns
(
b
,
clock_var
);
visualize_scheduled_insns
(
clock_var
);
}
/* Debug info. */
...
...
@@ -6364,7 +5482,7 @@ schedule_block (bb, rgn_n_insns)
{
fprintf
(
sched_dump
,
";;
\t
Ready list (final): "
);
debug_ready_list
(
&
ready
);
print_block_visualization
(
b
,
""
);
print_block_visualization
(
""
);
}
/* Sanity check -- queue must be empty now. Meaningless if region has
...
...
@@ -6402,14 +5520,13 @@ schedule_block (bb, rgn_n_insns)
clock_var
,
INSN_UID
(
head
));
fprintf
(
sched_dump
,
";; new tail = %d
\n\n
"
,
INSN_UID
(
tail
));
visualize_free
();
}
current_sched_info
->
head
=
head
;
current_sched_info
->
tail
=
tail
;
free
(
ready
.
vec
);
return
1
;
}
/* Print the bit-set of registers, S, callable from debugger. */
...
...
gcc/sched-vis.c
0 → 100644
View file @
c62c2659
/* Instruction scheduling pass.
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998,
1999, 2000 Free Software Foundation, Inc.
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.
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. */
#include "config.h"
#include "system.h"
#include "toplev.h"
#include "rtl.h"
#include "tm_p.h"
#include "regs.h"
#include "insn-attr.h"
#include "sched-int.h"
/* target_units bitmask has 1 for each unit in the cpu. It should be
possible to compute this variable from the machine description.
But currently it is computed by examining the insn list. Since
this is only needed for visualization, it seems an acceptable
solution. (For understanding the mapping of bits to units, see
definition of function_units[] in "insn-attrtab.c".) */
static
int
target_units
=
0
;
static
char
*
safe_concat
PARAMS
((
char
*
,
char
*
,
const
char
*
));
static
int
get_visual_tbl_length
PARAMS
((
void
));
static
void
print_exp
PARAMS
((
char
*
,
rtx
,
int
));
static
void
print_value
PARAMS
((
char
*
,
rtx
,
int
));
static
void
print_pattern
PARAMS
((
char
*
,
rtx
,
int
));
static
void
print_insn
PARAMS
((
char
*
,
rtx
,
int
));
/* Print names of units on which insn can/should execute, for debugging. */
void
insn_print_units
(
insn
)
rtx
insn
;
{
int
i
;
int
unit
=
insn_unit
(
insn
);
if
(
unit
==
-
1
)
fprintf
(
sched_dump
,
"none"
);
else
if
(
unit
>=
0
)
fprintf
(
sched_dump
,
"%s"
,
function_units
[
unit
].
name
);
else
{
fprintf
(
sched_dump
,
"["
);
for
(
i
=
0
,
unit
=
~
unit
;
unit
;
i
++
,
unit
>>=
1
)
if
(
unit
&
1
)
{
fprintf
(
sched_dump
,
"%s"
,
function_units
[
i
].
name
);
if
(
unit
!=
1
)
fprintf
(
sched_dump
,
" "
);
}
fprintf
(
sched_dump
,
"]"
);
}
}
/* MAX_VISUAL_LINES is the maximum number of lines in visualization table
of a basic block. If more lines are needed, table is splitted to two.
n_visual_lines is the number of lines printed so far for a block.
visual_tbl contains the block visualization info.
vis_no_unit holds insns in a cycle that are not mapped to any unit. */
#define MAX_VISUAL_LINES 100
#define INSN_LEN 30
int
n_visual_lines
;
char
*
visual_tbl
;
int
n_vis_no_unit
;
rtx
vis_no_unit
[
10
];
/* Finds units that are in use in this fuction. Required only
for visualization. */
void
init_target_units
()
{
rtx
insn
;
int
unit
;
for
(
insn
=
get_last_insn
();
insn
;
insn
=
PREV_INSN
(
insn
))
{
if
(
!
INSN_P
(
insn
))
continue
;
unit
=
insn_unit
(
insn
);
if
(
unit
<
0
)
target_units
|=
~
unit
;
else
target_units
|=
(
1
<<
unit
);
}
}
/* Return the length of the visualization table. */
static
int
get_visual_tbl_length
()
{
int
unit
,
i
;
int
n
,
n1
;
char
*
s
;
/* Compute length of one field in line. */
s
=
(
char
*
)
alloca
(
INSN_LEN
+
6
);
sprintf
(
s
,
" %33s"
,
"uname"
);
n1
=
strlen
(
s
);
/* Compute length of one line. */
n
=
strlen
(
";; "
);
n
+=
n1
;
for
(
unit
=
0
;
unit
<
FUNCTION_UNITS_SIZE
;
unit
++
)
if
(
function_units
[
unit
].
bitmask
&
target_units
)
for
(
i
=
0
;
i
<
function_units
[
unit
].
multiplicity
;
i
++
)
n
+=
n1
;
n
+=
n1
;
n
+=
strlen
(
"
\n
"
)
+
2
;
/* Compute length of visualization string. */
return
(
MAX_VISUAL_LINES
*
n
);
}
/* Init block visualization debugging info. */
void
init_block_visualization
()
{
strcpy
(
visual_tbl
,
""
);
n_visual_lines
=
0
;
n_vis_no_unit
=
0
;
}
#define BUF_LEN 2048
static
char
*
safe_concat
(
buf
,
cur
,
str
)
char
*
buf
;
char
*
cur
;
const
char
*
str
;
{
char
*
end
=
buf
+
BUF_LEN
-
2
;
/* Leave room for null. */
int
c
;
if
(
cur
>
end
)
{
*
end
=
'\0'
;
return
end
;
}
while
(
cur
<
end
&&
(
c
=
*
str
++
)
!=
'\0'
)
*
cur
++
=
c
;
*
cur
=
'\0'
;
return
cur
;
}
/* This recognizes rtx, I classified as expressions. These are always
represent some action on values or results of other expression, that
may be stored in objects representing values. */
static
void
print_exp
(
buf
,
x
,
verbose
)
char
*
buf
;
rtx
x
;
int
verbose
;
{
char
tmp
[
BUF_LEN
];
const
char
*
st
[
4
];
char
*
cur
=
buf
;
const
char
*
fun
=
(
char
*
)
0
;
const
char
*
sep
;
rtx
op
[
4
];
int
i
;
for
(
i
=
0
;
i
<
4
;
i
++
)
{
st
[
i
]
=
(
char
*
)
0
;
op
[
i
]
=
NULL_RTX
;
}
switch
(
GET_CODE
(
x
))
{
case
PLUS
:
op
[
0
]
=
XEXP
(
x
,
0
);
if
(
GET_CODE
(
XEXP
(
x
,
1
))
==
CONST_INT
&&
INTVAL
(
XEXP
(
x
,
1
))
<
0
)
{
st
[
1
]
=
"-"
;
op
[
1
]
=
GEN_INT
(
-
INTVAL
(
XEXP
(
x
,
1
)));
}
else
{
st
[
1
]
=
"+"
;
op
[
1
]
=
XEXP
(
x
,
1
);
}
break
;
case
LO_SUM
:
op
[
0
]
=
XEXP
(
x
,
0
);
st
[
1
]
=
"+low("
;
op
[
1
]
=
XEXP
(
x
,
1
);
st
[
2
]
=
")"
;
break
;
case
MINUS
:
op
[
0
]
=
XEXP
(
x
,
0
);
st
[
1
]
=
"-"
;
op
[
1
]
=
XEXP
(
x
,
1
);
break
;
case
COMPARE
:
fun
=
"cmp"
;
op
[
0
]
=
XEXP
(
x
,
0
);
op
[
1
]
=
XEXP
(
x
,
1
);
break
;
case
NEG
:
st
[
0
]
=
"-"
;
op
[
0
]
=
XEXP
(
x
,
0
);
break
;
case
MULT
:
op
[
0
]
=
XEXP
(
x
,
0
);
st
[
1
]
=
"*"
;
op
[
1
]
=
XEXP
(
x
,
1
);
break
;
case
DIV
:
op
[
0
]
=
XEXP
(
x
,
0
);
st
[
1
]
=
"/"
;
op
[
1
]
=
XEXP
(
x
,
1
);
break
;
case
UDIV
:
fun
=
"udiv"
;
op
[
0
]
=
XEXP
(
x
,
0
);
op
[
1
]
=
XEXP
(
x
,
1
);
break
;
case
MOD
:
op
[
0
]
=
XEXP
(
x
,
0
);
st
[
1
]
=
"%"
;
op
[
1
]
=
XEXP
(
x
,
1
);
break
;
case
UMOD
:
fun
=
"umod"
;
op
[
0
]
=
XEXP
(
x
,
0
);
op
[
1
]
=
XEXP
(
x
,
1
);
break
;
case
SMIN
:
fun
=
"smin"
;
op
[
0
]
=
XEXP
(
x
,
0
);
op
[
1
]
=
XEXP
(
x
,
1
);
break
;
case
SMAX
:
fun
=
"smax"
;
op
[
0
]
=
XEXP
(
x
,
0
);
op
[
1
]
=
XEXP
(
x
,
1
);
break
;
case
UMIN
:
fun
=
"umin"
;
op
[
0
]
=
XEXP
(
x
,
0
);
op
[
1
]
=
XEXP
(
x
,
1
);
break
;
case
UMAX
:
fun
=
"umax"
;
op
[
0
]
=
XEXP
(
x
,
0
);
op
[
1
]
=
XEXP
(
x
,
1
);
break
;
case
NOT
:
st
[
0
]
=
"!"
;
op
[
0
]
=
XEXP
(
x
,
0
);
break
;
case
AND
:
op
[
0
]
=
XEXP
(
x
,
0
);
st
[
1
]
=
"&"
;
op
[
1
]
=
XEXP
(
x
,
1
);
break
;
case
IOR
:
op
[
0
]
=
XEXP
(
x
,
0
);
st
[
1
]
=
"|"
;
op
[
1
]
=
XEXP
(
x
,
1
);
break
;
case
XOR
:
op
[
0
]
=
XEXP
(
x
,
0
);
st
[
1
]
=
"^"
;
op
[
1
]
=
XEXP
(
x
,
1
);
break
;
case
ASHIFT
:
op
[
0
]
=
XEXP
(
x
,
0
);
st
[
1
]
=
"<<"
;
op
[
1
]
=
XEXP
(
x
,
1
);
break
;
case
LSHIFTRT
:
op
[
0
]
=
XEXP
(
x
,
0
);
st
[
1
]
=
" 0>>"
;
op
[
1
]
=
XEXP
(
x
,
1
);
break
;
case
ASHIFTRT
:
op
[
0
]
=
XEXP
(
x
,
0
);
st
[
1
]
=
">>"
;
op
[
1
]
=
XEXP
(
x
,
1
);
break
;
case
ROTATE
:
op
[
0
]
=
XEXP
(
x
,
0
);
st
[
1
]
=
"<-<"
;
op
[
1
]
=
XEXP
(
x
,
1
);
break
;
case
ROTATERT
:
op
[
0
]
=
XEXP
(
x
,
0
);
st
[
1
]
=
">->"
;
op
[
1
]
=
XEXP
(
x
,
1
);
break
;
case
ABS
:
fun
=
"abs"
;
op
[
0
]
=
XEXP
(
x
,
0
);
break
;
case
SQRT
:
fun
=
"sqrt"
;
op
[
0
]
=
XEXP
(
x
,
0
);
break
;
case
FFS
:
fun
=
"ffs"
;
op
[
0
]
=
XEXP
(
x
,
0
);
break
;
case
EQ
:
op
[
0
]
=
XEXP
(
x
,
0
);
st
[
1
]
=
"=="
;
op
[
1
]
=
XEXP
(
x
,
1
);
break
;
case
NE
:
op
[
0
]
=
XEXP
(
x
,
0
);
st
[
1
]
=
"!="
;
op
[
1
]
=
XEXP
(
x
,
1
);
break
;
case
GT
:
op
[
0
]
=
XEXP
(
x
,
0
);
st
[
1
]
=
">"
;
op
[
1
]
=
XEXP
(
x
,
1
);
break
;
case
GTU
:
fun
=
"gtu"
;
op
[
0
]
=
XEXP
(
x
,
0
);
op
[
1
]
=
XEXP
(
x
,
1
);
break
;
case
LT
:
op
[
0
]
=
XEXP
(
x
,
0
);
st
[
1
]
=
"<"
;
op
[
1
]
=
XEXP
(
x
,
1
);
break
;
case
LTU
:
fun
=
"ltu"
;
op
[
0
]
=
XEXP
(
x
,
0
);
op
[
1
]
=
XEXP
(
x
,
1
);
break
;
case
GE
:
op
[
0
]
=
XEXP
(
x
,
0
);
st
[
1
]
=
">="
;
op
[
1
]
=
XEXP
(
x
,
1
);
break
;
case
GEU
:
fun
=
"geu"
;
op
[
0
]
=
XEXP
(
x
,
0
);
op
[
1
]
=
XEXP
(
x
,
1
);
break
;
case
LE
:
op
[
0
]
=
XEXP
(
x
,
0
);
st
[
1
]
=
"<="
;
op
[
1
]
=
XEXP
(
x
,
1
);
break
;
case
LEU
:
fun
=
"leu"
;
op
[
0
]
=
XEXP
(
x
,
0
);
op
[
1
]
=
XEXP
(
x
,
1
);
break
;
case
SIGN_EXTRACT
:
fun
=
(
verbose
)
?
"sign_extract"
:
"sxt"
;
op
[
0
]
=
XEXP
(
x
,
0
);
op
[
1
]
=
XEXP
(
x
,
1
);
op
[
2
]
=
XEXP
(
x
,
2
);
break
;
case
ZERO_EXTRACT
:
fun
=
(
verbose
)
?
"zero_extract"
:
"zxt"
;
op
[
0
]
=
XEXP
(
x
,
0
);
op
[
1
]
=
XEXP
(
x
,
1
);
op
[
2
]
=
XEXP
(
x
,
2
);
break
;
case
SIGN_EXTEND
:
fun
=
(
verbose
)
?
"sign_extend"
:
"sxn"
;
op
[
0
]
=
XEXP
(
x
,
0
);
break
;
case
ZERO_EXTEND
:
fun
=
(
verbose
)
?
"zero_extend"
:
"zxn"
;
op
[
0
]
=
XEXP
(
x
,
0
);
break
;
case
FLOAT_EXTEND
:
fun
=
(
verbose
)
?
"float_extend"
:
"fxn"
;
op
[
0
]
=
XEXP
(
x
,
0
);
break
;
case
TRUNCATE
:
fun
=
(
verbose
)
?
"trunc"
:
"trn"
;
op
[
0
]
=
XEXP
(
x
,
0
);
break
;
case
FLOAT_TRUNCATE
:
fun
=
(
verbose
)
?
"float_trunc"
:
"ftr"
;
op
[
0
]
=
XEXP
(
x
,
0
);
break
;
case
FLOAT
:
fun
=
(
verbose
)
?
"float"
:
"flt"
;
op
[
0
]
=
XEXP
(
x
,
0
);
break
;
case
UNSIGNED_FLOAT
:
fun
=
(
verbose
)
?
"uns_float"
:
"ufl"
;
op
[
0
]
=
XEXP
(
x
,
0
);
break
;
case
FIX
:
fun
=
"fix"
;
op
[
0
]
=
XEXP
(
x
,
0
);
break
;
case
UNSIGNED_FIX
:
fun
=
(
verbose
)
?
"uns_fix"
:
"ufx"
;
op
[
0
]
=
XEXP
(
x
,
0
);
break
;
case
PRE_DEC
:
st
[
0
]
=
"--"
;
op
[
0
]
=
XEXP
(
x
,
0
);
break
;
case
PRE_INC
:
st
[
0
]
=
"++"
;
op
[
0
]
=
XEXP
(
x
,
0
);
break
;
case
POST_DEC
:
op
[
0
]
=
XEXP
(
x
,
0
);
st
[
1
]
=
"--"
;
break
;
case
POST_INC
:
op
[
0
]
=
XEXP
(
x
,
0
);
st
[
1
]
=
"++"
;
break
;
case
CALL
:
st
[
0
]
=
"call "
;
op
[
0
]
=
XEXP
(
x
,
0
);
if
(
verbose
)
{
st
[
1
]
=
" argc:"
;
op
[
1
]
=
XEXP
(
x
,
1
);
}
break
;
case
IF_THEN_ELSE
:
st
[
0
]
=
"{("
;
op
[
0
]
=
XEXP
(
x
,
0
);
st
[
1
]
=
")?"
;
op
[
1
]
=
XEXP
(
x
,
1
);
st
[
2
]
=
":"
;
op
[
2
]
=
XEXP
(
x
,
2
);
st
[
3
]
=
"}"
;
break
;
case
TRAP_IF
:
fun
=
"trap_if"
;
op
[
0
]
=
TRAP_CONDITION
(
x
);
break
;
case
UNSPEC
:
case
UNSPEC_VOLATILE
:
{
cur
=
safe_concat
(
buf
,
cur
,
"unspec"
);
if
(
GET_CODE
(
x
)
==
UNSPEC_VOLATILE
)
cur
=
safe_concat
(
buf
,
cur
,
"/v"
);
cur
=
safe_concat
(
buf
,
cur
,
"["
);
sep
=
""
;
for
(
i
=
0
;
i
<
XVECLEN
(
x
,
0
);
i
++
)
{
print_pattern
(
tmp
,
XVECEXP
(
x
,
0
,
i
),
verbose
);
cur
=
safe_concat
(
buf
,
cur
,
sep
);
cur
=
safe_concat
(
buf
,
cur
,
tmp
);
sep
=
","
;
}
cur
=
safe_concat
(
buf
,
cur
,
"] "
);
sprintf
(
tmp
,
"%d"
,
XINT
(
x
,
1
));
cur
=
safe_concat
(
buf
,
cur
,
tmp
);
}
break
;
default
:
/* If (verbose) debug_rtx (x); */
st
[
0
]
=
GET_RTX_NAME
(
GET_CODE
(
x
));
break
;
}
/* Print this as a function? */
if
(
fun
)
{
cur
=
safe_concat
(
buf
,
cur
,
fun
);
cur
=
safe_concat
(
buf
,
cur
,
"("
);
}
for
(
i
=
0
;
i
<
4
;
i
++
)
{
if
(
st
[
i
])
cur
=
safe_concat
(
buf
,
cur
,
st
[
i
]);
if
(
op
[
i
])
{
if
(
fun
&&
i
!=
0
)
cur
=
safe_concat
(
buf
,
cur
,
","
);
print_value
(
tmp
,
op
[
i
],
verbose
);
cur
=
safe_concat
(
buf
,
cur
,
tmp
);
}
}
if
(
fun
)
cur
=
safe_concat
(
buf
,
cur
,
")"
);
}
/* print_exp */
/* Prints rtxes, I customly classified as values. They're constants,
registers, labels, symbols and memory accesses. */
static
void
print_value
(
buf
,
x
,
verbose
)
char
*
buf
;
rtx
x
;
int
verbose
;
{
char
t
[
BUF_LEN
];
char
*
cur
=
buf
;
switch
(
GET_CODE
(
x
))
{
case
CONST_INT
:
sprintf
(
t
,
HOST_WIDE_INT_PRINT_HEX
,
INTVAL
(
x
));
cur
=
safe_concat
(
buf
,
cur
,
t
);
break
;
case
CONST_DOUBLE
:
sprintf
(
t
,
"<0x%lx,0x%lx>"
,
(
long
)
XWINT
(
x
,
2
),
(
long
)
XWINT
(
x
,
3
));
cur
=
safe_concat
(
buf
,
cur
,
t
);
break
;
case
CONST_STRING
:
cur
=
safe_concat
(
buf
,
cur
,
"
\"
"
);
cur
=
safe_concat
(
buf
,
cur
,
XSTR
(
x
,
0
));
cur
=
safe_concat
(
buf
,
cur
,
"
\"
"
);
break
;
case
SYMBOL_REF
:
cur
=
safe_concat
(
buf
,
cur
,
"`"
);
cur
=
safe_concat
(
buf
,
cur
,
XSTR
(
x
,
0
));
cur
=
safe_concat
(
buf
,
cur
,
"'"
);
break
;
case
LABEL_REF
:
sprintf
(
t
,
"L%d"
,
INSN_UID
(
XEXP
(
x
,
0
)));
cur
=
safe_concat
(
buf
,
cur
,
t
);
break
;
case
CONST
:
print_value
(
t
,
XEXP
(
x
,
0
),
verbose
);
cur
=
safe_concat
(
buf
,
cur
,
"const("
);
cur
=
safe_concat
(
buf
,
cur
,
t
);
cur
=
safe_concat
(
buf
,
cur
,
")"
);
break
;
case
HIGH
:
print_value
(
t
,
XEXP
(
x
,
0
),
verbose
);
cur
=
safe_concat
(
buf
,
cur
,
"high("
);
cur
=
safe_concat
(
buf
,
cur
,
t
);
cur
=
safe_concat
(
buf
,
cur
,
")"
);
break
;
case
REG
:
if
(
REGNO
(
x
)
<
FIRST_PSEUDO_REGISTER
)
{
int
c
=
reg_names
[
REGNO
(
x
)][
0
];
if
(
c
>=
'0'
&&
c
<=
'9'
)
cur
=
safe_concat
(
buf
,
cur
,
"%"
);
cur
=
safe_concat
(
buf
,
cur
,
reg_names
[
REGNO
(
x
)]);
}
else
{
sprintf
(
t
,
"r%d"
,
REGNO
(
x
));
cur
=
safe_concat
(
buf
,
cur
,
t
);
}
break
;
case
SUBREG
:
print_value
(
t
,
SUBREG_REG
(
x
),
verbose
);
cur
=
safe_concat
(
buf
,
cur
,
t
);
sprintf
(
t
,
"#%d"
,
SUBREG_WORD
(
x
));
cur
=
safe_concat
(
buf
,
cur
,
t
);
break
;
case
SCRATCH
:
cur
=
safe_concat
(
buf
,
cur
,
"scratch"
);
break
;
case
CC0
:
cur
=
safe_concat
(
buf
,
cur
,
"cc0"
);
break
;
case
PC
:
cur
=
safe_concat
(
buf
,
cur
,
"pc"
);
break
;
case
MEM
:
print_value
(
t
,
XEXP
(
x
,
0
),
verbose
);
cur
=
safe_concat
(
buf
,
cur
,
"["
);
cur
=
safe_concat
(
buf
,
cur
,
t
);
cur
=
safe_concat
(
buf
,
cur
,
"]"
);
break
;
default
:
print_exp
(
t
,
x
,
verbose
);
cur
=
safe_concat
(
buf
,
cur
,
t
);
break
;
}
}
/* print_value */
/* The next step in insn detalization, its pattern recognition. */
static
void
print_pattern
(
buf
,
x
,
verbose
)
char
*
buf
;
rtx
x
;
int
verbose
;
{
char
t1
[
BUF_LEN
],
t2
[
BUF_LEN
],
t3
[
BUF_LEN
];
switch
(
GET_CODE
(
x
))
{
case
SET
:
print_value
(
t1
,
SET_DEST
(
x
),
verbose
);
print_value
(
t2
,
SET_SRC
(
x
),
verbose
);
sprintf
(
buf
,
"%s=%s"
,
t1
,
t2
);
break
;
case
RETURN
:
sprintf
(
buf
,
"return"
);
break
;
case
CALL
:
print_exp
(
buf
,
x
,
verbose
);
break
;
case
CLOBBER
:
print_value
(
t1
,
XEXP
(
x
,
0
),
verbose
);
sprintf
(
buf
,
"clobber %s"
,
t1
);
break
;
case
USE
:
print_value
(
t1
,
XEXP
(
x
,
0
),
verbose
);
sprintf
(
buf
,
"use %s"
,
t1
);
break
;
case
COND_EXEC
:
if
(
GET_CODE
(
COND_EXEC_TEST
(
x
))
==
NE
&&
XEXP
(
COND_EXEC_TEST
(
x
),
1
)
==
const0_rtx
)
print_value
(
t1
,
XEXP
(
COND_EXEC_TEST
(
x
),
0
),
verbose
);
else
if
(
GET_CODE
(
COND_EXEC_TEST
(
x
))
==
EQ
&&
XEXP
(
COND_EXEC_TEST
(
x
),
1
)
==
const0_rtx
)
{
t1
[
0
]
=
'!'
;
print_value
(
t1
+
1
,
XEXP
(
COND_EXEC_TEST
(
x
),
0
),
verbose
);
}
else
print_value
(
t1
,
COND_EXEC_TEST
(
x
),
verbose
);
print_pattern
(
t2
,
COND_EXEC_CODE
(
x
),
verbose
);
sprintf
(
buf
,
"(%s) %s"
,
t1
,
t2
);
break
;
case
PARALLEL
:
{
int
i
;
sprintf
(
t1
,
"{"
);
for
(
i
=
0
;
i
<
XVECLEN
(
x
,
0
);
i
++
)
{
print_pattern
(
t2
,
XVECEXP
(
x
,
0
,
i
),
verbose
);
sprintf
(
t3
,
"%s%s;"
,
t1
,
t2
);
strcpy
(
t1
,
t3
);
}
sprintf
(
buf
,
"%s}"
,
t1
);
}
break
;
case
SEQUENCE
:
{
int
i
;
sprintf
(
t1
,
"%%{"
);
for
(
i
=
0
;
i
<
XVECLEN
(
x
,
0
);
i
++
)
{
print_insn
(
t2
,
XVECEXP
(
x
,
0
,
i
),
verbose
);
sprintf
(
t3
,
"%s%s;"
,
t1
,
t2
);
strcpy
(
t1
,
t3
);
}
sprintf
(
buf
,
"%s%%}"
,
t1
);
}
break
;
case
ASM_INPUT
:
sprintf
(
buf
,
"asm {%s}"
,
XSTR
(
x
,
0
));
break
;
case
ADDR_VEC
:
break
;
case
ADDR_DIFF_VEC
:
print_value
(
buf
,
XEXP
(
x
,
0
),
verbose
);
break
;
case
TRAP_IF
:
print_value
(
t1
,
TRAP_CONDITION
(
x
),
verbose
);
sprintf
(
buf
,
"trap_if %s"
,
t1
);
break
;
case
UNSPEC
:
{
int
i
;
sprintf
(
t1
,
"unspec{"
);
for
(
i
=
0
;
i
<
XVECLEN
(
x
,
0
);
i
++
)
{
print_pattern
(
t2
,
XVECEXP
(
x
,
0
,
i
),
verbose
);
sprintf
(
t3
,
"%s%s;"
,
t1
,
t2
);
strcpy
(
t1
,
t3
);
}
sprintf
(
buf
,
"%s}"
,
t1
);
}
break
;
case
UNSPEC_VOLATILE
:
{
int
i
;
sprintf
(
t1
,
"unspec/v{"
);
for
(
i
=
0
;
i
<
XVECLEN
(
x
,
0
);
i
++
)
{
print_pattern
(
t2
,
XVECEXP
(
x
,
0
,
i
),
verbose
);
sprintf
(
t3
,
"%s%s;"
,
t1
,
t2
);
strcpy
(
t1
,
t3
);
}
sprintf
(
buf
,
"%s}"
,
t1
);
}
break
;
default
:
print_value
(
buf
,
x
,
verbose
);
}
}
/* print_pattern */
/* This is the main function in rtl visualization mechanism. It
accepts an rtx and tries to recognize it as an insn, then prints it
properly in human readable form, resembling assembler mnemonics.
For every insn it prints its UID and BB the insn belongs too.
(Probably the last "option" should be extended somehow, since it
depends now on sched.c inner variables ...) */
static
void
print_insn
(
buf
,
x
,
verbose
)
char
*
buf
;
rtx
x
;
int
verbose
;
{
char
t
[
BUF_LEN
];
rtx
insn
=
x
;
switch
(
GET_CODE
(
x
))
{
case
INSN
:
print_pattern
(
t
,
PATTERN
(
x
),
verbose
);
if
(
verbose
)
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
,
"%s: jump %s"
,
(
*
current_sched_info
->
print_insn
)
(
x
,
1
),
t
);
else
sprintf
(
buf
,
"%-4d %s"
,
INSN_UID
(
x
),
t
);
break
;
case
CALL_INSN
:
x
=
PATTERN
(
insn
);
if
(
GET_CODE
(
x
)
==
PARALLEL
)
{
x
=
XVECEXP
(
x
,
0
,
0
);
print_pattern
(
t
,
x
,
verbose
);
}
else
strcpy
(
t
,
"call <...>"
);
if
(
verbose
)
sprintf
(
buf
,
"%s: %s"
,
(
*
current_sched_info
->
print_insn
)
(
x
,
1
),
t
);
else
sprintf
(
buf
,
"%-4d %s"
,
INSN_UID
(
insn
),
t
);
break
;
case
CODE_LABEL
:
sprintf
(
buf
,
"L%d:"
,
INSN_UID
(
x
));
break
;
case
BARRIER
:
sprintf
(
buf
,
"i% 4d: barrier"
,
INSN_UID
(
x
));
break
;
case
NOTE
:
if
(
NOTE_LINE_NUMBER
(
x
)
>
0
)
sprintf
(
buf
,
"%4d note
\"
%s
\"
%d"
,
INSN_UID
(
x
),
NOTE_SOURCE_FILE
(
x
),
NOTE_LINE_NUMBER
(
x
));
else
sprintf
(
buf
,
"%4d %s"
,
INSN_UID
(
x
),
GET_NOTE_INSN_NAME
(
NOTE_LINE_NUMBER
(
x
)));
break
;
default
:
if
(
verbose
)
{
sprintf
(
buf
,
"Not an INSN at all
\n
"
);
debug_rtx
(
x
);
}
else
sprintf
(
buf
,
"i%-4d <What?>"
,
INSN_UID
(
x
));
}
}
/* print_insn */
/* Print visualization debugging info. */
void
print_block_visualization
(
s
)
const
char
*
s
;
{
int
unit
,
i
;
/* Print header. */
fprintf
(
sched_dump
,
"
\n
;; ==================== scheduling visualization %s
\n
"
,
s
);
/* Print names of units. */
fprintf
(
sched_dump
,
";; %-8s"
,
"clock"
);
for
(
unit
=
0
;
unit
<
FUNCTION_UNITS_SIZE
;
unit
++
)
if
(
function_units
[
unit
].
bitmask
&
target_units
)
for
(
i
=
0
;
i
<
function_units
[
unit
].
multiplicity
;
i
++
)
fprintf
(
sched_dump
,
" %-33s"
,
function_units
[
unit
].
name
);
fprintf
(
sched_dump
,
" %-8s
\n
"
,
"no-unit"
);
fprintf
(
sched_dump
,
";; %-8s"
,
"====="
);
for
(
unit
=
0
;
unit
<
FUNCTION_UNITS_SIZE
;
unit
++
)
if
(
function_units
[
unit
].
bitmask
&
target_units
)
for
(
i
=
0
;
i
<
function_units
[
unit
].
multiplicity
;
i
++
)
fprintf
(
sched_dump
,
" %-33s"
,
"=============================="
);
fprintf
(
sched_dump
,
" %-8s
\n
"
,
"======="
);
/* Print insns in each cycle. */
fprintf
(
sched_dump
,
"%s
\n
"
,
visual_tbl
);
}
/* Print insns in the 'no_unit' column of visualization. */
void
visualize_no_unit
(
insn
)
rtx
insn
;
{
vis_no_unit
[
n_vis_no_unit
]
=
insn
;
n_vis_no_unit
++
;
}
/* Print insns scheduled in clock, for visualization. */
void
visualize_scheduled_insns
(
clock
)
int
clock
;
{
int
i
,
unit
;
/* If no more room, split table into two. */
if
(
n_visual_lines
>=
MAX_VISUAL_LINES
)
{
print_block_visualization
(
"(incomplete)"
);
init_block_visualization
();
}
n_visual_lines
++
;
sprintf
(
visual_tbl
+
strlen
(
visual_tbl
),
";; %-8d"
,
clock
);
for
(
unit
=
0
;
unit
<
FUNCTION_UNITS_SIZE
;
unit
++
)
if
(
function_units
[
unit
].
bitmask
&
target_units
)
for
(
i
=
0
;
i
<
function_units
[
unit
].
multiplicity
;
i
++
)
{
int
instance
=
unit
+
i
*
FUNCTION_UNITS_SIZE
;
rtx
insn
=
get_unit_last_insn
(
instance
);
/* Print insns that still keep the unit busy. */
if
(
insn
&&
actual_hazard_this_instance
(
unit
,
instance
,
insn
,
clock
,
0
))
{
char
str
[
BUF_LEN
];
print_insn
(
str
,
insn
,
0
);
str
[
INSN_LEN
]
=
'\0'
;
sprintf
(
visual_tbl
+
strlen
(
visual_tbl
),
" %-33s"
,
str
);
}
else
sprintf
(
visual_tbl
+
strlen
(
visual_tbl
),
" %-33s"
,
"------------------------------"
);
}
/* Print insns that are not assigned to any unit. */
for
(
i
=
0
;
i
<
n_vis_no_unit
;
i
++
)
sprintf
(
visual_tbl
+
strlen
(
visual_tbl
),
" %-8d"
,
INSN_UID
(
vis_no_unit
[
i
]));
n_vis_no_unit
=
0
;
sprintf
(
visual_tbl
+
strlen
(
visual_tbl
),
"
\n
"
);
}
/* Print stalled cycles. */
void
visualize_stall_cycles
(
stalls
)
int
stalls
;
{
int
i
;
/* If no more room, split table into two. */
if
(
n_visual_lines
>=
MAX_VISUAL_LINES
)
{
print_block_visualization
(
"(incomplete)"
);
init_block_visualization
();
}
n_visual_lines
++
;
sprintf
(
visual_tbl
+
strlen
(
visual_tbl
),
";; "
);
for
(
i
=
0
;
i
<
stalls
;
i
++
)
sprintf
(
visual_tbl
+
strlen
(
visual_tbl
),
"."
);
sprintf
(
visual_tbl
+
strlen
(
visual_tbl
),
"
\n
"
);
}
/* Allocate data used for visualization during scheduling. */
void
visualize_alloc
()
{
visual_tbl
=
xmalloc
(
get_visual_tbl_length
());
}
/* Free data used for visualization. */
void
visualize_free
()
{
free
(
visual_tbl
);
}
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