2 * Author: Humberto Naves (hsnaves@gmail.com)
9 void live_analysis (list worklist
)
11 while (list_size (worklist
) != 0) {
12 struct basicedge
*edge
;
13 struct basicblock
*block
, *bref
;
14 struct subroutine
*sub
;
15 int i
, changed
, regno
;
18 block
= list_removehead (worklist
);
20 for (i
= 0; i
< NUM_REGMASK
; i
++)
21 block
->reg_live_out
[i
] =
22 (block
->reg_live_in
[i
] & ~(block
->reg_kill
[i
])) | block
->reg_gen
[i
];
24 ref
= list_head (block
->inrefs
);
28 edge
= element_getvalue (ref
);
31 for (i
= 0; i
< NUM_REGMASK
; i
++) {
32 changed
= changed
|| (block
->reg_live_out
[i
] & (~bref
->reg_live_in
[i
]));
33 bref
->reg_live_in
[i
] |= block
->reg_live_out
[i
];
36 if (changed
&& !bref
->mark1
) {
37 list_inserttail (worklist
, bref
);
41 ref
= element_next (ref
);
44 sub
= block
->info
.call
.calltarget
;
45 if (block
->type
== BLOCK_CALL
&& sub
) {
47 for (regno
= REGISTER_GPR_V0
; regno
<= REGISTER_GPR_V1
; regno
++) {
48 if (IS_BIT_SET (block
->reg_live_in
, regno
)) {
49 sub
->numregout
= MAX (sub
->numregout
, regno
- REGISTER_GPR_V0
+ 1);
53 if (sub
->status
& SUB_STAT_OPERATIONS_EXTRACTED
) {
55 for (regno
= REGISTER_GPR_V0
; regno
<= REGISTER_GPR_V1
; regno
++) {
56 if (IS_BIT_SET (block
->reg_live_in
, regno
)) {
57 changed
= changed
|| !IS_BIT_SET (sub
->endblock
->reg_gen
, regno
);
58 BIT_SET (sub
->endblock
->reg_gen
, regno
);
61 if (changed
&& !sub
->endblock
->mark1
) {
62 list_inserttail (worklist
, sub
->endblock
);
63 sub
->endblock
->mark1
= 1;
68 if (block
->type
== BLOCK_START
) {
71 for (regno
= REGISTER_GPR_A0
; regno
<= REGISTER_GPR_T3
; regno
++) {
72 if (IS_BIT_SET (block
->reg_live_in
, regno
)) {
73 sub
->numregargs
= MAX (sub
->numregargs
, regno
- REGISTER_GPR_A0
+ 1);
77 ref
= list_head (sub
->whereused
);
79 bref
= element_getvalue (ref
);
81 for (regno
= REGISTER_GPR_A0
; regno
<= REGISTER_GPR_T3
; regno
++) {
82 if (IS_BIT_SET (block
->reg_live_in
, regno
)) {
83 changed
= changed
|| !IS_BIT_SET (bref
->reg_gen
, regno
);
84 BIT_SET (bref
->reg_gen
, regno
);
87 if (changed
&& !bref
->mark1
) {
88 list_inserttail (worklist
, bref
);
91 ref
= element_next (ref
);
97 void live_registers (struct code
*c
)
99 list worklist
= list_alloc (c
->lstpool
);
100 element el
= list_head (c
->subroutines
);
103 struct subroutine
*sub
= element_getvalue (el
);
104 if (!sub
->import
&& !sub
->haserror
) {
106 sub
->status
|= SUB_STAT_LIVE_REGISTERS
;
107 sub
->endblock
->mark1
= 1;
108 list_inserthead (worklist
, sub
->endblock
);
110 el
= element_next (el
);
113 live_analysis (worklist
);
114 list_free (worklist
);
117 void live_registers_imports (struct code
*c
)
119 element el
= list_head (c
->subroutines
);
122 struct subroutine
*sub
= element_getvalue (el
);
123 if (sub
->import
&& sub
->numregargs
== -1) {
126 ref
= list_head (sub
->whereused
);
128 struct basicblock
*block
= element_getvalue (ref
);
129 struct operation
*op
= list_tailvalue (block
->operations
);
130 int count
= 0, maxcount
= 0;
133 opel
= list_head (op
->info
.callop
.arguments
);
135 struct value
*val
= element_getvalue (opel
);
138 if (list_size (val
->val
.variable
->uses
) == 1 &&
139 val
->val
.variable
->def
->type
!= OP_START
&&
140 val
->val
.variable
->def
->type
!= OP_CALL
) {
141 if (maxcount
< count
) maxcount
= count
;
143 opel
= element_next (opel
);
146 if (sub
->numregargs
< maxcount
)
147 sub
->numregargs
= maxcount
;
149 ref
= element_next (ref
);
152 ref
= list_head (sub
->whereused
);
154 struct basicblock
*block
= element_getvalue (ref
);
155 struct subroutine
*target
= block
->sub
;
157 target
->status
&= ~(SUB_STAT_SSA
| SUB_STAT_FIXUP_CALL_ARGS
);
158 ref
= element_next (ref
);
161 el
= element_next (el
);
164 el
= list_head (c
->subroutines
);
167 struct subroutine
*sub
= element_getvalue (el
);
168 if (!sub
->import
&& !sub
->haserror
&&
169 !(sub
->status
& SUB_STAT_SSA
)) {
171 remove_call_arguments (sub
);
173 el
= element_next (el
);