zend_ssa.c 51 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618
  1. /*
  2. +----------------------------------------------------------------------+
  3. | Zend Engine, SSA - Static Single Assignment Form |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1998-2018 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. | http://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: Dmitry Stogov <dmitry@php.net> |
  16. | Nikita Popov <nikic@php.net> |
  17. +----------------------------------------------------------------------+
  18. */
  19. #include "php.h"
  20. #include "zend_compile.h"
  21. #include "zend_dfg.h"
  22. #include "zend_ssa.h"
  23. #include "zend_dump.h"
  24. #include "zend_inference.h"
  25. #include "Optimizer/zend_optimizer_internal.h"
  26. static zend_bool dominates(const zend_basic_block *blocks, int a, int b) {
  27. while (blocks[b].level > blocks[a].level) {
  28. b = blocks[b].idom;
  29. }
  30. return a == b;
  31. }
  32. static zend_bool dominates_other_predecessors(
  33. const zend_cfg *cfg, const zend_basic_block *block, int check, int exclude) {
  34. int i;
  35. for (i = 0; i < block->predecessors_count; i++) {
  36. int predecessor = cfg->predecessors[block->predecessor_offset + i];
  37. if (predecessor != exclude && !dominates(cfg->blocks, check, predecessor)) {
  38. return 0;
  39. }
  40. }
  41. return 1;
  42. }
  43. static zend_bool needs_pi(const zend_op_array *op_array, zend_dfg *dfg, zend_ssa *ssa, int from, int to, int var) /* {{{ */
  44. {
  45. zend_basic_block *from_block, *to_block;
  46. int other_successor;
  47. if (!DFG_ISSET(dfg->in, dfg->size, to, var)) {
  48. /* Variable is not live, certainly won't benefit from pi */
  49. return 0;
  50. }
  51. /* Make sure that both sucessors of the from block aren't the same. Pi nodes are associated
  52. * with predecessor blocks, so we can't distinguish which edge the pi belongs to. */
  53. from_block = &ssa->cfg.blocks[from];
  54. ZEND_ASSERT(from_block->successors_count == 2);
  55. if (from_block->successors[0] == from_block->successors[1]) {
  56. return 0;
  57. }
  58. to_block = &ssa->cfg.blocks[to];
  59. if (to_block->predecessors_count == 1) {
  60. /* Always place pi if one predecessor (an if branch) */
  61. return 1;
  62. }
  63. /* Check that the other successor of the from block does not dominate all other predecessors.
  64. * If it does, we'd probably end up annihilating a positive+negative pi assertion. */
  65. other_successor = from_block->successors[0] == to
  66. ? from_block->successors[1] : from_block->successors[0];
  67. return !dominates_other_predecessors(&ssa->cfg, to_block, other_successor, from);
  68. }
  69. /* }}} */
  70. static zend_ssa_phi *add_pi(
  71. zend_arena **arena, const zend_op_array *op_array, zend_dfg *dfg, zend_ssa *ssa,
  72. int from, int to, int var) /* {{{ */
  73. {
  74. zend_ssa_phi *phi;
  75. if (!needs_pi(op_array, dfg, ssa, from, to, var)) {
  76. return NULL;
  77. }
  78. phi = zend_arena_calloc(arena, 1,
  79. ZEND_MM_ALIGNED_SIZE(sizeof(zend_ssa_phi)) +
  80. ZEND_MM_ALIGNED_SIZE(sizeof(int) * ssa->cfg.blocks[to].predecessors_count) +
  81. sizeof(void*) * ssa->cfg.blocks[to].predecessors_count);
  82. phi->sources = (int*)(((char*)phi) + ZEND_MM_ALIGNED_SIZE(sizeof(zend_ssa_phi)));
  83. memset(phi->sources, 0xff, sizeof(int) * ssa->cfg.blocks[to].predecessors_count);
  84. phi->use_chains = (zend_ssa_phi**)(((char*)phi->sources) + ZEND_MM_ALIGNED_SIZE(sizeof(int) * ssa->cfg.blocks[to].predecessors_count));
  85. phi->pi = from;
  86. phi->var = var;
  87. phi->ssa_var = -1;
  88. phi->next = ssa->blocks[to].phis;
  89. ssa->blocks[to].phis = phi;
  90. /* Block "to" now defines "var" via the pi statement, so add it to the "def" set. Note that
  91. * this is not entirely accurate, because the pi is actually placed along the edge from->to.
  92. * If there is a back-edge to "to" this may result in non-minimal SSA form. */
  93. DFG_SET(dfg->def, dfg->size, to, var);
  94. /* If there are multiple predecessors in the target block, we need to place a phi there.
  95. * However this can (generally) not be expressed in terms of dominance frontiers, so place it
  96. * explicitly. dfg->use here really is dfg->phi, we're reusing the set. */
  97. if (ssa->cfg.blocks[to].predecessors_count > 1) {
  98. DFG_SET(dfg->use, dfg->size, to, var);
  99. }
  100. return phi;
  101. }
  102. /* }}} */
  103. static void pi_range(
  104. zend_ssa_phi *phi, int min_var, int max_var, zend_long min, zend_long max,
  105. char underflow, char overflow, char negative) /* {{{ */
  106. {
  107. zend_ssa_range_constraint *constraint = &phi->constraint.range;
  108. constraint->min_var = min_var;
  109. constraint->max_var = max_var;
  110. constraint->min_ssa_var = -1;
  111. constraint->max_ssa_var = -1;
  112. constraint->range.min = min;
  113. constraint->range.max = max;
  114. constraint->range.underflow = underflow;
  115. constraint->range.overflow = overflow;
  116. constraint->negative = negative ? NEG_INIT : NEG_NONE;
  117. phi->has_range_constraint = 1;
  118. }
  119. /* }}} */
  120. static inline void pi_range_equals(zend_ssa_phi *phi, int var, zend_long val) {
  121. pi_range(phi, var, var, val, val, 0, 0, 0);
  122. }
  123. static inline void pi_range_not_equals(zend_ssa_phi *phi, int var, zend_long val) {
  124. pi_range(phi, var, var, val, val, 0, 0, 1);
  125. }
  126. static inline void pi_range_min(zend_ssa_phi *phi, int var, zend_long val) {
  127. pi_range(phi, var, -1, val, ZEND_LONG_MAX, 0, 1, 0);
  128. }
  129. static inline void pi_range_max(zend_ssa_phi *phi, int var, zend_long val) {
  130. pi_range(phi, -1, var, ZEND_LONG_MIN, val, 1, 0, 0);
  131. }
  132. static void pi_type_mask(zend_ssa_phi *phi, uint32_t type_mask) {
  133. phi->has_range_constraint = 0;
  134. phi->constraint.type.ce = NULL;
  135. phi->constraint.type.type_mask = MAY_BE_REF|MAY_BE_RC1|MAY_BE_RCN;
  136. phi->constraint.type.type_mask |= type_mask;
  137. if (type_mask & MAY_BE_NULL) {
  138. phi->constraint.type.type_mask |= MAY_BE_UNDEF;
  139. }
  140. }
  141. static inline void pi_not_type_mask(zend_ssa_phi *phi, uint32_t type_mask) {
  142. uint32_t relevant = MAY_BE_ANY|MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF;
  143. pi_type_mask(phi, ~type_mask & relevant);
  144. }
  145. static inline uint32_t mask_for_type_check(uint32_t type) {
  146. if (type & MAY_BE_ARRAY) {
  147. return MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF;
  148. } else {
  149. return type;
  150. }
  151. }
  152. /* We can interpret $a + 5 == 0 as $a = 0 - 5, i.e. shift the adjustment to the other operand.
  153. * This negated adjustment is what is written into the "adjustment" parameter. */
  154. static int find_adjusted_tmp_var(const zend_op_array *op_array, uint32_t build_flags, zend_op *opline, uint32_t var_num, zend_long *adjustment) /* {{{ */
  155. {
  156. zend_op *op = opline;
  157. zval *zv;
  158. while (op != op_array->opcodes) {
  159. op--;
  160. if (op->result_type != IS_TMP_VAR || op->result.var != var_num) {
  161. continue;
  162. }
  163. if (op->opcode == ZEND_POST_DEC) {
  164. if (op->op1_type == IS_CV) {
  165. *adjustment = -1;
  166. return EX_VAR_TO_NUM(op->op1.var);
  167. }
  168. } else if (op->opcode == ZEND_POST_INC) {
  169. if (op->op1_type == IS_CV) {
  170. *adjustment = 1;
  171. return EX_VAR_TO_NUM(op->op1.var);
  172. }
  173. } else if (op->opcode == ZEND_ADD) {
  174. if (op->op1_type == IS_CV && op->op2_type == IS_CONST) {
  175. zv = CRT_CONSTANT_EX(op_array, op, op->op2, (build_flags & ZEND_RT_CONSTANTS));
  176. if (Z_TYPE_P(zv) == IS_LONG
  177. && Z_LVAL_P(zv) != ZEND_LONG_MIN) {
  178. *adjustment = -Z_LVAL_P(zv);
  179. return EX_VAR_TO_NUM(op->op1.var);
  180. }
  181. } else if (op->op2_type == IS_CV && op->op1_type == IS_CONST) {
  182. zv = CRT_CONSTANT_EX(op_array, op, op->op1, (build_flags & ZEND_RT_CONSTANTS));
  183. if (Z_TYPE_P(zv) == IS_LONG
  184. && Z_LVAL_P(zv) != ZEND_LONG_MIN) {
  185. *adjustment = -Z_LVAL_P(zv);
  186. return EX_VAR_TO_NUM(op->op2.var);
  187. }
  188. }
  189. } else if (op->opcode == ZEND_SUB) {
  190. if (op->op1_type == IS_CV && op->op2_type == IS_CONST) {
  191. zv = CRT_CONSTANT_EX(op_array, op, op->op2, (build_flags & ZEND_RT_CONSTANTS));
  192. if (Z_TYPE_P(zv) == IS_LONG) {
  193. *adjustment = Z_LVAL_P(zv);
  194. return EX_VAR_TO_NUM(op->op1.var);
  195. }
  196. }
  197. }
  198. break;
  199. }
  200. return -1;
  201. }
  202. /* }}} */
  203. static inline zend_bool add_will_overflow(zend_long a, zend_long b) {
  204. return (b > 0 && a > ZEND_LONG_MAX - b)
  205. || (b < 0 && a < ZEND_LONG_MIN - b);
  206. }
  207. static inline zend_bool sub_will_overflow(zend_long a, zend_long b) {
  208. return (b > 0 && a < ZEND_LONG_MIN + b)
  209. || (b < 0 && a > ZEND_LONG_MAX + b);
  210. }
  211. /* e-SSA construction: Pi placement (Pi is actually a Phi with single
  212. * source and constraint).
  213. * Order of Phis is importent, Pis must be placed before Phis
  214. */
  215. static void place_essa_pis(
  216. zend_arena **arena, const zend_script *script, const zend_op_array *op_array,
  217. uint32_t build_flags, zend_ssa *ssa, zend_dfg *dfg) /* {{{ */ {
  218. zend_basic_block *blocks = ssa->cfg.blocks;
  219. int j, blocks_count = ssa->cfg.blocks_count;
  220. for (j = 0; j < blocks_count; j++) {
  221. zend_ssa_phi *pi;
  222. zend_op *opline = op_array->opcodes + blocks[j].start + blocks[j].len - 1;
  223. int bt; /* successor block number if a condition is true */
  224. int bf; /* successor block number if a condition is false */
  225. if ((blocks[j].flags & ZEND_BB_REACHABLE) == 0 || blocks[j].len == 0) {
  226. continue;
  227. }
  228. /* the last instruction of basic block is conditional branch,
  229. * based on comparison of CV(s)
  230. */
  231. switch (opline->opcode) {
  232. case ZEND_JMPZ:
  233. case ZEND_JMPZNZ:
  234. bf = blocks[j].successors[0];
  235. bt = blocks[j].successors[1];
  236. break;
  237. case ZEND_JMPNZ:
  238. bt = blocks[j].successors[0];
  239. bf = blocks[j].successors[1];
  240. break;
  241. default:
  242. continue;
  243. }
  244. if (opline->op1_type == IS_TMP_VAR &&
  245. ((opline-1)->opcode == ZEND_IS_EQUAL ||
  246. (opline-1)->opcode == ZEND_IS_NOT_EQUAL ||
  247. (opline-1)->opcode == ZEND_IS_SMALLER ||
  248. (opline-1)->opcode == ZEND_IS_SMALLER_OR_EQUAL) &&
  249. opline->op1.var == (opline-1)->result.var) {
  250. int var1 = -1;
  251. int var2 = -1;
  252. zend_long val1 = 0;
  253. zend_long val2 = 0;
  254. // long val = 0;
  255. if ((opline-1)->op1_type == IS_CV) {
  256. var1 = EX_VAR_TO_NUM((opline-1)->op1.var);
  257. } else if ((opline-1)->op1_type == IS_TMP_VAR) {
  258. var1 = find_adjusted_tmp_var(
  259. op_array, build_flags, opline, (opline-1)->op1.var, &val2);
  260. }
  261. if ((opline-1)->op2_type == IS_CV) {
  262. var2 = EX_VAR_TO_NUM((opline-1)->op2.var);
  263. } else if ((opline-1)->op2_type == IS_TMP_VAR) {
  264. var2 = find_adjusted_tmp_var(
  265. op_array, build_flags, opline, (opline-1)->op2.var, &val1);
  266. }
  267. if (var1 >= 0 && var2 >= 0) {
  268. if (!sub_will_overflow(val1, val2) && !sub_will_overflow(val2, val1)) {
  269. zend_long tmp = val1;
  270. val1 -= val2;
  271. val2 -= tmp;
  272. } else {
  273. var1 = -1;
  274. var2 = -1;
  275. }
  276. } else if (var1 >= 0 && var2 < 0) {
  277. zend_long add_val2 = 0;
  278. if ((opline-1)->op2_type == IS_CONST) {
  279. zval *zv = CRT_CONSTANT_EX(op_array, (opline-1), (opline-1)->op2, (build_flags & ZEND_RT_CONSTANTS));
  280. if (Z_TYPE_P(zv) == IS_LONG) {
  281. add_val2 = Z_LVAL_P(zv);
  282. } else if (Z_TYPE_P(zv) == IS_FALSE) {
  283. add_val2 = 0;
  284. } else if (Z_TYPE_P(zv) == IS_TRUE) {
  285. add_val2 = 1;
  286. } else {
  287. var1 = -1;
  288. }
  289. } else {
  290. var1 = -1;
  291. }
  292. if (!add_will_overflow(val2, add_val2)) {
  293. val2 += add_val2;
  294. } else {
  295. var1 = -1;
  296. }
  297. } else if (var1 < 0 && var2 >= 0) {
  298. zend_long add_val1 = 0;
  299. if ((opline-1)->op1_type == IS_CONST) {
  300. zval *zv = CRT_CONSTANT_EX(op_array, (opline-1), (opline-1)->op1, (build_flags & ZEND_RT_CONSTANTS));
  301. if (Z_TYPE_P(zv) == IS_LONG) {
  302. add_val1 = Z_LVAL_P(CRT_CONSTANT_EX(op_array, (opline-1), (opline-1)->op1, (build_flags & ZEND_RT_CONSTANTS)));
  303. } else if (Z_TYPE_P(zv) == IS_FALSE) {
  304. add_val1 = 0;
  305. } else if (Z_TYPE_P(zv) == IS_TRUE) {
  306. add_val1 = 1;
  307. } else {
  308. var2 = -1;
  309. }
  310. } else {
  311. var2 = -1;
  312. }
  313. if (!add_will_overflow(val1, add_val1)) {
  314. val1 += add_val1;
  315. } else {
  316. var2 = -1;
  317. }
  318. }
  319. if (var1 >= 0) {
  320. if ((opline-1)->opcode == ZEND_IS_EQUAL) {
  321. if ((pi = add_pi(arena, op_array, dfg, ssa, j, bt, var1))) {
  322. pi_range_equals(pi, var2, val2);
  323. }
  324. if ((pi = add_pi(arena, op_array, dfg, ssa, j, bf, var1))) {
  325. pi_range_not_equals(pi, var2, val2);
  326. }
  327. } else if ((opline-1)->opcode == ZEND_IS_NOT_EQUAL) {
  328. if ((pi = add_pi(arena, op_array, dfg, ssa, j, bf, var1))) {
  329. pi_range_equals(pi, var2, val2);
  330. }
  331. if ((pi = add_pi(arena, op_array, dfg, ssa, j, bt, var1))) {
  332. pi_range_not_equals(pi, var2, val2);
  333. }
  334. } else if ((opline-1)->opcode == ZEND_IS_SMALLER) {
  335. if (val2 > ZEND_LONG_MIN) {
  336. if ((pi = add_pi(arena, op_array, dfg, ssa, j, bt, var1))) {
  337. pi_range_max(pi, var2, val2-1);
  338. }
  339. }
  340. if ((pi = add_pi(arena, op_array, dfg, ssa, j, bf, var1))) {
  341. pi_range_min(pi, var2, val2);
  342. }
  343. } else if ((opline-1)->opcode == ZEND_IS_SMALLER_OR_EQUAL) {
  344. if ((pi = add_pi(arena, op_array, dfg, ssa, j, bt, var1))) {
  345. pi_range_max(pi, var2, val2);
  346. }
  347. if (val2 < ZEND_LONG_MAX) {
  348. if ((pi = add_pi(arena, op_array, dfg, ssa, j, bf, var1))) {
  349. pi_range_min(pi, var2, val2+1);
  350. }
  351. }
  352. }
  353. }
  354. if (var2 >= 0) {
  355. if((opline-1)->opcode == ZEND_IS_EQUAL) {
  356. if ((pi = add_pi(arena, op_array, dfg, ssa, j, bt, var2))) {
  357. pi_range_equals(pi, var1, val1);
  358. }
  359. if ((pi = add_pi(arena, op_array, dfg, ssa, j, bf, var2))) {
  360. pi_range_not_equals(pi, var1, val1);
  361. }
  362. } else if ((opline-1)->opcode == ZEND_IS_NOT_EQUAL) {
  363. if ((pi = add_pi(arena, op_array, dfg, ssa, j, bf, var2))) {
  364. pi_range_equals(pi, var1, val1);
  365. }
  366. if ((pi = add_pi(arena, op_array, dfg, ssa, j, bt, var2))) {
  367. pi_range_not_equals(pi, var1, val1);
  368. }
  369. } else if ((opline-1)->opcode == ZEND_IS_SMALLER) {
  370. if (val1 < ZEND_LONG_MAX) {
  371. if ((pi = add_pi(arena, op_array, dfg, ssa, j, bt, var2))) {
  372. pi_range_min(pi, var1, val1+1);
  373. }
  374. }
  375. if ((pi = add_pi(arena, op_array, dfg, ssa, j, bf, var2))) {
  376. pi_range_max(pi, var1, val1);
  377. }
  378. } else if ((opline-1)->opcode == ZEND_IS_SMALLER_OR_EQUAL) {
  379. if ((pi = add_pi(arena, op_array, dfg, ssa, j, bt, var2))) {
  380. pi_range_min(pi, var1, val1);
  381. }
  382. if (val1 > ZEND_LONG_MIN) {
  383. if ((pi = add_pi(arena, op_array, dfg, ssa, j, bf, var2))) {
  384. pi_range_max(pi, var1, val1-1);
  385. }
  386. }
  387. }
  388. }
  389. } else if (opline->op1_type == IS_TMP_VAR &&
  390. ((opline-1)->opcode == ZEND_POST_INC ||
  391. (opline-1)->opcode == ZEND_POST_DEC) &&
  392. opline->op1.var == (opline-1)->result.var &&
  393. (opline-1)->op1_type == IS_CV) {
  394. int var = EX_VAR_TO_NUM((opline-1)->op1.var);
  395. if ((opline-1)->opcode == ZEND_POST_DEC) {
  396. if ((pi = add_pi(arena, op_array, dfg, ssa, j, bf, var))) {
  397. pi_range_equals(pi, -1, -1);
  398. }
  399. if ((pi = add_pi(arena, op_array, dfg, ssa, j, bt, var))) {
  400. pi_range_not_equals(pi, -1, -1);
  401. }
  402. } else if ((opline-1)->opcode == ZEND_POST_INC) {
  403. if ((pi = add_pi(arena, op_array, dfg, ssa, j, bf, var))) {
  404. pi_range_equals(pi, -1, 1);
  405. }
  406. if ((pi = add_pi(arena, op_array, dfg, ssa, j, bt, var))) {
  407. pi_range_not_equals(pi, -1, 1);
  408. }
  409. }
  410. } else if (opline->op1_type == IS_VAR &&
  411. ((opline-1)->opcode == ZEND_PRE_INC ||
  412. (opline-1)->opcode == ZEND_PRE_DEC) &&
  413. opline->op1.var == (opline-1)->result.var &&
  414. (opline-1)->op1_type == IS_CV) {
  415. int var = EX_VAR_TO_NUM((opline-1)->op1.var);
  416. if ((pi = add_pi(arena, op_array, dfg, ssa, j, bf, var))) {
  417. pi_range_equals(pi, -1, 0);
  418. }
  419. /* speculative */
  420. if ((pi = add_pi(arena, op_array, dfg, ssa, j, bt, var))) {
  421. pi_range_not_equals(pi, -1, 0);
  422. }
  423. } else if (opline->op1_type == IS_TMP_VAR && (opline-1)->opcode == ZEND_TYPE_CHECK &&
  424. opline->op1.var == (opline-1)->result.var && (opline-1)->op1_type == IS_CV) {
  425. int var = EX_VAR_TO_NUM((opline-1)->op1.var);
  426. uint32_t type = (opline-1)->extended_value;
  427. if ((pi = add_pi(arena, op_array, dfg, ssa, j, bt, var))) {
  428. pi_type_mask(pi, mask_for_type_check(type));
  429. }
  430. if (type != MAY_BE_RESOURCE) {
  431. /* is_resource() may return false for closed resources */
  432. if ((pi = add_pi(arena, op_array, dfg, ssa, j, bf, var))) {
  433. pi_not_type_mask(pi, mask_for_type_check(type));
  434. }
  435. }
  436. } else if (opline->op1_type == IS_TMP_VAR &&
  437. ((opline-1)->opcode == ZEND_IS_IDENTICAL
  438. || (opline-1)->opcode == ZEND_IS_NOT_IDENTICAL) &&
  439. opline->op1.var == (opline-1)->result.var) {
  440. int var;
  441. zval *val;
  442. uint32_t type_mask;
  443. if ((opline-1)->op1_type == IS_CV && (opline-1)->op2_type == IS_CONST) {
  444. var = EX_VAR_TO_NUM((opline-1)->op1.var);
  445. val = CRT_CONSTANT_EX(op_array, (opline-1), (opline-1)->op2, (build_flags & ZEND_RT_CONSTANTS));
  446. } else if ((opline-1)->op1_type == IS_CONST && (opline-1)->op2_type == IS_CV) {
  447. var = EX_VAR_TO_NUM((opline-1)->op2.var);
  448. val = CRT_CONSTANT_EX(op_array, (opline-1), (opline-1)->op1, (build_flags & ZEND_RT_CONSTANTS));
  449. } else {
  450. continue;
  451. }
  452. /* We're interested in === null/true/false comparisons here, because they eliminate
  453. * a type in the false-branch. Other === VAL comparisons are unlikely to be useful. */
  454. if (Z_TYPE_P(val) != IS_NULL && Z_TYPE_P(val) != IS_TRUE && Z_TYPE_P(val) != IS_FALSE) {
  455. continue;
  456. }
  457. type_mask = _const_op_type(val);
  458. if ((opline-1)->opcode == ZEND_IS_IDENTICAL) {
  459. if ((pi = add_pi(arena, op_array, dfg, ssa, j, bt, var))) {
  460. pi_type_mask(pi, type_mask);
  461. }
  462. if ((pi = add_pi(arena, op_array, dfg, ssa, j, bf, var))) {
  463. pi_not_type_mask(pi, type_mask);
  464. }
  465. } else {
  466. if ((pi = add_pi(arena, op_array, dfg, ssa, j, bf, var))) {
  467. pi_type_mask(pi, type_mask);
  468. }
  469. if ((pi = add_pi(arena, op_array, dfg, ssa, j, bt, var))) {
  470. pi_not_type_mask(pi, type_mask);
  471. }
  472. }
  473. } else if (opline->op1_type == IS_TMP_VAR && (opline-1)->opcode == ZEND_INSTANCEOF &&
  474. opline->op1.var == (opline-1)->result.var && (opline-1)->op1_type == IS_CV &&
  475. (opline-1)->op2_type == IS_CONST) {
  476. int var = EX_VAR_TO_NUM((opline-1)->op1.var);
  477. zend_string *lcname = Z_STR_P(CRT_CONSTANT_EX(op_array, (opline-1), (opline-1)->op2, (build_flags & ZEND_RT_CONSTANTS)) + 1);
  478. zend_class_entry *ce = script ? zend_hash_find_ptr(&script->class_table, lcname) : NULL;
  479. if (!ce) {
  480. ce = zend_hash_find_ptr(CG(class_table), lcname);
  481. if (!ce || ce->type != ZEND_INTERNAL_CLASS) {
  482. continue;
  483. }
  484. }
  485. if ((pi = add_pi(arena, op_array, dfg, ssa, j, bt, var))) {
  486. pi_type_mask(pi, MAY_BE_OBJECT);
  487. pi->constraint.type.ce = ce;
  488. }
  489. }
  490. }
  491. }
  492. /* }}} */
  493. static int zend_ssa_rename(const zend_op_array *op_array, uint32_t build_flags, zend_ssa *ssa, int *var, int n) /* {{{ */
  494. {
  495. zend_basic_block *blocks = ssa->cfg.blocks;
  496. zend_ssa_block *ssa_blocks = ssa->blocks;
  497. zend_ssa_op *ssa_ops = ssa->ops;
  498. int ssa_vars_count = ssa->vars_count;
  499. int i, j;
  500. zend_op *opline, *end;
  501. int *tmp = NULL;
  502. ALLOCA_FLAG(use_heap);
  503. // FIXME: Can we optimize this copying out in some cases?
  504. if (blocks[n].next_child >= 0) {
  505. tmp = do_alloca(sizeof(int) * (op_array->last_var + op_array->T), use_heap);
  506. memcpy(tmp, var, sizeof(int) * (op_array->last_var + op_array->T));
  507. var = tmp;
  508. }
  509. if (ssa_blocks[n].phis) {
  510. zend_ssa_phi *phi = ssa_blocks[n].phis;
  511. do {
  512. if (phi->ssa_var < 0) {
  513. phi->ssa_var = ssa_vars_count;
  514. var[phi->var] = ssa_vars_count;
  515. ssa_vars_count++;
  516. } else {
  517. var[phi->var] = phi->ssa_var;
  518. }
  519. phi = phi->next;
  520. } while (phi);
  521. }
  522. opline = op_array->opcodes + blocks[n].start;
  523. end = opline + blocks[n].len;
  524. for (; opline < end; opline++) {
  525. uint32_t k = opline - op_array->opcodes;
  526. if (opline->opcode != ZEND_OP_DATA) {
  527. zend_op *next = opline + 1;
  528. if (next < end && next->opcode == ZEND_OP_DATA) {
  529. if (next->op1_type == IS_CV) {
  530. ssa_ops[k + 1].op1_use = var[EX_VAR_TO_NUM(next->op1.var)];
  531. //USE_SSA_VAR(next->op1.var);
  532. } else if (next->op1_type & (IS_VAR|IS_TMP_VAR)) {
  533. ssa_ops[k + 1].op1_use = var[EX_VAR_TO_NUM(next->op1.var)];
  534. //USE_SSA_VAR(op_array->last_var + next->op1.var);
  535. }
  536. if (next->op2_type == IS_CV) {
  537. ssa_ops[k + 1].op2_use = var[EX_VAR_TO_NUM(next->op2.var)];
  538. //USE_SSA_VAR(next->op2.var);
  539. } else if (next->op2_type & (IS_VAR|IS_TMP_VAR)) {
  540. ssa_ops[k + 1].op2_use = var[EX_VAR_TO_NUM(next->op2.var)];
  541. //USE_SSA_VAR(op_array->last_var + next->op2.var);
  542. }
  543. }
  544. if (opline->op1_type & (IS_CV|IS_VAR|IS_TMP_VAR)) {
  545. ssa_ops[k].op1_use = var[EX_VAR_TO_NUM(opline->op1.var)];
  546. //USE_SSA_VAR(op_array->last_var + opline->op1.var)
  547. }
  548. if (opline->opcode == ZEND_FE_FETCH_R || opline->opcode == ZEND_FE_FETCH_RW) {
  549. if (opline->op2_type == IS_CV) {
  550. ssa_ops[k].op2_use = var[EX_VAR_TO_NUM(opline->op2.var)];
  551. }
  552. ssa_ops[k].op2_def = ssa_vars_count;
  553. var[EX_VAR_TO_NUM(opline->op2.var)] = ssa_vars_count;
  554. ssa_vars_count++;
  555. //NEW_SSA_VAR(opline->op2.var)
  556. } else if (opline->op2_type & (IS_CV|IS_VAR|IS_TMP_VAR)) {
  557. ssa_ops[k].op2_use = var[EX_VAR_TO_NUM(opline->op2.var)];
  558. //USE_SSA_VAR(op_array->last_var + opline->op2.var)
  559. }
  560. switch (opline->opcode) {
  561. case ZEND_ASSIGN:
  562. if ((build_flags & ZEND_SSA_RC_INFERENCE) && opline->op2_type == IS_CV) {
  563. ssa_ops[k].op2_def = ssa_vars_count;
  564. var[EX_VAR_TO_NUM(opline->op2.var)] = ssa_vars_count;
  565. ssa_vars_count++;
  566. //NEW_SSA_VAR(opline->op2.var)
  567. }
  568. if (opline->op1_type == IS_CV) {
  569. ssa_ops[k].op1_def = ssa_vars_count;
  570. var[EX_VAR_TO_NUM(opline->op1.var)] = ssa_vars_count;
  571. ssa_vars_count++;
  572. //NEW_SSA_VAR(opline->op1.var)
  573. }
  574. break;
  575. case ZEND_ASSIGN_REF:
  576. //TODO: ???
  577. if (opline->op2_type == IS_CV) {
  578. ssa_ops[k].op2_def = ssa_vars_count;
  579. var[EX_VAR_TO_NUM(opline->op2.var)] = ssa_vars_count;
  580. ssa_vars_count++;
  581. //NEW_SSA_VAR(opline->op2.var)
  582. }
  583. if (opline->op1_type == IS_CV) {
  584. ssa_ops[k].op1_def = ssa_vars_count;
  585. var[EX_VAR_TO_NUM(opline->op1.var)] = ssa_vars_count;
  586. ssa_vars_count++;
  587. //NEW_SSA_VAR(opline->op1.var)
  588. }
  589. break;
  590. case ZEND_BIND_GLOBAL:
  591. case ZEND_BIND_STATIC:
  592. if (opline->op1_type == IS_CV) {
  593. ssa_ops[k].op1_def = ssa_vars_count;
  594. var[EX_VAR_TO_NUM(opline->op1.var)] = ssa_vars_count;
  595. ssa_vars_count++;
  596. //NEW_SSA_VAR(opline->op1.var)
  597. }
  598. break;
  599. case ZEND_ASSIGN_DIM:
  600. case ZEND_ASSIGN_OBJ:
  601. if (opline->op1_type == IS_CV) {
  602. ssa_ops[k].op1_def = ssa_vars_count;
  603. var[EX_VAR_TO_NUM(opline->op1.var)] = ssa_vars_count;
  604. ssa_vars_count++;
  605. //NEW_SSA_VAR(opline->op1.var)
  606. }
  607. if ((build_flags & ZEND_SSA_RC_INFERENCE) && next->op1_type == IS_CV) {
  608. ssa_ops[k + 1].op1_def = ssa_vars_count;
  609. var[EX_VAR_TO_NUM(next->op1.var)] = ssa_vars_count;
  610. ssa_vars_count++;
  611. //NEW_SSA_VAR(next->op1.var)
  612. }
  613. break;
  614. case ZEND_PRE_INC_OBJ:
  615. case ZEND_PRE_DEC_OBJ:
  616. case ZEND_POST_INC_OBJ:
  617. case ZEND_POST_DEC_OBJ:
  618. if (opline->op1_type == IS_CV) {
  619. ssa_ops[k].op1_def = ssa_vars_count;
  620. var[EX_VAR_TO_NUM(opline->op1.var)] = ssa_vars_count;
  621. ssa_vars_count++;
  622. //NEW_SSA_VAR(opline->op1.var)
  623. }
  624. break;
  625. case ZEND_ADD_ARRAY_ELEMENT:
  626. ssa_ops[k].result_use = var[EX_VAR_TO_NUM(opline->result.var)];
  627. case ZEND_INIT_ARRAY:
  628. if (((build_flags & ZEND_SSA_RC_INFERENCE)
  629. || (opline->extended_value & ZEND_ARRAY_ELEMENT_REF))
  630. && opline->op1_type == IS_CV) {
  631. ssa_ops[k].op1_def = ssa_vars_count;
  632. var[EX_VAR_TO_NUM(opline->op1.var)] = ssa_vars_count;
  633. ssa_vars_count++;
  634. //NEW_SSA_VAR(opline+->op1.var)
  635. }
  636. break;
  637. case ZEND_SEND_VAR:
  638. case ZEND_CAST:
  639. case ZEND_QM_ASSIGN:
  640. case ZEND_JMP_SET:
  641. case ZEND_COALESCE:
  642. if ((build_flags & ZEND_SSA_RC_INFERENCE) && opline->op1_type == IS_CV) {
  643. ssa_ops[k].op1_def = ssa_vars_count;
  644. var[EX_VAR_TO_NUM(opline->op1.var)] = ssa_vars_count;
  645. ssa_vars_count++;
  646. //NEW_SSA_VAR(opline->op1.var)
  647. }
  648. break;
  649. case ZEND_SEND_VAR_NO_REF:
  650. case ZEND_SEND_VAR_NO_REF_EX:
  651. case ZEND_SEND_VAR_EX:
  652. case ZEND_SEND_FUNC_ARG:
  653. case ZEND_SEND_REF:
  654. case ZEND_SEND_UNPACK:
  655. case ZEND_FE_RESET_RW:
  656. case ZEND_MAKE_REF:
  657. if (opline->op1_type == IS_CV) {
  658. ssa_ops[k].op1_def = ssa_vars_count;
  659. var[EX_VAR_TO_NUM(opline->op1.var)] = ssa_vars_count;
  660. ssa_vars_count++;
  661. //NEW_SSA_VAR(opline->op1.var)
  662. }
  663. break;
  664. case ZEND_FE_RESET_R:
  665. if ((build_flags & ZEND_SSA_RC_INFERENCE) && opline->op1_type == IS_CV) {
  666. ssa_ops[k].op1_def = ssa_vars_count;
  667. var[EX_VAR_TO_NUM(opline->op1.var)] = ssa_vars_count;
  668. ssa_vars_count++;
  669. //NEW_SSA_VAR(opline->op1.var)
  670. }
  671. break;
  672. case ZEND_ASSIGN_ADD:
  673. case ZEND_ASSIGN_SUB:
  674. case ZEND_ASSIGN_MUL:
  675. case ZEND_ASSIGN_DIV:
  676. case ZEND_ASSIGN_MOD:
  677. case ZEND_ASSIGN_SL:
  678. case ZEND_ASSIGN_SR:
  679. case ZEND_ASSIGN_CONCAT:
  680. case ZEND_ASSIGN_BW_OR:
  681. case ZEND_ASSIGN_BW_AND:
  682. case ZEND_ASSIGN_BW_XOR:
  683. case ZEND_ASSIGN_POW:
  684. case ZEND_PRE_INC:
  685. case ZEND_PRE_DEC:
  686. case ZEND_POST_INC:
  687. case ZEND_POST_DEC:
  688. if (opline->op1_type == IS_CV) {
  689. ssa_ops[k].op1_def = ssa_vars_count;
  690. var[EX_VAR_TO_NUM(opline->op1.var)] = ssa_vars_count;
  691. ssa_vars_count++;
  692. //NEW_SSA_VAR(opline->op1.var)
  693. }
  694. break;
  695. case ZEND_UNSET_CV:
  696. ssa_ops[k].op1_def = ssa_vars_count;
  697. var[EX_VAR_TO_NUM(opline->op1.var)] = ssa_vars_count;
  698. ssa_vars_count++;
  699. break;
  700. case ZEND_UNSET_DIM:
  701. case ZEND_UNSET_OBJ:
  702. case ZEND_FETCH_DIM_W:
  703. case ZEND_FETCH_DIM_RW:
  704. case ZEND_FETCH_DIM_FUNC_ARG:
  705. case ZEND_FETCH_DIM_UNSET:
  706. case ZEND_FETCH_OBJ_W:
  707. case ZEND_FETCH_OBJ_RW:
  708. case ZEND_FETCH_OBJ_FUNC_ARG:
  709. case ZEND_FETCH_OBJ_UNSET:
  710. case ZEND_FETCH_LIST_W:
  711. if (opline->op1_type == IS_CV) {
  712. ssa_ops[k].op1_def = ssa_vars_count;
  713. var[EX_VAR_TO_NUM(opline->op1.var)] = ssa_vars_count;
  714. ssa_vars_count++;
  715. //NEW_SSA_VAR(opline->op1.var)
  716. }
  717. break;
  718. case ZEND_BIND_LEXICAL:
  719. if ((opline->extended_value & ZEND_BIND_REF) || (build_flags & ZEND_SSA_RC_INFERENCE)) {
  720. ssa_ops[k].op2_def = ssa_vars_count;
  721. var[EX_VAR_TO_NUM(opline->op2.var)] = ssa_vars_count;
  722. ssa_vars_count++;
  723. }
  724. break;
  725. case ZEND_YIELD:
  726. if (opline->op1_type == IS_CV
  727. && ((op_array->fn_flags & ZEND_ACC_RETURN_REFERENCE)
  728. || (build_flags & ZEND_SSA_RC_INFERENCE))) {
  729. ssa_ops[k].op1_def = ssa_vars_count;
  730. var[EX_VAR_TO_NUM(opline->op1.var)] = ssa_vars_count;
  731. ssa_vars_count++;
  732. }
  733. break;
  734. case ZEND_VERIFY_RETURN_TYPE:
  735. if (opline->op1_type & (IS_TMP_VAR|IS_VAR|IS_CV)) {
  736. ssa_ops[k].op1_def = ssa_vars_count;
  737. var[EX_VAR_TO_NUM(opline->op1.var)] = ssa_vars_count;
  738. ssa_vars_count++;
  739. //NEW_SSA_VAR(opline->op1.var)
  740. }
  741. break;
  742. default:
  743. break;
  744. }
  745. if (opline->result_type == IS_CV) {
  746. if ((build_flags & ZEND_SSA_USE_CV_RESULTS)
  747. && opline->opcode != ZEND_RECV) {
  748. ssa_ops[k].result_use = var[EX_VAR_TO_NUM(opline->result.var)];
  749. }
  750. ssa_ops[k].result_def = ssa_vars_count;
  751. var[EX_VAR_TO_NUM(opline->result.var)] = ssa_vars_count;
  752. ssa_vars_count++;
  753. //NEW_SSA_VAR(opline->result.var)
  754. } else if (opline->result_type & (IS_VAR|IS_TMP_VAR)) {
  755. ssa_ops[k].result_def = ssa_vars_count;
  756. var[EX_VAR_TO_NUM(opline->result.var)] = ssa_vars_count;
  757. ssa_vars_count++;
  758. //NEW_SSA_VAR(op_array->last_var + opline->result.var)
  759. }
  760. }
  761. }
  762. for (i = 0; i < blocks[n].successors_count; i++) {
  763. int succ = blocks[n].successors[i];
  764. zend_ssa_phi *p;
  765. for (p = ssa_blocks[succ].phis; p; p = p->next) {
  766. if (p->pi == n) {
  767. /* e-SSA Pi */
  768. if (p->has_range_constraint) {
  769. if (p->constraint.range.min_var >= 0) {
  770. p->constraint.range.min_ssa_var = var[p->constraint.range.min_var];
  771. }
  772. if (p->constraint.range.max_var >= 0) {
  773. p->constraint.range.max_ssa_var = var[p->constraint.range.max_var];
  774. }
  775. }
  776. for (j = 0; j < blocks[succ].predecessors_count; j++) {
  777. p->sources[j] = var[p->var];
  778. }
  779. if (p->ssa_var < 0) {
  780. p->ssa_var = ssa_vars_count;
  781. ssa_vars_count++;
  782. }
  783. } else if (p->pi < 0) {
  784. /* Normal Phi */
  785. for (j = 0; j < blocks[succ].predecessors_count; j++)
  786. if (ssa->cfg.predecessors[blocks[succ].predecessor_offset + j] == n) {
  787. break;
  788. }
  789. ZEND_ASSERT(j < blocks[succ].predecessors_count);
  790. p->sources[j] = var[p->var];
  791. }
  792. }
  793. for (p = ssa_blocks[succ].phis; p && (p->pi >= 0); p = p->next) {
  794. if (p->pi == n) {
  795. zend_ssa_phi *q = p->next;
  796. while (q) {
  797. if (q->pi < 0 && q->var == p->var) {
  798. for (j = 0; j < blocks[succ].predecessors_count; j++) {
  799. if (ssa->cfg.predecessors[blocks[succ].predecessor_offset + j] == n) {
  800. break;
  801. }
  802. }
  803. ZEND_ASSERT(j < blocks[succ].predecessors_count);
  804. q->sources[j] = p->ssa_var;
  805. }
  806. q = q->next;
  807. }
  808. }
  809. }
  810. }
  811. ssa->vars_count = ssa_vars_count;
  812. j = blocks[n].children;
  813. while (j >= 0) {
  814. // FIXME: Tail call optimization?
  815. if (zend_ssa_rename(op_array, build_flags, ssa, var, j) != SUCCESS)
  816. return FAILURE;
  817. j = blocks[j].next_child;
  818. }
  819. if (tmp) {
  820. free_alloca(tmp, use_heap);
  821. }
  822. return SUCCESS;
  823. }
  824. /* }}} */
  825. int zend_build_ssa(zend_arena **arena, const zend_script *script, const zend_op_array *op_array, uint32_t build_flags, zend_ssa *ssa) /* {{{ */
  826. {
  827. zend_basic_block *blocks = ssa->cfg.blocks;
  828. zend_ssa_block *ssa_blocks;
  829. int blocks_count = ssa->cfg.blocks_count;
  830. uint32_t set_size;
  831. zend_bitset def, in, phi;
  832. int *var = NULL;
  833. int i, j, k, changed;
  834. zend_dfg dfg;
  835. ALLOCA_FLAG(dfg_use_heap)
  836. ALLOCA_FLAG(var_use_heap)
  837. if ((blocks_count * (op_array->last_var + op_array->T)) > 4 * 1024 * 1024) {
  838. /* Don't buld SSA for very big functions */
  839. return FAILURE;
  840. }
  841. ssa->rt_constants = (build_flags & ZEND_RT_CONSTANTS);
  842. ssa_blocks = zend_arena_calloc(arena, blocks_count, sizeof(zend_ssa_block));
  843. ssa->blocks = ssa_blocks;
  844. /* Compute Variable Liveness */
  845. dfg.vars = op_array->last_var + op_array->T;
  846. dfg.size = set_size = zend_bitset_len(dfg.vars);
  847. dfg.tmp = do_alloca((set_size * sizeof(zend_ulong)) * (blocks_count * 4 + 1), dfg_use_heap);
  848. memset(dfg.tmp, 0, (set_size * sizeof(zend_ulong)) * (blocks_count * 4 + 1));
  849. dfg.def = dfg.tmp + set_size;
  850. dfg.use = dfg.def + set_size * blocks_count;
  851. dfg.in = dfg.use + set_size * blocks_count;
  852. dfg.out = dfg.in + set_size * blocks_count;
  853. if (zend_build_dfg(op_array, &ssa->cfg, &dfg, build_flags) != SUCCESS) {
  854. free_alloca(dfg.tmp, dfg_use_heap);
  855. return FAILURE;
  856. }
  857. if (build_flags & ZEND_SSA_DEBUG_LIVENESS) {
  858. zend_dump_dfg(op_array, &ssa->cfg, &dfg);
  859. }
  860. def = dfg.def;
  861. in = dfg.in;
  862. /* Reuse the "use" set, as we no longer need it */
  863. phi = dfg.use;
  864. zend_bitset_clear(phi, set_size * blocks_count);
  865. /* Place e-SSA pis. This will add additional "def" points, so it must
  866. * happen before def propagation. */
  867. place_essa_pis(arena, script, op_array, build_flags, ssa, &dfg);
  868. /* SSA construction, Step 1: Propagate "def" sets in merge points */
  869. do {
  870. changed = 0;
  871. for (j = 0; j < blocks_count; j++) {
  872. zend_bitset def_j = def + j * set_size, phi_j = phi + j * set_size;
  873. if ((blocks[j].flags & ZEND_BB_REACHABLE) == 0) {
  874. continue;
  875. }
  876. if (blocks[j].predecessors_count > 1) {
  877. if (blocks[j].flags & ZEND_BB_IRREDUCIBLE_LOOP) {
  878. /* Prevent any values from flowing into irreducible loops by
  879. replacing all incoming values with explicit phis. The
  880. register allocator depends on this property. */
  881. zend_bitset_union(phi_j, in + (j * set_size), set_size);
  882. } else {
  883. for (k = 0; k < blocks[j].predecessors_count; k++) {
  884. i = ssa->cfg.predecessors[blocks[j].predecessor_offset + k];
  885. while (i != -1 && i != blocks[j].idom) {
  886. zend_bitset_union_with_intersection(
  887. phi_j, phi_j, def + (i * set_size), in + (j * set_size), set_size);
  888. i = blocks[i].idom;
  889. }
  890. }
  891. }
  892. if (!zend_bitset_subset(phi_j, def_j, set_size)) {
  893. zend_bitset_union(def_j, phi_j, set_size);
  894. changed = 1;
  895. }
  896. }
  897. }
  898. } while (changed);
  899. /* SSA construction, Step 2: Phi placement based on Dominance Frontiers */
  900. var = do_alloca(sizeof(int) * (op_array->last_var + op_array->T), var_use_heap);
  901. if (!var) {
  902. free_alloca(dfg.tmp, dfg_use_heap);
  903. return FAILURE;
  904. }
  905. for (j = 0; j < blocks_count; j++) {
  906. if ((blocks[j].flags & ZEND_BB_REACHABLE) == 0) {
  907. continue;
  908. }
  909. if (!zend_bitset_empty(phi + j * set_size, set_size)) {
  910. ZEND_BITSET_REVERSE_FOREACH(phi + j * set_size, set_size, i) {
  911. zend_ssa_phi *phi = zend_arena_calloc(arena, 1,
  912. ZEND_MM_ALIGNED_SIZE(sizeof(zend_ssa_phi)) +
  913. ZEND_MM_ALIGNED_SIZE(sizeof(int) * blocks[j].predecessors_count) +
  914. sizeof(void*) * blocks[j].predecessors_count);
  915. phi->sources = (int*)(((char*)phi) + ZEND_MM_ALIGNED_SIZE(sizeof(zend_ssa_phi)));
  916. memset(phi->sources, 0xff, sizeof(int) * blocks[j].predecessors_count);
  917. phi->use_chains = (zend_ssa_phi**)(((char*)phi->sources) + ZEND_MM_ALIGNED_SIZE(sizeof(int) * ssa->cfg.blocks[j].predecessors_count));
  918. phi->pi = -1;
  919. phi->var = i;
  920. phi->ssa_var = -1;
  921. /* Place phis after pis */
  922. {
  923. zend_ssa_phi **pp = &ssa_blocks[j].phis;
  924. while (*pp) {
  925. if ((*pp)->pi < 0) {
  926. break;
  927. }
  928. pp = &(*pp)->next;
  929. }
  930. phi->next = *pp;
  931. *pp = phi;
  932. }
  933. } ZEND_BITSET_FOREACH_END();
  934. }
  935. }
  936. if (build_flags & ZEND_SSA_DEBUG_PHI_PLACEMENT) {
  937. zend_dump_phi_placement(op_array, ssa);
  938. }
  939. /* SSA construction, Step 3: Renaming */
  940. ssa->ops = zend_arena_calloc(arena, op_array->last, sizeof(zend_ssa_op));
  941. memset(ssa->ops, 0xff, op_array->last * sizeof(zend_ssa_op));
  942. memset(var + op_array->last_var, 0xff, op_array->T * sizeof(int));
  943. /* Create uninitialized SSA variables for each CV */
  944. for (j = 0; j < op_array->last_var; j++) {
  945. var[j] = j;
  946. }
  947. ssa->vars_count = op_array->last_var;
  948. if (zend_ssa_rename(op_array, build_flags, ssa, var, 0) != SUCCESS) {
  949. free_alloca(var, var_use_heap);
  950. free_alloca(dfg.tmp, dfg_use_heap);
  951. return FAILURE;
  952. }
  953. free_alloca(var, var_use_heap);
  954. free_alloca(dfg.tmp, dfg_use_heap);
  955. return SUCCESS;
  956. }
  957. /* }}} */
  958. int zend_ssa_compute_use_def_chains(zend_arena **arena, const zend_op_array *op_array, zend_ssa *ssa) /* {{{ */
  959. {
  960. zend_ssa_var *ssa_vars;
  961. int i;
  962. if (!ssa->vars) {
  963. ssa->vars = zend_arena_calloc(arena, ssa->vars_count, sizeof(zend_ssa_var));
  964. }
  965. ssa_vars = ssa->vars;
  966. for (i = 0; i < op_array->last_var; i++) {
  967. ssa_vars[i].var = i;
  968. ssa_vars[i].scc = -1;
  969. ssa_vars[i].definition = -1;
  970. ssa_vars[i].use_chain = -1;
  971. }
  972. for (i = op_array->last_var; i < ssa->vars_count; i++) {
  973. ssa_vars[i].var = -1;
  974. ssa_vars[i].scc = -1;
  975. ssa_vars[i].definition = -1;
  976. ssa_vars[i].use_chain = -1;
  977. }
  978. for (i = op_array->last - 1; i >= 0; i--) {
  979. zend_ssa_op *op = ssa->ops + i;
  980. if (op->op1_use >= 0) {
  981. op->op1_use_chain = ssa_vars[op->op1_use].use_chain;
  982. ssa_vars[op->op1_use].use_chain = i;
  983. }
  984. if (op->op2_use >= 0 && op->op2_use != op->op1_use) {
  985. op->op2_use_chain = ssa_vars[op->op2_use].use_chain;
  986. ssa_vars[op->op2_use].use_chain = i;
  987. }
  988. if (op->result_use >= 0 && op->result_use != op->op1_use && op->result_use != op->op2_use) {
  989. op->res_use_chain = ssa_vars[op->result_use].use_chain;
  990. ssa_vars[op->result_use].use_chain = i;
  991. }
  992. if (op->op1_def >= 0) {
  993. ssa_vars[op->op1_def].var = EX_VAR_TO_NUM(op_array->opcodes[i].op1.var);
  994. ssa_vars[op->op1_def].definition = i;
  995. }
  996. if (op->op2_def >= 0) {
  997. ssa_vars[op->op2_def].var = EX_VAR_TO_NUM(op_array->opcodes[i].op2.var);
  998. ssa_vars[op->op2_def].definition = i;
  999. }
  1000. if (op->result_def >= 0) {
  1001. ssa_vars[op->result_def].var = EX_VAR_TO_NUM(op_array->opcodes[i].result.var);
  1002. ssa_vars[op->result_def].definition = i;
  1003. }
  1004. }
  1005. for (i = 0; i < ssa->cfg.blocks_count; i++) {
  1006. zend_ssa_phi *phi = ssa->blocks[i].phis;
  1007. while (phi) {
  1008. phi->block = i;
  1009. ssa_vars[phi->ssa_var].var = phi->var;
  1010. ssa_vars[phi->ssa_var].definition_phi = phi;
  1011. if (phi->pi >= 0) {
  1012. zend_ssa_phi *p;
  1013. ZEND_ASSERT(phi->sources[0] >= 0);
  1014. p = ssa_vars[phi->sources[0]].phi_use_chain;
  1015. while (p && p != phi) {
  1016. p = zend_ssa_next_use_phi(ssa, phi->sources[0], p);
  1017. }
  1018. if (!p) {
  1019. phi->use_chains[0] = ssa_vars[phi->sources[0]].phi_use_chain;
  1020. ssa_vars[phi->sources[0]].phi_use_chain = phi;
  1021. }
  1022. if (phi->has_range_constraint) {
  1023. /* min and max variables can't be used together */
  1024. zend_ssa_range_constraint *constraint = &phi->constraint.range;
  1025. if (constraint->min_ssa_var >= 0) {
  1026. phi->sym_use_chain = ssa_vars[constraint->min_ssa_var].sym_use_chain;
  1027. ssa_vars[constraint->min_ssa_var].sym_use_chain = phi;
  1028. } else if (constraint->max_ssa_var >= 0) {
  1029. phi->sym_use_chain = ssa_vars[constraint->max_ssa_var].sym_use_chain;
  1030. ssa_vars[constraint->max_ssa_var].sym_use_chain = phi;
  1031. }
  1032. }
  1033. } else {
  1034. int j;
  1035. for (j = 0; j < ssa->cfg.blocks[i].predecessors_count; j++) {
  1036. zend_ssa_phi *p;
  1037. ZEND_ASSERT(phi->sources[j] >= 0);
  1038. p = ssa_vars[phi->sources[j]].phi_use_chain;
  1039. while (p && p != phi) {
  1040. p = zend_ssa_next_use_phi(ssa, phi->sources[j], p);
  1041. }
  1042. if (!p) {
  1043. phi->use_chains[j] = ssa_vars[phi->sources[j]].phi_use_chain;
  1044. ssa_vars[phi->sources[j]].phi_use_chain = phi;
  1045. }
  1046. }
  1047. }
  1048. phi = phi->next;
  1049. }
  1050. }
  1051. /* Mark indirectly accessed variables */
  1052. for (i = 0; i < op_array->last_var; i++) {
  1053. if ((ssa->cfg.flags & ZEND_FUNC_INDIRECT_VAR_ACCESS)) {
  1054. ssa_vars[i].alias = SYMTABLE_ALIAS;
  1055. } else if (zend_string_equals_literal(op_array->vars[i], "php_errormsg")) {
  1056. ssa_vars[i].alias = PHP_ERRORMSG_ALIAS;
  1057. } else if (zend_string_equals_literal(op_array->vars[i], "http_response_header")) {
  1058. ssa_vars[i].alias = HTTP_RESPONSE_HEADER_ALIAS;
  1059. }
  1060. }
  1061. for (i = op_array->last_var; i < ssa->vars_count; i++) {
  1062. if (ssa_vars[i].var < op_array->last_var) {
  1063. ssa_vars[i].alias = ssa_vars[ssa_vars[i].var].alias;
  1064. }
  1065. }
  1066. return SUCCESS;
  1067. }
  1068. /* }}} */
  1069. int zend_ssa_unlink_use_chain(zend_ssa *ssa, int op, int var) /* {{{ */
  1070. {
  1071. if (ssa->vars[var].use_chain == op) {
  1072. ssa->vars[var].use_chain = zend_ssa_next_use(ssa->ops, var, op);
  1073. return 1;
  1074. } else {
  1075. int use = ssa->vars[var].use_chain;
  1076. while (use >= 0) {
  1077. if (ssa->ops[use].result_use == var) {
  1078. if (ssa->ops[use].res_use_chain == op) {
  1079. ssa->ops[use].res_use_chain = zend_ssa_next_use(ssa->ops, var, op);
  1080. return 1;
  1081. } else {
  1082. use = ssa->ops[use].res_use_chain;
  1083. }
  1084. } else if (ssa->ops[use].op1_use == var) {
  1085. if (ssa->ops[use].op1_use_chain == op) {
  1086. ssa->ops[use].op1_use_chain = zend_ssa_next_use(ssa->ops, var, op);
  1087. return 1;
  1088. } else {
  1089. use = ssa->ops[use].op1_use_chain;
  1090. }
  1091. } else if (ssa->ops[use].op2_use == var) {
  1092. if (ssa->ops[use].op2_use_chain == op) {
  1093. ssa->ops[use].op2_use_chain = zend_ssa_next_use(ssa->ops, var, op);
  1094. return 1;
  1095. } else {
  1096. use = ssa->ops[use].op2_use_chain;
  1097. }
  1098. } else {
  1099. break;
  1100. }
  1101. }
  1102. /* something wrong */
  1103. ZEND_ASSERT(0);
  1104. return 0;
  1105. }
  1106. }
  1107. /* }}} */
  1108. void zend_ssa_remove_instr(zend_ssa *ssa, zend_op *opline, zend_ssa_op *ssa_op) /* {{{ */
  1109. {
  1110. if (ssa_op->result_use >= 0) {
  1111. zend_ssa_unlink_use_chain(ssa, ssa_op - ssa->ops, ssa_op->result_use);
  1112. ssa_op->result_use = -1;
  1113. ssa_op->res_use_chain = -1;
  1114. }
  1115. if (ssa_op->op1_use >= 0) {
  1116. if (ssa_op->op1_use != ssa_op->op2_use) {
  1117. zend_ssa_unlink_use_chain(ssa, ssa_op - ssa->ops, ssa_op->op1_use);
  1118. } else {
  1119. ssa_op->op2_use_chain = ssa_op->op1_use_chain;
  1120. }
  1121. ssa_op->op1_use = -1;
  1122. ssa_op->op1_use_chain = -1;
  1123. }
  1124. if (ssa_op->op2_use >= 0) {
  1125. zend_ssa_unlink_use_chain(ssa, ssa_op - ssa->ops, ssa_op->op2_use);
  1126. ssa_op->op2_use = -1;
  1127. ssa_op->op2_use_chain = -1;
  1128. }
  1129. /* We let the caller make sure that all defs are gone */
  1130. ZEND_ASSERT(ssa_op->result_def == -1);
  1131. ZEND_ASSERT(ssa_op->op1_def == -1);
  1132. ZEND_ASSERT(ssa_op->op2_def == -1);
  1133. MAKE_NOP(opline);
  1134. }
  1135. /* }}} */
  1136. static inline zend_ssa_phi **zend_ssa_next_use_phi_ptr(zend_ssa *ssa, int var, zend_ssa_phi *p) /* {{{ */
  1137. {
  1138. if (p->pi >= 0) {
  1139. return &p->use_chains[0];
  1140. } else {
  1141. int j;
  1142. for (j = 0; j < ssa->cfg.blocks[p->block].predecessors_count; j++) {
  1143. if (p->sources[j] == var) {
  1144. return &p->use_chains[j];
  1145. }
  1146. }
  1147. }
  1148. ZEND_ASSERT(0);
  1149. return NULL;
  1150. }
  1151. /* }}} */
  1152. /* May be called even if source is not used in the phi (useful when removing uses in a phi
  1153. * with multiple identical operands) */
  1154. static inline void zend_ssa_remove_use_of_phi_source(zend_ssa *ssa, zend_ssa_phi *phi, int source, zend_ssa_phi *next_use_phi) /* {{{ */
  1155. {
  1156. zend_ssa_phi **cur = &ssa->vars[source].phi_use_chain;
  1157. while (*cur && *cur != phi) {
  1158. cur = zend_ssa_next_use_phi_ptr(ssa, source, *cur);
  1159. }
  1160. if (*cur) {
  1161. *cur = next_use_phi;
  1162. }
  1163. }
  1164. /* }}} */
  1165. static void zend_ssa_remove_uses_of_phi_sources(zend_ssa *ssa, zend_ssa_phi *phi) /* {{{ */
  1166. {
  1167. int source;
  1168. FOREACH_PHI_SOURCE(phi, source) {
  1169. zend_ssa_remove_use_of_phi_source(ssa, phi, source, zend_ssa_next_use_phi(ssa, source, phi));
  1170. } FOREACH_PHI_SOURCE_END();
  1171. }
  1172. /* }}} */
  1173. static void zend_ssa_remove_phi_from_block(zend_ssa *ssa, zend_ssa_phi *phi) /* {{{ */
  1174. {
  1175. zend_ssa_block *block = &ssa->blocks[phi->block];
  1176. zend_ssa_phi **cur = &block->phis;
  1177. while (*cur != phi) {
  1178. ZEND_ASSERT(*cur != NULL);
  1179. cur = &(*cur)->next;
  1180. }
  1181. *cur = (*cur)->next;
  1182. }
  1183. /* }}} */
  1184. static inline void zend_ssa_remove_defs_of_instr(zend_ssa *ssa, zend_ssa_op *ssa_op) /* {{{ */
  1185. {
  1186. if (ssa_op->op1_def >= 0) {
  1187. zend_ssa_remove_uses_of_var(ssa, ssa_op->op1_def);
  1188. zend_ssa_remove_op1_def(ssa, ssa_op);
  1189. }
  1190. if (ssa_op->op2_def >= 0) {
  1191. zend_ssa_remove_uses_of_var(ssa, ssa_op->op2_def);
  1192. zend_ssa_remove_op2_def(ssa, ssa_op);
  1193. }
  1194. if (ssa_op->result_def >= 0) {
  1195. zend_ssa_remove_uses_of_var(ssa, ssa_op->result_def);
  1196. zend_ssa_remove_result_def(ssa, ssa_op);
  1197. }
  1198. }
  1199. /* }}} */
  1200. static inline void zend_ssa_remove_phi_source(zend_ssa *ssa, zend_ssa_phi *phi, int pred_offset, int predecessors_count) /* {{{ */
  1201. {
  1202. int j, var_num = phi->sources[pred_offset];
  1203. zend_ssa_phi *next_phi = phi->use_chains[pred_offset];
  1204. predecessors_count--;
  1205. if (pred_offset < predecessors_count) {
  1206. memmove(phi->sources + pred_offset, phi->sources + pred_offset + 1, (predecessors_count - pred_offset) * sizeof(uint32_t));
  1207. memmove(phi->use_chains + pred_offset, phi->use_chains + pred_offset + 1, (predecessors_count - pred_offset) * sizeof(zend_ssa_phi*));
  1208. }
  1209. /* Check if they same var is used in a different phi operand as well, in this case we don't
  1210. * need to adjust the use chain (but may have to move the next pointer). */
  1211. for (j = 0; j < predecessors_count; j++) {
  1212. if (phi->sources[j] == var_num) {
  1213. if (j < pred_offset) {
  1214. if (next_phi == NULL) {
  1215. next_phi = phi->use_chains[pred_offset];
  1216. } else {
  1217. ZEND_ASSERT(phi->use_chains[pred_offset] == NULL);
  1218. }
  1219. } else if (j >= pred_offset) {
  1220. phi->use_chains[j] = next_phi;
  1221. }
  1222. return;
  1223. }
  1224. }
  1225. /* Variable only used in one operand, remove the phi from the use chain. */
  1226. zend_ssa_remove_use_of_phi_source(ssa, phi, var_num, next_phi);
  1227. }
  1228. /* }}} */
  1229. void zend_ssa_remove_phi(zend_ssa *ssa, zend_ssa_phi *phi) /* {{{ */
  1230. {
  1231. ZEND_ASSERT(phi->ssa_var >= 0);
  1232. ZEND_ASSERT(ssa->vars[phi->ssa_var].use_chain < 0
  1233. && ssa->vars[phi->ssa_var].phi_use_chain == NULL);
  1234. zend_ssa_remove_uses_of_phi_sources(ssa, phi);
  1235. zend_ssa_remove_phi_from_block(ssa, phi);
  1236. ssa->vars[phi->ssa_var].definition_phi = NULL;
  1237. phi->ssa_var = -1;
  1238. }
  1239. /* }}} */
  1240. void zend_ssa_remove_uses_of_var(zend_ssa *ssa, int var_num) /* {{{ */
  1241. {
  1242. zend_ssa_var *var = &ssa->vars[var_num];
  1243. zend_ssa_phi *phi;
  1244. int use;
  1245. FOREACH_PHI_USE(var, phi) {
  1246. int i, end = NUM_PHI_SOURCES(phi);
  1247. for (i = 0; i < end; i++) {
  1248. if (phi->sources[i] == var_num) {
  1249. phi->use_chains[i] = NULL;
  1250. }
  1251. }
  1252. } FOREACH_PHI_USE_END();
  1253. var->phi_use_chain = NULL;
  1254. FOREACH_USE(var, use) {
  1255. zend_ssa_op *ssa_op = &ssa->ops[use];
  1256. if (ssa_op->op1_use == var_num) {
  1257. ssa_op->op1_use = -1;
  1258. ssa_op->op1_use_chain = -1;
  1259. }
  1260. if (ssa_op->op2_use == var_num) {
  1261. ssa_op->op2_use = -1;
  1262. ssa_op->op2_use_chain = -1;
  1263. }
  1264. if (ssa_op->result_use == var_num) {
  1265. ssa_op->result_use = -1;
  1266. ssa_op->res_use_chain = -1;
  1267. }
  1268. } FOREACH_USE_END();
  1269. var->use_chain = -1;
  1270. }
  1271. /* }}} */
  1272. void zend_ssa_remove_predecessor(zend_ssa *ssa, int from, int to) /* {{{ */
  1273. {
  1274. zend_basic_block *next_block = &ssa->cfg.blocks[to];
  1275. zend_ssa_block *next_ssa_block = &ssa->blocks[to];
  1276. zend_ssa_phi *phi;
  1277. int j;
  1278. /* Find at which predecessor offset this block is referenced */
  1279. int pred_offset = -1;
  1280. int *predecessors = &ssa->cfg.predecessors[next_block->predecessor_offset];
  1281. for (j = 0; j < next_block->predecessors_count; j++) {
  1282. if (predecessors[j] == from) {
  1283. pred_offset = j;
  1284. break;
  1285. }
  1286. }
  1287. /* If there are duplicate successors, the predecessors may have been removed in
  1288. * a previous iteration already. */
  1289. if (pred_offset == -1) {
  1290. return;
  1291. }
  1292. /* For phis in successor blocks, remove the operands associated with this block */
  1293. for (phi = next_ssa_block->phis; phi; phi = phi->next) {
  1294. if (phi->pi >= 0) {
  1295. if (phi->pi == from) {
  1296. zend_ssa_remove_uses_of_var(ssa, phi->ssa_var);
  1297. zend_ssa_remove_phi(ssa, phi);
  1298. }
  1299. } else {
  1300. ZEND_ASSERT(phi->sources[pred_offset] >= 0);
  1301. zend_ssa_remove_phi_source(ssa, phi, pred_offset, next_block->predecessors_count);
  1302. }
  1303. }
  1304. /* Remove this predecessor */
  1305. next_block->predecessors_count--;
  1306. if (pred_offset < next_block->predecessors_count) {
  1307. predecessors = &ssa->cfg.predecessors[next_block->predecessor_offset + pred_offset];
  1308. memmove(predecessors, predecessors + 1, (next_block->predecessors_count - pred_offset) * sizeof(uint32_t));
  1309. }
  1310. }
  1311. /* }}} */
  1312. void zend_ssa_remove_block(zend_op_array *op_array, zend_ssa *ssa, int i) /* {{{ */
  1313. {
  1314. zend_basic_block *block = &ssa->cfg.blocks[i];
  1315. zend_ssa_block *ssa_block = &ssa->blocks[i];
  1316. int *predecessors;
  1317. zend_ssa_phi *phi;
  1318. int j, s;
  1319. block->flags &= ~ZEND_BB_REACHABLE;
  1320. /* Removes phis in this block */
  1321. for (phi = ssa_block->phis; phi; phi = phi->next) {
  1322. zend_ssa_remove_uses_of_var(ssa, phi->ssa_var);
  1323. zend_ssa_remove_phi(ssa, phi);
  1324. }
  1325. /* Remove instructions in this block */
  1326. for (j = block->start; j < block->start + block->len; j++) {
  1327. if (op_array->opcodes[j].opcode == ZEND_NOP) {
  1328. continue;
  1329. }
  1330. if (op_array->opcodes[j].result_type & (IS_TMP_VAR|IS_VAR)) {
  1331. zend_optimizer_remove_live_range_ex(op_array, op_array->opcodes[j].result.var, j);
  1332. }
  1333. zend_ssa_remove_defs_of_instr(ssa, &ssa->ops[j]);
  1334. zend_ssa_remove_instr(ssa, &op_array->opcodes[j], &ssa->ops[j]);
  1335. }
  1336. for (s = 0; s < block->successors_count; s++) {
  1337. zend_ssa_remove_predecessor(ssa, i, block->successors[s]);
  1338. }
  1339. /* Remove successors of predecessors */
  1340. predecessors = &ssa->cfg.predecessors[block->predecessor_offset];
  1341. for (j = 0; j < block->predecessors_count; j++) {
  1342. if (predecessors[j] >= 0) {
  1343. zend_basic_block *prev_block = &ssa->cfg.blocks[predecessors[j]];
  1344. for (s = 0; s < prev_block->successors_count; s++) {
  1345. if (prev_block->successors[s] == i) {
  1346. memmove(prev_block->successors + s,
  1347. prev_block->successors + s + 1,
  1348. sizeof(int) * (prev_block->successors_count - s - 1));
  1349. prev_block->successors_count--;
  1350. s--;
  1351. }
  1352. }
  1353. }
  1354. }
  1355. block->successors_count = 0;
  1356. block->predecessors_count = 0;
  1357. /* Remove from dominators tree */
  1358. if (block->idom >= 0) {
  1359. j = ssa->cfg.blocks[block->idom].children;
  1360. if (j == i) {
  1361. ssa->cfg.blocks[block->idom].children = block->next_child;
  1362. } else if (j >= 0) {
  1363. while (ssa->cfg.blocks[j].next_child >= 0) {
  1364. if (ssa->cfg.blocks[j].next_child == i) {
  1365. ssa->cfg.blocks[j].next_child = block->next_child;
  1366. break;
  1367. }
  1368. j = ssa->cfg.blocks[j].next_child;
  1369. }
  1370. }
  1371. }
  1372. block->idom = -1;
  1373. block->level = -1;
  1374. block->children = -1;
  1375. block->next_child = -1;
  1376. }
  1377. /* }}} */
  1378. static void propagate_phi_type_widening(zend_ssa *ssa, int var) /* {{{ */
  1379. {
  1380. zend_ssa_phi *phi;
  1381. FOREACH_PHI_USE(&ssa->vars[var], phi) {
  1382. if (ssa->var_info[var].type & ~ssa->var_info[phi->ssa_var].type) {
  1383. ssa->var_info[phi->ssa_var].type |= ssa->var_info[var].type;
  1384. propagate_phi_type_widening(ssa, phi->ssa_var);
  1385. }
  1386. } FOREACH_PHI_USE_END();
  1387. }
  1388. /* }}} */
  1389. void zend_ssa_rename_var_uses(zend_ssa *ssa, int old, int new, zend_bool update_types) /* {{{ */
  1390. {
  1391. zend_ssa_var *old_var = &ssa->vars[old];
  1392. zend_ssa_var *new_var = &ssa->vars[new];
  1393. int use;
  1394. zend_ssa_phi *phi;
  1395. ZEND_ASSERT(old >= 0 && new >= 0);
  1396. ZEND_ASSERT(old != new);
  1397. /* Only a no_val is both variables are */
  1398. new_var->no_val &= old_var->no_val;
  1399. /* Update ssa_op use chains */
  1400. FOREACH_USE(old_var, use) {
  1401. zend_ssa_op *ssa_op = &ssa->ops[use];
  1402. /* If the op already uses the new var, don't add the op to the use
  1403. * list again. Instead move the use_chain to the correct operand. */
  1404. zend_bool add_to_use_chain = 1;
  1405. if (ssa_op->result_use == new) {
  1406. add_to_use_chain = 0;
  1407. } else if (ssa_op->op1_use == new) {
  1408. if (ssa_op->result_use == old) {
  1409. ssa_op->res_use_chain = ssa_op->op1_use_chain;
  1410. ssa_op->op1_use_chain = -1;
  1411. }
  1412. add_to_use_chain = 0;
  1413. } else if (ssa_op->op2_use == new) {
  1414. if (ssa_op->result_use == old) {
  1415. ssa_op->res_use_chain = ssa_op->op2_use_chain;
  1416. ssa_op->op2_use_chain = -1;
  1417. } else if (ssa_op->op1_use == old) {
  1418. ssa_op->op1_use_chain = ssa_op->op2_use_chain;
  1419. ssa_op->op2_use_chain = -1;
  1420. }
  1421. add_to_use_chain = 0;
  1422. }
  1423. /* Perform the actual renaming */
  1424. if (ssa_op->result_use == old) {
  1425. ssa_op->result_use = new;
  1426. }
  1427. if (ssa_op->op1_use == old) {
  1428. ssa_op->op1_use = new;
  1429. }
  1430. if (ssa_op->op2_use == old) {
  1431. ssa_op->op2_use = new;
  1432. }
  1433. /* Add op to use chain of new var (if it isn't already). We use the
  1434. * first use chain of (result, op1, op2) that has the new variable. */
  1435. if (add_to_use_chain) {
  1436. if (ssa_op->result_use == new) {
  1437. ssa_op->res_use_chain = new_var->use_chain;
  1438. new_var->use_chain = use;
  1439. } else if (ssa_op->op1_use == new) {
  1440. ssa_op->op1_use_chain = new_var->use_chain;
  1441. new_var->use_chain = use;
  1442. } else {
  1443. ZEND_ASSERT(ssa_op->op2_use == new);
  1444. ssa_op->op2_use_chain = new_var->use_chain;
  1445. new_var->use_chain = use;
  1446. }
  1447. }
  1448. } FOREACH_USE_END();
  1449. old_var->use_chain = -1;
  1450. /* Update phi use chains */
  1451. FOREACH_PHI_USE(old_var, phi) {
  1452. int j;
  1453. zend_bool after_first_new_source = 0;
  1454. /* If the phi already uses the new var, find its use chain, as we may
  1455. * need to move it to a different source operand. */
  1456. zend_ssa_phi **existing_use_chain_ptr = NULL;
  1457. for (j = 0; j < ssa->cfg.blocks[phi->block].predecessors_count; j++) {
  1458. if (phi->sources[j] == new) {
  1459. existing_use_chain_ptr = &phi->use_chains[j];
  1460. break;
  1461. }
  1462. }
  1463. for (j = 0; j < ssa->cfg.blocks[phi->block].predecessors_count; j++) {
  1464. if (phi->sources[j] == new) {
  1465. after_first_new_source = 1;
  1466. } else if (phi->sources[j] == old) {
  1467. phi->sources[j] = new;
  1468. /* Either move existing use chain to this source, or add the phi
  1469. * to the phi use chain of the new variables. Do this only once. */
  1470. if (!after_first_new_source) {
  1471. if (existing_use_chain_ptr) {
  1472. phi->use_chains[j] = *existing_use_chain_ptr;
  1473. *existing_use_chain_ptr = NULL;
  1474. } else {
  1475. phi->use_chains[j] = new_var->phi_use_chain;
  1476. new_var->phi_use_chain = phi;
  1477. }
  1478. after_first_new_source = 1;
  1479. }
  1480. }
  1481. }
  1482. /* Make sure phi result types are not incorrectly narrow after renaming.
  1483. * This should not normally happen, but can occur if we DCE an assignment
  1484. * or unset and there is an improper phi-indirected use lateron. */
  1485. // TODO Alternatively we could rerun type-inference after DCE
  1486. if (update_types && (ssa->var_info[new].type & ~ssa->var_info[phi->ssa_var].type)) {
  1487. ssa->var_info[phi->ssa_var].type |= ssa->var_info[new].type;
  1488. propagate_phi_type_widening(ssa, phi->ssa_var);
  1489. }
  1490. } FOREACH_PHI_USE_END();
  1491. old_var->phi_use_chain = NULL;
  1492. }
  1493. /* }}} */
  1494. /*
  1495. * Local variables:
  1496. * tab-width: 4
  1497. * c-basic-offset: 4
  1498. * indent-tabs-mode: t
  1499. * End:
  1500. */