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++)