[clang] [Clang][AArch64] Add customisable immediate range checking to NEON (PR #100278)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Jul 23 16:25:23 PDT 2024
github-actions[bot] wrote:
<!--LLVM CODE FORMAT COMMENT: {clang-format}-->
:warning: C/C++ code formatter, clang-format found issues in your code. :warning:
<details>
<summary>
You can test this locally with the following command:
</summary>
``````````bash
git-clang-format --diff ce811fb6d94e1d4af1fd1f52fbf109bc34834970 1d9084e9c246d2fcb395c329c6cf1ca19ef032aa --extensions h,cpp,c -- clang/test/Sema/aarch64-neon-vcmla-ranges.c clang/include/clang/Basic/TargetBuiltins.h clang/include/clang/Sema/SemaARM.h clang/lib/Sema/SemaARM.cpp clang/test/CodeGen/aarch64-neon-vcmla.c clang/utils/TableGen/NeonEmitter.cpp clang/utils/TableGen/SveEmitter.cpp
``````````
</details>
<details>
<summary>
View the diff from clang-format here.
</summary>
``````````diff
diff --git a/clang/include/clang/Basic/TargetBuiltins.h b/clang/include/clang/Basic/TargetBuiltins.h
index 50e17ad7e1..384811f928 100644
--- a/clang/include/clang/Basic/TargetBuiltins.h
+++ b/clang/include/clang/Basic/TargetBuiltins.h
@@ -209,7 +209,7 @@ namespace clang {
Flags |= QuadFlag;
}
- EltType getEltType() const { return (EltType)(Flags & EltTypeMask); }
+ EltType getEltType() const { return (EltType)(Flags & EltTypeMask); }
bool isPoly() const {
EltType ET = getEltType();
return ET == Poly8 || ET == Poly16 || ET == Poly64;
@@ -217,36 +217,36 @@ namespace clang {
bool isUnsigned() const { return (Flags & UnsignedFlag) != 0; }
bool isQuad() const { return (Flags & QuadFlag) != 0; };
unsigned getEltSizeInBits() const {
- switch(getEltType()){
- case Int8:
- case Poly8:
- return 8;
- case Int16:
- case Float16:
- case Poly16:
- case BFloat16:
- return 16;
- case Int32:
- case Float32:
- return 32;
- case Int64:
- case Float64:
- case Poly64:
- return 64;
- case Poly128:
- return 128;
- default:
- llvm_unreachable("Invalid NeonTypeFlag!");
+ switch (getEltType()) {
+ case Int8:
+ case Poly8:
+ return 8;
+ case Int16:
+ case Float16:
+ case Poly16:
+ case BFloat16:
+ return 16;
+ case Int32:
+ case Float32:
+ return 32;
+ case Int64:
+ case Float64:
+ case Poly64:
+ return 64;
+ case Poly128:
+ return 128;
+ default:
+ llvm_unreachable("Invalid NeonTypeFlag!");
}
}
};
- // Shared between SVE/SME and NEON
- enum ArmImmCheckType {
+ // Shared between SVE/SME and NEON
+ enum ArmImmCheckType {
#define LLVM_GET_ARM_INTRIN_IMMCHECKTYPES
#include "clang/Basic/arm_sve_typeflags.inc"
-#undef LLVM_GET_ARM_INTRIN_IMMCHECKTYPES
- };
+#undef LLVM_GET_ARM_INTRIN_IMMCHECKTYPES
+ };
/// Flags to identify the types for overloaded SVE builtins.
class SVETypeFlags {
@@ -279,7 +279,6 @@ namespace clang {
#undef LLVM_GET_SVE_MERGETYPES
};
-
SVETypeFlags(uint64_t F) : Flags(F) {
EltTypeShift = llvm::countr_zero(EltTypeMask);
MemEltTypeShift = llvm::countr_zero(MemEltTypeMask);
diff --git a/clang/include/clang/Sema/SemaARM.h b/clang/include/clang/Sema/SemaARM.h
index 1ced84300c..2f13e60f08 100644
--- a/clang/include/clang/Sema/SemaARM.h
+++ b/clang/include/clang/Sema/SemaARM.h
@@ -41,8 +41,8 @@ public:
unsigned MaxWidth);
bool CheckNeonBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
CallExpr *TheCall);
- bool ParseNeonImmChecks(CallExpr *TheCall,
- SmallVector<std::tuple<int, int, int>, 2> &ImmChecks,
+ bool ParseNeonImmChecks(CallExpr *TheCall,
+ SmallVector<std::tuple<int, int, int>, 2> &ImmChecks,
int OverloadType);
bool CheckMVEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
bool CheckSVEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
diff --git a/clang/lib/Sema/SemaARM.cpp b/clang/lib/Sema/SemaARM.cpp
index 8f4d94e1df..bbcca1c724 100644
--- a/clang/lib/Sema/SemaARM.cpp
+++ b/clang/lib/Sema/SemaARM.cpp
@@ -369,62 +369,63 @@ enum ArmSMEState : unsigned {
ArmZT0Mask = 0b11 << 2
};
-bool SemaARM::ParseNeonImmChecks(CallExpr *TheCall, SmallVector<std::tuple<int, int, int>, 2>
- &ImmChecks, int OverloadType = -1) {
+bool SemaARM::ParseNeonImmChecks(
+ CallExpr *TheCall, SmallVector<std::tuple<int, int, int>, 2> &ImmChecks,
+ int OverloadType = -1) {
int ArgIdx, CheckTy, ElementType;
bool hasError = false;
for (auto &I : ImmChecks) {
std::tie(ArgIdx, CheckTy, ElementType) = I;
- NeonTypeFlags Type = (OverloadType != -1) ?
- NeonTypeFlags(OverloadType) : NeonTypeFlags(ElementType);
-
- switch((ArmImmCheckType)CheckTy) {
- case ArmImmCheckType::ImmCheck0_3:
- hasError |= SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 3);
- break;
- case ArmImmCheckType::ImmCheck0_63:
- hasError |= SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 63);
- break;
- case ArmImmCheckType::ImmCheck0_7:
- hasError |= SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 7);
- break;
- case ArmImmCheckType::ImmCheck1_16:
- hasError |= SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, 16);
- break;
- case ArmImmCheckType::ImmCheck1_32:
- hasError |= SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, 32);
- break;
- case ArmImmCheckType::ImmCheck1_64:
- hasError |= SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, 64);
- break;
- case ArmImmCheckType::ImmCheckLaneIndex:
- hasError |= SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, (64 << Type.isQuad()) /
- Type.getEltSizeInBits() - 1);
- break;
- case ArmImmCheckType::ImmCheckLaneQIndex: // force to use quad
- hasError |= SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0,
- (128/Type.getEltSizeInBits()) - 1);
- break;
- case ArmImmCheckType::ImmCheckShiftLeft:
- hasError |= SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0,
- Type.getEltSizeInBits() - 1);
- break;
- case ArmImmCheckType::ImmCheckShiftRight:
- hasError |= SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx,
- 1, Type.getEltSizeInBits());
- break;
- default:
- llvm_unreachable("Invalid Neon immediate range typeflag!");
- break;
+ NeonTypeFlags Type = (OverloadType != -1) ? NeonTypeFlags(OverloadType)
+ : NeonTypeFlags(ElementType);
+
+ switch ((ArmImmCheckType)CheckTy) {
+ case ArmImmCheckType::ImmCheck0_3:
+ hasError |= SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 3);
+ break;
+ case ArmImmCheckType::ImmCheck0_63:
+ hasError |= SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 63);
+ break;
+ case ArmImmCheckType::ImmCheck0_7:
+ hasError |= SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 7);
+ break;
+ case ArmImmCheckType::ImmCheck1_16:
+ hasError |= SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, 16);
+ break;
+ case ArmImmCheckType::ImmCheck1_32:
+ hasError |= SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, 32);
+ break;
+ case ArmImmCheckType::ImmCheck1_64:
+ hasError |= SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, 64);
+ break;
+ case ArmImmCheckType::ImmCheckLaneIndex:
+ hasError |= SemaRef.BuiltinConstantArgRange(
+ TheCall, ArgIdx, 0,
+ (64 << Type.isQuad()) / Type.getEltSizeInBits() - 1);
+ break;
+ case ArmImmCheckType::ImmCheckLaneQIndex: // force to use quad
+ hasError |= SemaRef.BuiltinConstantArgRange(
+ TheCall, ArgIdx, 0, (128 / Type.getEltSizeInBits()) - 1);
+ break;
+ case ArmImmCheckType::ImmCheckShiftLeft:
+ hasError |= SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0,
+ Type.getEltSizeInBits() - 1);
+ break;
+ case ArmImmCheckType::ImmCheckShiftRight:
+ hasError |= SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1,
+ Type.getEltSizeInBits());
+ break;
+ default:
+ llvm_unreachable("Invalid Neon immediate range typeflag!");
+ break;
}
}
return hasError;
}
-
bool SemaARM::ParseSVEImmChecks(
CallExpr *TheCall, SmallVector<std::tuple<int, int, int>, 3> &ImmChecks) {
// Perform all the immediate checks for this builtin call.
@@ -833,8 +834,8 @@ bool SemaARM::CheckNeonBuiltinFunctionCall(const TargetInfo &TI,
#include "clang/Basic/arm_fp16.inc"
#include "clang/Basic/arm_neon.inc"
#undef GET_NEON_IMMEDIATE_CHECK
- }
-
+ }
+
return ParseNeonImmChecks(TheCall, ImmChecks, TV);
}
diff --git a/clang/utils/TableGen/NeonEmitter.cpp b/clang/utils/TableGen/NeonEmitter.cpp
index 7666b53000..8dc6312525 100644
--- a/clang/utils/TableGen/NeonEmitter.cpp
+++ b/clang/utils/TableGen/NeonEmitter.cpp
@@ -370,10 +370,13 @@ class Intrinsic {
public:
Intrinsic(Record *R, StringRef Name, StringRef Proto, TypeSpec OutTS,
- TypeSpec InTS, ArrayRef<std::tuple<int, int, int>> ImmChecks, ClassKind CK, ListInit *Body, NeonEmitter &Emitter,
- StringRef ArchGuard, StringRef TargetGuard, bool IsUnavailable, bool BigEndianSafe)
- : R(R), Name(Name.str()), OutTS(OutTS), InTS(InTS), ImmChecks(ImmChecks), CK(CK), Body(Body),
- ArchGuard(ArchGuard.str()), TargetGuard(TargetGuard.str()), IsUnavailable(IsUnavailable),
+ TypeSpec InTS, ArrayRef<std::tuple<int, int, int>> ImmChecks,
+ ClassKind CK, ListInit *Body, NeonEmitter &Emitter,
+ StringRef ArchGuard, StringRef TargetGuard, bool IsUnavailable,
+ bool BigEndianSafe)
+ : R(R), Name(Name.str()), OutTS(OutTS), InTS(InTS), ImmChecks(ImmChecks),
+ CK(CK), Body(Body), ArchGuard(ArchGuard.str()),
+ TargetGuard(TargetGuard.str()), IsUnavailable(IsUnavailable),
BigEndianSafe(BigEndianSafe), PolymorphicKeyType(0), NeededEarly(false),
UseMacro(false), BaseType(OutTS, "."), InBaseType(InTS, "."),
Emitter(Emitter) {
@@ -416,14 +419,14 @@ public:
/// Get the architectural guard string (#ifdef).
std::string getArchGuard() const { return ArchGuard; }
std::string getTargetGuard() const { return TargetGuard; }
- ArrayRef<std::tuple<int, int, int>> getImmChecks() const {return ImmChecks; }
+ ArrayRef<std::tuple<int, int, int>> getImmChecks() const { return ImmChecks; }
/// Get the non-mangled name.
std::string getName() const { return Name; }
/// Return true if the intrinsic takes an immediate operand.
bool hasImmediate() const {
return llvm::any_of(Types, [](const Type &T) { return T.isImmediate(); });
- //return !ImmChecks.empty();
+ // return !ImmChecks.empty();
}
// Return if the supplied argument is an immediate
@@ -558,6 +561,7 @@ class NeonEmitter {
void genNeonImmCheckTypes(raw_ostream &OS);
void genIntrinsicRangeCheckCode(raw_ostream &OS,
SmallVectorImpl<Intrinsic *> &Defs);
+
public:
/// Called by Intrinsic - this attempts to get an intrinsic that takes
/// the given types as arguments.
@@ -1032,7 +1036,7 @@ std::string Intrinsic::getBuiltinTypeStr() {
if (LocalCK == ClassI && T.isInteger())
T.makeSigned();
- if(isArgImmediate(I))
+ if (isArgImmediate(I))
T.makeImmediate(32);
S += T.builtin_str();
@@ -1953,12 +1957,13 @@ void NeonEmitter::createIntrinsic(Record *R,
bool BigEndianSafe = R->getValueAsBit("BigEndianSafe");
std::string ArchGuard = std::string(R->getValueAsString("ArchGuard"));
std::string TargetGuard = std::string(R->getValueAsString("TargetGuard"));
- std::vector<Record*> ImmCheckList = R->getValueAsListOfDefs("ImmChecks");
+ std::vector<Record *> ImmCheckList = R->getValueAsListOfDefs("ImmChecks");
SmallVector<std::tuple<int, int, int>, 2> ImmChecks;
- for(const auto *R: ImmCheckList) {
+ for (const auto *R : ImmCheckList) {
- ImmChecks.push_back(std::make_tuple(R->getValueAsInt("Arg"),
+ ImmChecks.push_back(
+ std::make_tuple(R->getValueAsInt("Arg"),
R->getValueAsDef("Kind")->getValueAsInt("Value"),
R->getValueAsInt("EltSizeArg")));
}
@@ -2003,8 +2008,9 @@ void NeonEmitter::createIntrinsic(Record *R,
auto &Entry = IntrinsicMap[Name];
for (auto &I : NewTypeSpecs) {
- Entry.emplace_back(R, Name, Proto, I.first, I.second, ImmChecks, CK, Body, *this,
- ArchGuard, TargetGuard, IsUnavailable, BigEndianSafe);
+ Entry.emplace_back(R, Name, Proto, I.first, I.second, ImmChecks, CK, Body,
+ *this, ArchGuard, TargetGuard, IsUnavailable,
+ BigEndianSafe);
Out.push_back(&Entry.back());
}
@@ -2157,34 +2163,38 @@ void NeonEmitter::genNeonImmCheckTypes(raw_ostream &OS) {
OS << "#ifdef GET_NEON_IMMCHECKTYPES\n";
for (auto *RV : Records.getAllDerivedDefinitions("ImmCheckType")) {
- OS << " " << RV->getNameInitAsString() << " = " << RV->getValueAsInt("Value") << ",\n";
+ OS << " " << RV->getNameInitAsString() << " = "
+ << RV->getValueAsInt("Value") << ",\n";
}
OS << "#endif\n\n";
}
-void NeonEmitter::genIntrinsicRangeCheckCode(raw_ostream &OS, SmallVectorImpl<Intrinsic *> &Defs) {
+void NeonEmitter::genIntrinsicRangeCheckCode(
+ raw_ostream &OS, SmallVectorImpl<Intrinsic *> &Defs) {
OS << "#ifdef GET_NEON_IMMEDIATE_CHECK\n";
int EltType;
// Ensure these are only emitted once.
std::set<std::string> Emitted;
for (auto &Def : Defs) {
- if (Emitted.find(Def->getMangledName()) != Emitted.end() || !Def->hasImmediate())
+ if (Emitted.find(Def->getMangledName()) != Emitted.end() ||
+ !Def->hasImmediate())
continue;
// If the Def has a body (operation DAGs), it is not a __builtin_neon_
- if(Def->hasBody()) continue;
+ if (Def->hasBody())
+ continue;
OS << "case NEON::BI__builtin_neon_" << Def->getMangledName() << ":\n";
-
- for(const auto &Check: Def->getImmChecks()){
- EltType = std::get<2>(Check); // elt type argument
- if(EltType >= 0)
+
+ for (const auto &Check : Def->getImmChecks()) {
+ EltType = std::get<2>(Check); // elt type argument
+ if (EltType >= 0)
EltType = Def->getParamType(EltType).getNeonEnum();
- OS << " ImmChecks.push_back(std::make_tuple(" << std::get<0>(Check) <<
- ", " << std::get<1>(Check) << ", " << EltType << ")); \n";
+ OS << " ImmChecks.push_back(std::make_tuple(" << std::get<0>(Check)
+ << ", " << std::get<1>(Check) << ", " << EltType << ")); \n";
OS << " break;\n";
}
Emitted.insert(Def->getMangledName());
``````````
</details>
https://github.com/llvm/llvm-project/pull/100278
More information about the cfe-commits
mailing list