rbyd-rr: Rearranged diverged pruning/trimming after flipping
This was a bit more tricky than the other eager-flip related
transformations, mainly because we have to be careful to not prune the
diverging alt that connects the two diverged trunks. The diverging alt,
i.e. the first alt that diverges, passes all the criteria for pruning,
but is a bit special in that we need to keep it around until we stitch
the trunks together.
I ended up more-or-less just reverting the handling of both-diverging
nodes to being collapsed as a special case of our first encounter with
the diverging alt. Because we eagerly prune, both-diverging nodes can
only happen if they include the diverging alt. We can leveraging this to
simplify our diverging logic a bit, which is already crazy complicated.
Not only does this finish moving all of the alt-related logic into
"flipped space", it also moves all of the diverging logic together,
which is more readable and hopefully leads to better code deduplication
by the compiler.
Long story short, more code savings!
code stack
before: 34244 2864
after: 34176 (-0.2%) 2864 (+0.0%)
code frame stack
appendattr before: 2232 216 568
appendattr after: 2162 (-3.1%) 208 (-3.7%) 560 (-1.4%)
---
All of these code savings are making our 2-trunk range removal algorithm
more appealing:
code stack
rr-div-naive: 33968 2864
rr-div-altn: 34304 (+1.0%) 2864 (+0.0%)
rr-2trunk-altn: 34176 (+0.6%) 2864 (+0.0%)
code frame stack
appendattr rr-stitching: 1940 184 536
appendattr rr-div-naive: 2028 (+4.5%) 200 (+8.7%) 552 (+3.0%)
appendattr rr-div-altn: 2198 (+13.3%) 216 (+17.4%) 568 (+6.0%)
appendattr rr-2trunk-altn: 2162 (+11.4%) 208 (+13.0%) 560 (+4.5%)
That being said, it is getting increasingly hard to compare these
functions. You could argue the eager-flip transformations would also
result in code savings for the earlier iterations of our algorithm,
but it is worth noting the 2-trunk approach _did_ require more flips to
get working, so...
This commit is contained in:
@@ -2897,54 +2897,6 @@ trunk:;
|
||||
LFS_ASSERT(!(lfsr_tag_isred(alt) && lfsr_tag_isred(p[0].alt))
|
||||
|| lfsr_tag_isparallel(alt, p[0].alt));
|
||||
|
||||
// force diverged alts to be pruned
|
||||
if (diverged
|
||||
&& lfsr_tag_diverging2(
|
||||
alt, weight,
|
||||
p[0].alt, p[0].weight,
|
||||
lower_rid, upper_rid,
|
||||
a_rid, a_tag,
|
||||
b_rid, b_tag)) {
|
||||
// both diverged? collapse
|
||||
if (lfsr_tag_isred(p[0].alt)
|
||||
&& lfsr_tag_diverging(
|
||||
p[0].alt, p[0].weight,
|
||||
lower_rid, upper_rid,
|
||||
a_rid, a_tag,
|
||||
b_rid, b_tag)) {
|
||||
if (!lfsr_tag_isparallel(alt, p[0].alt)) {
|
||||
lfsr_tag_flip2(&alt, &weight,
|
||||
p[0].alt, p[0].weight,
|
||||
lower_rid, upper_rid);
|
||||
lfs_swap32(&jump, &branch_);
|
||||
}
|
||||
|
||||
p[0].alt = alt | LFSR_TAG_R;
|
||||
p[0].weight += weight;
|
||||
weight = 0;
|
||||
|
||||
// one diverged? trim so alt is pruned
|
||||
} else {
|
||||
if (lfsr_tag_follow2(
|
||||
alt, weight,
|
||||
p[0].alt, p[0].weight,
|
||||
lower_rid, upper_rid,
|
||||
a_rid, a_tag)) {
|
||||
lfsr_tag_flip2(
|
||||
&alt, &weight,
|
||||
p[0].alt, p[0].weight,
|
||||
lower_rid, upper_rid);
|
||||
lfs_swap32(&jump, &branch_);
|
||||
}
|
||||
|
||||
lfsr_tag_trim(
|
||||
alt, weight,
|
||||
&lower_rid, &upper_rid,
|
||||
&lower_tag, &upper_tag);
|
||||
weight = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// take black alt? needs a flip
|
||||
// <b >b
|
||||
// .-'| => .-'|
|
||||
@@ -2982,6 +2934,85 @@ trunk:;
|
||||
lfs_swap32(&jump, &branch_);
|
||||
}
|
||||
|
||||
// do bounds want to take different paths? begin diverging
|
||||
if (!diverged
|
||||
// diverging black?
|
||||
&& (lfsr_tag_isblack(alt)
|
||||
// give up if we find a yellow alt
|
||||
|| lfsr_tag_isred(p[0].alt))
|
||||
&& (lfsr_tag_diverging2(
|
||||
alt, weight,
|
||||
p[0].alt, p[0].weight,
|
||||
lower_rid, upper_rid,
|
||||
a_rid, a_tag,
|
||||
b_rid, b_tag)
|
||||
|| (lfsr_tag_isred(p[0].alt)
|
||||
&& lfsr_tag_diverging(
|
||||
p[0].alt, p[0].weight,
|
||||
lower_rid, upper_rid,
|
||||
a_rid, a_tag,
|
||||
b_rid, b_tag)))) {
|
||||
diverged = true;
|
||||
|
||||
// both diverged? collapse
|
||||
if (lfsr_tag_diverging2(
|
||||
alt, weight,
|
||||
p[0].alt, p[0].weight,
|
||||
lower_rid, upper_rid,
|
||||
a_rid, a_tag,
|
||||
b_rid, b_tag)
|
||||
&& (lfsr_tag_isred(p[0].alt)
|
||||
&& lfsr_tag_diverging(
|
||||
p[0].alt, p[0].weight,
|
||||
lower_rid, upper_rid,
|
||||
a_rid, a_tag,
|
||||
b_rid, b_tag))) {
|
||||
LFS_ASSERT(a_rid < b_rid || a_tag < b_tag);
|
||||
LFS_ASSERT(lfsr_tag_isparallel(alt, p[0].alt));
|
||||
|
||||
p[0].alt = alt | LFSR_TAG_R;
|
||||
p[0].weight += weight;
|
||||
weight = 0;
|
||||
}
|
||||
|
||||
// diverging upper? stitch together both trunks
|
||||
if (a_rid > b_rid || a_tag > b_tag) {
|
||||
lfsr_tag_trim2(
|
||||
alt, weight,
|
||||
p[0].alt, p[0].weight,
|
||||
&lower_rid, &upper_rid,
|
||||
&lower_tag, &upper_tag);
|
||||
|
||||
// stitch together both trunks
|
||||
err = lfsr_p_push(lfs, rbyd, p,
|
||||
LFSR_TAG_ALT(LFSR_TAG_LE, LFSR_TAG_B, d_tag),
|
||||
d_rid - (lower_rid - weight),
|
||||
jump);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// continue to next alt
|
||||
branch = branch_;
|
||||
continue;
|
||||
}
|
||||
|
||||
// force diverged alts to be pruned
|
||||
} else if (diverged
|
||||
&& lfsr_tag_diverging2(
|
||||
alt, weight,
|
||||
p[0].alt, p[0].weight,
|
||||
lower_rid, upper_rid,
|
||||
a_rid, a_tag,
|
||||
b_rid, b_tag)) {
|
||||
// one diverged? trim so alt is pruned
|
||||
lfsr_tag_trim(
|
||||
alt, weight,
|
||||
&lower_rid, &upper_rid,
|
||||
&lower_tag, &upper_tag);
|
||||
weight = 0;
|
||||
}
|
||||
|
||||
// prune?
|
||||
// <b >b
|
||||
// .-'| .-'|
|
||||
@@ -3027,47 +3058,6 @@ trunk:;
|
||||
}
|
||||
}
|
||||
|
||||
// do bounds want to take different paths? begin diverging
|
||||
if (!diverged
|
||||
// eagerly diverge on lower trunk
|
||||
&& ((a_rid < b_rid || a_tag < b_tag)
|
||||
// diverging black?
|
||||
|| lfsr_tag_isblack(alt)
|
||||
// give up if we find a yellow alt
|
||||
|| lfsr_tag_isred(p[0].alt))
|
||||
// we only need to check the second alt, either
|
||||
// lower or upper trunk will flip on follow
|
||||
&& lfsr_tag_diverging2(
|
||||
alt, weight,
|
||||
p[0].alt, p[0].weight,
|
||||
lower_rid, upper_rid,
|
||||
a_rid, a_tag,
|
||||
b_rid, b_tag)) {
|
||||
diverged = true;
|
||||
|
||||
// diverging upper? stitch together both trunks
|
||||
if (a_rid > b_rid || a_tag > b_tag) {
|
||||
lfsr_tag_trim2(
|
||||
alt, weight,
|
||||
p[0].alt, p[0].weight,
|
||||
&lower_rid, &upper_rid,
|
||||
&lower_tag, &upper_tag);
|
||||
|
||||
// stitch together both trunks
|
||||
err = lfsr_p_push(lfs, rbyd, p,
|
||||
LFSR_TAG_ALT(LFSR_TAG_LE, LFSR_TAG_B, d_tag),
|
||||
d_rid - (lower_rid - weight),
|
||||
jump);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// continue to next alt
|
||||
branch = branch_;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// two reds makes a yellow, split?
|
||||
//
|
||||
// note we've lost the original yellow edge because of flips, but
|
||||
|
||||
Reference in New Issue
Block a user