When using clang with -fno-unroll-loops (implicitly added with -O1), the LoopUnrollPass is not not added to the (legacy) pass pipeline. This also means that it will not process any loop metadata such as llvm.loop.unroll.enable (which is generated by #pragma unroll or #pragma clang loop unroll(enable)) and remain in the IR until the WarnMissedTransformationsPass emits a warning that a forced transformation has not been applied (see https://lists.llvm.org/pipermail/llvm-commits/Week-of-Mon-20181210/610833.html). Such explicit transformations should take precedence over disabling heuristics.
This patch unconditionally adds LoopUnrollPass to the optimizing pipeline (i.e. it is not added with -O0), but passes a flag indicating whether automatic unrolling is dis-/enabled. This is the same approach as LoopVectorize uses.
The new pass manager's pipeline builder has no option to disable unrolling, hence the problem does not apply.
I don't like this name "AlwaysUnroll" as it sounds like a forced action for all loops, and it's really a pass-enablement flag. I understand, however, that the corresponding flag in the loop vectorizer is named this:
which is also a suboptimal name, but as a comment which explains what it really means. You should have a similar comment here. Maybe a better name would be: OnlyWhenForced?