This is an archive of the discontinued LLVM Phabricator instance.

Refactor loop unrolling pass and add optimization remarks
Needs ReviewPublic

Authored by meheff on Oct 2 2015, 5:20 PM.

Details

Summary

This patch adds a full set of optimization remarks (-Rpass, -Rpass-missed, -Rpass-analysis) to the loop unrolling pass similar to what the loop vectorizer has. The logic within LoopUnroll::runOnLoop had gotten quite torturous making coverage of all possible paths with remarks challenging so I refactored the pass. Logic in runOnLoop should hopefully be clearer now.

One small functional change is that "#pragma loop unroll(full)" will not partially unroll loops now. If the loop is too large to fully unroll a warning is emitted and the loop is not unrolled. This makes more sense to me. If the unroller can't satisfy what the user is requesting it should just fail, not do something different but just more aggressive. We have "#pragma loop unroll(enable)" (equivalently "#pragma unroll") to handle the case where you just want the unroller to be more aggressive in general. I happened to notice this during the refactor so I included it in the change. I can make the small doc change in a followup patch.

Diff Detail

Event Timeline

meheff updated this revision to Diff 36414.Oct 2 2015, 5:20 PM
meheff retitled this revision from to Refactor loop unrolling pass and add optimization remarks.
meheff updated this object.
meheff added reviewers: hfinkel, TylerNowicki.
meheff added a subscriber: llvm-commits.

ping?

Thanks!
Mark

Hi Mark,

In general it looks good, but I'd prefer to split it to smaller patches. That is, separate refactoring (which brings no functionality changes) from adding new stuff (that is, printing remarks). The refactoring, in its turn, should be done in as small steps as possible - e.g. 1) factor out UnrollParameters class, 2) factor out UnrollLimits, etc.

One more question: loop-unrolling is currently executed twice in our O3 pipeline, and in theory it's possible that we'll unroll the same loop twice (e.g. partially the first time and completely the second time). In this case we'll emit two remarks for the same loop, which might be confusing for the user. Any thought on how we can avoid doing this?

Also, please find some comments inline.

Thanks,
Michael

lib/Transforms/Scalar/LoopUnrollPass.cpp
83

UnrollLimits is a struct, not a class, right?

248

I'm a bit worried about this name, as it's very general and doesn't mention unrolling. For instance, currently we have LoopInfo which sounds similar, but holds absolutely different information. I'm not saying we want to merge them in any way, but just mentioned it because it might be confusing for the future readers of the code, since LoopDecscription has no hint regarding how specialized it is.

hfinkel edited edge metadata.Oct 27 2015, 8:48 PM

Hi Mark,

...

One more question: loop-unrolling is currently executed twice in our O3 pipeline, and in theory it's possible that we'll unroll the same loop twice (e.g. partially the first time and completely the second time). In this case we'll emit two remarks for the same loop, which might be confusing for the user. Any thought on how we can avoid doing this?

No, this should not be possible. We only do full unrolling early in the pipeline. All forms of unrolling are enabled later in the pipeline.

hfinkel added inline comments.Oct 27 2015, 9:38 PM
lib/Transforms/Scalar/LoopUnrollPass.cpp
283

There were comments explaining why 2 is subtracted:

// When computing the unrolled size, note that the conditional branch on the
// backedge and the comparison feeding it are not replicated like the rest of
// the loop body (which is why 2 is subtracted).

please make sure these are transplanted with the calculation.

1005

Should we set SetExplicitly = true here? The comments say this is used to indicate a non-heuristically-chosen value. But this is a heuristically-chosen value, it just happens to have been chosen by the backend.