RISCVVEmitter.cpp 43 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352
  1. //===- RISCVVEmitter.cpp - Generate riscv_vector.h for use with clang -----===//
  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. //
  9. // This tablegen backend is responsible for emitting riscv_vector.h which
  10. // includes a declaration and definition of each intrinsic functions specified
  11. // in https://github.com/riscv/rvv-intrinsic-doc.
  12. //
  13. // See also the documentation in include/clang/Basic/riscv_vector.td.
  14. //
  15. //===----------------------------------------------------------------------===//
  16. #include "llvm/ADT/ArrayRef.h"
  17. #include "llvm/ADT/SmallSet.h"
  18. #include "llvm/ADT/StringExtras.h"
  19. #include "llvm/ADT/StringMap.h"
  20. #include "llvm/ADT/StringSet.h"
  21. #include "llvm/ADT/Twine.h"
  22. #include "llvm/TableGen/Error.h"
  23. #include "llvm/TableGen/Record.h"
  24. #include <numeric>
  25. using namespace llvm;
  26. using BasicType = char;
  27. using VScaleVal = Optional<unsigned>;
  28. namespace {
  29. // Exponential LMUL
  30. struct LMULType {
  31. int Log2LMUL;
  32. LMULType(int Log2LMUL);
  33. // Return the C/C++ string representation of LMUL
  34. std::string str() const;
  35. Optional<unsigned> getScale(unsigned ElementBitwidth) const;
  36. void MulLog2LMUL(int Log2LMUL);
  37. LMULType &operator*=(uint32_t RHS);
  38. };
  39. // This class is compact representation of a valid and invalid RVVType.
  40. class RVVType {
  41. enum ScalarTypeKind : uint32_t {
  42. Void,
  43. Size_t,
  44. Ptrdiff_t,
  45. UnsignedLong,
  46. SignedLong,
  47. Boolean,
  48. SignedInteger,
  49. UnsignedInteger,
  50. Float,
  51. Invalid,
  52. };
  53. BasicType BT;
  54. ScalarTypeKind ScalarType = Invalid;
  55. LMULType LMUL;
  56. bool IsPointer = false;
  57. // IsConstant indices are "int", but have the constant expression.
  58. bool IsImmediate = false;
  59. // Const qualifier for pointer to const object or object of const type.
  60. bool IsConstant = false;
  61. unsigned ElementBitwidth = 0;
  62. VScaleVal Scale = 0;
  63. bool Valid;
  64. std::string BuiltinStr;
  65. std::string ClangBuiltinStr;
  66. std::string Str;
  67. std::string ShortStr;
  68. public:
  69. RVVType() : RVVType(BasicType(), 0, StringRef()) {}
  70. RVVType(BasicType BT, int Log2LMUL, StringRef prototype);
  71. // Return the string representation of a type, which is an encoded string for
  72. // passing to the BUILTIN() macro in Builtins.def.
  73. const std::string &getBuiltinStr() const { return BuiltinStr; }
  74. // Return the clang builtin type for RVV vector type which are used in the
  75. // riscv_vector.h header file.
  76. const std::string &getClangBuiltinStr() const { return ClangBuiltinStr; }
  77. // Return the C/C++ string representation of a type for use in the
  78. // riscv_vector.h header file.
  79. const std::string &getTypeStr() const { return Str; }
  80. // Return the short name of a type for C/C++ name suffix.
  81. const std::string &getShortStr() {
  82. // Not all types are used in short name, so compute the short name by
  83. // demanded.
  84. if (ShortStr.empty())
  85. initShortStr();
  86. return ShortStr;
  87. }
  88. bool isValid() const { return Valid; }
  89. bool isScalar() const { return Scale.hasValue() && Scale.getValue() == 0; }
  90. bool isVector() const { return Scale.hasValue() && Scale.getValue() != 0; }
  91. bool isVector(unsigned Width) const {
  92. return isVector() && ElementBitwidth == Width;
  93. }
  94. bool isFloat() const { return ScalarType == ScalarTypeKind::Float; }
  95. bool isSignedInteger() const {
  96. return ScalarType == ScalarTypeKind::SignedInteger;
  97. }
  98. bool isFloatVector(unsigned Width) const {
  99. return isVector() && isFloat() && ElementBitwidth == Width;
  100. }
  101. bool isFloat(unsigned Width) const {
  102. return isFloat() && ElementBitwidth == Width;
  103. }
  104. private:
  105. // Verify RVV vector type and set Valid.
  106. bool verifyType() const;
  107. // Creates a type based on basic types of TypeRange
  108. void applyBasicType();
  109. // Applies a prototype modifier to the current type. The result maybe an
  110. // invalid type.
  111. void applyModifier(StringRef prototype);
  112. // Compute and record a string for legal type.
  113. void initBuiltinStr();
  114. // Compute and record a builtin RVV vector type string.
  115. void initClangBuiltinStr();
  116. // Compute and record a type string for used in the header.
  117. void initTypeStr();
  118. // Compute and record a short name of a type for C/C++ name suffix.
  119. void initShortStr();
  120. };
  121. using RVVTypePtr = RVVType *;
  122. using RVVTypes = std::vector<RVVTypePtr>;
  123. using RISCVPredefinedMacroT = uint8_t;
  124. enum RISCVPredefinedMacro : RISCVPredefinedMacroT {
  125. Basic = 0,
  126. V = 1 << 1,
  127. Zfh = 1 << 2,
  128. RV64 = 1 << 3,
  129. VectorMaxELen64 = 1 << 4,
  130. VectorMaxELenFp32 = 1 << 5,
  131. VectorMaxELenFp64 = 1 << 6,
  132. };
  133. // TODO refactor RVVIntrinsic class design after support all intrinsic
  134. // combination. This represents an instantiation of an intrinsic with a
  135. // particular type and prototype
  136. class RVVIntrinsic {
  137. private:
  138. std::string BuiltinName; // Builtin name
  139. std::string Name; // C intrinsic name.
  140. std::string MangledName;
  141. std::string IRName;
  142. bool IsMask;
  143. bool HasVL;
  144. bool HasPolicy;
  145. bool HasNoMaskedOverloaded;
  146. bool HasAutoDef; // There is automiatic definition in header
  147. std::string ManualCodegen;
  148. RVVTypePtr OutputType; // Builtin output type
  149. RVVTypes InputTypes; // Builtin input types
  150. // The types we use to obtain the specific LLVM intrinsic. They are index of
  151. // InputTypes. -1 means the return type.
  152. std::vector<int64_t> IntrinsicTypes;
  153. RISCVPredefinedMacroT RISCVPredefinedMacros = 0;
  154. unsigned NF = 1;
  155. public:
  156. RVVIntrinsic(StringRef Name, StringRef Suffix, StringRef MangledName,
  157. StringRef MangledSuffix, StringRef IRName, bool IsMask,
  158. bool HasMaskedOffOperand, bool HasVL, bool HasPolicy,
  159. bool HasNoMaskedOverloaded, bool HasAutoDef,
  160. StringRef ManualCodegen, const RVVTypes &Types,
  161. const std::vector<int64_t> &IntrinsicTypes,
  162. const std::vector<StringRef> &RequiredFeatures, unsigned NF);
  163. ~RVVIntrinsic() = default;
  164. StringRef getBuiltinName() const { return BuiltinName; }
  165. StringRef getName() const { return Name; }
  166. StringRef getMangledName() const { return MangledName; }
  167. bool hasVL() const { return HasVL; }
  168. bool hasPolicy() const { return HasPolicy; }
  169. bool hasNoMaskedOverloaded() const { return HasNoMaskedOverloaded; }
  170. bool hasManualCodegen() const { return !ManualCodegen.empty(); }
  171. bool hasAutoDef() const { return HasAutoDef; }
  172. bool isMask() const { return IsMask; }
  173. StringRef getIRName() const { return IRName; }
  174. StringRef getManualCodegen() const { return ManualCodegen; }
  175. RISCVPredefinedMacroT getRISCVPredefinedMacros() const {
  176. return RISCVPredefinedMacros;
  177. }
  178. unsigned getNF() const { return NF; }
  179. const std::vector<int64_t> &getIntrinsicTypes() const {
  180. return IntrinsicTypes;
  181. }
  182. // Return the type string for a BUILTIN() macro in Builtins.def.
  183. std::string getBuiltinTypeStr() const;
  184. // Emit the code block for switch body in EmitRISCVBuiltinExpr, it should
  185. // init the RVVIntrinsic ID and IntrinsicTypes.
  186. void emitCodeGenSwitchBody(raw_ostream &o) const;
  187. // Emit the macros for mapping C/C++ intrinsic function to builtin functions.
  188. void emitIntrinsicFuncDef(raw_ostream &o) const;
  189. // Emit the mangled function definition.
  190. void emitMangledFuncDef(raw_ostream &o) const;
  191. };
  192. class RVVEmitter {
  193. private:
  194. RecordKeeper &Records;
  195. std::string HeaderCode;
  196. // Concat BasicType, LMUL and Proto as key
  197. StringMap<RVVType> LegalTypes;
  198. StringSet<> IllegalTypes;
  199. public:
  200. RVVEmitter(RecordKeeper &R) : Records(R) {}
  201. /// Emit riscv_vector.h
  202. void createHeader(raw_ostream &o);
  203. /// Emit all the __builtin prototypes and code needed by Sema.
  204. void createBuiltins(raw_ostream &o);
  205. /// Emit all the information needed to map builtin -> LLVM IR intrinsic.
  206. void createCodeGen(raw_ostream &o);
  207. std::string getSuffixStr(char Type, int Log2LMUL, StringRef Prototypes);
  208. private:
  209. /// Create all intrinsics and add them to \p Out
  210. void createRVVIntrinsics(std::vector<std::unique_ptr<RVVIntrinsic>> &Out);
  211. /// Create Headers and add them to \p Out
  212. void createRVVHeaders(raw_ostream &OS);
  213. /// Compute output and input types by applying different config (basic type
  214. /// and LMUL with type transformers). It also record result of type in legal
  215. /// or illegal set to avoid compute the same config again. The result maybe
  216. /// have illegal RVVType.
  217. Optional<RVVTypes> computeTypes(BasicType BT, int Log2LMUL, unsigned NF,
  218. ArrayRef<std::string> PrototypeSeq);
  219. Optional<RVVTypePtr> computeType(BasicType BT, int Log2LMUL, StringRef Proto);
  220. /// Emit Acrh predecessor definitions and body, assume the element of Defs are
  221. /// sorted by extension.
  222. void emitArchMacroAndBody(
  223. std::vector<std::unique_ptr<RVVIntrinsic>> &Defs, raw_ostream &o,
  224. std::function<void(raw_ostream &, const RVVIntrinsic &)>);
  225. // Emit the architecture preprocessor definitions. Return true when emits
  226. // non-empty string.
  227. bool emitMacroRestrictionStr(RISCVPredefinedMacroT PredefinedMacros,
  228. raw_ostream &o);
  229. // Slice Prototypes string into sub prototype string and process each sub
  230. // prototype string individually in the Handler.
  231. void parsePrototypes(StringRef Prototypes,
  232. std::function<void(StringRef)> Handler);
  233. };
  234. } // namespace
  235. //===----------------------------------------------------------------------===//
  236. // Type implementation
  237. //===----------------------------------------------------------------------===//
  238. LMULType::LMULType(int NewLog2LMUL) {
  239. // Check Log2LMUL is -3, -2, -1, 0, 1, 2, 3
  240. assert(NewLog2LMUL <= 3 && NewLog2LMUL >= -3 && "Bad LMUL number!");
  241. Log2LMUL = NewLog2LMUL;
  242. }
  243. std::string LMULType::str() const {
  244. if (Log2LMUL < 0)
  245. return "mf" + utostr(1ULL << (-Log2LMUL));
  246. return "m" + utostr(1ULL << Log2LMUL);
  247. }
  248. VScaleVal LMULType::getScale(unsigned ElementBitwidth) const {
  249. int Log2ScaleResult = 0;
  250. switch (ElementBitwidth) {
  251. default:
  252. break;
  253. case 8:
  254. Log2ScaleResult = Log2LMUL + 3;
  255. break;
  256. case 16:
  257. Log2ScaleResult = Log2LMUL + 2;
  258. break;
  259. case 32:
  260. Log2ScaleResult = Log2LMUL + 1;
  261. break;
  262. case 64:
  263. Log2ScaleResult = Log2LMUL;
  264. break;
  265. }
  266. // Illegal vscale result would be less than 1
  267. if (Log2ScaleResult < 0)
  268. return None;
  269. return 1 << Log2ScaleResult;
  270. }
  271. void LMULType::MulLog2LMUL(int log2LMUL) { Log2LMUL += log2LMUL; }
  272. LMULType &LMULType::operator*=(uint32_t RHS) {
  273. assert(isPowerOf2_32(RHS));
  274. this->Log2LMUL = this->Log2LMUL + Log2_32(RHS);
  275. return *this;
  276. }
  277. RVVType::RVVType(BasicType BT, int Log2LMUL, StringRef prototype)
  278. : BT(BT), LMUL(LMULType(Log2LMUL)) {
  279. applyBasicType();
  280. applyModifier(prototype);
  281. Valid = verifyType();
  282. if (Valid) {
  283. initBuiltinStr();
  284. initTypeStr();
  285. if (isVector()) {
  286. initClangBuiltinStr();
  287. }
  288. }
  289. }
  290. // clang-format off
  291. // boolean type are encoded the ratio of n (SEW/LMUL)
  292. // SEW/LMUL | 1 | 2 | 4 | 8 | 16 | 32 | 64
  293. // c type | vbool64_t | vbool32_t | vbool16_t | vbool8_t | vbool4_t | vbool2_t | vbool1_t
  294. // IR type | nxv1i1 | nxv2i1 | nxv4i1 | nxv8i1 | nxv16i1 | nxv32i1 | nxv64i1
  295. // type\lmul | 1/8 | 1/4 | 1/2 | 1 | 2 | 4 | 8
  296. // -------- |------ | -------- | ------- | ------- | -------- | -------- | --------
  297. // i64 | N/A | N/A | N/A | nxv1i64 | nxv2i64 | nxv4i64 | nxv8i64
  298. // i32 | N/A | N/A | nxv1i32 | nxv2i32 | nxv4i32 | nxv8i32 | nxv16i32
  299. // i16 | N/A | nxv1i16 | nxv2i16 | nxv4i16 | nxv8i16 | nxv16i16 | nxv32i16
  300. // i8 | nxv1i8 | nxv2i8 | nxv4i8 | nxv8i8 | nxv16i8 | nxv32i8 | nxv64i8
  301. // double | N/A | N/A | N/A | nxv1f64 | nxv2f64 | nxv4f64 | nxv8f64
  302. // float | N/A | N/A | nxv1f32 | nxv2f32 | nxv4f32 | nxv8f32 | nxv16f32
  303. // half | N/A | nxv1f16 | nxv2f16 | nxv4f16 | nxv8f16 | nxv16f16 | nxv32f16
  304. // clang-format on
  305. bool RVVType::verifyType() const {
  306. if (ScalarType == Invalid)
  307. return false;
  308. if (isScalar())
  309. return true;
  310. if (!Scale.hasValue())
  311. return false;
  312. if (isFloat() && ElementBitwidth == 8)
  313. return false;
  314. unsigned V = Scale.getValue();
  315. switch (ElementBitwidth) {
  316. case 1:
  317. case 8:
  318. // Check Scale is 1,2,4,8,16,32,64
  319. return (V <= 64 && isPowerOf2_32(V));
  320. case 16:
  321. // Check Scale is 1,2,4,8,16,32
  322. return (V <= 32 && isPowerOf2_32(V));
  323. case 32:
  324. // Check Scale is 1,2,4,8,16
  325. return (V <= 16 && isPowerOf2_32(V));
  326. case 64:
  327. // Check Scale is 1,2,4,8
  328. return (V <= 8 && isPowerOf2_32(V));
  329. }
  330. return false;
  331. }
  332. void RVVType::initBuiltinStr() {
  333. assert(isValid() && "RVVType is invalid");
  334. switch (ScalarType) {
  335. case ScalarTypeKind::Void:
  336. BuiltinStr = "v";
  337. return;
  338. case ScalarTypeKind::Size_t:
  339. BuiltinStr = "z";
  340. if (IsImmediate)
  341. BuiltinStr = "I" + BuiltinStr;
  342. if (IsPointer)
  343. BuiltinStr += "*";
  344. return;
  345. case ScalarTypeKind::Ptrdiff_t:
  346. BuiltinStr = "Y";
  347. return;
  348. case ScalarTypeKind::UnsignedLong:
  349. BuiltinStr = "ULi";
  350. return;
  351. case ScalarTypeKind::SignedLong:
  352. BuiltinStr = "Li";
  353. return;
  354. case ScalarTypeKind::Boolean:
  355. assert(ElementBitwidth == 1);
  356. BuiltinStr += "b";
  357. break;
  358. case ScalarTypeKind::SignedInteger:
  359. case ScalarTypeKind::UnsignedInteger:
  360. switch (ElementBitwidth) {
  361. case 8:
  362. BuiltinStr += "c";
  363. break;
  364. case 16:
  365. BuiltinStr += "s";
  366. break;
  367. case 32:
  368. BuiltinStr += "i";
  369. break;
  370. case 64:
  371. BuiltinStr += "Wi";
  372. break;
  373. default:
  374. llvm_unreachable("Unhandled ElementBitwidth!");
  375. }
  376. if (isSignedInteger())
  377. BuiltinStr = "S" + BuiltinStr;
  378. else
  379. BuiltinStr = "U" + BuiltinStr;
  380. break;
  381. case ScalarTypeKind::Float:
  382. switch (ElementBitwidth) {
  383. case 16:
  384. BuiltinStr += "x";
  385. break;
  386. case 32:
  387. BuiltinStr += "f";
  388. break;
  389. case 64:
  390. BuiltinStr += "d";
  391. break;
  392. default:
  393. llvm_unreachable("Unhandled ElementBitwidth!");
  394. }
  395. break;
  396. default:
  397. llvm_unreachable("ScalarType is invalid!");
  398. }
  399. if (IsImmediate)
  400. BuiltinStr = "I" + BuiltinStr;
  401. if (isScalar()) {
  402. if (IsConstant)
  403. BuiltinStr += "C";
  404. if (IsPointer)
  405. BuiltinStr += "*";
  406. return;
  407. }
  408. BuiltinStr = "q" + utostr(Scale.getValue()) + BuiltinStr;
  409. // Pointer to vector types. Defined for segment load intrinsics.
  410. // segment load intrinsics have pointer type arguments to store the loaded
  411. // vector values.
  412. if (IsPointer)
  413. BuiltinStr += "*";
  414. }
  415. void RVVType::initClangBuiltinStr() {
  416. assert(isValid() && "RVVType is invalid");
  417. assert(isVector() && "Handle Vector type only");
  418. ClangBuiltinStr = "__rvv_";
  419. switch (ScalarType) {
  420. case ScalarTypeKind::Boolean:
  421. ClangBuiltinStr += "bool" + utostr(64 / Scale.getValue()) + "_t";
  422. return;
  423. case ScalarTypeKind::Float:
  424. ClangBuiltinStr += "float";
  425. break;
  426. case ScalarTypeKind::SignedInteger:
  427. ClangBuiltinStr += "int";
  428. break;
  429. case ScalarTypeKind::UnsignedInteger:
  430. ClangBuiltinStr += "uint";
  431. break;
  432. default:
  433. llvm_unreachable("ScalarTypeKind is invalid");
  434. }
  435. ClangBuiltinStr += utostr(ElementBitwidth) + LMUL.str() + "_t";
  436. }
  437. void RVVType::initTypeStr() {
  438. assert(isValid() && "RVVType is invalid");
  439. if (IsConstant)
  440. Str += "const ";
  441. auto getTypeString = [&](StringRef TypeStr) {
  442. if (isScalar())
  443. return Twine(TypeStr + Twine(ElementBitwidth) + "_t").str();
  444. return Twine("v" + TypeStr + Twine(ElementBitwidth) + LMUL.str() + "_t")
  445. .str();
  446. };
  447. switch (ScalarType) {
  448. case ScalarTypeKind::Void:
  449. Str = "void";
  450. return;
  451. case ScalarTypeKind::Size_t:
  452. Str = "size_t";
  453. if (IsPointer)
  454. Str += " *";
  455. return;
  456. case ScalarTypeKind::Ptrdiff_t:
  457. Str = "ptrdiff_t";
  458. return;
  459. case ScalarTypeKind::UnsignedLong:
  460. Str = "unsigned long";
  461. return;
  462. case ScalarTypeKind::SignedLong:
  463. Str = "long";
  464. return;
  465. case ScalarTypeKind::Boolean:
  466. if (isScalar())
  467. Str += "bool";
  468. else
  469. // Vector bool is special case, the formulate is
  470. // `vbool<N>_t = MVT::nxv<64/N>i1` ex. vbool16_t = MVT::4i1
  471. Str += "vbool" + utostr(64 / Scale.getValue()) + "_t";
  472. break;
  473. case ScalarTypeKind::Float:
  474. if (isScalar()) {
  475. if (ElementBitwidth == 64)
  476. Str += "double";
  477. else if (ElementBitwidth == 32)
  478. Str += "float";
  479. else if (ElementBitwidth == 16)
  480. Str += "_Float16";
  481. else
  482. llvm_unreachable("Unhandled floating type.");
  483. } else
  484. Str += getTypeString("float");
  485. break;
  486. case ScalarTypeKind::SignedInteger:
  487. Str += getTypeString("int");
  488. break;
  489. case ScalarTypeKind::UnsignedInteger:
  490. Str += getTypeString("uint");
  491. break;
  492. default:
  493. llvm_unreachable("ScalarType is invalid!");
  494. }
  495. if (IsPointer)
  496. Str += " *";
  497. }
  498. void RVVType::initShortStr() {
  499. switch (ScalarType) {
  500. case ScalarTypeKind::Boolean:
  501. assert(isVector());
  502. ShortStr = "b" + utostr(64 / Scale.getValue());
  503. return;
  504. case ScalarTypeKind::Float:
  505. ShortStr = "f" + utostr(ElementBitwidth);
  506. break;
  507. case ScalarTypeKind::SignedInteger:
  508. ShortStr = "i" + utostr(ElementBitwidth);
  509. break;
  510. case ScalarTypeKind::UnsignedInteger:
  511. ShortStr = "u" + utostr(ElementBitwidth);
  512. break;
  513. default:
  514. PrintFatalError("Unhandled case!");
  515. }
  516. if (isVector())
  517. ShortStr += LMUL.str();
  518. }
  519. void RVVType::applyBasicType() {
  520. switch (BT) {
  521. case 'c':
  522. ElementBitwidth = 8;
  523. ScalarType = ScalarTypeKind::SignedInteger;
  524. break;
  525. case 's':
  526. ElementBitwidth = 16;
  527. ScalarType = ScalarTypeKind::SignedInteger;
  528. break;
  529. case 'i':
  530. ElementBitwidth = 32;
  531. ScalarType = ScalarTypeKind::SignedInteger;
  532. break;
  533. case 'l':
  534. ElementBitwidth = 64;
  535. ScalarType = ScalarTypeKind::SignedInteger;
  536. break;
  537. case 'x':
  538. ElementBitwidth = 16;
  539. ScalarType = ScalarTypeKind::Float;
  540. break;
  541. case 'f':
  542. ElementBitwidth = 32;
  543. ScalarType = ScalarTypeKind::Float;
  544. break;
  545. case 'd':
  546. ElementBitwidth = 64;
  547. ScalarType = ScalarTypeKind::Float;
  548. break;
  549. default:
  550. PrintFatalError("Unhandled type code!");
  551. }
  552. assert(ElementBitwidth != 0 && "Bad element bitwidth!");
  553. }
  554. void RVVType::applyModifier(StringRef Transformer) {
  555. if (Transformer.empty())
  556. return;
  557. // Handle primitive type transformer
  558. auto PType = Transformer.back();
  559. switch (PType) {
  560. case 'e':
  561. Scale = 0;
  562. break;
  563. case 'v':
  564. Scale = LMUL.getScale(ElementBitwidth);
  565. break;
  566. case 'w':
  567. ElementBitwidth *= 2;
  568. LMUL *= 2;
  569. Scale = LMUL.getScale(ElementBitwidth);
  570. break;
  571. case 'q':
  572. ElementBitwidth *= 4;
  573. LMUL *= 4;
  574. Scale = LMUL.getScale(ElementBitwidth);
  575. break;
  576. case 'o':
  577. ElementBitwidth *= 8;
  578. LMUL *= 8;
  579. Scale = LMUL.getScale(ElementBitwidth);
  580. break;
  581. case 'm':
  582. ScalarType = ScalarTypeKind::Boolean;
  583. Scale = LMUL.getScale(ElementBitwidth);
  584. ElementBitwidth = 1;
  585. break;
  586. case '0':
  587. ScalarType = ScalarTypeKind::Void;
  588. break;
  589. case 'z':
  590. ScalarType = ScalarTypeKind::Size_t;
  591. break;
  592. case 't':
  593. ScalarType = ScalarTypeKind::Ptrdiff_t;
  594. break;
  595. case 'u':
  596. ScalarType = ScalarTypeKind::UnsignedLong;
  597. break;
  598. case 'l':
  599. ScalarType = ScalarTypeKind::SignedLong;
  600. break;
  601. default:
  602. PrintFatalError("Illegal primitive type transformers!");
  603. }
  604. Transformer = Transformer.drop_back();
  605. // Extract and compute complex type transformer. It can only appear one time.
  606. if (Transformer.startswith("(")) {
  607. size_t Idx = Transformer.find(')');
  608. assert(Idx != StringRef::npos);
  609. StringRef ComplexType = Transformer.slice(1, Idx);
  610. Transformer = Transformer.drop_front(Idx + 1);
  611. assert(!Transformer.contains('(') &&
  612. "Only allow one complex type transformer");
  613. auto UpdateAndCheckComplexProto = [&]() {
  614. Scale = LMUL.getScale(ElementBitwidth);
  615. const StringRef VectorPrototypes("vwqom");
  616. if (!VectorPrototypes.contains(PType))
  617. PrintFatalError("Complex type transformer only supports vector type!");
  618. if (Transformer.find_first_of("PCKWS") != StringRef::npos)
  619. PrintFatalError(
  620. "Illegal type transformer for Complex type transformer");
  621. };
  622. auto ComputeFixedLog2LMUL =
  623. [&](StringRef Value,
  624. std::function<bool(const int32_t &, const int32_t &)> Compare) {
  625. int32_t Log2LMUL;
  626. Value.getAsInteger(10, Log2LMUL);
  627. if (!Compare(Log2LMUL, LMUL.Log2LMUL)) {
  628. ScalarType = Invalid;
  629. return false;
  630. }
  631. // Update new LMUL
  632. LMUL = LMULType(Log2LMUL);
  633. UpdateAndCheckComplexProto();
  634. return true;
  635. };
  636. auto ComplexTT = ComplexType.split(":");
  637. if (ComplexTT.first == "Log2EEW") {
  638. uint32_t Log2EEW;
  639. ComplexTT.second.getAsInteger(10, Log2EEW);
  640. // update new elmul = (eew/sew) * lmul
  641. LMUL.MulLog2LMUL(Log2EEW - Log2_32(ElementBitwidth));
  642. // update new eew
  643. ElementBitwidth = 1 << Log2EEW;
  644. ScalarType = ScalarTypeKind::SignedInteger;
  645. UpdateAndCheckComplexProto();
  646. } else if (ComplexTT.first == "FixedSEW") {
  647. uint32_t NewSEW;
  648. ComplexTT.second.getAsInteger(10, NewSEW);
  649. // Set invalid type if src and dst SEW are same.
  650. if (ElementBitwidth == NewSEW) {
  651. ScalarType = Invalid;
  652. return;
  653. }
  654. // Update new SEW
  655. ElementBitwidth = NewSEW;
  656. UpdateAndCheckComplexProto();
  657. } else if (ComplexTT.first == "LFixedLog2LMUL") {
  658. // New LMUL should be larger than old
  659. if (!ComputeFixedLog2LMUL(ComplexTT.second, std::greater<int32_t>()))
  660. return;
  661. } else if (ComplexTT.first == "SFixedLog2LMUL") {
  662. // New LMUL should be smaller than old
  663. if (!ComputeFixedLog2LMUL(ComplexTT.second, std::less<int32_t>()))
  664. return;
  665. } else {
  666. PrintFatalError("Illegal complex type transformers!");
  667. }
  668. }
  669. // Compute the remain type transformers
  670. for (char I : Transformer) {
  671. switch (I) {
  672. case 'P':
  673. if (IsConstant)
  674. PrintFatalError("'P' transformer cannot be used after 'C'");
  675. if (IsPointer)
  676. PrintFatalError("'P' transformer cannot be used twice");
  677. IsPointer = true;
  678. break;
  679. case 'C':
  680. if (IsConstant)
  681. PrintFatalError("'C' transformer cannot be used twice");
  682. IsConstant = true;
  683. break;
  684. case 'K':
  685. IsImmediate = true;
  686. break;
  687. case 'U':
  688. ScalarType = ScalarTypeKind::UnsignedInteger;
  689. break;
  690. case 'I':
  691. ScalarType = ScalarTypeKind::SignedInteger;
  692. break;
  693. case 'F':
  694. ScalarType = ScalarTypeKind::Float;
  695. break;
  696. case 'S':
  697. LMUL = LMULType(0);
  698. // Update ElementBitwidth need to update Scale too.
  699. Scale = LMUL.getScale(ElementBitwidth);
  700. break;
  701. default:
  702. PrintFatalError("Illegal non-primitive type transformer!");
  703. }
  704. }
  705. }
  706. //===----------------------------------------------------------------------===//
  707. // RVVIntrinsic implementation
  708. //===----------------------------------------------------------------------===//
  709. RVVIntrinsic::RVVIntrinsic(StringRef NewName, StringRef Suffix,
  710. StringRef NewMangledName, StringRef MangledSuffix,
  711. StringRef IRName, bool IsMask,
  712. bool HasMaskedOffOperand, bool HasVL, bool HasPolicy,
  713. bool HasNoMaskedOverloaded, bool HasAutoDef,
  714. StringRef ManualCodegen, const RVVTypes &OutInTypes,
  715. const std::vector<int64_t> &NewIntrinsicTypes,
  716. const std::vector<StringRef> &RequiredFeatures,
  717. unsigned NF)
  718. : IRName(IRName), IsMask(IsMask), HasVL(HasVL), HasPolicy(HasPolicy),
  719. HasNoMaskedOverloaded(HasNoMaskedOverloaded), HasAutoDef(HasAutoDef),
  720. ManualCodegen(ManualCodegen.str()), NF(NF) {
  721. // Init BuiltinName, Name and MangledName
  722. BuiltinName = NewName.str();
  723. Name = BuiltinName;
  724. if (NewMangledName.empty())
  725. MangledName = NewName.split("_").first.str();
  726. else
  727. MangledName = NewMangledName.str();
  728. if (!Suffix.empty())
  729. Name += "_" + Suffix.str();
  730. if (!MangledSuffix.empty())
  731. MangledName += "_" + MangledSuffix.str();
  732. if (IsMask) {
  733. BuiltinName += "_m";
  734. Name += "_m";
  735. }
  736. // Init RISC-V extensions
  737. for (const auto &T : OutInTypes) {
  738. if (T->isFloatVector(16) || T->isFloat(16))
  739. RISCVPredefinedMacros |= RISCVPredefinedMacro::Zfh;
  740. if (T->isFloatVector(32))
  741. RISCVPredefinedMacros |= RISCVPredefinedMacro::VectorMaxELenFp32;
  742. if (T->isFloatVector(64))
  743. RISCVPredefinedMacros |= RISCVPredefinedMacro::VectorMaxELenFp64;
  744. if (T->isVector(64))
  745. RISCVPredefinedMacros |= RISCVPredefinedMacro::VectorMaxELen64;
  746. }
  747. for (auto Feature : RequiredFeatures) {
  748. if (Feature == "RV64")
  749. RISCVPredefinedMacros |= RISCVPredefinedMacro::RV64;
  750. // Note: Full multiply instruction (mulh, mulhu, mulhsu, smul) for EEW=64
  751. // require V.
  752. if (Feature == "FullMultiply" &&
  753. (RISCVPredefinedMacros & RISCVPredefinedMacro::VectorMaxELen64))
  754. RISCVPredefinedMacros |= RISCVPredefinedMacro::V;
  755. }
  756. // Init OutputType and InputTypes
  757. OutputType = OutInTypes[0];
  758. InputTypes.assign(OutInTypes.begin() + 1, OutInTypes.end());
  759. // IntrinsicTypes is nonmasked version index. Need to update it
  760. // if there is maskedoff operand (It is always in first operand).
  761. IntrinsicTypes = NewIntrinsicTypes;
  762. if (IsMask && HasMaskedOffOperand) {
  763. for (auto &I : IntrinsicTypes) {
  764. if (I >= 0)
  765. I += NF;
  766. }
  767. }
  768. }
  769. std::string RVVIntrinsic::getBuiltinTypeStr() const {
  770. std::string S;
  771. S += OutputType->getBuiltinStr();
  772. for (const auto &T : InputTypes) {
  773. S += T->getBuiltinStr();
  774. }
  775. return S;
  776. }
  777. void RVVIntrinsic::emitCodeGenSwitchBody(raw_ostream &OS) const {
  778. if (!getIRName().empty())
  779. OS << " ID = Intrinsic::riscv_" + getIRName() + ";\n";
  780. if (NF >= 2)
  781. OS << " NF = " + utostr(getNF()) + ";\n";
  782. if (hasManualCodegen()) {
  783. OS << ManualCodegen;
  784. OS << "break;\n";
  785. return;
  786. }
  787. if (isMask()) {
  788. if (hasVL()) {
  789. OS << " std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);\n";
  790. if (hasPolicy())
  791. OS << " Ops.push_back(ConstantInt::get(Ops.back()->getType(),"
  792. " TAIL_UNDISTURBED));\n";
  793. } else {
  794. OS << " std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end());\n";
  795. }
  796. }
  797. OS << " IntrinsicTypes = {";
  798. ListSeparator LS;
  799. for (const auto &Idx : IntrinsicTypes) {
  800. if (Idx == -1)
  801. OS << LS << "ResultType";
  802. else
  803. OS << LS << "Ops[" << Idx << "]->getType()";
  804. }
  805. // VL could be i64 or i32, need to encode it in IntrinsicTypes. VL is
  806. // always last operand.
  807. if (hasVL())
  808. OS << ", Ops.back()->getType()";
  809. OS << "};\n";
  810. OS << " break;\n";
  811. }
  812. void RVVIntrinsic::emitIntrinsicFuncDef(raw_ostream &OS) const {
  813. OS << "__attribute__((__clang_builtin_alias__(";
  814. OS << "__builtin_rvv_" << getBuiltinName() << ")))\n";
  815. OS << OutputType->getTypeStr() << " " << getName() << "(";
  816. // Emit function arguments
  817. if (!InputTypes.empty()) {
  818. ListSeparator LS;
  819. for (unsigned i = 0; i < InputTypes.size(); ++i)
  820. OS << LS << InputTypes[i]->getTypeStr();
  821. }
  822. OS << ");\n";
  823. }
  824. void RVVIntrinsic::emitMangledFuncDef(raw_ostream &OS) const {
  825. OS << "__attribute__((__clang_builtin_alias__(";
  826. OS << "__builtin_rvv_" << getBuiltinName() << ")))\n";
  827. OS << OutputType->getTypeStr() << " " << getMangledName() << "(";
  828. // Emit function arguments
  829. if (!InputTypes.empty()) {
  830. ListSeparator LS;
  831. for (unsigned i = 0; i < InputTypes.size(); ++i)
  832. OS << LS << InputTypes[i]->getTypeStr();
  833. }
  834. OS << ");\n";
  835. }
  836. //===----------------------------------------------------------------------===//
  837. // RVVEmitter implementation
  838. //===----------------------------------------------------------------------===//
  839. void RVVEmitter::createHeader(raw_ostream &OS) {
  840. OS << "/*===---- riscv_vector.h - RISC-V V-extension RVVIntrinsics "
  841. "-------------------===\n"
  842. " *\n"
  843. " *\n"
  844. " * Part of the LLVM Project, under the Apache License v2.0 with LLVM "
  845. "Exceptions.\n"
  846. " * See https://llvm.org/LICENSE.txt for license information.\n"
  847. " * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n"
  848. " *\n"
  849. " *===-----------------------------------------------------------------"
  850. "------===\n"
  851. " */\n\n";
  852. OS << "#ifndef __RISCV_VECTOR_H\n";
  853. OS << "#define __RISCV_VECTOR_H\n\n";
  854. OS << "#include <stdint.h>\n";
  855. OS << "#include <stddef.h>\n\n";
  856. OS << "#ifndef __riscv_vector\n";
  857. OS << "#error \"Vector intrinsics require the vector extension.\"\n";
  858. OS << "#endif\n\n";
  859. OS << "#ifdef __cplusplus\n";
  860. OS << "extern \"C\" {\n";
  861. OS << "#endif\n\n";
  862. createRVVHeaders(OS);
  863. std::vector<std::unique_ptr<RVVIntrinsic>> Defs;
  864. createRVVIntrinsics(Defs);
  865. // Print header code
  866. if (!HeaderCode.empty()) {
  867. OS << HeaderCode;
  868. }
  869. auto printType = [&](auto T) {
  870. OS << "typedef " << T->getClangBuiltinStr() << " " << T->getTypeStr()
  871. << ";\n";
  872. };
  873. constexpr int Log2LMULs[] = {-3, -2, -1, 0, 1, 2, 3};
  874. // Print RVV boolean types.
  875. for (int Log2LMUL : Log2LMULs) {
  876. auto T = computeType('c', Log2LMUL, "m");
  877. if (T.hasValue())
  878. printType(T.getValue());
  879. }
  880. // Print RVV int/float types.
  881. for (char I : StringRef("csil")) {
  882. for (int Log2LMUL : Log2LMULs) {
  883. auto T = computeType(I, Log2LMUL, "v");
  884. if (T.hasValue()) {
  885. printType(T.getValue());
  886. auto UT = computeType(I, Log2LMUL, "Uv");
  887. printType(UT.getValue());
  888. }
  889. }
  890. }
  891. OS << "#if defined(__riscv_zfh)\n";
  892. for (int Log2LMUL : Log2LMULs) {
  893. auto T = computeType('x', Log2LMUL, "v");
  894. if (T.hasValue())
  895. printType(T.getValue());
  896. }
  897. OS << "#endif\n";
  898. OS << "#if defined(__riscv_f)\n";
  899. for (int Log2LMUL : Log2LMULs) {
  900. auto T = computeType('f', Log2LMUL, "v");
  901. if (T.hasValue())
  902. printType(T.getValue());
  903. }
  904. OS << "#endif\n";
  905. OS << "#if defined(__riscv_d)\n";
  906. for (int Log2LMUL : Log2LMULs) {
  907. auto T = computeType('d', Log2LMUL, "v");
  908. if (T.hasValue())
  909. printType(T.getValue());
  910. }
  911. OS << "#endif\n\n";
  912. // The same extension include in the same arch guard marco.
  913. llvm::stable_sort(Defs, [](const std::unique_ptr<RVVIntrinsic> &A,
  914. const std::unique_ptr<RVVIntrinsic> &B) {
  915. return A->getRISCVPredefinedMacros() < B->getRISCVPredefinedMacros();
  916. });
  917. OS << "#define __rvv_ai static __inline__\n";
  918. // Print intrinsic functions with macro
  919. emitArchMacroAndBody(Defs, OS, [](raw_ostream &OS, const RVVIntrinsic &Inst) {
  920. OS << "__rvv_ai ";
  921. Inst.emitIntrinsicFuncDef(OS);
  922. });
  923. OS << "#undef __rvv_ai\n\n";
  924. OS << "#define __riscv_v_intrinsic_overloading 1\n";
  925. // Print Overloaded APIs
  926. OS << "#define __rvv_aio static __inline__ "
  927. "__attribute__((__overloadable__))\n";
  928. emitArchMacroAndBody(Defs, OS, [](raw_ostream &OS, const RVVIntrinsic &Inst) {
  929. if (!Inst.isMask() && !Inst.hasNoMaskedOverloaded())
  930. return;
  931. OS << "__rvv_aio ";
  932. Inst.emitMangledFuncDef(OS);
  933. });
  934. OS << "#undef __rvv_aio\n";
  935. OS << "\n#ifdef __cplusplus\n";
  936. OS << "}\n";
  937. OS << "#endif // __cplusplus\n";
  938. OS << "#endif // __RISCV_VECTOR_H\n";
  939. }
  940. void RVVEmitter::createBuiltins(raw_ostream &OS) {
  941. std::vector<std::unique_ptr<RVVIntrinsic>> Defs;
  942. createRVVIntrinsics(Defs);
  943. // Map to keep track of which builtin names have already been emitted.
  944. StringMap<RVVIntrinsic *> BuiltinMap;
  945. OS << "#if defined(TARGET_BUILTIN) && !defined(RISCVV_BUILTIN)\n";
  946. OS << "#define RISCVV_BUILTIN(ID, TYPE, ATTRS) TARGET_BUILTIN(ID, TYPE, "
  947. "ATTRS, \"zve32x|v\")\n";
  948. OS << "#endif\n";
  949. for (auto &Def : Defs) {
  950. auto P =
  951. BuiltinMap.insert(std::make_pair(Def->getBuiltinName(), Def.get()));
  952. if (!P.second) {
  953. // Verify that this would have produced the same builtin definition.
  954. if (P.first->second->hasAutoDef() != Def->hasAutoDef()) {
  955. PrintFatalError("Builtin with same name has different hasAutoDef");
  956. } else if (!Def->hasAutoDef() && P.first->second->getBuiltinTypeStr() !=
  957. Def->getBuiltinTypeStr()) {
  958. PrintFatalError("Builtin with same name has different type string");
  959. }
  960. continue;
  961. }
  962. OS << "RISCVV_BUILTIN(__builtin_rvv_" << Def->getBuiltinName() << ",\"";
  963. if (!Def->hasAutoDef())
  964. OS << Def->getBuiltinTypeStr();
  965. OS << "\", \"n\")\n";
  966. }
  967. OS << "#undef RISCVV_BUILTIN\n";
  968. }
  969. void RVVEmitter::createCodeGen(raw_ostream &OS) {
  970. std::vector<std::unique_ptr<RVVIntrinsic>> Defs;
  971. createRVVIntrinsics(Defs);
  972. // IR name could be empty, use the stable sort preserves the relative order.
  973. llvm::stable_sort(Defs, [](const std::unique_ptr<RVVIntrinsic> &A,
  974. const std::unique_ptr<RVVIntrinsic> &B) {
  975. return A->getIRName() < B->getIRName();
  976. });
  977. // Map to keep track of which builtin names have already been emitted.
  978. StringMap<RVVIntrinsic *> BuiltinMap;
  979. // Print switch body when the ir name or ManualCodegen changes from previous
  980. // iteration.
  981. RVVIntrinsic *PrevDef = Defs.begin()->get();
  982. for (auto &Def : Defs) {
  983. StringRef CurIRName = Def->getIRName();
  984. if (CurIRName != PrevDef->getIRName() ||
  985. (Def->getManualCodegen() != PrevDef->getManualCodegen())) {
  986. PrevDef->emitCodeGenSwitchBody(OS);
  987. }
  988. PrevDef = Def.get();
  989. auto P =
  990. BuiltinMap.insert(std::make_pair(Def->getBuiltinName(), Def.get()));
  991. if (P.second) {
  992. OS << "case RISCVVector::BI__builtin_rvv_" << Def->getBuiltinName()
  993. << ":\n";
  994. continue;
  995. }
  996. if (P.first->second->getIRName() != Def->getIRName())
  997. PrintFatalError("Builtin with same name has different IRName");
  998. else if (P.first->second->getManualCodegen() != Def->getManualCodegen())
  999. PrintFatalError("Builtin with same name has different ManualCodegen");
  1000. else if (P.first->second->getNF() != Def->getNF())
  1001. PrintFatalError("Builtin with same name has different NF");
  1002. else if (P.first->second->isMask() != Def->isMask())
  1003. PrintFatalError("Builtin with same name has different isMask");
  1004. else if (P.first->second->hasVL() != Def->hasVL())
  1005. PrintFatalError("Builtin with same name has different HasPolicy");
  1006. else if (P.first->second->hasPolicy() != Def->hasPolicy())
  1007. PrintFatalError("Builtin with same name has different HasPolicy");
  1008. else if (P.first->second->getIntrinsicTypes() != Def->getIntrinsicTypes())
  1009. PrintFatalError("Builtin with same name has different IntrinsicTypes");
  1010. }
  1011. Defs.back()->emitCodeGenSwitchBody(OS);
  1012. OS << "\n";
  1013. }
  1014. void RVVEmitter::parsePrototypes(StringRef Prototypes,
  1015. std::function<void(StringRef)> Handler) {
  1016. const StringRef Primaries("evwqom0ztul");
  1017. while (!Prototypes.empty()) {
  1018. size_t Idx = 0;
  1019. // Skip over complex prototype because it could contain primitive type
  1020. // character.
  1021. if (Prototypes[0] == '(')
  1022. Idx = Prototypes.find_first_of(')');
  1023. Idx = Prototypes.find_first_of(Primaries, Idx);
  1024. assert(Idx != StringRef::npos);
  1025. Handler(Prototypes.slice(0, Idx + 1));
  1026. Prototypes = Prototypes.drop_front(Idx + 1);
  1027. }
  1028. }
  1029. std::string RVVEmitter::getSuffixStr(char Type, int Log2LMUL,
  1030. StringRef Prototypes) {
  1031. SmallVector<std::string> SuffixStrs;
  1032. parsePrototypes(Prototypes, [&](StringRef Proto) {
  1033. auto T = computeType(Type, Log2LMUL, Proto);
  1034. SuffixStrs.push_back(T.getValue()->getShortStr());
  1035. });
  1036. return join(SuffixStrs, "_");
  1037. }
  1038. void RVVEmitter::createRVVIntrinsics(
  1039. std::vector<std::unique_ptr<RVVIntrinsic>> &Out) {
  1040. std::vector<Record *> RV = Records.getAllDerivedDefinitions("RVVBuiltin");
  1041. for (auto *R : RV) {
  1042. StringRef Name = R->getValueAsString("Name");
  1043. StringRef SuffixProto = R->getValueAsString("Suffix");
  1044. StringRef MangledName = R->getValueAsString("MangledName");
  1045. StringRef MangledSuffixProto = R->getValueAsString("MangledSuffix");
  1046. StringRef Prototypes = R->getValueAsString("Prototype");
  1047. StringRef TypeRange = R->getValueAsString("TypeRange");
  1048. bool HasMask = R->getValueAsBit("HasMask");
  1049. bool HasMaskedOffOperand = R->getValueAsBit("HasMaskedOffOperand");
  1050. bool HasVL = R->getValueAsBit("HasVL");
  1051. bool HasPolicy = R->getValueAsBit("HasPolicy");
  1052. bool HasNoMaskedOverloaded = R->getValueAsBit("HasNoMaskedOverloaded");
  1053. std::vector<int64_t> Log2LMULList = R->getValueAsListOfInts("Log2LMUL");
  1054. StringRef ManualCodegen = R->getValueAsString("ManualCodegen");
  1055. StringRef ManualCodegenMask = R->getValueAsString("ManualCodegenMask");
  1056. std::vector<int64_t> IntrinsicTypes =
  1057. R->getValueAsListOfInts("IntrinsicTypes");
  1058. std::vector<StringRef> RequiredFeatures =
  1059. R->getValueAsListOfStrings("RequiredFeatures");
  1060. StringRef IRName = R->getValueAsString("IRName");
  1061. StringRef IRNameMask = R->getValueAsString("IRNameMask");
  1062. unsigned NF = R->getValueAsInt("NF");
  1063. StringRef HeaderCodeStr = R->getValueAsString("HeaderCode");
  1064. bool HasAutoDef = HeaderCodeStr.empty();
  1065. if (!HeaderCodeStr.empty()) {
  1066. HeaderCode += HeaderCodeStr.str();
  1067. }
  1068. // Parse prototype and create a list of primitive type with transformers
  1069. // (operand) in ProtoSeq. ProtoSeq[0] is output operand.
  1070. SmallVector<std::string> ProtoSeq;
  1071. parsePrototypes(Prototypes, [&ProtoSeq](StringRef Proto) {
  1072. ProtoSeq.push_back(Proto.str());
  1073. });
  1074. // Compute Builtin types
  1075. SmallVector<std::string> ProtoMaskSeq = ProtoSeq;
  1076. if (HasMask) {
  1077. // If HasMaskedOffOperand, insert result type as first input operand.
  1078. if (HasMaskedOffOperand) {
  1079. if (NF == 1) {
  1080. ProtoMaskSeq.insert(ProtoMaskSeq.begin() + 1, ProtoSeq[0]);
  1081. } else {
  1082. // Convert
  1083. // (void, op0 address, op1 address, ...)
  1084. // to
  1085. // (void, op0 address, op1 address, ..., maskedoff0, maskedoff1, ...)
  1086. for (unsigned I = 0; I < NF; ++I)
  1087. ProtoMaskSeq.insert(
  1088. ProtoMaskSeq.begin() + NF + 1,
  1089. ProtoSeq[1].substr(1)); // Use substr(1) to skip '*'
  1090. }
  1091. }
  1092. if (HasMaskedOffOperand && NF > 1) {
  1093. // Convert
  1094. // (void, op0 address, op1 address, ..., maskedoff0, maskedoff1, ...)
  1095. // to
  1096. // (void, op0 address, op1 address, ..., mask, maskedoff0, maskedoff1,
  1097. // ...)
  1098. ProtoMaskSeq.insert(ProtoMaskSeq.begin() + NF + 1, "m");
  1099. } else {
  1100. // If HasMask, insert 'm' as first input operand.
  1101. ProtoMaskSeq.insert(ProtoMaskSeq.begin() + 1, "m");
  1102. }
  1103. }
  1104. // If HasVL, append 'z' to last operand
  1105. if (HasVL) {
  1106. ProtoSeq.push_back("z");
  1107. ProtoMaskSeq.push_back("z");
  1108. }
  1109. // Create Intrinsics for each type and LMUL.
  1110. for (char I : TypeRange) {
  1111. for (int Log2LMUL : Log2LMULList) {
  1112. Optional<RVVTypes> Types = computeTypes(I, Log2LMUL, NF, ProtoSeq);
  1113. // Ignored to create new intrinsic if there are any illegal types.
  1114. if (!Types.hasValue())
  1115. continue;
  1116. auto SuffixStr = getSuffixStr(I, Log2LMUL, SuffixProto);
  1117. auto MangledSuffixStr = getSuffixStr(I, Log2LMUL, MangledSuffixProto);
  1118. // Create a non-mask intrinsic
  1119. Out.push_back(std::make_unique<RVVIntrinsic>(
  1120. Name, SuffixStr, MangledName, MangledSuffixStr, IRName,
  1121. /*IsMask=*/false, /*HasMaskedOffOperand=*/false, HasVL, HasPolicy,
  1122. HasNoMaskedOverloaded, HasAutoDef, ManualCodegen, Types.getValue(),
  1123. IntrinsicTypes, RequiredFeatures, NF));
  1124. if (HasMask) {
  1125. // Create a mask intrinsic
  1126. Optional<RVVTypes> MaskTypes =
  1127. computeTypes(I, Log2LMUL, NF, ProtoMaskSeq);
  1128. Out.push_back(std::make_unique<RVVIntrinsic>(
  1129. Name, SuffixStr, MangledName, MangledSuffixStr, IRNameMask,
  1130. /*IsMask=*/true, HasMaskedOffOperand, HasVL, HasPolicy,
  1131. HasNoMaskedOverloaded, HasAutoDef, ManualCodegenMask,
  1132. MaskTypes.getValue(), IntrinsicTypes, RequiredFeatures, NF));
  1133. }
  1134. } // end for Log2LMULList
  1135. } // end for TypeRange
  1136. }
  1137. }
  1138. void RVVEmitter::createRVVHeaders(raw_ostream &OS) {
  1139. std::vector<Record *> RVVHeaders =
  1140. Records.getAllDerivedDefinitions("RVVHeader");
  1141. for (auto *R : RVVHeaders) {
  1142. StringRef HeaderCodeStr = R->getValueAsString("HeaderCode");
  1143. OS << HeaderCodeStr.str();
  1144. }
  1145. }
  1146. Optional<RVVTypes>
  1147. RVVEmitter::computeTypes(BasicType BT, int Log2LMUL, unsigned NF,
  1148. ArrayRef<std::string> PrototypeSeq) {
  1149. // LMUL x NF must be less than or equal to 8.
  1150. if ((Log2LMUL >= 1) && (1 << Log2LMUL) * NF > 8)
  1151. return llvm::None;
  1152. RVVTypes Types;
  1153. for (const std::string &Proto : PrototypeSeq) {
  1154. auto T = computeType(BT, Log2LMUL, Proto);
  1155. if (!T.hasValue())
  1156. return llvm::None;
  1157. // Record legal type index
  1158. Types.push_back(T.getValue());
  1159. }
  1160. return Types;
  1161. }
  1162. Optional<RVVTypePtr> RVVEmitter::computeType(BasicType BT, int Log2LMUL,
  1163. StringRef Proto) {
  1164. std::string Idx = Twine(Twine(BT) + Twine(Log2LMUL) + Proto).str();
  1165. // Search first
  1166. auto It = LegalTypes.find(Idx);
  1167. if (It != LegalTypes.end())
  1168. return &(It->second);
  1169. if (IllegalTypes.count(Idx))
  1170. return llvm::None;
  1171. // Compute type and record the result.
  1172. RVVType T(BT, Log2LMUL, Proto);
  1173. if (T.isValid()) {
  1174. // Record legal type index and value.
  1175. LegalTypes.insert({Idx, T});
  1176. return &(LegalTypes[Idx]);
  1177. }
  1178. // Record illegal type index.
  1179. IllegalTypes.insert(Idx);
  1180. return llvm::None;
  1181. }
  1182. void RVVEmitter::emitArchMacroAndBody(
  1183. std::vector<std::unique_ptr<RVVIntrinsic>> &Defs, raw_ostream &OS,
  1184. std::function<void(raw_ostream &, const RVVIntrinsic &)> PrintBody) {
  1185. RISCVPredefinedMacroT PrevMacros =
  1186. (*Defs.begin())->getRISCVPredefinedMacros();
  1187. bool NeedEndif = emitMacroRestrictionStr(PrevMacros, OS);
  1188. for (auto &Def : Defs) {
  1189. RISCVPredefinedMacroT CurMacros = Def->getRISCVPredefinedMacros();
  1190. if (CurMacros != PrevMacros) {
  1191. if (NeedEndif)
  1192. OS << "#endif\n\n";
  1193. NeedEndif = emitMacroRestrictionStr(CurMacros, OS);
  1194. PrevMacros = CurMacros;
  1195. }
  1196. if (Def->hasAutoDef())
  1197. PrintBody(OS, *Def);
  1198. }
  1199. if (NeedEndif)
  1200. OS << "#endif\n\n";
  1201. }
  1202. bool RVVEmitter::emitMacroRestrictionStr(RISCVPredefinedMacroT PredefinedMacros,
  1203. raw_ostream &OS) {
  1204. if (PredefinedMacros == RISCVPredefinedMacro::Basic)
  1205. return false;
  1206. OS << "#if ";
  1207. ListSeparator LS(" && ");
  1208. if (PredefinedMacros & RISCVPredefinedMacro::V)
  1209. OS << LS << "defined(__riscv_v)";
  1210. if (PredefinedMacros & RISCVPredefinedMacro::Zfh)
  1211. OS << LS << "defined(__riscv_zfh)";
  1212. if (PredefinedMacros & RISCVPredefinedMacro::RV64)
  1213. OS << LS << "(__riscv_xlen == 64)";
  1214. if (PredefinedMacros & RISCVPredefinedMacro::VectorMaxELen64)
  1215. OS << LS << "(__riscv_v_elen >= 64)";
  1216. if (PredefinedMacros & RISCVPredefinedMacro::VectorMaxELenFp32)
  1217. OS << LS << "(__riscv_v_elen_fp >= 32)";
  1218. if (PredefinedMacros & RISCVPredefinedMacro::VectorMaxELenFp64)
  1219. OS << LS << "(__riscv_v_elen_fp >= 64)";
  1220. OS << "\n";
  1221. return true;
  1222. }
  1223. namespace clang {
  1224. void EmitRVVHeader(RecordKeeper &Records, raw_ostream &OS) {
  1225. RVVEmitter(Records).createHeader(OS);
  1226. }
  1227. void EmitRVVBuiltins(RecordKeeper &Records, raw_ostream &OS) {
  1228. RVVEmitter(Records).createBuiltins(OS);
  1229. }
  1230. void EmitRVVBuiltinCG(RecordKeeper &Records, raw_ostream &OS) {
  1231. RVVEmitter(Records).createCodeGen(OS);
  1232. }
  1233. } // End namespace clang