https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102981
--- Comment #6 from Aldy Hernandez <aldyh at gcc dot gnu.org> --- This looks like a class of problems we could easily get if we wanted. The pattern is: PREHEADER | | V HEADER --> LOOPEXIT | | V SUCC | \ | \ DEAD \ | / | / | v XXXXXX On the PREHEADER->HEADER->SUCC path we want to know if the edge out of SUCC can be statically determined. The threader can't do this for a number of reasons. First, we'd be essentially peeling an iteration. Second, IIUC, we'd be rotating the loop. However, there's no reason we can't catch this in a loop optimizer like we did with the loopch pass. This is the exact type of problem that is trivially handled by the path solver, which is quite cheap when you don't have to do full path discovery like the threader has to do. Something like: gimple *control = gimple_outgoing_range_stmt_p (succ); if (control) { auto_vec<basic_block> bbs (3); bbs.quick_push (preheader); bbs.quick_push (header); bbs.quick_push (succ); int_range<2> r; path_range_query query; query.compute_ranges (bbs); query.range_of_stmt (r, control); if (r == desired_static_value...) peel(); ... } If "dead code on the first iteration" is something we want to handle, I could help with the ranger bits if someone gives me a hand with the loop bits.