[llvm] r372343 - [SVFS] Vector Function ABI demangling.

Francesco Petrogalli via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 19 10:47:32 PDT 2019


Author: fpetrogalli
Date: Thu Sep 19 10:47:32 2019
New Revision: 372343

URL: http://llvm.org/viewvc/llvm-project?rev=372343&view=rev
Log:
[SVFS] Vector Function ABI demangling.

This patch implements the demangling functionality as described in the
Vector Function ABI. This patch will be used to implement the
SearchVectorFunctionSystem (SVFS) as described in the RFC:

http://lists.llvm.org/pipermail/llvm-dev/2019-June/133484.html

A fuzzer is added to test the demangling utility.

Patch by Sumedh Arani <sumedh.arani at arm.com>

Differential revision: https://reviews.llvm.org/D66024

Added:
    llvm/trunk/lib/Analysis/VFABIDemangling.cpp
    llvm/trunk/tools/vfabi-demangle-fuzzer/
    llvm/trunk/tools/vfabi-demangle-fuzzer/CMakeLists.txt
    llvm/trunk/tools/vfabi-demangle-fuzzer/vfabi-demangler-fuzzer.cpp
    llvm/trunk/unittests/Analysis/VectorFunctionABITest.cpp
Modified:
    llvm/trunk/include/llvm/Analysis/VectorUtils.h
    llvm/trunk/lib/Analysis/CMakeLists.txt
    llvm/trunk/unittests/Analysis/CMakeLists.txt

