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

Reply via email to