When assigning loop headers, we should treat already detected
loops as collapsed to their loop header, instead of ignoring them.
This fixes the loop header of BB2 in mandel2 if live-range CFG
splitting is enabled.
Instead of walking the DJ spanning tree upwards, record entry and
exit times during the DFS and use these to determine whether CJ
edges are sp-back edges.
The previous implementation was doing O(blocks*levels) iterations,
which for a linear-ish domtree is O(blocks^2). Avoid this by sorting
the blocks by decreasing level upfront.
As it drops the warning. This is more problematic with constant
propagation, as tests would fail.
Extract a zend_optimizer_classify_function() function, as its now
needed by zend_cfg and update_opN.
Do not mark loop var free blocks as reachable after all -- as we
can't construct SSA for unreachable blocks, this would cause
issues down the line.
Instead add an extra UNREACHABLE_FREE flag and retain only the
FREE instruction during NOP removal. (If we retain all
instructions in the BB we might leave a jump instruction that goes
into the nowhere.)
This slightly improves calls to regular function and method calls in cost of a bit slower generator initialization.
Separate call frame for generators, allocated on heap, now created by ZEND_GENERATOR_CREATE instruction.
The used dominator intersection algorithm assumes a postorder
numbering of the CFG. The reversal of our natural numbering is
quite similar to postorder, but not the same.
In the future we should precompute both preorder/postorder
numberings and orderings, as these are useful in many places.
We must not split at live range boundaries for SSA constructions,
otherwise an OP_DATA instruction may be separated into new block
and not picked up during renaming.
It's also unnecessary for this use case and only blows up the CFG.
This opcodes inserts a local CV into the closure static variable
table. This replaces the previous mechanism of having static
variables marked as LEXICAL, which perform a symtable lookup
during copying.
This means a) functions which contain closures no longer have to
rebuild their symtable (better performance) and b) we can now track
used variables in SSA.
The DECLARE_(ANON_)INHERITED_CLASS(_DELAYED) opcodes were
referencing the parent ce VAR through extended_value. This is
hacky and we can't track the def-use chain in SSA.
To avoid this, the layout of declaration opcodes is changed
as follows: op1 points to the lcname and rtd_key literals, in
that order. (For anon/lambda declarations only one of lcname or
rtd_key is present.) This frees up op2, which is now used to
reference the parent ce VAR in inheriting declarations. The
jmp offset for anon class declarations is moved frop op2 to
extended_value.
The changes were applied both to class and function declarations
to keep everything symmetric.