diff --git a/clang/include/clang/Basic/arm_neon_incl.td b/clang/include/clang/Basic/arm_neon_incl.td index 28b00d162a00d..6313faf0fa30e 100644 --- a/clang/include/clang/Basic/arm_neon_incl.td +++ b/clang/include/clang/Basic/arm_neon_incl.td @@ -60,6 +60,15 @@ def op; // example: (call "vget_high", $p0) -> "vgetq_high_s16(__p0)" // (assuming $p0 has type int16x8_t). def call; +// call_mangled - Invoke another intrinsic matching the mangled name variation +// of the caller's base type. If there is no intrinsic defined +// that has the variation and takes the given types, an error +// is generated at tblgen time. +// example: (call_mangled "vfma_lane", $p0, $p1) -> "vfma_lane(__p0, __p1)" +// (assuming non-LaneQ caller) +// (call_mangled "vfma_lane", $p0, $p1) -> "vfma_laneq(__p0, __p1)" +// (assuming LaneQ caller) +def call_mangled; // cast - Perform a cast to a different type. This gets emitted as a static // C-style cast. For a pure reinterpret cast (T x = *(T*)&y), use // "bitcast". diff --git a/clang/utils/TableGen/NeonEmitter.cpp b/clang/utils/TableGen/NeonEmitter.cpp index 59ea15493f037..ea4060757a4fe 100644 --- a/clang/utils/TableGen/NeonEmitter.cpp +++ b/clang/utils/TableGen/NeonEmitter.cpp @@ -27,8 +27,9 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/None.h" -#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/Optional.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Casting.h" @@ -518,7 +519,8 @@ class Intrinsic { std::pair emitDagDupTyped(DagInit *DI); std::pair emitDagShuffle(DagInit *DI); std::pair emitDagCast(DagInit *DI, bool IsBitCast); - std::pair emitDagCall(DagInit *DI); + std::pair emitDagCall(DagInit *DI, + bool MatchMangledName); std::pair emitDagNameReplace(DagInit *DI); std::pair emitDagLiteral(DagInit *DI); std::pair emitDagOp(DagInit *DI); @@ -546,7 +548,8 @@ class NeonEmitter { public: /// Called by Intrinsic - this attempts to get an intrinsic that takes /// the given types as arguments. - Intrinsic &getIntrinsic(StringRef Name, ArrayRef Types); + Intrinsic &getIntrinsic(StringRef Name, ArrayRef Types, + Optional MangledName); /// Called by Intrinsic - returns a globally-unique number. unsigned getUniqueNumber() { return UniqueNumber++; } @@ -1383,8 +1386,8 @@ std::pair Intrinsic::DagEmitter::emitDag(DagInit *DI) { return emitDagSaveTemp(DI); if (Op == "op") return emitDagOp(DI); - if (Op == "call") - return emitDagCall(DI); + if (Op == "call" || Op == "call_mangled") + return emitDagCall(DI, Op == "call_mangled"); if (Op == "name_replace") return emitDagNameReplace(DI); if (Op == "literal") @@ -1411,7 +1414,8 @@ std::pair Intrinsic::DagEmitter::emitDagOp(DagInit *DI) { } } -std::pair Intrinsic::DagEmitter::emitDagCall(DagInit *DI) { +std::pair +Intrinsic::DagEmitter::emitDagCall(DagInit *DI, bool MatchMangledName) { std::vector Types; std::vector Values; for (unsigned I = 0; I < DI->getNumArgs() - 1; ++I) { @@ -1427,7 +1431,13 @@ std::pair Intrinsic::DagEmitter::emitDagCall(DagInit *DI) { N = SI->getAsUnquotedString(); else N = emitDagArg(DI->getArg(0), "").second; - Intrinsic &Callee = Intr.Emitter.getIntrinsic(N, Types); + Optional MangledName; + if (MatchMangledName) { + if (Intr.getRecord()->getValueAsBit("isLaneQ")) + N += "q"; + MangledName = Intr.mangleName(N, ClassS); + } + Intrinsic &Callee = Intr.Emitter.getIntrinsic(N, Types, MangledName); // Make sure the callee is known as an early def. Callee.setNeededEarly(); @@ -1832,7 +1842,8 @@ void Intrinsic::indexBody() { // NeonEmitter implementation //===----------------------------------------------------------------------===// -Intrinsic &NeonEmitter::getIntrinsic(StringRef Name, ArrayRef Types) { +Intrinsic &NeonEmitter::getIntrinsic(StringRef Name, ArrayRef Types, + Optional MangledName) { // First, look up the name in the intrinsic map. assert_with_loc(IntrinsicMap.find(Name.str()) != IntrinsicMap.end(), ("Intrinsic '" + Name + "' not found!").str()); @@ -1861,17 +1872,19 @@ Intrinsic &NeonEmitter::getIntrinsic(StringRef Name, ArrayRef Types) { } ErrMsg += ")\n"; + if (MangledName && MangledName != I.getMangledName(true)) + continue; + if (I.getNumParams() != Types.size()) continue; - bool Good = true; - for (unsigned Arg = 0; Arg < Types.size(); ++Arg) { - if (I.getParamType(Arg) != Types[Arg]) { - Good = false; - break; - } - } - if (Good) + unsigned ArgNum = 0; + bool MatchingArgumentTypes = + std::all_of(Types.begin(), Types.end(), [&](const auto &Type) { + return Type == I.getParamType(ArgNum++); + }); + + if (MatchingArgumentTypes) GoodVec.push_back(&I); }