From 902e84556a51c70d95088aaa059ab9c494ab3516 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Wed, 13 Nov 2019 15:23:38 +0000 Subject: [ARM,MVE] Add intrinsics for 'administrative' vector operations. This batch of intrinsics includes lots of things that move vector data around or change its type without really affecting its value very much. It includes the `vreinterpretq` family (cast one vector type to another); `vuninitializedq` (create a vector of a given type with don't-care contents); and `vcreateq` (make a 128-bit vector out of two `uint64_t` halves). These are all implemented using completely standard IR that's already tested in existing LLVM unit tests, so I've just written a clang test to check the IR is correct, and left it at that. I've also added some richer infrastructure to the MveEmitter Tablegen backend, to make it specify the exact integer type of integer arguments passed to IR construction functions, and wrap those arguments in a `static_cast` in the autogenerated C++. That was necessary to prevent an overloading ambiguity when passing the integer literal `0` to `IRBuilder::CreateInsertElement`, because otherwise, it could mean either a null pointer `llvm::Value *` or a zero `uint64_t`. Reviewers: ostannard, MarkMurrayARM, dmgreen Subscribers: kristof.beyls, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D70133 --- clang/utils/TableGen/MveEmitter.cpp | 46 ++++++++++++++++++++++++++++--------- 1 file changed, 35 insertions(+), 11 deletions(-) (limited to 'clang/utils') diff --git a/clang/utils/TableGen/MveEmitter.cpp b/clang/utils/TableGen/MveEmitter.cpp index 2941cb6ec08..4258dd0a1f4 100644 --- a/clang/utils/TableGen/MveEmitter.cpp +++ b/clang/utils/TableGen/MveEmitter.cpp @@ -632,10 +632,10 @@ public: StringRef CallPrefix; std::vector Args; std::set AddressArgs; - std::set IntConstantArgs; + std::map IntConstantArgs; IRBuilderResult(StringRef CallPrefix, std::vector Args, std::set AddressArgs, - std::set IntConstantArgs) + std::map IntConstantArgs) : CallPrefix(CallPrefix), Args(Args), AddressArgs(AddressArgs), IntConstantArgs(IntConstantArgs) {} void genCode(raw_ostream &OS, @@ -644,11 +644,13 @@ public: const char *Sep = ""; for (unsigned i = 0, e = Args.size(); i < e; ++i) { Ptr Arg = Args[i]; - if (IntConstantArgs.find(i) != IntConstantArgs.end()) { + auto it = IntConstantArgs.find(i); + if (it != IntConstantArgs.end()) { assert(Arg->hasIntegerConstantValue()); - OS << Sep + OS << Sep << "static_cast<" << it->second << ">(" << ParamAlloc.allocParam("unsigned", - utostr(Arg->integerConstantValue())); + utostr(Arg->integerConstantValue())) + << ")"; } else { OS << Sep << Arg->varname(); } @@ -763,6 +765,14 @@ class ACLEIntrinsic { // shares with at least one other intrinsic. std::string ShortName, FullName; + // A very small number of intrinsics _only_ have a polymorphic + // variant (vuninitializedq taking an unevaluated argument). + bool PolymorphicOnly; + + // Another rarely-used flag indicating that the builtin doesn't + // evaluate its argument(s) at all. + bool NonEvaluating; + const Type *ReturnType; std::vector ArgTypes; std::map ImmediateArgs; @@ -796,6 +806,8 @@ public: return false; } bool polymorphic() const { return ShortName != FullName; } + bool polymorphicOnly() const { return PolymorphicOnly; } + bool nonEvaluating() const { return NonEvaluating; } // External entry point for code generation, called from MveEmitter. void genCode(raw_ostream &OS, CodeGenParamAllocator &ParamAlloc, @@ -1126,11 +1138,15 @@ Result::Ptr MveEmitter::getCodeForDag(DagInit *D, const Result::Scope &Scope, Args.push_back(getCodeForDagArg(D, i, Scope, Param)); if (Op->isSubClassOf("IRBuilderBase")) { std::set AddressArgs; - for (unsigned i : Op->getValueAsListOfInts("address_params")) - AddressArgs.insert(i); - std::set IntConstantArgs; - for (unsigned i : Op->getValueAsListOfInts("int_constant_params")) - IntConstantArgs.insert(i); + std::map IntConstantArgs; + for (Record *sp : Op->getValueAsListOfDefs("special_params")) { + unsigned Index = sp->getValueAsInt("index"); + if (sp->isSubClassOf("IRBuilderAddrParam")) { + AddressArgs.insert(Index); + } else if (sp->isSubClassOf("IRBuilderIntParam")) { + IntConstantArgs[Index] = sp->getValueAsString("type"); + } + } return std::make_shared( Op->getValueAsString("prefix"), Args, AddressArgs, IntConstantArgs); } else if (Op->isSubClassOf("IRIntBase")) { @@ -1235,6 +1251,9 @@ ACLEIntrinsic::ACLEIntrinsic(MveEmitter &ME, Record *R, const Type *Param) } ShortName = join(std::begin(NameParts), std::end(NameParts), "_"); + PolymorphicOnly = R->getValueAsBit("polymorphicOnly"); + NonEvaluating = R->getValueAsBit("nonEvaluating"); + // Process the intrinsic's argument list. DagInit *ArgsDag = R->getValueAsDag("args"); Result::Scope Scope; @@ -1404,6 +1423,8 @@ void MveEmitter::EmitHeader(raw_ostream &OS) { for (bool Polymorphic : {false, true}) { if (Polymorphic && !Int.polymorphic()) continue; + if (!Polymorphic && Int.polymorphicOnly()) + continue; // We also generate each intrinsic under a name like __arm_vfooq // (which is in C language implementation namespace, so it's @@ -1557,7 +1578,10 @@ void MveEmitter::EmitBuiltinDef(raw_ostream &OS) { if (Int.polymorphic()) { StringRef Name = Int.shortName(); if (ShortNamesSeen.find(Name) == ShortNamesSeen.end()) { - OS << "BUILTIN(__builtin_arm_mve_" << Name << ", \"vi.\", \"nt\")\n"; + OS << "BUILTIN(__builtin_arm_mve_" << Name << ", \"vi.\", \"nt"; + if (Int.nonEvaluating()) + OS << "u"; // indicate that this builtin doesn't evaluate its args + OS << "\")\n"; ShortNamesSeen.insert(Name); } } -- cgit v1.2.3