scdf.h 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  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. #ifndef _SCDF_H
  19. #define _SCDF_H
  20. #include "zend_bitset.h"
  21. typedef struct _scdf_ctx {
  22. zend_op_array *op_array;
  23. zend_ssa *ssa;
  24. zend_bitset instr_worklist;
  25. /* Represent phi-instructions through the defining var */
  26. zend_bitset phi_var_worklist;
  27. zend_bitset block_worklist;
  28. zend_bitset executable_blocks;
  29. /* 1 bit per edge, see scdf_edge(cfg, from, to) */
  30. zend_bitset feasible_edges;
  31. uint32_t instr_worklist_len;
  32. uint32_t phi_var_worklist_len;
  33. uint32_t block_worklist_len;
  34. struct {
  35. void (*visit_instr)(
  36. struct _scdf_ctx *scdf, zend_op *opline, zend_ssa_op *ssa_op);
  37. void (*visit_phi)(
  38. struct _scdf_ctx *scdf, zend_ssa_phi *phi);
  39. void (*mark_feasible_successors)(
  40. struct _scdf_ctx *scdf, int block_num, zend_basic_block *block,
  41. zend_op *opline, zend_ssa_op *ssa_op);
  42. } handlers;
  43. } scdf_ctx;
  44. void scdf_init(zend_optimizer_ctx *ctx, scdf_ctx *scdf, zend_op_array *op_array, zend_ssa *ssa);
  45. void scdf_solve(scdf_ctx *scdf, const char *name);
  46. int scdf_remove_unreachable_blocks(scdf_ctx *scdf);
  47. /* Add uses to worklist */
  48. static inline void scdf_add_to_worklist(scdf_ctx *scdf, int var_num) {
  49. zend_ssa *ssa = scdf->ssa;
  50. zend_ssa_var *var = &ssa->vars[var_num];
  51. int use;
  52. zend_ssa_phi *phi;
  53. FOREACH_USE(var, use) {
  54. zend_bitset_incl(scdf->instr_worklist, use);
  55. } FOREACH_USE_END();
  56. FOREACH_PHI_USE(var, phi) {
  57. zend_bitset_incl(scdf->phi_var_worklist, phi->ssa_var);
  58. } FOREACH_PHI_USE_END();
  59. }
  60. /* This should usually not be necessary, however it's used for type narrowing. */
  61. static inline void scdf_add_def_to_worklist(scdf_ctx *scdf, int var_num) {
  62. zend_ssa_var *var = &scdf->ssa->vars[var_num];
  63. if (var->definition >= 0) {
  64. zend_bitset_incl(scdf->instr_worklist, var->definition);
  65. } else if (var->definition_phi) {
  66. zend_bitset_incl(scdf->phi_var_worklist, var_num);
  67. }
  68. }
  69. static inline uint32_t scdf_edge(zend_cfg *cfg, int from, int to) {
  70. zend_basic_block *to_block = cfg->blocks + to;
  71. int i;
  72. for (i = 0; i < to_block->predecessors_count; i++) {
  73. uint32_t edge = to_block->predecessor_offset + i;
  74. if (cfg->predecessors[edge] == from) {
  75. return edge;
  76. }
  77. }
  78. ZEND_UNREACHABLE();
  79. }
  80. static inline bool scdf_is_edge_feasible(scdf_ctx *scdf, int from, int to) {
  81. uint32_t edge = scdf_edge(&scdf->ssa->cfg, from, to);
  82. return zend_bitset_in(scdf->feasible_edges, edge);
  83. }
  84. void scdf_mark_edge_feasible(scdf_ctx *scdf, int from, int to);
  85. #endif