Liveness funcionando
[pspdecompiler.git] / constants.c
blobd85912cb4222cdbdb1e8cfdf87b884cdba515e86
3 #include "code.h"
4 #include "utils.h"
6 static
7 uint32 get_constant_value (struct value *val)
9 if (val->type == VAL_VARIABLE)
10 return val->val.variable->info;
11 else
12 return val->val.intval;
15 static
16 void combine_constants (struct variable *out, struct value *val)
18 uint32 constant;
19 if (out->type == VARIABLE_UNK) return;
21 if (val->type == VAL_REGISTER) {
22 out->type = VARIABLE_UNK;
23 return;
26 if (val->type == VAL_VARIABLE) {
27 if (val->val.variable->type == VARIABLE_CONSTANTUNK)
28 return;
29 if (val->val.variable->type == VARIABLE_UNK) {
30 out->type = VARIABLE_UNK;
31 return;
35 constant = get_constant_value (val);
36 if (out->type == VARIABLE_CONSTANTUNK) {
37 out->type = VARIABLE_CONSTANT;
38 out->info = constant;
39 } else {
40 if (out->info != constant)
41 out->type = VARIABLE_UNK;
45 void propagate_constants (struct subroutine *sub)
47 list worklist = list_alloc (sub->code->lstpool);
48 element varel;
50 varel = list_head (sub->variables);
51 while (varel) {
52 struct variable *var = element_getvalue (varel);
53 var->type = VARIABLE_CONSTANTUNK;
54 if (var->def->type == OP_ASM ||
55 var->def->type == OP_CALL ||
56 var->def->type == OP_START)
57 var->type = VARIABLE_UNK;
58 else
59 list_inserttail (worklist, var);
60 varel = element_next (varel);
63 while (list_size (worklist) != 0) {
64 struct variable *var = list_removehead (worklist);
65 struct variable temp;
66 struct value *val;
67 element opel;
69 if (var->type == VARIABLE_UNK) continue;
71 if (var->def->type == OP_PHI) {
72 temp.type = VARIABLE_CONSTANTUNK;
74 opel = list_head (var->def->operands);
75 while (opel) {
76 val = element_getvalue (opel);
77 combine_constants (&temp, val);
78 opel = element_next (opel);
80 } else {
81 temp.type = VARIABLE_CONSTANT;
83 opel = list_head (var->def->operands);
84 while (opel) {
85 val = element_getvalue (opel);
86 if (val->type == VAL_CONSTANT) {
87 } else if (val->type == VAL_VARIABLE) {
88 if (val->val.variable->type == VARIABLE_UNK)
89 temp.type = VARIABLE_UNK;
90 else if (val->val.variable->type == VARIABLE_CONSTANTUNK &&
91 temp.type != VARIABLE_UNK)
92 temp.type = VARIABLE_CONSTANTUNK;
94 opel = element_next (opel);
97 if (temp.type == VARIABLE_CONSTANT) {
98 if (var->def->type == OP_MOVE) {
99 val = list_headvalue (var->def->operands);
100 temp.info = get_constant_value (val);
101 var->def->deferred = TRUE;
102 } else if (var->def->type == OP_INSTRUCTION) {
103 uint32 val1, val2;
104 switch (var->def->info.iop.insn) {
105 case I_ADD:
106 case I_ADDU:
107 val1 = get_constant_value (list_headvalue (var->def->operands));
108 val2 = get_constant_value (list_tailvalue (var->def->operands));
109 temp.info = val1 + val2;
110 var->def->deferred = TRUE;
111 break;
112 case I_OR:
113 val1 = get_constant_value (list_headvalue (var->def->operands));
114 val2 = get_constant_value (list_tailvalue (var->def->operands));
115 temp.info = val1 | val2;
116 var->def->deferred = TRUE;
117 break;
118 default:
119 temp.type = VARIABLE_UNK;
120 break;
127 if (temp.type != var->type) {
128 element useel;
129 useel = list_head (var->uses);
130 while (useel) {
131 struct operation *use = element_getvalue (useel);
132 varel = list_head (use->results);
133 while (varel) {
134 val = element_getvalue (varel);
135 if (val->type == VAL_VARIABLE)
136 list_inserttail (worklist, val->val.variable);
137 varel = element_next (varel);
139 useel = element_next (useel);
142 var->type = temp.type;
143 var->info = temp.info;
147 list_free (worklist);