Bernd Schmidt wrote:
Thanks. Let me see if I understood the problem - please correct me
if I describe anything incorrectly.
The previous cross jumping code didn't care about register liveness,
since it just checked for identical instruction streams. The new,
more clever code, requires that regsets are identical at the end of
the blocks we're trying to match. In addition, cross-jumping can
modify blocks, requiring us to update life information (by calling a
global update_life_info in struct_equiv_init), which is the really
expensive part that caused the slowdown (how often did we end up
updating life info?).
The code has always required that the set of sucessor blocks is
identical, which implies that the regsets of live registers at the end
of the blocks must be identical too. The old code didn't require
up-to-date liveness information. The new code does. As a sanity check,
it verifies that the regsets are equal.
Because the new code as of December actually updated life information
incorrectly, the global updates that were done had also quite a lot of
work to do (and didn't really do it right, because of the presence of
fake edges).
The new patch prevents multiple updates by introducing
STRUCT_EQUIV_SUSPEND_UPDATE. However, I don't see how this is safe
given that cross jumping will modify basic blocks and change the set
of registers live at their ends.
Is there a way to keep life info accurate when doing the cross jump
(so we don't set any dirty flags)? Or, possibly, change the algorithm
so that it visits blocks in a different order - dirtying more blocks
before doing a global life update?
As far as I can tell, the global_live_{start,end} information is now
kept up to date, although I have to admit that I don't really understand
what was meant with the comment
/* We may have some registers visible trought the block. */
that is placed before setting the dirty flag on the block.
The REG_DEAD / REG_UNUSED notes may get out date, but AFAICS they are
not needed inside the loop that does the cross-jumping, and there is a
global update afterwards.
I'm not sure what the best way to keep the svn history sane is.
When/if the patch is approved, should I first do an
svn merge -r108792:108791, check that in, and then apply the patch
with the actual new stuff?
Maybe
svn diff -r108792:108791 |patch -p0
patch <fixes.diff
svn commit
That is the easy way, but my concern was with keeping the information
from svn annotate as sane as possible. Presumably a merge or svn copy
could have preserved the old
history from before the patch back-out, but since another patch to
cfgcleanup has gone in in the meantime, an svn copy is no longer a
realistic option.