This is an archive of the discontinued LLVM Phabricator instance.

[InstCombine] Fix scalable-vector bitwise select matching
ClosedPublic

Authored by frasercrmck on May 5 2022, 3:23 AM.

Details

Summary

D113035 enhanced the matching of bitwise selects from vector types. This
change unfortunately introduced crashes as it tries to cast scalable
vector types to integers.

Diff Detail

Event Timeline

frasercrmck created this revision.May 5 2022, 3:23 AM
Herald added a project: Restricted Project. · View Herald TranscriptMay 5 2022, 3:23 AM
frasercrmck requested review of this revision.May 5 2022, 3:23 AM
Herald added a project: Restricted Project. · View Herald TranscriptMay 5 2022, 3:23 AM
spatel added a comment.May 5 2022, 7:33 AM

Do we have a test for scalable vectors where the remaining part of the transform is valid?

spatel added a comment.May 5 2022, 7:41 AM

Do we have a test for scalable vectors where the remaining part of the transform is valid?

Ah, the 1st test covers that. But then couldn't we just make a one-line change to avoid the problematic part?

if (auto *VecTy = dyn_cast<FixedVectorType>(Cond->getType())) {

Do we have a test for scalable vectors where the remaining part of the transform is valid?

Ah, the 1st test covers that. But then couldn't we just make a one-line change to avoid the problematic part?

if (auto *VecTy = dyn_cast<FixedVectorType>(Cond->getType())) {

Aye, that's what the 1st test is for.

I was under the impression that if Cond->getType() is any vector type we must either be able to do the bitcast or bail. So wouldn't we just need the other checks I've added in an else?

spatel added a comment.May 5 2022, 8:11 AM

I was under the impression that if Cond->getType() is any vector type we must either be able to do the bitcast or bail. So wouldn't we just need the other checks I've added in an else?

We can still have a vector bitcast where the cast is to a type that matches the number of elements in the vector condition. That's the 2nd test IIUC, so if we just do the dyn_cast, it becomes:

define <vscale x 1 x i64> @vec_of_casted_bools_scalable(<vscale x 1 x i64> %a, <vscale x 1 x i64> %b, <vscale x 8 x i1> %cond) {
  %1 = bitcast <vscale x 1 x i64> %a to <vscale x 8 x i8>
  %2 = bitcast <vscale x 1 x i64> %b to <vscale x 8 x i8>
  %3 = select <vscale x 8 x i1> %cond, <vscale x 8 x i8> %1, <vscale x 8 x i8> %2
  %4 = bitcast <vscale x 8 x i8> %3 to <vscale x 1 x i64>
  ret <vscale x 1 x i64> %4
}

address comments

We can still have a vector bitcast where the cast is to a type that matches the number of elements in the vector condition. That's the 2nd test IIUC, so if we just do the dyn_cast, it becomes:

define <vscale x 1 x i64> @vec_of_casted_bools_scalable(<vscale x 1 x i64> %a, <vscale x 1 x i64> %b, <vscale x 8 x i1> %cond) {
  %1 = bitcast <vscale x 1 x i64> %a to <vscale x 8 x i8>
  %2 = bitcast <vscale x 1 x i64> %b to <vscale x 8 x i8>
  %3 = select <vscale x 8 x i1> %cond, <vscale x 8 x i8> %1, <vscale x 8 x i8> %2
  %4 = bitcast <vscale x 8 x i8> %3 to <vscale x 1 x i64>
  ret <vscale x 1 x i64> %4
}

Oh, right you are! Sorry, I had the wrong impression of how this worked. Thank you.

Oh, right you are! Sorry, I had the wrong impression of how this worked. Thank you.

The code comments could be improved. There are many different potential patterns within this block, and scalable vectors just make it harder to keep it all straight. :)
But after mucking around in here for a long time, I don't think the fix is sufficient.
I added a test with 7bad1d281c798929a to try to uncover another potential bug.
But I can't find a case currently where we would go wrong because code before here (ComputeNumSignBits) prevents matching a scalable vector with the right combination of bitcasts to trigger that bug.

A better fix should do something like this:

// If this is a vector, we may need to cast to match the condition's length.
Type *SelTy = A->getType();
if (auto *VecTy = dyn_cast<VectorType>(Cond->getType())) {
  // For a fixed or scalable vector get N from <{vscale x} N x iM>
  unsigned Elts = VecTy->getElementCount().getKnownMinValue();
  // For a fixed or scalable vector, get the value N x iM; for a scalar this is just M.
  unsigned SelEltSize = SelTy->getPrimitiveSizeInBits().getKnownMinSize();
  Type *EltTy = Builder.getIntNTy(SelEltSize / Elts);
  SelTy = VectorType::get(EltTy, VecTy->getElementCount());
}

I had a hard time making sense of the type and size APIs, so if anyone knows that better, please correct/improve if possible.

fix and enable bitcasts for scalable vectors

The code comments could be improved. There are many different potential patterns within this block, and scalable vectors just make it harder to keep it all straight. :)
But after mucking around in here for a long time, I don't think the fix is sufficient.
I added a test with 7bad1d281c798929a to try to uncover another potential bug.
But I can't find a case currently where we would go wrong because code before here (ComputeNumSignBits) prevents matching a scalable vector with the right combination of bitcasts to trigger that bug.

A better fix should do something like this:

// If this is a vector, we may need to cast to match the condition's length.
Type *SelTy = A->getType();
if (auto *VecTy = dyn_cast<VectorType>(Cond->getType())) {
  // For a fixed or scalable vector get N from <{vscale x} N x iM>
  unsigned Elts = VecTy->getElementCount().getKnownMinValue();
  // For a fixed or scalable vector, get the value N x iM; for a scalar this is just M.
  unsigned SelEltSize = SelTy->getPrimitiveSizeInBits().getKnownMinSize();
  Type *EltTy = Builder.getIntNTy(SelEltSize / Elts);
  SelTy = VectorType::get(EltTy, VecTy->getElementCount());
}

I had a hard time making sense of the type and size APIs, so if anyone knows that better, please correct/improve if possible.

Thanks for digging in. I also found it very difficult to get scalable-vector tests which would actually trigger all possible cases we're trying to handle.

I think what you've got looks okay. I adjusted the comments a little.

spatel accepted this revision.May 6 2022, 4:23 AM

LGTM

This revision is now accepted and ready to land.May 6 2022, 4:23 AM
frasercrmck edited the summary of this revision. (Show Details)May 6 2022, 4:55 AM
This revision was landed with ongoing or failed builds.May 6 2022, 5:12 AM
This revision was automatically updated to reflect the committed changes.