|
52 | 52 | #define DEBUG_PRINT(...)
|
53 | 53 | #endif
|
54 | 54 |
|
55 |
| -void scdf_mark_edge_feasible(scdf_ctx *ctx, int from, int to) { |
56 |
| - uint32_t edge = scdf_edge(&ctx->ssa->cfg, from, to); |
| 55 | +void scdf_mark_edge_feasible(scdf_ctx *scdf, int from, int to) { |
| 56 | + uint32_t edge = scdf_edge(&scdf->ssa->cfg, from, to); |
57 | 57 |
|
58 |
| - if (zend_bitset_in(ctx->feasible_edges, edge)) { |
| 58 | + if (zend_bitset_in(scdf->feasible_edges, edge)) { |
59 | 59 | /* We already handled this edge */
|
60 | 60 | return;
|
61 | 61 | }
|
62 | 62 |
|
63 | 63 | DEBUG_PRINT("Marking edge %d->%d feasible\n", from, to);
|
64 |
| - zend_bitset_incl(ctx->feasible_edges, edge); |
| 64 | + zend_bitset_incl(scdf->feasible_edges, edge); |
65 | 65 |
|
66 |
| - if (!zend_bitset_in(ctx->executable_blocks, to)) { |
67 |
| - if (!zend_bitset_in(ctx->block_worklist, to)) { |
| 66 | + if (!zend_bitset_in(scdf->executable_blocks, to)) { |
| 67 | + if (!zend_bitset_in(scdf->block_worklist, to)) { |
68 | 68 | DEBUG_PRINT("Adding block %d to worklist\n", to);
|
69 | 69 | }
|
70 |
| - zend_bitset_incl(ctx->block_worklist, to); |
| 70 | + zend_bitset_incl(scdf->block_worklist, to); |
71 | 71 | } else {
|
72 | 72 | /* Block is already executable, only a new edge became feasible.
|
73 | 73 | * Reevaluate phi nodes to account for changed source operands. */
|
74 |
| - zend_ssa_block *ssa_block = &ctx->ssa->blocks[to]; |
| 74 | + zend_ssa_block *ssa_block = &scdf->ssa->blocks[to]; |
75 | 75 | zend_ssa_phi *phi;
|
76 | 76 | for (phi = ssa_block->phis; phi; phi = phi->next) {
|
77 |
| - zend_bitset_excl(ctx->phi_var_worklist, phi->ssa_var); |
78 |
| - ctx->handlers.visit_phi(ctx, phi); |
| 77 | + zend_bitset_excl(scdf->phi_var_worklist, phi->ssa_var); |
| 78 | + scdf->handlers.visit_phi(scdf, phi); |
79 | 79 | }
|
80 | 80 | }
|
81 | 81 | }
|
82 | 82 |
|
83 |
| -void scdf_init(scdf_ctx *ctx, zend_op_array *op_array, zend_ssa *ssa) { |
| 83 | +void scdf_init(zend_optimizer_ctx *ctx, scdf_ctx *scdf, zend_op_array *op_array, zend_ssa *ssa) { |
84 | 84 | uint32_t edges_count = 0;
|
85 | 85 | int b;
|
86 | 86 |
|
87 | 87 | for (b = 0; b < ssa->cfg.blocks_count; b++) {
|
88 | 88 | edges_count += ssa->cfg.blocks[b].predecessors_count;
|
89 | 89 | }
|
90 | 90 |
|
91 |
| - ctx->op_array = op_array; |
92 |
| - ctx->ssa = ssa; |
| 91 | + scdf->op_array = op_array; |
| 92 | + scdf->ssa = ssa; |
93 | 93 |
|
94 |
| - ctx->instr_worklist_len = zend_bitset_len(op_array->last); |
95 |
| - ctx->phi_var_worklist_len = zend_bitset_len(ssa->vars_count); |
96 |
| - ctx->block_worklist_len = zend_bitset_len(ssa->cfg.blocks_count); |
| 94 | + scdf->instr_worklist_len = zend_bitset_len(op_array->last); |
| 95 | + scdf->phi_var_worklist_len = zend_bitset_len(ssa->vars_count); |
| 96 | + scdf->block_worklist_len = zend_bitset_len(ssa->cfg.blocks_count); |
97 | 97 |
|
98 |
| - ctx->instr_worklist = ecalloc( |
99 |
| - ctx->instr_worklist_len + ctx->phi_var_worklist_len + 2 * ctx->block_worklist_len + zend_bitset_len(edges_count), |
| 98 | + scdf->instr_worklist = zend_arena_calloc(&ctx->arena, |
| 99 | + scdf->instr_worklist_len + scdf->phi_var_worklist_len + 2 * scdf->block_worklist_len + zend_bitset_len(edges_count), |
100 | 100 | sizeof(zend_ulong));
|
101 | 101 |
|
102 |
| - ctx->phi_var_worklist = ctx->instr_worklist + ctx->instr_worklist_len; |
103 |
| - ctx->block_worklist = ctx->phi_var_worklist + ctx->phi_var_worklist_len; |
104 |
| - ctx->executable_blocks = ctx->block_worklist + ctx->block_worklist_len; |
105 |
| - ctx->feasible_edges = ctx->executable_blocks + ctx->block_worklist_len; |
| 102 | + scdf->phi_var_worklist = scdf->instr_worklist + scdf->instr_worklist_len; |
| 103 | + scdf->block_worklist = scdf->phi_var_worklist + scdf->phi_var_worklist_len; |
| 104 | + scdf->executable_blocks = scdf->block_worklist + scdf->block_worklist_len; |
| 105 | + scdf->feasible_edges = scdf->executable_blocks + scdf->block_worklist_len; |
106 | 106 |
|
107 |
| - zend_bitset_incl(ctx->block_worklist, 0); |
108 |
| - zend_bitset_incl(ctx->executable_blocks, 0); |
| 107 | + zend_bitset_incl(scdf->block_worklist, 0); |
| 108 | + zend_bitset_incl(scdf->executable_blocks, 0); |
109 | 109 | }
|
110 | 110 |
|
111 |
| -void scdf_free(scdf_ctx *ctx) { |
112 |
| - efree(ctx->instr_worklist); |
113 |
| -} |
114 |
| - |
115 |
| -void scdf_solve(scdf_ctx *ctx, const char *name) { |
116 |
| - zend_ssa *ssa = ctx->ssa; |
| 111 | +void scdf_solve(scdf_ctx *scdf, const char *name) { |
| 112 | + zend_ssa *ssa = scdf->ssa; |
117 | 113 | DEBUG_PRINT("Start SCDF solve (%s)\n", name);
|
118 |
| - while (!zend_bitset_empty(ctx->instr_worklist, ctx->instr_worklist_len) |
119 |
| - || !zend_bitset_empty(ctx->phi_var_worklist, ctx->phi_var_worklist_len) |
120 |
| - || !zend_bitset_empty(ctx->block_worklist, ctx->block_worklist_len) |
| 114 | + while (!zend_bitset_empty(scdf->instr_worklist, scdf->instr_worklist_len) |
| 115 | + || !zend_bitset_empty(scdf->phi_var_worklist, scdf->phi_var_worklist_len) |
| 116 | + || !zend_bitset_empty(scdf->block_worklist, scdf->block_worklist_len) |
121 | 117 | ) {
|
122 | 118 | int i;
|
123 |
| - while ((i = zend_bitset_pop_first(ctx->phi_var_worklist, ctx->phi_var_worklist_len)) >= 0) { |
| 119 | + while ((i = zend_bitset_pop_first(scdf->phi_var_worklist, scdf->phi_var_worklist_len)) >= 0) { |
124 | 120 | zend_ssa_phi *phi = ssa->vars[i].definition_phi;
|
125 | 121 | ZEND_ASSERT(phi);
|
126 |
| - if (zend_bitset_in(ctx->executable_blocks, phi->block)) { |
127 |
| - ctx->handlers.visit_phi(ctx, phi); |
| 122 | + if (zend_bitset_in(scdf->executable_blocks, phi->block)) { |
| 123 | + scdf->handlers.visit_phi(scdf, phi); |
128 | 124 | }
|
129 | 125 | }
|
130 | 126 |
|
131 |
| - while ((i = zend_bitset_pop_first(ctx->instr_worklist, ctx->instr_worklist_len)) >= 0) { |
| 127 | + while ((i = zend_bitset_pop_first(scdf->instr_worklist, scdf->instr_worklist_len)) >= 0) { |
132 | 128 | int block_num = ssa->cfg.map[i];
|
133 |
| - if (zend_bitset_in(ctx->executable_blocks, block_num)) { |
| 129 | + if (zend_bitset_in(scdf->executable_blocks, block_num)) { |
134 | 130 | zend_basic_block *block = &ssa->cfg.blocks[block_num];
|
135 |
| - zend_op *opline = &ctx->op_array->opcodes[i]; |
| 131 | + zend_op *opline = &scdf->op_array->opcodes[i]; |
136 | 132 | zend_ssa_op *ssa_op = &ssa->ops[i];
|
137 | 133 | if (opline->opcode == ZEND_OP_DATA) {
|
138 | 134 | opline--;
|
139 | 135 | ssa_op--;
|
140 | 136 | }
|
141 |
| - ctx->handlers.visit_instr(ctx, opline, ssa_op); |
| 137 | + scdf->handlers.visit_instr(scdf, opline, ssa_op); |
142 | 138 | if (i == block->start + block->len - 1) {
|
143 | 139 | if (block->successors_count == 1) {
|
144 |
| - scdf_mark_edge_feasible(ctx, block_num, block->successors[0]); |
| 140 | + scdf_mark_edge_feasible(scdf, block_num, block->successors[0]); |
145 | 141 | } else if (block->successors_count > 1) {
|
146 |
| - ctx->handlers.mark_feasible_successors(ctx, block_num, block, opline, ssa_op); |
| 142 | + scdf->handlers.mark_feasible_successors(scdf, block_num, block, opline, ssa_op); |
147 | 143 | }
|
148 | 144 | }
|
149 | 145 | }
|
150 | 146 | }
|
151 | 147 |
|
152 |
| - while ((i = zend_bitset_pop_first(ctx->block_worklist, ctx->block_worklist_len)) >= 0) { |
| 148 | + while ((i = zend_bitset_pop_first(scdf->block_worklist, scdf->block_worklist_len)) >= 0) { |
153 | 149 | /* This block is now live. Interpret phis and instructions in it. */
|
154 | 150 | zend_basic_block *block = &ssa->cfg.blocks[i];
|
155 | 151 | zend_ssa_block *ssa_block = &ssa->blocks[i];
|
156 | 152 |
|
157 | 153 | DEBUG_PRINT("Pop block %d from worklist\n", i);
|
158 |
| - zend_bitset_incl(ctx->executable_blocks, i); |
| 154 | + zend_bitset_incl(scdf->executable_blocks, i); |
159 | 155 |
|
160 | 156 | {
|
161 | 157 | zend_ssa_phi *phi;
|
162 | 158 | for (phi = ssa_block->phis; phi; phi = phi->next) {
|
163 |
| - zend_bitset_excl(ctx->phi_var_worklist, phi->ssa_var); |
164 |
| - ctx->handlers.visit_phi(ctx, phi); |
| 159 | + zend_bitset_excl(scdf->phi_var_worklist, phi->ssa_var); |
| 160 | + scdf->handlers.visit_phi(scdf, phi); |
165 | 161 | }
|
166 | 162 | }
|
167 | 163 |
|
168 | 164 | if (block->len == 0) {
|
169 | 165 | /* Zero length blocks don't have a last instruction that would normally do this */
|
170 |
| - scdf_mark_edge_feasible(ctx, i, block->successors[0]); |
| 166 | + scdf_mark_edge_feasible(scdf, i, block->successors[0]); |
171 | 167 | } else {
|
172 | 168 | zend_op *opline;
|
173 | 169 | int j, end = block->start + block->len;
|
174 | 170 | for (j = block->start; j < end; j++) {
|
175 |
| - opline = &ctx->op_array->opcodes[j]; |
176 |
| - zend_bitset_excl(ctx->instr_worklist, j); |
| 171 | + opline = &scdf->op_array->opcodes[j]; |
| 172 | + zend_bitset_excl(scdf->instr_worklist, j); |
177 | 173 | if (opline->opcode != ZEND_OP_DATA) {
|
178 |
| - ctx->handlers.visit_instr(ctx, opline, &ssa->ops[j]); |
| 174 | + scdf->handlers.visit_instr(scdf, opline, &ssa->ops[j]); |
179 | 175 | }
|
180 | 176 | }
|
181 | 177 | if (block->successors_count == 1) {
|
182 |
| - scdf_mark_edge_feasible(ctx, i, block->successors[0]); |
| 178 | + scdf_mark_edge_feasible(scdf, i, block->successors[0]); |
183 | 179 | } else if (block->successors_count > 1) {
|
184 | 180 | if (opline->opcode == ZEND_OP_DATA) {
|
185 | 181 | opline--;
|
186 | 182 | j--;
|
187 | 183 | }
|
188 |
| - ctx->handlers.mark_feasible_successors(ctx, i, block, opline, &ssa->ops[j-1]); |
| 184 | + scdf->handlers.mark_feasible_successors(scdf, i, block, opline, &ssa->ops[j-1]); |
189 | 185 | }
|
190 | 186 | }
|
191 | 187 | }
|
|
0 commit comments