This is an archive of the discontinued LLVM Phabricator instance.

[InstCombine] move vector select ahead of select-shuffle
ClosedPublic

Authored by spatel on Jun 2 2020, 9:42 AM.

Details

Summary

select Cond, (shuf_sel X, Y), X --> shuf_sel X, (select Cond, Y, X)

A select of a select-shuffle ("blend" in x86 lingo) can be reversed so that the select is done first.
This is a more limited version of what I was trying in D80658, but it enables existing demanded bits transforms to catch some of the motivating cases. The tricky bit in that seems to be that by moving the shuffle later, we can always guarantee that poison is correctly inhibited by the shuffle mask in the final value.

Alive2 checks for the basic tests:
http://volta.cs.utah.edu:8080/z/Qqd3RK
http://volta.cs.utah.edu:8080/z/S4wchM
http://volta.cs.utah.edu:8080/z/wf9zPL
http://volta.cs.utah.edu:8080/z/wJeEGk

Diff Detail

Event Timeline

spatel created this revision.Jun 2 2020, 9:42 AM
Herald added a project: Restricted Project. · View Herald TranscriptJun 2 2020, 9:42 AM
lebedev.ri accepted this revision.Jun 4 2020, 4:46 AM

LG, alive2 is happy with test changes.

This revision is now accepted and ready to land.Jun 4 2020, 4:46 AM
This revision was automatically updated to reflect the committed changes.
srj added a subscriber: srj.Jun 4 2020, 12:47 PM

This seems to have injected breakages into Halide when used for x86-64 targets with 'narrow' SIMD (eg., using only SSE2 or SSE4.1); many of our tests now fail in that configuration with variations of

/path/tollvm-project/llvm/lib/IR/Instructions.cpp:2049: bool isSingleSourceMaskImpl(llvm::ArrayRef<int>, int): Assertion `Mask[i] >= 0 && Mask[i] < (NumOpElts * 2) && "Out-of-bounds shuffle mask element"' failed.
In D81013#2074535, @srj wrote:

This seems to have injected breakages into Halide when used for x86-64 targets with 'narrow' SIMD (eg., using only SSE2 or SSE4.1); many of our tests now fail in that configuration with variations of

/path/tollvm-project/llvm/lib/IR/Instructions.cpp:2049: bool isSingleSourceMaskImpl(llvm::ArrayRef<int>, int): Assertion `Mask[i] >= 0 && Mask[i] < (NumOpElts * 2) && "Out-of-bounds shuffle mask element"' failed.

Looks like we are missing !increasesLength() check somewhere.

lebedev.ri added inline comments.Jun 4 2020, 1:29 PM
llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
2416–2417

The problem is that we call ShuffleVectorInst::isSelectMask() before we ensure that select and shuffle have common operand, so by now types of their ops might be non-matching, and shuffle is lenght-changing.

That being said, i do not understand how we can end up with non--1 widening element,
https://godbolt.org/z/nBhmko <- impossible as per ShuffleVectorInst::isValidOperands().

So i'd like to see a reproducer.

Ah, i guess i see it.
The problem is that ShuffleVectorInst::isSingleSourceMask(ArrayRef<int> Mask) is kinda broken:
it can't tell isSingleSourceMaskImpl() how many src elts there are,
so naturally it will immediately assert as long as it selects from non-first source..

spatel added a comment.Jun 4 2020, 1:55 PM

Ah, i guess i see it.
The problem is that ShuffleVectorInst::isSingleSourceMask(ArrayRef<int> Mask) is kinda broken:
it can't tell isSingleSourceMaskImpl() how many src elts there are,
so naturally it will immediately assert as long as it selects from non-first source..

Would this be fixed with "cast<ShuffleVectorInst>(TVal)->isSelect()" instead of the mask check?
Let me know if I should revert or if we have a test case to work on.

Ah, i guess i see it.
The problem is that ShuffleVectorInst::isSingleSourceMask(ArrayRef<int> Mask) is kinda broken:
it can't tell isSingleSourceMaskImpl() how many src elts there are,
so naturally it will immediately assert as long as it selects from non-first source..

Would this be fixed with "cast<ShuffleVectorInst>(TVal)->isSelect()" instead of the mask check?

I think so.

Let me know if I should revert or if we have a test case to work on.

This should do the trick, but my opt is out-of-date to check

define <5 x i8> @widening(<4 x i8> %x, <4 x i8> %y, <5 x i8> %x2, <5 x i1> %cmp) {
  %blend = shufflevector <4 x i8> %x, <4 x i8> %y, <5 x i32> <i32 0, i32 5, i32 2, i32 7, i32 7>
  %r = select <5 x i1> %cmp, <5 x i8> %blend, <5 x i8> %x2
  ret <5 x i8> %r
}
spatel added a comment.Jun 4 2020, 2:30 PM

This should do the trick, but my opt is out-of-date to check

define <5 x i8> @widening(<4 x i8> %x, <4 x i8> %y, <5 x i8> %x2, <5 x i1> %cmp) {
  %blend = shufflevector <4 x i8> %x, <4 x i8> %y, <5 x i32> <i32 0, i32 5, i32 2, i32 7, i32 7>
  %r = select <5 x i1> %cmp, <5 x i8> %blend, <5 x i8> %x2
  ret <5 x i8> %r
}

I couldn't find a widening version that fails, but the narrowing variant does it:
rG192cb718361dbd7be082bc0893f43bbc9782288f

@srj - sorry about the crashing. Let me know if there are still problems.

srj added a comment.Jun 4 2020, 3:16 PM

@spatel thanks for the quick fix!