https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102906
--- Comment #16 from Aldy Hernandez <aldyh at gcc dot gnu.org> --- (In reply to rguent...@suse.de from comment #15) > On Wed, 10 Nov 2021, aldyh at gcc dot gnu.org wrote: > > @@ -60,6 +63,24 @@ should_duplicate_loop_header_p (basic_block header, class > > loop *loop, > > if (optimize_loop_for_size_p (loop) > > && !loop->force_vectorize) > > { > > + if (gcond *last = safe_dyn_cast <gcond *> (last_stmt (header))) > > + { > > + gimple_ranger ranger; > > + int_range<2> r; > > + path_range_query path (ranger, /*resolve=*/true); > > + auto_vec<basic_block> bbs (2); > > + edge e = loop_preheader_edge (loop); > > + > > + gcc_checking_assert (e->dest == header); > > + bbs.quick_push (header); > > + bbs.quick_push (e->src); > > + bitmap imports = ranger.gori ().imports (header); > > + path.compute_ranges (bbs, imports); > > + path.range_of_stmt (r, last); > > + r.dump (); > > + fputc ('\n', stderr); > > Nice. Does composing the path from the exact two BBs mean that > it won't pick up a case like > > if (n > 0) > if (k > 0) > for (; n > 0;) > ... > > where the n > 0 outer condition is on the predecessor from > e->src? Or is the path merely built to denote the fact > that we're interested on the entry edge of the loop only > (on the backedge the condition wouldn't be known)? If the predecessor for e->src dominates it, it will also pick that up. The path merely denotes the blocks we care about for intra-block ranges / relationals, etc. With resolve=true (above), any range or relation not known within the path we will just pick up the range on entry to the path by asking ranger. Does that answer your question? For the record, I also agree that we should pull out these loop rotations, peels, etc from the threaders into the loop optimizers, as they have a better model to make decisions about loops.