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
);
78 op
->status
&= ~OP_STAT_CONSTANT
;
80 if (CONST_TYPE (var
->status
) == VAR_STAT_NOTCONSTANT
) continue;
82 if (op
->type
== OP_PHI
) {
83 temp
.status
= VAR_STAT_UNKCONSTANT
;
85 opel
= list_head (op
->operands
);
87 val
= element_getvalue (opel
);
88 combine_constants (&temp
, val
);
89 opel
= element_next (opel
);
92 temp
.status
= VAR_STAT_CONSTANT
;
94 opel
= list_head (op
->operands
);
96 val
= element_getvalue (opel
);
97 if (val
->type
== VAL_SSAVAR
) {
98 aux
= val
->val
.variable
;
99 if (CONST_TYPE (aux
->status
) == VAR_STAT_NOTCONSTANT
) {
100 temp
.status
= VAR_STAT_NOTCONSTANT
;
102 } else if (CONST_TYPE (aux
->status
) == VAR_STAT_UNKCONSTANT
)
103 temp
.status
= VAR_STAT_UNKCONSTANT
;
105 opel
= element_next (opel
);
108 if (temp
.status
== VAR_STAT_CONSTANT
) {
109 if (op
->type
== OP_MOVE
) {
110 val
= list_headvalue (op
->operands
);
111 temp
.value
= get_constant_value (val
);
112 op
->status
|= OP_STAT_CONSTANT
;
113 } else if (op
->type
== OP_INSTRUCTION
) {
115 switch (op
->info
.iop
.insn
) {
118 val1
= get_constant_value (list_headvalue (op
->operands
));
119 val2
= get_constant_value (list_tailvalue (op
->operands
));
120 op
->status
|= OP_STAT_CONSTANT
;
121 temp
.value
= val1
+ val2
;
124 val1
= get_constant_value (list_headvalue (op
->operands
));
125 val2
= get_constant_value (list_tailvalue (op
->operands
));
126 op
->status
|= OP_STAT_CONSTANT
;
127 temp
.value
= val1
| val2
;
130 temp
.status
= VAR_STAT_NOTCONSTANT
;
137 if (temp
.status
!= CONST_TYPE (var
->status
)) {
139 useel
= list_head (var
->uses
);
141 struct operation
*use
= element_getvalue (useel
);
142 if (use
->type
== OP_INSTRUCTION
|| use
->type
== OP_MOVE
|| use
->type
== OP_PHI
) {
143 varel
= list_head (use
->results
);
145 val
= element_getvalue (varel
);
146 if (val
->type
== VAL_SSAVAR
) {
147 aux
= val
->val
.variable
;
150 list_inserttail (worklist
, aux
);
153 varel
= element_next (varel
);
156 useel
= element_next (useel
);
159 CONST_SETTYPE (var
->status
, temp
.status
);
160 var
->value
= temp
.value
;
163 list_free (worklist
);
166 varel
= list_head (sub
->ssavars
);
168 struct ssavar
*var
= element_getvalue (varel
);
169 struct operation
*op
= var
->def
;
172 if (CONST_TYPE (var
->status
) == VAR_STAT_CONSTANT
) {
173 op
->status
|= OP_STAT_DEFERRED
;
174 useel
= list_head (var
->uses
);
176 struct operation
*use
= element_getvalue (useel
);
177 if (use
->type
== OP_PHI
) {
178 struct value
*val
= list_headvalue (use
->results
);
179 if (val
->type
!= VAL_SSAVAR
) break;
180 if (CONST_TYPE (val
->val
.variable
->status
) != VAR_STAT_CONSTANT
)
182 } else if (use
->type
== OP_ASM
) break;
183 useel
= element_next (useel
);
186 op
->status
&= ~OP_STAT_DEFERRED
;
190 varel
= element_next (varel
);