https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109564
--- Comment #8 from Richard Biener <rguenth at gcc dot gnu.org> ---
We basically see
if (!have_bitrate) {
state_size = (have_state_size ? state_size : (1600L));
output = ((state_size << 5) / 100L + 7L) & ~0x07L;
bitrate = output << 1;
}
optimized to
if (!have_bitrate) {
output = ((state_size << 5) / 100L + 7L) & ~0x07L;
bitrate = output << 1;
}
thus the inner have_state_size gets optimized (state_size != -65536).
So I wonder if when seeing
if (_1 != -65536)
at a place dominated by the
# state_size_8 = PHI <state_size_17(D), _1>
PHI we derive the state_size_8 == _1 equivalence relation from we're
considering this equivalent to
if (state_size_8 != -65536)
? Again this PHI is from
<bb2>
if (_1 != -65536)
<bb3>
goto bb5;
else
goto bb5;
<bb5>
# state_size_8 = PHI <state_size_17(D)(2), _1(3)>
so clearly state_size_8 is "optimistically" equal to _1 but _1 is _not_
equal to state_size_8 (even optimistically).
That is, the equality relation doesn't hold both ways in case there's
UNDEFINED (or even just influenced by UNDEFINED!) ranges involved.
So if VR_EQ always hold both ways I think we need to scrap the skipping
of arg_range.undefined (). For invariants we will of course use the
equivalence only one-way so those are fine.
The following tries to single out this case and avoids registering a
symbolic equivalence if we've ignored any edge (but as said that might
not be good enough because ranges might have folded in UNDEFINED
ranges). I fear something more fundamental is broken here and we
possibly should play safe and not register any equivalence relation
from PHIs.
diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc
index 429734f954a..0c4ffbf3b57 100644
--- a/gcc/gimple-range-fold.cc
+++ b/gcc/gimple-range-fold.cc
@@ -743,6 +744,7 @@ fold_using_range::range_of_phi (vrange &r, gphi *phi,
fur_source &src)
// Track if all executable arguments are the same.
tree single_arg = NULL_TREE;
bool seen_arg = false;
+ bool seen_undefined = false;
// Start with an empty range, unioning in each argument's range.
r.set_undefined ();
@@ -781,6 +783,8 @@ fold_using_range::range_of_phi (vrange &r, gphi *phi,
fur_source &src)
else if (single_arg != arg)
single_arg = NULL_TREE;
}
+ else
+ seen_undefined = true;
// Once the value reaches varying, stop looking.
if (r.varying_p () && single_arg == NULL_TREE)
@@ -802,7 +806,8 @@ fold_using_range::range_of_phi (vrange &r, gphi *phi,
fur_source &src)
// dominate any incoming edge for SINGLE_ARG.
// See PR 108139 and 109462.
basic_block bb = gimple_bb (phi);
- if (!dom_info_available_p (CDI_DOMINATORS))
+ if (seen_undefined
+ || !dom_info_available_p (CDI_DOMINATORS))
single_arg = NULL;
else
for (x = 0; x < gimple_phi_num_args (phi); x++)