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