This is an archive of the discontinued LLVM Phabricator instance.

Fix an out-of-bounds shufflevector index bug
ClosedPublic

Authored by george.burgess.iv on Sep 14 2017, 6:24 PM.

Details

Summary

I'm somewhat confident about my fix on its own, but I'm not at all familiar with vector instructions. Since I had to modify existing tests, please take a look. :)

Bug: MaxIndex represents the maximum index we're passing to ShuffleVector. If it's a power of two, we can end up splitting into two vectors which have a total size == MaxIndex. This caused an assertion failure in SelectionDAG::getVectorShuffle:

Assertion `llvm::all_of(Mask, [&](int M) { return M < (NElts * 2); }) && "Index out of range"' failed

(NElts == 4, and Mask == {0, 8, -1, -1})

Diff Detail

Repository
rL LLVM

Event Timeline

javed.absar added inline comments.Sep 15 2017, 1:35 AM
test/CodeGen/ARM/crash-on-pow2-shufflevector.ll
19 ↗(On Diff #115332)

Shouldn't this test have some sort of 'CHECK'?

RKSimon added inline comments.Sep 15 2017, 3:00 AM
test/CodeGen/ARM/crash-on-pow2-shufflevector.ll
19 ↗(On Diff #115332)

Make the lit command something like:

; RUN: llc < %s -mtriple=armv7--linux-android | FileCheck %s

You should then be able to use utils/update_llc_test_checks.py to create the CHECKS

63 ↗(On Diff #115332)

You should be able to reduce this test case a lot more, either by hand or with bugpoint

jbhateja edited edge metadata.Sep 15 2017, 3:06 AM
This comment was removed by jbhateja.
george.burgess.iv marked 3 inline comments as done.

Address all feedback

Thanks for the comments!

I propose following as the fix , Simon and other reviews can comment.

That'll probably fix the assertion, but I don't think it'll do what we want here. AFAICT, in that function, VecIn1 contains elements [0..3] from the original vector, and VecIn2 contains elements [4..7]. However, we're trying to shuffle out elements 0 and 8.

Hopefully the new test-case is more clear about this.

test/CodeGen/ARM/crash-on-pow2-shufflevector.ll
19 ↗(On Diff #115332)

Shouldn't this test have some sort of 'CHECK'?

I didn't do checks because goal of this test was to get an assertion to fail. If we'd rather have checks here, I'm happy to do that, too. ¯\_(ツ)_/¯

You should then be able to use utils/update_llc_test_checks.py to create the CHECKS

Thanks for the pointer! (Here and for bugpoint :) )

jbhateja added inline comments.Sep 15 2017, 10:35 PM
lib/CodeGen/SelectionDAG/DAGCombiner.cpp
14472 ↗(On Diff #115487)

If MaxIndex is same as MaxSize of vector it will cause later split (line #14475) to be futile.

RKSimon accepted this revision.Sep 24 2017, 7:25 AM

LGTM

This revision is now accepted and ready to land.Sep 24 2017, 7:25 AM

LGTM

Do you have any observations over alternate fixed proposed. I think it will make this full proof.

Sorry for taking so long to get back to this, and thanks again for the comments/reviews!

Since -- as outlined above -- I still don't think the other proposed fix is correct, I plan to commit this as-is. I'll do so in two days, so people have time to voice objections if they have them. (And I'm always happy to revert if we do find a better way to fix this.)

lib/CodeGen/SelectionDAG/DAGCombiner.cpp
14472 ↗(On Diff #115487)

I tried adding InVT.getVectorNumElements() != NearestPow2 into the conditional below, and it seems to substantially change the output of some test cases (e.g. one of the tests in test/CodeGen/X86/avx512-shuffles/partial_permute.ll goes from 4 vector instructions to 18).

Since I don't know this code, and it looks like your comment applies to this code even without this patch, I'd rather not have that change as a part of this.

jbhateja added inline comments.Sep 26 2017, 2:35 AM
lib/CodeGen/SelectionDAG/DAGCombiner.cpp
14472 ↗(On Diff #115487)

Hi George,

Your fix is fine, I looked at it again but for the boundary case it will be more appropriate to AND another condition for if block which is MaxIndex < NearestPow2. This shall save unnecessary splif of vector.

So if condition should be

if (InVT.isSimple() && (NearestPow2 > 2) &&
    ( MaxIndex < NearestPow2) &&
    ((NumElems * 2) < NearestPow2)) {

Thanks

george.burgess.iv marked an inline comment as done.

Address all feedback

jbhateja accepted this revision.Sep 27 2017, 10:21 PM

LGTM with a minor comment, please run clang-format. over the changes for better inndentation.

Thanks

Thanks!

please run clang-format. over the changes for better inndentation

Done; the formatting remained unchanged for me. ¯\_(ツ)_/¯

This revision was automatically updated to reflect the committed changes.