https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119712

--- Comment #4 from Andrew Macleod <amacleod at redhat dot com> ---
The change tweaks an issue that I haven't seen in the cache before.

When it is propagating values in the cache (the only real iteration ranger has)
 the values are always suppose to get "better", and in the interest of speed,
the cache performs an update when the newly calculated value is different than
the old.    This avoid the overhead of doing an intersect every time the cache
propagates values.  That decision also predates integrating  bitmasks into
irange.

In this particular case, the physical range remains the same, but the mask
changes.

Iteration one:  

FWD visiting block 4 for _11  starting range : [irange] int [-INF, 2147483644]
MASK 0xfffffffc VALUE 0x1
  edge 6->4 :[irange] int [-INF, 2147483644] MASK 0xfffffffc VALUE 0x1
  edge 7->4 :[irange] int [0, 1]
  edge 3->4 :[irange] int [1, 1] MASK 0xfffffffc VALUE 0x1
Updating range to [irange] int [-INF, 2147483644] MASK 0xfffffffd VALUE 0x0


[-INF, 2147483644] MASK 0xfffffffc VALUE 0x1  maps to 
[-INF, -1][1, 1][4, 2147483626] MASK 0xfffffffc VALUE 0x1

and 
[irange] int [-INF, 2147483644] MASK 0xfffffffd VALUE 0x0  maps to 
[-INF, 1][4, 2147483626] MASK 0xfffffffd VALUE 0x0

Note that the new range is *different* but not better.  Its actually worse... 
The result of the union of these 3 ranges includes zero, but then original does
not.

When this value is then propagated through a few blocks and the updated returns
to block 4, :

FWD visiting block 4 for _11  starting range : [irange] int [-INF, 2147483644]
MASK 0xfffffffd VALUE 0x0
  edge 6->4 :[irange] int [-INF, 2147483644] MASK 0xfffffffc VALUE 0x1
  edge 7->4 :[irange] int [1, 1]
  edge 3->4 :[irange] int [1, 1] MASK 0xfffffffc VALUE 0x1
  Updating range to [irange] int [-INF, 2147483644] MASK 0xfffffffc VALUE 0x1

Note the newly refined range from edge 7->4 no longer includes zero, so the new
range is different again, and in fact is back to the original value. 

And thus we hang in an infinite cycle up update because we storied a value
which was NOT better during the initial update.


We should be intersecting during the cache update now that we have masks. 
Intersect will only return TRUE if the resulting range is *better*, thus
avoiding the cycle. 

I am checking the Correctness and timing difference if I DTRT, like so:

diff --git a/gcc/gimple-range-cache.cc b/gcc/gimple-range-cache.cc
index ecf03319cd4..29dfcf894e5 100644
--- a/gcc/gimple-range-cache.cc
+++ b/gcc/gimple-range-cache.cc
@@ -1368,9 +1368,9 @@ ranger_cache::propagate_cache (tree name)
        }

       // If the range on entry has changed, update it.
-      if (new_range != current_range)
+      if (current_range.intersect (new_range))
        {
-         bool ok_p = m_on_entry.set_bb_range (name, bb, new_range);
+         bool ok_p = m_on_entry.set_bb_range (name, bb, current_range);
          // If the cache couldn't set the value, mark it as failed.
          if (!ok_p)
            m_update->propagation_failed (bb);

What do i add to the testsuite to timeout the compilation after a few seconds? 
It should normally compile very fast.

Reply via email to