From 94eb672315d6a2afa6c71de3999029e846972d25 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Sun, 14 Apr 2024 23:59:07 -0500 Subject: [PATCH] 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... --- lfs.c | 168 +++++++++++++++++++++++++++------------------------------- 1 file changed, 79 insertions(+), 89 deletions(-) diff --git a/lfs.c b/lfs.c index 89b6f458..96be579b 100644 --- a/lfs.c +++ b/lfs.c @@ -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 // .-'| => .-'| @@ -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 // .-'| .-'| @@ -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