This is an archive of the discontinued LLVM Phabricator instance.

[SelectionDAG] Implement SplitVecOp_INSERT_SUBVECTOR
ClosedPublic

Authored by joechrisellis on Dec 7 2020, 6:10 AM.

Details

Summary

This function is needed for when it is necessary to split the subvector
operand of an llvm.experimental.vector.insert call. Splitting the
subvector operand means performing two insertions: one inserting the
lower part of the split subvector into the destination vector, and
another for inserting the upper part.

Through experimenting, it seems quite rare to need split the subvector
operand, but this is necessary to avoid assertion errors.

Diff Detail

Event Timeline

joechrisellis created this revision.Dec 7 2020, 6:10 AM
joechrisellis requested review of this revision.Dec 7 2020, 6:10 AM
Herald added a project: Restricted Project. · View Herald TranscriptDec 7 2020, 6:10 AM
joechrisellis planned changes to this revision.Dec 7 2020, 6:15 AM

@lebedev.ri hi, I am aware of this. Changes planned. 🙂

Hi @joechrisellis, hope you don't mind but I've added @paulwalker-arm and @kmclaughlin as reviewers, due to the legalisation work they've been involved in for the last few months!

Is it possible to add a brief description of what the intent of this patch is? It's not immediately obvious why we're adding the split function from the code or summary. I'm assuming it's related to the new intrinsic in your test, since LLVM has not needed this function until now?

joechrisellis edited the summary of this revision. (Show Details)Dec 8 2020, 9:33 AM

Is it possible to add a brief description of what the intent of this patch is? It's not immediately obvious why we're adding the split function from the code or summary. I'm assuming it's related to the new intrinsic in your test, since LLVM has not needed this function until now?

Yes, good idea. I am not sure, but I think it might have actually been possible to hit a codepath that expects the split function to exist even without the new llvm.experimental.vector.insert intrinsics (unless the INSERT_SUBVECTOR ISD nodes are never created?). From our experiments, it's pretty rare that we end up needing this function even with the intrinsics anyway. But it does prevent an assertion error in certain circumstances. 🙂

Also, it might be worth noting that operand splitting is already implemented for EXTRACT_SUBVECTOR.

If you can find a test that exposes the need for this split function with generic IR that would be really helpful I think - LLVM has managed for a long time without needing this split function so something has changed. I suspect it's probably just the new intrinsic that now exposes this code path.

llvm/test/CodeGen/AArch64/split-vector-insert.ll
6

Could you add a few more tests here, for example test floating point (nxv2f64.v8f64) and predicate vectors (nxv2i1.v8i1)?

If you can find a test that exposes the need for this split function with generic IR that would be really helpful I think - LLVM has managed for a long time without needing this split function so something has changed. I suspect it's probably just the new intrinsic that now exposes this code path.

Personally I think using the intrinsic as the test is better than trying to rely on an exact sequence of unluckiness to generate the failure.

For information I believe scalable vectors is what has changed. Specifically the changes we've made to INSERT_SUBVECTOR to allow a fixed-length vector to be extracted from/inserted into a scalable vector. Before this you'd only ever insert "fixed into fixed" or "scalable into scalable". Given the nature of INSERT_SUBVECTOR the operand is always smaller than the result and thus if the operand type is illegal then the result type must also be illegal, in which case SplitVecRes_INSERT_SUBVECTOR will handle type legalisation. However by allowing mixed vector types we've opened up the possibility for extracting an illegal vector type, that requires splitting to be made legal, from a legal one.

HI @paulwalker-arm, right that makes sense and thanks for the explanation!

paulwalker-arm added inline comments.Dec 9 2020, 3:19 AM
llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
2287–2291

Is this protection necessary? From what I can see the code below should work for all valid forms of INSERT_SUBVECTOR. That's to say you don't need to worry about the case of inserting a scalable vector into a fixed length vector because that is not a valid use of INSERT_SUBVECTOR and thus should be caught before getting here.

llvm/test/CodeGen/AArch64/split-vector-insert.ll
54

Is this required? I'm wondering if simply passing the subvector as a function parameter (or loading it from memory) and returning the scalable result directly, leads to a simpler test.

