Skip to content

Commit e0ad5dd

Browse files
committed
Changed representation of "feasible_edges", using one bit per edge.
1 parent afee313 commit e0ad5dd

File tree

2 files changed

+36
-56
lines changed

2 files changed

+36
-56
lines changed

ext/opcache/Optimizer/scdf.c

Lines changed: 21 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -52,30 +52,17 @@
5252
#define DEBUG_PRINT(...)
5353
#endif
5454

55-
static void mark_edge_feasible(scdf_ctx *ctx, int from, const int *to_ptr, int suc_num) {
56-
int to = *to_ptr;
57-
if (suc_num < 2) {
58-
int edge = from * 2 + suc_num;
59-
if (zend_bitset_in(ctx->feasible_edges, edge)) {
60-
/* We already handled this edge */
61-
return;
62-
}
55+
static void mark_edge_feasible(scdf_ctx *ctx, int from, int to) {
56+
uint32_t edge = scdf_edge(&ctx->ssa->cfg, from, to);
6357

64-
DEBUG_PRINT("Marking edge %d->%d (successor %d) feasible\n", from, to, suc_num);
65-
zend_bitset_incl(ctx->feasible_edges, edge);
66-
} else {
67-
if (!ctx->feasible_edges_ht) {
68-
ALLOC_HASHTABLE(ctx->feasible_edges_ht);
69-
zend_hash_init(ctx->feasible_edges_ht, 0, NULL, NULL, 0);
70-
}
71-
if (!zend_hash_index_add_empty_element(
72-
ctx->feasible_edges_ht, (zend_long) (intptr_t) to_ptr)) {
73-
/* We already handled this edge */
74-
return;
75-
}
76-
DEBUG_PRINT("Marking edge %d->%d (successor %d) feasible\n", from, to, suc_num);
58+
if (zend_bitset_in(ctx->feasible_edges, edge)) {
59+
/* We already handled this edge */
60+
return;
7761
}
7862

63+
DEBUG_PRINT("Marking edge %d->%d feasible\n", from, to);
64+
zend_bitset_incl(ctx->feasible_edges, edge);
65+
7966
if (!zend_bitset_in(ctx->executable_blocks, to)) {
8067
if (!zend_bitset_in(ctx->block_worklist, to)) {
8168
DEBUG_PRINT("Adding block %d to worklist\n", to);
@@ -120,24 +107,29 @@ static void handle_instr(scdf_ctx *ctx, int block_num, zend_op *opline, zend_ssa
120107
// TODO For now consider all edges feasible
121108
int s;
122109
for (s = 0; s < block->successors_count; s++) {
123-
mark_edge_feasible(ctx, block_num, &block->successors[s], s);
110+
mark_edge_feasible(ctx, block_num, block->successors[s]);
124111
}
125112
} else {
126113
zend_bool suc[2] = {0};
127114
if (get_feasible_successors(ctx, block, opline, ssa_op, suc)) {
128115
if (suc[0]) {
129-
mark_edge_feasible(ctx, block_num, &block->successors[0], 0);
116+
mark_edge_feasible(ctx, block_num, block->successors[0]);
130117
}
131118
if (suc[1]) {
132-
mark_edge_feasible(ctx, block_num, &block->successors[1], 1);
119+
mark_edge_feasible(ctx, block_num, block->successors[1]);
133120
}
134121
}
135122
}
136123
}
137124
}
138125

139126
void scdf_init(scdf_ctx *ctx, zend_op_array *op_array, zend_ssa *ssa, void *extra_ctx) {
140-
zend_ulong *bitsets;
127+
uint32_t edges_count = 0;
128+
int b;
129+
130+
for (b = 0; b < ssa->cfg.blocks_count; b++) {
131+
edges_count += ssa->cfg.blocks[b].predecessors_count;
132+
}
141133

142134
ctx->op_array = op_array;
143135
ctx->ssa = ssa;
@@ -147,32 +139,20 @@ void scdf_init(scdf_ctx *ctx, zend_op_array *op_array, zend_ssa *ssa, void *extr
147139
ctx->phi_var_worklist_len = zend_bitset_len(ssa->vars_count);
148140
ctx->block_worklist_len = zend_bitset_len(ssa->cfg.blocks_count);
149141

150-
bitsets = safe_emalloc(
151-
ctx->instr_worklist_len + ctx->phi_var_worklist_len + 4 * ctx->block_worklist_len,
152-
sizeof(zend_ulong), 0);
142+
ctx->instr_worklist = ecalloc(
143+
ctx->instr_worklist_len + ctx->phi_var_worklist_len + 2 * ctx->block_worklist_len + zend_bitset_len(edges_count),
144+
sizeof(zend_ulong));
153145

154-
ctx->instr_worklist = bitsets;
155146
ctx->phi_var_worklist = ctx->instr_worklist + ctx->instr_worklist_len;
156147
ctx->block_worklist = ctx->phi_var_worklist + ctx->phi_var_worklist_len;
157148
ctx->executable_blocks = ctx->block_worklist + ctx->block_worklist_len;
158149
ctx->feasible_edges = ctx->executable_blocks + ctx->block_worklist_len;
159-
ctx->feasible_edges_ht = NULL;
160-
161-
zend_bitset_clear(ctx->instr_worklist, ctx->instr_worklist_len);
162-
zend_bitset_clear(ctx->phi_var_worklist, ctx->phi_var_worklist_len);
163-
zend_bitset_clear(ctx->block_worklist, ctx->block_worklist_len);
164-
zend_bitset_clear(ctx->executable_blocks, ctx->block_worklist_len);
165-
zend_bitset_clear(ctx->feasible_edges, ctx->block_worklist_len * 2);
166150

167151
zend_bitset_incl(ctx->block_worklist, 0);
168152
zend_bitset_incl(ctx->executable_blocks, 0);
169153
}
170154

171155
void scdf_free(scdf_ctx *ctx) {
172-
if (ctx->feasible_edges_ht) {
173-
zend_hash_destroy(ctx->feasible_edges_ht);
174-
efree(ctx->feasible_edges_ht);
175-
}
176156
efree(ctx->instr_worklist);
177157
}
178158

@@ -225,7 +205,7 @@ void scdf_solve(scdf_ctx *ctx, const char *name) {
225205

226206
if (block->len == 0) {
227207
/* Zero length blocks don't have a last instruction that would normally do this */
228-
mark_edge_feasible(ctx, i, &block->successors[0], 0);
208+
mark_edge_feasible(ctx, i, block->successors[0]);
229209
}
230210
}
231211
}

ext/opcache/Optimizer/scdf.h

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,8 @@ typedef struct _scdf_ctx {
3030
zend_bitset phi_var_worklist;
3131
zend_bitset block_worklist;
3232
zend_bitset executable_blocks;
33-
/* Edge encoding: 2 bits per block, one for each successor */
33+
/* 1 bit per edge, see scdf_edge(cfg, from, to) */
3434
zend_bitset feasible_edges;
35-
/* If there are more than two successors, an HT is used instead */
36-
HashTable *feasible_edges_ht;
3735
uint32_t instr_worklist_len;
3836
uint32_t phi_var_worklist_len;
3937
uint32_t block_worklist_len;
@@ -79,21 +77,23 @@ static inline void scdf_add_def_to_worklist(scdf_ctx *scdf, int var_num) {
7977
}
8078
}
8179

82-
static inline zend_bool scdf_is_edge_feasible(scdf_ctx *scdf, int from, int to) {
83-
zend_basic_block *block = &scdf->ssa->cfg.blocks[from];
84-
int s;
85-
for (s = 0; s < block->successors_count; s++) {
86-
if (block->successors[s] == to) {
87-
if (s < 2) {
88-
return zend_bitset_in(scdf->feasible_edges, 2 * from + s);
89-
} else {
90-
return scdf->feasible_edges_ht
91-
&& zend_hash_index_exists(scdf->feasible_edges_ht,
92-
(zend_long) (intptr_t) &block->successors[s]);
93-
}
80+
static inline uint32_t scdf_edge(zend_cfg *cfg, int from, int to) {
81+
zend_basic_block *to_block = cfg->blocks + to;
82+
int i;
83+
84+
for (i = 0; i < to_block->predecessors_count; i++) {
85+
uint32_t edge = to_block->predecessor_offset + i;
86+
87+
if (cfg->predecessors[edge] == from) {
88+
return edge;
9489
}
9590
}
9691
ZEND_ASSERT(0);
9792
}
9893

94+
static inline zend_bool scdf_is_edge_feasible(scdf_ctx *scdf, int from, int to) {
95+
uint32_t edge = scdf_edge(&scdf->ssa->cfg, from, to);
96+
return zend_bitset_in(scdf->feasible_edges, edge);
97+
}
98+
9999
#endif

0 commit comments

Comments
 (0)