Passo intermediario, ainda falta um longo caminho
[pspdecompiler.git] / liveness.c
blobf223f7ce5a8e27c6ddfef9e2fffd730ef1f4322f
2 #include "code.h"
3 #include "utils.h"
5 static
6 void live_analysis (list worklist)
8 while (list_size (worklist) != 0) {
9 struct basicedge *edge;
10 struct basicblock *block, *bref;
11 struct subroutine *sub;
12 int i, changed, regno;
13 element ref;
15 block = list_removehead (worklist);
16 block->mark1 = 0;
17 for (i = 0; i < NUM_REGMASK; i++)
18 block->reg_live_out[i] =
19 (block->reg_live_in[i] & ~(block->reg_kill[i])) | block->reg_gen[i];
21 ref = list_head (block->inrefs);
22 while (ref) {
23 changed = FALSE;
25 edge = element_getvalue (ref);
26 bref = edge->from;
28 for (i = 0; i < NUM_REGMASK; i++) {
29 changed = changed || (block->reg_live_out[i] & (~bref->reg_live_in[i]));
30 bref->reg_live_in[i] |= block->reg_live_out[i];
33 if (changed && !bref->mark1) {
34 list_inserttail (worklist, bref);
35 bref->mark1 = 1;
38 ref = element_next (ref);
41 sub = block->info.call.calltarget;
42 if (block->type == BLOCK_CALL && sub) {
44 for (regno = REGISTER_GPR_V0; regno <= REGISTER_GPR_V1; regno++) {
45 if (IS_BIT_SET (block->reg_live_in, regno)) {
46 sub->numregout = MAX (sub->numregout, regno - REGISTER_GPR_V0 + 1);
50 if (sub->status & SUBROUTINE_OPERATIONS_EXTRACTED) {
51 changed = FALSE;
52 for (regno = REGISTER_GPR_V0; regno <= REGISTER_GPR_V1; regno++) {
53 if (IS_BIT_SET (block->reg_live_in, regno)) {
54 changed = changed || !IS_BIT_SET (sub->endblock->reg_gen, regno);
55 BIT_SET (sub->endblock->reg_gen, regno);
58 if (changed && !sub->endblock->mark1) {
59 list_inserttail (worklist, sub->endblock);
60 sub->endblock->mark1 = 1;
65 if (block->type == BLOCK_START) {
66 sub = block->sub;
68 for (regno = REGISTER_GPR_A0; regno <= REGISTER_GPR_T3; regno++) {
69 if (IS_BIT_SET (block->reg_live_in, regno)) {
70 sub->numregargs = MAX (sub->numregargs, regno - REGISTER_GPR_A0 + 1);
74 ref = list_head (sub->whereused);
75 while (ref) {
76 bref = element_getvalue (ref);
77 changed = FALSE;
78 for (regno = REGISTER_GPR_A0; regno <= REGISTER_GPR_T3; regno++) {
79 if (IS_BIT_SET (block->reg_live_in, regno)) {
80 changed = changed || !IS_BIT_SET (bref->reg_gen, regno);
81 BIT_SET (bref->reg_gen, regno);
84 if (changed && !bref->mark1) {
85 list_inserttail (worklist, bref);
86 bref->mark1 = 1;
88 ref = element_next (ref);
94 void live_registers (struct code *c)
96 list worklist = list_alloc (c->lstpool);
97 element el = list_head (c->subroutines);
99 while (el) {
100 struct subroutine *sub = element_getvalue (el);
101 if (!sub->import && !sub->haserror) {
102 reset_marks (sub);
103 sub->status |= SUBROUTINE_LIVE_REGISTERS;
104 sub->endblock->mark1 = 1;
105 list_inserthead (worklist, sub->endblock);
107 el = element_next (el);
110 live_analysis (worklist);
111 list_free (worklist);
114 void live_registers_imports (struct code *c)
116 element el = list_head (c->subroutines);
118 while (el) {
119 struct subroutine *sub = element_getvalue (el);
120 if (sub->import && sub->numregargs == -1) {
121 element ref;
123 ref = list_head (sub->whereused);
124 while (ref) {
125 struct basicblock *block = element_getvalue (ref);
126 struct operation *op = list_tailvalue (block->operations);
127 int count = 0, maxcount = 0;
128 element opel;
130 opel = list_head (op->info.callop.arguments);
131 while (opel) {
132 struct value *val = element_getvalue (opel);
133 count++;
135 if (list_size (val->val.variable->uses) == 1 &&
136 val->val.variable->def->type != OP_START &&
137 val->val.variable->def->type != OP_CALL) {
138 if (maxcount < count) maxcount = count;
140 opel = element_next (opel);
143 if (sub->numregargs < maxcount)
144 sub->numregargs = maxcount;
146 ref = element_next (ref);
149 ref = list_head (sub->whereused);
150 while (ref) {
151 struct basicblock *block = element_getvalue (ref);
152 struct subroutine *target = block->sub;
154 target->status &= ~(SUBROUTINE_SSA | SUBROUTINE_FIXUP_CALL_ARGS);
155 ref = element_next (ref);
158 el = element_next (el);
161 el = list_head (c->subroutines);
163 while (el) {
164 struct subroutine *sub = element_getvalue (el);
165 if (!sub->import && !sub->haserror &&
166 !(sub->status & SUBROUTINE_SSA)) {
167 unbuild_ssa (sub);
168 remove_call_arguments (sub);
170 el = element_next (el);