rbyd-rr: Consolidated all pruning before flips and stuff
This adds lfsr_tag_prune to compliment lfsr_tag_prune2, and deduplicates all of the reachability-related pruning logic to before any tree mutation occurs for red/black flips, yellow splits, etc. The previous, post-flips logic was arguably simpler and more mistake-proof, but moving pruning logic pre-flips ensures we don't miss any prunability due to yellow splits. This is the reason diverged pruning _must_ occur pre-flips. And code deduplication is always nice. Note lfsr_tag_prune is _not_ the same as lfsr_tag_unreachable it replaces. The prune functions check for both unreachability and only-reachability to determine if an alt should be pruned.
This commit is contained in:
@@ -914,43 +914,6 @@ static inline bool lfsr_tag_follow2(
|
|||||||
return lfsr_tag_follow(alt, weight, lower, upper, rid, tag);
|
return lfsr_tag_follow(alt, weight, lower, upper, rid, tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool lfsr_tag_prune2(
|
|
||||||
lfsr_tag_t alt, lfsr_rid_t weight,
|
|
||||||
lfsr_tag_t alt2, lfsr_rid_t weight2,
|
|
||||||
lfsr_srid_t lower_rid, lfsr_srid_t upper_rid,
|
|
||||||
lfsr_tag_t lower_tag, lfsr_tag_t upper_tag) {
|
|
||||||
if (lfsr_tag_isgt(alt)) {
|
|
||||||
return lfsr_tag_follow2(
|
|
||||||
alt, weight,
|
|
||||||
alt2, weight2,
|
|
||||||
lower_rid, upper_rid,
|
|
||||||
lower_rid-1, lower_tag+1);
|
|
||||||
} else {
|
|
||||||
return lfsr_tag_follow2(
|
|
||||||
alt, weight,
|
|
||||||
alt2, weight2,
|
|
||||||
lower_rid, upper_rid,
|
|
||||||
upper_rid-1, upper_tag-1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool lfsr_tag_unreachable(
|
|
||||||
lfsr_tag_t alt, lfsr_rid_t weight,
|
|
||||||
lfsr_srid_t lower_rid, lfsr_srid_t upper_rid,
|
|
||||||
lfsr_tag_t lower_tag, lfsr_tag_t upper_tag) {
|
|
||||||
if (lfsr_tag_isgt(alt)) {
|
|
||||||
return !lfsr_tag_follow(
|
|
||||||
alt, weight,
|
|
||||||
lower_rid, upper_rid,
|
|
||||||
upper_rid-1, upper_tag-1);
|
|
||||||
} else {
|
|
||||||
return !lfsr_tag_follow(
|
|
||||||
alt, weight,
|
|
||||||
lower_rid, upper_rid,
|
|
||||||
lower_rid-1, lower_tag+1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void lfsr_tag_flip(
|
static inline void lfsr_tag_flip(
|
||||||
lfsr_tag_t *alt, lfsr_rid_t *weight,
|
lfsr_tag_t *alt, lfsr_rid_t *weight,
|
||||||
lfsr_srid_t lower, lfsr_srid_t upper) {
|
lfsr_srid_t lower, lfsr_srid_t upper) {
|
||||||
@@ -1003,6 +966,54 @@ static inline void lfsr_tag_trim2(
|
|||||||
lower_tag, upper_tag);
|
lower_tag, upper_tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool lfsr_tag_prune(
|
||||||
|
lfsr_tag_t alt, lfsr_rid_t weight,
|
||||||
|
lfsr_srid_t lower_rid, lfsr_srid_t upper_rid,
|
||||||
|
lfsr_tag_t lower_tag, lfsr_tag_t upper_tag) {
|
||||||
|
if (lfsr_tag_isgt(alt)) {
|
||||||
|
// unreachable?
|
||||||
|
return !lfsr_tag_follow(
|
||||||
|
alt, weight,
|
||||||
|
lower_rid, upper_rid,
|
||||||
|
upper_rid-1, upper_tag-1)
|
||||||
|
// only-reachable?
|
||||||
|
|| lfsr_tag_follow(
|
||||||
|
alt, weight,
|
||||||
|
lower_rid, upper_rid,
|
||||||
|
lower_rid-1, lower_tag+1);
|
||||||
|
} else {
|
||||||
|
// unreachable?
|
||||||
|
return !lfsr_tag_follow(
|
||||||
|
alt, weight,
|
||||||
|
lower_rid, upper_rid,
|
||||||
|
lower_rid-1, lower_tag+1)
|
||||||
|
// only-reachable?
|
||||||
|
|| lfsr_tag_follow(
|
||||||
|
alt, weight,
|
||||||
|
lower_rid, upper_rid,
|
||||||
|
upper_rid-1, upper_tag-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool lfsr_tag_prune2(
|
||||||
|
lfsr_tag_t alt, lfsr_rid_t weight,
|
||||||
|
lfsr_tag_t alt2, lfsr_rid_t weight2,
|
||||||
|
lfsr_srid_t lower_rid, lfsr_srid_t upper_rid,
|
||||||
|
lfsr_tag_t lower_tag, lfsr_tag_t upper_tag) {
|
||||||
|
if (lfsr_tag_isred(alt2)) {
|
||||||
|
lfsr_tag_trim(
|
||||||
|
alt2, weight2,
|
||||||
|
&lower_rid, &upper_rid,
|
||||||
|
&lower_tag, &upper_tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
return lfsr_tag_prune(
|
||||||
|
alt, weight,
|
||||||
|
lower_rid, upper_rid,
|
||||||
|
lower_tag, upper_tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// support for encoding/decoding tags on disk
|
// support for encoding/decoding tags on disk
|
||||||
|
|
||||||
// tag encoding:
|
// tag encoding:
|
||||||
@@ -2965,32 +2976,19 @@ again:;
|
|||||||
// goto prune;
|
// goto prune;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// prune?
|
|
||||||
// <b >b
|
|
||||||
// .-'| .-'|
|
|
||||||
// <y | | |
|
|
||||||
// .-------'| | | |
|
|
||||||
// | <r | => | <b
|
|
||||||
// | .----' | .-----------|-'|
|
|
||||||
// | | <b | <b |
|
|
||||||
// | | .----'| | .----'| |
|
|
||||||
// 1 2 3 4 4 1 2 3 4 4 2
|
|
||||||
if (lfsr_tag_prune2(
|
|
||||||
alt, weight,
|
|
||||||
p_alts[0], p_weights[0],
|
|
||||||
lower_rid, upper_rid,
|
|
||||||
lower_tag, upper_tag)
|
|
||||||
// prune because of diverged paths?
|
// prune because of diverged paths?
|
||||||
|| (lfsr_d_isdiverged(d_state)
|
if (lfsr_d_isdiverged(d_state)
|
||||||
&& (d_state == LFSR_D_DIVERGEDUPPER)
|
&& (d_state == LFSR_D_DIVERGEDUPPER)
|
||||||
^ lfsr_tag_isgt(alt)
|
^ lfsr_tag_isgt(alt)
|
||||||
^ lfsr_tag_follow2(
|
^ lfsr_tag_follow2(
|
||||||
alt, weight,
|
alt, weight,
|
||||||
p_alts[0], p_weights[0],
|
p_alts[0], p_weights[0],
|
||||||
lower_rid, upper_rid,
|
lower_rid, upper_rid,
|
||||||
a_rid, a_tag))) {
|
a_rid, a_tag)) {
|
||||||
// note, yellow prunes always follow and have no weight, it's
|
// note, yellow prunes always follow and have no weight, it's
|
||||||
// only diverged pruning that needs all these special cases
|
// only diverged pruning that needs all these special cases
|
||||||
|
|
||||||
|
// eagerly flip in case we are ambiguous yellow alts
|
||||||
if (lfsr_tag_follow2(
|
if (lfsr_tag_follow2(
|
||||||
alt, weight,
|
alt, weight,
|
||||||
p_alts[0], p_weights[0],
|
p_alts[0], p_weights[0],
|
||||||
@@ -3007,6 +3005,56 @@ again:;
|
|||||||
&lower_rid, &upper_rid,
|
&lower_rid, &upper_rid,
|
||||||
&lower_tag, &upper_tag);
|
&lower_tag, &upper_tag);
|
||||||
|
|
||||||
|
// red alts we can collapse
|
||||||
|
if (lfsr_tag_isred(p_alts[0])) {
|
||||||
|
printf("%04x->%04x: drprune 0x%x w%d\n",
|
||||||
|
branch,
|
||||||
|
rbyd->eoff,
|
||||||
|
alt,
|
||||||
|
weight);
|
||||||
|
goto prune;
|
||||||
|
|
||||||
|
// black alts just become unreachable, if we pruned these
|
||||||
|
// it would break the coloring of our tree
|
||||||
|
} else {
|
||||||
|
printf("%04x->%04x: dbprune 0x%x w%d\n",
|
||||||
|
branch,
|
||||||
|
rbyd->eoff,
|
||||||
|
alt,
|
||||||
|
weight);
|
||||||
|
alt = LFSR_TAG_ALT(LFSR_TAG_LE, LFSR_TAG_B, 0);
|
||||||
|
weight = 0;
|
||||||
|
// jump = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// prune?
|
||||||
|
// <b >b
|
||||||
|
// .-'| .-'|
|
||||||
|
// <y | | |
|
||||||
|
// .-------'| | | |
|
||||||
|
// | <r | => | <b
|
||||||
|
// | .----' | .-----------|-'|
|
||||||
|
// | | <b | <b |
|
||||||
|
// | | .----'| | .----'| |
|
||||||
|
// 1 2 3 4 4 1 2 3 4 4 2
|
||||||
|
if (lfsr_tag_prune2(
|
||||||
|
alt, weight,
|
||||||
|
p_alts[0], p_weights[0],
|
||||||
|
lower_rid, upper_rid,
|
||||||
|
lower_tag, upper_tag)) {
|
||||||
|
// note, yellow prunes always follow and have no weight, it's
|
||||||
|
// only diverged pruning that needs all these special cases
|
||||||
|
|
||||||
|
// eagerly flip in case we are ambiguous yellow alts
|
||||||
|
if (lfsr_tag_follow2(
|
||||||
|
alt, weight,
|
||||||
|
p_alts[0], p_weights[0],
|
||||||
|
lower_rid, upper_rid,
|
||||||
|
a_rid, a_tag)) {
|
||||||
|
lfs_swap32(&jump, &branch_);
|
||||||
|
}
|
||||||
|
|
||||||
// red alts we can collapse
|
// red alts we can collapse
|
||||||
if (lfsr_tag_isred(p_alts[0])) {
|
if (lfsr_tag_isred(p_alts[0])) {
|
||||||
printf("%04x->%04x: yrprune 0x%x w%d\n",
|
printf("%04x->%04x: yrprune 0x%x w%d\n",
|
||||||
@@ -3148,84 +3196,15 @@ again:;
|
|||||||
lower_rid, upper_rid);
|
lower_rid, upper_rid);
|
||||||
lfs_swap32(&jump, &branch_);
|
lfs_swap32(&jump, &branch_);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// red unreachable? prune
|
// trim alts from our current bounds
|
||||||
if (lfsr_tag_unreachable(
|
lfsr_tag_trim2(
|
||||||
p_alts[0], p_weights[0],
|
alt, weight,
|
||||||
lower_rid, upper_rid,
|
|
||||||
lower_tag, upper_tag)) {
|
|
||||||
printf("%04x->%04x: rprune 0x%x w%d\n",
|
|
||||||
branch,
|
|
||||||
rbyd->eoff,
|
|
||||||
p_alts[0],
|
|
||||||
p_weights[0]);
|
|
||||||
lfsr_tag_trim(
|
|
||||||
p_alts[0], p_weights[0],
|
p_alts[0], p_weights[0],
|
||||||
&lower_rid, &upper_rid,
|
&lower_rid, &upper_rid,
|
||||||
&lower_tag, &upper_tag);
|
&lower_tag, &upper_tag);
|
||||||
lfsr_rbyd_p_pop(p_alts, p_weights, p_jumps);
|
|
||||||
|
|
||||||
// trim red bounds
|
|
||||||
} else {
|
|
||||||
lfsr_tag_trim(
|
|
||||||
p_alts[0], p_weights[0],
|
|
||||||
&lower_rid, &upper_rid,
|
|
||||||
&lower_tag, &upper_tag);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// unreachable?
|
|
||||||
if (lfsr_tag_unreachable(
|
|
||||||
alt, weight,
|
|
||||||
lower_rid, upper_rid,
|
|
||||||
lower_tag, upper_tag)) {
|
|
||||||
// red unreachable? prune
|
|
||||||
if (lfsr_tag_isred(p_alts[0])) {
|
|
||||||
printf("%04x->%04x: brprune 0x%x w%d\n",
|
|
||||||
branch,
|
|
||||||
rbyd->eoff,
|
|
||||||
alt,
|
|
||||||
weight);
|
|
||||||
lfsr_tag_trim(
|
|
||||||
alt, weight,
|
|
||||||
&lower_rid, &upper_rid,
|
|
||||||
&lower_tag, &upper_tag);
|
|
||||||
p_alts[0] &= ~LFSR_TAG_R;
|
|
||||||
y_branch = branch;
|
|
||||||
branch = branch_;
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// black unreachable? collapse to alt-nevers, otherwise
|
|
||||||
// we risk breaking the coloring of our tree
|
|
||||||
} else {
|
|
||||||
printf("%04x->%04x: bprune 0x%x w%d\n",
|
|
||||||
branch,
|
|
||||||
rbyd->eoff,
|
|
||||||
alt,
|
|
||||||
weight);
|
|
||||||
lfsr_tag_trim(
|
|
||||||
alt, weight,
|
|
||||||
&lower_rid, &upper_rid,
|
|
||||||
&lower_tag, &upper_tag);
|
|
||||||
alt = LFSR_TAG_ALT(LFSR_TAG_LE, LFSR_TAG_B, 0);
|
|
||||||
weight = 0;
|
|
||||||
jump = 0;
|
|
||||||
}
|
|
||||||
// trim black bounds
|
|
||||||
} else {
|
|
||||||
lfsr_tag_trim(
|
|
||||||
alt, weight,
|
|
||||||
&lower_rid, &upper_rid,
|
|
||||||
&lower_tag, &upper_tag);
|
|
||||||
}
|
|
||||||
|
|
||||||
// // trim alts from our current bounds
|
|
||||||
// lfsr_tag_trim2(
|
|
||||||
// alt, weight,
|
|
||||||
// p_alts[0], p_weights[0],
|
|
||||||
// &lower_rid, &upper_rid,
|
|
||||||
// &lower_tag, &upper_tag);
|
|
||||||
//
|
|
||||||
// // keep track of last alt on diverged trunk to stitch the
|
// // keep track of last alt on diverged trunk to stitch the
|
||||||
// // trunks together with
|
// // trunks together with
|
||||||
// if ((d_state == LFSR_D_DIVERGEDLOWER
|
// if ((d_state == LFSR_D_DIVERGEDLOWER
|
||||||
|
|||||||
Reference in New Issue
Block a user