/src/php-src/Zend/Optimizer/scdf.h
Line | Count | Source |
1 | | /* |
2 | | +----------------------------------------------------------------------+ |
3 | | | Zend Engine, Call Graph | |
4 | | +----------------------------------------------------------------------+ |
5 | | | Copyright © The PHP Group and Contributors. | |
6 | | +----------------------------------------------------------------------+ |
7 | | | This source file is subject to the Modified BSD License that is | |
8 | | | bundled with this package in the file LICENSE, and is available | |
9 | | | through the World Wide Web at <https://www.php.net/license/>. | |
10 | | | | |
11 | | | SPDX-License-Identifier: BSD-3-Clause | |
12 | | +----------------------------------------------------------------------+ |
13 | | | Authors: Nikita Popov <nikic@php.net> | |
14 | | +----------------------------------------------------------------------+ |
15 | | */ |
16 | | |
17 | | #ifndef _SCDF_H |
18 | | #define _SCDF_H |
19 | | |
20 | | #include "zend_bitset.h" |
21 | | |
22 | | typedef struct _scdf_ctx { |
23 | | zend_op_array *op_array; |
24 | | zend_ssa *ssa; |
25 | | zend_bitset instr_worklist; |
26 | | /* Represent phi-instructions through the defining var */ |
27 | | zend_bitset phi_var_worklist; |
28 | | zend_bitset block_worklist; |
29 | | zend_bitset executable_blocks; |
30 | | /* 1 bit per edge, see scdf_edge(cfg, from, to) */ |
31 | | zend_bitset feasible_edges; |
32 | | uint32_t instr_worklist_len; |
33 | | uint32_t phi_var_worklist_len; |
34 | | uint32_t block_worklist_len; |
35 | | |
36 | | struct { |
37 | | void (*visit_instr)( |
38 | | struct _scdf_ctx *scdf, zend_op *opline, zend_ssa_op *ssa_op); |
39 | | void (*visit_phi)( |
40 | | struct _scdf_ctx *scdf, const zend_ssa_phi *phi); |
41 | | void (*mark_feasible_successors)( |
42 | | struct _scdf_ctx *scdf, int block_num, zend_basic_block *block, |
43 | | zend_op *opline, zend_ssa_op *ssa_op); |
44 | | } handlers; |
45 | | } scdf_ctx; |
46 | | |
47 | | void scdf_init(zend_optimizer_ctx *ctx, scdf_ctx *scdf, zend_op_array *op_array, zend_ssa *ssa); |
48 | | void scdf_solve(scdf_ctx *scdf, const char *name); |
49 | | |
50 | | uint32_t scdf_remove_unreachable_blocks(const scdf_ctx *scdf); |
51 | | |
52 | | /* Add uses to worklist */ |
53 | 521k | static inline void scdf_add_to_worklist(const scdf_ctx *scdf, int var_num) { |
54 | 521k | const zend_ssa *ssa = scdf->ssa; |
55 | 521k | const zend_ssa_var *var = &ssa->vars[var_num]; |
56 | 521k | int use; |
57 | 521k | zend_ssa_phi *phi; |
58 | 1.02M | FOREACH_USE(var, use) { |
59 | 1.02M | zend_bitset_incl(scdf->instr_worklist, use); |
60 | 1.02M | } FOREACH_USE_END(); |
61 | 652k | FOREACH_PHI_USE(var, phi) { |
62 | 652k | zend_bitset_incl(scdf->phi_var_worklist, phi->ssa_var); |
63 | 652k | } FOREACH_PHI_USE_END(); |
64 | 521k | } sccp.c:scdf_add_to_worklist Line | Count | Source | 53 | 521k | static inline void scdf_add_to_worklist(const scdf_ctx *scdf, int var_num) { | 54 | 521k | const zend_ssa *ssa = scdf->ssa; | 55 | 521k | const zend_ssa_var *var = &ssa->vars[var_num]; | 56 | 521k | int use; | 57 | 521k | zend_ssa_phi *phi; | 58 | 1.02M | FOREACH_USE(var, use) { | 59 | 1.02M | zend_bitset_incl(scdf->instr_worklist, use); | 60 | 1.02M | } FOREACH_USE_END(); | 61 | 652k | FOREACH_PHI_USE(var, phi) { | 62 | 652k | zend_bitset_incl(scdf->phi_var_worklist, phi->ssa_var); | 63 | 652k | } FOREACH_PHI_USE_END(); | 64 | 521k | } |
Unexecuted instantiation: scdf.c:scdf_add_to_worklist |
65 | | |
66 | | /* This should usually not be necessary, however it's used for type narrowing. */ |
67 | 0 | static inline void scdf_add_def_to_worklist(const scdf_ctx *scdf, int var_num) { |
68 | 0 | const zend_ssa_var *var = &scdf->ssa->vars[var_num]; |
69 | 0 | if (var->definition >= 0) { |
70 | 0 | zend_bitset_incl(scdf->instr_worklist, var->definition); |
71 | 0 | } else if (var->definition_phi) { |
72 | 0 | zend_bitset_incl(scdf->phi_var_worklist, var_num); |
73 | 0 | } |
74 | 0 | } Unexecuted instantiation: sccp.c:scdf_add_def_to_worklist Unexecuted instantiation: scdf.c:scdf_add_def_to_worklist |
75 | | |
76 | 246k | static inline uint32_t scdf_edge(const zend_cfg *cfg, int from, uint32_t to) { |
77 | 246k | const zend_basic_block *to_block = cfg->blocks + to; |
78 | | |
79 | 350k | for (uint32_t i = 0; i < to_block->predecessors_count; i++) { |
80 | 350k | uint32_t edge = to_block->predecessor_offset + i; |
81 | | |
82 | 350k | if (cfg->predecessors[edge] == from) { |
83 | 246k | return edge; |
84 | 246k | } |
85 | 350k | } |
86 | 0 | ZEND_UNREACHABLE(); |
87 | 0 | } Line | Count | Source | 76 | 145k | static inline uint32_t scdf_edge(const zend_cfg *cfg, int from, uint32_t to) { | 77 | 145k | const zend_basic_block *to_block = cfg->blocks + to; | 78 | | | 79 | 213k | for (uint32_t i = 0; i < to_block->predecessors_count; i++) { | 80 | 213k | uint32_t edge = to_block->predecessor_offset + i; | 81 | | | 82 | 213k | if (cfg->predecessors[edge] == from) { | 83 | 145k | return edge; | 84 | 145k | } | 85 | 213k | } | 86 | 0 | ZEND_UNREACHABLE(); | 87 | 0 | } |
Line | Count | Source | 76 | 100k | static inline uint32_t scdf_edge(const zend_cfg *cfg, int from, uint32_t to) { | 77 | 100k | const zend_basic_block *to_block = cfg->blocks + to; | 78 | | | 79 | 136k | for (uint32_t i = 0; i < to_block->predecessors_count; i++) { | 80 | 136k | uint32_t edge = to_block->predecessor_offset + i; | 81 | | | 82 | 136k | if (cfg->predecessors[edge] == from) { | 83 | 100k | return edge; | 84 | 100k | } | 85 | 136k | } | 86 | 0 | ZEND_UNREACHABLE(); | 87 | 0 | } |
|
88 | | |
89 | 145k | static inline bool scdf_is_edge_feasible(const scdf_ctx *scdf, int from, uint32_t to) { |
90 | 145k | uint32_t edge = scdf_edge(&scdf->ssa->cfg, from, to); |
91 | 145k | return zend_bitset_in(scdf->feasible_edges, edge); |
92 | 145k | } sccp.c:scdf_is_edge_feasible Line | Count | Source | 89 | 145k | static inline bool scdf_is_edge_feasible(const scdf_ctx *scdf, int from, uint32_t to) { | 90 | 145k | uint32_t edge = scdf_edge(&scdf->ssa->cfg, from, to); | 91 | 145k | return zend_bitset_in(scdf->feasible_edges, edge); | 92 | 145k | } |
Unexecuted instantiation: scdf.c:scdf_is_edge_feasible |
93 | | |
94 | | void scdf_mark_edge_feasible(scdf_ctx *scdf, int from, int to); |
95 | | |
96 | | #endif |