[llvm] [LoopUnroll][Compile-time] Cap runtime unrolling in pathologically large loop nests (PR #221702)

Madhur Amilkanthwar via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 16 23:51:10 PDT 2026


madhur13490 wrote:

> > On internal workloads whose initialization and parameter routines build loop nests containing well over a thousand loops, this reduces LTO compile time by roughly 13-14% with no measurable run-time change.
> 
> Could you elaborate on the motivation for the change? Why isn't `llvm.loop.unroll.disable` acceptable?


Thanks for taking a look! Just double checking, did you look at the RFC?

These come from machine-generated Fortran init/parameter routines where a large `SELECT CASE` expands into one top-level loop whose nest holds 1000+ sibling/child loops. Each heuristic runtime-unroll, partial-unroll, or peel calls `forgetTopmostLoop`, invalidating ScalarEvolution for the *whole* nest — so with every candidate re-invalidating the nest, compile time is ~O(nest²). For this cold init code the run-time benefit is negligible, so it's a large super-linear compile-time cost for nothing (~13–14% of LTO compile time on the affected TUs, no measurable run-time change, no rate-suite regressions).

`unroll.disable` is not applicable here. It's a per-loop annotation, but (a) these loops are frontend-generated — the user can't realistically annotate thousands of them; (b) the problem is a *whole-nest* property, so you'd have to mark every loop in the nest and first detect that the nest is pathological — exactly the cheap once-per-function check this cap does; and (c) the nest only becomes pathological after inlining/LTO, so a static frontend annotation can't capture it. This is meant as a general compile-time guard (like the existing `-unroll-max-upperbound` bailout); the default of 128 leaves ordinary code untouched, and explicit pragmas / forced counts still unroll.

https://github.com/llvm/llvm-project/pull/221702


More information about the llvm-commits mailing list