1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-23 03:02:36 +01:00

[SVE][CodeGen] Scalable vector MVT size queries

* Implements scalable size queries for MVTs, split out from D53137.

* Contains a fix for FindMemType to avoid using scalable vector type
  to contain non-scalable types.

* Explicit casts for several places where implicit integer sign
  changes or promotion from 32 to 64 bits caused problems.

* CodeGenDAGPatterns will treat scalable and non-scalable vector types
  as different.

Reviewers: greened, cameron.mcinally, sdesmalen, rovka

Reviewed By: rovka

Differential Revision: https://reviews.llvm.org/D66871
This commit is contained in:
Graham Hunter 2019-08-14 11:48:39 +01:00
parent e3dc3bbf4c
commit 6e15087bc5
20 changed files with 268 additions and 116 deletions

View File

@ -42,6 +42,7 @@
#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MachineValueType.h"
#include "llvm/Support/TypeSize.h"
#include <algorithm>
#include <cassert>
#include <climits>
@ -170,11 +171,15 @@ public:
}
/// Returns the size of the value in bits.
unsigned getValueSizeInBits() const {
///
/// If the value type is a scalable vector type, the scalable property will
/// be set and the runtime size will be a positive integer multiple of the
/// base size.
TypeSize getValueSizeInBits() const {
return getValueType().getSizeInBits();
}
unsigned getScalarValueSizeInBits() const {
TypeSize getScalarValueSizeInBits() const {
return getValueType().getScalarType().getSizeInBits();
}
@ -1022,7 +1027,11 @@ public:
}
/// Returns MVT::getSizeInBits(getValueType(ResNo)).
unsigned getValueSizeInBits(unsigned ResNo) const {
///
/// If the value type is a scalable vector type, the scalable property will
/// be set and the runtime size will be a positive integer multiple of the
/// base size.
TypeSize getValueSizeInBits(unsigned ResNo) const {
return getValueType(ResNo).getSizeInBits();
}

View File

@ -18,6 +18,7 @@
#include "llvm/Support/Compiler.h"
#include "llvm/Support/MachineValueType.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/TypeSize.h"
#include <cassert>
#include <cstdint>
#include <string>
@ -209,11 +210,13 @@ namespace llvm {
/// Return true if the bit size is a multiple of 8.
bool isByteSized() const {
return (getSizeInBits() & 7) == 0;
return getSizeInBits().isByteSized();
}
/// Return true if the size is a power-of-two number of bytes.
bool isRound() const {
if (isScalableVector())
return false;
unsigned BitSize = getSizeInBits();
return BitSize >= 8 && !(BitSize & (BitSize - 1));
}
@ -288,25 +291,38 @@ namespace llvm {
}
/// Return the size of the specified value type in bits.
unsigned getSizeInBits() const {
///
/// If the value type is a scalable vector type, the scalable property will
/// be set and the runtime size will be a positive integer multiple of the
/// base size.
TypeSize getSizeInBits() const {
if (isSimple())
return V.getSizeInBits();
return getExtendedSizeInBits();
}
unsigned getScalarSizeInBits() const {
TypeSize getScalarSizeInBits() const {
return getScalarType().getSizeInBits();
}
/// Return the number of bytes overwritten by a store of the specified value
/// type.
unsigned getStoreSize() const {
return (getSizeInBits() + 7) / 8;
///
/// If the value type is a scalable vector type, the scalable property will
/// be set and the runtime size will be a positive integer multiple of the
/// base size.
TypeSize getStoreSize() const {
TypeSize BaseSize = getSizeInBits();
return {(BaseSize.getKnownMinSize() + 7) / 8, BaseSize.isScalable()};
}
/// Return the number of bits overwritten by a store of the specified value
/// type.
unsigned getStoreSizeInBits() const {
///
/// If the value type is a scalable vector type, the scalable property will
/// be set and the runtime size will be a positive integer multiple of the
/// base size.
TypeSize getStoreSizeInBits() const {
return getStoreSize() * 8;
}
@ -428,7 +444,7 @@ namespace llvm {
bool isExtended2048BitVector() const LLVM_READONLY;
EVT getExtendedVectorElementType() const;
unsigned getExtendedVectorNumElements() const LLVM_READONLY;
unsigned getExtendedSizeInBits() const LLVM_READONLY;
TypeSize getExtendedSizeInBits() const LLVM_READONLY;
};
} // end namespace llvm

View File

@ -671,7 +671,12 @@ namespace llvm {
return { getVectorNumElements(), isScalableVector() };
}
unsigned getSizeInBits() const {
/// Returns the size of the specified MVT in bits.
///
/// If the value type is a scalable vector type, the scalable property will
/// be set and the runtime size will be a positive integer multiple of the
/// base size.
TypeSize getSizeInBits() const {
switch (SimpleTy) {
default:
llvm_unreachable("getSizeInBits called on extended MVT.");
@ -691,25 +696,25 @@ namespace llvm {
case Metadata:
llvm_unreachable("Value type is metadata.");
case i1:
case v1i1:
case nxv1i1: return 1;
case v2i1:
case nxv2i1: return 2;
case v4i1:
case nxv4i1: return 4;
case v1i1: return TypeSize::Fixed(1);
case nxv1i1: return TypeSize::Scalable(1);
case v2i1: return TypeSize::Fixed(2);
case nxv2i1: return TypeSize::Scalable(2);
case v4i1: return TypeSize::Fixed(4);
case nxv4i1: return TypeSize::Scalable(4);
case i8 :
case v1i8:
case v8i1:
case v8i1: return TypeSize::Fixed(8);
case nxv1i8:
case nxv8i1: return 8;
case nxv8i1: return TypeSize::Scalable(8);
case i16 :
case f16:
case v16i1:
case v2i8:
case v1i16:
case v1i16: return TypeSize::Fixed(16);
case nxv16i1:
case nxv2i8:
case nxv1i16: return 16;
case nxv1i16: return TypeSize::Scalable(16);
case f32 :
case i32 :
case v32i1:
@ -717,15 +722,15 @@ namespace llvm {
case v2i16:
case v2f16:
case v1f32:
case v1i32:
case v1i32: return TypeSize::Fixed(32);
case nxv32i1:
case nxv4i8:
case nxv2i16:
case nxv1i32:
case nxv2f16:
case nxv1f32: return 32;
case nxv1f32: return TypeSize::Scalable(32);
case v3i16:
case v3f16: return 48;
case v3f16: return TypeSize::Fixed(48);
case x86mmx:
case f64 :
case i64 :
@ -736,17 +741,17 @@ namespace llvm {
case v1i64:
case v4f16:
case v2f32:
case v1f64:
case v1f64: return TypeSize::Fixed(64);
case nxv8i8:
case nxv4i16:
case nxv2i32:
case nxv1i64:
case nxv4f16:
case nxv2f32:
case nxv1f64: return 64;
case f80 : return 80;
case nxv1f64: return TypeSize::Scalable(64);
case f80 : return TypeSize::Fixed(80);
case v3i32:
case v3f32: return 96;
case v3f32: return TypeSize::Fixed(96);
case f128:
case ppcf128:
case i128:
@ -758,16 +763,16 @@ namespace llvm {
case v1i128:
case v8f16:
case v4f32:
case v2f64:
case v2f64: return TypeSize::Fixed(128);
case nxv16i8:
case nxv8i16:
case nxv4i32:
case nxv2i64:
case nxv8f16:
case nxv4f32:
case nxv2f64: return 128;
case nxv2f64: return TypeSize::Scalable(128);
case v5i32:
case v5f32: return 160;
case v5f32: return TypeSize::Fixed(160);
case v256i1:
case v32i8:
case v16i16:
@ -775,13 +780,13 @@ namespace llvm {
case v4i64:
case v16f16:
case v8f32:
case v4f64:
case v4f64: return TypeSize::Fixed(256);
case nxv32i8:
case nxv16i16:
case nxv8i32:
case nxv4i64:
case nxv8f32:
case nxv4f64: return 256;
case nxv4f64: return TypeSize::Scalable(256);
case v512i1:
case v64i8:
case v32i16:
@ -789,56 +794,71 @@ namespace llvm {
case v8i64:
case v32f16:
case v16f32:
case v8f64:
case v8f64: return TypeSize::Fixed(512);
case nxv32i16:
case nxv16i32:
case nxv8i64:
case nxv16f32:
case nxv8f64: return 512;
case nxv8f64: return TypeSize::Scalable(512);
case v1024i1:
case v128i8:
case v64i16:
case v32i32:
case v16i64:
case v32f32:
case v32f32: return TypeSize::Fixed(1024);
case nxv32i32:
case nxv16i64: return 1024;
case nxv16i64: return TypeSize::Scalable(1024);
case v256i8:
case v128i16:
case v64i32:
case v32i64:
case v64f32:
case nxv32i64: return 2048;
case v64f32: return TypeSize::Fixed(2048);
case nxv32i64: return TypeSize::Scalable(2048);
case v128i32:
case v128f32: return 4096;
case v128f32: return TypeSize::Fixed(4096);
case v256i32:
case v256f32: return 8192;
case v256f32: return TypeSize::Fixed(8192);
case v512i32:
case v512f32: return 16384;
case v512f32: return TypeSize::Fixed(16384);
case v1024i32:
case v1024f32: return 32768;
case v1024f32: return TypeSize::Fixed(32768);
case v2048i32:
case v2048f32: return 65536;
case exnref: return 0; // opaque type
case v2048f32: return TypeSize::Fixed(65536);
case exnref: return TypeSize::Fixed(0); // opaque type
}
}
unsigned getScalarSizeInBits() const {
TypeSize getScalarSizeInBits() const {
return getScalarType().getSizeInBits();
}
/// Return the number of bytes overwritten by a store of the specified value
/// type.
unsigned getStoreSize() const {
return (getSizeInBits() + 7) / 8;
///
/// If the value type is a scalable vector type, the scalable property will
/// be set and the runtime size will be a positive integer multiple of the
/// base size.
TypeSize getStoreSize() const {
TypeSize BaseSize = getSizeInBits();
return {(BaseSize.getKnownMinSize() + 7) / 8, BaseSize.isScalable()};
}
/// Return the number of bits overwritten by a store of the specified value
/// type.
unsigned getStoreSizeInBits() const {
///
/// If the value type is a scalable vector type, the scalable property will
/// be set and the runtime size will be a positive integer multiple of the
/// base size.
TypeSize getStoreSizeInBits() const {
return getStoreSize() * 8;
}
/// Returns true if the number of bits for the type is a multiple of an
/// 8-bit byte.
bool isByteSized() const {
return getSizeInBits().isByteSized();
}
/// Return true if this has more bits than VT.
bool bitsGT(MVT VT) const {
return getSizeInBits() > VT.getSizeInBits();

View File

@ -138,6 +138,11 @@ public:
return IsScalable;
}
// Returns true if the number of bits is a multiple of an 8-bit byte.
bool isByteSized() const {
return (MinSize & 7) == 0;
}
// Casts to a uint64_t if this is a fixed-width size.
//
// NOTE: This interface is obsolete and will be removed in a future version

View File

@ -220,11 +220,13 @@ namespace {
ForCodeSize = DAG.getMachineFunction().getFunction().hasOptSize();
MaximumLegalStoreInBits = 0;
// We use the minimum store size here, since that's all we can guarantee
// for the scalable vector types.
for (MVT VT : MVT::all_valuetypes())
if (EVT(VT).isSimple() && VT != MVT::Other &&
TLI.isTypeLegal(EVT(VT)) &&
VT.getSizeInBits() >= MaximumLegalStoreInBits)
MaximumLegalStoreInBits = VT.getSizeInBits();
VT.getSizeInBits().getKnownMinSize() >= MaximumLegalStoreInBits)
MaximumLegalStoreInBits = VT.getSizeInBits().getKnownMinSize();
}
void ConsiderForPruning(SDNode *N) {
@ -13969,8 +13971,8 @@ SDValue DAGCombiner::ForwardStoreValueToDirectLoad(LoadSDNode *LD) {
// the stored value). With Offset=n (for n > 0) the loaded value starts at the
// n:th least significant byte of the stored value.
if (DAG.getDataLayout().isBigEndian())
Offset = (STMemType.getStoreSizeInBits() -
LDMemType.getStoreSizeInBits()) / 8 - Offset;
Offset = ((int64_t)STMemType.getStoreSizeInBits() -
(int64_t)LDMemType.getStoreSizeInBits()) / 8 - Offset;
// Check that the stored value cover all bits that are loaded.
bool STCoversLD =
@ -15127,7 +15129,7 @@ bool DAGCombiner::MergeStoresOfConstantsOrVecElts(
// The latest Node in the DAG.
SDLoc DL(StoreNodes[0].MemNode);
int64_t ElementSizeBits = MemVT.getStoreSizeInBits();
TypeSize ElementSizeBits = MemVT.getStoreSizeInBits();
unsigned SizeInBits = NumStores * ElementSizeBits;
unsigned NumMemElts = MemVT.isVector() ? MemVT.getVectorNumElements() : 1;
@ -15512,7 +15514,7 @@ bool DAGCombiner::MergeConsecutiveStores(StoreSDNode *St) {
Attribute::NoImplicitFloat);
// This function cannot currently deal with non-byte-sized memory sizes.
if (ElementSizeBytes * 8 != MemVT.getSizeInBits())
if (ElementSizeBytes * 8 != (int64_t)MemVT.getSizeInBits())
return false;
if (!MemVT.isSimple())

View File

@ -23,6 +23,7 @@
#include "llvm/IR/DataLayout.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/TypeSize.h"
using namespace llvm;
#define DEBUG_TYPE "legalize-types"
@ -4680,7 +4681,8 @@ static EVT FindMemType(SelectionDAG& DAG, const TargetLowering &TLI,
unsigned Width, EVT WidenVT,
unsigned Align = 0, unsigned WidenEx = 0) {
EVT WidenEltVT = WidenVT.getVectorElementType();
unsigned WidenWidth = WidenVT.getSizeInBits();
const bool Scalable = WidenVT.isScalableVector();
unsigned WidenWidth = WidenVT.getSizeInBits().getKnownMinSize();
unsigned WidenEltWidth = WidenEltVT.getSizeInBits();
unsigned AlignInBits = Align*8;
@ -4691,23 +4693,27 @@ static EVT FindMemType(SelectionDAG& DAG, const TargetLowering &TLI,
// See if there is larger legal integer than the element type to load/store.
unsigned VT;
for (VT = (unsigned)MVT::LAST_INTEGER_VALUETYPE;
VT >= (unsigned)MVT::FIRST_INTEGER_VALUETYPE; --VT) {
EVT MemVT((MVT::SimpleValueType) VT);
unsigned MemVTWidth = MemVT.getSizeInBits();
if (MemVT.getSizeInBits() <= WidenEltWidth)
break;
auto Action = TLI.getTypeAction(*DAG.getContext(), MemVT);
if ((Action == TargetLowering::TypeLegal ||
Action == TargetLowering::TypePromoteInteger) &&
(WidenWidth % MemVTWidth) == 0 &&
isPowerOf2_32(WidenWidth / MemVTWidth) &&
(MemVTWidth <= Width ||
(Align!=0 && MemVTWidth<=AlignInBits && MemVTWidth<=Width+WidenEx))) {
if (MemVTWidth == WidenWidth)
return MemVT;
RetVT = MemVT;
break;
// Don't bother looking for an integer type if the vector is scalable, skip
// to vector types.
if (!Scalable) {
for (VT = (unsigned)MVT::LAST_INTEGER_VALUETYPE;
VT >= (unsigned)MVT::FIRST_INTEGER_VALUETYPE; --VT) {
EVT MemVT((MVT::SimpleValueType) VT);
unsigned MemVTWidth = MemVT.getSizeInBits();
if (MemVT.getSizeInBits() <= WidenEltWidth)
break;
auto Action = TLI.getTypeAction(*DAG.getContext(), MemVT);
if ((Action == TargetLowering::TypeLegal ||
Action == TargetLowering::TypePromoteInteger) &&
(WidenWidth % MemVTWidth) == 0 &&
isPowerOf2_32(WidenWidth / MemVTWidth) &&
(MemVTWidth <= Width ||
(Align!=0 && MemVTWidth<=AlignInBits && MemVTWidth<=Width+WidenEx))) {
if (MemVTWidth == WidenWidth)
return MemVT;
RetVT = MemVT;
break;
}
}
}
@ -4716,7 +4722,10 @@ static EVT FindMemType(SelectionDAG& DAG, const TargetLowering &TLI,
for (VT = (unsigned)MVT::LAST_VECTOR_VALUETYPE;
VT >= (unsigned)MVT::FIRST_VECTOR_VALUETYPE; --VT) {
EVT MemVT = (MVT::SimpleValueType) VT;
unsigned MemVTWidth = MemVT.getSizeInBits();
// Skip vector MVTs which don't match the scalable property of WidenVT.
if (Scalable != MemVT.isScalableVector())
continue;
unsigned MemVTWidth = MemVT.getSizeInBits().getKnownMinSize();
auto Action = TLI.getTypeAction(*DAG.getContext(), MemVT);
if ((Action == TargetLowering::TypeLegal ||
Action == TargetLowering::TypePromoteInteger) &&

View File

@ -8842,7 +8842,9 @@ MemSDNode::MemSDNode(unsigned Opc, unsigned Order, const DebugLoc &dl,
// We check here that the size of the memory operand fits within the size of
// the MMO. This is because the MMO might indicate only a possible address
// range instead of specifying the affected memory addresses precisely.
assert(memvt.getStoreSize() <= MMO->getSize() && "Size mismatch!");
// TODO: Make MachineMemOperands aware of scalable vectors.
assert(memvt.getStoreSize().getKnownMinSize() <= MMO->getSize() &&
"Size mismatch!");
}
/// Profile - Gather unique data for the node.

View File

@ -4304,7 +4304,10 @@ void SelectionDAGBuilder::visitMaskedStore(const CallInst &I,
MachineMemOperand *MMO =
DAG.getMachineFunction().
getMachineMemOperand(MachinePointerInfo(PtrOperand),
MachineMemOperand::MOStore, VT.getStoreSize(),
MachineMemOperand::MOStore,
// TODO: Make MachineMemOperands aware of scalable
// vectors.
VT.getStoreSize().getKnownMinSize(),
Alignment, AAInfo);
SDValue StoreNode = DAG.getMaskedStore(getRoot(), sdl, Src0, Ptr, Mask, VT,
MMO, false /* Truncating */,
@ -4408,7 +4411,10 @@ void SelectionDAGBuilder::visitMaskedScatter(const CallInst &I) {
const Value *MemOpBasePtr = UniformBase ? BasePtr : nullptr;
MachineMemOperand *MMO = DAG.getMachineFunction().
getMachineMemOperand(MachinePointerInfo(MemOpBasePtr),
MachineMemOperand::MOStore, VT.getStoreSize(),
MachineMemOperand::MOStore,
// TODO: Make MachineMemOperands aware of scalable
// vectors.
VT.getStoreSize().getKnownMinSize(),
Alignment, AAInfo);
if (!UniformBase) {
Base = DAG.getConstant(0, sdl, TLI.getPointerTy(DAG.getDataLayout()));
@ -4477,7 +4483,10 @@ void SelectionDAGBuilder::visitMaskedLoad(const CallInst &I, bool IsExpanding) {
MachineMemOperand *MMO =
DAG.getMachineFunction().
getMachineMemOperand(MachinePointerInfo(PtrOperand),
MachineMemOperand::MOLoad, VT.getStoreSize(),
MachineMemOperand::MOLoad,
// TODO: Make MachineMemOperands aware of scalable
// vectors.
VT.getStoreSize().getKnownMinSize(),
Alignment, AAInfo, Ranges);
SDValue Load = DAG.getMaskedLoad(VT, sdl, InChain, Ptr, Mask, Src0, VT, MMO,
@ -4528,7 +4537,10 @@ void SelectionDAGBuilder::visitMaskedGather(const CallInst &I) {
MachineMemOperand *MMO =
DAG.getMachineFunction().
getMachineMemOperand(MachinePointerInfo(UniformBase ? BasePtr : nullptr),
MachineMemOperand::MOLoad, VT.getStoreSize(),
MachineMemOperand::MOLoad,
// TODO: Make MachineMemOperands aware of scalable
// vectors.
VT.getStoreSize().getKnownMinSize(),
Alignment, AAInfo, Ranges);
if (!UniformBase) {
@ -9248,9 +9260,11 @@ TargetLowering::LowerCallTo(TargetLowering::CallLoweringInfo &CLI) const {
for (unsigned j = 0; j != NumParts; ++j) {
// if it isn't first piece, alignment must be 1
// For scalable vectors the scalable part is currently handled
// by individual targets, so we just use the known minimum size here.
ISD::OutputArg MyFlags(Flags, Parts[j].getValueType(), VT,
i < CLI.NumFixedArgs,
i, j*Parts[j].getValueType().getStoreSize());
i < CLI.NumFixedArgs, i,
j*Parts[j].getValueType().getStoreSize().getKnownMinSize());
if (NumParts > 1 && j == 0)
MyFlags.Flags.setSplit();
else if (j != 0) {
@ -9719,8 +9733,11 @@ void SelectionDAGISel::LowerArguments(const Function &F) {
unsigned NumRegs = TLI->getNumRegistersForCallingConv(
*CurDAG->getContext(), F.getCallingConv(), VT);
for (unsigned i = 0; i != NumRegs; ++i) {
// For scalable vectors, use the minimum size; individual targets
// are responsible for handling scalable vector arguments and
// return values.
ISD::InputArg MyFlags(Flags, RegisterVT, VT, isArgValueUsed,
ArgNo, PartBase+i*RegisterVT.getStoreSize());
ArgNo, PartBase+i*RegisterVT.getStoreSize().getKnownMinSize());
if (NumRegs > 1 && i == 0)
MyFlags.Flags.setSplit();
// if it isn't first piece, alignment must be 1
@ -9733,7 +9750,7 @@ void SelectionDAGISel::LowerArguments(const Function &F) {
}
if (NeedsRegBlock && Value == NumValues - 1)
Ins[Ins.size() - 1].Flags.setInConsecutiveRegsLast();
PartBase += VT.getStoreSize();
PartBase += VT.getStoreSize().getKnownMinSize();
}
}

View File

@ -384,7 +384,8 @@ spillIncomingStatepointValue(SDValue Incoming, SDValue Chain,
// can consider allowing spills of smaller values to larger slots
// (i.e. change the '==' in the assert below to a '>=').
MachineFrameInfo &MFI = Builder.DAG.getMachineFunction().getFrameInfo();
assert((MFI.getObjectSize(Index) * 8) == Incoming.getValueSizeInBits() &&
assert((MFI.getObjectSize(Index) * 8) ==
(int64_t)Incoming.getValueSizeInBits() &&
"Bad spill: stack slot does not match!");
// Note: Using the alignment of the spill slot (rather than the abi or

View File

@ -11,6 +11,7 @@
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Type.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/TypeSize.h"
using namespace llvm;
EVT EVT::changeExtendedTypeToInteger() const {
@ -101,12 +102,12 @@ unsigned EVT::getExtendedVectorNumElements() const {
return cast<VectorType>(LLVMTy)->getNumElements();
}
unsigned EVT::getExtendedSizeInBits() const {
TypeSize EVT::getExtendedSizeInBits() const {
assert(isExtended() && "Type is not extended!");
if (IntegerType *ITy = dyn_cast<IntegerType>(LLVMTy))
return ITy->getBitWidth();
return TypeSize::Fixed(ITy->getBitWidth());
if (VectorType *VTy = dyn_cast<VectorType>(LLVMTy))
return VTy->getBitWidth();
return VTy->getPrimitiveSizeInBits();
llvm_unreachable("Unrecognized extended type!");
}

View File

@ -9937,7 +9937,7 @@ static SDValue performBitcastCombine(SDNode *N,
// Only interested in 64-bit vectors as the ultimate result.
EVT VT = N->getValueType(0);
if (!VT.isVector())
if (!VT.isVector() || VT.isScalableVector())
return SDValue();
if (VT.getSimpleVT().getSizeInBits() != 64)
return SDValue();

View File

@ -15,6 +15,7 @@
#define LLVM_LIB_TARGET_AARCH64_AARCH64STACKOFFSET_H
#include "llvm/Support/MachineValueType.h"
#include "llvm/Support/TypeSize.h"
namespace llvm {
@ -45,8 +46,7 @@ public:
StackOffset() : Bytes(0), ScalableBytes(0) {}
StackOffset(int64_t Offset, MVT::SimpleValueType T) : StackOffset() {
assert(MVT(T).getSizeInBits() % 8 == 0 &&
"Offset type is not a multiple of bytes");
assert(MVT(T).isByteSized() && "Offset type is not a multiple of bytes");
*this += Part(Offset, T);
}
@ -56,11 +56,11 @@ public:
StackOffset &operator=(const StackOffset &) = default;
StackOffset &operator+=(const StackOffset::Part &Other) {
int64_t OffsetInBytes = Other.first * (Other.second.getSizeInBits() / 8);
if (Other.second.isScalableVector())
ScalableBytes += OffsetInBytes;
const TypeSize Size = Other.second.getSizeInBits();
if (Size.isScalable())
ScalableBytes += Other.first * ((int64_t)Size.getKnownMinSize() / 8);
else
Bytes += OffsetInBytes;
Bytes += Other.first * ((int64_t)Size.getFixedSize() / 8);
return *this;
}

View File

@ -14886,7 +14886,7 @@ static bool isLegalT2AddressImmediate(int64_t V, EVT VT,
V = -V;
}
unsigned NumBytes = std::max(VT.getSizeInBits() / 8, 1U);
unsigned NumBytes = std::max((unsigned)VT.getSizeInBits() / 8, 1U);
// MVE: size * imm7
if (VT.isVector() && Subtarget->hasMVEIntegerOps()) {

View File

@ -475,7 +475,7 @@ HexagonTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
MemAddr = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, MemAddr);
if (ArgAlign)
LargestAlignSeen = std::max(LargestAlignSeen,
VA.getLocVT().getStoreSizeInBits() >> 3);
(unsigned)VA.getLocVT().getStoreSizeInBits() >> 3);
if (Flags.isByVal()) {
// The argument is a struct passed by value. According to LLVM, "Arg"
// is a pointer.

View File

@ -122,7 +122,8 @@ unsigned MipsTargetLowering::getNumRegistersForCallingConv(LLVMContext &Context,
CallingConv::ID CC,
EVT VT) const {
if (VT.isVector())
return std::max((VT.getSizeInBits() / (Subtarget.isABI_O32() ? 32 : 64)),
return std::max(((unsigned)VT.getSizeInBits() /
(Subtarget.isABI_O32() ? 32 : 64)),
1U);
return MipsTargetLowering::getNumRegisters(Context, VT);
}

View File

@ -885,7 +885,7 @@ bool NVPTXDAGToDAGISel::tryLoad(SDNode *N) {
MVT SimpleVT = LoadedVT.getSimpleVT();
MVT ScalarVT = SimpleVT.getScalarType();
// Read at least 8 bits (predicates are stored as 8-bit values)
unsigned fromTypeWidth = std::max(8U, ScalarVT.getSizeInBits());
unsigned fromTypeWidth = std::max(8U, (unsigned)ScalarVT.getSizeInBits());
unsigned int fromType;
// Vector Setting
@ -1030,7 +1030,7 @@ bool NVPTXDAGToDAGISel::tryLoadVector(SDNode *N) {
// Float : ISD::NON_EXTLOAD or ISD::EXTLOAD and the type is float
MVT ScalarVT = SimpleVT.getScalarType();
// Read at least 8 bits (predicates are stored as 8-bit values)
unsigned FromTypeWidth = std::max(8U, ScalarVT.getSizeInBits());
unsigned FromTypeWidth = std::max(8U, (unsigned)ScalarVT.getSizeInBits());
unsigned int FromType;
// The last operand holds the original LoadSDNode::getExtensionType() value
unsigned ExtensionType = cast<ConstantSDNode>(

View File

@ -1044,7 +1044,7 @@ static unsigned allUsesTruncate(SelectionDAG *CurDAG, SDNode *N) {
if (Use->isMachineOpcode())
return 0;
MaxTruncation =
std::max(MaxTruncation, Use->getValueType(0).getSizeInBits());
std::max(MaxTruncation, (unsigned)Use->getValueType(0).getSizeInBits());
continue;
case ISD::STORE: {
if (Use->isMachineOpcode())

View File

@ -5835,7 +5835,7 @@ static SDValue getExtendInVec(unsigned Opcode, const SDLoc &DL, EVT VT,
"Expected VTs to be the same size!");
unsigned Scale = VT.getScalarSizeInBits() / InVT.getScalarSizeInBits();
In = extractSubVector(In, 0, DAG, DL,
std::max(128U, VT.getSizeInBits() / Scale));
std::max(128U, (unsigned)VT.getSizeInBits() / Scale));
InVT = In.getValueType();
}
@ -8626,7 +8626,7 @@ static SDValue LowerBUILD_VECTORvXi1(SDValue Op, SelectionDAG &DAG,
ImmH = DAG.getBitcast(MVT::v32i1, ImmH);
DstVec = DAG.getNode(ISD::CONCAT_VECTORS, dl, MVT::v64i1, ImmL, ImmH);
} else {
MVT ImmVT = MVT::getIntegerVT(std::max(VT.getSizeInBits(), 8U));
MVT ImmVT = MVT::getIntegerVT(std::max((unsigned)VT.getSizeInBits(), 8U));
SDValue Imm = DAG.getConstant(Immediate, dl, ImmVT);
MVT VecVT = VT.getSizeInBits() >= 8 ? VT : MVT::v8i1;
DstVec = DAG.getBitcast(VecVT, Imm);
@ -32849,7 +32849,8 @@ static SDValue combineX86ShuffleChainWithExtract(
Offset += Src.getConstantOperandVal(1);
Src = Src.getOperand(0);
}
WideSizeInBits = std::max(WideSizeInBits, Src.getValueSizeInBits());
WideSizeInBits = std::max(WideSizeInBits,
(unsigned)Src.getValueSizeInBits());
assert((Offset % BaseVT.getVectorNumElements()) == 0 &&
"Unexpected subvector extraction");
Offset /= BaseVT.getVectorNumElements();
@ -35786,7 +35787,7 @@ static SDValue createPSADBW(SelectionDAG &DAG, const SDValue &Zext0,
const X86Subtarget &Subtarget) {
// Find the appropriate width for the PSADBW.
EVT InVT = Zext0.getOperand(0).getValueType();
unsigned RegSize = std::max(128u, InVT.getSizeInBits());
unsigned RegSize = std::max(128u, (unsigned)InVT.getSizeInBits());
// "Zero-extend" the i8 vectors. This is not a per-element zext, rather we
// fill in the missing vector elements with 0.

View File

@ -120,4 +120,61 @@ TEST(ScalableVectorMVTsTest, VTToIRTranslation) {
ScV4Float64Ty->getElementType());
}
TEST(ScalableVectorMVTsTest, SizeQueries) {
LLVMContext Ctx;
EVT nxv4i32 = EVT::getVectorVT(Ctx, MVT::i32, 4, /*Scalable=*/ true);
EVT nxv2i32 = EVT::getVectorVT(Ctx, MVT::i32, 2, /*Scalable=*/ true);
EVT nxv2i64 = EVT::getVectorVT(Ctx, MVT::i64, 2, /*Scalable=*/ true);
EVT nxv2f64 = EVT::getVectorVT(Ctx, MVT::f64, 2, /*Scalable=*/ true);
EVT v4i32 = EVT::getVectorVT(Ctx, MVT::i32, 4);
EVT v2i32 = EVT::getVectorVT(Ctx, MVT::i32, 2);
EVT v2i64 = EVT::getVectorVT(Ctx, MVT::i64, 2);
EVT v2f64 = EVT::getVectorVT(Ctx, MVT::f64, 2);
// Check equivalence and ordering on scalable types.
EXPECT_EQ(nxv4i32.getSizeInBits(), nxv2i64.getSizeInBits());
EXPECT_EQ(nxv2f64.getSizeInBits(), nxv2i64.getSizeInBits());
EXPECT_NE(nxv2i32.getSizeInBits(), nxv4i32.getSizeInBits());
EXPECT_LT(nxv2i32.getSizeInBits(), nxv2i64.getSizeInBits());
EXPECT_LE(nxv4i32.getSizeInBits(), nxv2i64.getSizeInBits());
EXPECT_GT(nxv4i32.getSizeInBits(), nxv2i32.getSizeInBits());
EXPECT_GE(nxv2i64.getSizeInBits(), nxv4i32.getSizeInBits());
// Check equivalence and ordering on fixed types.
EXPECT_EQ(v4i32.getSizeInBits(), v2i64.getSizeInBits());
EXPECT_EQ(v2f64.getSizeInBits(), v2i64.getSizeInBits());
EXPECT_NE(v2i32.getSizeInBits(), v4i32.getSizeInBits());
EXPECT_LT(v2i32.getSizeInBits(), v2i64.getSizeInBits());
EXPECT_LE(v4i32.getSizeInBits(), v2i64.getSizeInBits());
EXPECT_GT(v4i32.getSizeInBits(), v2i32.getSizeInBits());
EXPECT_GE(v2i64.getSizeInBits(), v4i32.getSizeInBits());
// Check that scalable and non-scalable types with the same minimum size
// are not considered equal.
ASSERT_TRUE(v4i32.getSizeInBits() != nxv4i32.getSizeInBits());
ASSERT_FALSE(v2i64.getSizeInBits() == nxv2f64.getSizeInBits());
// Check that we can obtain a known-exact size from a non-scalable type.
EXPECT_EQ(v4i32.getSizeInBits(), 128U);
EXPECT_EQ(v2i64.getSizeInBits().getFixedSize(), 128U);
// Check that we can query the known minimum size for both scalable and
// fixed length types.
EXPECT_EQ(nxv2i32.getSizeInBits().getKnownMinSize(), 64U);
EXPECT_EQ(nxv2f64.getSizeInBits().getKnownMinSize(), 128U);
EXPECT_EQ(v2i32.getSizeInBits().getKnownMinSize(),
nxv2i32.getSizeInBits().getKnownMinSize());
// Check scalable property.
ASSERT_FALSE(v4i32.getSizeInBits().isScalable());
ASSERT_TRUE(nxv4i32.getSizeInBits().isScalable());
// Check convenience size scaling methods.
EXPECT_EQ(v2i32.getSizeInBits() * 2, v4i32.getSizeInBits());
EXPECT_EQ(2 * nxv2i32.getSizeInBits(), nxv4i32.getSizeInBits());
EXPECT_EQ(nxv2f64.getSizeInBits() / 2, nxv2i32.getSizeInBits());
}
} // end anonymous namespace

View File

@ -23,6 +23,7 @@
#include "llvm/ADT/Twine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/TypeSize.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h"
#include <algorithm>
@ -503,18 +504,24 @@ bool TypeInfer::EnforceSmallerThan(TypeSetByHwMode &Small,
}
auto LT = [](MVT A, MVT B) -> bool {
return A.getScalarSizeInBits() < B.getScalarSizeInBits() ||
(A.getScalarSizeInBits() == B.getScalarSizeInBits() &&
A.getSizeInBits() < B.getSizeInBits());
// Always treat non-scalable MVTs as smaller than scalable MVTs for the
// purposes of ordering.
auto ASize = std::make_tuple(A.isScalableVector(), A.getScalarSizeInBits(),
A.getSizeInBits());
auto BSize = std::make_tuple(B.isScalableVector(), B.getScalarSizeInBits(),
B.getSizeInBits());
return ASize < BSize;
};
auto LE = [&LT](MVT A, MVT B) -> bool {
auto SameKindLE = [](MVT A, MVT B) -> bool {
// This function is used when removing elements: when a vector is compared
// to a non-vector, it should return false (to avoid removal).
if (A.isVector() != B.isVector())
// to a non-vector or a scalable vector to any non-scalable MVT, it should
// return false (to avoid removal).
if (std::make_tuple(A.isVector(), A.isScalableVector()) !=
std::make_tuple(B.isVector(), B.isScalableVector()))
return false;
return LT(A, B) || (A.getScalarSizeInBits() == B.getScalarSizeInBits() &&
A.getSizeInBits() == B.getSizeInBits());
return std::make_tuple(A.getScalarSizeInBits(), A.getSizeInBits()) <=
std::make_tuple(B.getScalarSizeInBits(), B.getSizeInBits());
};
for (unsigned M : Modes) {
@ -524,25 +531,29 @@ bool TypeInfer::EnforceSmallerThan(TypeSetByHwMode &Small,
// smaller-or-equal than MinS.
auto MinS = min_if(S.begin(), S.end(), isScalar, LT);
if (MinS != S.end())
Changed |= berase_if(B, std::bind(LE, std::placeholders::_1, *MinS));
Changed |= berase_if(B, std::bind(SameKindLE,
std::placeholders::_1, *MinS));
// MaxS = max scalar in Big, remove all scalars from Small that are
// larger than MaxS.
auto MaxS = max_if(B.begin(), B.end(), isScalar, LT);
if (MaxS != B.end())
Changed |= berase_if(S, std::bind(LE, *MaxS, std::placeholders::_1));
Changed |= berase_if(S, std::bind(SameKindLE,
*MaxS, std::placeholders::_1));
// MinV = min vector in Small, remove all vectors from Big that are
// smaller-or-equal than MinV.
auto MinV = min_if(S.begin(), S.end(), isVector, LT);
if (MinV != S.end())
Changed |= berase_if(B, std::bind(LE, std::placeholders::_1, *MinV));
Changed |= berase_if(B, std::bind(SameKindLE,
std::placeholders::_1, *MinV));
// MaxV = max vector in Big, remove all vectors from Small that are
// larger than MaxV.
auto MaxV = max_if(B.begin(), B.end(), isVector, LT);
if (MaxV != B.end())
Changed |= berase_if(S, std::bind(LE, *MaxV, std::placeholders::_1));
Changed |= berase_if(S, std::bind(SameKindLE,
*MaxV, std::placeholders::_1));
}
return Changed;