30
30
#include "zend_inference.h"
31
31
#include "zend_dump.h"
32
32
33
- void optimize_dfa (zend_op_array * op_array , zend_optimizer_ctx * ctx )
33
+ int zend_dfa_analyze_op_array (zend_op_array * op_array , zend_optimizer_ctx * ctx , zend_ssa * ssa , uint32_t * flags )
34
34
{
35
- void * checkpoint ;
36
35
uint32_t build_flags ;
37
- uint32_t flags = 0 ;
38
- zend_ssa ssa ;
39
36
40
37
/* Build SSA */
41
- memset (& ssa , 0 , sizeof (ssa ));
42
- checkpoint = zend_arena_checkpoint (ctx -> arena );
38
+ memset (ssa , 0 , sizeof (zend_ssa ));
43
39
44
- if (zend_build_cfg (& ctx -> arena , op_array , 0 , & ssa .cfg , & flags ) != SUCCESS ) {
45
- zend_arena_release (& ctx -> arena , checkpoint );
46
- return ;
40
+ if (zend_build_cfg (& ctx -> arena , op_array , 0 , & ssa -> cfg , flags ) != SUCCESS ) {
41
+ return FAILURE ;
47
42
}
48
43
49
- if (flags & ZEND_FUNC_TOO_DYNAMIC ) {
50
- zend_arena_release (& ctx -> arena , checkpoint );
51
- return ;
44
+ if (* flags & ZEND_FUNC_TOO_DYNAMIC ) {
45
+ return FAILURE ;
52
46
}
53
47
54
- if (zend_cfg_build_predecessors (& ctx -> arena , & ssa .cfg ) != SUCCESS ) {
55
- zend_arena_release (& ctx -> arena , checkpoint );
56
- return ;
48
+ if (zend_cfg_build_predecessors (& ctx -> arena , & ssa -> cfg ) != SUCCESS ) {
49
+ return FAILURE ;
57
50
}
58
51
59
52
if (ctx -> debug_level & ZEND_DUMP_DFA_CFG ) {
60
- zend_dump_op_array (op_array , ZEND_DUMP_CFG | ZEND_DUMP_HIDE_UNUSED_VARS , "dfa cfg" , & ssa . cfg );
53
+ zend_dump_op_array (op_array , ZEND_DUMP_CFG | ZEND_DUMP_HIDE_UNUSED_VARS , "dfa cfg" , & ssa -> cfg );
61
54
}
62
55
63
56
/* Compute Dominators Tree */
64
- if (zend_cfg_compute_dominators_tree (op_array , & ssa .cfg ) != SUCCESS ) {
65
- zend_arena_release (& ctx -> arena , checkpoint );
66
- return ;
57
+ if (zend_cfg_compute_dominators_tree (op_array , & ssa -> cfg ) != SUCCESS ) {
58
+ return FAILURE ;
67
59
}
68
60
69
61
/* Identify reducible and irreducible loops */
70
- if (zend_cfg_identify_loops (op_array , & ssa .cfg , & flags ) != SUCCESS ) {
71
- zend_arena_release (& ctx -> arena , checkpoint );
72
- return ;
62
+ if (zend_cfg_identify_loops (op_array , & ssa -> cfg , flags ) != SUCCESS ) {
63
+ return FAILURE ;
73
64
}
74
65
75
66
if (ctx -> debug_level & ZEND_DUMP_DFA_DOMINATORS ) {
76
- zend_dump_dominators (op_array , & ssa . cfg );
67
+ zend_dump_dominators (op_array , & ssa -> cfg );
77
68
}
78
69
79
70
build_flags = 0 ;
@@ -83,45 +74,45 @@ void optimize_dfa(zend_op_array *op_array, zend_optimizer_ctx *ctx)
83
74
if (ctx -> debug_level & ZEND_DUMP_DFA_PHI ) {
84
75
build_flags |= ZEND_SSA_DEBUG_PHI_PLACEMENT ;
85
76
}
86
- if (zend_build_ssa (& ctx -> arena , op_array , build_flags , & ssa , & flags ) != SUCCESS ) {
87
- zend_arena_release (& ctx -> arena , checkpoint );
88
- return ;
77
+ if (zend_build_ssa (& ctx -> arena , op_array , build_flags , ssa , flags ) != SUCCESS ) {
78
+ return FAILURE ;
89
79
}
90
80
91
81
if (ctx -> debug_level & ZEND_DUMP_DFA_SSA ) {
92
- zend_dump_op_array (op_array , ZEND_DUMP_SSA | ZEND_DUMP_HIDE_UNUSED_VARS , "before dfa pass" , & ssa );
82
+ zend_dump_op_array (op_array , ZEND_DUMP_SSA | ZEND_DUMP_HIDE_UNUSED_VARS , "before dfa pass" , ssa );
93
83
}
94
84
95
85
96
- if (zend_ssa_compute_use_def_chains (& ctx -> arena , op_array , & ssa ) != SUCCESS ){
97
- zend_arena_release (& ctx -> arena , checkpoint );
98
- return ;
86
+ if (zend_ssa_compute_use_def_chains (& ctx -> arena , op_array , ssa ) != SUCCESS ){
87
+ return FAILURE ;
99
88
}
100
89
101
- if (zend_ssa_find_false_dependencies (op_array , & ssa ) != SUCCESS ) {
102
- zend_arena_release (& ctx -> arena , checkpoint );
103
- return ;
90
+ if (zend_ssa_find_false_dependencies (op_array , ssa ) != SUCCESS ) {
91
+ return FAILURE ;
104
92
}
105
93
106
- if (zend_ssa_find_sccs (op_array , & ssa ) != SUCCESS ){
107
- zend_arena_release (& ctx -> arena , checkpoint );
108
- return ;
94
+ if (zend_ssa_find_sccs (op_array , ssa ) != SUCCESS ){
95
+ return FAILURE ;
109
96
}
110
97
111
- if (zend_ssa_inference (& ctx -> arena , op_array , ctx -> script , & ssa ) != SUCCESS ) {
112
- return ;
98
+ if (zend_ssa_inference (& ctx -> arena , op_array , ctx -> script , ssa ) != SUCCESS ) {
99
+ return FAILURE ;
113
100
}
114
101
115
102
if (ctx -> debug_level & ZEND_DUMP_DFA_SSA_VARS ) {
116
- zend_dump_ssa_variables (op_array , & ssa );
103
+ zend_dump_ssa_variables (op_array , ssa );
117
104
}
118
105
106
+ return SUCCESS ;
107
+ }
108
+
109
+ void zend_dfa_optimize_op_array (zend_op_array * op_array , zend_optimizer_ctx * ctx , zend_ssa * ssa )
110
+ {
119
111
if (ctx -> debug_level & ZEND_DUMP_BEFORE_DFA_PASS ) {
120
- zend_dump_op_array (op_array , ZEND_DUMP_SSA | ZEND_DUMP_HIDE_UNUSED_VARS , "before dfa pass" , & ssa );
112
+ zend_dump_op_array (op_array , ZEND_DUMP_SSA | ZEND_DUMP_HIDE_UNUSED_VARS , "before dfa pass" , ssa );
121
113
}
122
114
123
- //TODO: Add optimization patterns ???
124
- if (ssa .var_info ) {
115
+ if (ssa -> var_info ) {
125
116
int i ;
126
117
int remove_nops = 0 ;
127
118
@@ -132,48 +123,48 @@ void optimize_dfa(zend_op_array *op_array, zend_optimizer_ctx *ctx)
132
123
// --
133
124
// 2: ASSIGN #2.CV [undef,scalar] -> #3.CV, #1.CV | 3.CV = QM_ASSIGN #1.CV
134
125
135
- for (i = 0 ; i < ssa . vars_count ; i ++ ) {
136
- int op2 = ssa . vars [i ].definition ;
126
+ for (i = 0 ; i < ssa -> vars_count ; i ++ ) {
127
+ int op2 = ssa -> vars [i ].definition ;
137
128
138
129
if (op2 >= 0
139
130
&& op_array -> opcodes [op2 ].opcode == ZEND_ASSIGN
140
131
&& op_array -> opcodes [op2 ].op1_type == IS_CV
141
132
&& !RETURN_VALUE_USED (& op_array -> opcodes [op2 ])
142
133
) {
143
- int var2 = ssa . ops [op2 ].op1_use ;
134
+ int var2 = ssa -> ops [op2 ].op1_use ;
144
135
145
136
if (var2 >= 0
146
- && !(ssa . var_info [var2 ].type & (MAY_BE_STRING |MAY_BE_ARRAY |MAY_BE_OBJECT |MAY_BE_RESOURCE |MAY_BE_REF ))
137
+ && !(ssa -> var_info [var2 ].type & (MAY_BE_STRING |MAY_BE_ARRAY |MAY_BE_OBJECT |MAY_BE_RESOURCE |MAY_BE_REF ))
147
138
) {
148
139
149
140
if (op_array -> opcodes [op2 ].op2_type & (IS_TMP_VAR |IS_VAR )) {
150
- int var1 = ssa . ops [op2 ].op2_use ;
141
+ int var1 = ssa -> ops [op2 ].op2_use ;
151
142
152
143
if (var1 >= 0
153
- && !(ssa . var_info [var1 ].type & MAY_BE_REF )
154
- && ssa . vars [var1 ].definition >= 0
155
- && ssa . ops [ssa . vars [var1 ].definition ].result_def == var1
156
- && ssa . ops [ssa . vars [var1 ].definition ].result_use < 0
157
- && ssa . vars [var1 ].use_chain == op2
158
- && ssa . ops [op2 ].op2_use_chain < 0
159
- && !ssa . vars [var1 ].phi_use_chain
160
- && !ssa . vars [var1 ].sym_use_chain
144
+ && !(ssa -> var_info [var1 ].type & MAY_BE_REF )
145
+ && ssa -> vars [var1 ].definition >= 0
146
+ && ssa -> ops [ssa -> vars [var1 ].definition ].result_def == var1
147
+ && ssa -> ops [ssa -> vars [var1 ].definition ].result_use < 0
148
+ && ssa -> vars [var1 ].use_chain == op2
149
+ && ssa -> ops [op2 ].op2_use_chain < 0
150
+ && !ssa -> vars [var1 ].phi_use_chain
151
+ && !ssa -> vars [var1 ].sym_use_chain
161
152
) {
162
- int op1 = ssa . vars [var1 ].definition ;
153
+ int op1 = ssa -> vars [var1 ].definition ;
163
154
int var3 = i ;
164
155
165
- if (zend_ssa_unlink_use_chain (& ssa , op2 , var2 )) {
156
+ if (zend_ssa_unlink_use_chain (ssa , op2 , var2 )) {
166
157
/* Reconstruct SSA */
167
- ssa . vars [var3 ].definition = op1 ;
168
- ssa . ops [op1 ].result_def = var3 ;
158
+ ssa -> vars [var3 ].definition = op1 ;
159
+ ssa -> ops [op1 ].result_def = var3 ;
169
160
170
- ssa . vars [var1 ].definition = -1 ;
171
- ssa . vars [var1 ].use_chain = -1 ;
161
+ ssa -> vars [var1 ].definition = -1 ;
162
+ ssa -> vars [var1 ].use_chain = -1 ;
172
163
173
- ssa . ops [op2 ].op1_use = -1 ;
174
- ssa . ops [op2 ].op2_use = -1 ;
175
- ssa . ops [op2 ].op1_def = -1 ;
176
- ssa . ops [op2 ].op1_use_chain = -1 ;
164
+ ssa -> ops [op2 ].op1_use = -1 ;
165
+ ssa -> ops [op2 ].op2_use = -1 ;
166
+ ssa -> ops [op2 ].op1_def = -1 ;
167
+ ssa -> ops [op2 ].op1_use_chain = -1 ;
177
168
178
169
/* Update opcodes */
179
170
op_array -> opcodes [op1 ].result_type = op_array -> opcodes [op2 ].op1_type ;
@@ -184,20 +175,20 @@ void optimize_dfa(zend_op_array *op_array, zend_optimizer_ctx *ctx)
184
175
}
185
176
} else if (op_array -> opcodes [op2 ].op2_type == IS_CONST
186
177
|| (op_array -> opcodes [op2 ].op2_type == IS_CV
187
- && ssa . ops [op2 ].op2_use >= 0
188
- && ssa . ops [op2 ].op2_def < 0
189
- && !(ssa . var_info [ssa . ops [op2 ].op2_use ].type & MAY_BE_REF ))
178
+ && ssa -> ops [op2 ].op2_use >= 0
179
+ && ssa -> ops [op2 ].op2_def < 0
180
+ && !(ssa -> var_info [ssa -> ops [op2 ].op2_use ].type & MAY_BE_REF ))
190
181
) {
191
182
int var3 = i ;
192
183
193
- if (zend_ssa_unlink_use_chain (& ssa , op2 , var2 )) {
184
+ if (zend_ssa_unlink_use_chain (ssa , op2 , var2 )) {
194
185
/* Reconstruct SSA */
195
- ssa . ops [op2 ].result_def = var3 ;
196
- ssa . ops [op2 ].op1_def = -1 ;
197
- ssa . ops [op2 ].op1_use = ssa . ops [op2 ].op2_use ;
198
- ssa . ops [op2 ].op1_use_chain = ssa . ops [op2 ].op2_use_chain ;
199
- ssa . ops [op2 ].op2_use = -1 ;
200
- ssa . ops [op2 ].op2_use_chain = -1 ;
186
+ ssa -> ops [op2 ].result_def = var3 ;
187
+ ssa -> ops [op2 ].op1_def = -1 ;
188
+ ssa -> ops [op2 ].op1_use = ssa -> ops [op2 ].op2_use ;
189
+ ssa -> ops [op2 ].op1_use_chain = ssa -> ops [op2 ].op2_use_chain ;
190
+ ssa -> ops [op2 ].op2_use = -1 ;
191
+ ssa -> ops [op2 ].op2_use_chain = -1 ;
201
192
202
193
/* Update opcode */
203
194
op_array -> opcodes [op2 ].result_type = op_array -> opcodes [op2 ].op1_type ;
@@ -217,11 +208,24 @@ void optimize_dfa(zend_op_array *op_array, zend_optimizer_ctx *ctx)
217
208
}
218
209
}
219
210
220
-
221
211
if (ctx -> debug_level & ZEND_DUMP_AFTER_DFA_PASS ) {
222
- zend_dump_op_array (op_array , ZEND_DUMP_SSA | ZEND_DUMP_HIDE_UNUSED_VARS , "after dfa pass" , & ssa );
212
+ zend_dump_op_array (op_array , ZEND_DUMP_SSA | ZEND_DUMP_HIDE_UNUSED_VARS , "after dfa pass" , ssa );
213
+ }
214
+ }
215
+
216
+ void optimize_dfa (zend_op_array * op_array , zend_optimizer_ctx * ctx )
217
+ {
218
+ void * checkpoint = zend_arena_checkpoint (ctx -> arena );
219
+ uint32_t flags = 0 ;
220
+ zend_ssa ssa ;
221
+
222
+ if (zend_dfa_analyze_op_array (op_array , ctx , & ssa , & flags ) != SUCCESS ) {
223
+ zend_arena_release (& ctx -> arena , checkpoint );
224
+ return ;
223
225
}
224
226
227
+ zend_dfa_optimize_op_array (op_array , ctx , & ssa );
228
+
225
229
/* Destroy SSA */
226
230
zend_arena_release (& ctx -> arena , checkpoint );
227
231
}
0 commit comments