[clang] f6ea026 - [SveEmitter] Fix encoding/decoding of SVETypeFlags
Sander de Smalen via cfe-commits
cfe-commits at lists.llvm.org
Tue Apr 14 07:51:17 PDT 2020
Author: Sander de Smalen
Date: 2020-04-14T15:48:28+01:00
New Revision: f6ea026f179a02cd335d71e4800b4d67c25c006b
URL: https://github.com/llvm/llvm-project/commit/f6ea026f179a02cd335d71e4800b4d67c25c006b
DIFF: https://github.com/llvm/llvm-project/commit/f6ea026f179a02cd335d71e4800b4d67c25c006b.diff
LOG: [SveEmitter] Fix encoding/decoding of SVETypeFlags
Summary:
This issue was introduced when reworking D75861. The bug isn't
actually hit with current unit tests because the contiguous loads/stores
infer the EltType and the MemEltType from the pointer and result, rather
than using the flags. But it will be needed for other intrinsics, such as
gather/scatter.
Reviewers: SjoerdMeijer, Andrzej
Reviewed By: SjoerdMeijer
Subscribers: andwar, tschuett, cfe-commits, llvm-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D76617
Added:
Modified:
clang/include/clang/Basic/TargetBuiltins.h
clang/include/clang/Basic/arm_sve.td
clang/utils/TableGen/SveEmitter.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/Basic/TargetBuiltins.h b/clang/include/clang/Basic/TargetBuiltins.h
index 99af2412426f..468167957974 100644
--- a/clang/include/clang/Basic/TargetBuiltins.h
+++ b/clang/include/clang/Basic/TargetBuiltins.h
@@ -17,6 +17,7 @@
#include <stdint.h>
#include "clang/Basic/Builtins.h"
+#include "llvm/Support/MathExtras.h"
#undef PPC
namespace clang {
@@ -163,6 +164,9 @@ namespace clang {
/// Flags to identify the types for overloaded SVE builtins.
class SVETypeFlags {
uint64_t Flags;
+ unsigned EltTypeShift;
+ unsigned MemEltTypeShift;
+ unsigned MergeTypeShift;
public:
#define LLVM_GET_SVE_TYPEFLAGS
@@ -181,15 +185,27 @@ namespace clang {
#undef LLVM_GET_SVE_MEMELTTYPES
};
- SVETypeFlags(uint64_t F) : Flags(F) {}
- SVETypeFlags(EltType ET, bool IsUnsigned) : Flags(ET) {}
+ enum MergeType {
+#define LLVM_GET_SVE_MERGETYPES
+#include "clang/Basic/arm_sve_typeflags.inc"
+#undef LLVM_GET_SVE_MERGETYPES
+ };
+ SVETypeFlags(uint64_t F) : Flags(F) {
+ EltTypeShift = llvm::countTrailingZeros(EltTypeMask);
+ MemEltTypeShift = llvm::countTrailingZeros(MemEltTypeMask);
+ MergeTypeShift = llvm::countTrailingZeros(MergeTypeMask);
+ }
EltType getEltType() const {
- return (EltType)((Flags & EltTypeMask) - FirstEltType);
+ return (EltType)((Flags & EltTypeMask) >> EltTypeShift);
}
MemEltType getMemEltType() const {
- return (MemEltType)((Flags & MemEltTypeMask) - FirstMemEltType);
+ return (MemEltType)((Flags & MemEltTypeMask) >> MemEltTypeShift);
+ }
+
+ MergeType getMergeType() const {
+ return (MergeType)((Flags & MergeTypeMask) >> MergeTypeShift);
}
bool isLoad() const { return Flags & IsLoad; }
diff --git a/clang/include/clang/Basic/arm_sve.td b/clang/include/clang/Basic/arm_sve.td
index 4e75d0339b5c..9ed4ae86e1b7 100644
--- a/clang/include/clang/Basic/arm_sve.td
+++ b/clang/include/clang/Basic/arm_sve.td
@@ -84,15 +84,16 @@
// Y: const pointer to uint32_t
// Z: const pointer to uint64_t
-class MergeType<int val> {
+class MergeType<int val, string suffix=""> {
int Value = val;
+ string Suffix = suffix;
}
def MergeNone : MergeType<0>;
-def MergeAny : MergeType<1>;
-def MergeOp1 : MergeType<2>;
-def MergeZero : MergeType<3>;
-def MergeAnyExp : MergeType<4>; // Use merged builtin with explicit
-def MergeZeroExp : MergeType<5>; // generation of its inactive argument.
+def MergeAny : MergeType<1, "_x">;
+def MergeOp1 : MergeType<2, "_m">;
+def MergeZero : MergeType<3, "_z">;
+def MergeAnyExp : MergeType<4, "_x">; // Use merged builtin with explicit
+def MergeZeroExp : MergeType<5, "_z">; // generation of its inactive argument.
class EltType<int val> {
int Value = val;
@@ -134,13 +135,17 @@ def FirstMemEltType : FlagType<0x00000010>;
// : :
// : :
def MemEltTypeMask : FlagType<0x00000070>;
-def IsLoad : FlagType<0x00000080>;
-def IsStore : FlagType<0x00000100>;
-def IsGatherLoad : FlagType<0x00000200>;
-def IsScatterStore : FlagType<0x00000400>;
-def IsStructLoad : FlagType<0x00000800>;
-def IsStructStore : FlagType<0x00001000>;
-def IsZExtReturn : FlagType<0x00002000>; // Return value is sign-extend by default
+def FirstMergeTypeMask : FlagType<0x00000080>;
+// : :
+// : :
+def MergeTypeMask : FlagType<0x00000380>;
+def IsLoad : FlagType<0x00002000>;
+def IsStore : FlagType<0x00004000>;
+def IsGatherLoad : FlagType<0x00008000>;
+def IsScatterStore : FlagType<0x00010000>;
+def IsStructLoad : FlagType<0x00020000>;
+def IsStructStore : FlagType<0x00040000>;
+def IsZExtReturn : FlagType<0x00080000>; // Return value is sign-extend by default
// Every intrinsic subclasses Inst.
class Inst<string n, string p, string t, MergeType mt, string i,
@@ -150,6 +155,7 @@ class Inst<string n, string p, string t, MergeType mt, string i,
string Types = t;
string ArchGuard = "";
int Merge = mt.Value;
+ string MergeSuffix = mt.Suffix;
string LLVMIntrinsic = i;
list<FlagType> Flags = ft;
int MemEltType = met.Value;
diff --git a/clang/utils/TableGen/SveEmitter.cpp b/clang/utils/TableGen/SveEmitter.cpp
index 831dfa804ca0..dc009e5ca443 100644
--- a/clang/utils/TableGen/SveEmitter.cpp
+++ b/clang/utils/TableGen/SveEmitter.cpp
@@ -65,9 +65,6 @@ class SVEType {
applyModifier(CharMod);
}
- /// Return the value in SVETypeFlags for this type.
- unsigned getTypeFlags() const;
-
bool isPointer() const { return Pointer; }
bool isVoidPointer() const { return Pointer && Void; }
bool isSigned() const { return Signed; }
@@ -138,36 +135,22 @@ class Intrinsic {
/// The architectural #ifdef guard.
std::string Guard;
+ // The merge suffix such as _m, _x or _z.
+ std::string MergeSuffix;
+
/// The types of return value [0] and parameters [1..].
std::vector<SVEType> Types;
/// The "base type", which is VarType('d', BaseTypeSpec).
SVEType BaseType;
- unsigned Flags;
+ uint64_t Flags;
public:
- /// The type of predication.
- enum MergeType {
- MergeNone,
- MergeAny,
- MergeOp1,
- MergeZero,
- MergeAnyExp,
- MergeZeroExp,
- MergeInvalid
- } Merge;
-
- Intrinsic(StringRef Name, StringRef Proto, int64_t MT, StringRef LLVMName,
- unsigned Flags, TypeSpec BT, ClassKind Class, SVEEmitter &Emitter,
- StringRef Guard)
- : Name(Name.str()), LLVMName(LLVMName), Proto(Proto.str()),
- BaseTypeSpec(BT), Class(Class), Guard(Guard.str()), BaseType(BT, 'd'),
- Flags(Flags), Merge(MergeType(MT)) {
- // Types[0] is the return value.
- for (unsigned I = 0; I < Proto.size(); ++I)
- Types.emplace_back(BaseTypeSpec, Proto[I]);
- }
+ Intrinsic(StringRef Name, StringRef Proto, uint64_t MergeTy,
+ StringRef MergeSuffix, uint64_t MemoryElementTy, StringRef LLVMName,
+ uint64_t Flags, TypeSpec BT, ClassKind Class, SVEEmitter &Emitter,
+ StringRef Guard);
~Intrinsic()=default;
@@ -179,14 +162,13 @@ class Intrinsic {
StringRef getGuard() const { return Guard; }
ClassKind getClassKind() const { return Class; }
- MergeType getMergeType() const { return Merge; }
SVEType getReturnType() const { return Types[0]; }
ArrayRef<SVEType> getTypes() const { return Types; }
SVEType getParamType(unsigned I) const { return Types[I + 1]; }
unsigned getNumParams() const { return Proto.size() - 1; }
- unsigned getFlags() const { return Flags; }
+ uint64_t getFlags() const { return Flags; }
bool isFlagSet(uint64_t Flag) const { return Flags & Flag;}
/// Return the type string for a BUILTIN() macro in Builtins.def.
@@ -209,7 +191,7 @@ class Intrinsic {
void emitIntrinsic(raw_ostream &OS) const;
private:
- std::string getMergeSuffix() const;
+ std::string getMergeSuffix() const { return MergeSuffix; }
std::string mangleName(ClassKind LocalCK) const;
std::string replaceTemplatedArgs(std::string Name, TypeSpec TS,
std::string Proto) const;
@@ -221,8 +203,8 @@ class SVEEmitter {
llvm::StringMap<uint64_t> EltTypes;
llvm::StringMap<uint64_t> MemEltTypes;
llvm::StringMap<uint64_t> FlagTypes;
+ llvm::StringMap<uint64_t> MergeTypes;
- unsigned getTypeFlags(const SVEType &T);
public:
SVEEmitter(RecordKeeper &R) : Records(R) {
for (auto *RV : Records.getAllDerivedDefinitions("EltType"))
@@ -231,8 +213,42 @@ class SVEEmitter {
MemEltTypes[RV->getNameInitAsString()] = RV->getValueAsInt("Value");
for (auto *RV : Records.getAllDerivedDefinitions("FlagType"))
FlagTypes[RV->getNameInitAsString()] = RV->getValueAsInt("Value");
+ for (auto *RV : Records.getAllDerivedDefinitions("MergeType"))
+ MergeTypes[RV->getNameInitAsString()] = RV->getValueAsInt("Value");
+ }
+
+ // Returns the SVETypeFlags for a given value and mask.
+ uint64_t encodeFlag(uint64_t V, StringRef MaskName) const {
+ auto It = FlagTypes.find(MaskName);
+ if (It != FlagTypes.end()) {
+ uint64_t Mask = It->getValue();
+ unsigned Shift = llvm::countTrailingZeros(Mask);
+ return (V << Shift) & Mask;
+ }
+ llvm_unreachable("Unsupported flag");
+ }
+
+ // Returns the SVETypeFlags for the given element type.
+ uint64_t encodeEltType(StringRef EltName) {
+ auto It = EltTypes.find(EltName);
+ if (It != EltTypes.end())
+ return encodeFlag(It->getValue(), "EltTypeMask");
+ llvm_unreachable("Unsupported EltType");
+ }
+
+ // Returns the SVETypeFlags for the given memory element type.
+ uint64_t encodeMemoryElementType(uint64_t MT) {
+ return encodeFlag(MT, "MemEltTypeMask");
}
+ // Returns the SVETypeFlags for the given merge type.
+ uint64_t encodeMergeType(uint64_t MT) {
+ return encodeFlag(MT, "MergeTypeMask");
+ }
+
+ // Returns the SVETypeFlags value for the given SVEType.
+ uint64_t encodeTypeFlags(const SVEType &T);
+
/// Emit arm_sve.h.
void createHeader(raw_ostream &o);
@@ -256,36 +272,6 @@ class SVEEmitter {
// Type implementation
//===----------------------------------------------------------------------===//
-unsigned SVEEmitter::getTypeFlags(const SVEType &T) {
- unsigned FirstEltType = EltTypes["FirstEltType"];
- if (T.isFloat()) {
- switch (T.getElementSizeInBits()) {
- case 16: return FirstEltType + EltTypes["EltTyFloat16"];
- case 32: return FirstEltType + EltTypes["EltTyFloat32"];
- case 64: return FirstEltType + EltTypes["EltTyFloat64"];
- default: llvm_unreachable("Unhandled float element bitwidth!");
- }
- }
-
- if (T.isPredicateVector()) {
- switch (T.getElementSizeInBits()) {
- case 8: return FirstEltType + EltTypes["EltTyBool8"];
- case 16: return FirstEltType + EltTypes["EltTyBool16"];
- case 32: return FirstEltType + EltTypes["EltTyBool32"];
- case 64: return FirstEltType + EltTypes["EltTyBool64"];
- default: llvm_unreachable("Unhandled predicate element bitwidth!");
- }
- }
-
- switch (T.getElementSizeInBits()) {
- case 8: return FirstEltType + EltTypes["EltTyInt8"];
- case 16: return FirstEltType + EltTypes["EltTyInt16"];
- case 32: return FirstEltType + EltTypes["EltTyInt32"];
- case 64: return FirstEltType + EltTypes["EltTyInt64"];
- default: llvm_unreachable("Unhandled integer element bitwidth!");
- }
-}
-
std::string SVEType::builtin_str() const {
std::string S;
if (isVoid())
@@ -543,6 +529,26 @@ void SVEType::applyModifier(char Mod) {
// Intrinsic implementation
//===----------------------------------------------------------------------===//
+Intrinsic::Intrinsic(StringRef Name, StringRef Proto, uint64_t MergeTy,
+ StringRef MergeSuffix, uint64_t MemoryElementTy,
+ StringRef LLVMName, uint64_t Flags, TypeSpec BT,
+ ClassKind Class, SVEEmitter &Emitter, StringRef Guard)
+ : Name(Name.str()), LLVMName(LLVMName), Proto(Proto.str()),
+ BaseTypeSpec(BT), Class(Class), Guard(Guard.str()),
+ MergeSuffix(MergeSuffix.str()), BaseType(BT, 'd'), Flags(Flags) {
+
+ // Types[0] is the return value.
+ for (unsigned I = 0; I < Proto.size(); ++I) {
+ SVEType T(BaseTypeSpec, Proto[I]);
+ Types.push_back(T);
+ }
+
+ // Set flags based on properties
+ this->Flags |= Emitter.encodeTypeFlags(BaseType);
+ this->Flags |= Emitter.encodeMemoryElementType(MemoryElementTy);
+ this->Flags |= Emitter.encodeMergeType(MergeTy);
+}
+
std::string Intrinsic::getBuiltinTypeStr() {
std::string S;
@@ -601,20 +607,6 @@ std::string Intrinsic::replaceTemplatedArgs(std::string Name, TypeSpec TS,
return Ret;
}
-// ACLE function names have a merge style postfix.
-std::string Intrinsic::getMergeSuffix() const {
- switch (getMergeType()) {
- default:
- llvm_unreachable("Unknown predication specifier");
- case MergeNone: return "";
- case MergeAny:
- case MergeAnyExp: return "_x";
- case MergeOp1: return "_m";
- case MergeZero:
- case MergeZeroExp: return "_z";
- }
-}
-
std::string Intrinsic::mangleName(ClassKind LocalCK) const {
std::string S = getName();
@@ -668,6 +660,49 @@ void Intrinsic::emitIntrinsic(raw_ostream &OS) const {
//===----------------------------------------------------------------------===//
// SVEEmitter implementation
//===----------------------------------------------------------------------===//
+uint64_t SVEEmitter::encodeTypeFlags(const SVEType &T) {
+ if (T.isFloat()) {
+ switch (T.getElementSizeInBits()) {
+ case 16:
+ return encodeEltType("EltTyFloat16");
+ case 32:
+ return encodeEltType("EltTyFloat32");
+ case 64:
+ return encodeEltType("EltTyFloat64");
+ default:
+ llvm_unreachable("Unhandled float element bitwidth!");
+ }
+ }
+
+ if (T.isPredicateVector()) {
+ switch (T.getElementSizeInBits()) {
+ case 8:
+ return encodeEltType("EltTyBool8");
+ case 16:
+ return encodeEltType("EltTyBool16");
+ case 32:
+ return encodeEltType("EltTyBool32");
+ case 64:
+ return encodeEltType("EltTyBool64");
+ default:
+ llvm_unreachable("Unhandled predicate element bitwidth!");
+ }
+ }
+
+ switch (T.getElementSizeInBits()) {
+ case 8:
+ return encodeEltType("EltTyInt8");
+ case 16:
+ return encodeEltType("EltTyInt16");
+ case 32:
+ return encodeEltType("EltTyInt32");
+ case 64:
+ return encodeEltType("EltTyInt64");
+ default:
+ llvm_unreachable("Unhandled integer element bitwidth!");
+ }
+}
+
void SVEEmitter::createIntrinsic(
Record *R, SmallVectorImpl<std::unique_ptr<Intrinsic>> &Out) {
StringRef Name = R->getValueAsString("Name");
@@ -675,13 +710,14 @@ void SVEEmitter::createIntrinsic(
StringRef Types = R->getValueAsString("Types");
StringRef Guard = R->getValueAsString("ArchGuard");
StringRef LLVMName = R->getValueAsString("LLVMIntrinsic");
- int64_t Merge = R->getValueAsInt("Merge");
+ uint64_t Merge = R->getValueAsInt("Merge");
+ StringRef MergeSuffix = R->getValueAsString("MergeSuffix");
+ uint64_t MemEltType = R->getValueAsInt("MemEltType");
std::vector<Record*> FlagsList = R->getValueAsListOfDefs("Flags");
int64_t Flags = 0;
for (auto FlagRec : FlagsList)
Flags |= FlagRec->getValueAsInt("Value");
- Flags |= R->getValueAsInt("MemEltType") + MemEltTypes["FirstMemEltType"];
// Extract type specs from string
SmallVector<TypeSpec, 8> TypeSpecs;
@@ -701,14 +737,15 @@ void SVEEmitter::createIntrinsic(
// Create an Intrinsic for each type spec.
for (auto TS : TypeSpecs) {
- Out.push_back(std::make_unique<Intrinsic>(Name, Proto, Merge,
- LLVMName, Flags, TS, ClassS,
- *this, Guard));
+ Out.push_back(std::make_unique<Intrinsic>(Name, Proto, Merge, MergeSuffix,
+ MemEltType, LLVMName, Flags, TS,
+ ClassS, *this, Guard));
// Also generate the short-form (e.g. svadd_m) for the given type-spec.
if (Intrinsic::isOverloadedIntrinsic(Name))
- Out.push_back(std::make_unique<Intrinsic>(
- Name, Proto, Merge, LLVMName, Flags, TS, ClassG, *this, Guard));
+ Out.push_back(std::make_unique<Intrinsic>(Name, Proto, Merge, MergeSuffix,
+ MemEltType, LLVMName, Flags, TS,
+ ClassG, *this, Guard));
}
}
@@ -846,7 +883,7 @@ void SVEEmitter::createCodeGenMap(raw_ostream &OS) {
if (Def->getClassKind() == ClassG)
continue;
- uint64_t Flags = Def->getFlags() | getTypeFlags(Def->getBaseType());
+ uint64_t Flags = Def->getFlags();
auto FlagString = std::to_string(Flags);
std::string LLVMName = Def->getLLVMName();
@@ -876,6 +913,11 @@ void SVEEmitter::createTypeFlags(raw_ostream &OS) {
for (auto &KV : MemEltTypes)
OS << " " << KV.getKey() << " = " << KV.getValue() << ",\n";
OS << "#endif\n\n";
+
+ OS << "#ifdef LLVM_GET_SVE_MERGETYPES\n";
+ for (auto &KV : MergeTypes)
+ OS << " " << KV.getKey() << " = " << KV.getValue() << ",\n";
+ OS << "#endif\n\n";
}
namespace clang {
More information about the cfe-commits
mailing list