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.
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
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?
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 }
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.