Index: clang/lib/CodeGen/CGBuiltin.cpp =================================================================== --- clang/lib/CodeGen/CGBuiltin.cpp +++ clang/lib/CodeGen/CGBuiltin.cpp @@ -5645,7 +5645,7 @@ if (BuiltinID == NEON::BI__builtin_neon_splatq_lane_v) NumElements = NumElements * 2; if (BuiltinID == NEON::BI__builtin_neon_splat_laneq_v) - NumElements = NumElements / 2; + NumElements = NumElements.coefficientDiv(2); Ops[0] = Builder.CreateBitCast(Ops[0], VTy); return EmitNeonSplat(Ops[0], cast(Ops[1]), NumElements); @@ -8478,8 +8478,7 @@ case SVE::BI__builtin_sve_svtbl2_f64: { SVETypeFlags TF(Builtin->TypeModifier); auto VTy = cast(getSVEType(TF)); - auto TupleTy = llvm::VectorType::get(VTy->getElementType(), - VTy->getElementCount() * 2); + auto TupleTy = llvm::VectorType::getDoubleElementsVectorType(VTy); Function *FExtr = CGM.getIntrinsic(Intrinsic::aarch64_sve_tuple_get, {VTy, TupleTy}); Value *V0 = Builder.CreateCall(FExtr, {Ops[0], Builder.getInt32(0)}); Index: llvm/include/llvm/CodeGen/ValueTypes.h =================================================================== --- llvm/include/llvm/CodeGen/ValueTypes.h +++ llvm/include/llvm/CodeGen/ValueTypes.h @@ -384,7 +384,16 @@ EVT EltVT = getVectorElementType(); auto EltCnt = getVectorElementCount(); assert(EltCnt.isKnownEven() && "Splitting vector, but not in half!"); - return EVT::getVectorVT(Context, EltVT, EltCnt / 2); + return EVT::getVectorVT(Context, EltVT, EltCnt.coefficientDiv(2)); + } + + // Return a VT for a vector type with the same element type but + // double the number of elements. The type returned may be an + // extended type. + EVT getDoubleNumVectorElementsVT(LLVMContext &Context) const { + EVT EltVT = getVectorElementType(); + auto EltCnt = getVectorElementCount(); + return EVT::getVectorVT(Context, EltVT, EltCnt * 2); } /// Returns true if the given vector is a power of 2. Index: llvm/include/llvm/IR/DerivedTypes.h =================================================================== --- llvm/include/llvm/IR/DerivedTypes.h +++ llvm/include/llvm/IR/DerivedTypes.h @@ -504,7 +504,7 @@ auto EltCnt = VTy->getElementCount(); assert(EltCnt.isKnownEven() && "Cannot halve vector with odd number of elements."); - return VectorType::get(VTy->getElementType(), EltCnt/2); + return VectorType::get(VTy->getElementType(), EltCnt.coefficientDiv(2)); } /// This static method returns a VectorType with twice as many elements as the Index: llvm/include/llvm/Support/MachineValueType.h =================================================================== --- llvm/include/llvm/Support/MachineValueType.h +++ llvm/include/llvm/Support/MachineValueType.h @@ -425,7 +425,7 @@ MVT EltVT = getVectorElementType(); auto EltCnt = getVectorElementCount(); assert(EltCnt.isKnownEven() && "Splitting vector, but not in half!"); - return getVectorVT(EltVT, EltCnt / 2); + return getVectorVT(EltVT, EltCnt.coefficientDiv(2)); } /// Returns true if the given vector is a power of 2. Index: llvm/include/llvm/Support/TypeSize.h =================================================================== --- llvm/include/llvm/Support/TypeSize.h +++ llvm/include/llvm/Support/TypeSize.h @@ -44,10 +44,6 @@ ElementCount operator*(unsigned RHS) { return { Min * RHS, Scalable }; } - ElementCount operator/(unsigned RHS) { - assert(Min % RHS == 0 && "Min is not a multiple of RHS."); - return { Min / RHS, Scalable }; - } friend ElementCount operator-(const ElementCount &LHS, const ElementCount &RHS) { @@ -70,15 +66,27 @@ return *this; } - ElementCount &operator/=(unsigned RHS) { - Min /= RHS; - return *this; + /// We do not provide the '/' operator here because division for polynomial + /// types does not work in the same way as for normal integer types. We can + /// only divide the minimum value (or coefficient) by RHS, which is not the + /// same as + /// (Min * Vscale) / RHS + /// The caller is recommended to use this function in combination with + /// isKnownMultipleOf(RHS), which lets the caller know if it's possible to + /// perform a lossless divide by RHS. + ElementCount coefficientDiv(unsigned RHS) const { + return ElementCount(Min / RHS, Scalable); } ElementCount NextPowerOf2() const { return {(unsigned)llvm::NextPowerOf2(Min), Scalable}; } + /// This function tells the caller whether the element count is known at + /// compile time to be a multiple of the scalar value RHS. If the element + /// count is not scalable then a false return value guarantees it is not + /// a multiple of RHS. However, for scalable values a false return simply + /// means we don't know, since this depends on the value of 'vscale'. bool isKnownMultipleOf(unsigned RHS) const { return Min % RHS == 0; } @@ -203,8 +211,16 @@ return { LHS * RHS.MinSize, RHS.IsScalable }; } - TypeSize operator/(unsigned RHS) const { - return { MinSize / RHS, IsScalable }; + /// We do not provide the '/' operator here because division for polynomial + /// types does not work in the same way as for normal integer types. We can + /// only divide the minimum value (or coefficient) by RHS, which is not the + /// same as + /// (MinSize * Vscale) / RHS + /// The caller is recommended to use this function in combination with + /// isKnownMultipleOf(RHS), which lets the caller know if it's possible to + /// perform a lossless divide by RHS. + TypeSize coefficientDiv(uint64_t RHS) const { + return {MinSize / RHS, IsScalable}; } TypeSize &operator-=(TypeSize RHS) { @@ -227,18 +243,6 @@ return {LHS.MinSize - RHS.MinSize, LHS.IsScalable}; } - friend TypeSize operator/(const TypeSize &LHS, const TypeSize &RHS) { - assert(LHS.IsScalable == RHS.IsScalable && - "Arithmetic using mixed scalable and fixed types"); - return {LHS.MinSize / RHS.MinSize, LHS.IsScalable}; - } - - friend TypeSize operator%(const TypeSize &LHS, const TypeSize &RHS) { - assert(LHS.IsScalable == RHS.IsScalable && - "Arithmetic using mixed scalable and fixed types"); - return {LHS.MinSize % RHS.MinSize, LHS.IsScalable}; - } - // Return the minimum size with the assumption that the size is exact. // Use in places where a scalable size doesn't make sense (e.g. non-vector // types, or vectors in backends which don't support scalable vectors). @@ -270,6 +274,13 @@ // Returns true if the type size is zero. bool isZero() const { return MinSize == 0; } + /// This function tells the caller whether the type size is known at + /// compile time to be a multiple of the scalar value RHS. If the type + /// size is not scalable then a false return value guarantees it is not + /// a multiple of RHS. However, for scalable values a false return simply + /// means we don't know, since this depends on the value of 'vscale'. + bool isKnownMultipleOf(uint64_t RHS) const { return MinSize % RHS == 0; } + // Casts to a uint64_t if this is a fixed-width size. // // This interface is deprecated and will be removed in a future version @@ -326,18 +337,6 @@ return { LHS * RHS.MinSize, RHS.IsScalable }; } - TypeSize operator/(uint64_t RHS) const { - return { MinSize / RHS, IsScalable }; - } - - TypeSize operator/(int RHS) const { - return { MinSize / RHS, IsScalable }; - } - - TypeSize operator/(int64_t RHS) const { - return { MinSize / RHS, IsScalable }; - } - TypeSize NextPowerOf2() const { return TypeSize(llvm::NextPowerOf2(MinSize), IsScalable); } Index: llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -19498,7 +19498,8 @@ if ((DestNumElts % SrcNumElts) == 0) { unsigned DestSrcRatio = DestNumElts / SrcNumElts; if ((NVT.getVectorMinNumElements() % DestSrcRatio) == 0) { - ElementCount NewExtEC = NVT.getVectorElementCount() / DestSrcRatio; + ElementCount NewExtEC = + NVT.getVectorElementCount().coefficientDiv(DestSrcRatio); EVT ScalarVT = SrcVT.getScalarType(); if ((ExtIdx % DestSrcRatio) == 0) { SDLoc DL(N); @@ -20665,7 +20666,7 @@ } else if ((N1SrcSVT.getSizeInBits() % EltSizeInBits) == 0) { unsigned Scale = N1SrcSVT.getSizeInBits() / EltSizeInBits; if (NumElts.isKnownMultipleOf(Scale) && (InsIdx % Scale) == 0) { - NewVT = EVT::getVectorVT(Ctx, N1SrcSVT, NumElts / Scale); + NewVT = EVT::getVectorVT(Ctx, N1SrcSVT, NumElts.coefficientDiv(Scale)); NewIdx = DAG.getVectorIdxConstant(InsIdx / Scale, DL); } } Index: llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp +++ llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp @@ -2636,7 +2636,7 @@ EVT::getFloatingPointVT(InElementSize/2) : EVT::getIntegerVT(*DAG.getContext(), InElementSize/2); EVT HalfVT = EVT::getVectorVT(*DAG.getContext(), HalfElementVT, - NumElements/2); + NumElements.coefficientDiv(2)); SDValue HalfLo; SDValue HalfHi; @@ -5062,11 +5062,12 @@ EVT NewLdTy = LdOps[i].getValueType(); if (NewLdTy != LdTy) { // Create a larger vector. + TypeSize LdTySize = LdTy.getSizeInBits(); + TypeSize NewLdTySize = NewLdTy.getSizeInBits(); + assert(NewLdTySize.isScalable() == LdTySize.isScalable() && + NewLdTySize.isKnownMultipleOf(LdTySize.getKnownMinSize())); unsigned NumOps = - (NewLdTy.getSizeInBits() / LdTy.getSizeInBits()).getKnownMinSize(); - assert( - (NewLdTy.getSizeInBits() % LdTy.getSizeInBits()).getKnownMinSize() == - 0); + NewLdTySize.getKnownMinSize() / LdTySize.getKnownMinSize(); SmallVector WidenOps(NumOps); unsigned j = 0; for (; j != End-Idx; ++j) @@ -5087,7 +5088,8 @@ makeArrayRef(&ConcatOps[Idx], End - Idx)); // We need to fill the rest with undefs to build the vector. - unsigned NumOps = (WidenWidth / LdTy.getSizeInBits()).getKnownMinSize(); + unsigned NumOps = + WidenWidth.getKnownMinSize() / LdTy.getSizeInBits().getKnownMinSize(); SmallVector WidenOps(NumOps); SDValue UndefVal = DAG.getUNDEF(LdTy); { Index: llvm/lib/CodeGen/TargetLoweringBase.cpp =================================================================== --- llvm/lib/CodeGen/TargetLoweringBase.cpp +++ llvm/lib/CodeGen/TargetLoweringBase.cpp @@ -831,9 +831,9 @@ "Promote may not follow Expand or Promote"); if (LA == TypeSplitVector) - return LegalizeKind(LA, - EVT::getVectorVT(Context, SVT.getVectorElementType(), - SVT.getVectorElementCount() / 2)); + return LegalizeKind( + LA, EVT::getVectorVT(Context, SVT.getVectorElementType(), + SVT.getVectorElementCount().coefficientDiv(2))); if (LA == TypeScalarizeVector) return LegalizeKind(LA, SVT.getVectorElementType()); return LegalizeKind(LA, NVT); @@ -889,7 +889,7 @@ // <4 x i140> -> <2 x i140> if (LK.first == TypeExpandInteger) return LegalizeKind(TypeSplitVector, - EVT::getVectorVT(Context, EltVT, NumElts / 2)); + VT.getHalfNumVectorElementsVT(Context)); // Promote the integer element types until a legal vector type is found // or until the element integer type is too big. If a legal type was not @@ -949,7 +949,8 @@ } // Vectors with illegal element types are expanded. - EVT NVT = EVT::getVectorVT(Context, EltVT, VT.getVectorElementCount() / 2); + EVT NVT = EVT::getVectorVT(Context, EltVT, + VT.getVectorElementCount().coefficientDiv(2)); return LegalizeKind(TypeSplitVector, NVT); } @@ -982,7 +983,7 @@ // scalar. while (EC.getKnownMinValue() > 1 && !TLI->isTypeLegal(MVT::getVectorVT(EltTy, EC))) { - EC /= 2; + EC = EC.coefficientDiv(2); NumVectorRegs <<= 1; } @@ -1483,7 +1484,7 @@ // end with a scalar if the target doesn't support vectors. while (EltCnt.getKnownMinValue() > 1 && !isTypeLegal(EVT::getVectorVT(Context, EltTy, EltCnt))) { - EltCnt /= 2; + EltCnt = EltCnt.coefficientDiv(2); NumVectorRegs <<= 1; } Index: llvm/lib/Target/AArch64/AArch64ISelLowering.cpp =================================================================== --- llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -10447,7 +10447,7 @@ "invalid tuple vector type!"); EVT SplitVT = EVT::getVectorVT(*DAG.getContext(), VT.getVectorElementType(), - VT.getVectorElementCount() / N); + VT.getVectorElementCount().coefficientDiv(N)); assert(isTypeLegal(SplitVT)); SmallVector VTs(N, SplitVT); @@ -14188,9 +14188,7 @@ assert((EltTy == MVT::i8 || EltTy == MVT::i16 || EltTy == MVT::i32) && "Sign extending from an invalid type"); - EVT ExtVT = EVT::getVectorVT(*DAG.getContext(), - VT.getVectorElementType(), - VT.getVectorElementCount() * 2); + EVT ExtVT = VT.getDoubleNumVectorElementsVT(*DAG.getContext()); SDValue Ext = DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, ExtOp.getValueType(), ExtOp, DAG.getValueType(ExtVT)); Index: llvm/unittests/CodeGen/ScalableVectorMVTsTest.cpp =================================================================== --- llvm/unittests/CodeGen/ScalableVectorMVTsTest.cpp +++ llvm/unittests/CodeGen/ScalableVectorMVTsTest.cpp @@ -63,7 +63,8 @@ // Check that overloaded '*' and '/' operators work EXPECT_EQ(EVT::getVectorVT(Ctx, MVT::i64, EltCnt * 2), MVT::nxv4i64); - EXPECT_EQ(EVT::getVectorVT(Ctx, MVT::i64, EltCnt / 2), MVT::nxv1i64); + EXPECT_EQ(EVT::getVectorVT(Ctx, MVT::i64, EltCnt.coefficientDiv(2)), + MVT::nxv1i64); // Check that float->int conversion works EVT Vnx2f64 = EVT::getVectorVT(Ctx, MVT::f64, ElementCount::getScalable(2)); Index: llvm/unittests/IR/VectorTypesTest.cpp =================================================================== --- llvm/unittests/IR/VectorTypesTest.cpp +++ llvm/unittests/IR/VectorTypesTest.cpp @@ -71,8 +71,8 @@ EXPECT_EQ(V4Int64Ty->getNumElements(), 4U); EXPECT_EQ(V4Int64Ty->getElementType()->getScalarSizeInBits(), 64U); - auto *V2Int64Ty = - dyn_cast(VectorType::get(Int64Ty, EltCnt / 2)); + auto *V2Int64Ty = dyn_cast( + VectorType::get(Int64Ty, EltCnt.coefficientDiv(2))); ASSERT_NE(nullptr, V2Int64Ty); EXPECT_EQ(V2Int64Ty->getNumElements(), 2U); EXPECT_EQ(V2Int64Ty->getElementType()->getScalarSizeInBits(), 64U); @@ -166,8 +166,8 @@ EXPECT_EQ(ScV4Int64Ty->getMinNumElements(), 4U); EXPECT_EQ(ScV4Int64Ty->getElementType()->getScalarSizeInBits(), 64U); - auto *ScV2Int64Ty = - dyn_cast(VectorType::get(Int64Ty, EltCnt / 2)); + auto *ScV2Int64Ty = dyn_cast( + VectorType::get(Int64Ty, EltCnt.coefficientDiv(2))); ASSERT_NE(nullptr, ScV2Int64Ty); EXPECT_EQ(ScV2Int64Ty->getMinNumElements(), 2U); EXPECT_EQ(ScV2Int64Ty->getElementType()->getScalarSizeInBits(), 64U);