Modified: llvm/trunk/include/llvm/Analysis/VectorUtils.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/VectorUtils.h?rev=372343&r1=372342&r2=372343&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Analysis/VectorUtils.h (original)
+++ llvm/trunk/include/llvm/Analysis/VectorUtils.h Thu Sep 19 10:47:32 2019
@@ -20,6 +20,117 @@
 
 namespace llvm {
 
+/// Describes the type of Parameters
+enum class VFParamKind {
+  Vector,            // No semantic information.
+  OMP_Linear,        // declare simd linear(i)
+  OMP_LinearRef,     // declare simd linear(ref(i))
+  OMP_LinearVal,     // declare simd linear(val(i))
+  OMP_LinearUVal,    // declare simd linear(uval(i))
+  OMP_LinearPos,     // declare simd linear(i:c) uniform(c)
+  OMP_LinearValPos,  // declare simd linear(val(i:c)) uniform(c)
+  OMP_LinearRefPos,  // declare simd linear(ref(i:c)) uniform(c)
+  OMP_LinearUValPos, // declare simd linear(uval(i:c)) uniform(c
+  OMP_Uniform,       // declare simd uniform(i)
+  GlobalPredicate,   // Global logical predicate that acts on all lanes
+                     // of the input and output mask concurrently. For
+                     // example, it is implied by the `M` token in the
+                     // Vector Function ABI mangled name.
+  Unknown
+};
+
+/// Describes the type of Instruction Set Architecture
+enum class VFISAKind {
+  AdvancedSIMD, // AArch64 Advanced SIMD (NEON)
+  SVE,          // AArch64 Scalable Vector Extension
+  SSE,          // x86 SSE
+  AVX,          // x86 AVX
+  AVX2,         // x86 AVX2
+  AVX512,       // x86 AVX512
+  Unknown       // Unknown ISA
+};
+
+/// Encapsulates information needed to describe a parameter.
+///
+/// The description of the parameter is not linked directly to
+/// OpenMP or any other vector function description. This structure
+/// is extendible to handle other paradigms that describe vector
+/// functions and their parameters.
+struct VFParameter {
+  unsigned ParamPos;         // Parameter Position in Scalar Function.
+  VFParamKind ParamKind;     // Kind of Parameter.
+  int LinearStepOrPos = 0;   // Step or Position of the Parameter.
+  Align Alignment = Align(); // Optional aligment in bytes, defaulted to 1.
+
+  // Comparison operator.
+  bool operator==(const VFParameter &Other) const {
+    return std::tie(ParamPos, ParamKind, LinearStepOrPos, Alignment) ==
+           std::tie(Other.ParamPos, Other.ParamKind, Other.LinearStepOrPos,
+                    Other.Alignment);
+  }
+};
+
+/// Contains the information about the kind of vectorization
+/// available.
+///
+/// This object in independent on the paradigm used to
+/// represent vector functions. in particular, it is not attached to
+/// any target-specific ABI.
+struct VFShape {
+  unsigned VF;     // Vectorization factor.
+  bool IsScalable; // True if the function is a scalable function.
+  VFISAKind ISA;   // Instruction Set Architecture.
+  SmallVector<VFParameter, 8> Parameters; // List of parameter informations.
+  // Comparison operator.
+  bool operator==(const VFShape &Other) const {
+    return std::tie(VF, IsScalable, ISA, Parameters) ==
+           std::tie(Other.VF, Other.IsScalable, Other.ISA, Other.Parameters);
+  }
+};
+
+/// Holds the VFShape for a specific scalar to vector function mapping.
+struct VFInfo {
+  VFShape Shape;        // Classification of the vector function.
+  StringRef ScalarName; // Scalar Function Name.
+  StringRef VectorName; // Vector Function Name associated to this VFInfo.
+
+  // Comparison operator.
+  bool operator==(const VFInfo &Other) const {
+    return std::tie(Shape, ScalarName, VectorName) ==
+           std::tie(Shape, Other.ScalarName, Other.VectorName);
+  }
+};
+
+namespace VFABI {
+/// Function to contruct a VFInfo out of a mangled names in the
+/// following format:
+///
+/// <VFABI_name>{(<redirection>)}
+///
+/// where <VFABI_name> is the name of the vector function, mangled according
+/// to the rules described in the Vector Function ABI of the target vector
+/// extentsion (or <isa> from now on). The <VFABI_name> is in the following
+/// format:
+///
+/// _ZGV<isa><mask><vlen><parameters>_<scalarname>[(<redirection>)]
+///
+/// This methods support demangling rules for the following <isa>:
+///
+/// * AArch64: https://developer.arm.com/docs/101129/latest
+///
+/// * x86 (libmvec): https://sourceware.org/glibc/wiki/libmvec and
+///  https://sourceware.org/glibc/wiki/libmvec?action=AttachFile&do=view&target=VectorABI.txt
+///
+///
+///
+/// \param MangledName -> input string in the format
+/// _ZGV<isa><mask><vlen><parameters>_<scalarname>[(<redirection>)].
+Optional<VFInfo> tryDemangleForVFABI(StringRef MangledName);
+
+/// Retrieve the `VFParamKind` from a string token.
+VFParamKind getVFParamKindFromString(const StringRef Token);
+} // end namespace VFABI
+
 template <typename T> class ArrayRef;
 class DemandedBits;
 class GetElementPtrInst;

Modified: llvm/trunk/lib/Analysis/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/CMakeLists.txt?rev=372343&r1=372342&r2=372343&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/CMakeLists.txt (original)
+++ llvm/trunk/lib/Analysis/CMakeLists.txt Thu Sep 19 10:47:32 2019
@@ -97,6 +97,7 @@ add_llvm_library(LLVMAnalysis
   ValueLatticeUtils.cpp
   ValueTracking.cpp
   VectorUtils.cpp
+  VFABIDemangling.cpp
 
   ADDITIONAL_HEADER_DIRS
   ${LLVM_MAIN_INCLUDE_DIR}/llvm/Analysis

Added: llvm/trunk/lib/Analysis/VFABIDemangling.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/VFABIDemangling.cpp?rev=372343&view=auto
==============================================================================
--- llvm/trunk/lib/Analysis/VFABIDemangling.cpp (added)
+++ llvm/trunk/lib/Analysis/VFABIDemangling.cpp Thu Sep 19 10:47:32 2019
@@ -0,0 +1,418 @@
+//===- VFABIDemangling.cpp - Vector Function ABI demangling utilities. ---===//
+//
+// 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/Analysis/VectorUtils.h"
+
+using namespace llvm;
+
+namespace {
+/// Utilities for the Vector Function ABI name parser.
+
+/// Return types for the parser functions.
+enum class ParseRet {
+  OK,   // Found.
+  None, // Not found.
+  Error // Syntax error.
+};
+
+/// Extracts the `<isa>` information from the mangled string, and
+/// sets the `ISA` accordingly.
+ParseRet tryParseISA(StringRef &MangledName, VFISAKind &ISA) {
+  if (MangledName.empty())
+    return ParseRet::Error;
+
+  ISA = StringSwitch<VFISAKind>(MangledName.take_front(1))
+            .Case("n", VFISAKind::AdvancedSIMD)
+            .Case("s", VFISAKind::SVE)
+            .Case("b", VFISAKind::SSE)
+            .Case("c", VFISAKind::AVX)
+            .Case("d", VFISAKind::AVX2)
+            .Case("e", VFISAKind::AVX512)
+            .Default(VFISAKind::Unknown);
+
+  MangledName = MangledName.drop_front(1);
+
+  return ParseRet::OK;
+}
+
+/// Extracts the `<mask>` information from the mangled string, and
+/// sets `IsMasked` accordingly. The input string `MangledName` is
+/// left unmodified.
+ParseRet tryParseMask(StringRef &MangledName, bool &IsMasked) {
+  if (MangledName.consume_front("M")) {
+    IsMasked = true;
+    return ParseRet::OK;
+  }
+
+  if (MangledName.consume_front("N")) {
+    IsMasked = false;
+    return ParseRet::OK;
+  }
+
+  return ParseRet::Error;
+}
+
+/// Extract the `<vlen>` information from the mangled string, and
+/// sets `VF` accordingly. A `<vlen> == "x"` token is interpreted as a scalable
+/// vector length. On success, the `<vlen>` token is removed from
+/// the input string `ParseString`.
+///
+ParseRet tryParseVLEN(StringRef &ParseString, unsigned &VF, bool &IsScalable) {
+  if (ParseString.consume_front("x")) {
+    VF = 0;
+    IsScalable = true;
+    return ParseRet::OK;
+  }
+
+  if (ParseString.consumeInteger(10, VF))
+    return ParseRet::Error;
+
+  IsScalable = false;
+  return ParseRet::OK;
+}
+
+/// The function looks for the following strings at the beginning of
+/// the input string `ParseString`:
+///
+///  <token> <number>
+///
+/// On success, it removes the parsed parameter from `ParseString`,
+/// sets `PKind` to the correspondent enum value, sets `Pos` to
+/// <number>, and return success.  On a syntax error, it return a
+/// parsing error. If nothing is parsed, it returns None.
+///
+/// The function expects <token> to be one of "ls", "Rs", "Us" or
+/// "Ls".
+ParseRet tryParseLinearTokenWithRuntimeStep(StringRef &ParseString,
+                                            VFParamKind &PKind, int &Pos,
+                                            const StringRef Token) {
+  if (ParseString.consume_front(Token)) {
+    PKind = VFABI::getVFParamKindFromString(Token);
+    if (ParseString.consumeInteger(10, Pos))
+      return ParseRet::Error;
+    return ParseRet::OK;
+  }
+
+  return ParseRet::None;
+}
+
+/// The function looks for the following stringt at the beginning of
+/// the input string `ParseString`:
+///
+///  <token> <number>
+///
+/// <token> is one of "ls", "Rs", "Us" or "Ls".
+///
+/// On success, it removes the parsed parameter from `ParseString`,
+/// sets `PKind` to the correspondent enum value, sets `StepOrPos` to
+/// <number>, and return success.  On a syntax error, it return a
+/// parsing error. If nothing is parsed, it returns None.
+ParseRet tryParseLinearWithRuntimeStep(StringRef &ParseString,
+                                       VFParamKind &PKind, int &StepOrPos) {
+  ParseRet Ret;
+
+  // "ls" <RuntimeStepPos>
+  Ret = tryParseLinearTokenWithRuntimeStep(ParseString, PKind, StepOrPos, "ls");
+  if (Ret != ParseRet::None)
+    return Ret;
+
+  // "Rs" <RuntimeStepPos>
+  Ret = tryParseLinearTokenWithRuntimeStep(ParseString, PKind, StepOrPos, "Rs");
+  if (Ret != ParseRet::None)
+    return Ret;
+
+  // "Ls" <RuntimeStepPos>
+  Ret = tryParseLinearTokenWithRuntimeStep(ParseString, PKind, StepOrPos, "Ls");
+  if (Ret != ParseRet::None)
+    return Ret;
+
+  // "Us" <RuntimeStepPos>
+  Ret = tryParseLinearTokenWithRuntimeStep(ParseString, PKind, StepOrPos, "Us");
+  if (Ret != ParseRet::None)
+    return Ret;
+
+  return ParseRet::None;
+}
+
+/// The function looks for the following strings at the beginning of
+/// the input string `ParseString`:
+///
+///  <token> {"n"} <number>
+///
+/// On success, it removes the parsed parameter from `ParseString`,
+/// sets `PKind` to the correspondent enum value, sets `LinearStep` to
+/// <number>, and return success.  On a syntax error, it return a
+/// parsing error. If nothing is parsed, it returns None.
+///
+/// The function expects <token> to be one of "l", "R", "U" or
+/// "L".
+ParseRet tryParseCompileTimeLinearToken(StringRef &ParseString,
+                                        VFParamKind &PKind, int &LinearStep,
+                                        const StringRef Token) {
+  if (ParseString.consume_front(Token)) {
+    PKind = VFABI::getVFParamKindFromString(Token);
+    const bool Negate = ParseString.consume_front("n");
+    if (ParseString.consumeInteger(10, LinearStep))
+      LinearStep = 1;
+    if (Negate)
+      LinearStep *= -1;
+    return ParseRet::OK;
+  }
+
+  return ParseRet::None;
+}
+
+/// The function looks for the following strings at the beginning of
+/// the input string `ParseString`:
+///
+/// ["l" | "R" | "U" | "L"] {"n"} <number>
+///
+/// On success, it removes the parsed parameter from `ParseString`,
+/// sets `PKind` to the correspondent enum value, sets `LinearStep` to
+/// <number>, and return success.  On a syntax error, it return a
+/// parsing error. If nothing is parsed, it returns None.
+ParseRet tryParseLinearWithCompileTimeStep(StringRef &ParseString,
+                                           VFParamKind &PKind, int &StepOrPos) {
+  // "l" {"n"} <CompileTimeStep>
+  if (tryParseCompileTimeLinearToken(ParseString, PKind, StepOrPos, "l") ==
+      ParseRet::OK)
+    return ParseRet::OK;
+
+  // "R" {"n"} <CompileTimeStep>
+  if (tryParseCompileTimeLinearToken(ParseString, PKind, StepOrPos, "R") ==
+      ParseRet::OK)
+    return ParseRet::OK;
+
+  // "L" {"n"} <CompileTimeStep>
+  if (tryParseCompileTimeLinearToken(ParseString, PKind, StepOrPos, "L") ==
+      ParseRet::OK)
+    return ParseRet::OK;
+
+  // "U" {"n"} <CompileTimeStep>
+  if (tryParseCompileTimeLinearToken(ParseString, PKind, StepOrPos, "U") ==
+      ParseRet::OK)
+    return ParseRet::OK;
+
+  return ParseRet::None;
+}
+
+/// The function looks for the following strings at the beginning of
+/// the input string `ParseString`:
+///
+/// "u" <number>
+///
+/// On success, it removes the parsed parameter from `ParseString`,
+/// sets `PKind` to the correspondent enum value, sets `Pos` to
+/// <number>, and return success.  On a syntax error, it return a
+/// parsing error. If nothing is parsed, it returns None.
+ParseRet tryParseUniform(StringRef &ParseString, VFParamKind &PKind, int &Pos) {
+  // "u" <Pos>
+  const char *UniformToken = "u";
+  if (ParseString.consume_front(UniformToken)) {
+    PKind = VFABI::getVFParamKindFromString(UniformToken);
+    if (ParseString.consumeInteger(10, Pos))
+      return ParseRet::Error;
+
+    return ParseRet::OK;
+  }
+  return ParseRet::None;
+}
+
+/// Looks into the <parameters> part of the mangled name in search
+/// for valid paramaters at the beginning of the string
+/// `ParseString`.
+///
+/// On success, it removes the parsed parameter from `ParseString`,
+/// sets `PKind` to the correspondent enum value, sets `StepOrPos`
+/// accordingly, and return success.  On a syntax error, it return a
+/// parsing error. If nothing is parsed, it returns None.
+ParseRet tryParseParameter(StringRef &ParseString, VFParamKind &PKind,
+                           int &StepOrPos) {
+  if (ParseString.consume_front("v")) {
+    PKind = VFParamKind::Vector;
+    StepOrPos = 0;
+    return ParseRet::OK;
+  }
+
+  const ParseRet HasLinearRuntime =
+      tryParseLinearWithRuntimeStep(ParseString, PKind, StepOrPos);
+  if (HasLinearRuntime != ParseRet::None)
+    return HasLinearRuntime;
+
+  const ParseRet HasLinearCompileTime =
+      tryParseLinearWithCompileTimeStep(ParseString, PKind, StepOrPos);
+  if (HasLinearCompileTime != ParseRet::None)
+    return HasLinearCompileTime;
+
+  const ParseRet HasUniform = tryParseUniform(ParseString, PKind, StepOrPos);
+  if (HasUniform != ParseRet::None)
+    return HasUniform;
+
+  return ParseRet::None;
+}
+
+/// Looks into the <parameters> part of the mangled name in search
+/// of a valid 'aligned' clause. The function should be invoked
+/// after parsing a parameter via `tryParseParameter`.
+///
+/// On success, it removes the parsed parameter from `ParseString`,
+/// sets `PKind` to the correspondent enum value, sets `StepOrPos`
+/// accordingly, and return success.  On a syntax error, it return a
+/// parsing error. If nothing is parsed, it returns None.
+ParseRet tryParseAlign(StringRef &ParseString, Align &Alignment) {
+  uint64_t Val;
+  //    "a" <number>
+  if (ParseString.consume_front("a")) {
+    if (ParseString.consumeInteger(10, Val))
+      return ParseRet::Error;
+
+    if (!isPowerOf2_64(Val))
+      return ParseRet::Error;
+
+    Alignment = Align(Val);
+
+    return ParseRet::OK;
+  }
+
+  return ParseRet::None;
+}
+} // namespace
+
+// Format of the ABI name:
+// _ZGV<isa><mask><vlen><parameters>_<scalarname>[(<redirection>)]
+Optional<VFInfo> VFABI::tryDemangleForVFABI(StringRef MangledName) {
+  // Assume there is no custom name <redirection>, and therefore the
+  // vector name consists of
+  // _ZGV<isa><mask><vlen><parameters>_<scalarname>.
+  StringRef VectorName = MangledName;
+
+  // Parse the fixed size part of the manled name
+  if (!MangledName.consume_front("_ZGV"))
+    return None;
+
+  // Extract ISA. An unknow ISA is also supported, so we accept all
+  // values.
+  VFISAKind ISA;
+  if (tryParseISA(MangledName, ISA) != ParseRet::OK)
+    return None;
+
+  // Extract <mask>.
+  bool IsMasked;
+  if (tryParseMask(MangledName, IsMasked) != ParseRet::OK)
+    return None;
+
+  // Parse the variable size, starting from <vlen>.
+  unsigned VF;
+  bool IsScalable;
+  if (tryParseVLEN(MangledName, VF, IsScalable) != ParseRet::OK)
+    return None;
+
+  // Parse the <parameters>.
+  ParseRet ParamFound;
+  SmallVector<VFParameter, 8> Parameters;
+  do {
+    const unsigned ParameterPos = Parameters.size();
+    VFParamKind PKind;
+    int StepOrPos;
+    ParamFound = tryParseParameter(MangledName, PKind, StepOrPos);
+
+    // Bail off if there is a parsing error in the parsing of the parameter.
+    if (ParamFound == ParseRet::Error)
+      return None;
+
+    if (ParamFound == ParseRet::OK) {
+      Align Alignment;
+      // Look for the alignment token "a <number>".
+      const ParseRet AlignFound = tryParseAlign(MangledName, Alignment);
+      // Bail off if there is a syntax error in the align token.
+      if (AlignFound == ParseRet::Error)
+        return None;
+
+      // Add the parameter.
+      Parameters.push_back({ParameterPos, PKind, StepOrPos, Alignment});
+    }
+  } while (ParamFound == ParseRet::OK);
+
+  // A valid MangledName mus have at least one valid entry in the
+  // <parameters>.
+  if (Parameters.empty())
+    return None;
+
+  // Check for the <scalarname> and the optional <redirection>, which
+  // are separated from the prefix with "_"
+  if (!MangledName.consume_front("_"))
+    return None;
+
+  // The rest of the string must be in the format:
+  // <scalarname>[(<redirection>)]
+  const StringRef ScalarName =
+      MangledName.take_while([](char In) { return In != '('; });
+
+  if (ScalarName.empty())
+    return None;
+
+  // Reduce MangledName to [(<redirection>)].
+  MangledName = MangledName.ltrim(ScalarName);
+  // Find the optional custom name redirection.
+  if (MangledName.consume_front("(")) {
+    if (!MangledName.consume_back(")"))
+      return None;
+    // Update the vector variant with the one specified by the user.
+    VectorName = MangledName;
+    // If the vector name is missing, bail out.
+    if (VectorName.empty())
+      return None;
+  }
+
+  // When <mask> is "M", we need to add a parameter that is used as
+  // global predicate for the function.
+  if (IsMasked) {
+    const unsigned Pos = Parameters.size();
+    Parameters.push_back({Pos, VFParamKind::GlobalPredicate});
+  }
+
+  // Asserts for parameters of type `VFParamKind::GlobalPredicate`, as
+  // prescribed by the Vector Function ABI specifications supported by
+  // this parser:
+  // 1. Uniqueness.
+  // 2. Must be the last in the parameter list.
+  const auto NGlobalPreds = std::count_if(
+      Parameters.begin(), Parameters.end(), [](const VFParameter PK) {
+        return PK.ParamKind == VFParamKind::GlobalPredicate;
+      });
+  assert(NGlobalPreds < 2 && "Cannot have more than one global predicate.");
+  if (NGlobalPreds)
+    assert(Parameters.back().ParamKind == VFParamKind::GlobalPredicate &&
+           "The global predicate must be the last parameter");
+
+  const VFShape Shape({VF, IsScalable, ISA, Parameters});
+  return VFInfo({Shape, ScalarName, VectorName});
+}
+
+VFParamKind VFABI::getVFParamKindFromString(const StringRef Token) {
+  const VFParamKind ParamKind = StringSwitch<VFParamKind>(Token)
+                                    .Case("v", VFParamKind::Vector)
+                                    .Case("l", VFParamKind::OMP_Linear)
+                                    .Case("R", VFParamKind::OMP_LinearRef)
+                                    .Case("L", VFParamKind::OMP_LinearVal)
+                                    .Case("U", VFParamKind::OMP_LinearUVal)
+                                    .Case("ls", VFParamKind::OMP_LinearPos)
+                                    .Case("Ls", VFParamKind::OMP_LinearValPos)
+                                    .Case("Rs", VFParamKind::OMP_LinearRefPos)
+                                    .Case("Us", VFParamKind::OMP_LinearUValPos)
+                                    .Case("u", VFParamKind::OMP_Uniform)
+                                    .Default(VFParamKind::Unknown);
+
+  if (ParamKind != VFParamKind::Unknown)
+    return ParamKind;
+
+  // This function should never be invoked with an invalid input.
+  llvm_unreachable("This fuction should be invoken only on parameters"
+                   " that have a textual representation in the mangled name"
+                   " of the Vector Function ABI");
+}

Added: llvm/trunk/tools/vfabi-demangle-fuzzer/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/vfabi-demangle-fuzzer/CMakeLists.txt?rev=372343&view=auto
==============================================================================
--- llvm/trunk/tools/vfabi-demangle-fuzzer/CMakeLists.txt (added)
+++ llvm/trunk/tools/vfabi-demangle-fuzzer/CMakeLists.txt Thu Sep 19 10:47:32 2019
@@ -0,0 +1,7 @@
+set(LLVM_LINK_COMPONENTS
+  Analysis
+  Support
+)
+add_llvm_fuzzer(vfabi-demangler-fuzzer
+  vfabi-demangler-fuzzer.cpp
+)

Added: llvm/trunk/tools/vfabi-demangle-fuzzer/vfabi-demangler-fuzzer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/vfabi-demangle-fuzzer/vfabi-demangler-fuzzer.cpp?rev=372343&view=auto
==============================================================================
--- llvm/trunk/tools/vfabi-demangle-fuzzer/vfabi-demangler-fuzzer.cpp (added)
+++ llvm/trunk/tools/vfabi-demangle-fuzzer/vfabi-demangler-fuzzer.cpp Thu Sep 19 10:47:32 2019
@@ -0,0 +1,26 @@
+//===-- vfabi-demangler-fuzzer.cpp - Fuzzer VFABI using lib/Fuzzer   ------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// Build tool to fuzz the demangler for the vector function ABI names.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Analysis/VectorUtils.h"
+
+using namespace llvm;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+  const StringRef MangledName((const char *)Data, Size);
+  const auto Info = VFABI::tryDemangleForVFABI(MangledName);
+
+  // Do not optimize away the return value. Inspired by
+  // https://github.com/google/benchmark/blob/master/include/benchmark/benchmark.h#L307-L345
+  asm volatile("" : : "r,m"(Info) : "memory");
+
+  return 0;
+}

Modified: llvm/trunk/unittests/Analysis/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Analysis/CMakeLists.txt?rev=372343&r1=372342&r2=372343&view=diff
==============================================================================
--- llvm/trunk/unittests/Analysis/CMakeLists.txt (original)
+++ llvm/trunk/unittests/Analysis/CMakeLists.txt Thu Sep 19 10:47:32 2019
@@ -28,6 +28,7 @@ add_llvm_unittest(AnalysisTests
   PhiValuesTest.cpp
   ProfileSummaryInfoTest.cpp
   ScalarEvolutionTest.cpp
+  VectorFunctionABITest.cpp
   SparsePropagation.cpp
   TargetLibraryInfoTest.cpp
   TBAATest.cpp

Added: llvm/trunk/unittests/Analysis/VectorFunctionABITest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Analysis/VectorFunctionABITest.cpp?rev=372343&view=auto
==============================================================================
--- llvm/trunk/unittests/Analysis/VectorFunctionABITest.cpp (added)
+++ llvm/trunk/unittests/Analysis/VectorFunctionABITest.cpp Thu Sep 19 10:47:32 2019
@@ -0,0 +1,439 @@
+//===------- VectorFunctionABITest.cpp - VFABI Unittests  ---------===//
+//
+// 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/Analysis/VectorUtils.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+// This test makes sure that the getFromVFABI method succeeds only on
+// valid values of the string.
+TEST(VectorFunctionABITests, OnlyValidNames) {
+  // Incomplete string.
+  EXPECT_FALSE(VFABI::tryDemangleForVFABI("").hasValue());
+  EXPECT_FALSE(VFABI::tryDemangleForVFABI("_ZGV").hasValue());
+  EXPECT_FALSE(VFABI::tryDemangleForVFABI("_ZGVn").hasValue());
+  EXPECT_FALSE(VFABI::tryDemangleForVFABI("_ZGVnN").hasValue());
+  EXPECT_FALSE(VFABI::tryDemangleForVFABI("_ZGVnN2").hasValue());
+  EXPECT_FALSE(VFABI::tryDemangleForVFABI("_ZGVnN2v").hasValue());
+  EXPECT_FALSE(VFABI::tryDemangleForVFABI("_ZGVnN2v_").hasValue());
+  // Missing parameters.
+  EXPECT_FALSE(VFABI::tryDemangleForVFABI("_ZGVnN2_foo").hasValue());
+  // Missing _ZGV prefix.
+  EXPECT_FALSE(VFABI::tryDemangleForVFABI("_ZVnN2v_foo").hasValue());
+  // Missing <isa>.
+  EXPECT_FALSE(VFABI::tryDemangleForVFABI("_ZGVN2v_foo").hasValue());
+  // Missing <mask>.
+  EXPECT_FALSE(VFABI::tryDemangleForVFABI("_ZGVn2v_foo").hasValue());
+  // Missing <vlen>.
+  EXPECT_FALSE(VFABI::tryDemangleForVFABI("_ZGVnNv_foo").hasValue());
+  // Missing <scalarname>.
+  EXPECT_FALSE(VFABI::tryDemangleForVFABI("_ZGVnN2v_").hasValue());
+  // Missing _ separator.
+  EXPECT_FALSE(VFABI::tryDemangleForVFABI("_ZGVnN2vfoo").hasValue());
+  // Missing <vectorname>.
+  EXPECT_FALSE(VFABI::tryDemangleForVFABI("_ZGVnN2v_foo()").hasValue());
+  // Unterminated name.
+  EXPECT_FALSE(VFABI::tryDemangleForVFABI("_ZGVnN2v_foo(bar").hasValue());
+}
+
+TEST(VectorFunctionABITests, ParamListParsing) {
+  // Testing "vl16Ls32R3l"
+  const auto OptVFS = VFABI::tryDemangleForVFABI("_ZGVnN2vl16Ls32R3l_foo");
+  EXPECT_TRUE(OptVFS.hasValue());
+  const VFInfo VFS = OptVFS.getValue();
+  EXPECT_EQ(VFS.Shape.Parameters.size(), (unsigned)5);
+  EXPECT_EQ(VFS.Shape.Parameters[0], VFParameter({0, VFParamKind::Vector, 0}));
+  EXPECT_EQ(VFS.Shape.Parameters[1],
+            VFParameter({1, VFParamKind::OMP_Linear, 16}));
+  EXPECT_EQ(VFS.Shape.Parameters[2],
+            VFParameter({2, VFParamKind::OMP_LinearValPos, 32}));
+  EXPECT_EQ(VFS.Shape.Parameters[3],
+            VFParameter({3, VFParamKind::OMP_LinearRef, 3}));
+  EXPECT_EQ(VFS.Shape.Parameters[4],
+            VFParameter({4, VFParamKind::OMP_Linear, 1}));
+}
+
+TEST(VectorFunctionABITests, ScalarNameAndVectorName) {
+  // Parse Scalar Name
+  const auto A = VFABI::tryDemangleForVFABI("_ZGVnM2v_sin");
+  const auto B = VFABI::tryDemangleForVFABI("_ZGVnM2v_sin(UserFunc)");
+  const auto C = VFABI::tryDemangleForVFABI("_ZGVnM2v___sin_sin_sin");
+  EXPECT_TRUE(A.hasValue());
+  EXPECT_TRUE(B.hasValue());
+  EXPECT_TRUE(C.hasValue());
+  EXPECT_EQ(A.getValue().ScalarName, "sin");
+  EXPECT_EQ(B.getValue().ScalarName, "sin");
+  EXPECT_EQ(C.getValue().ScalarName, "__sin_sin_sin");
+  EXPECT_EQ(A.getValue().VectorName, "_ZGVnM2v_sin");
+  EXPECT_EQ(B.getValue().VectorName, "UserFunc");
+  EXPECT_EQ(C.getValue().VectorName, "_ZGVnM2v___sin_sin_sin");
+}
+
+namespace {
+// Test fixture needed that holds the veariables needed by the parser.
+class VFABIParserTest : public ::testing::Test {
+private:
+  // Parser output.
+  VFInfo Info;
+  // Reset the parser output references.
+  void reset() { Info = VFInfo(); }
+
+protected:
+  // Referencies to the parser output field.
+  unsigned &VF = Info.Shape.VF;
+  VFISAKind &ISA = Info.Shape.ISA;
+  SmallVector<VFParameter, 8> &Parameters = Info.Shape.Parameters;
+  StringRef &ScalarName = Info.ScalarName;
+  StringRef &VectorName = Info.VectorName;
+  bool &IsScalable = Info.Shape.IsScalable;
+  // Invoke the parser.
+  bool invokeParser(const StringRef MangledName) {
+    reset();
+    const auto OptInfo = VFABI::tryDemangleForVFABI(MangledName);
+    if (OptInfo.hasValue()) {
+      Info = OptInfo.getValue();
+      return true;
+    }
+
+    return false;
+  }
+  // Checks that 1. the last Parameter in the Shape is of type
+  // VFParamKind::GlobalPredicate and 2. it is the only one of such
+  // type.
+  bool IsMasked() const {
+    const auto NGlobalPreds =
+        std::count_if(Info.Shape.Parameters.begin(),
+                      Info.Shape.Parameters.end(), [](const VFParameter PK) {
+                        return PK.ParamKind == VFParamKind::GlobalPredicate;
+                      });
+    return NGlobalPreds == 1 && Info.Shape.Parameters.back().ParamKind ==
+                                    VFParamKind::GlobalPredicate;
+  }
+};
+} // unnamed namespace
+
+TEST_F(VFABIParserTest, Parse) {
+  EXPECT_TRUE(invokeParser("_ZGVnN2vls2Ls27Us4Rs5l1L10U100R1000_sin"));
+  EXPECT_EQ(VF, (unsigned)2);
+  EXPECT_FALSE(IsMasked());
+  EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD);
+  EXPECT_FALSE(IsScalable);
+  EXPECT_EQ(Parameters.size(), (unsigned)9);
+  EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector, 0}));
+  EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::OMP_LinearPos, 2}));
+  EXPECT_EQ(Parameters[2], VFParameter({2, VFParamKind::OMP_LinearValPos, 27}));
+  EXPECT_EQ(Parameters[3], VFParameter({3, VFParamKind::OMP_LinearUValPos, 4}));
+  EXPECT_EQ(Parameters[4], VFParameter({4, VFParamKind::OMP_LinearRefPos, 5}));
+  EXPECT_EQ(Parameters[5], VFParameter({5, VFParamKind::OMP_Linear, 1}));
+  EXPECT_EQ(Parameters[6], VFParameter({6, VFParamKind::OMP_LinearVal, 10}));
+  EXPECT_EQ(Parameters[7], VFParameter({7, VFParamKind::OMP_LinearUVal, 100}));
+  EXPECT_EQ(Parameters[8], VFParameter({8, VFParamKind::OMP_LinearRef, 1000}));
+  EXPECT_EQ(ScalarName, "sin");
+  EXPECT_EQ(VectorName, "_ZGVnN2vls2Ls27Us4Rs5l1L10U100R1000_sin");
+}
+
+TEST_F(VFABIParserTest, ParseVectorName) {
+  EXPECT_TRUE(invokeParser("_ZGVnN2v_sin(my_v_sin)"));
+  EXPECT_EQ(VF, (unsigned)2);
+  EXPECT_FALSE(IsMasked());
+  EXPECT_FALSE(IsScalable);
+  EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD);
+  EXPECT_EQ(Parameters.size(), (unsigned)1);
+  EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector, 0}));
+  EXPECT_EQ(ScalarName, "sin");
+  EXPECT_EQ(VectorName, "my_v_sin");
+}
+
+TEST_F(VFABIParserTest, LinearWithCompileTimeNegativeStep) {
+  EXPECT_TRUE(invokeParser("_ZGVnN2ln1Ln10Un100Rn1000_sin"));
+  EXPECT_EQ(VF, (unsigned)2);
+  EXPECT_FALSE(IsMasked());
+  EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD);
+  EXPECT_FALSE(IsScalable);
+  EXPECT_EQ(Parameters.size(), (unsigned)4);
+  EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::OMP_Linear, -1}));
+  EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::OMP_LinearVal, -10}));
+  EXPECT_EQ(Parameters[2], VFParameter({2, VFParamKind::OMP_LinearUVal, -100}));
+  EXPECT_EQ(Parameters[3], VFParameter({3, VFParamKind::OMP_LinearRef, -1000}));
+  EXPECT_EQ(ScalarName, "sin");
+  EXPECT_EQ(VectorName, "_ZGVnN2ln1Ln10Un100Rn1000_sin");
+}
+
+TEST_F(VFABIParserTest, ParseScalableSVE) {
+  EXPECT_TRUE(invokeParser("_ZGVsMxv_sin"));
+  EXPECT_EQ(VF, (unsigned)0);
+  EXPECT_TRUE(IsMasked());
+  EXPECT_TRUE(IsScalable);
+  EXPECT_EQ(ISA, VFISAKind::SVE);
+  EXPECT_EQ(ScalarName, "sin");
+  EXPECT_EQ(VectorName, "_ZGVsMxv_sin");
+}
+
+TEST_F(VFABIParserTest, ParseFixedWidthSVE) {
+  EXPECT_TRUE(invokeParser("_ZGVsM2v_sin"));
+  EXPECT_EQ(VF, (unsigned)2);
+  EXPECT_TRUE(IsMasked());
+  EXPECT_FALSE(IsScalable);
+  EXPECT_EQ(ISA, VFISAKind::SVE);
+  EXPECT_EQ(ScalarName, "sin");
+  EXPECT_EQ(VectorName, "_ZGVsM2v_sin");
+}
+
+TEST_F(VFABIParserTest, NotAVectorFunctionABIName) {
+  // Vector names should start with `_ZGV`.
+  EXPECT_FALSE(invokeParser("ZGVnN2v_sin"));
+}
+
+TEST_F(VFABIParserTest, LinearWithRuntimeStep) {
+  EXPECT_FALSE(invokeParser("_ZGVnN2ls_sin"))
+      << "A number should be present after \"ls\".";
+  EXPECT_TRUE(invokeParser("_ZGVnN2ls2_sin"));
+  EXPECT_FALSE(invokeParser("_ZGVnN2Rs_sin"))
+      << "A number should be present after \"Rs\".";
+  EXPECT_TRUE(invokeParser("_ZGVnN2Rs4_sin"));
+  EXPECT_FALSE(invokeParser("_ZGVnN2Ls_sin"))
+      << "A number should be present after \"Ls\".";
+  EXPECT_TRUE(invokeParser("_ZGVnN2Ls6_sin"));
+  EXPECT_FALSE(invokeParser("_ZGVnN2Us_sin"))
+      << "A number should be present after \"Us\".";
+  EXPECT_TRUE(invokeParser("_ZGVnN2Us8_sin"));
+}
+
+TEST_F(VFABIParserTest, LinearWithoutCompileTime) {
+  EXPECT_TRUE(invokeParser("_ZGVnN3lLRUlnLnRnUn_sin"));
+  EXPECT_EQ(Parameters.size(), (unsigned)8);
+  EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::OMP_Linear, 1}));
+  EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::OMP_LinearVal, 1}));
+  EXPECT_EQ(Parameters[2], VFParameter({2, VFParamKind::OMP_LinearRef, 1}));
+  EXPECT_EQ(Parameters[3], VFParameter({3, VFParamKind::OMP_LinearUVal, 1}));
+  EXPECT_EQ(Parameters[4], VFParameter({4, VFParamKind::OMP_Linear, -1}));
+  EXPECT_EQ(Parameters[5], VFParameter({5, VFParamKind::OMP_LinearVal, -1}));
+  EXPECT_EQ(Parameters[6], VFParameter({6, VFParamKind::OMP_LinearRef, -1}));
+  EXPECT_EQ(Parameters[7], VFParameter({7, VFParamKind::OMP_LinearUVal, -1}));
+}
+
+TEST_F(VFABIParserTest, ISA) {
+  EXPECT_TRUE(invokeParser("_ZGVqN2v_sin"));
+  EXPECT_EQ(ISA, VFISAKind::Unknown);
+
+  EXPECT_TRUE(invokeParser("_ZGVnN2v_sin"));
+  EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD);
+
+  EXPECT_TRUE(invokeParser("_ZGVsN2v_sin"));
+  EXPECT_EQ(ISA, VFISAKind::SVE);
+
+  EXPECT_TRUE(invokeParser("_ZGVbN2v_sin"));
+  EXPECT_EQ(ISA, VFISAKind::SSE);
+
+  EXPECT_TRUE(invokeParser("_ZGVcN2v_sin"));
+  EXPECT_EQ(ISA, VFISAKind::AVX);
+
+  EXPECT_TRUE(invokeParser("_ZGVdN2v_sin"));
+  EXPECT_EQ(ISA, VFISAKind::AVX2);
+
+  EXPECT_TRUE(invokeParser("_ZGVeN2v_sin"));
+  EXPECT_EQ(ISA, VFISAKind::AVX512);
+}
+
+TEST_F(VFABIParserTest, InvalidMask) {
+  EXPECT_FALSE(invokeParser("_ZGVsK2v_sin"));
+}
+
+TEST_F(VFABIParserTest, InvalidParameter) {
+  EXPECT_FALSE(invokeParser("_ZGVsM2vX_sin"));
+}
+
+TEST_F(VFABIParserTest, Align) {
+  EXPECT_TRUE(invokeParser("_ZGVsN2l2a2_sin"));
+  EXPECT_EQ(Parameters.size(), (unsigned)1);
+  EXPECT_EQ(Parameters[0].Alignment, Align(2));
+
+  // Missing alignement value.
+  EXPECT_FALSE(invokeParser("_ZGVsM2l2a_sin"));
+  // Invalid alignment token "x".
+  EXPECT_FALSE(invokeParser("_ZGVsM2l2ax_sin"));
+  // Alignment MUST be associated to a paramater.
+  EXPECT_FALSE(invokeParser("_ZGVsM2a2_sin"));
+  // Alignment must be a power of 2.
+  EXPECT_FALSE(invokeParser("_ZGVsN2l2a0_sin"));
+  EXPECT_TRUE(invokeParser("_ZGVsN2l2a1_sin"));
+  EXPECT_FALSE(invokeParser("_ZGVsN2l2a3_sin"));
+  EXPECT_FALSE(invokeParser("_ZGVsN2l2a6_sin"));
+}
+
+TEST_F(VFABIParserTest, ParseUniform) {
+  EXPECT_TRUE(invokeParser("_ZGVnN2u0_sin"));
+  EXPECT_EQ(VF, (unsigned)2);
+  EXPECT_FALSE(IsMasked());
+  EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD);
+  EXPECT_FALSE(IsScalable);
+  EXPECT_EQ(Parameters.size(), (unsigned)1);
+  EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::OMP_Uniform, 0}));
+  EXPECT_EQ(ScalarName, "sin");
+  EXPECT_EQ(VectorName, "_ZGVnN2u0_sin");
+
+  EXPECT_FALSE(invokeParser("_ZGVnN2u_sin"));
+  EXPECT_FALSE(invokeParser("_ZGVnN2ul_sin"));
+}
+
+TEST_F(VFABIParserTest, ISAIndependentMangling) {
+  // This test makes sure that the mangling of the parameters in
+  // independent on the <isa> token.
+  const SmallVector<VFParameter, 8> ExpectedParams = {
+      VFParameter({0, VFParamKind::Vector, 0}),
+      VFParameter({1, VFParamKind::OMP_LinearPos, 2}),
+      VFParameter({2, VFParamKind::OMP_LinearValPos, 27}),
+      VFParameter({3, VFParamKind::OMP_LinearUValPos, 4}),
+      VFParameter({4, VFParamKind::OMP_LinearRefPos, 5}),
+      VFParameter({5, VFParamKind::OMP_Linear, 1}),
+      VFParameter({6, VFParamKind::OMP_LinearVal, 10}),
+      VFParameter({7, VFParamKind::OMP_LinearUVal, 100}),
+      VFParameter({8, VFParamKind::OMP_LinearRef, 1000}),
+      VFParameter({9, VFParamKind::OMP_Uniform, 2}),
+  };
+
+#define __COMMON_CHECKS                                                        \
+  do {                                                                         \
+    EXPECT_EQ(VF, (unsigned)2);                                                \
+    EXPECT_FALSE(IsMasked());                                                  \
+    EXPECT_FALSE(IsScalable);                                                  \
+    EXPECT_EQ(Parameters.size(), (unsigned)10);                                \
+    EXPECT_EQ(Parameters, ExpectedParams);                                     \
+    EXPECT_EQ(ScalarName, "sin");                                              \
+  } while (0)
+
+  // Advanced SIMD: <isa> = "n"
+  EXPECT_TRUE(invokeParser("_ZGVnN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin"));
+  EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD);
+  __COMMON_CHECKS;
+  EXPECT_EQ(VectorName, "_ZGVnN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin");
+
+  // SVE: <isa> = "s"
+  EXPECT_TRUE(invokeParser("_ZGVsN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin"));
+  EXPECT_EQ(ISA, VFISAKind::SVE);
+  __COMMON_CHECKS;
+  EXPECT_EQ(VectorName, "_ZGVsN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin");
+
+  // SSE: <isa> = "b"
+  EXPECT_TRUE(invokeParser("_ZGVbN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin"));
+  EXPECT_EQ(ISA, VFISAKind::SSE);
+  __COMMON_CHECKS;
+  EXPECT_EQ(VectorName, "_ZGVbN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin");
+
+  // AVX: <isa> = "c"
+  EXPECT_TRUE(invokeParser("_ZGVcN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin"));
+  EXPECT_EQ(ISA, VFISAKind::AVX);
+  __COMMON_CHECKS;
+  EXPECT_EQ(VectorName, "_ZGVcN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin");
+
+  // AVX2: <isa> = "d"
+  EXPECT_TRUE(invokeParser("_ZGVdN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin"));
+  EXPECT_EQ(ISA, VFISAKind::AVX2);
+  __COMMON_CHECKS;
+  EXPECT_EQ(VectorName, "_ZGVdN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin");
+
+  // AVX512: <isa> = "e"
+  EXPECT_TRUE(invokeParser("_ZGVeN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin"));
+  EXPECT_EQ(ISA, VFISAKind::AVX512);
+  __COMMON_CHECKS;
+  EXPECT_EQ(VectorName, "_ZGVeN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin");
+
+  // Unknown ISA (randomly using "q"). This test will need update if
+  // some targets decide to use "q" as their ISA token.
+  EXPECT_TRUE(invokeParser("_ZGVqN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin"));
+  EXPECT_EQ(ISA, VFISAKind::Unknown);
+  __COMMON_CHECKS;
+  EXPECT_EQ(VectorName, "_ZGVqN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin");
+
+#undef __COMMON_CHECKS
+}
+
+TEST_F(VFABIParserTest, MissingScalarName) {
+  EXPECT_FALSE(invokeParser("_ZGVnN2v_"));
+}
+
+TEST_F(VFABIParserTest, MissingVectorName) {
+  EXPECT_FALSE(invokeParser("_ZGVnN2v_foo()"));
+}
+
+TEST_F(VFABIParserTest, MissingVectorNameTermination) {
+  EXPECT_FALSE(invokeParser("_ZGVnN2v_foo(bar"));
+}
+
+TEST_F(VFABIParserTest, ParseMaskingNEON) {
+  EXPECT_TRUE(invokeParser("_ZGVnM2v_sin"));
+  EXPECT_EQ(VF, (unsigned)2);
+  EXPECT_TRUE(IsMasked());
+  EXPECT_FALSE(IsScalable);
+  EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD);
+  EXPECT_EQ(Parameters.size(), (unsigned)2);
+  EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));
+  EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate}));
+  EXPECT_EQ(ScalarName, "sin");
+}
+
+TEST_F(VFABIParserTest, ParseMaskingSVE) {
+  EXPECT_TRUE(invokeParser("_ZGVsM2v_sin"));
+  EXPECT_EQ(VF, (unsigned)2);
+  EXPECT_TRUE(IsMasked());
+  EXPECT_FALSE(IsScalable);
+  EXPECT_EQ(ISA, VFISAKind::SVE);
+  EXPECT_EQ(Parameters.size(), (unsigned)2);
+  EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));
+  EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate}));
+  EXPECT_EQ(ScalarName, "sin");
+}
+
+TEST_F(VFABIParserTest, ParseMaskingSSE) {
+  EXPECT_TRUE(invokeParser("_ZGVbM2v_sin"));
+  EXPECT_EQ(VF, (unsigned)2);
+  EXPECT_TRUE(IsMasked());
+  EXPECT_FALSE(IsScalable);
+  EXPECT_EQ(ISA, VFISAKind::SSE);
+  EXPECT_EQ(Parameters.size(), (unsigned)2);
+  EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));
+  EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate}));
+  EXPECT_EQ(ScalarName, "sin");
+}
+
+TEST_F(VFABIParserTest, ParseMaskingAVX) {
+  EXPECT_TRUE(invokeParser("_ZGVcM2v_sin"));
+  EXPECT_EQ(VF, (unsigned)2);
+  EXPECT_TRUE(IsMasked());
+  EXPECT_FALSE(IsScalable);
+  EXPECT_EQ(ISA, VFISAKind::AVX);
+  EXPECT_EQ(Parameters.size(), (unsigned)2);
+  EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));
+  EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate}));
+  EXPECT_EQ(ScalarName, "sin");
+}
+
+TEST_F(VFABIParserTest, ParseMaskingAVX2) {
+  EXPECT_TRUE(invokeParser("_ZGVdM2v_sin"));
+  EXPECT_EQ(VF, (unsigned)2);
+  EXPECT_TRUE(IsMasked());
+  EXPECT_FALSE(IsScalable);
+  EXPECT_EQ(ISA, VFISAKind::AVX2);
+  EXPECT_EQ(Parameters.size(), (unsigned)2);
+  EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));
+  EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate}));
+  EXPECT_EQ(ScalarName, "sin");
+}
+
+TEST_F(VFABIParserTest, ParseMaskingAVX512) {
+  EXPECT_TRUE(invokeParser("_ZGVeM2v_sin"));
+  EXPECT_EQ(VF, (unsigned)2);
+  EXPECT_TRUE(IsMasked());
+  EXPECT_FALSE(IsScalable);
+  EXPECT_EQ(ISA, VFISAKind::AVX512);
+  EXPECT_EQ(Parameters.size(), (unsigned)2);
+  EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));
+  EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate}));
+  EXPECT_EQ(ScalarName, "sin");
+}




More information about the llvm-commits mailing list