VFABIDemangling.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481
  1. //===- VFABIDemangling.cpp - Vector Function ABI demangling utilities. ---===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #include "llvm/ADT/SmallSet.h"
  9. #include "llvm/ADT/SmallString.h"
  10. #include "llvm/Analysis/VectorUtils.h"
  11. using namespace llvm;
  12. namespace {
  13. /// Utilities for the Vector Function ABI name parser.
  14. /// Return types for the parser functions.
  15. enum class ParseRet {
  16. OK, // Found.
  17. None, // Not found.
  18. Error // Syntax error.
  19. };
  20. /// Extracts the `<isa>` information from the mangled string, and
  21. /// sets the `ISA` accordingly.
  22. ParseRet tryParseISA(StringRef &MangledName, VFISAKind &ISA) {
  23. if (MangledName.empty())
  24. return ParseRet::Error;
  25. if (MangledName.startswith(VFABI::_LLVM_)) {
  26. MangledName = MangledName.drop_front(strlen(VFABI::_LLVM_));
  27. ISA = VFISAKind::LLVM;
  28. } else {
  29. ISA = StringSwitch<VFISAKind>(MangledName.take_front(1))
  30. .Case("n", VFISAKind::AdvancedSIMD)
  31. .Case("s", VFISAKind::SVE)
  32. .Case("b", VFISAKind::SSE)
  33. .Case("c", VFISAKind::AVX)
  34. .Case("d", VFISAKind::AVX2)
  35. .Case("e", VFISAKind::AVX512)
  36. .Default(VFISAKind::Unknown);
  37. MangledName = MangledName.drop_front(1);
  38. }
  39. return ParseRet::OK;
  40. }
  41. /// Extracts the `<mask>` information from the mangled string, and
  42. /// sets `IsMasked` accordingly. The input string `MangledName` is
  43. /// left unmodified.
  44. ParseRet tryParseMask(StringRef &MangledName, bool &IsMasked) {
  45. if (MangledName.consume_front("M")) {
  46. IsMasked = true;
  47. return ParseRet::OK;
  48. }
  49. if (MangledName.consume_front("N")) {
  50. IsMasked = false;
  51. return ParseRet::OK;
  52. }
  53. return ParseRet::Error;
  54. }
  55. /// Extract the `<vlen>` information from the mangled string, and
  56. /// sets `VF` accordingly. A `<vlen> == "x"` token is interpreted as a scalable
  57. /// vector length. On success, the `<vlen>` token is removed from
  58. /// the input string `ParseString`.
  59. ///
  60. ParseRet tryParseVLEN(StringRef &ParseString, unsigned &VF, bool &IsScalable) {
  61. if (ParseString.consume_front("x")) {
  62. // Set VF to 0, to be later adjusted to a value grater than zero
  63. // by looking at the signature of the vector function with
  64. // `getECFromSignature`.
  65. VF = 0;
  66. IsScalable = true;
  67. return ParseRet::OK;
  68. }
  69. if (ParseString.consumeInteger(10, VF))
  70. return ParseRet::Error;
  71. // The token `0` is invalid for VLEN.
  72. if (VF == 0)
  73. return ParseRet::Error;
  74. IsScalable = false;
  75. return ParseRet::OK;
  76. }
  77. /// The function looks for the following strings at the beginning of
  78. /// the input string `ParseString`:
  79. ///
  80. /// <token> <number>
  81. ///
  82. /// On success, it removes the parsed parameter from `ParseString`,
  83. /// sets `PKind` to the correspondent enum value, sets `Pos` to
  84. /// <number>, and return success. On a syntax error, it return a
  85. /// parsing error. If nothing is parsed, it returns None.
  86. ///
  87. /// The function expects <token> to be one of "ls", "Rs", "Us" or
  88. /// "Ls".
  89. ParseRet tryParseLinearTokenWithRuntimeStep(StringRef &ParseString,
  90. VFParamKind &PKind, int &Pos,
  91. const StringRef Token) {
  92. if (ParseString.consume_front(Token)) {
  93. PKind = VFABI::getVFParamKindFromString(Token);
  94. if (ParseString.consumeInteger(10, Pos))
  95. return ParseRet::Error;
  96. return ParseRet::OK;
  97. }
  98. return ParseRet::None;
  99. }
  100. /// The function looks for the following stringt at the beginning of
  101. /// the input string `ParseString`:
  102. ///
  103. /// <token> <number>
  104. ///
  105. /// <token> is one of "ls", "Rs", "Us" or "Ls".
  106. ///
  107. /// On success, it removes the parsed parameter from `ParseString`,
  108. /// sets `PKind` to the correspondent enum value, sets `StepOrPos` to
  109. /// <number>, and return success. On a syntax error, it return a
  110. /// parsing error. If nothing is parsed, it returns None.
  111. ParseRet tryParseLinearWithRuntimeStep(StringRef &ParseString,
  112. VFParamKind &PKind, int &StepOrPos) {
  113. ParseRet Ret;
  114. // "ls" <RuntimeStepPos>
  115. Ret = tryParseLinearTokenWithRuntimeStep(ParseString, PKind, StepOrPos, "ls");
  116. if (Ret != ParseRet::None)
  117. return Ret;
  118. // "Rs" <RuntimeStepPos>
  119. Ret = tryParseLinearTokenWithRuntimeStep(ParseString, PKind, StepOrPos, "Rs");
  120. if (Ret != ParseRet::None)
  121. return Ret;
  122. // "Ls" <RuntimeStepPos>
  123. Ret = tryParseLinearTokenWithRuntimeStep(ParseString, PKind, StepOrPos, "Ls");
  124. if (Ret != ParseRet::None)
  125. return Ret;
  126. // "Us" <RuntimeStepPos>
  127. Ret = tryParseLinearTokenWithRuntimeStep(ParseString, PKind, StepOrPos, "Us");
  128. if (Ret != ParseRet::None)
  129. return Ret;
  130. return ParseRet::None;
  131. }
  132. /// The function looks for the following strings at the beginning of
  133. /// the input string `ParseString`:
  134. ///
  135. /// <token> {"n"} <number>
  136. ///
  137. /// On success, it removes the parsed parameter from `ParseString`,
  138. /// sets `PKind` to the correspondent enum value, sets `LinearStep` to
  139. /// <number>, and return success. On a syntax error, it return a
  140. /// parsing error. If nothing is parsed, it returns None.
  141. ///
  142. /// The function expects <token> to be one of "l", "R", "U" or
  143. /// "L".
  144. ParseRet tryParseCompileTimeLinearToken(StringRef &ParseString,
  145. VFParamKind &PKind, int &LinearStep,
  146. const StringRef Token) {
  147. if (ParseString.consume_front(Token)) {
  148. PKind = VFABI::getVFParamKindFromString(Token);
  149. const bool Negate = ParseString.consume_front("n");
  150. if (ParseString.consumeInteger(10, LinearStep))
  151. LinearStep = 1;
  152. if (Negate)
  153. LinearStep *= -1;
  154. return ParseRet::OK;
  155. }
  156. return ParseRet::None;
  157. }
  158. /// The function looks for the following strings at the beginning of
  159. /// the input string `ParseString`:
  160. ///
  161. /// ["l" | "R" | "U" | "L"] {"n"} <number>
  162. ///
  163. /// On success, it removes the parsed parameter from `ParseString`,
  164. /// sets `PKind` to the correspondent enum value, sets `LinearStep` to
  165. /// <number>, and return success. On a syntax error, it return a
  166. /// parsing error. If nothing is parsed, it returns None.
  167. ParseRet tryParseLinearWithCompileTimeStep(StringRef &ParseString,
  168. VFParamKind &PKind, int &StepOrPos) {
  169. // "l" {"n"} <CompileTimeStep>
  170. if (tryParseCompileTimeLinearToken(ParseString, PKind, StepOrPos, "l") ==
  171. ParseRet::OK)
  172. return ParseRet::OK;
  173. // "R" {"n"} <CompileTimeStep>
  174. if (tryParseCompileTimeLinearToken(ParseString, PKind, StepOrPos, "R") ==
  175. ParseRet::OK)
  176. return ParseRet::OK;
  177. // "L" {"n"} <CompileTimeStep>
  178. if (tryParseCompileTimeLinearToken(ParseString, PKind, StepOrPos, "L") ==
  179. ParseRet::OK)
  180. return ParseRet::OK;
  181. // "U" {"n"} <CompileTimeStep>
  182. if (tryParseCompileTimeLinearToken(ParseString, PKind, StepOrPos, "U") ==
  183. ParseRet::OK)
  184. return ParseRet::OK;
  185. return ParseRet::None;
  186. }
  187. /// Looks into the <parameters> part of the mangled name in search
  188. /// for valid paramaters at the beginning of the string
  189. /// `ParseString`.
  190. ///
  191. /// On success, it removes the parsed parameter from `ParseString`,
  192. /// sets `PKind` to the correspondent enum value, sets `StepOrPos`
  193. /// accordingly, and return success. On a syntax error, it return a
  194. /// parsing error. If nothing is parsed, it returns None.
  195. ParseRet tryParseParameter(StringRef &ParseString, VFParamKind &PKind,
  196. int &StepOrPos) {
  197. if (ParseString.consume_front("v")) {
  198. PKind = VFParamKind::Vector;
  199. StepOrPos = 0;
  200. return ParseRet::OK;
  201. }
  202. if (ParseString.consume_front("u")) {
  203. PKind = VFParamKind::OMP_Uniform;
  204. StepOrPos = 0;
  205. return ParseRet::OK;
  206. }
  207. const ParseRet HasLinearRuntime =
  208. tryParseLinearWithRuntimeStep(ParseString, PKind, StepOrPos);
  209. if (HasLinearRuntime != ParseRet::None)
  210. return HasLinearRuntime;
  211. const ParseRet HasLinearCompileTime =
  212. tryParseLinearWithCompileTimeStep(ParseString, PKind, StepOrPos);
  213. if (HasLinearCompileTime != ParseRet::None)
  214. return HasLinearCompileTime;
  215. return ParseRet::None;
  216. }
  217. /// Looks into the <parameters> part of the mangled name in search
  218. /// of a valid 'aligned' clause. The function should be invoked
  219. /// after parsing a parameter via `tryParseParameter`.
  220. ///
  221. /// On success, it removes the parsed parameter from `ParseString`,
  222. /// sets `PKind` to the correspondent enum value, sets `StepOrPos`
  223. /// accordingly, and return success. On a syntax error, it return a
  224. /// parsing error. If nothing is parsed, it returns None.
  225. ParseRet tryParseAlign(StringRef &ParseString, Align &Alignment) {
  226. uint64_t Val;
  227. // "a" <number>
  228. if (ParseString.consume_front("a")) {
  229. if (ParseString.consumeInteger(10, Val))
  230. return ParseRet::Error;
  231. if (!isPowerOf2_64(Val))
  232. return ParseRet::Error;
  233. Alignment = Align(Val);
  234. return ParseRet::OK;
  235. }
  236. return ParseRet::None;
  237. }
  238. #ifndef NDEBUG
  239. // Verify the assumtion that all vectors in the signature of a vector
  240. // function have the same number of elements.
  241. bool verifyAllVectorsHaveSameWidth(FunctionType *Signature) {
  242. SmallVector<VectorType *, 2> VecTys;
  243. if (auto *RetTy = dyn_cast<VectorType>(Signature->getReturnType()))
  244. VecTys.push_back(RetTy);
  245. for (auto *Ty : Signature->params())
  246. if (auto *VTy = dyn_cast<VectorType>(Ty))
  247. VecTys.push_back(VTy);
  248. if (VecTys.size() <= 1)
  249. return true;
  250. assert(VecTys.size() > 1 && "Invalid number of elements.");
  251. const ElementCount EC = VecTys[0]->getElementCount();
  252. return llvm::all_of(llvm::drop_begin(VecTys), [&EC](VectorType *VTy) {
  253. return (EC == VTy->getElementCount());
  254. });
  255. }
  256. #endif // NDEBUG
  257. // Extract the VectorizationFactor from a given function signature,
  258. // under the assumtion that all vectors have the same number of
  259. // elements, i.e. same ElementCount.Min.
  260. ElementCount getECFromSignature(FunctionType *Signature) {
  261. assert(verifyAllVectorsHaveSameWidth(Signature) &&
  262. "Invalid vector signature.");
  263. if (auto *RetTy = dyn_cast<VectorType>(Signature->getReturnType()))
  264. return RetTy->getElementCount();
  265. for (auto *Ty : Signature->params())
  266. if (auto *VTy = dyn_cast<VectorType>(Ty))
  267. return VTy->getElementCount();
  268. return ElementCount::getFixed(/*Min=*/1);
  269. }
  270. } // namespace
  271. // Format of the ABI name:
  272. // _ZGV<isa><mask><vlen><parameters>_<scalarname>[(<redirection>)]
  273. Optional<VFInfo> VFABI::tryDemangleForVFABI(StringRef MangledName,
  274. const Module &M) {
  275. const StringRef OriginalName = MangledName;
  276. // Assume there is no custom name <redirection>, and therefore the
  277. // vector name consists of
  278. // _ZGV<isa><mask><vlen><parameters>_<scalarname>.
  279. StringRef VectorName = MangledName;
  280. // Parse the fixed size part of the manled name
  281. if (!MangledName.consume_front("_ZGV"))
  282. return None;
  283. // Extract ISA. An unknow ISA is also supported, so we accept all
  284. // values.
  285. VFISAKind ISA;
  286. if (tryParseISA(MangledName, ISA) != ParseRet::OK)
  287. return None;
  288. // Extract <mask>.
  289. bool IsMasked;
  290. if (tryParseMask(MangledName, IsMasked) != ParseRet::OK)
  291. return None;
  292. // Parse the variable size, starting from <vlen>.
  293. unsigned VF;
  294. bool IsScalable;
  295. if (tryParseVLEN(MangledName, VF, IsScalable) != ParseRet::OK)
  296. return None;
  297. // Parse the <parameters>.
  298. ParseRet ParamFound;
  299. SmallVector<VFParameter, 8> Parameters;
  300. do {
  301. const unsigned ParameterPos = Parameters.size();
  302. VFParamKind PKind;
  303. int StepOrPos;
  304. ParamFound = tryParseParameter(MangledName, PKind, StepOrPos);
  305. // Bail off if there is a parsing error in the parsing of the parameter.
  306. if (ParamFound == ParseRet::Error)
  307. return None;
  308. if (ParamFound == ParseRet::OK) {
  309. Align Alignment;
  310. // Look for the alignment token "a <number>".
  311. const ParseRet AlignFound = tryParseAlign(MangledName, Alignment);
  312. // Bail off if there is a syntax error in the align token.
  313. if (AlignFound == ParseRet::Error)
  314. return None;
  315. // Add the parameter.
  316. Parameters.push_back({ParameterPos, PKind, StepOrPos, Alignment});
  317. }
  318. } while (ParamFound == ParseRet::OK);
  319. // A valid MangledName must have at least one valid entry in the
  320. // <parameters>.
  321. if (Parameters.empty())
  322. return None;
  323. // Check for the <scalarname> and the optional <redirection>, which
  324. // are separated from the prefix with "_"
  325. if (!MangledName.consume_front("_"))
  326. return None;
  327. // The rest of the string must be in the format:
  328. // <scalarname>[(<redirection>)]
  329. const StringRef ScalarName =
  330. MangledName.take_while([](char In) { return In != '('; });
  331. if (ScalarName.empty())
  332. return None;
  333. // Reduce MangledName to [(<redirection>)].
  334. MangledName = MangledName.ltrim(ScalarName);
  335. // Find the optional custom name redirection.
  336. if (MangledName.consume_front("(")) {
  337. if (!MangledName.consume_back(")"))
  338. return None;
  339. // Update the vector variant with the one specified by the user.
  340. VectorName = MangledName;
  341. // If the vector name is missing, bail out.
  342. if (VectorName.empty())
  343. return None;
  344. }
  345. // LLVM internal mapping via the TargetLibraryInfo (TLI) must be
  346. // redirected to an existing name.
  347. if (ISA == VFISAKind::LLVM && VectorName == OriginalName)
  348. return None;
  349. // When <mask> is "M", we need to add a parameter that is used as
  350. // global predicate for the function.
  351. if (IsMasked) {
  352. const unsigned Pos = Parameters.size();
  353. Parameters.push_back({Pos, VFParamKind::GlobalPredicate});
  354. }
  355. // Asserts for parameters of type `VFParamKind::GlobalPredicate`, as
  356. // prescribed by the Vector Function ABI specifications supported by
  357. // this parser:
  358. // 1. Uniqueness.
  359. // 2. Must be the last in the parameter list.
  360. const auto NGlobalPreds = std::count_if(
  361. Parameters.begin(), Parameters.end(), [](const VFParameter PK) {
  362. return PK.ParamKind == VFParamKind::GlobalPredicate;
  363. });
  364. assert(NGlobalPreds < 2 && "Cannot have more than one global predicate.");
  365. if (NGlobalPreds)
  366. assert(Parameters.back().ParamKind == VFParamKind::GlobalPredicate &&
  367. "The global predicate must be the last parameter");
  368. // Adjust the VF for scalable signatures. The EC.Min is not encoded
  369. // in the name of the function, but it is encoded in the IR
  370. // signature of the function. We need to extract this information
  371. // because it is needed by the loop vectorizer, which reasons in
  372. // terms of VectorizationFactor or ElementCount. In particular, we
  373. // need to make sure that the VF field of the VFShape class is never
  374. // set to 0.
  375. if (IsScalable) {
  376. const Function *F = M.getFunction(VectorName);
  377. // The declaration of the function must be present in the module
  378. // to be able to retrieve its signature.
  379. if (!F)
  380. return None;
  381. const ElementCount EC = getECFromSignature(F->getFunctionType());
  382. VF = EC.getKnownMinValue();
  383. }
  384. // 1. We don't accept a zero lanes vectorization factor.
  385. // 2. We don't accept the demangling if the vector function is not
  386. // present in the module.
  387. if (VF == 0)
  388. return None;
  389. if (!M.getFunction(VectorName))
  390. return None;
  391. const VFShape Shape({ElementCount::get(VF, IsScalable), Parameters});
  392. return VFInfo({Shape, std::string(ScalarName), std::string(VectorName), ISA});
  393. }
  394. VFParamKind VFABI::getVFParamKindFromString(const StringRef Token) {
  395. const VFParamKind ParamKind = StringSwitch<VFParamKind>(Token)
  396. .Case("v", VFParamKind::Vector)
  397. .Case("l", VFParamKind::OMP_Linear)
  398. .Case("R", VFParamKind::OMP_LinearRef)
  399. .Case("L", VFParamKind::OMP_LinearVal)
  400. .Case("U", VFParamKind::OMP_LinearUVal)
  401. .Case("ls", VFParamKind::OMP_LinearPos)
  402. .Case("Ls", VFParamKind::OMP_LinearValPos)
  403. .Case("Rs", VFParamKind::OMP_LinearRefPos)
  404. .Case("Us", VFParamKind::OMP_LinearUValPos)
  405. .Case("u", VFParamKind::OMP_Uniform)
  406. .Default(VFParamKind::Unknown);
  407. if (ParamKind != VFParamKind::Unknown)
  408. return ParamKind;
  409. // This function should never be invoked with an invalid input.
  410. llvm_unreachable("This fuction should be invoken only on parameters"
  411. " that have a textual representation in the mangled name"
  412. " of the Vector Function ABI");
  413. }