Index: llvm/include/llvm/CodeGen/ValueTypes.h =================================================================== --- llvm/include/llvm/CodeGen/ValueTypes.h +++ llvm/include/llvm/CodeGen/ValueTypes.h @@ -232,28 +232,58 @@ return getSizeInBits() == VT.getSizeInBits(); } + /// Return true if we know at compile time this has more bits than VT. + bool knownBitsGT(EVT VT) const { + return TypeSize::isKnownGT(getSizeInBits(), VT.getSizeInBits()); + } + + /// Return true if we know at compile time this has more than or the same + /// bits as VT. + bool knownBitsGE(EVT VT) const { + return TypeSize::isKnownGE(getSizeInBits(), VT.getSizeInBits()); + } + + /// Return true if we know at compile time this has fewer bits than VT. + bool knownBitsLT(EVT VT) const { + return TypeSize::isKnownLT(getSizeInBits(), VT.getSizeInBits()); + } + + /// Return true if we know at compile time this has fewer than or the same + /// bits as VT. + bool knownBitsLE(EVT VT) const { + return TypeSize::isKnownLE(getSizeInBits(), VT.getSizeInBits()); + } + /// Return true if this has more bits than VT. bool bitsGT(EVT VT) const { if (EVT::operator==(VT)) return false; - return getSizeInBits() > VT.getSizeInBits(); + assert(isScalableVector() == VT.isScalableVector() && + "Comparison between scalable and fixed types"); + return knownBitsGT(VT); } /// Return true if this has no less bits than VT. bool bitsGE(EVT VT) const { if (EVT::operator==(VT)) return true; - return getSizeInBits() >= VT.getSizeInBits(); + assert(isScalableVector() == VT.isScalableVector() && + "Comparison between scalable and fixed types"); + return knownBitsGE(VT); } /// Return true if this has less bits than VT. bool bitsLT(EVT VT) const { if (EVT::operator==(VT)) return false; - return getSizeInBits() < VT.getSizeInBits(); + assert(isScalableVector() == VT.isScalableVector() && + "Comparison between scalable and fixed types"); + return knownBitsLT(VT); } /// Return true if this has no more bits than VT. bool bitsLE(EVT VT) const { if (EVT::operator==(VT)) return true; - return getSizeInBits() <= VT.getSizeInBits(); + assert(isScalableVector() == VT.isScalableVector() && + "Comparison between scalable and fixed types"); + return knownBitsLE(VT); } /// Return the SimpleValueType held in the specified simple EVT. Index: llvm/include/llvm/Support/MachineValueType.h =================================================================== --- llvm/include/llvm/Support/MachineValueType.h +++ llvm/include/llvm/Support/MachineValueType.h @@ -954,24 +954,54 @@ return getSizeInBits().isByteSized(); } + /// Return true if we know at compile time this has more bits than VT. + bool knownBitsGT(MVT VT) const { + return TypeSize::isKnownGT(getSizeInBits(), VT.getSizeInBits()); + } + + /// Return true if we know at compile time this has more than or the same + /// bits as VT. + bool knownBitsGE(MVT VT) const { + return TypeSize::isKnownGE(getSizeInBits(), VT.getSizeInBits()); + } + + /// Return true if we know at compile time this has fewer bits than VT. + bool knownBitsLT(MVT VT) const { + return TypeSize::isKnownLT(getSizeInBits(), VT.getSizeInBits()); + } + + /// Return true if we know at compile time this has fewer than or the same + /// bits as VT. + bool knownBitsLE(MVT VT) const { + return TypeSize::isKnownLE(getSizeInBits(), VT.getSizeInBits()); + } + /// Return true if this has more bits than VT. bool bitsGT(MVT VT) const { - return getSizeInBits() > VT.getSizeInBits(); + assert(isScalableVector() == VT.isScalableVector() && + "Comparison between scalable and fixed types"); + return knownBitsGT(VT); } /// Return true if this has no less bits than VT. bool bitsGE(MVT VT) const { - return getSizeInBits() >= VT.getSizeInBits(); + assert(isScalableVector() == VT.isScalableVector() && + "Comparison between scalable and fixed types"); + return knownBitsGE(VT); } /// Return true if this has less bits than VT. bool bitsLT(MVT VT) const { - return getSizeInBits() < VT.getSizeInBits(); + assert(isScalableVector() == VT.isScalableVector() && + "Comparison between scalable and fixed types"); + return knownBitsLT(VT); } /// Return true if this has no more bits than VT. bool bitsLE(MVT VT) const { - return getSizeInBits() <= VT.getSizeInBits(); + assert(isScalableVector() == VT.isScalableVector() && + "Comparison between scalable and fixed types"); + return knownBitsLE(VT); } static MVT getFloatingPointVT(unsigned BitWidth) { Index: llvm/include/llvm/Support/TypeSize.h =================================================================== --- llvm/include/llvm/Support/TypeSize.h +++ llvm/include/llvm/Support/TypeSize.h @@ -165,23 +165,52 @@ // Scalable vector types with the same minimum size as a fixed size type are // not guaranteed to be the same size at runtime, so they are never // considered to be equal. - friend bool operator==(const TypeSize &LHS, const TypeSize &RHS) { - return LHS.MinSize == RHS.MinSize && LHS.IsScalable == RHS.IsScalable; + bool operator==(const TypeSize &RHS) const { + return MinSize == RHS.MinSize && IsScalable == RHS.IsScalable; } - friend bool operator!=(const TypeSize &LHS, const TypeSize &RHS) { - return !(LHS == RHS); + bool operator!=(const TypeSize &RHS) const { + return !(*this == RHS); } - // For many cases, size ordering between scalable and fixed size types cannot + // For some cases, size ordering between scalable and fixed size types cannot // be determined at compile time, so such comparisons aren't allowed. // // e.g. could be bigger than <4 x i32> with a runtime // vscale >= 5, equal sized with a vscale of 4, and smaller with // a vscale <= 3. // - // If the scalable flags match, just perform the requested comparison - // between the minimum sizes. + // All the functions below make use of the fact vscale is always >= 1, which + // means that is guaranteed to be >= <4 x i32>, etc. + + static bool isKnownLT(const TypeSize &LHS, const TypeSize &RHS) { + if (!LHS.IsScalable || RHS.IsScalable) return LHS.MinSize < RHS.MinSize; + + // LHS.IsScalable = true, RHS.IsScalable = false + return false; + } + + static bool isKnownGT(const TypeSize &LHS, const TypeSize &RHS) { + if (LHS.IsScalable || !RHS.IsScalable) return LHS.MinSize > RHS.MinSize; + + // LHS.IsScalable = false, RHS.IsScalable = true + return false; + } + + static bool isKnownLE(const TypeSize &LHS, const TypeSize &RHS) { + if (!LHS.IsScalable || RHS.IsScalable) return LHS.MinSize <= RHS.MinSize; + + // LHS.IsScalable = true, RHS.IsScalable = false + return false; + } + + static bool isKnownGE(const TypeSize &LHS, const TypeSize& RHS) { + if (LHS.IsScalable || !RHS.IsScalable) return LHS.MinSize >= RHS.MinSize; + + // LHS.IsScalable = false, RHS.IsScalable = true + return false; + } + friend bool operator<(const TypeSize &LHS, const TypeSize &RHS) { assert(LHS.IsScalable == RHS.IsScalable && "Ordering comparison of scalable and fixed types");