2 * Author: Humberto Naves (hsnaves@gmail.com)
10 uint32
get_constant_value (struct value
*val
)
12 if (val
->type
== VAL_SSAVAR
)
13 return val
->val
.variable
->value
;
15 return val
->val
.intval
;
19 void combine_constants (struct ssavar
*out
, struct value
*val
)
22 if (CONST_TYPE (out
->status
) == VAR_STAT_NOTCONSTANT
) return;
24 if (val
->type
== VAL_REGISTER
) {
25 CONST_SETTYPE (out
->status
, VAR_STAT_NOTCONSTANT
);
28 if (val
->type
== VAL_SSAVAR
) {
29 if (CONST_TYPE (val
->val
.variable
->status
) == VAR_STAT_UNKCONSTANT
)
31 if (CONST_TYPE (val
->val
.variable
->status
) == VAR_STAT_NOTCONSTANT
) {
32 CONST_SETTYPE (out
->status
, VAR_STAT_NOTCONSTANT
);
37 constant
= get_constant_value (val
);
38 if (CONST_TYPE (out
->status
) == VAR_STAT_UNKCONSTANT
) {
39 CONST_SETTYPE (out
->status
, VAR_STAT_CONSTANT
);
40 out
->value
= constant
;
42 if (out
->value
!= constant
)
43 CONST_SETTYPE (out
->status
, VAR_STAT_NOTCONSTANT
);
47 void propagate_constants (struct subroutine
*sub
)
49 list worklist
= list_alloc (sub
->code
->lstpool
);
52 varel
= list_head (sub
->ssavars
);
54 struct ssavar
*var
= element_getvalue (varel
);
55 struct operation
*op
= var
->def
;
56 CONST_SETTYPE (var
->status
, VAR_STAT_UNKCONSTANT
);
57 if (op
->type
== OP_ASM
||
58 op
->type
== OP_CALL
||
59 op
->type
== OP_START
||
60 !(IS_BIT_SET (regmask_localvars
, var
->name
.val
.intval
)))
61 CONST_SETTYPE (var
->status
, VAR_STAT_NOTCONSTANT
);
64 list_inserttail (worklist
, var
);
66 varel
= element_next (varel
);
69 while (list_size (worklist
) != 0) {
70 struct ssavar
*aux
, *var
= list_removehead (worklist
);
77 if (CONST_TYPE (var
->status
) == VAR_STAT_NOTCONSTANT
) continue;
80 if (op
->type
== OP_PHI
) {
81 temp
.status
= VAR_STAT_UNKCONSTANT
;
83 opel
= list_head (op
->operands
);
85 val
= element_getvalue (opel
);
86 combine_constants (&temp
, val
);
87 opel
= element_next (opel
);
90 temp
.status
= VAR_STAT_CONSTANT
;
92 opel
= list_head (op
->operands
);
94 val
= element_getvalue (opel
);
95 if (val
->type
== VAL_SSAVAR
) {
96 aux
= val
->val
.variable
;
97 if (CONST_TYPE (aux
->status
) == VAR_STAT_NOTCONSTANT
) {
98 temp
.status
= VAR_STAT_NOTCONSTANT
;
100 } else if (CONST_TYPE (aux
->status
) == VAR_STAT_UNKCONSTANT
)
101 temp
.status
= VAR_STAT_UNKCONSTANT
;
103 opel
= element_next (opel
);
106 if (temp
.status
== VAR_STAT_CONSTANT
) {
107 if (op
->type
== OP_MOVE
) {
108 val
= list_headvalue (op
->operands
);
109 temp
.value
= get_constant_value (val
);
110 op
->status
|= OP_STAT_CONSTANT
;
111 } else if (op
->type
== OP_INSTRUCTION
) {
113 switch (op
->info
.iop
.insn
) {
116 val1
= get_constant_value (list_headvalue (op
->operands
));
117 val2
= get_constant_value (list_tailvalue (op
->operands
));
118 op
->status
|= OP_STAT_CONSTANT
;
119 temp
.value
= val1
+ val2
;
122 val1
= get_constant_value (list_headvalue (op
->operands
));
123 val2
= get_constant_value (list_tailvalue (op
->operands
));
124 op
->status
|= OP_STAT_CONSTANT
;
125 temp
.value
= val1
| val2
;
128 temp
.status
= VAR_STAT_NOTCONSTANT
;
136 if (temp
.status
!= CONST_TYPE (var
->status
)) {
138 useel
= list_head (var
->uses
);
140 struct operation
*use
= element_getvalue (useel
);
141 if (use
->type
== OP_INSTRUCTION
|| use
->type
== OP_MOVE
|| use
->type
== OP_PHI
) {
142 varel
= list_head (use
->results
);
144 val
= element_getvalue (varel
);
145 if (val
->type
== VAL_SSAVAR
) {
146 aux
= val
->val
.variable
;
149 list_inserttail (worklist
, aux
);
152 varel
= element_next (varel
);
155 useel
= element_next (useel
);
158 CONST_SETTYPE (var
->status
, temp
.status
);
159 var
->value
= temp
.value
;
162 list_free (worklist
);
165 varel
= list_head (sub
->ssavars
);
167 struct ssavar
*var
= element_getvalue (varel
);
168 struct operation
*op
= var
->def
;
171 if (CONST_TYPE (var
->status
) == VAR_STAT_CONSTANT
) {
172 op
->status
|= OP_STAT_DEFERRED
;
173 useel
= list_head (var
->uses
);
175 struct operation
*use
= element_getvalue (useel
);
176 if (use
->type
== OP_PHI
) {
177 struct value
*val
= list_headvalue (use
->results
);
178 if (val
->type
!= VAL_SSAVAR
) break;
179 if (CONST_TYPE (val
->val
.variable
->status
) != VAR_STAT_CONSTANT
)
181 } else if (use
->type
== OP_ASM
) break;
182 useel
= element_next (useel
);
185 op
->status
&= ~OP_STAT_DEFERRED
;
189 varel
= element_next (varel
);