paulwalker-arm added inline comments.Dec 9 2020, 3:27 AM
llvm/test/CodeGen/AArch64/split-vector-insert.ll
2

This RUN line requires an asserts build so the test will need ; REQUIRES: asserts . However, for what it's worth it seems overkill to test both the code generation output and the result of the legaliser with generally the assembler output from llc usually being enough.

joechrisellis marked an inline comment as done.

Add more tests, address @paulwalker-arm and @david-arm's review comments.

Remove unneeded files.

llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
2287–2291

It might not be necessary, but since SplitVecOp_EXTRACT_SUBVECTOR has a similar check I would like to keep this for the time being!

llvm/test/CodeGen/AArch64/split-vector-insert.ll
2

I've added the ; REQUIRES: asserts line. I am a little reluctant to remove the legaliser checks because without them it is not clear we are testing SplitVecOp_INSERT_SUBVECTOR?

6

Done for floating point vectors -- I also tried to hit this codepath with predicate vectors but couldn't find a test case that works. Please ping if you think this is something we definitely need! 😄

54

I think it is necessary. I did try to simplify this test further, but didn't get anywhere. FWIW, calls to SplitVecOp_INSERT_SUBVECTOR seem to be very rare. I was unable to write a test by hand that exercised this codepath -- I actually got this test by using creduce + bugpoint to reduce a failure we had in a project that uses the ACLE.

It seems that simpler examples, like what you suggest, allow the compiler to factor out the INSERT_SUBVECTOR ISD node earlier on.

paulwalker-arm added inline comments.Dec 9 2020, 7:35 AM
llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
2287–2291

I believe in SplitVecOp_EXTRACT_SUBVECTOR's case there is a check for a legitimate scenario that if hit may require an update to the function. However, in your instance the check is simply validating the DAG, which is not necessary because that's the job of SelectionDAG::getNode, of which I can see:

assert((VT.isScalableVector() || N2VT.isFixedLengthVector()) &&                 
           "Cannot insert a scalable vector into a fixed length vector!");

So unless the check serves a different purpose the code looks redundant and redundant code should be removed. I guess if you are super paranoid you could replicate SelectionDAG::getNode's assert but I really don't see the need.

Harbormaster completed remote builds in B81631: Diff 310521.
joechrisellis marked an inline comment as done.

Remove redudant check for valid INSERTION_SUBVECTOR ISD node.

joechrisellis added inline comments.Dec 9 2020, 8:02 AM
llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
2287–2291

Ahh okay, that makes sense -- my bad! Will remove this check. 🙂

Simplify test.

paulwalker-arm accepted this revision.Dec 10 2020, 5:04 AM

A few stylistic things to consider (I'm only really bothered about loosing the v32 tests) but otherwise looks good.

llvm/test/CodeGen/AArch64/split-vector-insert.ll
2

It's up to you but I prefer to keep RUN lines minimal so:

-o - is not needed as that is the default when redirecting files into llc,
-mtriple=aarch64-- can be replaced with target triple = "aarch64-unknown-linux-gnu"
-mcpu=a64fx can be replaced with a function attribute attributes #0 = { "target-features"="+sve" } remembering to reference #0 in the function definitions.

3

Again your choice, but you could drop this then just use CHECK for the code generation validation, which is more in keeping with the majority of the code generation tests.

117

I don't believe this and the other v32 test offers any value. The v8 tests are already testing nested (two levels) type legalisation, so there's no reason to test it again at four levels. Add this to the fact the generated code it pretty unreadable I recommend removing them.

This revision is now accepted and ready to land.Dec 10 2020, 5:04 AM
joechrisellis marked 2 inline comments as done.

Address @paulwalker-arm's style comments.

joechrisellis marked an inline comment as done.Dec 10 2020, 5:40 AM

Thanks for the comments! 😄

paulwalker-arm added inline comments.Dec 10 2020, 7:11 AM
llvm/test/CodeGen/AArch64/split-vector-insert.ll
3

--check-prefix=CHECK is not needed as it's the default when no --check-prefix is specified.

Remove redundant --check-prefix=CHECK.

This revision was landed with ongoing or failed builds.Dec 11 2020, 3:08 AM
This revision was automatically updated to reflect the committed changes.