Whenever the IL changes under ranger, its possible the resulting range calculation could be different. Once cached, we don't really recalculate ranges unless we can detect an input range has caused the result to go stale. Simplification and folding can both change the IL in such a way that the result can be refined, but it is not obvious to ranger. Ive been looking at a case from glibc (I finally produced a reduced testcase which I included) where the original IL is  __message_length_90 = __builtin_strlen (iftmp.39_117); for which which we calculate a range:   [irange] size_t [0, 9223372036854775805] NONZERO 0x7fffffffffffffff Then in vrp1, simplification at the last second changes the IL to:  __message_length_90 = 52; but range has no way to know this has happened, and continues with the original range.  This eventually feeds _39 = __builtin_constant_p (__message_length_90); and if we are not aware of the new range, we fold this builtin the wrong way.  Then a function with no linkage that should have been removed remains in the object, and glibc builds break. doh. I've been looking at various alternatives, none of which I liked much.  I tried a final re-evaluation every time we looked at a stmt for the last time in VRP, but that was a 20% penalty. yuck. What I finally settled on is simple and effective for all passes.  ssa has an update_stmt() call which is invoked to ensure all the ssa-operands are updated properly when the IL changes.  I added an update_stmt call to the generic range_query (which does nothing), then overload it in ranger to force a recalculation of the statement, and update the global value only if it changes as a result. THis solves the problem elegantly, and will be applicable no matter where and how the IL changes.  The overhead of adding the call to update_stmt is very minute..  0.01% overall, and the VRP pass itself only slows down by 0.3%. And this should allow glibc to build again. Bootstrapped on x86_64-pc-linux-gnu with no regressions.  Pushed. Andrew