RFC: LoopEditor, a high-level loop transform toolkit

James Molloy james at jamesmolloy.co.uk
Tue Jul 28 01:08:56 PDT 2015


Hi Michael,

Thanks for the feedback.

> As a show-case, how does it help to simplify the aforementioned
createEmptyBlock?

That's a good example. If you look at http://reviews.llvm.org/D11530 line
916 in the .cpp file, there's a function "versionWidenAndInterleaveLoop"
that does basically createEmptyBlock(). It also does more stuff - it
performs the loop interleave too - but as an example showcase it should do.

For the vectorizer, I think the cleanest thing would be to add a delegate
hook that's called whenever an instruction is about to be cloned. Then, the
vectorizer could override that hook and provide its own implementation
(instead of cloning an instruction completely, it'd replace it with a
vector variant. So the entire main body of the vectorizer would look
something like this:

struct Delegate : public LoopEditor::Delegate {
  Value *hookCloneInstruction(Instruction *OldI, IRBuilder<> &IRB) {
    if (isControlFlowInst(OldI)) return IRB.CreateExtractElement; // Don't
vectorize branches
    return createVectorVersionOfInstruction(OldI, VF, IRB); // Defined
somewhere in LoopVectorize
  }
};
BasicBlock *PredBB;
Delegate D;
LoopEditor LE(L, DT, SE, LI);
LoopEditor VectorLE = LE.versionWidenAndInterleaveLoop(UF, PredBB, &D);
VectorLE.widen(VF); // Widen further, so it's widened by VF*UF. Only
affects induction variable steps and trip count.

How does that look to you?

> Also, I think it’s very important to explicitly define requirements for
loops we can handle, and what we do with other loops. E.g. what do we do if
a loop has multiple back-edges? What do we do if a loop body has
complicated control-flow?

Good point, agreed. I think we need to handle loops in LoopSimplify form
and LCSSA form at least. Some functions may not be able to handle arbitrary
control flow but most should be agnostic to it (for example making sure
control flow is correct in a vectorized loop, should be the user's job not
LoopEditor's). But defining exactly what loop type each function supports
and ensuring it does support that is a good idea.

I'm also trying to work out what's the best way of getting this in-tree.
It's a lot of code and I don't want to dump it in one go, but getting
pre-commit review on every little step would make it take forever. Do you
have any suggestions as to methodology? I was thinking getting review on
the header (API), then committing that with stub implementations and
implementing them bit by bit from there...

Cheers,

James

On Mon, 27 Jul 2015 at 20:23 Michael Zolotukhin <mzolotukhin at apple.com>
wrote:

> Hi James,
>
> On Jul 27, 2015, at 10:04 AM, James Molloy <james at jamesmolloy.co.uk>
> wrote:
>
> Hi all,
>
> LLVM currently lacks a single coherent way to edit, modify and transform
> loops. We have the Loop abstraction that provides some functionality, and
> we have a cluster of functions and abstractions in LoopUtils, but each is
> fairly cumbersome to use. There's also VersionedLoop, but that's quite
> specific and not really extendable/composable.
>
> I've recently been trying to do some prototyping of a high level loop
> optimization (unroll-and-jam) and ended up with quite a bit of spaghetti
> code doing what should be simple transforms (as another example, look at
> LoopVectorize::createEmptyBlock()!)
>
> Totally agree here!
>
>
> So I decided to prototype an API for performing more high level operations
> on LLVM Loops - cloning, widening, interleaving, stitching the output of
> one loop into another loop, setting loop trip counts, peeling... and all
> while keeping loopinfo, domtree and SCEV updated.
>
> I've uploaded my current prototype to Phab here:
> http://reviews.llvm.org/D11530
> <https://urldefense.proofpoint.com/v2/url?u=http-3A__reviews.llvm.org_D11530&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=3t7gCOgkqnA-65i6cez_eslTon3hxx5XJKhMBw98kv0&s=yCaxJfCogeqwUH-wlsdHFPHktniLwG3-cZnq1yciR04&e=>
>
>
> It's still at the prototype stage so there are lots of things that need
> fixing - sorting out the testing story being top of my list. But I'm
> looking for feedback on:
>   * Is this a useful abstraction? Is it something the community would like
> to see in-tree (eventually)?
>
> I think it could be very useful - depending on how easy it would be to
> use. As a show-case, how does it help to simplify the aforementioned
> createEmptyBlock?
>
>   * Does the API design make sense? Are there obvious things I've missed
> that people need?
>
> From the first glance, it seems reasonable. One probably missing thing: we
> have peelAfter, but we may also need peelBefore (it would be helpful if we
> create prologues for alignment for instance).
>
> Also, I think it’s very important to explicitly define requirements for
> loops we can handle, and what we do with other loops. E.g. what do we do if
> a loop has multiple back-edges? What do we do if a loop body has
> complicated control-flow?
>
> Thanks,
> Michael
>
>
> I've thought about the use cases of the loop vectorizer, loop
> distribution, loop unrolling, loop versioning, and I think the current
> design can solve their use cases fairly elegantly. I've used this API to
> write a fairly sophisticated unroll-and-jam transform in very few lines too.
>
> Any feedback would be gratefully appreciated!
>
> Cheers,
>
> James
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20150728/02a85240/attachment.html>


More information about the llvm-commits mailing list