rbyd-rr: Minor tweaks, adopted diverging check for diverged triming

Previously we used the direction of post-diverged alts to decide if they
need to be trimmed or not:

  lfsr_d_isdiverged(d_state)
      && lfsr_d_isupper(d_state)
          ^ lfsr_tag_isgt(alt)
          ^ lfsr_tag_follow2(
              alt, weight,
              p[0].alt, p[0].weight,
              lower_rid, upper_rid,
              a_rid, a_tag)

But this working is a bit accidental. The real condition that needs to
be met for trimming is if our bounds continue to diverge on the alt:

  lfsr_d_isdiverged(d_state)
      && lfsr_tag_follow2(
              alt, weight,
              p[0].alt, p[0].weight,
              lower_rid, upper_rid,
              a_rid, a_tag)
          ^ lfsr_tag_follow2(
              alt, weight,
              p[0].alt, p[0].weight,
              lower_rid, upper_rid,
              b_rid, b_tag)

This may seem more complicated, and does add code, but I'm hopeful it
can eventually lead to better code deduplication with the preceding
not-diverged -> diverged checks:

           code          stack
  before: 34468           2864
  after:  34492 (+0.1%)   2864 (+0.0%)

                     code          frame          stack
  appendattr before: 2390            216            568
  appendattr after:  2414 (+1.0%)    216 (+0.0%)    568 (+0.0%)

I've also been trying to simplify/deduplicate the diverging logic more,
but it's proven difficult. There's an annoying catch-22 where 1. we need
to trim diverging alts before applying color transformations, but 2. we
need to resolve yellow splits before triming diverging alts.
This commit is contained in:
Christopher Haster
2024-04-08 14:12:24 -05:00
parent 01b28b3224
commit d3e09b082f
+13 -15
View File
@@ -2888,14 +2888,12 @@ trunk:;
goto leaf;
}
// keep track of the tag we find at the end of the trunk
lfsr_tag_t tag_ = 0;
// queue of pending alts we can emulate rotations with
lfsr_alt_t p[3] = {{0}, {0}, {0}};
// keep track of the last incoming branch for yellow splits
lfs_size_t y_branch = 0;
// keep track of the tag we find at the end of the trunk
lfsr_tag_t tag_ = 0;
// descend down tree, building alt pointers
while (true) {
@@ -2949,16 +2947,16 @@ trunk:;
b_rid, b_tag)))) {
d_state = lfsr_d_diverge(d_state);
// diverged red? flip
// diverging red? flip
if (lfsr_tag_isred(p[0].alt)
&& (lfsr_tag_follow(
&& lfsr_tag_follow(
p[0].alt, p[0].weight,
lower_rid, upper_rid,
a_rid, a_tag)
^ lfsr_tag_follow(
p[0].alt, p[0].weight,
lower_rid, upper_rid,
b_rid, b_tag))) {
b_rid, b_tag)) {
if (lfsr_tag_isparallel(alt, p[0].alt)) {
lfsr_tag_flip2(&alt, &weight,
p[0].alt, p[0].weight,
@@ -2993,9 +2991,8 @@ trunk:;
}
}
// diverged upper? stitch together both trunks
// diverging upper? stitch together both trunks
if (lfsr_d_isupper(d_state)) {
// flip
if (lfsr_tag_isgt(alt)) {
lfsr_tag_flip2(
&alt, &weight,
@@ -3003,8 +3000,6 @@ trunk:;
lower_rid, upper_rid);
lfs_swap32(&jump, &branch_);
}
// trim
lfsr_tag_trim2(
alt, weight,
p[0].alt, p[0].weight,
@@ -3025,15 +3020,18 @@ trunk:;
continue;
}
// trim unreachable diverged alts so they end up pruned
// force diverged alts to be pruned
} else if (lfsr_d_isdiverged(d_state)
&& (lfsr_d_isupper(d_state)
^ lfsr_tag_isgt(alt)
&& lfsr_tag_follow2(
alt, weight,
p[0].alt, p[0].weight,
lower_rid, upper_rid,
a_rid, a_tag)
^ lfsr_tag_follow2(
alt, weight,
p[0].alt, p[0].weight,
lower_rid, upper_rid,
a_rid, a_tag))) {
b_rid, b_tag)) {
if (lfsr_tag_follow2(
alt, weight,
p[0].alt, p[0].weight,