getVectorNumElements() returns a value for scalable vectors
without any warning so it is effectively getVectorMinNumElements().
By renaming it and making getVectorNumElements() forward to
it, we can insert a check for scalable vectors into getVectorNumElements()
similar to EVT. I didn't do that in this patch because there are still more
fixes needed, but I was able to temporarily do it and passed the RISCV
lit tests with these changes.
The changes to isPow2VectorType and getPow2VectorType are copied from EVT.
The change to TypeInfer::EnforceSameNumElts reduces the size of AArch64's isel table.
We're now considering SameNumElts to require the scalable property to match which
removes some unneeded type checks.
This was motivated by the bug I fixed yesterday in
80b9510806cf11c57f2dd87191d3989fc45defa8
Reviewed By: frasercrmck, sdesmalen
Differential Revision: https://reviews.llvm.org/D102262
/// Returns true if the given vector is a power of 2.
bool isPow2VectorType() const {
- unsigned NElts = getVectorNumElements();
+ unsigned NElts = getVectorMinNumElements();
return !(NElts & (NElts - 1));
}
if (isPow2VectorType())
return *this;
- unsigned NElts = getVectorNumElements();
- unsigned Pow2NElts = 1 << Log2_32_Ceil(NElts);
- return MVT::getVectorVT(getVectorElementType(), Pow2NElts);
+ ElementCount NElts = getVectorElementCount();
+ unsigned NewMinCount = 1 << Log2_32_Ceil(NElts.getKnownMinValue());
+ NElts = ElementCount::get(NewMinCount, NElts.isScalable());
+ return MVT::getVectorVT(getVectorElementType(), NElts);
}
/// If this is a vector, return the element type, otherwise return this.
}
}
- unsigned getVectorNumElements() const {
+ /// Given a vector type, return the minimum number of elements it contains.
+ unsigned getVectorMinNumElements() const {
switch (SimpleTy) {
default:
llvm_unreachable("Not a vector MVT!");
}
ElementCount getVectorElementCount() const {
- return ElementCount::get(getVectorNumElements(), isScalableVector());
+ return ElementCount::get(getVectorMinNumElements(), isScalableVector());
}
- /// Given a vector type, return the minimum number of elements it contains.
- unsigned getVectorMinNumElements() const {
- return getVectorElementCount().getKnownMinValue();
+ unsigned getVectorNumElements() const {
+ // TODO: Check that this isn't a scalable vector.
+ return getVectorMinNumElements();
}
/// Returns the size of the specified MVT in bits.
TargetLoweringBase::LegalizeTypeAction
SITargetLowering::getPreferredVectorAction(MVT VT) const {
- int NumElts = VT.getVectorNumElements();
- if (NumElts != 1 && VT.getScalarType().bitsLE(MVT::i16))
+ if (!VT.isScalableVector() && VT.getVectorNumElements() != 1 &&
+ VT.getScalarType().bitsLE(MVT::i16))
return VT.isPow2VectorType() ? TypeSplitVector : TypeWidenVector;
return TargetLoweringBase::getPreferredVectorAction(VT);
}
TargetLoweringBase::LegalizeTypeAction
HexagonTargetLowering::getPreferredVectorAction(MVT VT) const {
- unsigned VecLen = VT.getVectorNumElements();
+ unsigned VecLen = VT.getVectorMinNumElements();
MVT ElemTy = VT.getVectorElementType();
if (VecLen == 1 || VT.isScalableVector())
TargetLoweringBase::LegalizeTypeAction
NVPTXTargetLowering::getPreferredVectorAction(MVT VT) const {
- if (VT.getVectorNumElements() != 1 && VT.getScalarType() == MVT::i1)
+ if (!VT.isScalableVector() && VT.getVectorNumElements() != 1 &&
+ VT.getScalarType() == MVT::i1)
return TypeSplitVector;
if (VT == MVT::v2f16)
return TypeLegal;
/// then the VPERM for the shuffle. All in all a very slow sequence.
TargetLoweringBase::LegalizeTypeAction getPreferredVectorAction(MVT VT)
const override {
- if (VT.getVectorNumElements() != 1 && VT.getScalarSizeInBits() % 8 == 0)
+ if (!VT.isScalableVector() && VT.getVectorNumElements() != 1 &&
+ VT.getScalarSizeInBits() % 8 == 0)
return TypeWidenVector;
return TargetLoweringBase::getPreferredVectorAction(VT);
}
!Subtarget.hasBWI())
return TypeSplitVector;
- if (VT.getVectorNumElements() != 1 &&
+ if (!VT.isScalableVector() && VT.getVectorNumElements() != 1 &&
VT.getVectorElementType() != MVT::i1)
return TypeWidenVector;
return false;
if (B.getVectorElementType() != P.getVectorElementType())
return false;
- return B.getVectorNumElements() < P.getVectorNumElements();
+ return B.getVectorMinNumElements() < P.getVectorMinNumElements();
};
/// Return true if S has no element (vector type) that T is a sub-vector of,
// An actual vector type cannot have 0 elements, so we can treat scalars
// as zero-length vectors. This way both vectors and scalars can be
// processed identically.
- auto NoLength = [](const SmallSet<unsigned,2> &Lengths, MVT T) -> bool {
- return !Lengths.count(T.isVector() ? T.getVectorNumElements() : 0);
+ auto NoLength = [](const SmallDenseSet<ElementCount> &Lengths,
+ MVT T) -> bool {
+ return !Lengths.count(T.isVector() ? T.getVectorElementCount()
+ : ElementCount::getNull());
};
SmallVector<unsigned, 4> Modes;
TypeSetByHwMode::SetType &VS = V.get(M);
TypeSetByHwMode::SetType &WS = W.get(M);
- SmallSet<unsigned,2> VN, WN;
+ SmallDenseSet<ElementCount> VN, WN;
for (MVT T : VS)
- VN.insert(T.isVector() ? T.getVectorNumElements() : 0);
+ VN.insert(T.isVector() ? T.getVectorElementCount()
+ : ElementCount::getNull());
for (MVT T : WS)
- WN.insert(T.isVector() ? T.getVectorNumElements() : 0);
+ WN.insert(T.isVector() ? T.getVectorElementCount()
+ : ElementCount::getNull());
Changed |= berase_if(VS, std::bind(NoLength, WN, std::placeholders::_1));
Changed |= berase_if(WS, std::bind(NoLength, VN, std::placeholders::_1));
MVT VVT = VT;
if (VVT.isScalableVector())
Sig.push_back(IIT_SCALABLE_VEC);
- switch (VVT.getVectorNumElements()) {
+ switch (VVT.getVectorMinNumElements()) {
default: PrintFatalError("unhandled vector type width in intrinsic!");
case 1: Sig.push_back(IIT_V1); break;
case 2: Sig.push_back(IIT_V2); break;