[PATCH] D14526: Don't recompute LCSSA after loop-unrolling when possible.
Justin Bogner via llvm-commits
llvm-commits at lists.llvm.org
Tue Nov 10 13:12:08 PST 2015
Michael Zolotukhin <mzolotukhin at apple.com> writes:
> Hi Duncan,
>
>> On Nov 10, 2015, at 9:45 AM, Duncan P. N. Exon Smith
>> <dexonsmith at apple.com> wrote:
>>
>>
>>> On 2015-Nov-09, at 20:54, Michael Zolotukhin <mzolotukhin at apple.com> wrote:
>>>
>>> mzolotukhin created this revision.
>>> mzolotukhin added reviewers: chandlerc, hfinkel, dexonsmith,
>>> bogner, joker.eph.
>>> mzolotukhin added a subscriber: llvm-commits.
>>>
>>> Currently we always recompute LCSSA for outer loops after unrolling an
>>> inner loop. That leads to compile time problem when we have big loop
>>> nests, and we can solve it by avoiding unnecessary work. For instance,
>>> if w eonly do partial unrolling, we don't break LCSSA, so we don't need
>>> to rebuild it. Also, if all exits from the inner loop are inside the
>>> enclosing loop, then complete unrolling won't break LCSSA either.
>>>
>>> I replaced unconditional LCSSA recomputation with conditional recomputation +
>>> unconditional assert and added several tests, which were failing when I
>>> experimented with it.
>>>
>>> Soon I plan to follow up with a similar patch for recalculation of dominators
>>> tree.
>>>
>>> http://reviews.llvm.org/D14526
>>>
>>> Files:
>>> lib/Transforms/Utils/LoopUnroll.cpp
>>> test/Transforms/LoopUnroll/rebuild_lcssa.ll
>>>
>>> <D14526.39782.patch>
>>
>> This makes sense to me, although I don't know the loop algorithms too well
>> so maybe someone else can confirm. A few nitpicks below.
>>
>>> Index: lib/Transforms/Utils/LoopUnroll.cpp
>>> ===================================================================
>>> --- lib/Transforms/Utils/LoopUnroll.cpp
>>> +++ lib/Transforms/Utils/LoopUnroll.cpp
>>> @@ -221,6 +221,16 @@
>>>
>>> // Are we eliminating the loop control altogether?
>>> bool CompletelyUnroll = Count == TripCount;
>>> + SmallVector<BasicBlock *, 4> ExitBlocks;
>>> + L->getExitBlocks(ExitBlocks);
>>> + Loop *ParentL = L->getParentLoop();
>>> + bool AllExitsAreInsideParentLoop = true;
>>> + for (auto BB : ExitBlocks) {
>>
>> This would be clearer as `const BasicBlock *BB`, but should at least be
>> `const auto *BB` to make clear to readers that there are no copies going
>> on.
> Makes sense.
>>
>>> + if (LI->getLoopFor(BB) != ParentL) {
>>> + AllExitsAreInsideParentLoop = false;
>>> + break;
>>> + }
>>> + }
>>>
>>> // We assume a run-time trip count if the compiler cannot
>>> // figure out the loop trip count and the unroll-runtime
>>> @@ -554,7 +564,11 @@
>>> while (OuterL->getParentLoop() != LatchLoop)
>>> OuterL = OuterL->getParentLoop();
>>>
>>> - formLCSSARecursively(*OuterL, *DT, LI, SE);
>>> + if (CompletelyUnroll && !AllExitsAreInsideParentLoop)
>>> + formLCSSARecursively(*OuterL, *DT, LI, SE);
>>> +
>>> + assert(OuterL->isLCSSAForm(*DT) &&
>>
>> Is this check cheap? If not, it seems wasteful to do it when we've just
>> called `formLCSSARecursively()`. Can you put this in an `else`, or do
>> an early continue inside the `if`?
> I thought it was fine to have even expensive checks under assert - isn’t it?
It's "fine", but if it's easy to avoid it we might as well. No sense
making the asserts build slower for no reason.
>>
>>> + "Must have loops in LCSSA form to after loop-unroll.");
>>
>> s/to after/after/
> Thanks!
>>
>>> }
>>> }
>>>
>>>
>>
More information about the llvm-commits
mailing list