Revert "[GlobalISel][LLT] Introduce FPInfo for LLT (Enable bfloat, ppc128float and others in GlobalISel) (#155107)" (#188344)
This reverts commit b1aa6a45060bb9f89efded9e694503d6b4626a4a and commit
ce44d63e0d14039f1e8f68e6b7c4672457cabd4e.
This fails the build with some older gcc:
llvm/include/llvm/CodeGenTypes/LowLevelType.h:501:35: error: call to
non-constexpr function ‘static llvm::LLT llvm::LLT::integer(unsigned
int)’
return integer(getSizeInBits());
^
This commit is contained in:
parent
6b128091ba
commit
6a045c29a9
@ -650,8 +650,6 @@ private:
|
||||
|
||||
StackProtectorDescriptor SPDescriptor;
|
||||
|
||||
bool mayTranslateUserTypes(const User &U) const;
|
||||
|
||||
/// Switch analysis and optimization.
|
||||
class GISelSwitchLowering : public SwitchCG::SwitchLowering {
|
||||
public:
|
||||
|
||||
@ -402,11 +402,6 @@ LLVM_ABI LegalizeMutation changeElementCountTo(unsigned TypeIdx,
|
||||
LLVM_ABI LegalizeMutation changeElementSizeTo(unsigned TypeIdx,
|
||||
unsigned FromTypeIdx);
|
||||
|
||||
/// Change the scalar size or element size to have the same scalar size as the
|
||||
/// type \p NewTy. Unlike changeElementTo, this discards pointer types and only
|
||||
/// changes the size.
|
||||
LLVM_ABI LegalizeMutation changeElementSizeTo(unsigned TypeIdx, LLT NewTy);
|
||||
|
||||
/// Widen the scalar type or vector element type for the given type index to the
|
||||
/// next power of 2.
|
||||
LLVM_ABI LegalizeMutation widenScalarOrEltToNextPow2(unsigned TypeIdx,
|
||||
@ -1053,7 +1048,7 @@ public:
|
||||
using namespace LegalizeMutations;
|
||||
return actionIf(LegalizeAction::WidenScalar,
|
||||
scalarOrEltNarrowerThan(TypeIdx, Ty.getScalarSizeInBits()),
|
||||
changeElementSizeTo(typeIdx(TypeIdx), Ty));
|
||||
changeElementTo(typeIdx(TypeIdx), Ty));
|
||||
}
|
||||
|
||||
/// Ensure the scalar or element is at least as wide as Ty.
|
||||
@ -1064,7 +1059,7 @@ public:
|
||||
return actionIf(LegalizeAction::WidenScalar,
|
||||
all(Predicate, scalarOrEltNarrowerThan(
|
||||
TypeIdx, Ty.getScalarSizeInBits())),
|
||||
changeElementSizeTo(typeIdx(TypeIdx), Ty));
|
||||
changeElementTo(typeIdx(TypeIdx), Ty));
|
||||
}
|
||||
|
||||
/// Ensure the vector size is at least as wide as VectorSize by promoting the
|
||||
@ -1083,8 +1078,7 @@ public:
|
||||
const LLT VecTy = Query.Types[TypeIdx];
|
||||
unsigned NumElts = VecTy.getNumElements();
|
||||
unsigned MinSize = VectorSize / NumElts;
|
||||
LLT NewTy = LLT::fixed_vector(
|
||||
NumElts, VecTy.getElementType().changeElementSize(MinSize));
|
||||
LLT NewTy = LLT::fixed_vector(NumElts, LLT::scalar(MinSize));
|
||||
return std::make_pair(TypeIdx, NewTy);
|
||||
});
|
||||
}
|
||||
@ -1095,7 +1089,7 @@ public:
|
||||
using namespace LegalizeMutations;
|
||||
return actionIf(LegalizeAction::WidenScalar,
|
||||
scalarNarrowerThan(TypeIdx, Ty.getSizeInBits()),
|
||||
changeElementSizeTo(typeIdx(TypeIdx), Ty));
|
||||
changeTo(typeIdx(TypeIdx), Ty));
|
||||
}
|
||||
LegalizeRuleSet &minScalar(bool Pred, unsigned TypeIdx, const LLT Ty) {
|
||||
if (!Pred)
|
||||
@ -1116,7 +1110,7 @@ public:
|
||||
QueryTy.getSizeInBits() < Ty.getSizeInBits() &&
|
||||
Predicate(Query);
|
||||
},
|
||||
changeElementSizeTo(typeIdx(TypeIdx), Ty));
|
||||
changeTo(typeIdx(TypeIdx), Ty));
|
||||
}
|
||||
|
||||
/// Ensure the scalar is at most as wide as Ty.
|
||||
@ -1125,7 +1119,7 @@ public:
|
||||
using namespace LegalizeMutations;
|
||||
return actionIf(LegalizeAction::NarrowScalar,
|
||||
scalarOrEltWiderThan(TypeIdx, Ty.getScalarSizeInBits()),
|
||||
changeElementSizeTo(typeIdx(TypeIdx), Ty));
|
||||
changeElementTo(typeIdx(TypeIdx), Ty));
|
||||
}
|
||||
|
||||
/// Ensure the scalar is at most as wide as Ty.
|
||||
@ -1134,7 +1128,7 @@ public:
|
||||
using namespace LegalizeMutations;
|
||||
return actionIf(LegalizeAction::NarrowScalar,
|
||||
scalarWiderThan(TypeIdx, Ty.getSizeInBits()),
|
||||
changeElementSizeTo(typeIdx(TypeIdx), Ty));
|
||||
changeTo(typeIdx(TypeIdx), Ty));
|
||||
}
|
||||
|
||||
/// Conditionally limit the maximum size of the scalar.
|
||||
@ -1152,7 +1146,7 @@ public:
|
||||
QueryTy.getSizeInBits() > Ty.getSizeInBits() &&
|
||||
Predicate(Query);
|
||||
},
|
||||
changeElementSizeTo(typeIdx(TypeIdx), Ty));
|
||||
changeElementTo(typeIdx(TypeIdx), Ty));
|
||||
}
|
||||
|
||||
/// Limit the range of scalar sizes to MinTy and MaxTy.
|
||||
@ -1217,8 +1211,9 @@ public:
|
||||
Predicate(Query);
|
||||
},
|
||||
[=](const LegalityQuery &Query) {
|
||||
LLT T = Query.Types[TypeIdx].changeElementSize(
|
||||
Query.Types[LargeTypeIdx].getScalarSizeInBits());
|
||||
LLT T = Query.Types[LargeTypeIdx];
|
||||
if (T.isPointerVector())
|
||||
T = T.changeElementType(LLT::scalar(T.getScalarSizeInBits()));
|
||||
return std::make_pair(TypeIdx, T);
|
||||
});
|
||||
}
|
||||
|
||||
@ -41,6 +41,6 @@ LLVM_ABI LLT getLLTForMVT(MVT Ty);
|
||||
/// Get the appropriate floating point arithmetic semantic based on the bit size
|
||||
/// of the given scalar LLT.
|
||||
LLVM_ABI const llvm::fltSemantics &getFltSemanticForLLT(LLT Ty);
|
||||
} // namespace llvm
|
||||
}
|
||||
|
||||
#endif // LLVM_CODEGEN_LOWLEVELTYPEUTILS_H
|
||||
|
||||
@ -443,7 +443,7 @@ public:
|
||||
/// G_INSERT_VECTOR_ELT, G_EXTRACT_VECTOR_ELT,
|
||||
/// G_INSERT_SUBVECTOR, and G_EXTRACT_SUBVECTOR
|
||||
LLT getVectorIdxLLT(const DataLayout &DL) const {
|
||||
return LLT::integer(getVectorIdxWidth(DL));
|
||||
return LLT::scalar(getVectorIdxWidth(DL));
|
||||
}
|
||||
|
||||
/// Returns the type to be used for the EVL/AVL operand of VP nodes:
|
||||
|
||||
@ -9,32 +9,27 @@
|
||||
/// Implement a low-level type suitable for MachineInstr level instruction
|
||||
/// selection.
|
||||
///
|
||||
/// For a type attached to a MachineInstr, we care about total
|
||||
/// size, the number of vector lanes (if any)
|
||||
/// and the kind of the type (anyscalar, integer, float and etc).
|
||||
/// Floating point are filled with APFloat::Semantics to make them
|
||||
/// distinguishable.
|
||||
/// For a type attached to a MachineInstr, we only care about 2 details: total
|
||||
/// size and the number of vector lanes (if any). Accordingly, there are 4
|
||||
/// possible valid type-kinds:
|
||||
///
|
||||
/// Earlier other information required for correct selection was expected to be
|
||||
/// carried only by the opcode, or non-type flags. For example the distinction
|
||||
/// between G_ADD and G_FADD for int/float or fast-math flags.
|
||||
/// * `sN` for scalars and aggregates
|
||||
/// * `<N x sM>` for vectors, which must have at least 2 elements.
|
||||
/// * `pN` for pointers
|
||||
///
|
||||
/// Now we also able to rely on the kind of the type.
|
||||
/// This may be useful to distinguish different types of the same size used at
|
||||
/// the same opcode, for example, G_FADD with half vs G_FADD with bfloat16.
|
||||
/// Other information required for correct selection is expected to be carried
|
||||
/// by the opcode, or non-type flags. For example the distinction between G_ADD
|
||||
/// and G_FADD for int/float or fast-math flags.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CODEGEN_LOWLEVELTYPE_H
|
||||
#define LLVM_CODEGEN_LOWLEVELTYPE_H
|
||||
|
||||
#include "llvm/ADT/APFloat.h"
|
||||
#include "llvm/ADT/DenseMapInfo.h"
|
||||
#include "llvm/ADT/bit.h"
|
||||
#include "llvm/CodeGenTypes/MachineValueType.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include <cassert>
|
||||
|
||||
namespace llvm {
|
||||
@ -44,166 +39,68 @@ class raw_ostream;
|
||||
|
||||
class LLT {
|
||||
public:
|
||||
using FpSemantics = APFloat::Semantics;
|
||||
|
||||
enum class Kind : uint8_t {
|
||||
INVALID,
|
||||
ANY_SCALAR,
|
||||
INTEGER,
|
||||
FLOAT,
|
||||
POINTER,
|
||||
VECTOR_ANY,
|
||||
VECTOR_INTEGER,
|
||||
VECTOR_FLOAT,
|
||||
VECTOR_POINTER,
|
||||
};
|
||||
|
||||
constexpr static Kind toVector(Kind Ty) {
|
||||
if (Ty == Kind::POINTER)
|
||||
return Kind::VECTOR_POINTER;
|
||||
|
||||
if (Ty == Kind::INTEGER)
|
||||
return Kind::VECTOR_INTEGER;
|
||||
|
||||
if (Ty == Kind::FLOAT)
|
||||
return Kind::VECTOR_FLOAT;
|
||||
|
||||
return Kind::VECTOR_ANY;
|
||||
}
|
||||
|
||||
constexpr static Kind toScalar(Kind Ty) {
|
||||
if (Ty == Kind::VECTOR_POINTER)
|
||||
return Kind::POINTER;
|
||||
|
||||
if (Ty == Kind::VECTOR_INTEGER)
|
||||
return Kind::INTEGER;
|
||||
|
||||
if (Ty == Kind::VECTOR_FLOAT)
|
||||
return Kind::FLOAT;
|
||||
|
||||
return Kind::ANY_SCALAR;
|
||||
}
|
||||
|
||||
/// Get a low-level scalar or aggregate "bag of bits".
|
||||
static constexpr LLT scalar(unsigned SizeInBits) {
|
||||
return LLT{Kind::ANY_SCALAR, ElementCount::getFixed(0), SizeInBits};
|
||||
}
|
||||
|
||||
static LLT integer(unsigned SizeInBits) {
|
||||
if (!getUseExtended())
|
||||
return LLT::scalar(SizeInBits);
|
||||
|
||||
return LLT{Kind::INTEGER, ElementCount::getFixed(0), SizeInBits};
|
||||
}
|
||||
|
||||
static LLT floatingPoint(const FpSemantics &Sem) {
|
||||
if (!getUseExtended())
|
||||
return LLT::scalar(
|
||||
APFloat::getSizeInBits(APFloatBase::EnumToSemantics(Sem)));
|
||||
|
||||
return LLT{Kind::FLOAT, ElementCount::getFixed(0),
|
||||
APFloat::getSizeInBits(APFloatBase::EnumToSemantics(Sem)), Sem};
|
||||
return LLT{/*isPointer=*/false, /*isVector=*/false, /*isScalar=*/true,
|
||||
ElementCount::getFixed(0), SizeInBits,
|
||||
/*AddressSpace=*/0};
|
||||
}
|
||||
|
||||
/// Get a low-level token; just a scalar with zero bits (or no size).
|
||||
static constexpr LLT token() {
|
||||
return LLT{Kind::ANY_SCALAR, ElementCount::getFixed(0),
|
||||
/*SizeInBits=*/0};
|
||||
return LLT{/*isPointer=*/false, /*isVector=*/false,
|
||||
/*isScalar=*/true, ElementCount::getFixed(0),
|
||||
/*SizeInBits=*/0,
|
||||
/*AddressSpace=*/0};
|
||||
}
|
||||
|
||||
/// Get a low-level pointer in the given address space.
|
||||
static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits) {
|
||||
assert(SizeInBits > 0 && "invalid pointer size");
|
||||
return LLT{Kind::POINTER, ElementCount::getFixed(0), SizeInBits,
|
||||
AddressSpace};
|
||||
return LLT{/*isPointer=*/true, /*isVector=*/false, /*isScalar=*/false,
|
||||
ElementCount::getFixed(0), SizeInBits, AddressSpace};
|
||||
}
|
||||
|
||||
/// Get a low-level vector of some number of elements and element width.
|
||||
static constexpr LLT vector(ElementCount EC, unsigned ScalarSizeInBits) {
|
||||
assert(!EC.isScalar() && "invalid number of vector elements");
|
||||
return LLT{Kind::VECTOR_ANY, EC, ScalarSizeInBits};
|
||||
return LLT{/*isPointer=*/false, /*isVector=*/true, /*isScalar=*/false,
|
||||
EC, ScalarSizeInBits, /*AddressSpace=*/0};
|
||||
}
|
||||
|
||||
/// Get a low-level vector of some number of elements and element type.
|
||||
static constexpr LLT vector(ElementCount EC, LLT ScalarTy) {
|
||||
assert(!EC.isScalar() && "invalid number of vector elements");
|
||||
assert(!ScalarTy.isVector() && "invalid vector element type");
|
||||
|
||||
Kind Info = toVector(ScalarTy.Info);
|
||||
if (ScalarTy.isPointer())
|
||||
return LLT{Info, EC, ScalarTy.getSizeInBits().getFixedValue(),
|
||||
ScalarTy.getAddressSpace()};
|
||||
if (ScalarTy.isFloat())
|
||||
return LLT{Info, EC, ScalarTy.getSizeInBits().getFixedValue(),
|
||||
ScalarTy.getFpSemantics()};
|
||||
|
||||
return LLT{Info, EC, ScalarTy.getSizeInBits().getFixedValue()};
|
||||
return LLT{ScalarTy.isPointer(),
|
||||
/*isVector=*/true,
|
||||
/*isScalar=*/false,
|
||||
EC,
|
||||
ScalarTy.getSizeInBits().getFixedValue(),
|
||||
ScalarTy.isPointer() ? ScalarTy.getAddressSpace() : 0};
|
||||
}
|
||||
|
||||
// FIXME: Remove this builder
|
||||
static LLT floatIEEE(unsigned SizeInBits) {
|
||||
if (!getUseExtended())
|
||||
return LLT::scalar(SizeInBits);
|
||||
|
||||
switch (SizeInBits) {
|
||||
default:
|
||||
llvm_unreachable("Wrong SizeInBits for IEEE Floating point!");
|
||||
case 16:
|
||||
return float16();
|
||||
case 32:
|
||||
return float32();
|
||||
case 64:
|
||||
return float64();
|
||||
case 128:
|
||||
return float128();
|
||||
}
|
||||
}
|
||||
|
||||
// Get a bfloat16 value.
|
||||
static constexpr LLT bfloat16() {
|
||||
return LLT{Kind::FLOAT, ElementCount::getFixed(0), 16,
|
||||
FpSemantics::S_BFloat};
|
||||
}
|
||||
/// Get a 16-bit IEEE half value.
|
||||
/// TODO: Add IEEE semantics to type - This currently returns a simple `scalar(16)`.
|
||||
static constexpr LLT float16() {
|
||||
return LLT{Kind::FLOAT, ElementCount::getFixed(0), 16,
|
||||
FpSemantics::S_IEEEhalf};
|
||||
return scalar(16);
|
||||
}
|
||||
|
||||
/// Get a 32-bit IEEE float value.
|
||||
static constexpr LLT float32() {
|
||||
return LLT{Kind::FLOAT, ElementCount::getFixed(0), 32,
|
||||
FpSemantics::S_IEEEsingle};
|
||||
return scalar(32);
|
||||
}
|
||||
|
||||
/// Get a 64-bit IEEE double value.
|
||||
static constexpr LLT float64() {
|
||||
return LLT{Kind::FLOAT, ElementCount::getFixed(0), 64,
|
||||
FpSemantics::S_IEEEdouble};
|
||||
}
|
||||
|
||||
/// Get a 80-bit X86 floating point value.
|
||||
static constexpr LLT x86fp80() {
|
||||
return LLT{Kind::FLOAT, ElementCount::getFixed(0), 80,
|
||||
FpSemantics::S_x87DoubleExtended};
|
||||
}
|
||||
|
||||
/// Get a 128-bit IEEE quad value.
|
||||
static constexpr LLT float128() {
|
||||
return LLT{Kind::FLOAT, ElementCount::getFixed(0), 128,
|
||||
FpSemantics::S_IEEEquad};
|
||||
}
|
||||
|
||||
/// Get a 128-bit PowerPC double double value.
|
||||
static constexpr LLT ppcf128() {
|
||||
return LLT{Kind::FLOAT, ElementCount::getFixed(0), 128,
|
||||
FpSemantics::S_PPCDoubleDouble};
|
||||
return scalar(64);
|
||||
}
|
||||
|
||||
/// Get a low-level fixed-width vector of some number of elements and element
|
||||
/// width.
|
||||
static constexpr LLT fixed_vector(unsigned NumElements,
|
||||
unsigned ScalarSizeInBits) {
|
||||
return vector(ElementCount::getFixed(NumElements),
|
||||
LLT::scalar(ScalarSizeInBits));
|
||||
return vector(ElementCount::getFixed(NumElements), ScalarSizeInBits);
|
||||
}
|
||||
|
||||
/// Get a low-level fixed-width vector of some number of elements and element
|
||||
@ -216,8 +113,7 @@ public:
|
||||
/// width.
|
||||
static constexpr LLT scalable_vector(unsigned MinNumElements,
|
||||
unsigned ScalarSizeInBits) {
|
||||
return vector(ElementCount::getScalable(MinNumElements),
|
||||
LLT::scalar(ScalarSizeInBits));
|
||||
return vector(ElementCount::getScalable(MinNumElements), ScalarSizeInBits);
|
||||
}
|
||||
|
||||
/// Get a low-level scalable vector of some number of elements and element
|
||||
@ -236,81 +132,27 @@ public:
|
||||
return scalarOrVector(EC, LLT::scalar(static_cast<unsigned>(ScalarSize)));
|
||||
}
|
||||
|
||||
explicit constexpr LLT(Kind Info, ElementCount EC, uint64_t SizeInBits)
|
||||
: LLT() {
|
||||
init(Info, EC, SizeInBits);
|
||||
}
|
||||
|
||||
explicit constexpr LLT(Kind Info, ElementCount EC, uint64_t SizeInBits,
|
||||
explicit constexpr LLT(bool isPointer, bool isVector, bool isScalar,
|
||||
ElementCount EC, uint64_t SizeInBits,
|
||||
unsigned AddressSpace)
|
||||
: LLT() {
|
||||
init(Info, EC, SizeInBits, AddressSpace);
|
||||
}
|
||||
|
||||
explicit constexpr LLT(Kind Info, ElementCount EC, uint64_t SizeInBits,
|
||||
FpSemantics Sem)
|
||||
: LLT() {
|
||||
init(Info, EC, SizeInBits, Sem);
|
||||
init(isPointer, isVector, isScalar, EC, SizeInBits, AddressSpace);
|
||||
}
|
||||
explicit constexpr LLT()
|
||||
: IsScalar(false), IsPointer(false), IsVector(false), RawData(0) {}
|
||||
|
||||
LLVM_ABI explicit LLT(MVT VT);
|
||||
explicit constexpr LLT() : RawData(0), Info(static_cast<Kind>(0)) {}
|
||||
|
||||
constexpr bool isToken() const {
|
||||
return Info == Kind::ANY_SCALAR && RawData == 0;
|
||||
}
|
||||
constexpr bool isValid() const { return isToken() || RawData != 0; }
|
||||
constexpr bool isAnyScalar() const { return Info == Kind::ANY_SCALAR; }
|
||||
constexpr bool isInteger() const { return Info == Kind::INTEGER; }
|
||||
constexpr bool isFloat() const { return Info == Kind::FLOAT; }
|
||||
constexpr bool isPointer() const { return Info == Kind::POINTER; }
|
||||
constexpr bool isAnyVector() const { return Info == Kind::VECTOR_ANY; }
|
||||
constexpr bool isIntegerVector() const {
|
||||
return Info == Kind::VECTOR_INTEGER;
|
||||
}
|
||||
constexpr bool isFloatVector() const { return Info == Kind::VECTOR_FLOAT; }
|
||||
constexpr bool isPointerVector() const {
|
||||
return Info == Kind::VECTOR_POINTER;
|
||||
constexpr bool isValid() const { return IsScalar || RawData != 0; }
|
||||
constexpr bool isScalar() const { return IsScalar; }
|
||||
constexpr bool isToken() const { return IsScalar && RawData == 0; };
|
||||
constexpr bool isVector() const { return isValid() && IsVector; }
|
||||
constexpr bool isPointer() const {
|
||||
return isValid() && IsPointer && !IsVector;
|
||||
}
|
||||
constexpr bool isPointerVector() const { return IsPointer && isVector(); }
|
||||
constexpr bool isPointerOrPointerVector() const {
|
||||
return isPointer() || isPointerVector();
|
||||
}
|
||||
|
||||
constexpr bool isScalar() const {
|
||||
return Info == Kind::ANY_SCALAR || Info == Kind::INTEGER ||
|
||||
Info == Kind::FLOAT;
|
||||
}
|
||||
constexpr bool isScalar(unsigned Size) const {
|
||||
return isScalar() && getScalarSizeInBits() == Size;
|
||||
}
|
||||
constexpr bool isVector() const {
|
||||
return Info == Kind::VECTOR_ANY || Info == Kind::VECTOR_INTEGER ||
|
||||
Info == Kind::VECTOR_FLOAT || Info == Kind::VECTOR_POINTER;
|
||||
}
|
||||
|
||||
constexpr bool isInteger(unsigned Size) const {
|
||||
return isInteger() && getScalarSizeInBits() == Size;
|
||||
}
|
||||
|
||||
constexpr bool isFloat(unsigned Size) const {
|
||||
return isFloat() && getScalarSizeInBits() == Size;
|
||||
}
|
||||
constexpr bool isFloat(FpSemantics Sem) const {
|
||||
return isFloat() && getFpSemantics() == Sem;
|
||||
}
|
||||
// FIXME: Remove or rework this predicate
|
||||
constexpr bool isFloatIEEE() const {
|
||||
return isFloat(APFloatBase::S_IEEEhalf) ||
|
||||
isFloat(APFloatBase::S_IEEEsingle) ||
|
||||
isFloat(APFloatBase::S_IEEEdouble) ||
|
||||
isFloat(APFloatBase::S_IEEEquad);
|
||||
}
|
||||
constexpr bool isBFloat16() const { return isFloat(FpSemantics::S_BFloat); }
|
||||
constexpr bool isX86FP80() const {
|
||||
return isFloat(FpSemantics::S_x87DoubleExtended);
|
||||
}
|
||||
constexpr bool isPPCF128() const {
|
||||
return isFloat(FpSemantics::S_PPCDoubleDouble);
|
||||
return IsPointer && isValid();
|
||||
}
|
||||
|
||||
/// Returns the number of elements in a vector LLT. Must only be called on
|
||||
@ -335,18 +177,12 @@ public:
|
||||
/// if the LLT is not a vector type.
|
||||
constexpr bool isFixedVector() const { return isVector() && !isScalable(); }
|
||||
|
||||
constexpr bool isFixedVector(unsigned NumElements,
|
||||
unsigned ScalarSize) const {
|
||||
return isFixedVector() && getNumElements() == NumElements &&
|
||||
getScalarSizeInBits() == ScalarSize;
|
||||
}
|
||||
|
||||
/// Returns true if the LLT is a scalable vector. Returns false otherwise,
|
||||
/// even if the LLT is not a vector type.
|
||||
constexpr bool isScalableVector() const { return isVector() && isScalable(); }
|
||||
|
||||
constexpr ElementCount getElementCount() const {
|
||||
assert(isVector() && "cannot get number of elements on scalar/aggregate");
|
||||
assert(IsVector && "cannot get number of elements on scalar/aggregate");
|
||||
return ElementCount::get(getFieldValue(VectorElementsFieldInfo),
|
||||
isScalable());
|
||||
}
|
||||
@ -371,14 +207,6 @@ public:
|
||||
return isVector() ? getElementType() : *this;
|
||||
}
|
||||
|
||||
constexpr FpSemantics getFpSemantics() const {
|
||||
assert((isFloat() || isFloatVector()) &&
|
||||
"cannot get FP info for non float type");
|
||||
return FpSemantics(getFieldValue(FpSemanticFieldInfo));
|
||||
}
|
||||
|
||||
constexpr Kind getKind() const { return Info; }
|
||||
|
||||
/// Returns a vector with the same number of elements but the new element
|
||||
/// type. Must only be called on vector types.
|
||||
constexpr LLT changeVectorElementType(LLT NewEltTy) const {
|
||||
@ -393,21 +221,12 @@ public:
|
||||
|
||||
/// If this type is a vector, return a vector with the same number of elements
|
||||
/// but the new element size. Otherwise, return the new element type. Invalid
|
||||
/// for pointer types. For these, use changeElementType.
|
||||
/// for pointer types. For pointer types, use changeElementType.
|
||||
constexpr LLT changeElementSize(unsigned NewEltSize) const {
|
||||
assert(!isPointerOrPointerVector() &&
|
||||
"invalid to directly change element size for pointers");
|
||||
if (isVector())
|
||||
return LLT::vector(getElementCount(),
|
||||
getElementType().changeElementSize(NewEltSize));
|
||||
|
||||
if (isInteger())
|
||||
return LLT::integer(NewEltSize);
|
||||
|
||||
if (isFloatIEEE())
|
||||
return LLT::floatIEEE(NewEltSize);
|
||||
|
||||
return LLT::scalar(NewEltSize);
|
||||
return isVector() ? LLT::vector(getElementCount(), NewEltSize)
|
||||
: LLT::scalar(NewEltSize);
|
||||
}
|
||||
|
||||
/// Return a vector with the same element type and the new element count. Must
|
||||
@ -424,17 +243,13 @@ public:
|
||||
return LLT::scalarOrVector(EC, getScalarType());
|
||||
}
|
||||
|
||||
constexpr LLT changeElementCount(unsigned NumElements) const {
|
||||
return changeElementCount(ElementCount::getFixed(NumElements));
|
||||
}
|
||||
|
||||
/// Return a type that is \p Factor times smaller. Reduces the number of
|
||||
/// elements if this is a vector, or the bitwidth for scalar/pointers. Does
|
||||
/// not attempt to handle cases that aren't evenly divisible.
|
||||
constexpr LLT divide(int Factor) const {
|
||||
assert(Factor != 1);
|
||||
assert((!isScalar() || getScalarSizeInBits() != 0) && !isFloat() &&
|
||||
"cannot divide scalar of size zero and floats");
|
||||
assert((!isScalar() || getScalarSizeInBits() != 0) &&
|
||||
"cannot divide scalar of size zero");
|
||||
if (isVector()) {
|
||||
assert(getElementCount().isKnownMultipleOf(Factor));
|
||||
return scalarOrVector(getElementCount().divideCoefficientBy(Factor),
|
||||
@ -442,9 +257,6 @@ public:
|
||||
}
|
||||
|
||||
assert(getScalarSizeInBits() % Factor == 0);
|
||||
if (isInteger())
|
||||
return integer(getScalarSizeInBits() / Factor);
|
||||
|
||||
return scalar(getScalarSizeInBits() / Factor);
|
||||
}
|
||||
|
||||
@ -479,26 +291,10 @@ public:
|
||||
/// Returns the vector's element type. Only valid for vector types.
|
||||
constexpr LLT getElementType() const {
|
||||
assert(isVector() && "cannot get element type of scalar/aggregate");
|
||||
if (isPointerVector())
|
||||
if (IsPointer)
|
||||
return pointer(getAddressSpace(), getScalarSizeInBits());
|
||||
|
||||
if (isFloatVector())
|
||||
return floatingPoint(getFpSemantics());
|
||||
|
||||
if (isIntegerVector())
|
||||
return integer(getScalarSizeInBits());
|
||||
|
||||
return scalar(getScalarSizeInBits());
|
||||
}
|
||||
|
||||
constexpr LLT changeToInteger() const {
|
||||
if (isPointer() || isPointerVector())
|
||||
return *this;
|
||||
|
||||
if (isVector())
|
||||
return vector(getElementCount(), LLT::integer(getScalarSizeInBits()));
|
||||
|
||||
return integer(getSizeInBits());
|
||||
else
|
||||
return scalar(getScalarSizeInBits());
|
||||
}
|
||||
|
||||
LLVM_ABI void print(raw_ostream &OS) const;
|
||||
@ -508,15 +304,8 @@ public:
|
||||
#endif
|
||||
|
||||
constexpr bool operator==(const LLT &RHS) const {
|
||||
if (isAnyScalar() || RHS.isAnyScalar())
|
||||
return isScalar() == RHS.isScalar() &&
|
||||
getScalarSizeInBits() == RHS.getScalarSizeInBits();
|
||||
|
||||
if (isVector() && RHS.isVector())
|
||||
return getElementType() == RHS.getElementType() &&
|
||||
getElementCount() == RHS.getElementCount();
|
||||
|
||||
return Info == RHS.Info && RawData == RHS.RawData;
|
||||
return IsPointer == RHS.IsPointer && IsVector == RHS.IsVector &&
|
||||
IsScalar == RHS.IsScalar && RHS.RawData == RawData;
|
||||
}
|
||||
|
||||
constexpr bool operator!=(const LLT &RHS) const { return !(*this == RHS); }
|
||||
@ -526,80 +315,67 @@ public:
|
||||
|
||||
private:
|
||||
/// LLT is packed into 64 bits as follows:
|
||||
/// RawData : 60
|
||||
/// Info : 4
|
||||
/// RawData remaining for Kind-specific data, packed in
|
||||
/// bitfields as described below. As there isn't a simple portable way to pack
|
||||
/// bits into bitfields, here the different fields in the packed structure is
|
||||
/// isScalar : 1
|
||||
/// isPointer : 1
|
||||
/// isVector : 1
|
||||
/// with 61 bits remaining for Kind-specific data, packed in bitfields
|
||||
/// as described below. As there isn't a simple portable way to pack bits
|
||||
/// into bitfields, here the different fields in the packed structure is
|
||||
/// described in static const *Field variables. Each of these variables
|
||||
/// is a 2-element array, with the first element describing the bitfield size
|
||||
/// and the second element describing the bitfield offset.
|
||||
///
|
||||
/*
|
||||
--- LLT ---
|
||||
|
||||
63 56 47 39 31 23 15 7 0
|
||||
| | | | | | | | |
|
||||
|xxxxxxxx|xxxxxxxx|xxxxxxxx|xxxxxxxx|xxxxxxxx|xxxxxxxx|xxxxxxxx|xxxxxxxx|
|
||||
%%%% (1)
|
||||
.... ........ ........ ........ .... (2)
|
||||
**** ******** **** (3)
|
||||
~~~~ ~~~~~~~~ ~~~~~~~~ ~~~~ (4)
|
||||
#### #### (5)
|
||||
^^^^ ^^^^^^^^ ^^^^ (6)
|
||||
@ (7)
|
||||
|
||||
(1) Kind: [63:60]
|
||||
(2) ScalarSize: [59:28]
|
||||
(3) PointerSize: [59:44]
|
||||
(4) PointerAddressSpace: [43:20]
|
||||
(5) FpSemantics: [27:20]
|
||||
(6) VectorElements: [19:4]
|
||||
(7) VectorScalable: [0:0]
|
||||
|
||||
*/
|
||||
|
||||
/// This is how the LLT are packed per Kind:
|
||||
/// * Invalid:
|
||||
/// Info: [63:60] = 0
|
||||
/// RawData: [59:0] = 0;
|
||||
/// +--------+---------+--------+----------+----------------------+
|
||||
/// |isScalar|isPointer|isVector| RawData |Notes |
|
||||
/// +--------+---------+--------+----------+----------------------+
|
||||
/// | 0 | 0 | 0 | 0 |Invalid |
|
||||
/// +--------+---------+--------+----------+----------------------+
|
||||
/// | 0 | 0 | 1 | 0 |Tombstone Key |
|
||||
/// +--------+---------+--------+----------+----------------------+
|
||||
/// | 0 | 1 | 0 | 0 |Empty Key |
|
||||
/// +--------+---------+--------+----------+----------------------+
|
||||
/// | 1 | 0 | 0 | 0 |Token |
|
||||
/// +--------+---------+--------+----------+----------------------+
|
||||
/// | 1 | 0 | 0 | non-zero |Scalar |
|
||||
/// +--------+---------+--------+----------+----------------------+
|
||||
/// | 0 | 1 | 0 | non-zero |Pointer |
|
||||
/// +--------+---------+--------+----------+----------------------+
|
||||
/// | 0 | 0 | 1 | non-zero |Vector of non-pointer |
|
||||
/// +--------+---------+--------+----------+----------------------+
|
||||
/// | 0 | 1 | 1 | non-zero |Vector of pointer |
|
||||
/// +--------+---------+--------+----------+----------------------+
|
||||
///
|
||||
/// * Non-pointer scalar (isPointer == 0 && isVector == 0):
|
||||
/// Info: [63:60];
|
||||
/// SizeOfElement: [59:28];
|
||||
/// FpSemantics: [27:20];
|
||||
///
|
||||
/// * Pointer (isPointer == 1 && isVector == 0):
|
||||
/// Info: [63:60];
|
||||
/// SizeInBits: [59:44];
|
||||
/// AddressSpace: [43:20];
|
||||
///
|
||||
/// * Vector-of-non-pointer (isPointer == 0 && isVector == 1):
|
||||
/// Info: [63:60]
|
||||
/// SizeOfElement: [59:28];
|
||||
/// FpSemantics: [27:20];
|
||||
/// VectorElements: [19:4];
|
||||
/// Scalable: [0:0];
|
||||
///
|
||||
/// * Vector-of-pointer (isPointer == 1 && isVector == 1):
|
||||
/// Info: [63:60];
|
||||
/// SizeInBits: [59:44];
|
||||
/// AddressSpace: [43:20];
|
||||
/// VectorElements: [19:4];
|
||||
/// Scalable: [0:0];
|
||||
|
||||
/// BitFieldInfo: {Size, Offset}
|
||||
/// Everything else is reserved.
|
||||
typedef int BitFieldInfo[2];
|
||||
static_assert(bit_width_constexpr((uint32_t)APFloat::S_MaxSemantics) <= 8);
|
||||
///
|
||||
/// This is how the bitfields are packed per Kind:
|
||||
/// * Invalid:
|
||||
/// gets encoded as RawData == 0, as that is an invalid encoding, since for
|
||||
/// valid encodings, SizeInBits/SizeOfElement must be larger than 0.
|
||||
/// * Non-pointer scalar (isPointer == 0 && isVector == 0):
|
||||
/// SizeInBits: 32;
|
||||
static constexpr BitFieldInfo ScalarSizeFieldInfo{32, 29};
|
||||
/// * Pointer (isPointer == 1 && isVector == 0):
|
||||
/// SizeInBits: 16;
|
||||
/// AddressSpace: 24;
|
||||
static constexpr BitFieldInfo PointerSizeFieldInfo{16, 45};
|
||||
static constexpr BitFieldInfo PointerAddressSpaceFieldInfo{24, 21};
|
||||
/// * Vector-of-non-pointer (isPointer == 0 && isVector == 1):
|
||||
/// NumElements: 16;
|
||||
/// SizeOfElement: 32;
|
||||
/// Scalable: 1;
|
||||
static constexpr BitFieldInfo VectorElementsFieldInfo{16, 5};
|
||||
static constexpr BitFieldInfo VectorScalableFieldInfo{1, 0};
|
||||
static constexpr BitFieldInfo VectorElementsFieldInfo{16, 4};
|
||||
static constexpr BitFieldInfo FpSemanticFieldInfo{8, 20};
|
||||
static constexpr BitFieldInfo PointerAddressSpaceFieldInfo{24, 20};
|
||||
static constexpr BitFieldInfo ScalarSizeFieldInfo{32, 28};
|
||||
static constexpr BitFieldInfo PointerSizeFieldInfo{16, 44};
|
||||
/// * Vector-of-pointer (isPointer == 1 && isVector == 1):
|
||||
/// NumElements: 16;
|
||||
/// SizeOfElement: 16;
|
||||
/// AddressSpace: 24;
|
||||
/// Scalable: 1;
|
||||
|
||||
uint64_t RawData : 60;
|
||||
Kind Info : 4;
|
||||
uint64_t IsScalar : 1;
|
||||
uint64_t IsPointer : 1;
|
||||
uint64_t IsVector : 1;
|
||||
uint64_t RawData : 61;
|
||||
|
||||
static constexpr uint64_t getMask(const BitFieldInfo FieldInfo) {
|
||||
const int FieldSizeInBits = FieldInfo[0];
|
||||
@ -619,51 +395,21 @@ private:
|
||||
return getMask(FieldInfo) & (RawData >> FieldInfo[1]);
|
||||
}
|
||||
|
||||
// Init for scalar and integer single or vector types
|
||||
constexpr void init(Kind Info, ElementCount EC, uint64_t SizeInBits) {
|
||||
assert(SizeInBits <= std::numeric_limits<unsigned>::max() &&
|
||||
"Not enough bits in LLT to represent size");
|
||||
assert((Info == Kind::ANY_SCALAR || Info == Kind::INTEGER ||
|
||||
Info == Kind::VECTOR_ANY || Info == Kind::VECTOR_INTEGER) &&
|
||||
"Called initializer for wrong LLT Kind");
|
||||
this->Info = Info;
|
||||
RawData = maskAndShift(SizeInBits, ScalarSizeFieldInfo);
|
||||
|
||||
if (Info == Kind::VECTOR_ANY || Info == Kind::VECTOR_INTEGER) {
|
||||
RawData = maskAndShift(SizeInBits, ScalarSizeFieldInfo) |
|
||||
maskAndShift(EC.getKnownMinValue(), VectorElementsFieldInfo) |
|
||||
maskAndShift(EC.isScalable() ? 1 : 0, VectorScalableFieldInfo);
|
||||
}
|
||||
}
|
||||
|
||||
// Init pointer or pointer vector
|
||||
constexpr void init(Kind Info, ElementCount EC, uint64_t SizeInBits,
|
||||
constexpr void init(bool IsPointer, bool IsVector, bool IsScalar,
|
||||
ElementCount EC, uint64_t SizeInBits,
|
||||
unsigned AddressSpace) {
|
||||
assert(SizeInBits <= std::numeric_limits<unsigned>::max() &&
|
||||
"Not enough bits in LLT to represent size");
|
||||
assert((Info == Kind::POINTER || Info == Kind::VECTOR_POINTER) &&
|
||||
"Called initializer for wrong LLT Kind");
|
||||
this->Info = Info;
|
||||
RawData = maskAndShift(SizeInBits, PointerSizeFieldInfo) |
|
||||
maskAndShift(AddressSpace, PointerAddressSpaceFieldInfo);
|
||||
|
||||
if (Info == Kind::VECTOR_POINTER) {
|
||||
RawData |= maskAndShift(EC.getKnownMinValue(), VectorElementsFieldInfo) |
|
||||
maskAndShift(EC.isScalable() ? 1 : 0, VectorScalableFieldInfo);
|
||||
this->IsPointer = IsPointer;
|
||||
this->IsVector = IsVector;
|
||||
this->IsScalar = IsScalar;
|
||||
if (IsPointer) {
|
||||
RawData = maskAndShift(SizeInBits, PointerSizeFieldInfo) |
|
||||
maskAndShift(AddressSpace, PointerAddressSpaceFieldInfo);
|
||||
} else {
|
||||
RawData = maskAndShift(SizeInBits, ScalarSizeFieldInfo);
|
||||
}
|
||||
}
|
||||
|
||||
constexpr void init(Kind Info, ElementCount EC, uint64_t SizeInBits,
|
||||
FpSemantics Sem) {
|
||||
assert(SizeInBits <= std::numeric_limits<unsigned>::max() &&
|
||||
"Not enough bits in LLT to represent size");
|
||||
assert((Info == Kind::FLOAT || Info == Kind::VECTOR_FLOAT) &&
|
||||
"Called initializer for wrong LLT Kind");
|
||||
this->Info = Info;
|
||||
RawData = maskAndShift(SizeInBits, ScalarSizeFieldInfo) |
|
||||
maskAndShift((uint64_t)Sem, FpSemanticFieldInfo);
|
||||
|
||||
if (Info == Kind::VECTOR_FLOAT) {
|
||||
if (IsVector) {
|
||||
RawData |= maskAndShift(EC.getKnownMinValue(), VectorElementsFieldInfo) |
|
||||
maskAndShift(EC.isScalable() ? 1 : 0, VectorScalableFieldInfo);
|
||||
}
|
||||
@ -671,39 +417,36 @@ private:
|
||||
|
||||
public:
|
||||
constexpr uint64_t getUniqueRAWLLTData() const {
|
||||
return ((uint64_t)RawData) | ((uint64_t)Info) << 60;
|
||||
return ((uint64_t)RawData) << 3 | ((uint64_t)IsScalar) << 2 |
|
||||
((uint64_t)IsPointer) << 1 | ((uint64_t)IsVector);
|
||||
}
|
||||
|
||||
static bool getUseExtended() { return ExtendedLLT; }
|
||||
static void setUseExtended(bool Enable) { ExtendedLLT = Enable; }
|
||||
|
||||
private:
|
||||
static bool ExtendedLLT;
|
||||
};
|
||||
|
||||
inline raw_ostream &operator<<(raw_ostream &OS, const LLT &Ty) {
|
||||
inline raw_ostream& operator<<(raw_ostream &OS, const LLT &Ty) {
|
||||
Ty.print(OS);
|
||||
return OS;
|
||||
}
|
||||
|
||||
template <> struct DenseMapInfo<LLT> {
|
||||
template<> struct DenseMapInfo<LLT> {
|
||||
static inline LLT getEmptyKey() {
|
||||
LLT Invalid;
|
||||
Invalid.Info = LLT::Kind::POINTER;
|
||||
Invalid.IsPointer = true;
|
||||
return Invalid;
|
||||
}
|
||||
static inline LLT getTombstoneKey() {
|
||||
LLT Invalid;
|
||||
Invalid.Info = LLT::Kind::VECTOR_ANY;
|
||||
Invalid.IsVector = true;
|
||||
return Invalid;
|
||||
}
|
||||
static inline unsigned getHashValue(const LLT &Ty) {
|
||||
uint64_t Val = Ty.getUniqueRAWLLTData();
|
||||
return DenseMapInfo<uint64_t>::getHashValue(Val);
|
||||
}
|
||||
static bool isEqual(const LLT &LHS, const LLT &RHS) { return LHS == RHS; }
|
||||
static bool isEqual(const LLT &LHS, const LLT &RHS) {
|
||||
return LHS == RHS;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace llvm
|
||||
}
|
||||
|
||||
#endif // LLVM_CODEGEN_LOWLEVELTYPE_H
|
||||
|
||||
@ -335,24 +335,13 @@ mergeVectorRegsToResultRegs(MachineIRBuilder &B, ArrayRef<Register> DstRegs,
|
||||
if (LCMTy == LLTy) {
|
||||
// Common case where no padding is needed.
|
||||
assert(DstRegs.size() == 1);
|
||||
|
||||
SmallVector<Register, 8> ConcatRegs(SrcRegs.size());
|
||||
llvm::copy(SrcRegs, ConcatRegs.begin());
|
||||
|
||||
if (LLTy.getScalarType() != PartLLT.getScalarType())
|
||||
for (size_t I = 0, E = SrcRegs.size(); I != E; ++I) {
|
||||
auto BitcastDst =
|
||||
MRI.getType(SrcRegs[I]).changeElementType(LLTy.getScalarType());
|
||||
ConcatRegs[I] = B.buildBitcast(BitcastDst, SrcRegs[I]).getReg(0);
|
||||
}
|
||||
|
||||
return B.buildConcatVectors(DstRegs[0], ConcatRegs);
|
||||
return B.buildConcatVectors(DstRegs[0], SrcRegs);
|
||||
}
|
||||
|
||||
// We need to create an unmerge to the result registers, which may require
|
||||
// widening the original value.
|
||||
Register UnmergeSrcReg;
|
||||
if (LCMTy.getSizeInBits() != PartLLT.getSizeInBits()) {
|
||||
if (LCMTy != PartLLT) {
|
||||
assert(DstRegs.size() == 1);
|
||||
return B.buildDeleteTrailingVectorElements(
|
||||
DstRegs[0], B.buildMergeLikeInstr(LCMTy, SrcRegs));
|
||||
@ -363,18 +352,15 @@ mergeVectorRegsToResultRegs(MachineIRBuilder &B, ArrayRef<Register> DstRegs,
|
||||
UnmergeSrcReg = SrcRegs[0];
|
||||
}
|
||||
|
||||
size_t NumDst = LCMTy.getSizeInBits() / LLTy.getSizeInBits();
|
||||
int NumDst = LCMTy.getSizeInBits() / LLTy.getSizeInBits();
|
||||
|
||||
SmallVector<Register, 8> PadDstRegs(NumDst);
|
||||
llvm::copy(DstRegs, PadDstRegs.begin());
|
||||
|
||||
// Create the excess dead defs for the unmerge.
|
||||
for (size_t I = DstRegs.size(); I != NumDst; ++I)
|
||||
for (int I = DstRegs.size(); I != NumDst; ++I)
|
||||
PadDstRegs[I] = MRI.createGenericVirtualRegister(LLTy);
|
||||
|
||||
if (PartLLT != LCMTy)
|
||||
UnmergeSrcReg = B.buildBitcast(LCMTy, UnmergeSrcReg).getReg(0);
|
||||
|
||||
if (PadDstRegs.size() == 1)
|
||||
return B.buildDeleteTrailingVectorElements(DstRegs[0], UnmergeSrcReg);
|
||||
return B.buildUnmerge(PadDstRegs, UnmergeSrcReg);
|
||||
@ -462,7 +448,7 @@ void CallLowering::buildCopyFromRegs(MachineIRBuilder &B,
|
||||
PartLLT = NewTy;
|
||||
}
|
||||
|
||||
if (LLTy.getScalarSizeInBits() == PartLLT.getScalarSizeInBits()) {
|
||||
if (LLTy.getScalarType() == PartLLT.getElementType()) {
|
||||
mergeVectorRegsToResultRegs(B, OrigRegs, CastRegs);
|
||||
} else {
|
||||
unsigned I = 0;
|
||||
@ -808,8 +794,8 @@ bool CallLowering::handleAssignments(ValueHandler &Handler,
|
||||
const MVT ValVT = VA.getValVT();
|
||||
const MVT LocVT = VA.getLocVT();
|
||||
|
||||
const LLT LocTy = getLLTForMVT(LocVT);
|
||||
const LLT ValTy = getLLTForMVT(ValVT);
|
||||
const LLT LocTy(LocVT);
|
||||
const LLT ValTy(ValVT);
|
||||
const LLT NewLLT = Handler.isIncomingArgumentHandler() ? LocTy : ValTy;
|
||||
const EVT OrigVT = TLI->getValueType(DL, Args[i].Ty);
|
||||
// Use the EVT here to strip pointerness.
|
||||
@ -1313,7 +1299,7 @@ void CallLowering::ValueHandler::copyArgumentMemory(
|
||||
MemSize, DstAlign);
|
||||
|
||||
const LLT PtrTy = MRI.getType(DstPtr);
|
||||
const LLT SizeTy = LLT::integer(PtrTy.getSizeInBits());
|
||||
const LLT SizeTy = LLT::scalar(PtrTy.getSizeInBits());
|
||||
|
||||
auto SizeConst = MIRBuilder.buildConstant(SizeTy, MemSize);
|
||||
MIRBuilder.buildMemCpy(DstPtr, SrcPtr, SizeConst, *DstMMO, *SrcMMO);
|
||||
@ -1415,7 +1401,7 @@ void CallLowering::IncomingValueHandler::assignValueToReg(
|
||||
Register ValVReg, Register PhysReg, const CCValAssign &VA,
|
||||
ISD::ArgFlagsTy Flags) {
|
||||
const MVT LocVT = VA.getLocVT();
|
||||
const LLT LocTy = getLLTForMVT(LocVT);
|
||||
const LLT LocTy(LocVT);
|
||||
const LLT RegTy = MRI.getType(ValVReg);
|
||||
|
||||
if (isCopyCompatibleType(RegTy, LocTy)) {
|
||||
|
||||
@ -2358,22 +2358,9 @@ void CombinerHelper::applyCombineUnmergeConstant(
|
||||
assert((MI.getNumOperands() - 1 == Csts.size()) &&
|
||||
"Not enough operands to replace all defs");
|
||||
unsigned NumElems = MI.getNumOperands() - 1;
|
||||
|
||||
Register SrcReg = MI.getOperand(NumElems).getReg();
|
||||
|
||||
if (MRI.getType(SrcReg).isFloat()) {
|
||||
APFloat Val(getFltSemanticForLLT(MRI.getType(MI.getOperand(0).getReg())));
|
||||
|
||||
for (unsigned Idx = 0; Idx < NumElems; ++Idx) {
|
||||
Register DstReg = MI.getOperand(Idx).getReg();
|
||||
Val.convertFromAPInt(Csts[Idx], false, detail::rmTowardZero);
|
||||
Builder.buildFConstant(DstReg, Val);
|
||||
}
|
||||
} else {
|
||||
for (unsigned Idx = 0; Idx < NumElems; ++Idx) {
|
||||
Register DstReg = MI.getOperand(Idx).getReg();
|
||||
Builder.buildConstant(DstReg, Csts[Idx]);
|
||||
}
|
||||
for (unsigned Idx = 0; Idx < NumElems; ++Idx) {
|
||||
Register DstReg = MI.getOperand(Idx).getReg();
|
||||
Builder.buildConstant(DstReg, Csts[Idx]);
|
||||
}
|
||||
|
||||
MI.eraseFromParent();
|
||||
|
||||
@ -306,9 +306,23 @@ void IRTranslator::addMachineCFGPred(CFGEdge Edge, MachineBasicBlock *NewPred) {
|
||||
MachinePreds[Edge].push_back(NewPred);
|
||||
}
|
||||
|
||||
static bool targetSupportsBF16Type(const MachineFunction *MF) {
|
||||
return MF->getTarget().getTargetTriple().isSPIRV();
|
||||
}
|
||||
|
||||
static bool containsBF16Type(const User &U) {
|
||||
// BF16 cannot currently be represented by LLT, to avoid miscompiles we
|
||||
// prevent any instructions using them. FIXME: This can be removed once LLT
|
||||
// supports bfloat.
|
||||
return U.getType()->getScalarType()->isBFloatTy() ||
|
||||
any_of(U.operands(), [](Value *V) {
|
||||
return V->getType()->getScalarType()->isBFloatTy();
|
||||
});
|
||||
}
|
||||
|
||||
bool IRTranslator::translateBinaryOp(unsigned Opcode, const User &U,
|
||||
MachineIRBuilder &MIRBuilder) {
|
||||
if (!mayTranslateUserTypes(U))
|
||||
if (containsBF16Type(U) && !targetSupportsBF16Type(MF))
|
||||
return false;
|
||||
|
||||
// Get or create a virtual register for each value.
|
||||
@ -330,7 +344,7 @@ bool IRTranslator::translateBinaryOp(unsigned Opcode, const User &U,
|
||||
|
||||
bool IRTranslator::translateUnaryOp(unsigned Opcode, const User &U,
|
||||
MachineIRBuilder &MIRBuilder) {
|
||||
if (!mayTranslateUserTypes(U))
|
||||
if (containsBF16Type(U) && !targetSupportsBF16Type(MF))
|
||||
return false;
|
||||
|
||||
Register Op0 = getOrCreateVReg(*U.getOperand(0));
|
||||
@ -350,7 +364,7 @@ bool IRTranslator::translateFNeg(const User &U, MachineIRBuilder &MIRBuilder) {
|
||||
|
||||
bool IRTranslator::translateCompare(const User &U,
|
||||
MachineIRBuilder &MIRBuilder) {
|
||||
if (!mayTranslateUserTypes(U))
|
||||
if (containsBF16Type(U) && !targetSupportsBF16Type(MF))
|
||||
return false;
|
||||
|
||||
auto *CI = cast<CmpInst>(&U);
|
||||
@ -904,7 +918,7 @@ bool IRTranslator::emitJumpTableHeader(SwitchCG::JumpTable &JT,
|
||||
auto Cst = getOrCreateVReg(
|
||||
*ConstantInt::get(SValue.getType(), JTH.Last - JTH.First));
|
||||
Cst = MIB.buildZExtOrTrunc(PtrScalarTy, Cst).getReg(0);
|
||||
auto Cmp = MIB.buildICmp(CmpInst::ICMP_UGT, LLT::integer(1), Sub, Cst);
|
||||
auto Cmp = MIB.buildICmp(CmpInst::ICMP_UGT, LLT::scalar(1), Sub, Cst);
|
||||
|
||||
auto BrCond = MIB.buildBrCond(Cmp.getReg(0), *JT.Default);
|
||||
|
||||
@ -935,7 +949,7 @@ void IRTranslator::emitSwitchCase(SwitchCG::CaseBlock &CB,
|
||||
return;
|
||||
}
|
||||
|
||||
const LLT i1Ty = LLT::integer(1);
|
||||
const LLT i1Ty = LLT::scalar(1);
|
||||
// Build the compare.
|
||||
if (!CB.CmpMHS) {
|
||||
const auto *CI = dyn_cast<ConstantInt>(CB.CmpRHS);
|
||||
@ -1147,7 +1161,7 @@ void IRTranslator::emitBitTestHeader(SwitchCG::BitTestBlock &B,
|
||||
if (!B.FallthroughUnreachable) {
|
||||
// Conditional branch to the default block.
|
||||
auto RangeCst = MIB.buildConstant(SwitchOpTy, B.Range);
|
||||
auto RangeCmp = MIB.buildICmp(CmpInst::Predicate::ICMP_UGT, LLT::integer(1),
|
||||
auto RangeCmp = MIB.buildICmp(CmpInst::Predicate::ICMP_UGT, LLT::scalar(1),
|
||||
RangeSub, RangeCst);
|
||||
MIB.buildBrCond(RangeCmp, *B.Default);
|
||||
}
|
||||
@ -1173,16 +1187,15 @@ void IRTranslator::emitBitTestCase(SwitchCG::BitTestBlock &BB,
|
||||
// would need to be to shift a 1 bit in that position.
|
||||
auto MaskTrailingZeros =
|
||||
MIB.buildConstant(SwitchTy, llvm::countr_zero(B.Mask));
|
||||
Cmp = MIB.buildICmp(ICmpInst::ICMP_EQ, LLT::integer(1), Reg,
|
||||
MaskTrailingZeros)
|
||||
.getReg(0);
|
||||
Cmp =
|
||||
MIB.buildICmp(ICmpInst::ICMP_EQ, LLT::scalar(1), Reg, MaskTrailingZeros)
|
||||
.getReg(0);
|
||||
} else if (PopCount == BB.Range) {
|
||||
// There is only one zero bit in the range, test for it directly.
|
||||
auto MaskTrailingOnes =
|
||||
MIB.buildConstant(SwitchTy, llvm::countr_one(B.Mask));
|
||||
Cmp =
|
||||
MIB.buildICmp(CmpInst::ICMP_NE, LLT::integer(1), Reg, MaskTrailingOnes)
|
||||
.getReg(0);
|
||||
Cmp = MIB.buildICmp(CmpInst::ICMP_NE, LLT::scalar(1), Reg, MaskTrailingOnes)
|
||||
.getReg(0);
|
||||
} else {
|
||||
// Make desired shift.
|
||||
auto CstOne = MIB.buildConstant(SwitchTy, 1);
|
||||
@ -1192,7 +1205,7 @@ void IRTranslator::emitBitTestCase(SwitchCG::BitTestBlock &BB,
|
||||
auto CstMask = MIB.buildConstant(SwitchTy, B.Mask);
|
||||
auto AndOp = MIB.buildAnd(SwitchTy, SwitchVal, CstMask);
|
||||
auto CstZero = MIB.buildConstant(SwitchTy, 0);
|
||||
Cmp = MIB.buildICmp(CmpInst::ICMP_NE, LLT::integer(1), AndOp, CstZero)
|
||||
Cmp = MIB.buildICmp(CmpInst::ICMP_NE, LLT::scalar(1), AndOp, CstZero)
|
||||
.getReg(0);
|
||||
}
|
||||
|
||||
@ -1577,7 +1590,7 @@ bool IRTranslator::translateBitCast(const User &U,
|
||||
|
||||
bool IRTranslator::translateCast(unsigned Opcode, const User &U,
|
||||
MachineIRBuilder &MIRBuilder) {
|
||||
if (!mayTranslateUserTypes(U))
|
||||
if (containsBF16Type(U) && !targetSupportsBF16Type(MF))
|
||||
return false;
|
||||
|
||||
uint32_t Flags = 0;
|
||||
@ -1739,7 +1752,7 @@ bool IRTranslator::translateMemFunc(const CallInst &CI,
|
||||
SrcRegs.push_back(SrcReg);
|
||||
}
|
||||
|
||||
LLT SizeTy = LLT::integer(MinPtrSize);
|
||||
LLT SizeTy = LLT::scalar(MinPtrSize);
|
||||
|
||||
// The size operand should be the minimum of the pointer sizes.
|
||||
Register &SizeOpReg = SrcRegs[SrcRegs.size() - 1];
|
||||
@ -2692,7 +2705,7 @@ bool IRTranslator::translateKnownIntrinsic(const CallInst &CI, Intrinsic::ID ID,
|
||||
|
||||
bool IRTranslator::translateInlineAsm(const CallBase &CB,
|
||||
MachineIRBuilder &MIRBuilder) {
|
||||
if (!mayTranslateUserTypes(CB))
|
||||
if (containsBF16Type(CB) && !targetSupportsBF16Type(MF))
|
||||
return false;
|
||||
|
||||
const InlineAsmLowering *ALI = MF->getSubtarget().getInlineAsmLowering();
|
||||
@ -2783,7 +2796,7 @@ bool IRTranslator::translateCallBase(const CallBase &CB,
|
||||
}
|
||||
|
||||
bool IRTranslator::translateCall(const User &U, MachineIRBuilder &MIRBuilder) {
|
||||
if (!mayTranslateUserTypes(U))
|
||||
if (containsBF16Type(U) && !targetSupportsBF16Type(MF))
|
||||
return false;
|
||||
|
||||
const CallInst &CI = cast<CallInst>(U);
|
||||
@ -3054,7 +3067,7 @@ bool IRTranslator::translateInvoke(const User &U,
|
||||
/// intrinsics such as amdgcn.kill.
|
||||
bool IRTranslator::translateCallBr(const User &U,
|
||||
MachineIRBuilder &MIRBuilder) {
|
||||
if (!mayTranslateUserTypes(U))
|
||||
if (containsBF16Type(U))
|
||||
return false; // see translateCall
|
||||
|
||||
const CallBrInst &I = cast<CallBrInst>(U);
|
||||
@ -3271,8 +3284,7 @@ bool IRTranslator::translateInsertElement(const User &U,
|
||||
if (!Idx)
|
||||
Idx = getOrCreateVReg(*U.getOperand(2));
|
||||
if (MRI->getType(Idx).getSizeInBits() != PreferredVecIdxWidth) {
|
||||
const LLT VecIdxTy =
|
||||
MRI->getType(Idx).changeElementSize(PreferredVecIdxWidth);
|
||||
const LLT VecIdxTy = LLT::scalar(PreferredVecIdxWidth);
|
||||
Idx = MIRBuilder.buildZExtOrTrunc(VecIdxTy, Idx).getReg(0);
|
||||
}
|
||||
MIRBuilder.buildInsertVectorElement(Res, Val, Elt, Idx);
|
||||
@ -3353,8 +3365,7 @@ bool IRTranslator::translateExtractElement(const User &U,
|
||||
if (!Idx)
|
||||
Idx = getOrCreateVReg(*U.getOperand(1));
|
||||
if (MRI->getType(Idx).getSizeInBits() != PreferredVecIdxWidth) {
|
||||
const LLT VecIdxTy =
|
||||
MRI->getType(Idx).changeElementSize(PreferredVecIdxWidth);
|
||||
const LLT VecIdxTy = LLT::scalar(PreferredVecIdxWidth);
|
||||
Idx = MIRBuilder.buildZExtOrTrunc(VecIdxTy, Idx).getReg(0);
|
||||
}
|
||||
MIRBuilder.buildExtractVectorElement(Res, Val, Idx);
|
||||
@ -3522,7 +3533,7 @@ bool IRTranslator::translateAtomicCmpXchg(const User &U,
|
||||
|
||||
bool IRTranslator::translateAtomicRMW(const User &U,
|
||||
MachineIRBuilder &MIRBuilder) {
|
||||
if (!mayTranslateUserTypes(U))
|
||||
if (containsBF16Type(U) && !targetSupportsBF16Type(MF))
|
||||
return false;
|
||||
|
||||
const AtomicRMWInst &I = cast<AtomicRMWInst>(U);
|
||||
@ -3869,22 +3880,6 @@ bool IRTranslator::translate(const Constant &C, Register Reg) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IRTranslator::mayTranslateUserTypes(const User &U) const {
|
||||
const TargetMachine &TM = TLI->getTargetMachine();
|
||||
if (LLT::getUseExtended())
|
||||
return true;
|
||||
|
||||
// BF16 cannot currently be represented by default LLT. To avoid miscompiles
|
||||
// we prevent any instructions using them by default in all targets that do
|
||||
// not explicitly enable it via LLT::setUseExtended(true).
|
||||
// SPIRV target is exception.
|
||||
return TM.getTargetTriple().isSPIRV() ||
|
||||
(!U.getType()->getScalarType()->isBFloatTy() &&
|
||||
!any_of(U.operands(), [](Value *V) {
|
||||
return V->getType()->getScalarType()->isBFloatTy();
|
||||
}));
|
||||
}
|
||||
|
||||
bool IRTranslator::finalizeBasicBlock(const BasicBlock &BB,
|
||||
MachineBasicBlock &MBB) {
|
||||
for (auto &BTB : SL->BitTestCases) {
|
||||
@ -4085,7 +4080,7 @@ bool IRTranslator::emitSPDescriptorParent(StackProtectorDescriptor &SPD,
|
||||
|
||||
// Perform the comparison.
|
||||
auto Cmp =
|
||||
CurBuilder->buildICmp(CmpInst::ICMP_NE, LLT::integer(1), Guard, GuardVal);
|
||||
CurBuilder->buildICmp(CmpInst::ICMP_NE, LLT::scalar(1), Guard, GuardVal);
|
||||
// If the guard/stackslot do not equal, branch to failure MBB.
|
||||
CurBuilder->buildBrCond(Cmp, *SPD.getFailureMBB());
|
||||
// Otherwise branch to success MBB.
|
||||
|
||||
@ -67,17 +67,8 @@ LegalizeMutation LegalizeMutations::changeElementSizeTo(unsigned TypeIdx,
|
||||
return [=](const LegalityQuery &Query) {
|
||||
const LLT OldTy = Query.Types[TypeIdx];
|
||||
const LLT NewTy = Query.Types[FromTypeIdx];
|
||||
return std::make_pair(TypeIdx,
|
||||
OldTy.changeElementSize(NewTy.getScalarSizeInBits()));
|
||||
};
|
||||
}
|
||||
|
||||
LegalizeMutation LegalizeMutations::changeElementSizeTo(unsigned TypeIdx,
|
||||
LLT NewTy) {
|
||||
return [=](const LegalityQuery &Query) {
|
||||
const LLT OldTy = Query.Types[TypeIdx];
|
||||
return std::make_pair(TypeIdx,
|
||||
OldTy.changeElementSize(NewTy.getScalarSizeInBits()));
|
||||
const LLT NewEltTy = LLT::scalar(NewTy.getScalarSizeInBits());
|
||||
return std::make_pair(TypeIdx, OldTy.changeElementType(NewEltTy));
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -1182,7 +1182,7 @@ LegalizerHelper::createFCMPLibcall(MachineInstr &MI,
|
||||
const CmpInst::Predicate ICmpPred,
|
||||
const DstOp &Res) -> Register {
|
||||
// FCMP libcall always returns an i32, and needs an ICMP with #0.
|
||||
LLT TempLLT = LLT::integer(32);
|
||||
constexpr LLT TempLLT = LLT::scalar(32);
|
||||
Register Temp = MRI.createGenericVirtualRegister(TempLLT);
|
||||
// Generate libcall, holding result in Temp
|
||||
const auto Status = createLibcall(
|
||||
@ -3296,8 +3296,10 @@ LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
|
||||
LLT VecTy = MRI.getType(VecReg);
|
||||
Observer.changingInstr(MI);
|
||||
|
||||
widenScalarSrc(MI, LLT::vector(VecTy.getElementCount(), WideTy), 1,
|
||||
TargetOpcode::G_ANYEXT);
|
||||
widenScalarSrc(
|
||||
MI,
|
||||
VecTy.changeVectorElementType(LLT::scalar(WideTy.getSizeInBits())), 1,
|
||||
TargetOpcode::G_ANYEXT);
|
||||
|
||||
widenScalarDst(MI, WideTy, 0);
|
||||
Observer.changedInstr(MI);
|
||||
@ -3951,7 +3953,7 @@ LegalizerHelper::bitcastConcatVector(MachineInstr &MI, unsigned TypeIdx,
|
||||
|
||||
// Check if bitcast is Legal
|
||||
auto [DstReg, DstTy, SrcReg, SrcTy] = MI.getFirst2RegLLTs();
|
||||
LLT SrcScalTy = CastTy.getScalarType();
|
||||
LLT SrcScalTy = LLT::scalar(SrcTy.getSizeInBits());
|
||||
|
||||
// Check if the build vector is Legal
|
||||
if (!LI.isLegal({TargetOpcode::G_BUILD_VECTOR, {CastTy, SrcScalTy}})) {
|
||||
@ -4149,8 +4151,6 @@ LegalizerHelper::LegalizeResult LegalizerHelper::lowerLoad(GAnyLoad &LoadMI) {
|
||||
LLT MemTy = MMO.getMemoryType();
|
||||
MachineFunction &MF = MIRBuilder.getMF();
|
||||
|
||||
LLT EltTy = MemTy.getScalarType();
|
||||
|
||||
unsigned MemSizeInBits = MemTy.getSizeInBits();
|
||||
unsigned MemStoreSizeInBits = 8 * MemTy.getSizeInBytes();
|
||||
|
||||
@ -4160,7 +4160,7 @@ LegalizerHelper::LegalizeResult LegalizerHelper::lowerLoad(GAnyLoad &LoadMI) {
|
||||
|
||||
// Promote to a byte-sized load if not loading an integral number of
|
||||
// bytes. For example, promote EXTLOAD:i20 -> EXTLOAD:i24.
|
||||
LLT WideMemTy = EltTy.changeElementSize(MemStoreSizeInBits);
|
||||
LLT WideMemTy = LLT::scalar(MemStoreSizeInBits);
|
||||
MachineMemOperand *NewMMO =
|
||||
MF.getMachineMemOperand(&MMO, MMO.getPointerInfo(), WideMemTy);
|
||||
|
||||
@ -4262,21 +4262,12 @@ LegalizerHelper::LegalizeResult LegalizerHelper::lowerLoad(GAnyLoad &LoadMI) {
|
||||
|
||||
LLT PtrTy = MRI.getType(PtrReg);
|
||||
unsigned AnyExtSize = PowerOf2Ceil(DstTy.getSizeInBits());
|
||||
|
||||
LLT AnyExtTy;
|
||||
LLT OffsetCstRes;
|
||||
if (EltTy.isPointer()) {
|
||||
AnyExtTy = LLT::scalar(AnyExtSize);
|
||||
OffsetCstRes = LLT::scalar(PtrTy.getSizeInBits());
|
||||
} else {
|
||||
AnyExtTy = EltTy.changeElementSize(AnyExtSize);
|
||||
OffsetCstRes = EltTy.changeElementSize(PtrTy.getSizeInBits());
|
||||
}
|
||||
|
||||
LLT AnyExtTy = LLT::scalar(AnyExtSize);
|
||||
auto LargeLoad = MIRBuilder.buildLoadInstr(TargetOpcode::G_ZEXTLOAD, AnyExtTy,
|
||||
PtrReg, *LargeMMO);
|
||||
|
||||
auto OffsetCst = MIRBuilder.buildConstant(OffsetCstRes, LargeSplitSize / 8);
|
||||
auto OffsetCst = MIRBuilder.buildConstant(LLT::scalar(PtrTy.getSizeInBits()),
|
||||
LargeSplitSize / 8);
|
||||
Register PtrAddReg = MRI.createGenericVirtualRegister(PtrTy);
|
||||
auto SmallPtr = MIRBuilder.buildObjectPtrOffset(PtrAddReg, PtrReg, OffsetCst);
|
||||
auto SmallLoad = MIRBuilder.buildLoadInstr(LoadMI.getOpcode(), AnyExtTy,
|
||||
@ -4413,7 +4404,7 @@ LegalizerHelper::scalarizeVectorBooleanStore(GStore &StoreMI) {
|
||||
// We need to build an integer scalar of the vector bit pattern.
|
||||
// It's not legal for us to add padding when storing a vector.
|
||||
unsigned NumBits = MemTy.getSizeInBits();
|
||||
LLT IntTy = LLT::integer(NumBits);
|
||||
LLT IntTy = LLT::scalar(NumBits);
|
||||
auto CurrVal = MIRBuilder.buildConstant(IntTy, 0);
|
||||
LLT IdxTy = TLI.getVectorIdxLLT(MF.getDataLayout());
|
||||
|
||||
@ -4597,28 +4588,12 @@ LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT LowerHintTy) {
|
||||
return Legalized;
|
||||
}
|
||||
case TargetOpcode::G_FNEG: {
|
||||
auto [Res, ResTy, SubByReg, SubByRegTy] = MI.getFirst2RegLLTs();
|
||||
LLT TyInt =
|
||||
ResTy.changeElementType(LLT::integer(ResTy.getScalarSizeInBits()));
|
||||
Register CastedSubByReg = SubByReg;
|
||||
|
||||
if (!SubByRegTy.getScalarType().isAnyScalar() &&
|
||||
!SubByRegTy.getScalarType().isInteger()) {
|
||||
auto BitcastDst = SubByRegTy.changeElementType(
|
||||
LLT::integer(SubByRegTy.getScalarSizeInBits()));
|
||||
CastedSubByReg = MIRBuilder.buildBitcast(BitcastDst, SubByReg).getReg(0);
|
||||
}
|
||||
auto [Res, SubByReg] = MI.getFirst2Regs();
|
||||
LLT Ty = MRI.getType(Res);
|
||||
|
||||
auto SignMask = MIRBuilder.buildConstant(
|
||||
TyInt, APInt::getSignMask(TyInt.getScalarSizeInBits()));
|
||||
|
||||
if (ResTy != TyInt) {
|
||||
Register NewDst =
|
||||
MIRBuilder.buildXor(TyInt, CastedSubByReg, SignMask).getReg(0);
|
||||
MIRBuilder.buildBitcast(Res, NewDst);
|
||||
} else
|
||||
MIRBuilder.buildXor(Res, CastedSubByReg, SignMask).getReg(0);
|
||||
|
||||
Ty, APInt::getSignMask(Ty.getScalarSizeInBits()));
|
||||
MIRBuilder.buildXor(Res, SubByReg, SignMask);
|
||||
MI.eraseFromParent();
|
||||
return Legalized;
|
||||
}
|
||||
@ -5488,7 +5463,7 @@ LegalizerHelper::reduceLoadStoreWidth(GLoadStore &LdStMI, unsigned TypeIdx,
|
||||
return UnableToLegalize;
|
||||
|
||||
LLT PtrTy = MRI.getType(AddrReg);
|
||||
const LLT OffsetTy = LLT::integer(PtrTy.getSizeInBits());
|
||||
const LLT OffsetTy = LLT::scalar(PtrTy.getSizeInBits());
|
||||
|
||||
unsigned TotalSize = ValTy.getSizeInBits();
|
||||
|
||||
@ -6182,7 +6157,7 @@ LegalizerHelper::narrowScalarShift(MachineInstr &MI, unsigned TypeIdx,
|
||||
// input. If that isn't small enough, the resulting pieces will be further
|
||||
// legalized.
|
||||
const unsigned NewBitSize = DstEltSize / 2;
|
||||
const LLT HalfTy = DstTy.getScalarType().changeElementSize(NewBitSize);
|
||||
const LLT HalfTy = LLT::scalar(NewBitSize);
|
||||
const LLT CondTy = LLT::scalar(1);
|
||||
|
||||
if (auto VRegAndVal = getIConstantVRegValWithLookThrough(Amt, MRI)) {
|
||||
@ -8331,13 +8306,11 @@ LegalizerHelper::lowerU64ToF64BitFloatOps(MachineInstr &MI) {
|
||||
static LegalizerHelper::LegalizeResult
|
||||
loweri64tof16ITOFP(MachineInstr &MI, Register Dst, LLT DstTy, Register Src,
|
||||
LLT SrcTy, MachineIRBuilder &MIRBuilder) {
|
||||
auto DstFpTy =
|
||||
SrcTy.changeElementType(LLT::floatIEEE(SrcTy.getScalarSizeInBits()));
|
||||
auto M1 = MI.getOpcode() == TargetOpcode::G_UITOFP
|
||||
? MIRBuilder.buildUITOFP(DstFpTy, Src)
|
||||
: MIRBuilder.buildSITOFP(DstFpTy, Src);
|
||||
LLT F32Ty = DstFpTy.changeElementSize(32);
|
||||
auto M2 = MIRBuilder.buildFPTrunc(F32Ty, M1);
|
||||
? MIRBuilder.buildUITOFP(SrcTy, Src)
|
||||
: MIRBuilder.buildSITOFP(SrcTy, Src);
|
||||
LLT S32Ty = SrcTy.changeElementSize(32);
|
||||
auto M2 = MIRBuilder.buildFPTrunc(S32Ty, M1);
|
||||
MIRBuilder.buildFPTrunc(Dst, M2);
|
||||
MI.eraseFromParent();
|
||||
return LegalizerHelper::Legalized;
|
||||
@ -8376,11 +8349,11 @@ LegalizerHelper::LegalizeResult LegalizerHelper::lowerUITOFP(MachineInstr &MI) {
|
||||
LegalizerHelper::LegalizeResult LegalizerHelper::lowerSITOFP(MachineInstr &MI) {
|
||||
auto [Dst, DstTy, Src, SrcTy] = MI.getFirst2RegLLTs();
|
||||
|
||||
const LLT I64 = LLT::integer(64);
|
||||
const LLT I32 = LLT::integer(32);
|
||||
const LLT I1 = LLT::integer(1);
|
||||
const LLT S64 = LLT::scalar(64);
|
||||
const LLT S32 = LLT::scalar(32);
|
||||
const LLT S1 = LLT::scalar(1);
|
||||
|
||||
if (SrcTy == I1) {
|
||||
if (SrcTy == S1) {
|
||||
auto True = MIRBuilder.buildFConstant(DstTy, -1.0);
|
||||
auto False = MIRBuilder.buildFConstant(DstTy, 0.0);
|
||||
MIRBuilder.buildSelect(Dst, Src, True, False);
|
||||
@ -8391,26 +8364,26 @@ LegalizerHelper::LegalizeResult LegalizerHelper::lowerSITOFP(MachineInstr &MI) {
|
||||
if (DstTy.getScalarSizeInBits() == 16 && SrcTy.getScalarSizeInBits() == 64)
|
||||
return loweri64tof16ITOFP(MI, Dst, DstTy, Src, SrcTy, MIRBuilder);
|
||||
|
||||
if (SrcTy != I64)
|
||||
if (SrcTy != S64)
|
||||
return UnableToLegalize;
|
||||
|
||||
if (DstTy.getScalarSizeInBits() == 32) {
|
||||
if (DstTy == S32) {
|
||||
// signed cl2f(long l) {
|
||||
// long s = l >> 63;
|
||||
// float r = cul2f((l + s) ^ s);
|
||||
// return s ? -r : r;
|
||||
// }
|
||||
Register L = Src;
|
||||
auto SignBit = MIRBuilder.buildConstant(I64, 63);
|
||||
auto S = MIRBuilder.buildAShr(I64, L, SignBit);
|
||||
auto SignBit = MIRBuilder.buildConstant(S64, 63);
|
||||
auto S = MIRBuilder.buildAShr(S64, L, SignBit);
|
||||
|
||||
auto LPlusS = MIRBuilder.buildAdd(I64, L, S);
|
||||
auto Xor = MIRBuilder.buildXor(I64, LPlusS, S);
|
||||
auto R = MIRBuilder.buildUITOFP(I32, Xor);
|
||||
auto LPlusS = MIRBuilder.buildAdd(S64, L, S);
|
||||
auto Xor = MIRBuilder.buildXor(S64, LPlusS, S);
|
||||
auto R = MIRBuilder.buildUITOFP(S32, Xor);
|
||||
|
||||
auto RNeg = MIRBuilder.buildFNeg(I32, R);
|
||||
auto SignNotZero = MIRBuilder.buildICmp(CmpInst::ICMP_NE, I1, S,
|
||||
MIRBuilder.buildConstant(I64, 0));
|
||||
auto RNeg = MIRBuilder.buildFNeg(S32, R);
|
||||
auto SignNotZero = MIRBuilder.buildICmp(CmpInst::ICMP_NE, S1, S,
|
||||
MIRBuilder.buildConstant(S64, 0));
|
||||
MIRBuilder.buildSelect(Dst, SignNotZero, RNeg, R);
|
||||
MI.eraseFromParent();
|
||||
return Legalized;
|
||||
@ -8558,13 +8531,14 @@ LegalizerHelper::lowerFPTOINT_SAT(MachineInstr &MI) {
|
||||
if (AreExactFloatBounds) {
|
||||
// Clamp Src by MinFloat from below. If Src is NaN the result is MinFloat.
|
||||
auto MaxC = MIRBuilder.buildFConstant(SrcTy, MinFloat);
|
||||
auto MaxP =
|
||||
MIRBuilder.buildFCmp(CmpInst::FCMP_OGT, LLT::integer(1), Src, MaxC);
|
||||
auto MaxP = MIRBuilder.buildFCmp(CmpInst::FCMP_OGT,
|
||||
SrcTy.changeElementSize(1), Src, MaxC);
|
||||
auto Max = MIRBuilder.buildSelect(SrcTy, MaxP, Src, MaxC);
|
||||
// Clamp by MaxFloat from above. NaN cannot occur.
|
||||
auto MinC = MIRBuilder.buildFConstant(SrcTy, MaxFloat);
|
||||
auto MinP = MIRBuilder.buildFCmp(CmpInst::FCMP_OLT, LLT::integer(1), Max,
|
||||
MinC, MachineInstr::FmNoNans);
|
||||
auto MinP =
|
||||
MIRBuilder.buildFCmp(CmpInst::FCMP_OLT, SrcTy.changeElementSize(1), Max,
|
||||
MinC, MachineInstr::FmNoNans);
|
||||
auto Min =
|
||||
MIRBuilder.buildSelect(SrcTy, MinP, Max, MinC, MachineInstr::FmNoNans);
|
||||
// Convert clamped value to integer. In the unsigned case we're done,
|
||||
@ -8577,8 +8551,8 @@ LegalizerHelper::lowerFPTOINT_SAT(MachineInstr &MI) {
|
||||
|
||||
// Otherwise, select 0 if Src is NaN.
|
||||
auto FpToInt = MIRBuilder.buildFPTOSI(DstTy, Min);
|
||||
auto IsZero =
|
||||
MIRBuilder.buildFCmp(CmpInst::FCMP_UNO, LLT::integer(1), Src, Src);
|
||||
auto IsZero = MIRBuilder.buildFCmp(CmpInst::FCMP_UNO,
|
||||
DstTy.changeElementSize(1), Src, Src);
|
||||
MIRBuilder.buildSelect(Dst, IsZero, MIRBuilder.buildConstant(DstTy, 0),
|
||||
FpToInt);
|
||||
MI.eraseFromParent();
|
||||
@ -8593,13 +8567,15 @@ LegalizerHelper::lowerFPTOINT_SAT(MachineInstr &MI) {
|
||||
|
||||
// If Src ULT MinFloat, select MinInt. In particular, this also selects
|
||||
// MinInt if Src is NaN.
|
||||
auto ULT = MIRBuilder.buildFCmp(CmpInst::FCMP_ULT, LLT::integer(1), Src,
|
||||
MIRBuilder.buildFConstant(SrcTy, MinFloat));
|
||||
auto ULT =
|
||||
MIRBuilder.buildFCmp(CmpInst::FCMP_ULT, SrcTy.changeElementSize(1), Src,
|
||||
MIRBuilder.buildFConstant(SrcTy, MinFloat));
|
||||
auto Max = MIRBuilder.buildSelect(
|
||||
DstTy, ULT, MIRBuilder.buildConstant(DstTy, MinInt), FpToInt);
|
||||
// If Src OGT MaxFloat, select MaxInt.
|
||||
auto OGT = MIRBuilder.buildFCmp(CmpInst::FCMP_OGT, LLT::integer(1), Src,
|
||||
MIRBuilder.buildFConstant(SrcTy, MaxFloat));
|
||||
auto OGT =
|
||||
MIRBuilder.buildFCmp(CmpInst::FCMP_OGT, SrcTy.changeElementSize(1), Src,
|
||||
MIRBuilder.buildFConstant(SrcTy, MaxFloat));
|
||||
|
||||
// In the unsigned case we are done, because we mapped NaN to MinInt, which
|
||||
// is already zero.
|
||||
@ -8613,8 +8589,8 @@ LegalizerHelper::lowerFPTOINT_SAT(MachineInstr &MI) {
|
||||
// Otherwise, select 0 if Src is NaN.
|
||||
auto Min = MIRBuilder.buildSelect(
|
||||
DstTy, OGT, MIRBuilder.buildConstant(DstTy, MaxInt), Max);
|
||||
auto IsZero =
|
||||
MIRBuilder.buildFCmp(CmpInst::FCMP_UNO, LLT::integer(1), Src, Src);
|
||||
auto IsZero = MIRBuilder.buildFCmp(CmpInst::FCMP_UNO,
|
||||
DstTy.changeElementSize(1), Src, Src);
|
||||
MIRBuilder.buildSelect(Dst, IsZero, MIRBuilder.buildConstant(DstTy, 0), Min);
|
||||
MI.eraseFromParent();
|
||||
return Legalized;
|
||||
@ -8806,7 +8782,7 @@ LegalizerHelper::LegalizeResult LegalizerHelper::lowerMinMax(MachineInstr &MI) {
|
||||
auto [Dst, Src0, Src1] = MI.getFirst3Regs();
|
||||
|
||||
const CmpInst::Predicate Pred = minMaxToCompare(MI.getOpcode());
|
||||
LLT CmpType = MRI.getType(Dst).changeElementType(LLT::integer(1));
|
||||
LLT CmpType = MRI.getType(Dst).changeElementType(LLT::scalar(1));
|
||||
|
||||
auto Cmp = MIRBuilder.buildICmp(Pred, CmpType, Src0, Src1);
|
||||
MIRBuilder.buildSelect(Dst, Cmp, Src0, Src1);
|
||||
@ -8869,43 +8845,26 @@ LegalizerHelper::lowerFCopySign(MachineInstr &MI) {
|
||||
const int Src0Size = Src0Ty.getScalarSizeInBits();
|
||||
const int Src1Size = Src1Ty.getScalarSizeInBits();
|
||||
|
||||
LLT DstIntTy =
|
||||
DstTy.changeElementType(LLT::integer(DstTy.getScalarSizeInBits()));
|
||||
LLT Src0IntTy = Src0Ty.changeElementType(LLT::integer(Src0Size));
|
||||
LLT Src1IntTy = Src1Ty.changeElementType(LLT::integer(Src1Size));
|
||||
|
||||
Register Src0Int = Src0;
|
||||
Register Src1Int = Src1;
|
||||
|
||||
if (!(Src0Ty.getScalarType().isAnyScalar() ||
|
||||
Src0Ty.getScalarType().isInteger()))
|
||||
Src0Int = MIRBuilder.buildBitcast(Src0IntTy, Src0).getReg(0);
|
||||
|
||||
if (!(Src1Ty.getScalarType().isAnyScalar() ||
|
||||
Src1Ty.getScalarType().isInteger()))
|
||||
Src1Int = MIRBuilder.buildBitcast(Src1IntTy, Src1).getReg(0);
|
||||
|
||||
auto SignBitMask =
|
||||
MIRBuilder.buildConstant(Src0IntTy, APInt::getSignMask(Src0Size));
|
||||
auto SignBitMask = MIRBuilder.buildConstant(
|
||||
Src0Ty, APInt::getSignMask(Src0Size));
|
||||
|
||||
auto NotSignBitMask = MIRBuilder.buildConstant(
|
||||
Src0IntTy, APInt::getLowBitsSet(Src0Size, Src0Size - 1));
|
||||
Src0Ty, APInt::getLowBitsSet(Src0Size, Src0Size - 1));
|
||||
|
||||
Register And0 =
|
||||
MIRBuilder.buildAnd(Src0IntTy, Src0Int, NotSignBitMask).getReg(0);
|
||||
Register And0 = MIRBuilder.buildAnd(Src0Ty, Src0, NotSignBitMask).getReg(0);
|
||||
Register And1;
|
||||
if (Src0Ty == Src1Ty) {
|
||||
And1 = MIRBuilder.buildAnd(Src1IntTy, Src1Int, SignBitMask).getReg(0);
|
||||
And1 = MIRBuilder.buildAnd(Src1Ty, Src1, SignBitMask).getReg(0);
|
||||
} else if (Src0Size > Src1Size) {
|
||||
auto ShiftAmt = MIRBuilder.buildConstant(Src0IntTy, Src0Size - Src1Size);
|
||||
auto Zext = MIRBuilder.buildZExt(Src0IntTy, Src1Int);
|
||||
auto Shift = MIRBuilder.buildShl(Src0IntTy, Zext, ShiftAmt);
|
||||
auto ShiftAmt = MIRBuilder.buildConstant(Src0Ty, Src0Size - Src1Size);
|
||||
auto Zext = MIRBuilder.buildZExt(Src0Ty, Src1);
|
||||
auto Shift = MIRBuilder.buildShl(Src0Ty, Zext, ShiftAmt);
|
||||
And1 = MIRBuilder.buildAnd(Src0Ty, Shift, SignBitMask).getReg(0);
|
||||
} else {
|
||||
auto ShiftAmt = MIRBuilder.buildConstant(Src1IntTy, Src1Size - Src0Size);
|
||||
auto Shift = MIRBuilder.buildLShr(Src1IntTy, Src1Int, ShiftAmt);
|
||||
auto Trunc = MIRBuilder.buildTrunc(Src0IntTy, Shift);
|
||||
And1 = MIRBuilder.buildAnd(Src0IntTy, Trunc, SignBitMask).getReg(0);
|
||||
auto ShiftAmt = MIRBuilder.buildConstant(Src1Ty, Src1Size - Src0Size);
|
||||
auto Shift = MIRBuilder.buildLShr(Src1Ty, Src1, ShiftAmt);
|
||||
auto Trunc = MIRBuilder.buildTrunc(Src0Ty, Shift);
|
||||
And1 = MIRBuilder.buildAnd(Src0Ty, Trunc, SignBitMask).getReg(0);
|
||||
}
|
||||
|
||||
// Be careful about setting nsz/nnan/ninf on every instruction, since the
|
||||
@ -8916,12 +8875,7 @@ LegalizerHelper::lowerFCopySign(MachineInstr &MI) {
|
||||
// We masked the sign bit and the not-sign bit, so these are disjoint.
|
||||
Flags |= MachineInstr::Disjoint;
|
||||
|
||||
if (DstTy == DstIntTy)
|
||||
MIRBuilder.buildOr(Dst, And0, And1, Flags).getReg(0);
|
||||
else {
|
||||
Register NewDst = MIRBuilder.buildOr(DstIntTy, And0, And1, Flags).getReg(0);
|
||||
MIRBuilder.buildBitcast(Dst, NewDst);
|
||||
}
|
||||
MIRBuilder.buildOr(Dst, And0, And1, Flags);
|
||||
|
||||
MI.eraseFromParent();
|
||||
return Legalized;
|
||||
@ -10241,17 +10195,12 @@ LegalizerHelper::LegalizeResult LegalizerHelper::lowerSelect(MachineInstr &MI) {
|
||||
auto [DstReg, DstTy, MaskReg, MaskTy, Op1Reg, Op1Ty, Op2Reg, Op2Ty] =
|
||||
MI.getFirst4RegLLTs();
|
||||
|
||||
LLT Op1TyInt =
|
||||
Op1Ty.changeElementType(LLT::integer(Op1Ty.getScalarSizeInBits()));
|
||||
|
||||
bool IsEltPtr = DstTy.isPointerOrPointerVector();
|
||||
if (IsEltPtr) {
|
||||
LLT ScalarPtrTy = LLT::scalar(DstTy.getScalarSizeInBits());
|
||||
LLT NewTy = DstTy.changeElementType(ScalarPtrTy);
|
||||
Op1Reg = MIRBuilder.buildPtrToInt(NewTy, Op1Reg).getReg(0);
|
||||
Op1Ty = MRI.getType(Op1Reg);
|
||||
Op2Reg = MIRBuilder.buildPtrToInt(NewTy, Op2Reg).getReg(0);
|
||||
Op2Ty = MRI.getType(Op2Reg);
|
||||
DstTy = NewTy;
|
||||
}
|
||||
|
||||
@ -10286,17 +10235,6 @@ LegalizerHelper::LegalizeResult LegalizerHelper::lowerSelect(MachineInstr &MI) {
|
||||
return UnableToLegalize;
|
||||
}
|
||||
|
||||
if (!(Op1Ty.getScalarType().isAnyScalar() ||
|
||||
Op1Ty.getScalarType().isInteger()))
|
||||
Op1Reg = MIRBuilder.buildBitcast(Op1TyInt, Op1Reg).getReg(0);
|
||||
|
||||
if (!(Op2Ty.getScalarType().isAnyScalar() ||
|
||||
Op2Ty.getScalarType().isInteger())) {
|
||||
auto Op2TyInt =
|
||||
Op2Ty.changeElementType(LLT::integer(Op2Ty.getScalarSizeInBits()));
|
||||
Op2Reg = MIRBuilder.buildBitcast(Op2TyInt, Op2Reg).getReg(0);
|
||||
}
|
||||
|
||||
auto NotMask = MIRBuilder.buildNot(MaskTy, MaskReg);
|
||||
auto NewOp1 = MIRBuilder.buildAnd(MaskTy, Op1Reg, MaskReg);
|
||||
auto NewOp2 = MIRBuilder.buildAnd(MaskTy, Op2Reg, NotMask);
|
||||
@ -10304,12 +10242,7 @@ LegalizerHelper::LegalizeResult LegalizerHelper::lowerSelect(MachineInstr &MI) {
|
||||
auto Or = MIRBuilder.buildOr(DstTy, NewOp1, NewOp2);
|
||||
MIRBuilder.buildIntToPtr(DstReg, Or);
|
||||
} else {
|
||||
if (DstTy == Op1TyInt)
|
||||
MIRBuilder.buildOr(DstReg, NewOp1, NewOp2);
|
||||
else {
|
||||
auto Or = MIRBuilder.buildOr(Op1TyInt, NewOp1, NewOp2);
|
||||
MIRBuilder.buildBitcast(DstReg, Or.getReg(0));
|
||||
}
|
||||
MIRBuilder.buildOr(DstReg, NewOp1, NewOp2);
|
||||
}
|
||||
MI.eraseFromParent();
|
||||
return Legalized;
|
||||
@ -10425,36 +10358,16 @@ LegalizerHelper::lowerAbsDiffToMinMax(MachineInstr &MI) {
|
||||
}
|
||||
|
||||
LegalizerHelper::LegalizeResult LegalizerHelper::lowerFAbs(MachineInstr &MI) {
|
||||
auto [DstReg, DstTy, SrcReg, SrcTy] = MI.getFirst2RegLLTs();
|
||||
LLT TyInt =
|
||||
DstTy.changeElementType(LLT::integer(DstTy.getScalarSizeInBits()));
|
||||
Register CastedSrc = SrcReg;
|
||||
Register SrcReg = MI.getOperand(1).getReg();
|
||||
Register DstReg = MI.getOperand(0).getReg();
|
||||
|
||||
if (!(SrcTy.getScalarType().isAnyScalar() ||
|
||||
SrcTy.getScalarType().isInteger())) {
|
||||
auto SrcTyInt =
|
||||
SrcTy.changeElementType(LLT::integer(SrcTy.getScalarSizeInBits()));
|
||||
CastedSrc = MIRBuilder.buildBitcast(SrcTyInt, SrcReg).getReg(0);
|
||||
}
|
||||
LLT Ty = MRI.getType(DstReg);
|
||||
|
||||
if (MRI.getType(DstReg) != TyInt) {
|
||||
// Reset sign bit
|
||||
Register NewDst =
|
||||
MIRBuilder
|
||||
.buildAnd(TyInt, CastedSrc,
|
||||
MIRBuilder.buildConstant(
|
||||
TyInt, APInt::getSignedMaxValue(
|
||||
DstTy.getScalarSizeInBits())))
|
||||
.getReg(0);
|
||||
|
||||
MIRBuilder.buildBitcast(DstReg, NewDst);
|
||||
} else
|
||||
MIRBuilder
|
||||
.buildAnd(
|
||||
DstReg, CastedSrc,
|
||||
MIRBuilder.buildConstant(
|
||||
TyInt, APInt::getSignedMaxValue(DstTy.getScalarSizeInBits())))
|
||||
.getReg(0);
|
||||
// Reset sign bit
|
||||
MIRBuilder.buildAnd(
|
||||
DstReg, SrcReg,
|
||||
MIRBuilder.buildConstant(
|
||||
Ty, APInt::getSignedMaxValue(Ty.getScalarSizeInBits())));
|
||||
|
||||
MI.eraseFromParent();
|
||||
return Legalized;
|
||||
|
||||
@ -587,8 +587,7 @@ MachineInstrBuilder MachineIRBuilder::buildExtOrTrunc(unsigned ExtOpc,
|
||||
Op.getLLTTy(*getMRI()).getSizeInBits())
|
||||
Opcode = TargetOpcode::G_TRUNC;
|
||||
else
|
||||
assert(Res.getLLTTy(*getMRI()).getSizeInBits() ==
|
||||
Op.getLLTTy(*getMRI()).getSizeInBits());
|
||||
assert(Res.getLLTTy(*getMRI()) == Op.getLLTTy(*getMRI()));
|
||||
|
||||
return buildInstr(Opcode, Res, Op);
|
||||
}
|
||||
@ -787,7 +786,7 @@ MachineInstrBuilder MachineIRBuilder::buildShuffleSplat(const DstOp &Res,
|
||||
assert(Src.getLLTTy(*getMRI()) == DstTy.getElementType() &&
|
||||
"Expected Src to match Dst elt ty");
|
||||
auto UndefVec = buildUndef(DstTy);
|
||||
auto Zero = buildConstant(LLT::integer(64), 0);
|
||||
auto Zero = buildConstant(LLT::scalar(64), 0);
|
||||
auto InsElt = buildInsertVectorElement(DstTy, UndefVec, Src, Zero);
|
||||
SmallVector<int, 16> ZeroMask(DstTy.getNumElements());
|
||||
return buildShuffleVector(DstTy, InsElt, UndefVec, ZeroMask);
|
||||
|
||||
@ -790,35 +790,15 @@ llvm::ConstantFoldFPBinOp(unsigned Opcode, const Register Op1,
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
static GBuildVector *getBuildVectorLikeDef(Register Reg,
|
||||
const MachineRegisterInfo &MRI) {
|
||||
if (auto *BV = getOpcodeDef<GBuildVector>(Reg, MRI))
|
||||
return BV;
|
||||
|
||||
auto *Bitcast = getOpcodeDef(TargetOpcode::G_BITCAST, Reg, MRI);
|
||||
if (!Bitcast)
|
||||
return nullptr;
|
||||
|
||||
auto [Dst, DstTy, Src, SrcTy] = Bitcast->getFirst2RegLLTs();
|
||||
if (!SrcTy.isVector() || !DstTy.isVector())
|
||||
return nullptr;
|
||||
if (SrcTy.getElementCount() != DstTy.getElementCount())
|
||||
return nullptr;
|
||||
if (SrcTy.getScalarSizeInBits() != DstTy.getScalarSizeInBits())
|
||||
return nullptr;
|
||||
|
||||
return getOpcodeDef<GBuildVector>(Src, MRI);
|
||||
}
|
||||
|
||||
SmallVector<APInt>
|
||||
llvm::ConstantFoldVectorBinop(unsigned Opcode, const Register Op1,
|
||||
const Register Op2,
|
||||
const MachineRegisterInfo &MRI) {
|
||||
auto *SrcVec2 = getBuildVectorLikeDef(Op2, MRI);
|
||||
auto *SrcVec2 = getOpcodeDef<GBuildVector>(Op2, MRI);
|
||||
if (!SrcVec2)
|
||||
return SmallVector<APInt>();
|
||||
|
||||
auto *SrcVec1 = getBuildVectorLikeDef(Op1, MRI);
|
||||
auto *SrcVec1 = getOpcodeDef<GBuildVector>(Op1, MRI);
|
||||
if (!SrcVec1)
|
||||
return SmallVector<APInt>();
|
||||
|
||||
|
||||
@ -18,7 +18,7 @@
|
||||
using namespace llvm;
|
||||
|
||||
LLT llvm::getLLTForType(Type &Ty, const DataLayout &DL) {
|
||||
if (auto *VTy = dyn_cast<VectorType>(&Ty)) {
|
||||
if (auto VTy = dyn_cast<VectorType>(&Ty)) {
|
||||
auto EC = VTy->getElementCount();
|
||||
LLT ScalarTy = getLLTForType(*VTy->getElementType(), DL);
|
||||
if (EC.isScalar())
|
||||
@ -26,7 +26,7 @@ LLT llvm::getLLTForType(Type &Ty, const DataLayout &DL) {
|
||||
return LLT::vector(EC, ScalarTy);
|
||||
}
|
||||
|
||||
if (auto *PTy = dyn_cast<PointerType>(&Ty)) {
|
||||
if (auto PTy = dyn_cast<PointerType>(&Ty)) {
|
||||
unsigned AddrSpace = PTy->getAddressSpace();
|
||||
return LLT::pointer(AddrSpace, DL.getPointerSizeInBits(AddrSpace));
|
||||
}
|
||||
@ -36,35 +36,6 @@ LLT llvm::getLLTForType(Type &Ty, const DataLayout &DL) {
|
||||
// concerned.
|
||||
auto SizeInBits = DL.getTypeSizeInBits(&Ty);
|
||||
assert(SizeInBits != 0 && "invalid zero-sized type");
|
||||
|
||||
// Return simple scalar
|
||||
if (!LLT::getUseExtended())
|
||||
return LLT::scalar(SizeInBits);
|
||||
|
||||
// Choose more precise LLT variant
|
||||
if (Ty.isFloatingPointTy())
|
||||
switch (Ty.getTypeID()) {
|
||||
default:
|
||||
llvm_unreachable("Unhandled LLVM IR floating point type");
|
||||
case Type::HalfTyID:
|
||||
return LLT::float16();
|
||||
case Type::BFloatTyID:
|
||||
return LLT::bfloat16();
|
||||
case Type::FloatTyID:
|
||||
return LLT::float32();
|
||||
case Type::DoubleTyID:
|
||||
return LLT::float64();
|
||||
case Type::X86_FP80TyID:
|
||||
return LLT::x86fp80();
|
||||
case Type::FP128TyID:
|
||||
return LLT::float128();
|
||||
case Type::PPC_FP128TyID:
|
||||
return LLT::ppcf128();
|
||||
}
|
||||
|
||||
if (Ty.isIntegerTy())
|
||||
return LLT::integer(SizeInBits);
|
||||
|
||||
return LLT::scalar(SizeInBits);
|
||||
}
|
||||
|
||||
@ -75,24 +46,12 @@ LLT llvm::getLLTForType(Type &Ty, const DataLayout &DL) {
|
||||
}
|
||||
|
||||
MVT llvm::getMVTForLLT(LLT Ty) {
|
||||
if (Ty.isVector())
|
||||
return MVT::getVectorVT(getMVTForLLT(Ty.getElementType()),
|
||||
Ty.getElementCount());
|
||||
if (!Ty.isVector())
|
||||
return MVT::getIntegerVT(Ty.getSizeInBits());
|
||||
|
||||
if (Ty.isFloat()) {
|
||||
if (Ty.isBFloat16())
|
||||
return MVT::bf16;
|
||||
|
||||
if (Ty.isX86FP80())
|
||||
return MVT::f80;
|
||||
|
||||
if (Ty.isPPCF128())
|
||||
return MVT::ppcf128;
|
||||
|
||||
return MVT::getFloatingPointVT(Ty.getSizeInBits());
|
||||
}
|
||||
|
||||
return MVT::getIntegerVT(Ty.getSizeInBits());
|
||||
return MVT::getVectorVT(
|
||||
MVT::getIntegerVT(Ty.getElementType().getSizeInBits()),
|
||||
Ty.getElementCount());
|
||||
}
|
||||
|
||||
EVT llvm::getApproximateEVTForLLT(LLT Ty, LLVMContext &Ctx) {
|
||||
@ -104,28 +63,25 @@ EVT llvm::getApproximateEVTForLLT(LLT Ty, LLVMContext &Ctx) {
|
||||
return EVT::getIntegerVT(Ctx, Ty.getSizeInBits());
|
||||
}
|
||||
|
||||
LLT llvm::getLLTForMVT(MVT VT) { return LLT(VT); }
|
||||
LLT llvm::getLLTForMVT(MVT Ty) {
|
||||
if (!Ty.isVector())
|
||||
return LLT::scalar(Ty.getSizeInBits());
|
||||
|
||||
return LLT::scalarOrVector(Ty.getVectorElementCount(),
|
||||
Ty.getVectorElementType().getSizeInBits());
|
||||
}
|
||||
|
||||
const llvm::fltSemantics &llvm::getFltSemanticForLLT(LLT Ty) {
|
||||
assert((Ty.isAnyScalar() || Ty.isFloat()) &&
|
||||
"Expected a any scalar or float type.");
|
||||
|
||||
// Any scalar type always matches IEEE format
|
||||
// FIXME: Remove this handling
|
||||
if (Ty.isAnyScalar()) {
|
||||
switch (Ty.getSizeInBits()) {
|
||||
default:
|
||||
llvm_unreachable("Invalid FP type size.");
|
||||
case 16:
|
||||
return APFloat::IEEEhalf();
|
||||
case 32:
|
||||
return APFloat::IEEEsingle();
|
||||
case 64:
|
||||
return APFloat::IEEEdouble();
|
||||
case 128:
|
||||
return APFloat::IEEEquad();
|
||||
}
|
||||
assert(Ty.isScalar() && "Expected a scalar type.");
|
||||
switch (Ty.getSizeInBits()) {
|
||||
case 16:
|
||||
return APFloat::IEEEhalf();
|
||||
case 32:
|
||||
return APFloat::IEEEsingle();
|
||||
case 64:
|
||||
return APFloat::IEEEdouble();
|
||||
case 128:
|
||||
return APFloat::IEEEquad();
|
||||
}
|
||||
|
||||
return APFloat::EnumToSemantics(Ty.getFpSemantics());
|
||||
llvm_unreachable("Invalid FP type size.");
|
||||
}
|
||||
|
||||
@ -2115,35 +2115,26 @@ static bool verifyAddrSpace(uint64_t AddrSpace) {
|
||||
}
|
||||
|
||||
bool MIParser::parseLowLevelType(StringRef::iterator Loc, LLT &Ty) {
|
||||
StringRef TypeDigits = Token.range();
|
||||
if (TypeDigits.consume_front("s") || TypeDigits.consume_front("i") ||
|
||||
TypeDigits.consume_front("f") || TypeDigits.consume_front("p") ||
|
||||
TypeDigits.consume_front("bf")) {
|
||||
if (TypeDigits.empty() || !llvm::all_of(TypeDigits, isdigit))
|
||||
return error(
|
||||
"expected integers after 's'/'i'/'f'/'bf'/'p' type identifier");
|
||||
if (Token.range().front() == 's' || Token.range().front() == 'p') {
|
||||
StringRef SizeStr = Token.range().drop_front();
|
||||
if (SizeStr.size() == 0 || !llvm::all_of(SizeStr, isdigit))
|
||||
return error("expected integers after 's'/'p' type character");
|
||||
}
|
||||
|
||||
bool Scalar = Token.range().starts_with("s");
|
||||
if (Scalar || Token.range().starts_with("i")) {
|
||||
auto ScalarSize = APSInt(TypeDigits).getZExtValue();
|
||||
if (!ScalarSize) {
|
||||
if (Token.range().front() == 's') {
|
||||
auto ScalarSize = APSInt(Token.range().drop_front()).getZExtValue();
|
||||
if (ScalarSize) {
|
||||
if (!verifyScalarSize(ScalarSize))
|
||||
return error("invalid size for scalar type");
|
||||
Ty = LLT::scalar(ScalarSize);
|
||||
} else {
|
||||
Ty = LLT::token();
|
||||
lex();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!verifyScalarSize(ScalarSize))
|
||||
return error("invalid size for scalar type");
|
||||
|
||||
Ty = Scalar ? LLT::scalar(ScalarSize) : LLT::integer(ScalarSize);
|
||||
lex();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Token.range().starts_with("p")) {
|
||||
} else if (Token.range().front() == 'p') {
|
||||
const DataLayout &DL = MF.getDataLayout();
|
||||
uint64_t AS = APSInt(TypeDigits).getZExtValue();
|
||||
uint64_t AS = APSInt(Token.range().drop_front()).getZExtValue();
|
||||
if (!verifyAddrSpace(AS))
|
||||
return error("invalid address space number");
|
||||
|
||||
@ -2152,25 +2143,10 @@ bool MIParser::parseLowLevelType(StringRef::iterator Loc, LLT &Ty) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Token.range().starts_with("f") || Token.range().starts_with("bf")) {
|
||||
auto ScalarSize = APSInt(TypeDigits).getZExtValue();
|
||||
if (!ScalarSize || !verifyScalarSize(ScalarSize))
|
||||
return error("invalid size for scalar type");
|
||||
|
||||
if (Token.range().starts_with("bf") && ScalarSize != 16)
|
||||
return error("invalid size for bfloat");
|
||||
|
||||
Ty = Token.range().starts_with("bf") ? LLT::bfloat16()
|
||||
: LLT::floatIEEE(ScalarSize);
|
||||
lex();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Now we're looking for a vector.
|
||||
if (Token.isNot(MIToken::less))
|
||||
return error(Loc, "expected tN, pA, <M x tN>, <M x pA>, <vscale x M x tN>, "
|
||||
"or <vscale x M x pA> for GlobalISel type, "
|
||||
"where t = {'s', 'i', 'f', 'bf'}");
|
||||
return error(Loc, "expected sN, pA, <M x sN>, <M x pA>, <vscale x M x sN>, "
|
||||
"or <vscale x M x pA> for GlobalISel type");
|
||||
lex();
|
||||
|
||||
bool HasVScale =
|
||||
@ -2178,17 +2154,15 @@ bool MIParser::parseLowLevelType(StringRef::iterator Loc, LLT &Ty) {
|
||||
if (HasVScale) {
|
||||
lex();
|
||||
if (Token.isNot(MIToken::Identifier) || Token.stringValue() != "x")
|
||||
return error(
|
||||
"expected <vscale x M x tN>, where t = {'s', 'i', 'f', 'bf', 'p'}");
|
||||
return error("expected <vscale x M x sN> or <vscale x M x pA>");
|
||||
lex();
|
||||
}
|
||||
|
||||
auto GetError = [this, &HasVScale, Loc]() {
|
||||
if (HasVScale)
|
||||
return error(Loc, "expected <vscale x M x tN> for vector type, where t = "
|
||||
"{'s', 'i', 'f', 'bf', 'p'}");
|
||||
return error(Loc, "expected <M x tN> for vector type, where t = {'s', 'i', "
|
||||
"'f', 'bf', 'p'}");
|
||||
return error(
|
||||
Loc, "expected <vscale x M x sN> or <vscale M x pA> for vector type");
|
||||
return error(Loc, "expected <M x sN> or <M x pA> for vector type");
|
||||
};
|
||||
|
||||
if (Token.isNot(MIToken::IntegerLiteral))
|
||||
@ -2203,40 +2177,25 @@ bool MIParser::parseLowLevelType(StringRef::iterator Loc, LLT &Ty) {
|
||||
return GetError();
|
||||
lex();
|
||||
|
||||
StringRef VectorTyDigits = Token.range();
|
||||
if (!VectorTyDigits.consume_front("s") &&
|
||||
!VectorTyDigits.consume_front("i") &&
|
||||
!VectorTyDigits.consume_front("f") &&
|
||||
!VectorTyDigits.consume_front("p") && !VectorTyDigits.consume_front("bf"))
|
||||
if (Token.range().front() != 's' && Token.range().front() != 'p')
|
||||
return GetError();
|
||||
|
||||
if (VectorTyDigits.empty() || !llvm::all_of(VectorTyDigits, isdigit))
|
||||
return error(
|
||||
"expected integers after 's'/'i'/'f'/'bf'/'p' type identifier");
|
||||
StringRef SizeStr = Token.range().drop_front();
|
||||
if (SizeStr.size() == 0 || !llvm::all_of(SizeStr, isdigit))
|
||||
return error("expected integers after 's'/'p' type character");
|
||||
|
||||
Scalar = Token.range().starts_with("s");
|
||||
if (Scalar || Token.range().starts_with("i")) {
|
||||
auto ScalarSize = APSInt(VectorTyDigits).getZExtValue();
|
||||
if (Token.range().front() == 's') {
|
||||
auto ScalarSize = APSInt(Token.range().drop_front()).getZExtValue();
|
||||
if (!verifyScalarSize(ScalarSize))
|
||||
return error("invalid size for scalar element in vector");
|
||||
Ty = Scalar ? LLT::scalar(ScalarSize) : LLT::integer(ScalarSize);
|
||||
} else if (Token.range().starts_with("p")) {
|
||||
Ty = LLT::scalar(ScalarSize);
|
||||
} else if (Token.range().front() == 'p') {
|
||||
const DataLayout &DL = MF.getDataLayout();
|
||||
uint64_t AS = APSInt(VectorTyDigits).getZExtValue();
|
||||
uint64_t AS = APSInt(Token.range().drop_front()).getZExtValue();
|
||||
if (!verifyAddrSpace(AS))
|
||||
return error("invalid address space number");
|
||||
|
||||
Ty = LLT::pointer(AS, DL.getPointerSizeInBits(AS));
|
||||
} else if (Token.range().starts_with("f")) {
|
||||
auto ScalarSize = APSInt(VectorTyDigits).getZExtValue();
|
||||
if (!verifyScalarSize(ScalarSize))
|
||||
return error("invalid size for float element in vector");
|
||||
Ty = LLT::floatIEEE(ScalarSize);
|
||||
} else if (Token.range().starts_with("bf")) {
|
||||
auto ScalarSize = APSInt(VectorTyDigits).getZExtValue();
|
||||
if (!verifyScalarSize(ScalarSize))
|
||||
return error("invalid size for bfloat element in vector");
|
||||
Ty = LLT::bfloat16();
|
||||
} else {
|
||||
return GetError();
|
||||
}
|
||||
@ -2253,15 +2212,14 @@ bool MIParser::parseLowLevelType(StringRef::iterator Loc, LLT &Ty) {
|
||||
|
||||
bool MIParser::parseTypedImmediateOperand(MachineOperand &Dest) {
|
||||
assert(Token.is(MIToken::Identifier));
|
||||
StringRef TypeDigits = Token.range();
|
||||
if (!TypeDigits.consume_front("i") && !TypeDigits.consume_front("s") &&
|
||||
!TypeDigits.consume_front("p") && !TypeDigits.consume_front("f") &&
|
||||
!TypeDigits.consume_front("bf"))
|
||||
return error("a typed immediate operand should start with one of 'i', "
|
||||
"'s', 'f', 'bf', or 'p'");
|
||||
if (TypeDigits.empty() || !llvm::all_of(TypeDigits, isdigit))
|
||||
StringRef TypeStr = Token.range();
|
||||
if (TypeStr.front() != 'i' && TypeStr.front() != 's' &&
|
||||
TypeStr.front() != 'p')
|
||||
return error(
|
||||
"expected integers after 'i'/'s'/'f'/'bf'/'p' type identifier");
|
||||
"a typed immediate operand should start with one of 'i', 's', or 'p'");
|
||||
StringRef SizeStr = Token.range().drop_front();
|
||||
if (SizeStr.size() == 0 || !llvm::all_of(SizeStr, isdigit))
|
||||
return error("expected integers after 'i'/'s'/'p' type character");
|
||||
|
||||
auto Loc = Token.location();
|
||||
lex();
|
||||
|
||||
@ -1336,16 +1336,7 @@ void MachineVerifier::verifyPreISelGenericInstruction(const MachineInstr *MI) {
|
||||
if (SrcTy.getSizeInBits() != DstTy.getSizeInBits())
|
||||
report("bitcast sizes must match", MI);
|
||||
|
||||
bool SameType = SrcTy.getKind() == DstTy.getKind();
|
||||
if (SameType && SrcTy.isPointerOrPointerVector())
|
||||
SameType &= SrcTy.getAddressSpace() == DstTy.getAddressSpace();
|
||||
|
||||
SameType &= SrcTy.getScalarSizeInBits() == DstTy.getScalarSizeInBits();
|
||||
|
||||
if (SameType && SrcTy.isVector())
|
||||
SameType &= SrcTy.getElementCount() == DstTy.getElementCount();
|
||||
|
||||
if (SameType)
|
||||
if (SrcTy == DstTy)
|
||||
report("bitcast must change the type", MI);
|
||||
|
||||
break;
|
||||
|
||||
@ -16,91 +16,36 @@
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
using namespace llvm;
|
||||
|
||||
bool LLT::ExtendedLLT = false;
|
||||
|
||||
static LLT::FpSemantics getFpSemanticsForMVT(MVT VT) {
|
||||
switch (VT.getScalarType().SimpleTy) {
|
||||
default:
|
||||
llvm_unreachable("Unknown FP format");
|
||||
case MVT::f16:
|
||||
return LLT::FpSemantics::S_IEEEhalf;
|
||||
case MVT::bf16:
|
||||
return LLT::FpSemantics::S_BFloat;
|
||||
case MVT::f32:
|
||||
return LLT::FpSemantics::S_IEEEsingle;
|
||||
case MVT::f64:
|
||||
return LLT::FpSemantics::S_IEEEdouble;
|
||||
case MVT::f80:
|
||||
return LLT::FpSemantics::S_x87DoubleExtended;
|
||||
case MVT::f128:
|
||||
return LLT::FpSemantics::S_IEEEquad;
|
||||
case MVT::ppcf128:
|
||||
return LLT::FpSemantics::S_PPCDoubleDouble;
|
||||
}
|
||||
}
|
||||
|
||||
LLT::LLT(MVT VT) {
|
||||
if (!ExtendedLLT) {
|
||||
if (VT.isVector()) {
|
||||
bool AsVector = VT.getVectorMinNumElements() > 1 || VT.isScalableVector();
|
||||
Kind Info = AsVector ? Kind::VECTOR_ANY : Kind::ANY_SCALAR;
|
||||
init(Info, VT.getVectorElementCount(),
|
||||
VT.getVectorElementType().getSizeInBits());
|
||||
} else if (VT.isValid() && !VT.isScalableTargetExtVT()) {
|
||||
init(Kind::ANY_SCALAR, ElementCount::getFixed(0), VT.getSizeInBits());
|
||||
} else {
|
||||
this->Info = Kind::INVALID;
|
||||
this->RawData = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
bool IsFloatingPoint = VT.isFloatingPoint();
|
||||
bool AsVector = VT.isVector() &&
|
||||
(VT.getVectorMinNumElements() > 1 || VT.isScalableVector());
|
||||
|
||||
if (AsVector) {
|
||||
if (IsFloatingPoint)
|
||||
init(LLT::Kind::VECTOR_FLOAT, VT.getVectorElementCount(),
|
||||
VT.getVectorElementType().getSizeInBits(), getFpSemanticsForMVT(VT));
|
||||
else
|
||||
init(LLT::Kind::VECTOR_INTEGER, VT.getVectorElementCount(),
|
||||
VT.getVectorElementType().getSizeInBits());
|
||||
if (VT.isVector()) {
|
||||
bool asVector = VT.getVectorMinNumElements() > 1 || VT.isScalableVector();
|
||||
init(/*IsPointer=*/false, asVector, /*IsScalar=*/!asVector,
|
||||
VT.getVectorElementCount(), VT.getVectorElementType().getSizeInBits(),
|
||||
/*AddressSpace=*/0);
|
||||
} else if (VT.isValid() && !VT.isScalableTargetExtVT()) {
|
||||
// Aggregates are no different from real scalars as far as GlobalISel is
|
||||
// concerned.
|
||||
if (IsFloatingPoint)
|
||||
init(LLT::Kind::FLOAT, ElementCount::getFixed(0), VT.getSizeInBits(),
|
||||
getFpSemanticsForMVT(VT));
|
||||
else
|
||||
init(LLT::Kind::INTEGER, ElementCount::getFixed(0), VT.getSizeInBits());
|
||||
init(/*IsPointer=*/false, /*IsVector=*/false, /*IsScalar=*/true,
|
||||
ElementCount::getFixed(0), VT.getSizeInBits(), /*AddressSpace=*/0);
|
||||
} else {
|
||||
this->Info = Kind::INVALID;
|
||||
this->RawData = 0;
|
||||
IsScalar = false;
|
||||
IsPointer = false;
|
||||
IsVector = false;
|
||||
RawData = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void LLT::print(raw_ostream &OS) const {
|
||||
if (isVector()) {
|
||||
OS << "<";
|
||||
OS << getElementCount() << " x " << getElementType() << ">";
|
||||
} else if (isPointer()) {
|
||||
} else if (isPointer())
|
||||
OS << "p" << getAddressSpace();
|
||||
} else if (isBFloat16()) {
|
||||
OS << "bf16";
|
||||
} else if (isPPCF128()) {
|
||||
OS << "ppcf128";
|
||||
} else if (isFloatIEEE()) {
|
||||
OS << "f" << getScalarSizeInBits();
|
||||
} else if (isInteger()) {
|
||||
OS << "i" << getScalarSizeInBits();
|
||||
} else if (isValid()) {
|
||||
else if (isValid()) {
|
||||
assert(isScalar() && "unexpected type");
|
||||
OS << "s" << getScalarSizeInBits();
|
||||
} else {
|
||||
} else
|
||||
OS << "LLT_invalid";
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
|
||||
|
||||
@ -463,9 +463,8 @@ bool AMDGPUCombinerHelper::matchCombineFmulWithSelectToFldexp(
|
||||
LLT DestTy = MRI.getType(Dst);
|
||||
LLT ScalarDestTy = DestTy.getScalarType();
|
||||
|
||||
// TODO: Expected float type in ScalarDestTy
|
||||
if ((ScalarDestTy != LLT::scalar(64) && ScalarDestTy != LLT::scalar(32) &&
|
||||
ScalarDestTy != LLT::scalar(16)) ||
|
||||
if ((ScalarDestTy != LLT::float64() && ScalarDestTy != LLT::float32() &&
|
||||
ScalarDestTy != LLT::float16()) ||
|
||||
!MRI.hasOneNonDBGUse(Sel.getOperand(0).getReg()))
|
||||
return false;
|
||||
|
||||
@ -486,8 +485,7 @@ bool AMDGPUCombinerHelper::matchCombineFmulWithSelectToFldexp(
|
||||
return false;
|
||||
|
||||
// For f32, only non-inline constants should be transformed.
|
||||
// TODO: Expected float32
|
||||
if (ScalarDestTy == LLT::scalar(32) && TII.isInlineConstant(*SelectTrueVal) &&
|
||||
if (ScalarDestTy == LLT::float32() && TII.isInlineConstant(*SelectTrueVal) &&
|
||||
TII.isInlineConstant(*SelectFalseVal))
|
||||
return false;
|
||||
|
||||
|
||||
@ -297,9 +297,9 @@ constexpr LLT S1 = LLT::scalar(1);
|
||||
constexpr LLT S8 = LLT::scalar(8);
|
||||
constexpr LLT S16 = LLT::scalar(16);
|
||||
constexpr LLT S32 = LLT::scalar(32);
|
||||
constexpr LLT F32 = LLT::scalar(32); // TODO: Expected float32
|
||||
constexpr LLT F32 = LLT::float32();
|
||||
constexpr LLT S64 = LLT::scalar(64);
|
||||
constexpr LLT F64 = LLT::scalar(64); // TODO: Expected float64
|
||||
constexpr LLT F64 = LLT::float64();
|
||||
constexpr LLT S96 = LLT::scalar(96);
|
||||
constexpr LLT S128 = LLT::scalar(128);
|
||||
constexpr LLT S160 = LLT::scalar(160);
|
||||
@ -319,8 +319,7 @@ constexpr LLT V10S16 = LLT::fixed_vector(10, 16);
|
||||
constexpr LLT V12S16 = LLT::fixed_vector(12, 16);
|
||||
constexpr LLT V16S16 = LLT::fixed_vector(16, 16);
|
||||
|
||||
// TODO: Expected LLT::fixed_vector(2, LLT::float16())
|
||||
constexpr LLT V2F16 = LLT::fixed_vector(2, LLT::scalar(16));
|
||||
constexpr LLT V2F16 = LLT::fixed_vector(2, LLT::float16());
|
||||
constexpr LLT V2BF16 = V2F16; // FIXME
|
||||
|
||||
constexpr LLT V2S32 = LLT::fixed_vector(2, 32);
|
||||
@ -3473,12 +3472,11 @@ bool AMDGPULegalizerInfo::legalizeFMad(
|
||||
const SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
|
||||
|
||||
// TODO: Always legal with future ftz flag.
|
||||
// TODO: Type is expected to be LLT::float32()/LLT::float16()
|
||||
// FIXME: Do we need just output?
|
||||
if (Ty == LLT::scalar(32) &&
|
||||
if (Ty == LLT::float32() &&
|
||||
MFI->getMode().FP32Denormals == DenormalMode::getPreserveSign())
|
||||
return true;
|
||||
if (Ty == LLT::scalar(16) &&
|
||||
if (Ty == LLT::float16() &&
|
||||
MFI->getMode().FP64FP16Denormals == DenormalMode::getPreserveSign())
|
||||
return true;
|
||||
|
||||
@ -4210,8 +4208,8 @@ bool AMDGPULegalizerInfo::legalizeFPow(MachineInstr &MI,
|
||||
Register Src1 = MI.getOperand(2).getReg();
|
||||
unsigned Flags = MI.getFlags();
|
||||
LLT Ty = B.getMRI()->getType(Dst);
|
||||
const LLT F16 = LLT::scalar(16); // TODO: Expected LLT::float16()
|
||||
const LLT F32 = LLT::scalar(32); // TODO: Expected LLT::float32()
|
||||
const LLT F16 = LLT::float16();
|
||||
const LLT F32 = LLT::float32();
|
||||
|
||||
if (Ty == F32) {
|
||||
auto Log = B.buildFLog2(F32, Src0, Flags);
|
||||
@ -4254,7 +4252,7 @@ bool AMDGPULegalizerInfo::legalizeFFloor(MachineInstr &MI,
|
||||
MachineIRBuilder &B) const {
|
||||
|
||||
const LLT S1 = LLT::scalar(1);
|
||||
const LLT F64 = LLT::scalar(64); // TODO: Expected float64
|
||||
const LLT F64 = LLT::float64();
|
||||
Register Dst = MI.getOperand(0).getReg();
|
||||
Register OrigSrc = MI.getOperand(1).getReg();
|
||||
unsigned Flags = MI.getFlags();
|
||||
|
||||
@ -334,14 +334,10 @@ define i32 @extract_v4iptr_vector_insert_const_fixed_legal(<4 x ptr> %a, <4 x pt
|
||||
; CHECK-NEXT: {{ $}}
|
||||
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(<2 x s64>) = COPY $q0
|
||||
; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(<2 x s64>) = COPY $q1
|
||||
; CHECK-NEXT: [[BITCAST:%[0-9]+]]:_(<2 x p0>) = G_BITCAST [[COPY]](<2 x s64>)
|
||||
; CHECK-NEXT: [[BITCAST1:%[0-9]+]]:_(<2 x p0>) = G_BITCAST [[COPY1]](<2 x s64>)
|
||||
; CHECK-NEXT: [[CONCAT_VECTORS:%[0-9]+]]:_(<4 x p0>) = G_CONCAT_VECTORS [[BITCAST]](<2 x p0>), [[BITCAST1]](<2 x p0>)
|
||||
; CHECK-NEXT: [[CONCAT_VECTORS:%[0-9]+]]:_(<4 x p0>) = G_CONCAT_VECTORS [[COPY]](<2 x s64>), [[COPY1]](<2 x s64>)
|
||||
; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(<2 x s64>) = COPY $q2
|
||||
; CHECK-NEXT: [[COPY3:%[0-9]+]]:_(<2 x s64>) = COPY $q3
|
||||
; CHECK-NEXT: [[BITCAST2:%[0-9]+]]:_(<2 x p0>) = G_BITCAST [[COPY2]](<2 x s64>)
|
||||
; CHECK-NEXT: [[BITCAST3:%[0-9]+]]:_(<2 x p0>) = G_BITCAST [[COPY3]](<2 x s64>)
|
||||
; CHECK-NEXT: [[CONCAT_VECTORS1:%[0-9]+]]:_(<4 x p0>) = G_CONCAT_VECTORS [[BITCAST2]](<2 x p0>), [[BITCAST3]](<2 x p0>)
|
||||
; CHECK-NEXT: [[CONCAT_VECTORS1:%[0-9]+]]:_(<4 x p0>) = G_CONCAT_VECTORS [[COPY2]](<2 x s64>), [[COPY3]](<2 x s64>)
|
||||
; CHECK-NEXT: [[COPY4:%[0-9]+]]:_(p0) = COPY $x0
|
||||
; CHECK-NEXT: [[COPY5:%[0-9]+]]:_(p0) = COPY $x1
|
||||
; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
|
||||
|
||||
@ -12,14 +12,16 @@ define <4 x ptr> @pr168872(<4 x ptr> %ptrs) {
|
||||
; CHECK-NEXT: {{ $}}
|
||||
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(<2 x s64>) = COPY $q0
|
||||
; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(<2 x s64>) = COPY $q1
|
||||
; CHECK-NEXT: [[BITCAST:%[0-9]+]]:_(<2 x p0>) = G_BITCAST [[COPY]](<2 x s64>)
|
||||
; CHECK-NEXT: [[BITCAST1:%[0-9]+]]:_(<2 x p0>) = G_BITCAST [[COPY1]](<2 x s64>)
|
||||
; CHECK-NEXT: [[C:%[0-9]+]]:_(p0) = G_CONSTANT i64 0
|
||||
; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x p0>) = G_BUILD_VECTOR [[C]](p0), [[C]](p0)
|
||||
; CHECK-NEXT: [[BITCAST:%[0-9]+]]:_(<2 x p0>) = G_BITCAST [[COPY]](<2 x s64>)
|
||||
; CHECK-NEXT: [[BITCAST1:%[0-9]+]]:_(<2 x p0>) = G_BITCAST [[COPY1]](<2 x s64>)
|
||||
; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(<2 x s64>) = G_ICMP intpred(ugt), [[BITCAST]](<2 x p0>), [[BUILD_VECTOR]]
|
||||
; CHECK-NEXT: [[ICMP1:%[0-9]+]]:_(<2 x s64>) = G_ICMP intpred(ugt), [[BITCAST1]](<2 x p0>), [[BUILD_VECTOR]]
|
||||
; CHECK-NEXT: [[PTRTOINT:%[0-9]+]]:_(<2 x s64>) = G_PTRTOINT [[BITCAST]](<2 x p0>)
|
||||
; CHECK-NEXT: [[PTRTOINT1:%[0-9]+]]:_(<2 x s64>) = G_PTRTOINT [[BITCAST1]](<2 x p0>)
|
||||
; CHECK-NEXT: [[BITCAST2:%[0-9]+]]:_(<2 x p0>) = G_BITCAST [[COPY]](<2 x s64>)
|
||||
; CHECK-NEXT: [[BITCAST3:%[0-9]+]]:_(<2 x p0>) = G_BITCAST [[COPY1]](<2 x s64>)
|
||||
; CHECK-NEXT: [[PTRTOINT:%[0-9]+]]:_(<2 x s64>) = G_PTRTOINT [[BITCAST2]](<2 x p0>)
|
||||
; CHECK-NEXT: [[PTRTOINT1:%[0-9]+]]:_(<2 x s64>) = G_PTRTOINT [[BITCAST3]](<2 x p0>)
|
||||
; CHECK-NEXT: [[PTRTOINT2:%[0-9]+]]:_(<2 x s64>) = G_PTRTOINT [[BUILD_VECTOR]](<2 x p0>)
|
||||
; CHECK-NEXT: [[PTRTOINT3:%[0-9]+]]:_(<2 x s64>) = G_PTRTOINT [[BUILD_VECTOR]](<2 x p0>)
|
||||
; CHECK-NEXT: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 -1
|
||||
@ -34,10 +36,10 @@ define <4 x ptr> @pr168872(<4 x ptr> %ptrs) {
|
||||
; CHECK-NEXT: [[OR1:%[0-9]+]]:_(<2 x s64>) = G_OR [[AND1]], [[AND3]]
|
||||
; CHECK-NEXT: [[INTTOPTR:%[0-9]+]]:_(<2 x p0>) = G_INTTOPTR [[OR]](<2 x s64>)
|
||||
; CHECK-NEXT: [[INTTOPTR1:%[0-9]+]]:_(<2 x p0>) = G_INTTOPTR [[OR1]](<2 x s64>)
|
||||
; CHECK-NEXT: [[BITCAST2:%[0-9]+]]:_(<2 x s64>) = G_BITCAST [[INTTOPTR]](<2 x p0>)
|
||||
; CHECK-NEXT: [[BITCAST3:%[0-9]+]]:_(<2 x s64>) = G_BITCAST [[INTTOPTR1]](<2 x p0>)
|
||||
; CHECK-NEXT: $q0 = COPY [[BITCAST2]](<2 x s64>)
|
||||
; CHECK-NEXT: $q1 = COPY [[BITCAST3]](<2 x s64>)
|
||||
; CHECK-NEXT: [[BITCAST4:%[0-9]+]]:_(<2 x s64>) = G_BITCAST [[INTTOPTR]](<2 x p0>)
|
||||
; CHECK-NEXT: [[BITCAST5:%[0-9]+]]:_(<2 x s64>) = G_BITCAST [[INTTOPTR1]](<2 x p0>)
|
||||
; CHECK-NEXT: $q0 = COPY [[BITCAST4]](<2 x s64>)
|
||||
; CHECK-NEXT: $q1 = COPY [[BITCAST5]](<2 x s64>)
|
||||
; CHECK-NEXT: RET_ReallyLR implicit $q0, implicit $q1
|
||||
entry:
|
||||
%cmp = icmp ugt <4 x ptr> %ptrs, zeroinitializer
|
||||
|
||||
@ -153,9 +153,7 @@ define <4 x ptr> @vector_gep_v4i32(<4 x ptr> %b, <4 x i32> %off) {
|
||||
; CHECK-NEXT: {{ $}}
|
||||
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(<2 x s64>) = COPY $q0
|
||||
; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(<2 x s64>) = COPY $q1
|
||||
; CHECK-NEXT: [[BITCAST:%[0-9]+]]:_(<2 x p0>) = G_BITCAST [[COPY]](<2 x s64>)
|
||||
; CHECK-NEXT: [[BITCAST1:%[0-9]+]]:_(<2 x p0>) = G_BITCAST [[COPY1]](<2 x s64>)
|
||||
; CHECK-NEXT: [[CONCAT_VECTORS:%[0-9]+]]:_(<4 x p0>) = G_CONCAT_VECTORS [[BITCAST]](<2 x p0>), [[BITCAST1]](<2 x p0>)
|
||||
; CHECK-NEXT: [[CONCAT_VECTORS:%[0-9]+]]:_(<4 x p0>) = G_CONCAT_VECTORS [[COPY]](<2 x s64>), [[COPY1]](<2 x s64>)
|
||||
; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(<4 x s32>) = COPY $q2
|
||||
; CHECK-NEXT: [[SEXT:%[0-9]+]]:_(<4 x s64>) = G_SEXT [[COPY2]](<4 x s32>)
|
||||
; CHECK-NEXT: [[PTR_ADD:%[0-9]+]]:_(<4 x p0>) = G_PTR_ADD [[CONCAT_VECTORS]], [[SEXT]](<4 x s64>)
|
||||
|
||||
@ -20,11 +20,7 @@ define void @formal_argument_mix_sve(
|
||||
; CHECK-NEXT: [[COPY5:%[0-9]+]]:_(<vscale x 2 x s64>) = COPY $z5
|
||||
; CHECK-NEXT: [[COPY6:%[0-9]+]]:_(<vscale x 2 x s64>) = COPY $z6
|
||||
; CHECK-NEXT: [[COPY7:%[0-9]+]]:_(<vscale x 2 x s64>) = COPY $z7
|
||||
; CHECK-NEXT: [[BITCAST:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY4]](<vscale x 2 x s64>)
|
||||
; CHECK-NEXT: [[BITCAST1:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY5]](<vscale x 2 x s64>)
|
||||
; CHECK-NEXT: [[BITCAST2:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY6]](<vscale x 2 x s64>)
|
||||
; CHECK-NEXT: [[BITCAST3:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY7]](<vscale x 2 x s64>)
|
||||
; CHECK-NEXT: [[CONCAT_VECTORS1:%[0-9]+]]:_(<vscale x 8 x p0>) = G_CONCAT_VECTORS [[BITCAST]](<vscale x 2 x p0>), [[BITCAST1]](<vscale x 2 x p0>), [[BITCAST2]](<vscale x 2 x p0>), [[BITCAST3]](<vscale x 2 x p0>)
|
||||
; CHECK-NEXT: [[CONCAT_VECTORS1:%[0-9]+]]:_(<vscale x 8 x p0>) = G_CONCAT_VECTORS [[COPY4]](<vscale x 2 x s64>), [[COPY5]](<vscale x 2 x s64>), [[COPY6]](<vscale x 2 x s64>), [[COPY7]](<vscale x 2 x s64>)
|
||||
; CHECK-NEXT: RET_ReallyLR
|
||||
<vscale x 8 x i16> %0, <vscale x 8 x float> %1, <vscale x 16 x i8> %2, <vscale x 8 x ptr> %3
|
||||
) {
|
||||
@ -194,24 +190,16 @@ define void @formal_argument_nxv4p0_4(<vscale x 4 x ptr> %0, <vscale x 4 x ptr>
|
||||
; CHECK-NEXT: {{ $}}
|
||||
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(<vscale x 2 x s64>) = COPY $z0
|
||||
; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(<vscale x 2 x s64>) = COPY $z1
|
||||
; CHECK-NEXT: [[BITCAST:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY]](<vscale x 2 x s64>)
|
||||
; CHECK-NEXT: [[BITCAST1:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY1]](<vscale x 2 x s64>)
|
||||
; CHECK-NEXT: [[CONCAT_VECTORS:%[0-9]+]]:_(<vscale x 4 x p0>) = G_CONCAT_VECTORS [[BITCAST]](<vscale x 2 x p0>), [[BITCAST1]](<vscale x 2 x p0>)
|
||||
; CHECK-NEXT: [[CONCAT_VECTORS:%[0-9]+]]:_(<vscale x 4 x p0>) = G_CONCAT_VECTORS [[COPY]](<vscale x 2 x s64>), [[COPY1]](<vscale x 2 x s64>)
|
||||
; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(<vscale x 2 x s64>) = COPY $z2
|
||||
; CHECK-NEXT: [[COPY3:%[0-9]+]]:_(<vscale x 2 x s64>) = COPY $z3
|
||||
; CHECK-NEXT: [[BITCAST2:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY2]](<vscale x 2 x s64>)
|
||||
; CHECK-NEXT: [[BITCAST3:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY3]](<vscale x 2 x s64>)
|
||||
; CHECK-NEXT: [[CONCAT_VECTORS1:%[0-9]+]]:_(<vscale x 4 x p0>) = G_CONCAT_VECTORS [[BITCAST2]](<vscale x 2 x p0>), [[BITCAST3]](<vscale x 2 x p0>)
|
||||
; CHECK-NEXT: [[CONCAT_VECTORS1:%[0-9]+]]:_(<vscale x 4 x p0>) = G_CONCAT_VECTORS [[COPY2]](<vscale x 2 x s64>), [[COPY3]](<vscale x 2 x s64>)
|
||||
; CHECK-NEXT: [[COPY4:%[0-9]+]]:_(<vscale x 2 x s64>) = COPY $z4
|
||||
; CHECK-NEXT: [[COPY5:%[0-9]+]]:_(<vscale x 2 x s64>) = COPY $z5
|
||||
; CHECK-NEXT: [[BITCAST4:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY4]](<vscale x 2 x s64>)
|
||||
; CHECK-NEXT: [[BITCAST5:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY5]](<vscale x 2 x s64>)
|
||||
; CHECK-NEXT: [[CONCAT_VECTORS2:%[0-9]+]]:_(<vscale x 4 x p0>) = G_CONCAT_VECTORS [[BITCAST4]](<vscale x 2 x p0>), [[BITCAST5]](<vscale x 2 x p0>)
|
||||
; CHECK-NEXT: [[CONCAT_VECTORS2:%[0-9]+]]:_(<vscale x 4 x p0>) = G_CONCAT_VECTORS [[COPY4]](<vscale x 2 x s64>), [[COPY5]](<vscale x 2 x s64>)
|
||||
; CHECK-NEXT: [[COPY6:%[0-9]+]]:_(<vscale x 2 x s64>) = COPY $z6
|
||||
; CHECK-NEXT: [[COPY7:%[0-9]+]]:_(<vscale x 2 x s64>) = COPY $z7
|
||||
; CHECK-NEXT: [[BITCAST6:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY6]](<vscale x 2 x s64>)
|
||||
; CHECK-NEXT: [[BITCAST7:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY7]](<vscale x 2 x s64>)
|
||||
; CHECK-NEXT: [[CONCAT_VECTORS3:%[0-9]+]]:_(<vscale x 4 x p0>) = G_CONCAT_VECTORS [[BITCAST6]](<vscale x 2 x p0>), [[BITCAST7]](<vscale x 2 x p0>)
|
||||
; CHECK-NEXT: [[CONCAT_VECTORS3:%[0-9]+]]:_(<vscale x 4 x p0>) = G_CONCAT_VECTORS [[COPY6]](<vscale x 2 x s64>), [[COPY7]](<vscale x 2 x s64>)
|
||||
; CHECK-NEXT: RET_ReallyLR
|
||||
ret void
|
||||
}
|
||||
@ -326,20 +314,12 @@ define void @formal_argument_nxv8p0_2(<vscale x 8 x ptr> %0, <vscale x 8 x ptr>
|
||||
; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(<vscale x 2 x s64>) = COPY $z1
|
||||
; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(<vscale x 2 x s64>) = COPY $z2
|
||||
; CHECK-NEXT: [[COPY3:%[0-9]+]]:_(<vscale x 2 x s64>) = COPY $z3
|
||||
; CHECK-NEXT: [[BITCAST:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY]](<vscale x 2 x s64>)
|
||||
; CHECK-NEXT: [[BITCAST1:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY1]](<vscale x 2 x s64>)
|
||||
; CHECK-NEXT: [[BITCAST2:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY2]](<vscale x 2 x s64>)
|
||||
; CHECK-NEXT: [[BITCAST3:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY3]](<vscale x 2 x s64>)
|
||||
; CHECK-NEXT: [[CONCAT_VECTORS:%[0-9]+]]:_(<vscale x 8 x p0>) = G_CONCAT_VECTORS [[BITCAST]](<vscale x 2 x p0>), [[BITCAST1]](<vscale x 2 x p0>), [[BITCAST2]](<vscale x 2 x p0>), [[BITCAST3]](<vscale x 2 x p0>)
|
||||
; CHECK-NEXT: [[CONCAT_VECTORS:%[0-9]+]]:_(<vscale x 8 x p0>) = G_CONCAT_VECTORS [[COPY]](<vscale x 2 x s64>), [[COPY1]](<vscale x 2 x s64>), [[COPY2]](<vscale x 2 x s64>), [[COPY3]](<vscale x 2 x s64>)
|
||||
; CHECK-NEXT: [[COPY4:%[0-9]+]]:_(<vscale x 2 x s64>) = COPY $z4
|
||||
; CHECK-NEXT: [[COPY5:%[0-9]+]]:_(<vscale x 2 x s64>) = COPY $z5
|
||||
; CHECK-NEXT: [[COPY6:%[0-9]+]]:_(<vscale x 2 x s64>) = COPY $z6
|
||||
; CHECK-NEXT: [[COPY7:%[0-9]+]]:_(<vscale x 2 x s64>) = COPY $z7
|
||||
; CHECK-NEXT: [[BITCAST4:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY4]](<vscale x 2 x s64>)
|
||||
; CHECK-NEXT: [[BITCAST5:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY5]](<vscale x 2 x s64>)
|
||||
; CHECK-NEXT: [[BITCAST6:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY6]](<vscale x 2 x s64>)
|
||||
; CHECK-NEXT: [[BITCAST7:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY7]](<vscale x 2 x s64>)
|
||||
; CHECK-NEXT: [[CONCAT_VECTORS1:%[0-9]+]]:_(<vscale x 8 x p0>) = G_CONCAT_VECTORS [[BITCAST4]](<vscale x 2 x p0>), [[BITCAST5]](<vscale x 2 x p0>), [[BITCAST6]](<vscale x 2 x p0>), [[BITCAST7]](<vscale x 2 x p0>)
|
||||
; CHECK-NEXT: [[CONCAT_VECTORS1:%[0-9]+]]:_(<vscale x 8 x p0>) = G_CONCAT_VECTORS [[COPY4]](<vscale x 2 x s64>), [[COPY5]](<vscale x 2 x s64>), [[COPY6]](<vscale x 2 x s64>), [[COPY7]](<vscale x 2 x s64>)
|
||||
; CHECK-NEXT: RET_ReallyLR
|
||||
ret void
|
||||
}
|
||||
@ -456,15 +436,7 @@ define void @formal_argument_nxv16p0_1(<vscale x 16 x ptr> %0) {
|
||||
; CHECK-NEXT: [[COPY5:%[0-9]+]]:_(<vscale x 2 x s64>) = COPY $z5
|
||||
; CHECK-NEXT: [[COPY6:%[0-9]+]]:_(<vscale x 2 x s64>) = COPY $z6
|
||||
; CHECK-NEXT: [[COPY7:%[0-9]+]]:_(<vscale x 2 x s64>) = COPY $z7
|
||||
; CHECK-NEXT: [[BITCAST:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY]](<vscale x 2 x s64>)
|
||||
; CHECK-NEXT: [[BITCAST1:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY1]](<vscale x 2 x s64>)
|
||||
; CHECK-NEXT: [[BITCAST2:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY2]](<vscale x 2 x s64>)
|
||||
; CHECK-NEXT: [[BITCAST3:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY3]](<vscale x 2 x s64>)
|
||||
; CHECK-NEXT: [[BITCAST4:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY4]](<vscale x 2 x s64>)
|
||||
; CHECK-NEXT: [[BITCAST5:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY5]](<vscale x 2 x s64>)
|
||||
; CHECK-NEXT: [[BITCAST6:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY6]](<vscale x 2 x s64>)
|
||||
; CHECK-NEXT: [[BITCAST7:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY7]](<vscale x 2 x s64>)
|
||||
; CHECK-NEXT: [[CONCAT_VECTORS:%[0-9]+]]:_(<vscale x 16 x p0>) = G_CONCAT_VECTORS [[BITCAST]](<vscale x 2 x p0>), [[BITCAST1]](<vscale x 2 x p0>), [[BITCAST2]](<vscale x 2 x p0>), [[BITCAST3]](<vscale x 2 x p0>), [[BITCAST4]](<vscale x 2 x p0>), [[BITCAST5]](<vscale x 2 x p0>), [[BITCAST6]](<vscale x 2 x p0>), [[BITCAST7]](<vscale x 2 x p0>)
|
||||
; CHECK-NEXT: [[CONCAT_VECTORS:%[0-9]+]]:_(<vscale x 16 x p0>) = G_CONCAT_VECTORS [[COPY]](<vscale x 2 x s64>), [[COPY1]](<vscale x 2 x s64>), [[COPY2]](<vscale x 2 x s64>), [[COPY3]](<vscale x 2 x s64>), [[COPY4]](<vscale x 2 x s64>), [[COPY5]](<vscale x 2 x s64>), [[COPY6]](<vscale x 2 x s64>), [[COPY7]](<vscale x 2 x s64>)
|
||||
; CHECK-NEXT: RET_ReallyLR
|
||||
ret void
|
||||
}
|
||||
|
||||
@ -155,9 +155,7 @@ define void @formal_argument_nxv4p0(<vscale x 4 x ptr> %0) {
|
||||
; CHECK-NEXT: {{ $}}
|
||||
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(<vscale x 2 x s64>) = COPY $z0
|
||||
; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(<vscale x 2 x s64>) = COPY $z1
|
||||
; CHECK-NEXT: [[BITCAST:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY]](<vscale x 2 x s64>)
|
||||
; CHECK-NEXT: [[BITCAST1:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY1]](<vscale x 2 x s64>)
|
||||
; CHECK-NEXT: [[CONCAT_VECTORS:%[0-9]+]]:_(<vscale x 4 x p0>) = G_CONCAT_VECTORS [[BITCAST]](<vscale x 2 x p0>), [[BITCAST1]](<vscale x 2 x p0>)
|
||||
; CHECK-NEXT: [[CONCAT_VECTORS:%[0-9]+]]:_(<vscale x 4 x p0>) = G_CONCAT_VECTORS [[COPY]](<vscale x 2 x s64>), [[COPY1]](<vscale x 2 x s64>)
|
||||
; CHECK-NEXT: RET_ReallyLR
|
||||
ret void
|
||||
}
|
||||
@ -257,11 +255,7 @@ define void @formal_argument_nxv8p0(<vscale x 8 x ptr> %0) {
|
||||
; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(<vscale x 2 x s64>) = COPY $z1
|
||||
; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(<vscale x 2 x s64>) = COPY $z2
|
||||
; CHECK-NEXT: [[COPY3:%[0-9]+]]:_(<vscale x 2 x s64>) = COPY $z3
|
||||
; CHECK-NEXT: [[BITCAST:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY]](<vscale x 2 x s64>)
|
||||
; CHECK-NEXT: [[BITCAST1:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY1]](<vscale x 2 x s64>)
|
||||
; CHECK-NEXT: [[BITCAST2:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY2]](<vscale x 2 x s64>)
|
||||
; CHECK-NEXT: [[BITCAST3:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY3]](<vscale x 2 x s64>)
|
||||
; CHECK-NEXT: [[CONCAT_VECTORS:%[0-9]+]]:_(<vscale x 8 x p0>) = G_CONCAT_VECTORS [[BITCAST]](<vscale x 2 x p0>), [[BITCAST1]](<vscale x 2 x p0>), [[BITCAST2]](<vscale x 2 x p0>), [[BITCAST3]](<vscale x 2 x p0>)
|
||||
; CHECK-NEXT: [[CONCAT_VECTORS:%[0-9]+]]:_(<vscale x 8 x p0>) = G_CONCAT_VECTORS [[COPY]](<vscale x 2 x s64>), [[COPY1]](<vscale x 2 x s64>), [[COPY2]](<vscale x 2 x s64>), [[COPY3]](<vscale x 2 x s64>)
|
||||
; CHECK-NEXT: RET_ReallyLR
|
||||
ret void
|
||||
}
|
||||
@ -389,15 +383,7 @@ define void @formal_argument_nxv16p0(<vscale x 16 x ptr> %0) {
|
||||
; CHECK-NEXT: [[COPY5:%[0-9]+]]:_(<vscale x 2 x s64>) = COPY $z5
|
||||
; CHECK-NEXT: [[COPY6:%[0-9]+]]:_(<vscale x 2 x s64>) = COPY $z6
|
||||
; CHECK-NEXT: [[COPY7:%[0-9]+]]:_(<vscale x 2 x s64>) = COPY $z7
|
||||
; CHECK-NEXT: [[BITCAST:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY]](<vscale x 2 x s64>)
|
||||
; CHECK-NEXT: [[BITCAST1:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY1]](<vscale x 2 x s64>)
|
||||
; CHECK-NEXT: [[BITCAST2:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY2]](<vscale x 2 x s64>)
|
||||
; CHECK-NEXT: [[BITCAST3:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY3]](<vscale x 2 x s64>)
|
||||
; CHECK-NEXT: [[BITCAST4:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY4]](<vscale x 2 x s64>)
|
||||
; CHECK-NEXT: [[BITCAST5:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY5]](<vscale x 2 x s64>)
|
||||
; CHECK-NEXT: [[BITCAST6:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY6]](<vscale x 2 x s64>)
|
||||
; CHECK-NEXT: [[BITCAST7:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY7]](<vscale x 2 x s64>)
|
||||
; CHECK-NEXT: [[CONCAT_VECTORS:%[0-9]+]]:_(<vscale x 16 x p0>) = G_CONCAT_VECTORS [[BITCAST]](<vscale x 2 x p0>), [[BITCAST1]](<vscale x 2 x p0>), [[BITCAST2]](<vscale x 2 x p0>), [[BITCAST3]](<vscale x 2 x p0>), [[BITCAST4]](<vscale x 2 x p0>), [[BITCAST5]](<vscale x 2 x p0>), [[BITCAST6]](<vscale x 2 x p0>), [[BITCAST7]](<vscale x 2 x p0>)
|
||||
; CHECK-NEXT: [[CONCAT_VECTORS:%[0-9]+]]:_(<vscale x 16 x p0>) = G_CONCAT_VECTORS [[COPY]](<vscale x 2 x s64>), [[COPY1]](<vscale x 2 x s64>), [[COPY2]](<vscale x 2 x s64>), [[COPY3]](<vscale x 2 x s64>), [[COPY4]](<vscale x 2 x s64>), [[COPY5]](<vscale x 2 x s64>), [[COPY6]](<vscale x 2 x s64>), [[COPY7]](<vscale x 2 x s64>)
|
||||
; CHECK-NEXT: RET_ReallyLR
|
||||
ret void
|
||||
}
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
# RUN: not llc -mtriple=aarch64-- -run-pass none -o /dev/null %s 2>&1 | FileCheck %s
|
||||
# When a low-level type is only a single 's'/'i'/'f'/'bf'/'p' type identifier
|
||||
# When a low-level type is only a single 's'/'p' character
|
||||
---
|
||||
name: test_low_level_type_is_single_s_p
|
||||
body: |
|
||||
bb.0:
|
||||
liveins: $x0
|
||||
; CHECK: [[@LINE+1]]:10: expected integers after 's'/'i'/'f'/'bf'/'p' type identifier
|
||||
; CHECK: [[@LINE+1]]:10: expected integers after 's'/'p' type character
|
||||
%0:_(s) = COPY $x0
|
||||
...
|
||||
|
||||
@ -5,6 +5,6 @@ name: test_low_level_type_does_not_start_with_s_p_lt
|
||||
body: |
|
||||
bb.0:
|
||||
liveins: $x0
|
||||
; CHECK: [[@LINE+1]]:10: expected tN, pA, <M x tN>, <M x pA>, <vscale x M x tN>, or <vscale x M x pA> for GlobalISel type, where t = {'s', 'i', 'f', 'bf'}
|
||||
%0:_(n64) = COPY $x0
|
||||
; CHECK: [[@LINE+1]]:10: expected sN, pA, <M x sN>, <M x pA>, <vscale x M x sN>, or <vscale x M x pA> for GlobalISel type
|
||||
%0:_(i64) = COPY $x0
|
||||
...
|
||||
|
||||
@ -5,6 +5,6 @@ name: test_low_level_type_is_single_s_p
|
||||
body: |
|
||||
bb.0:
|
||||
liveins: $q0
|
||||
; CHECK: [[@LINE+1]]:15: expected integers after 's'/'i'/'f'/'bf'/'p' type identifier
|
||||
; CHECK: [[@LINE+1]]:15: expected integers after 's'/'p' type character
|
||||
%0:_(<2 x p>) = COPY $q0
|
||||
...
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
# RUN: not llc -mtriple=aarch64-- -run-pass none -o /dev/null %s 2>&1 | FileCheck %s
|
||||
# When a low-level type is a vector which element type does not start with right type identifier
|
||||
# When a low-level type is a vector which element type does not start with 's' or 'p'
|
||||
---
|
||||
name: test_low_level_type_does_not_start_with_s_p
|
||||
body: |
|
||||
bb.0:
|
||||
liveins: $q0
|
||||
; CHECK: [[@LINE+1]]:10: expected <M x tN> for vector type, where t = {'s', 'i', 'f', 'bf', 'p'}
|
||||
%0:_(<2 x n64>) = COPY $q0
|
||||
; CHECK: [[@LINE+1]]:10: expected <M x sN> or <M x pA> for vector type
|
||||
%0:_(<2 x i64>) = COPY $q0
|
||||
...
|
||||
|
||||
@ -6,5 +6,5 @@ body: |
|
||||
%0:_(<vscale) = IMPLICIT_DEF
|
||||
...
|
||||
|
||||
# CHECK: expected <vscale x M x tN>, where t = {'s', 'i', 'f', 'bf', 'p'}
|
||||
# CHECK: expected <vscale x M x sN> or <vscale x M x pA>
|
||||
|
||||
|
||||
@ -6,4 +6,4 @@ body: |
|
||||
%0:_(<vscale notanx) = IMPLICIT_DEF
|
||||
...
|
||||
|
||||
# CHECK: expected <vscale x M x tN>, where t = {'s', 'i', 'f', 'bf', 'p'}
|
||||
# CHECK: expected <vscale x M x sN> or <vscale x M x pA>
|
||||
|
||||
@ -7,4 +7,4 @@ body: |
|
||||
%0:_(<vscale x 4 x p) = IMPLICIT_DEF
|
||||
...
|
||||
|
||||
# CHECK: expected integers after 's'/'i'/'f'/'bf'/'p' type identifier
|
||||
# CHECK: expected integers after 's'/'p' type character
|
||||
|
||||
@ -7,4 +7,4 @@ body: |
|
||||
%0:_(<vscale x 4 x s32) = IMPLICIT_DEF
|
||||
...
|
||||
|
||||
# CHECK: expected <vscale x M x tN> for vector type, where t = {'s', 'i', 'f', 'bf', 'p'}
|
||||
# CHECK: expected <vscale x M x sN> or <vscale M x pA> for vector type
|
||||
|
||||
@ -7,4 +7,4 @@ body: |
|
||||
%0:_(<vscale x 4 x p0) = IMPLICIT_DEF
|
||||
...
|
||||
|
||||
# CHECK: expected <vscale x M x tN> for vector type, where t = {'s', 'i', 'f', 'bf', 'p'}
|
||||
# CHECK: expected <vscale x M x sN> or <vscale M x pA> for vector type
|
||||
|
||||
@ -7,4 +7,4 @@ body: |
|
||||
%0:_(<vscale x 4 x s32 X) = IMPLICIT_DEF
|
||||
...
|
||||
|
||||
# CHECK: expected <vscale x M x tN> for vector type, where t = {'s', 'i', 'f', 'bf', 'p'}
|
||||
# CHECK: expected <vscale x M x sN> or <vscale M x pA> for vector type
|
||||
|
||||
@ -7,4 +7,4 @@ body: |
|
||||
%0:_(<vscale x 4 x p0 X) = IMPLICIT_DEF
|
||||
...
|
||||
|
||||
# CHECK: expected <vscale x M x tN> for vector type, where t = {'s', 'i', 'f', 'bf', 'p'}
|
||||
# CHECK: expected <vscale x M x sN> or <vscale M x pA> for vector type
|
||||
|
||||
@ -7,4 +7,4 @@ body: |
|
||||
%0:_(notatype) = IMPLICIT_DEF
|
||||
...
|
||||
|
||||
# CHECK: expected tN, pA, <M x tN>, <M x pA>, <vscale x M x tN>, or <vscale x M x pA> for GlobalISel type, where t = {'s', 'i', 'f', 'bf'}
|
||||
# CHECK: expected sN, pA, <M x sN>, <M x pA>, <vscale x M x sN>, or <vscale x M x pA> for GlobalISel type
|
||||
|
||||
@ -6,4 +6,4 @@ body: |
|
||||
%0:_(<vscale x) = IMPLICIT_DEF
|
||||
...
|
||||
|
||||
# CHECK: expected <vscale x M x tN> for vector type, where t = {'s', 'i', 'f', 'bf', 'p'}
|
||||
# CHECK: expected <vscale x M x sN> or <vscale M x pA> for vector type
|
||||
|
||||
@ -6,4 +6,4 @@ body: |
|
||||
%0:_(<vscale x) = IMPLICIT_DEF
|
||||
...
|
||||
|
||||
# CHECK: expected <vscale x M x tN> for vector type, where t = {'s', 'i', 'f', 'bf', 'p'}
|
||||
# CHECK: expected <vscale x M x sN> or <vscale M x pA> for vector type
|
||||
|
||||
@ -6,5 +6,5 @@ body: |
|
||||
%0:_(<vscale x notanint) = IMPLICIT_DEF
|
||||
...
|
||||
|
||||
# CHECK: expected <vscale x M x tN> for vector type, where t = {'s', 'i', 'f', 'bf', 'p'}
|
||||
# CHECK: expected <vscale x M x sN> or <vscale M x pA> for vector type
|
||||
|
||||
|
||||
@ -6,4 +6,4 @@ body: |
|
||||
%0:_(<vscale x 4) = IMPLICIT_DEF
|
||||
...
|
||||
|
||||
# CHECK: expected <vscale x M x tN> for vector type, where t = {'s', 'i', 'f', 'bf', 'p'}
|
||||
# CHECK: expected <vscale x M x sN> or <vscale M x pA> for vector type
|
||||
|
||||
@ -7,5 +7,5 @@ body: |
|
||||
%0:_(<vscale x 4 x) = IMPLICIT_DEF
|
||||
...
|
||||
|
||||
# CHECK: expected <vscale x M x tN> for vector type, where t = {'s', 'i', 'f', 'bf', 'p'}
|
||||
# CHECK: expected <vscale x M x sN> or <vscale M x pA> for vector type
|
||||
|
||||
|
||||
@ -6,4 +6,4 @@ body: |
|
||||
%0:_(<vscale x 4 x notansorp) = IMPLICIT_DEF
|
||||
...
|
||||
|
||||
# CHECK: expected <vscale x M x tN> for vector type, where t = {'s', 'i', 'f', 'bf', 'p'}
|
||||
# CHECK: expected <vscale x M x sN> or <vscale M x pA> for vector type
|
||||
|
||||
@ -7,4 +7,4 @@ body: |
|
||||
%0:_(<vscale x 4 x s) = IMPLICIT_DEF
|
||||
...
|
||||
|
||||
# CHECK: expected integers after 's'/'i'/'f'/'bf'/'p' type identifier
|
||||
# CHECK: expected integers after 's'/'p' type character
|
||||
|
||||
@ -6,6 +6,6 @@ body: |
|
||||
%0:_(<vscale x 4 x pX) = IMPLICIT_DEF
|
||||
...
|
||||
|
||||
# CHECK: expected integers after 's'/'i'/'f'/'bf'/'p' type identifier
|
||||
# CHECK: expected integers after 's'/'p' type character
|
||||
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
# RUN: not llc -mtriple=wasm32-unknown-unknown -run-pass none -o /dev/null %s 2>&1 | FileCheck %s
|
||||
# When a typed immediate operand is only a single type character
|
||||
# When a typed immediate operand is only a single 'i'/'s'/'p' character
|
||||
---
|
||||
name: test_typed_immediate_operand_invalid0
|
||||
liveins:
|
||||
@ -7,7 +7,7 @@ liveins:
|
||||
body: |
|
||||
bb.0:
|
||||
liveins: $arguments
|
||||
; CHECK: [[@LINE+1]]:24: expected integers after 'i'/'s'/'f'/'bf'/'p' type identifier
|
||||
; CHECK: [[@LINE+1]]:24: expected integers after 'i'/'s'/'p' type character
|
||||
%0:i32 = CONST_I32 i 0, implicit-def dead $arguments
|
||||
RETURN implicit-def dead $arguments
|
||||
...
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
# RUN: not llc -mtriple=wasm32-unknown-unknown -run-pass none -o /dev/null %s 2>&1 | FileCheck %s
|
||||
# When a typed immediate operand does not start with right type identifier
|
||||
# When a typed immediate operand does not start with 'i', 's', or 'p'
|
||||
---
|
||||
name: test_typed_immediate_operand_invalid1
|
||||
liveins:
|
||||
@ -7,7 +7,7 @@ liveins:
|
||||
body: |
|
||||
bb.0:
|
||||
liveins: $arguments
|
||||
; CHECK: [[@LINE+1]]:24: a typed immediate operand should start with one of 'i', 's', 'f', 'bf', or 'p'
|
||||
; CHECK: [[@LINE+1]]:24: a typed immediate operand should start with one of 'i', 's', or 'p'
|
||||
%0:i32 = CONST_I32 abc 0, implicit-def dead $arguments
|
||||
RETURN implicit-def dead $arguments
|
||||
...
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
// RUN: llvm-tblgen -gen-global-isel -I %p/../../../include -I %p/../Common -optimize-match-table=false %s -o %t.non-optimized.cpp
|
||||
// RUN: llvm-tblgen -gen-global-isel -I %p/../../../include -I %p/../Common -optimize-match-table=true %s -o %t.optimized.cpp
|
||||
// RUN: llvm-tblgen -gen-global-isel -I %p/../../../include -I %p/../Common %s -o %t.default.cpp
|
||||
// RUN: llvm-tblgen -gen-global-isel -I %p/../../../include -I %p/../Common -gisel-extended-llt %s -o %t.extended-llt.cpp
|
||||
|
||||
// RUN: FileCheck %s --check-prefixes=CHECK,R19C,R19N -input-file=%t.non-optimized.cpp
|
||||
// RUN: FileCheck %s --check-prefixes=CHECK,R19C,R19O -input-file=%t.optimized.cpp
|
||||
@ -20,7 +19,6 @@
|
||||
|
||||
// RUN: FileCheck %s --check-prefixes=CHECK,R02C,R02N,NOOPT -input-file=%t.non-optimized.cpp
|
||||
// RUN: FileCheck %s --check-prefixes=CHECK,R02C,R02O -input-file=%t.optimized.cpp
|
||||
// RUN: FileCheck %s --check-prefixes=EXTENDED -input-file=%t.extended-llt.cpp
|
||||
|
||||
// RUN: diff %t.default.cpp %t.optimized.cpp
|
||||
|
||||
@ -100,28 +98,15 @@ def HasC : Predicate<"Subtarget->hasC()"> { let RecomputePerFunction = 1; }
|
||||
|
||||
// CHECK-LABEL: // LLT Objects.
|
||||
// CHECK-NEXT: enum {
|
||||
// CHECK-NEXT: GILLT_p0s32
|
||||
// CHECK-NEXT: GILLT_s32,
|
||||
// CHECK-NEXT: GILLT_p0s32,
|
||||
// CHECK-NEXT: };
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: const static size_t NumTypeObjects = 2;
|
||||
// CHECK-NEXT: const static LLT TypeObjects[] = {
|
||||
// CHECK-NEXT: LLT::scalar(32),
|
||||
// CHECK-NEXT: LLT::pointer(0, 32),
|
||||
// CHECK-NEXT: LLT::scalar(32),
|
||||
// CHECK-NEXT: };
|
||||
|
||||
// EXTENDED-LABEL: // LLT Objects.
|
||||
// EXTENDED-NEXT: enum {
|
||||
// EXTENDED-NEXT: GILLT_i32,
|
||||
// EXTENDED-NEXT: GILLT_f32,
|
||||
// EXTENDED-NEXT: GILLT_p0s32,
|
||||
// EXTENDED-NEXT: };
|
||||
// EXTENDED-NEXT: const static size_t NumTypeObjects = 3;
|
||||
// EXTENDED-NEXT: const static LLT TypeObjects[] = {
|
||||
// EXTENDED-NEXT: LLT::integer(32),
|
||||
// EXTENDED-NEXT: LLT::floatIEEE(32),
|
||||
// EXTENDED-NEXT: LLT::pointer(0, 32),
|
||||
// EXTENDED-NEXT: };
|
||||
|
||||
// CHECK-LABEL: enum SubtargetFeatureBits : uint8_t {
|
||||
// CHECK-NEXT: Feature_HasABit = 0,
|
||||
// CHECK-NEXT: Feature_HasBBit = 1,
|
||||
@ -271,10 +256,6 @@ def HasC : Predicate<"Subtarget->hasC()"> { let RecomputePerFunction = 1; }
|
||||
// CHECK-LABEL: MyTargetInstructionSelector::getMatchTable() const {
|
||||
// CHECK-NEXT: MatchTable0[] = {
|
||||
|
||||
// EXTENDED: const uint8_t *
|
||||
// EXTENDED-LABEL: MyTargetInstructionSelector::getMatchTable() const {
|
||||
// EXTENDED-NEXT: MatchTable0[] = {
|
||||
|
||||
//===- Test a pattern with multiple ComplexPatterns in multiple instrs ----===//
|
||||
//
|
||||
// R19O-NEXT: GIM_SwitchOpcode, /*MI*/0, /*[*/GIMT_Encode2({{[0-9]+}}), GIMT_Encode2({{[0-9]+}}), /*)*//*default:*//*Label [[DEFAULT_NUM:[0-9]+]]*/ GIMT_Encode4([[DEFAULT:[0-9]+]]),
|
||||
@ -352,17 +333,6 @@ def HasC : Predicate<"Subtarget->hasC()"> { let RecomputePerFunction = 1; }
|
||||
// R19O: // Label [[DEFAULT_NUM]]: @[[DEFAULT]]
|
||||
// R19O-NEXT: GIM_Reject,
|
||||
// R19O-NEXT: };
|
||||
//
|
||||
// EXTENDED-NEXT: GIM_SwitchOpcode, /*MI*/0, /*[*/GIMT_Encode2({{[0-9]+}}), GIMT_Encode2({{[0-9]+}}), /*)*//*default:*//*Label [[DEFAULT_NUM:[0-9]+]]*/ GIMT_Encode4([[DEFAULT:[0-9]+]]),
|
||||
// EXTENDED-NEXT: /*TargetOpcode::G_ADD*//*Label [[CASE_ADD_NUM:[0-9]+]]*/ GIMT_Encode4([[CASE_ADD:[0-9]+]]),
|
||||
// EXTENDED: /*TargetOpcode::G_SELECT*//*Label [[CASE_SELECT_NUM:[0-9]+]]*/ GIMT_Encode4([[CASE_SELECT:[0-9]+]]),
|
||||
// EXTENDED: // Label [[CASE_ADD_NUM]]: @[[CASE_ADD]]
|
||||
// EXTENDED: // Label [[CASE_SELECT_NUM]]: @[[CASE_SELECT]]
|
||||
// EXTENDED-NEXT: GIM_Try, /*On fail goto*//*Label [[GROUP_NUM:[0-9]+]]*/ GIMT_Encode4([[GROUP:[0-9]+]]),
|
||||
// EXTENDED-NEXT: GIM_RootCheckType, /*Op*/0, /*Type*/GILLT_i32,
|
||||
// EXTENDED-NEXT: GIM_RootCheckType, /*Op*/1, /*Type*/GILLT_i32,
|
||||
// EXTENDED-NEXT: GIM_RootCheckType, /*Op*/2, /*Type*/GILLT_i32,
|
||||
// EXTENDED-NEXT: GIM_RootCheckType, /*Op*/3, /*Type*/GILLT_i32,
|
||||
|
||||
def INSN3 : I<(outs GPR32:$dst),
|
||||
(ins GPR32Op:$src1, GPR32:$src2a, GPR32:$src2b, GPR32:$scr), []>;
|
||||
|
||||
@ -70,17 +70,17 @@ class I<dag OOps, dag IOps, list<dag> Pat>
|
||||
|
||||
// CHECK-LABEL: // LLT Objects.
|
||||
// CHECK-NEXT: enum {
|
||||
// CHECK-NEXT: GILLT_s32,
|
||||
// CHECK-NEXT: GILLT_s64,
|
||||
// CHECK-NEXT: GILLT_p0s32,
|
||||
// CHECK-NEXT: GILLT_p0s64,
|
||||
// CHECK-NEXT: };
|
||||
// CHECK-NEXT: GILLT_s32,
|
||||
// CHECK-NEXT: GILLT_s64,
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: const static size_t NumTypeObjects = 4;
|
||||
// CHECK-NEXT: const static LLT TypeObjects[] = {
|
||||
// CHECK-NEXT: LLT::scalar(32),
|
||||
// CHECK-NEXT: LLT::scalar(64),
|
||||
// CHECK-NEXT: LLT::pointer(0, 32),
|
||||
// CHECK-NEXT: LLT::pointer(0, 64),
|
||||
// CHECK-NEXT: LLT::scalar(32),
|
||||
// CHECK-NEXT: LLT::scalar(64),
|
||||
// CHECK-NEXT: };
|
||||
|
||||
// CHECK-LABEL: enum SubtargetFeatureBits : uint8_t {
|
||||
|
||||
@ -14,7 +14,6 @@ set(LLVM_LINK_COMPONENTS
|
||||
)
|
||||
|
||||
add_llvm_unittest(GlobalISelTests
|
||||
IRTranslatorBF16Test.cpp
|
||||
ConstantFoldingTest.cpp
|
||||
CSETest.cpp
|
||||
GIMatchTableExecutorTest.cpp
|
||||
|
||||
@ -1,135 +0,0 @@
|
||||
//===- IRTranslator.cpp - IRTranslator unit tests -------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/AsmParser/Parser.h"
|
||||
#include "llvm/CodeGen/GlobalISel/IRTranslator.h"
|
||||
#include "llvm/CodeGen/MachineFunction.h"
|
||||
#include "llvm/CodeGen/MachineModuleInfo.h"
|
||||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||
#include "llvm/CodeGen/TargetFrameLowering.h"
|
||||
#include "llvm/CodeGen/TargetInstrInfo.h"
|
||||
#include "llvm/CodeGen/TargetOpcodes.h"
|
||||
#include "llvm/CodeGen/TargetPassConfig.h"
|
||||
#include "llvm/IR/LLVMContext.h"
|
||||
#include "llvm/IR/LegacyPassManager.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
#include "llvm/InitializePasses.h"
|
||||
#include "llvm/MC/TargetRegistry.h"
|
||||
#include "llvm/Support/SourceMgr.h"
|
||||
#include "llvm/Support/TargetSelect.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
#include "llvm/Target/TargetOptions.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include <memory>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace {
|
||||
struct AArch64IRTranslatorTest : public ::testing::Test {
|
||||
LLVMContext C;
|
||||
|
||||
public:
|
||||
AArch64IRTranslatorTest() {}
|
||||
std::unique_ptr<TargetMachine> createTargetMachine() const {
|
||||
Triple TargetTriple("aarch64--");
|
||||
std::string Error;
|
||||
const Target *T = TargetRegistry::lookupTarget("", TargetTriple, Error);
|
||||
if (!T)
|
||||
return nullptr;
|
||||
|
||||
TargetOptions Options;
|
||||
return std::unique_ptr<TargetMachine>(
|
||||
T->createTargetMachine(TargetTriple, "", "", Options, std::nullopt,
|
||||
std::nullopt, CodeGenOptLevel::None));
|
||||
}
|
||||
|
||||
std::unique_ptr<Module> parseIR(const char *IR) {
|
||||
SMDiagnostic Err;
|
||||
std::unique_ptr<Module> Mod = parseAssemblyString(IR, Err, C);
|
||||
if (!Mod)
|
||||
Err.print("Test TargetIRTranslator", errs());
|
||||
return Mod;
|
||||
}
|
||||
};
|
||||
} // namespace
|
||||
|
||||
TEST_F(AArch64IRTranslatorTest, IRTranslateBfloat16) {
|
||||
InitializeAllTargets();
|
||||
InitializeAllTargetMCs();
|
||||
InitializeAllAsmPrinters();
|
||||
InitializeAllAsmParsers();
|
||||
|
||||
PassRegistry *Registry = PassRegistry::getPassRegistry();
|
||||
initializeCore(*Registry);
|
||||
initializeCodeGen(*Registry);
|
||||
initializeGlobalISel(*Registry);
|
||||
|
||||
std::unique_ptr<Module> M = parseIR(R"(
|
||||
define void @foo(ptr %p0) {
|
||||
%ptr1 = getelementptr bfloat, ptr %p0, i64 0
|
||||
%ptr2 = getelementptr bfloat, ptr %p0, i64 1
|
||||
%ptr3 = getelementptr bfloat, ptr %p0, i64 2
|
||||
%a = load bfloat, ptr %ptr1, align 2
|
||||
%b = load bfloat, ptr %ptr2, align 2
|
||||
%c = load bfloat, ptr %ptr3, align 2
|
||||
%mul = fmul bfloat %a, %b
|
||||
%res = fadd bfloat %mul, %c
|
||||
%ptr4 = getelementptr bfloat, ptr %p0, i64 3
|
||||
store bfloat %res, ptr %ptr4, align 2
|
||||
ret void
|
||||
}
|
||||
)");
|
||||
|
||||
auto TM = createTargetMachine();
|
||||
if (!TM)
|
||||
GTEST_SKIP();
|
||||
M->setDataLayout(TM->createDataLayout());
|
||||
|
||||
TM->setGlobalISel(true);
|
||||
TM->setGlobalISelAbort(GlobalISelAbortMode::DisableWithDiag);
|
||||
LLT::setUseExtended(true);
|
||||
|
||||
legacy::PassManager PM;
|
||||
TargetPassConfig *TPC(TM->createPassConfig(PM));
|
||||
|
||||
MachineModuleInfoWrapperPass *MMIWP =
|
||||
new MachineModuleInfoWrapperPass(TM.get());
|
||||
PM.add(TPC);
|
||||
PM.add(MMIWP);
|
||||
PM.add(new IRTranslator());
|
||||
PM.run(*M);
|
||||
|
||||
auto *MMI = &MMIWP->getMMI();
|
||||
Function *F = M->getFunction("foo");
|
||||
auto *MF = MMI->getMachineFunction(*F);
|
||||
MachineRegisterInfo &MRI = MF->getRegInfo();
|
||||
EXPECT_FALSE(MF->getProperties().hasProperty(
|
||||
llvm::MachineFunctionProperties::Property::FailedISel));
|
||||
for (auto &MI : MF->front()) {
|
||||
if (MI.getOpcode() == TargetOpcode::G_LOAD) {
|
||||
EXPECT_TRUE(MRI.getType(MI.getOperand(0).getReg()).isBFloat16());
|
||||
}
|
||||
|
||||
if (MI.getOpcode() == TargetOpcode::G_FADD ||
|
||||
MI.getOpcode() == TargetOpcode::G_FMUL) {
|
||||
for (auto &Op : MI.operands()) {
|
||||
EXPECT_TRUE(MRI.getType(Op.getReg()).isBFloat16());
|
||||
}
|
||||
}
|
||||
}
|
||||
MMI->deleteMachineFunctionFor(*F);
|
||||
|
||||
// Run again without extended LLT
|
||||
LLT::setUseExtended(false);
|
||||
|
||||
PM.run(*M);
|
||||
MF = MMI->getMachineFunction(*F);
|
||||
EXPECT_TRUE(MF->getProperties().hasProperty(
|
||||
llvm::MachineFunctionProperties::Property::FailedISel));
|
||||
}
|
||||
@ -42,9 +42,6 @@ add_llvm_library(LLVMTableGenCommon STATIC OBJECT EXCLUDE_FROM_ALL DISABLE_LLVM_
|
||||
DEPENDS
|
||||
vt_gen
|
||||
intrinsics_gen
|
||||
|
||||
LINK_COMPONENTS
|
||||
CodeGenTypes
|
||||
)
|
||||
|
||||
# Users may include its headers as "Common/*.h"
|
||||
|
||||
@ -10,7 +10,6 @@
|
||||
#include "Common/CodeGenInstruction.h"
|
||||
#include "Common/CodeGenRegisters.h"
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/LEB128.h"
|
||||
#include "llvm/Support/ScopedPrinter.h"
|
||||
@ -364,96 +363,42 @@ std::string LLTCodeGen::getCxxEnumValue() const {
|
||||
|
||||
void LLTCodeGen::emitCxxEnumValue(raw_ostream &OS) const {
|
||||
if (Ty.isScalar()) {
|
||||
if (Ty.isBFloat16())
|
||||
OS << "GILLT_bf16";
|
||||
else if (Ty.isPPCF128())
|
||||
OS << "GILLT_ppcf128";
|
||||
else if (Ty.isX86FP80())
|
||||
OS << "GILLT_x86fp80";
|
||||
else if (Ty.isFloat())
|
||||
OS << "GILLT_f" << Ty.getSizeInBits();
|
||||
else if (Ty.isInteger())
|
||||
OS << "GILLT_i" << Ty.getSizeInBits();
|
||||
else
|
||||
OS << "GILLT_s" << Ty.getSizeInBits();
|
||||
OS << "GILLT_s" << Ty.getSizeInBits();
|
||||
return;
|
||||
}
|
||||
if (Ty.isVector()) {
|
||||
OS << (Ty.isScalable() ? "GILLT_nxv" : "GILLT_v")
|
||||
<< Ty.getElementCount().getKnownMinValue();
|
||||
|
||||
LLT ElemTy = Ty.getElementType();
|
||||
if (ElemTy.isBFloat16())
|
||||
OS << "bf16";
|
||||
else if (ElemTy.isPPCF128())
|
||||
OS << "ppcf128";
|
||||
else if (ElemTy.isX86FP80())
|
||||
OS << "x86fp80";
|
||||
else if (ElemTy.isFloat())
|
||||
OS << "f" << ElemTy.getSizeInBits();
|
||||
else if (ElemTy.isInteger())
|
||||
OS << "i" << ElemTy.getSizeInBits();
|
||||
else
|
||||
OS << "s" << ElemTy.getSizeInBits();
|
||||
<< Ty.getElementCount().getKnownMinValue() << "s"
|
||||
<< Ty.getScalarSizeInBits();
|
||||
return;
|
||||
}
|
||||
|
||||
if (Ty.isPointer()) {
|
||||
OS << "GILLT_p" << Ty.getAddressSpace();
|
||||
if (Ty.getSizeInBits() > 0)
|
||||
OS << "s" << Ty.getSizeInBits();
|
||||
return;
|
||||
}
|
||||
|
||||
llvm_unreachable("Unhandled LLT");
|
||||
}
|
||||
|
||||
void LLTCodeGen::emitCxxConstructorCall(raw_ostream &OS) const {
|
||||
if (Ty.isScalar()) {
|
||||
if (Ty.isInteger())
|
||||
OS << "LLT::integer(" << Ty.getScalarSizeInBits() << ")";
|
||||
else if (Ty.isBFloat16())
|
||||
OS << "LLT::bfloat16()";
|
||||
else if (Ty.isPPCF128())
|
||||
OS << "LLT::ppcf128()";
|
||||
else if (Ty.isX86FP80())
|
||||
OS << "LLT::x86fp80()";
|
||||
else if (Ty.isFloat())
|
||||
OS << "LLT::floatIEEE(" << Ty.getScalarSizeInBits() << ")";
|
||||
else
|
||||
OS << "LLT::scalar(" << Ty.getScalarSizeInBits() << ")";
|
||||
OS << "LLT::scalar(" << Ty.getSizeInBits() << ")";
|
||||
return;
|
||||
}
|
||||
|
||||
if (Ty.isVector()) {
|
||||
OS << "LLT::vector("
|
||||
<< (Ty.isScalable() ? "ElementCount::getScalable("
|
||||
: "ElementCount::getFixed(")
|
||||
<< Ty.getElementCount().getKnownMinValue() << "), ";
|
||||
|
||||
LLT ElemTy = Ty.getElementType();
|
||||
if (ElemTy.isInteger())
|
||||
OS << "LLT::integer(" << ElemTy.getScalarSizeInBits() << ")";
|
||||
else if (ElemTy.isBFloat16())
|
||||
OS << "LLT::bfloat16()";
|
||||
else if (ElemTy.isPPCF128())
|
||||
OS << "LLT::ppcf128()";
|
||||
else if (ElemTy.isX86FP80())
|
||||
OS << "LLT::x86fp80()";
|
||||
else if (ElemTy.isFloat())
|
||||
OS << "LLT::floatIEEE(" << ElemTy.getScalarSizeInBits() << ")";
|
||||
else
|
||||
OS << "LLT::scalar(" << Ty.getScalarSizeInBits() << ")";
|
||||
OS << ")";
|
||||
<< Ty.getElementCount().getKnownMinValue() << "), "
|
||||
<< Ty.getScalarSizeInBits() << ")";
|
||||
return;
|
||||
}
|
||||
|
||||
if (Ty.isPointer() && Ty.getSizeInBits() > 0) {
|
||||
OS << "LLT::pointer(" << Ty.getAddressSpace() << ", " << Ty.getSizeInBits()
|
||||
<< ")";
|
||||
return;
|
||||
}
|
||||
|
||||
llvm_unreachable("Unhandled LLT");
|
||||
}
|
||||
|
||||
@ -461,17 +406,47 @@ void LLTCodeGen::emitCxxConstructorCall(raw_ostream &OS) const {
|
||||
/// particular logic behind the order but either A < B or B < A must be
|
||||
/// true if A != B.
|
||||
bool LLTCodeGen::operator<(const LLTCodeGen &Other) const {
|
||||
return Ty.getUniqueRAWLLTData() < Other.Ty.getUniqueRAWLLTData();
|
||||
if (Ty.isValid() != Other.Ty.isValid())
|
||||
return Ty.isValid() < Other.Ty.isValid();
|
||||
if (!Ty.isValid())
|
||||
return false;
|
||||
|
||||
if (Ty.isVector() != Other.Ty.isVector())
|
||||
return Ty.isVector() < Other.Ty.isVector();
|
||||
if (Ty.isScalar() != Other.Ty.isScalar())
|
||||
return Ty.isScalar() < Other.Ty.isScalar();
|
||||
if (Ty.isPointer() != Other.Ty.isPointer())
|
||||
return Ty.isPointer() < Other.Ty.isPointer();
|
||||
|
||||
if (Ty.isPointer() && Ty.getAddressSpace() != Other.Ty.getAddressSpace())
|
||||
return Ty.getAddressSpace() < Other.Ty.getAddressSpace();
|
||||
|
||||
if (Ty.isVector() && Ty.getElementCount() != Other.Ty.getElementCount())
|
||||
return std::tuple(Ty.isScalable(),
|
||||
Ty.getElementCount().getKnownMinValue()) <
|
||||
std::tuple(Other.Ty.isScalable(),
|
||||
Other.Ty.getElementCount().getKnownMinValue());
|
||||
|
||||
assert((!Ty.isVector() || Ty.isScalable() == Other.Ty.isScalable()) &&
|
||||
"Unexpected mismatch of scalable property");
|
||||
return Ty.isVector()
|
||||
? std::tuple(Ty.isScalable(),
|
||||
Ty.getSizeInBits().getKnownMinValue()) <
|
||||
std::tuple(Other.Ty.isScalable(),
|
||||
Other.Ty.getSizeInBits().getKnownMinValue())
|
||||
: Ty.getSizeInBits().getFixedValue() <
|
||||
Other.Ty.getSizeInBits().getFixedValue();
|
||||
}
|
||||
|
||||
//===- LLTCodeGen Helpers -------------------------------------------------===//
|
||||
|
||||
std::optional<LLTCodeGen> llvm::gi::MVTToLLT(MVT VT) {
|
||||
if (VT.isVector() && !VT.getVectorElementCount().isScalar())
|
||||
return LLTCodeGen(LLT(VT));
|
||||
return LLTCodeGen(
|
||||
LLT::vector(VT.getVectorElementCount(), VT.getScalarSizeInBits()));
|
||||
|
||||
if (VT.isInteger() || VT.isFloatingPoint())
|
||||
return LLTCodeGen(LLT(VT));
|
||||
return LLTCodeGen(LLT::scalar(VT.getSizeInBits()));
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
@ -8,21 +8,11 @@
|
||||
|
||||
#include "GlobalISelMatchTableExecutorEmitter.h"
|
||||
#include "GlobalISelMatchTable.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/TableGen/CodeGenHelpers.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::gi;
|
||||
|
||||
static cl::opt<bool>
|
||||
AllowExtendedLLT("gisel-extended-llt",
|
||||
cl::desc("Generate extended llt names in match tables"),
|
||||
cl::init(false));
|
||||
|
||||
GlobalISelMatchTableExecutorEmitter::GlobalISelMatchTableExecutorEmitter() {
|
||||
LLT::setUseExtended(AllowExtendedLLT);
|
||||
}
|
||||
|
||||
void GlobalISelMatchTableExecutorEmitter::emitSubtargetFeatureBitsetImpl(
|
||||
raw_ostream &OS, ArrayRef<RuleMatcher> Rules) {
|
||||
SubtargetFeatureInfo::emitSubtargetFeatureBitEnumeration(SubtargetFeatures,
|
||||
|
||||
@ -188,7 +188,7 @@ protected:
|
||||
Comment);
|
||||
}
|
||||
|
||||
GlobalISelMatchTableExecutorEmitter();
|
||||
GlobalISelMatchTableExecutorEmitter() = default;
|
||||
|
||||
public:
|
||||
virtual ~GlobalISelMatchTableExecutorEmitter() = default;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user