1 //===- NeonEmitter.cpp - Generate arm_neon.h for use with clang -*- C++ -*-===// 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 arm_neon.h, which includes 10 // a declaration and definition of each function specified by the ARM NEON 11 // compiler interface. See ARM document DUI0348B. 12 // 13 // Each NEON instruction is implemented in terms of 1 or more functions which 14 // are suffixed with the element type of the input vectors. Functions may be 15 // implemented in terms of generic vector operations such as +, *, -, etc. or 16 // by calling a __builtin_-prefixed function which will be handled by clang's 17 // CodeGen library. 18 // 19 // Additional validation code can be generated by this file when runHeader() is 20 // called, rather than the normal run() entry point. 21 // 22 // See also the documentation in include/clang/Basic/arm_neon.td. 23 // 24 //===----------------------------------------------------------------------===// 25 26 #include "TableGenBackends.h" 27 #include "llvm/ADT/ArrayRef.h" 28 #include "llvm/ADT/DenseMap.h" 29 #include "llvm/ADT/None.h" 30 #include "llvm/ADT/Optional.h" 31 #include "llvm/ADT/STLExtras.h" 32 #include "llvm/ADT/SmallVector.h" 33 #include "llvm/ADT/StringExtras.h" 34 #include "llvm/ADT/StringRef.h" 35 #include "llvm/Support/Casting.h" 36 #include "llvm/Support/ErrorHandling.h" 37 #include "llvm/Support/raw_ostream.h" 38 #include "llvm/TableGen/Error.h" 39 #include "llvm/TableGen/Record.h" 40 #include "llvm/TableGen/SetTheory.h" 41 #include <algorithm> 42 #include <cassert> 43 #include <cctype> 44 #include <cstddef> 45 #include <cstdint> 46 #include <deque> 47 #include <map> 48 #include <set> 49 #include <sstream> 50 #include <string> 51 #include <utility> 52 #include <vector> 53 54 using namespace llvm; 55 56 namespace { 57 58 // While globals are generally bad, this one allows us to perform assertions 59 // liberally and somehow still trace them back to the def they indirectly 60 // came from. 61 static Record *CurrentRecord = nullptr; 62 static void assert_with_loc(bool Assertion, const std::string &Str) { 63 if (!Assertion) { 64 if (CurrentRecord) 65 PrintFatalError(CurrentRecord->getLoc(), Str); 66 else 67 PrintFatalError(Str); 68 } 69 } 70 71 enum ClassKind { 72 ClassNone, 73 ClassI, // generic integer instruction, e.g., "i8" suffix 74 ClassS, // signed/unsigned/poly, e.g., "s8", "u8" or "p8" suffix 75 ClassW, // width-specific instruction, e.g., "8" suffix 76 ClassB, // bitcast arguments with enum argument to specify type 77 ClassL, // Logical instructions which are op instructions 78 // but we need to not emit any suffix for in our 79 // tests. 80 ClassNoTest // Instructions which we do not test since they are 81 // not TRUE instructions. 82 }; 83 84 /// NeonTypeFlags - Flags to identify the types for overloaded Neon 85 /// builtins. These must be kept in sync with the flags in 86 /// include/clang/Basic/TargetBuiltins.h. 87 namespace NeonTypeFlags { 88 89 enum { EltTypeMask = 0xf, UnsignedFlag = 0x10, QuadFlag = 0x20 }; 90 91 enum EltType { 92 Int8, 93 Int16, 94 Int32, 95 Int64, 96 Poly8, 97 Poly16, 98 Poly64, 99 Poly128, 100 Float16, 101 Float32, 102 Float64, 103 BFloat16 104 }; 105 106 } // end namespace NeonTypeFlags 107 108 class NeonEmitter; 109 110 //===----------------------------------------------------------------------===// 111 // TypeSpec 112 //===----------------------------------------------------------------------===// 113 114 /// A TypeSpec is just a simple wrapper around a string, but gets its own type 115 /// for strong typing purposes. 116 /// 117 /// A TypeSpec can be used to create a type. 118 class TypeSpec : public std::string { 119 public: 120 static std::vector<TypeSpec> fromTypeSpecs(StringRef Str) { 121 std::vector<TypeSpec> Ret; 122 TypeSpec Acc; 123 for (char I : Str.str()) { 124 if (islower(I)) { 125 Acc.push_back(I); 126 Ret.push_back(TypeSpec(Acc)); 127 Acc.clear(); 128 } else { 129 Acc.push_back(I); 130 } 131 } 132 return Ret; 133 } 134 }; 135 136 //===----------------------------------------------------------------------===// 137 // Type 138 //===----------------------------------------------------------------------===// 139 140 /// A Type. Not much more to say here. 141 class Type { 142 private: 143 TypeSpec TS; 144 145 enum TypeKind { 146 Void, 147 Float, 148 SInt, 149 UInt, 150 Poly, 151 BFloat16, 152 }; 153 TypeKind Kind; 154 bool Immediate, Constant, Pointer; 155 // ScalarForMangling and NoManglingQ are really not suited to live here as 156 // they are not related to the type. But they live in the TypeSpec (not the 157 // prototype), so this is really the only place to store them. 158 bool ScalarForMangling, NoManglingQ; 159 unsigned Bitwidth, ElementBitwidth, NumVectors; 160 161 public: 162 Type() 163 : Kind(Void), Immediate(false), Constant(false), 164 Pointer(false), ScalarForMangling(false), NoManglingQ(false), 165 Bitwidth(0), ElementBitwidth(0), NumVectors(0) {} 166 167 Type(TypeSpec TS, StringRef CharMods) 168 : TS(std::move(TS)), Kind(Void), Immediate(false), 169 Constant(false), Pointer(false), ScalarForMangling(false), 170 NoManglingQ(false), Bitwidth(0), ElementBitwidth(0), NumVectors(0) { 171 applyModifiers(CharMods); 172 } 173 174 /// Returns a type representing "void". 175 static Type getVoid() { return Type(); } 176 177 bool operator==(const Type &Other) const { return str() == Other.str(); } 178 bool operator!=(const Type &Other) const { return !operator==(Other); } 179 180 // 181 // Query functions 182 // 183 bool isScalarForMangling() const { return ScalarForMangling; } 184 bool noManglingQ() const { return NoManglingQ; } 185 186 bool isPointer() const { return Pointer; } 187 bool isValue() const { return !isVoid() && !isPointer(); } 188 bool isScalar() const { return isValue() && NumVectors == 0; } 189 bool isVector() const { return isValue() && NumVectors > 0; } 190 bool isConstPointer() const { return Constant; } 191 bool isFloating() const { return Kind == Float; } 192 bool isInteger() const { return Kind == SInt || Kind == UInt; } 193 bool isPoly() const { return Kind == Poly; } 194 bool isSigned() const { return Kind == SInt; } 195 bool isImmediate() const { return Immediate; } 196 bool isFloat() const { return isFloating() && ElementBitwidth == 32; } 197 bool isDouble() const { return isFloating() && ElementBitwidth == 64; } 198 bool isHalf() const { return isFloating() && ElementBitwidth == 16; } 199 bool isChar() const { return ElementBitwidth == 8; } 200 bool isShort() const { return isInteger() && ElementBitwidth == 16; } 201 bool isInt() const { return isInteger() && ElementBitwidth == 32; } 202 bool isLong() const { return isInteger() && ElementBitwidth == 64; } 203 bool isVoid() const { return Kind == Void; } 204 bool isBFloat16() const { return Kind == BFloat16; } 205 unsigned getNumElements() const { return Bitwidth / ElementBitwidth; } 206 unsigned getSizeInBits() const { return Bitwidth; } 207 unsigned getElementSizeInBits() const { return ElementBitwidth; } 208 unsigned getNumVectors() const { return NumVectors; } 209 210 // 211 // Mutator functions 212 // 213 void makeUnsigned() { 214 assert(!isVoid() && "not a potentially signed type"); 215 Kind = UInt; 216 } 217 void makeSigned() { 218 assert(!isVoid() && "not a potentially signed type"); 219 Kind = SInt; 220 } 221 222 void makeInteger(unsigned ElemWidth, bool Sign) { 223 assert(!isVoid() && "converting void to int probably not useful"); 224 Kind = Sign ? SInt : UInt; 225 Immediate = false; 226 ElementBitwidth = ElemWidth; 227 } 228 229 void makeImmediate(unsigned ElemWidth) { 230 Kind = SInt; 231 Immediate = true; 232 ElementBitwidth = ElemWidth; 233 } 234 235 void makeScalar() { 236 Bitwidth = ElementBitwidth; 237 NumVectors = 0; 238 } 239 240 void makeOneVector() { 241 assert(isVector()); 242 NumVectors = 1; 243 } 244 245 void make32BitElement() { 246 assert_with_loc(Bitwidth > 32, "Not enough bits to make it 32!"); 247 ElementBitwidth = 32; 248 } 249 250 void doubleLanes() { 251 assert_with_loc(Bitwidth != 128, "Can't get bigger than 128!"); 252 Bitwidth = 128; 253 } 254 255 void halveLanes() { 256 assert_with_loc(Bitwidth != 64, "Can't get smaller than 64!"); 257 Bitwidth = 64; 258 } 259 260 /// Return the C string representation of a type, which is the typename 261 /// defined in stdint.h or arm_neon.h. 262 std::string str() const; 263 264 /// Return the string representation of a type, which is an encoded 265 /// string for passing to the BUILTIN() macro in Builtins.def. 266 std::string builtin_str() const; 267 268 /// Return the value in NeonTypeFlags for this type. 269 unsigned getNeonEnum() const; 270 271 /// Parse a type from a stdint.h or arm_neon.h typedef name, 272 /// for example uint32x2_t or int64_t. 273 static Type fromTypedefName(StringRef Name); 274 275 private: 276 /// Creates the type based on the typespec string in TS. 277 /// Sets "Quad" to true if the "Q" or "H" modifiers were 278 /// seen. This is needed by applyModifier as some modifiers 279 /// only take effect if the type size was changed by "Q" or "H". 280 void applyTypespec(bool &Quad); 281 /// Applies prototype modifiers to the type. 282 void applyModifiers(StringRef Mods); 283 }; 284 285 //===----------------------------------------------------------------------===// 286 // Variable 287 //===----------------------------------------------------------------------===// 288 289 /// A variable is a simple class that just has a type and a name. 290 class Variable { 291 Type T; 292 std::string N; 293 294 public: 295 Variable() : T(Type::getVoid()), N("") {} 296 Variable(Type T, std::string N) : T(std::move(T)), N(std::move(N)) {} 297 298 Type getType() const { return T; } 299 std::string getName() const { return "__" + N; } 300 }; 301 302 //===----------------------------------------------------------------------===// 303 // Intrinsic 304 //===----------------------------------------------------------------------===// 305 306 /// The main grunt class. This represents an instantiation of an intrinsic with 307 /// a particular typespec and prototype. 308 class Intrinsic { 309 /// The Record this intrinsic was created from. 310 Record *R; 311 /// The unmangled name. 312 std::string Name; 313 /// The input and output typespecs. InTS == OutTS except when 314 /// CartesianProductWith is non-empty - this is the case for vreinterpret. 315 TypeSpec OutTS, InTS; 316 /// The base class kind. Most intrinsics use ClassS, which has full type 317 /// info for integers (s32/u32). Some use ClassI, which doesn't care about 318 /// signedness (i32), while some (ClassB) have no type at all, only a width 319 /// (32). 320 ClassKind CK; 321 /// The list of DAGs for the body. May be empty, in which case we should 322 /// emit a builtin call. 323 ListInit *Body; 324 /// The architectural #ifdef guard. 325 std::string Guard; 326 /// Set if the Unavailable bit is 1. This means we don't generate a body, 327 /// just an "unavailable" attribute on a declaration. 328 bool IsUnavailable; 329 /// Is this intrinsic safe for big-endian? or does it need its arguments 330 /// reversing? 331 bool BigEndianSafe; 332 333 /// The types of return value [0] and parameters [1..]. 334 std::vector<Type> Types; 335 /// The index of the key type passed to CGBuiltin.cpp for polymorphic calls. 336 int PolymorphicKeyType; 337 /// The local variables defined. 338 std::map<std::string, Variable> Variables; 339 /// NeededEarly - set if any other intrinsic depends on this intrinsic. 340 bool NeededEarly; 341 /// UseMacro - set if we should implement using a macro or unset for a 342 /// function. 343 bool UseMacro; 344 /// The set of intrinsics that this intrinsic uses/requires. 345 std::set<Intrinsic *> Dependencies; 346 /// The "base type", which is Type('d', OutTS). InBaseType is only 347 /// different if CartesianProductWith is non-empty (for vreinterpret). 348 Type BaseType, InBaseType; 349 /// The return variable. 350 Variable RetVar; 351 /// A postfix to apply to every variable. Defaults to "". 352 std::string VariablePostfix; 353 354 NeonEmitter &Emitter; 355 std::stringstream OS; 356 357 bool isBigEndianSafe() const { 358 if (BigEndianSafe) 359 return true; 360 361 for (const auto &T : Types){ 362 if (T.isVector() && T.getNumElements() > 1) 363 return false; 364 } 365 return true; 366 } 367 368 public: 369 Intrinsic(Record *R, StringRef Name, StringRef Proto, TypeSpec OutTS, 370 TypeSpec InTS, ClassKind CK, ListInit *Body, NeonEmitter &Emitter, 371 StringRef Guard, bool IsUnavailable, bool BigEndianSafe) 372 : R(R), Name(Name.str()), OutTS(OutTS), InTS(InTS), CK(CK), Body(Body), 373 Guard(Guard.str()), IsUnavailable(IsUnavailable), 374 BigEndianSafe(BigEndianSafe), PolymorphicKeyType(0), NeededEarly(false), 375 UseMacro(false), BaseType(OutTS, "."), InBaseType(InTS, "."), 376 Emitter(Emitter) { 377 // Modify the TypeSpec per-argument to get a concrete Type, and create 378 // known variables for each. 379 // Types[0] is the return value. 380 unsigned Pos = 0; 381 Types.emplace_back(OutTS, getNextModifiers(Proto, Pos)); 382 StringRef Mods = getNextModifiers(Proto, Pos); 383 while (!Mods.empty()) { 384 Types.emplace_back(InTS, Mods); 385 if (Mods.find("!") != StringRef::npos) 386 PolymorphicKeyType = Types.size() - 1; 387 388 Mods = getNextModifiers(Proto, Pos); 389 } 390 391 for (auto Type : Types) { 392 // If this builtin takes an immediate argument, we need to #define it rather 393 // than use a standard declaration, so that SemaChecking can range check 394 // the immediate passed by the user. 395 396 // Pointer arguments need to use macros to avoid hiding aligned attributes 397 // from the pointer type. 398 399 // It is not permitted to pass or return an __fp16 by value, so intrinsics 400 // taking a scalar float16_t must be implemented as macros. 401 if (Type.isImmediate() || Type.isPointer() || 402 (Type.isScalar() && Type.isHalf())) 403 UseMacro = true; 404 } 405 } 406 407 /// Get the Record that this intrinsic is based off. 408 Record *getRecord() const { return R; } 409 /// Get the set of Intrinsics that this intrinsic calls. 410 /// this is the set of immediate dependencies, NOT the 411 /// transitive closure. 412 const std::set<Intrinsic *> &getDependencies() const { return Dependencies; } 413 /// Get the architectural guard string (#ifdef). 414 std::string getGuard() const { return Guard; } 415 /// Get the non-mangled name. 416 std::string getName() const { return Name; } 417 418 /// Return true if the intrinsic takes an immediate operand. 419 bool hasImmediate() const { 420 return std::any_of(Types.begin(), Types.end(), 421 [](const Type &T) { return T.isImmediate(); }); 422 } 423 424 /// Return the parameter index of the immediate operand. 425 unsigned getImmediateIdx() const { 426 for (unsigned Idx = 0; Idx < Types.size(); ++Idx) 427 if (Types[Idx].isImmediate()) 428 return Idx - 1; 429 llvm_unreachable("Intrinsic has no immediate"); 430 } 431 432 433 unsigned getNumParams() const { return Types.size() - 1; } 434 Type getReturnType() const { return Types[0]; } 435 Type getParamType(unsigned I) const { return Types[I + 1]; } 436 Type getBaseType() const { return BaseType; } 437 Type getPolymorphicKeyType() const { return Types[PolymorphicKeyType]; } 438 439 /// Return true if the prototype has a scalar argument. 440 bool protoHasScalar() const; 441 442 /// Return the index that parameter PIndex will sit at 443 /// in a generated function call. This is often just PIndex, 444 /// but may not be as things such as multiple-vector operands 445 /// and sret parameters need to be taken into accont. 446 unsigned getGeneratedParamIdx(unsigned PIndex) { 447 unsigned Idx = 0; 448 if (getReturnType().getNumVectors() > 1) 449 // Multiple vectors are passed as sret. 450 ++Idx; 451 452 for (unsigned I = 0; I < PIndex; ++I) 453 Idx += std::max(1U, getParamType(I).getNumVectors()); 454 455 return Idx; 456 } 457 458 bool hasBody() const { return Body && !Body->getValues().empty(); } 459 460 void setNeededEarly() { NeededEarly = true; } 461 462 bool operator<(const Intrinsic &Other) const { 463 // Sort lexicographically on a two-tuple (Guard, Name) 464 if (Guard != Other.Guard) 465 return Guard < Other.Guard; 466 return Name < Other.Name; 467 } 468 469 ClassKind getClassKind(bool UseClassBIfScalar = false) { 470 if (UseClassBIfScalar && !protoHasScalar()) 471 return ClassB; 472 return CK; 473 } 474 475 /// Return the name, mangled with type information. 476 /// If ForceClassS is true, use ClassS (u32/s32) instead 477 /// of the intrinsic's own type class. 478 std::string getMangledName(bool ForceClassS = false) const; 479 /// Return the type code for a builtin function call. 480 std::string getInstTypeCode(Type T, ClassKind CK) const; 481 /// Return the type string for a BUILTIN() macro in Builtins.def. 482 std::string getBuiltinTypeStr(); 483 484 /// Generate the intrinsic, returning code. 485 std::string generate(); 486 /// Perform type checking and populate the dependency graph, but 487 /// don't generate code yet. 488 void indexBody(); 489 490 private: 491 StringRef getNextModifiers(StringRef Proto, unsigned &Pos) const; 492 493 std::string mangleName(std::string Name, ClassKind CK) const; 494 495 void initVariables(); 496 std::string replaceParamsIn(std::string S); 497 498 void emitBodyAsBuiltinCall(); 499 500 void generateImpl(bool ReverseArguments, 501 StringRef NamePrefix, StringRef CallPrefix); 502 void emitReturn(); 503 void emitBody(StringRef CallPrefix); 504 void emitShadowedArgs(); 505 void emitArgumentReversal(); 506 void emitReturnReversal(); 507 void emitReverseVariable(Variable &Dest, Variable &Src); 508 void emitNewLine(); 509 void emitClosingBrace(); 510 void emitOpeningBrace(); 511 void emitPrototype(StringRef NamePrefix); 512 513 class DagEmitter { 514 Intrinsic &Intr; 515 StringRef CallPrefix; 516 517 public: 518 DagEmitter(Intrinsic &Intr, StringRef CallPrefix) : 519 Intr(Intr), CallPrefix(CallPrefix) { 520 } 521 std::pair<Type, std::string> emitDagArg(Init *Arg, std::string ArgName); 522 std::pair<Type, std::string> emitDagSaveTemp(DagInit *DI); 523 std::pair<Type, std::string> emitDagSplat(DagInit *DI); 524 std::pair<Type, std::string> emitDagDup(DagInit *DI); 525 std::pair<Type, std::string> emitDagDupTyped(DagInit *DI); 526 std::pair<Type, std::string> emitDagShuffle(DagInit *DI); 527 std::pair<Type, std::string> emitDagCast(DagInit *DI, bool IsBitCast); 528 std::pair<Type, std::string> emitDagCall(DagInit *DI, 529 bool MatchMangledName); 530 std::pair<Type, std::string> emitDagNameReplace(DagInit *DI); 531 std::pair<Type, std::string> emitDagLiteral(DagInit *DI); 532 std::pair<Type, std::string> emitDagOp(DagInit *DI); 533 std::pair<Type, std::string> emitDag(DagInit *DI); 534 }; 535 }; 536 537 //===----------------------------------------------------------------------===// 538 // NeonEmitter 539 //===----------------------------------------------------------------------===// 540 541 class NeonEmitter { 542 RecordKeeper &Records; 543 DenseMap<Record *, ClassKind> ClassMap; 544 std::map<std::string, std::deque<Intrinsic>> IntrinsicMap; 545 unsigned UniqueNumber; 546 547 void createIntrinsic(Record *R, SmallVectorImpl<Intrinsic *> &Out); 548 void genBuiltinsDef(raw_ostream &OS, SmallVectorImpl<Intrinsic *> &Defs); 549 void genOverloadTypeCheckCode(raw_ostream &OS, 550 SmallVectorImpl<Intrinsic *> &Defs); 551 void genIntrinsicRangeCheckCode(raw_ostream &OS, 552 SmallVectorImpl<Intrinsic *> &Defs); 553 554 public: 555 /// Called by Intrinsic - this attempts to get an intrinsic that takes 556 /// the given types as arguments. 557 Intrinsic &getIntrinsic(StringRef Name, ArrayRef<Type> Types, 558 Optional<std::string> MangledName); 559 560 /// Called by Intrinsic - returns a globally-unique number. 561 unsigned getUniqueNumber() { return UniqueNumber++; } 562 563 NeonEmitter(RecordKeeper &R) : Records(R), UniqueNumber(0) { 564 Record *SI = R.getClass("SInst"); 565 Record *II = R.getClass("IInst"); 566 Record *WI = R.getClass("WInst"); 567 Record *SOpI = R.getClass("SOpInst"); 568 Record *IOpI = R.getClass("IOpInst"); 569 Record *WOpI = R.getClass("WOpInst"); 570 Record *LOpI = R.getClass("LOpInst"); 571 Record *NoTestOpI = R.getClass("NoTestOpInst"); 572 573 ClassMap[SI] = ClassS; 574 ClassMap[II] = ClassI; 575 ClassMap[WI] = ClassW; 576 ClassMap[SOpI] = ClassS; 577 ClassMap[IOpI] = ClassI; 578 ClassMap[WOpI] = ClassW; 579 ClassMap[LOpI] = ClassL; 580 ClassMap[NoTestOpI] = ClassNoTest; 581 } 582 583 // run - Emit arm_neon.h.inc 584 void run(raw_ostream &o); 585 586 // runFP16 - Emit arm_fp16.h.inc 587 void runFP16(raw_ostream &o); 588 589 // runBF16 - Emit arm_bf16.h.inc 590 void runBF16(raw_ostream &o); 591 592 // runHeader - Emit all the __builtin prototypes used in arm_neon.h, 593 // arm_fp16.h and arm_bf16.h 594 void runHeader(raw_ostream &o); 595 596 // runTests - Emit tests for all the Neon intrinsics. 597 void runTests(raw_ostream &o); 598 }; 599 600 } // end anonymous namespace 601 602 //===----------------------------------------------------------------------===// 603 // Type implementation 604 //===----------------------------------------------------------------------===// 605 606 std::string Type::str() const { 607 if (isVoid()) 608 return "void"; 609 std::string S; 610 611 if (isInteger() && !isSigned()) 612 S += "u"; 613 614 if (isPoly()) 615 S += "poly"; 616 else if (isFloating()) 617 S += "float"; 618 else if (isBFloat16()) 619 S += "bfloat"; 620 else 621 S += "int"; 622 623 S += utostr(ElementBitwidth); 624 if (isVector()) 625 S += "x" + utostr(getNumElements()); 626 if (NumVectors > 1) 627 S += "x" + utostr(NumVectors); 628 S += "_t"; 629 630 if (Constant) 631 S += " const"; 632 if (Pointer) 633 S += " *"; 634 635 return S; 636 } 637 638 std::string Type::builtin_str() const { 639 std::string S; 640 if (isVoid()) 641 return "v"; 642 643 if (isPointer()) { 644 // All pointers are void pointers. 645 S = "v"; 646 if (isConstPointer()) 647 S += "C"; 648 S += "*"; 649 return S; 650 } else if (isInteger()) 651 switch (ElementBitwidth) { 652 case 8: S += "c"; break; 653 case 16: S += "s"; break; 654 case 32: S += "i"; break; 655 case 64: S += "Wi"; break; 656 case 128: S += "LLLi"; break; 657 default: llvm_unreachable("Unhandled case!"); 658 } 659 else if (isBFloat16()) { 660 assert(ElementBitwidth == 16 && "BFloat16 can only be 16 bits"); 661 S += "y"; 662 } else 663 switch (ElementBitwidth) { 664 case 16: S += "h"; break; 665 case 32: S += "f"; break; 666 case 64: S += "d"; break; 667 default: llvm_unreachable("Unhandled case!"); 668 } 669 670 // FIXME: NECESSARY??????????????????????????????????????????????????????????????????????? 671 if (isChar() && !isPointer() && isSigned()) 672 // Make chars explicitly signed. 673 S = "S" + S; 674 else if (isInteger() && !isSigned()) 675 S = "U" + S; 676 677 // Constant indices are "int", but have the "constant expression" modifier. 678 if (isImmediate()) { 679 assert(isInteger() && isSigned()); 680 S = "I" + S; 681 } 682 683 if (isScalar()) 684 return S; 685 686 std::string Ret; 687 for (unsigned I = 0; I < NumVectors; ++I) 688 Ret += "V" + utostr(getNumElements()) + S; 689 690 return Ret; 691 } 692 693 unsigned Type::getNeonEnum() const { 694 unsigned Addend; 695 switch (ElementBitwidth) { 696 case 8: Addend = 0; break; 697 case 16: Addend = 1; break; 698 case 32: Addend = 2; break; 699 case 64: Addend = 3; break; 700 case 128: Addend = 4; break; 701 default: llvm_unreachable("Unhandled element bitwidth!"); 702 } 703 704 unsigned Base = (unsigned)NeonTypeFlags::Int8 + Addend; 705 if (isPoly()) { 706 // Adjustment needed because Poly32 doesn't exist. 707 if (Addend >= 2) 708 --Addend; 709 Base = (unsigned)NeonTypeFlags::Poly8 + Addend; 710 } 711 if (isFloating()) { 712 assert(Addend != 0 && "Float8 doesn't exist!"); 713 Base = (unsigned)NeonTypeFlags::Float16 + (Addend - 1); 714 } 715 716 if (isBFloat16()) { 717 assert(Addend == 1 && "BFloat16 is only 16 bit"); 718 Base = (unsigned)NeonTypeFlags::BFloat16; 719 } 720 721 if (Bitwidth == 128) 722 Base |= (unsigned)NeonTypeFlags::QuadFlag; 723 if (isInteger() && !isSigned()) 724 Base |= (unsigned)NeonTypeFlags::UnsignedFlag; 725 726 return Base; 727 } 728 729 Type Type::fromTypedefName(StringRef Name) { 730 Type T; 731 T.Kind = SInt; 732 733 if (Name.front() == 'u') { 734 T.Kind = UInt; 735 Name = Name.drop_front(); 736 } 737 738 if (Name.startswith("float")) { 739 T.Kind = Float; 740 Name = Name.drop_front(5); 741 } else if (Name.startswith("poly")) { 742 T.Kind = Poly; 743 Name = Name.drop_front(4); 744 } else if (Name.startswith("bfloat")) { 745 T.Kind = BFloat16; 746 Name = Name.drop_front(6); 747 } else { 748 assert(Name.startswith("int")); 749 Name = Name.drop_front(3); 750 } 751 752 unsigned I = 0; 753 for (I = 0; I < Name.size(); ++I) { 754 if (!isdigit(Name[I])) 755 break; 756 } 757 Name.substr(0, I).getAsInteger(10, T.ElementBitwidth); 758 Name = Name.drop_front(I); 759 760 T.Bitwidth = T.ElementBitwidth; 761 T.NumVectors = 1; 762 763 if (Name.front() == 'x') { 764 Name = Name.drop_front(); 765 unsigned I = 0; 766 for (I = 0; I < Name.size(); ++I) { 767 if (!isdigit(Name[I])) 768 break; 769 } 770 unsigned NumLanes; 771 Name.substr(0, I).getAsInteger(10, NumLanes); 772 Name = Name.drop_front(I); 773 T.Bitwidth = T.ElementBitwidth * NumLanes; 774 } else { 775 // Was scalar. 776 T.NumVectors = 0; 777 } 778 if (Name.front() == 'x') { 779 Name = Name.drop_front(); 780 unsigned I = 0; 781 for (I = 0; I < Name.size(); ++I) { 782 if (!isdigit(Name[I])) 783 break; 784 } 785 Name.substr(0, I).getAsInteger(10, T.NumVectors); 786 Name = Name.drop_front(I); 787 } 788 789 assert(Name.startswith("_t") && "Malformed typedef!"); 790 return T; 791 } 792 793 void Type::applyTypespec(bool &Quad) { 794 std::string S = TS; 795 ScalarForMangling = false; 796 Kind = SInt; 797 ElementBitwidth = ~0U; 798 NumVectors = 1; 799 800 for (char I : S) { 801 switch (I) { 802 case 'S': 803 ScalarForMangling = true; 804 break; 805 case 'H': 806 NoManglingQ = true; 807 Quad = true; 808 break; 809 case 'Q': 810 Quad = true; 811 break; 812 case 'P': 813 Kind = Poly; 814 break; 815 case 'U': 816 Kind = UInt; 817 break; 818 case 'c': 819 ElementBitwidth = 8; 820 break; 821 case 'h': 822 Kind = Float; 823 LLVM_FALLTHROUGH; 824 case 's': 825 ElementBitwidth = 16; 826 break; 827 case 'f': 828 Kind = Float; 829 LLVM_FALLTHROUGH; 830 case 'i': 831 ElementBitwidth = 32; 832 break; 833 case 'd': 834 Kind = Float; 835 LLVM_FALLTHROUGH; 836 case 'l': 837 ElementBitwidth = 64; 838 break; 839 case 'k': 840 ElementBitwidth = 128; 841 // Poly doesn't have a 128x1 type. 842 if (isPoly()) 843 NumVectors = 0; 844 break; 845 case 'b': 846 Kind = BFloat16; 847 ElementBitwidth = 16; 848 break; 849 default: 850 llvm_unreachable("Unhandled type code!"); 851 } 852 } 853 assert(ElementBitwidth != ~0U && "Bad element bitwidth!"); 854 855 Bitwidth = Quad ? 128 : 64; 856 } 857 858 void Type::applyModifiers(StringRef Mods) { 859 bool AppliedQuad = false; 860 applyTypespec(AppliedQuad); 861 862 for (char Mod : Mods) { 863 switch (Mod) { 864 case '.': 865 break; 866 case 'v': 867 Kind = Void; 868 break; 869 case 'S': 870 Kind = SInt; 871 break; 872 case 'U': 873 Kind = UInt; 874 break; 875 case 'B': 876 Kind = BFloat16; 877 ElementBitwidth = 16; 878 break; 879 case 'F': 880 Kind = Float; 881 break; 882 case 'P': 883 Kind = Poly; 884 break; 885 case '>': 886 assert(ElementBitwidth < 128); 887 ElementBitwidth *= 2; 888 break; 889 case '<': 890 assert(ElementBitwidth > 8); 891 ElementBitwidth /= 2; 892 break; 893 case '1': 894 NumVectors = 0; 895 break; 896 case '2': 897 NumVectors = 2; 898 break; 899 case '3': 900 NumVectors = 3; 901 break; 902 case '4': 903 NumVectors = 4; 904 break; 905 case '*': 906 Pointer = true; 907 break; 908 case 'c': 909 Constant = true; 910 break; 911 case 'Q': 912 Bitwidth = 128; 913 break; 914 case 'q': 915 Bitwidth = 64; 916 break; 917 case 'I': 918 Kind = SInt; 919 ElementBitwidth = Bitwidth = 32; 920 NumVectors = 0; 921 Immediate = true; 922 break; 923 case 'p': 924 if (isPoly()) 925 Kind = UInt; 926 break; 927 case '!': 928 // Key type, handled elsewhere. 929 break; 930 default: 931 llvm_unreachable("Unhandled character!"); 932 } 933 } 934 } 935 936 //===----------------------------------------------------------------------===// 937 // Intrinsic implementation 938 //===----------------------------------------------------------------------===// 939 940 StringRef Intrinsic::getNextModifiers(StringRef Proto, unsigned &Pos) const { 941 if (Proto.size() == Pos) 942 return StringRef(); 943 else if (Proto[Pos] != '(') 944 return Proto.substr(Pos++, 1); 945 946 size_t Start = Pos + 1; 947 size_t End = Proto.find(')', Start); 948 assert_with_loc(End != StringRef::npos, "unmatched modifier group paren"); 949 Pos = End + 1; 950 return Proto.slice(Start, End); 951 } 952 953 std::string Intrinsic::getInstTypeCode(Type T, ClassKind CK) const { 954 char typeCode = '\0'; 955 bool printNumber = true; 956 957 if (CK == ClassB) 958 return ""; 959 960 if (T.isBFloat16()) 961 return "bf16"; 962 963 if (T.isPoly()) 964 typeCode = 'p'; 965 else if (T.isInteger()) 966 typeCode = T.isSigned() ? 's' : 'u'; 967 else 968 typeCode = 'f'; 969 970 if (CK == ClassI) { 971 switch (typeCode) { 972 default: 973 break; 974 case 's': 975 case 'u': 976 case 'p': 977 typeCode = 'i'; 978 break; 979 } 980 } 981 if (CK == ClassB) { 982 typeCode = '\0'; 983 } 984 985 std::string S; 986 if (typeCode != '\0') 987 S.push_back(typeCode); 988 if (printNumber) 989 S += utostr(T.getElementSizeInBits()); 990 991 return S; 992 } 993 994 std::string Intrinsic::getBuiltinTypeStr() { 995 ClassKind LocalCK = getClassKind(true); 996 std::string S; 997 998 Type RetT = getReturnType(); 999 if ((LocalCK == ClassI || LocalCK == ClassW) && RetT.isScalar() && 1000 !RetT.isFloating() && !RetT.isBFloat16()) 1001 RetT.makeInteger(RetT.getElementSizeInBits(), false); 1002 1003 // Since the return value must be one type, return a vector type of the 1004 // appropriate width which we will bitcast. An exception is made for 1005 // returning structs of 2, 3, or 4 vectors which are returned in a sret-like 1006 // fashion, storing them to a pointer arg. 1007 if (RetT.getNumVectors() > 1) { 1008 S += "vv*"; // void result with void* first argument 1009 } else { 1010 if (RetT.isPoly()) 1011 RetT.makeInteger(RetT.getElementSizeInBits(), false); 1012 if (!RetT.isScalar() && RetT.isInteger() && !RetT.isSigned()) 1013 RetT.makeSigned(); 1014 1015 if (LocalCK == ClassB && RetT.isValue() && !RetT.isScalar()) 1016 // Cast to vector of 8-bit elements. 1017 RetT.makeInteger(8, true); 1018 1019 S += RetT.builtin_str(); 1020 } 1021 1022 for (unsigned I = 0; I < getNumParams(); ++I) { 1023 Type T = getParamType(I); 1024 if (T.isPoly()) 1025 T.makeInteger(T.getElementSizeInBits(), false); 1026 1027 if (LocalCK == ClassB && !T.isScalar()) 1028 T.makeInteger(8, true); 1029 // Halves always get converted to 8-bit elements. 1030 if (T.isHalf() && T.isVector() && !T.isScalarForMangling()) 1031 T.makeInteger(8, true); 1032 1033 if (LocalCK == ClassI && T.isInteger()) 1034 T.makeSigned(); 1035 1036 if (hasImmediate() && getImmediateIdx() == I) 1037 T.makeImmediate(32); 1038 1039 S += T.builtin_str(); 1040 } 1041 1042 // Extra constant integer to hold type class enum for this function, e.g. s8 1043 if (LocalCK == ClassB) 1044 S += "i"; 1045 1046 return S; 1047 } 1048 1049 std::string Intrinsic::getMangledName(bool ForceClassS) const { 1050 // Check if the prototype has a scalar operand with the type of the vector 1051 // elements. If not, bitcasting the args will take care of arg checking. 1052 // The actual signedness etc. will be taken care of with special enums. 1053 ClassKind LocalCK = CK; 1054 if (!protoHasScalar()) 1055 LocalCK = ClassB; 1056 1057 return mangleName(Name, ForceClassS ? ClassS : LocalCK); 1058 } 1059 1060 std::string Intrinsic::mangleName(std::string Name, ClassKind LocalCK) const { 1061 std::string typeCode = getInstTypeCode(BaseType, LocalCK); 1062 std::string S = Name; 1063 1064 if (Name == "vcvt_f16_f32" || Name == "vcvt_f32_f16" || 1065 Name == "vcvt_f32_f64" || Name == "vcvt_f64_f32") 1066 return Name; 1067 1068 if (!typeCode.empty()) { 1069 // If the name ends with _xN (N = 2,3,4), insert the typeCode before _xN. 1070 if (Name.size() >= 3 && isdigit(Name.back()) && 1071 Name[Name.length() - 2] == 'x' && Name[Name.length() - 3] == '_') 1072 S.insert(S.length() - 3, "_" + typeCode); 1073 else 1074 S += "_" + typeCode; 1075 } 1076 1077 if (BaseType != InBaseType) { 1078 // A reinterpret - out the input base type at the end. 1079 S += "_" + getInstTypeCode(InBaseType, LocalCK); 1080 } 1081 1082 if (LocalCK == ClassB) 1083 S += "_v"; 1084 1085 // Insert a 'q' before the first '_' character so that it ends up before 1086 // _lane or _n on vector-scalar operations. 1087 if (BaseType.getSizeInBits() == 128 && !BaseType.noManglingQ()) { 1088 size_t Pos = S.find('_'); 1089 S.insert(Pos, "q"); 1090 } 1091 1092 char Suffix = '\0'; 1093 if (BaseType.isScalarForMangling()) { 1094 switch (BaseType.getElementSizeInBits()) { 1095 case 8: Suffix = 'b'; break; 1096 case 16: Suffix = 'h'; break; 1097 case 32: Suffix = 's'; break; 1098 case 64: Suffix = 'd'; break; 1099 default: llvm_unreachable("Bad suffix!"); 1100 } 1101 } 1102 if (Suffix != '\0') { 1103 size_t Pos = S.find('_'); 1104 S.insert(Pos, &Suffix, 1); 1105 } 1106 1107 return S; 1108 } 1109 1110 std::string Intrinsic::replaceParamsIn(std::string S) { 1111 while (S.find('$') != std::string::npos) { 1112 size_t Pos = S.find('$'); 1113 size_t End = Pos + 1; 1114 while (isalpha(S[End])) 1115 ++End; 1116 1117 std::string VarName = S.substr(Pos + 1, End - Pos - 1); 1118 assert_with_loc(Variables.find(VarName) != Variables.end(), 1119 "Variable not defined!"); 1120 S.replace(Pos, End - Pos, Variables.find(VarName)->second.getName()); 1121 } 1122 1123 return S; 1124 } 1125 1126 void Intrinsic::initVariables() { 1127 Variables.clear(); 1128 1129 // Modify the TypeSpec per-argument to get a concrete Type, and create 1130 // known variables for each. 1131 for (unsigned I = 1; I < Types.size(); ++I) { 1132 char NameC = '0' + (I - 1); 1133 std::string Name = "p"; 1134 Name.push_back(NameC); 1135 1136 Variables[Name] = Variable(Types[I], Name + VariablePostfix); 1137 } 1138 RetVar = Variable(Types[0], "ret" + VariablePostfix); 1139 } 1140 1141 void Intrinsic::emitPrototype(StringRef NamePrefix) { 1142 if (UseMacro) 1143 OS << "#define "; 1144 else 1145 OS << "__ai " << Types[0].str() << " "; 1146 1147 OS << NamePrefix.str() << mangleName(Name, ClassS) << "("; 1148 1149 for (unsigned I = 0; I < getNumParams(); ++I) { 1150 if (I != 0) 1151 OS << ", "; 1152 1153 char NameC = '0' + I; 1154 std::string Name = "p"; 1155 Name.push_back(NameC); 1156 assert(Variables.find(Name) != Variables.end()); 1157 Variable &V = Variables[Name]; 1158 1159 if (!UseMacro) 1160 OS << V.getType().str() << " "; 1161 OS << V.getName(); 1162 } 1163 1164 OS << ")"; 1165 } 1166 1167 void Intrinsic::emitOpeningBrace() { 1168 if (UseMacro) 1169 OS << " __extension__ ({"; 1170 else 1171 OS << " {"; 1172 emitNewLine(); 1173 } 1174 1175 void Intrinsic::emitClosingBrace() { 1176 if (UseMacro) 1177 OS << "})"; 1178 else 1179 OS << "}"; 1180 } 1181 1182 void Intrinsic::emitNewLine() { 1183 if (UseMacro) 1184 OS << " \\\n"; 1185 else 1186 OS << "\n"; 1187 } 1188 1189 void Intrinsic::emitReverseVariable(Variable &Dest, Variable &Src) { 1190 if (Dest.getType().getNumVectors() > 1) { 1191 emitNewLine(); 1192 1193 for (unsigned K = 0; K < Dest.getType().getNumVectors(); ++K) { 1194 OS << " " << Dest.getName() << ".val[" << K << "] = " 1195 << "__builtin_shufflevector(" 1196 << Src.getName() << ".val[" << K << "], " 1197 << Src.getName() << ".val[" << K << "]"; 1198 for (int J = Dest.getType().getNumElements() - 1; J >= 0; --J) 1199 OS << ", " << J; 1200 OS << ");"; 1201 emitNewLine(); 1202 } 1203 } else { 1204 OS << " " << Dest.getName() 1205 << " = __builtin_shufflevector(" << Src.getName() << ", " << Src.getName(); 1206 for (int J = Dest.getType().getNumElements() - 1; J >= 0; --J) 1207 OS << ", " << J; 1208 OS << ");"; 1209 emitNewLine(); 1210 } 1211 } 1212 1213 void Intrinsic::emitArgumentReversal() { 1214 if (isBigEndianSafe()) 1215 return; 1216 1217 // Reverse all vector arguments. 1218 for (unsigned I = 0; I < getNumParams(); ++I) { 1219 std::string Name = "p" + utostr(I); 1220 std::string NewName = "rev" + utostr(I); 1221 1222 Variable &V = Variables[Name]; 1223 Variable NewV(V.getType(), NewName + VariablePostfix); 1224 1225 if (!NewV.getType().isVector() || NewV.getType().getNumElements() == 1) 1226 continue; 1227 1228 OS << " " << NewV.getType().str() << " " << NewV.getName() << ";"; 1229 emitReverseVariable(NewV, V); 1230 V = NewV; 1231 } 1232 } 1233 1234 void Intrinsic::emitReturnReversal() { 1235 if (isBigEndianSafe()) 1236 return; 1237 if (!getReturnType().isVector() || getReturnType().isVoid() || 1238 getReturnType().getNumElements() == 1) 1239 return; 1240 emitReverseVariable(RetVar, RetVar); 1241 } 1242 1243 void Intrinsic::emitShadowedArgs() { 1244 // Macro arguments are not type-checked like inline function arguments, 1245 // so assign them to local temporaries to get the right type checking. 1246 if (!UseMacro) 1247 return; 1248 1249 for (unsigned I = 0; I < getNumParams(); ++I) { 1250 // Do not create a temporary for an immediate argument. 1251 // That would defeat the whole point of using a macro! 1252 if (getParamType(I).isImmediate()) 1253 continue; 1254 // Do not create a temporary for pointer arguments. The input 1255 // pointer may have an alignment hint. 1256 if (getParamType(I).isPointer()) 1257 continue; 1258 1259 std::string Name = "p" + utostr(I); 1260 1261 assert(Variables.find(Name) != Variables.end()); 1262 Variable &V = Variables[Name]; 1263 1264 std::string NewName = "s" + utostr(I); 1265 Variable V2(V.getType(), NewName + VariablePostfix); 1266 1267 OS << " " << V2.getType().str() << " " << V2.getName() << " = " 1268 << V.getName() << ";"; 1269 emitNewLine(); 1270 1271 V = V2; 1272 } 1273 } 1274 1275 bool Intrinsic::protoHasScalar() const { 1276 return std::any_of(Types.begin(), Types.end(), [](const Type &T) { 1277 return T.isScalar() && !T.isImmediate(); 1278 }); 1279 } 1280 1281 void Intrinsic::emitBodyAsBuiltinCall() { 1282 std::string S; 1283 1284 // If this builtin returns a struct 2, 3, or 4 vectors, pass it as an implicit 1285 // sret-like argument. 1286 bool SRet = getReturnType().getNumVectors() >= 2; 1287 1288 StringRef N = Name; 1289 ClassKind LocalCK = CK; 1290 if (!protoHasScalar()) 1291 LocalCK = ClassB; 1292 1293 if (!getReturnType().isVoid() && !SRet) 1294 S += "(" + RetVar.getType().str() + ") "; 1295 1296 S += "__builtin_neon_" + mangleName(std::string(N), LocalCK) + "("; 1297 1298 if (SRet) 1299 S += "&" + RetVar.getName() + ", "; 1300 1301 for (unsigned I = 0; I < getNumParams(); ++I) { 1302 Variable &V = Variables["p" + utostr(I)]; 1303 Type T = V.getType(); 1304 1305 // Handle multiple-vector values specially, emitting each subvector as an 1306 // argument to the builtin. 1307 if (T.getNumVectors() > 1) { 1308 // Check if an explicit cast is needed. 1309 std::string Cast; 1310 if (LocalCK == ClassB) { 1311 Type T2 = T; 1312 T2.makeOneVector(); 1313 T2.makeInteger(8, /*Signed=*/true); 1314 Cast = "(" + T2.str() + ")"; 1315 } 1316 1317 for (unsigned J = 0; J < T.getNumVectors(); ++J) 1318 S += Cast + V.getName() + ".val[" + utostr(J) + "], "; 1319 continue; 1320 } 1321 1322 std::string Arg = V.getName(); 1323 Type CastToType = T; 1324 1325 // Check if an explicit cast is needed. 1326 if (CastToType.isVector() && 1327 (LocalCK == ClassB || (T.isHalf() && !T.isScalarForMangling()))) { 1328 CastToType.makeInteger(8, true); 1329 Arg = "(" + CastToType.str() + ")" + Arg; 1330 } else if (CastToType.isVector() && LocalCK == ClassI) { 1331 if (CastToType.isInteger()) 1332 CastToType.makeSigned(); 1333 Arg = "(" + CastToType.str() + ")" + Arg; 1334 } 1335 1336 S += Arg + ", "; 1337 } 1338 1339 // Extra constant integer to hold type class enum for this function, e.g. s8 1340 if (getClassKind(true) == ClassB) { 1341 S += utostr(getPolymorphicKeyType().getNeonEnum()); 1342 } else { 1343 // Remove extraneous ", ". 1344 S.pop_back(); 1345 S.pop_back(); 1346 } 1347 S += ");"; 1348 1349 std::string RetExpr; 1350 if (!SRet && !RetVar.getType().isVoid()) 1351 RetExpr = RetVar.getName() + " = "; 1352 1353 OS << " " << RetExpr << S; 1354 emitNewLine(); 1355 } 1356 1357 void Intrinsic::emitBody(StringRef CallPrefix) { 1358 std::vector<std::string> Lines; 1359 1360 assert(RetVar.getType() == Types[0]); 1361 // Create a return variable, if we're not void. 1362 if (!RetVar.getType().isVoid()) { 1363 OS << " " << RetVar.getType().str() << " " << RetVar.getName() << ";"; 1364 emitNewLine(); 1365 } 1366 1367 if (!Body || Body->getValues().empty()) { 1368 // Nothing specific to output - must output a builtin. 1369 emitBodyAsBuiltinCall(); 1370 return; 1371 } 1372 1373 // We have a list of "things to output". The last should be returned. 1374 for (auto *I : Body->getValues()) { 1375 if (StringInit *SI = dyn_cast<StringInit>(I)) { 1376 Lines.push_back(replaceParamsIn(SI->getAsString())); 1377 } else if (DagInit *DI = dyn_cast<DagInit>(I)) { 1378 DagEmitter DE(*this, CallPrefix); 1379 Lines.push_back(DE.emitDag(DI).second + ";"); 1380 } 1381 } 1382 1383 assert(!Lines.empty() && "Empty def?"); 1384 if (!RetVar.getType().isVoid()) 1385 Lines.back().insert(0, RetVar.getName() + " = "); 1386 1387 for (auto &L : Lines) { 1388 OS << " " << L; 1389 emitNewLine(); 1390 } 1391 } 1392 1393 void Intrinsic::emitReturn() { 1394 if (RetVar.getType().isVoid()) 1395 return; 1396 if (UseMacro) 1397 OS << " " << RetVar.getName() << ";"; 1398 else 1399 OS << " return " << RetVar.getName() << ";"; 1400 emitNewLine(); 1401 } 1402 1403 std::pair<Type, std::string> Intrinsic::DagEmitter::emitDag(DagInit *DI) { 1404 // At this point we should only be seeing a def. 1405 DefInit *DefI = cast<DefInit>(DI->getOperator()); 1406 std::string Op = DefI->getAsString(); 1407 1408 if (Op == "cast" || Op == "bitcast") 1409 return emitDagCast(DI, Op == "bitcast"); 1410 if (Op == "shuffle") 1411 return emitDagShuffle(DI); 1412 if (Op == "dup") 1413 return emitDagDup(DI); 1414 if (Op == "dup_typed") 1415 return emitDagDupTyped(DI); 1416 if (Op == "splat") 1417 return emitDagSplat(DI); 1418 if (Op == "save_temp") 1419 return emitDagSaveTemp(DI); 1420 if (Op == "op") 1421 return emitDagOp(DI); 1422 if (Op == "call" || Op == "call_mangled") 1423 return emitDagCall(DI, Op == "call_mangled"); 1424 if (Op == "name_replace") 1425 return emitDagNameReplace(DI); 1426 if (Op == "literal") 1427 return emitDagLiteral(DI); 1428 assert_with_loc(false, "Unknown operation!"); 1429 return std::make_pair(Type::getVoid(), ""); 1430 } 1431 1432 std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagOp(DagInit *DI) { 1433 std::string Op = cast<StringInit>(DI->getArg(0))->getAsUnquotedString(); 1434 if (DI->getNumArgs() == 2) { 1435 // Unary op. 1436 std::pair<Type, std::string> R = 1437 emitDagArg(DI->getArg(1), std::string(DI->getArgNameStr(1))); 1438 return std::make_pair(R.first, Op + R.second); 1439 } else { 1440 assert(DI->getNumArgs() == 3 && "Can only handle unary and binary ops!"); 1441 std::pair<Type, std::string> R1 = 1442 emitDagArg(DI->getArg(1), std::string(DI->getArgNameStr(1))); 1443 std::pair<Type, std::string> R2 = 1444 emitDagArg(DI->getArg(2), std::string(DI->getArgNameStr(2))); 1445 assert_with_loc(R1.first == R2.first, "Argument type mismatch!"); 1446 return std::make_pair(R1.first, R1.second + " " + Op + " " + R2.second); 1447 } 1448 } 1449 1450 std::pair<Type, std::string> 1451 Intrinsic::DagEmitter::emitDagCall(DagInit *DI, bool MatchMangledName) { 1452 std::vector<Type> Types; 1453 std::vector<std::string> Values; 1454 for (unsigned I = 0; I < DI->getNumArgs() - 1; ++I) { 1455 std::pair<Type, std::string> R = 1456 emitDagArg(DI->getArg(I + 1), std::string(DI->getArgNameStr(I + 1))); 1457 Types.push_back(R.first); 1458 Values.push_back(R.second); 1459 } 1460 1461 // Look up the called intrinsic. 1462 std::string N; 1463 if (StringInit *SI = dyn_cast<StringInit>(DI->getArg(0))) 1464 N = SI->getAsUnquotedString(); 1465 else 1466 N = emitDagArg(DI->getArg(0), "").second; 1467 Optional<std::string> MangledName; 1468 if (MatchMangledName) { 1469 if (Intr.getRecord()->getValueAsBit("isLaneQ")) 1470 N += "q"; 1471 MangledName = Intr.mangleName(N, ClassS); 1472 } 1473 Intrinsic &Callee = Intr.Emitter.getIntrinsic(N, Types, MangledName); 1474 1475 // Make sure the callee is known as an early def. 1476 Callee.setNeededEarly(); 1477 Intr.Dependencies.insert(&Callee); 1478 1479 // Now create the call itself. 1480 std::string S = ""; 1481 if (!Callee.isBigEndianSafe()) 1482 S += CallPrefix.str(); 1483 S += Callee.getMangledName(true) + "("; 1484 for (unsigned I = 0; I < DI->getNumArgs() - 1; ++I) { 1485 if (I != 0) 1486 S += ", "; 1487 S += Values[I]; 1488 } 1489 S += ")"; 1490 1491 return std::make_pair(Callee.getReturnType(), S); 1492 } 1493 1494 std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagCast(DagInit *DI, 1495 bool IsBitCast){ 1496 // (cast MOD* VAL) -> cast VAL to type given by MOD. 1497 std::pair<Type, std::string> R = 1498 emitDagArg(DI->getArg(DI->getNumArgs() - 1), 1499 std::string(DI->getArgNameStr(DI->getNumArgs() - 1))); 1500 Type castToType = R.first; 1501 for (unsigned ArgIdx = 0; ArgIdx < DI->getNumArgs() - 1; ++ArgIdx) { 1502 1503 // MOD can take several forms: 1504 // 1. $X - take the type of parameter / variable X. 1505 // 2. The value "R" - take the type of the return type. 1506 // 3. a type string 1507 // 4. The value "U" or "S" to switch the signedness. 1508 // 5. The value "H" or "D" to half or double the bitwidth. 1509 // 6. The value "8" to convert to 8-bit (signed) integer lanes. 1510 if (!DI->getArgNameStr(ArgIdx).empty()) { 1511 assert_with_loc(Intr.Variables.find(std::string( 1512 DI->getArgNameStr(ArgIdx))) != Intr.Variables.end(), 1513 "Variable not found"); 1514 castToType = 1515 Intr.Variables[std::string(DI->getArgNameStr(ArgIdx))].getType(); 1516 } else { 1517 StringInit *SI = dyn_cast<StringInit>(DI->getArg(ArgIdx)); 1518 assert_with_loc(SI, "Expected string type or $Name for cast type"); 1519 1520 if (SI->getAsUnquotedString() == "R") { 1521 castToType = Intr.getReturnType(); 1522 } else if (SI->getAsUnquotedString() == "U") { 1523 castToType.makeUnsigned(); 1524 } else if (SI->getAsUnquotedString() == "S") { 1525 castToType.makeSigned(); 1526 } else if (SI->getAsUnquotedString() == "H") { 1527 castToType.halveLanes(); 1528 } else if (SI->getAsUnquotedString() == "D") { 1529 castToType.doubleLanes(); 1530 } else if (SI->getAsUnquotedString() == "8") { 1531 castToType.makeInteger(8, true); 1532 } else if (SI->getAsUnquotedString() == "32") { 1533 castToType.make32BitElement(); 1534 } else { 1535 castToType = Type::fromTypedefName(SI->getAsUnquotedString()); 1536 assert_with_loc(!castToType.isVoid(), "Unknown typedef"); 1537 } 1538 } 1539 } 1540 1541 std::string S; 1542 if (IsBitCast) { 1543 // Emit a reinterpret cast. The second operand must be an lvalue, so create 1544 // a temporary. 1545 std::string N = "reint"; 1546 unsigned I = 0; 1547 while (Intr.Variables.find(N) != Intr.Variables.end()) 1548 N = "reint" + utostr(++I); 1549 Intr.Variables[N] = Variable(R.first, N + Intr.VariablePostfix); 1550 1551 Intr.OS << R.first.str() << " " << Intr.Variables[N].getName() << " = " 1552 << R.second << ";"; 1553 Intr.emitNewLine(); 1554 1555 S = "*(" + castToType.str() + " *) &" + Intr.Variables[N].getName() + ""; 1556 } else { 1557 // Emit a normal (static) cast. 1558 S = "(" + castToType.str() + ")(" + R.second + ")"; 1559 } 1560 1561 return std::make_pair(castToType, S); 1562 } 1563 1564 std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagShuffle(DagInit *DI){ 1565 // See the documentation in arm_neon.td for a description of these operators. 1566 class LowHalf : public SetTheory::Operator { 1567 public: 1568 void apply(SetTheory &ST, DagInit *Expr, SetTheory::RecSet &Elts, 1569 ArrayRef<SMLoc> Loc) override { 1570 SetTheory::RecSet Elts2; 1571 ST.evaluate(Expr->arg_begin(), Expr->arg_end(), Elts2, Loc); 1572 Elts.insert(Elts2.begin(), Elts2.begin() + (Elts2.size() / 2)); 1573 } 1574 }; 1575 1576 class HighHalf : public SetTheory::Operator { 1577 public: 1578 void apply(SetTheory &ST, DagInit *Expr, SetTheory::RecSet &Elts, 1579 ArrayRef<SMLoc> Loc) override { 1580 SetTheory::RecSet Elts2; 1581 ST.evaluate(Expr->arg_begin(), Expr->arg_end(), Elts2, Loc); 1582 Elts.insert(Elts2.begin() + (Elts2.size() / 2), Elts2.end()); 1583 } 1584 }; 1585 1586 class Rev : public SetTheory::Operator { 1587 unsigned ElementSize; 1588 1589 public: 1590 Rev(unsigned ElementSize) : ElementSize(ElementSize) {} 1591 1592 void apply(SetTheory &ST, DagInit *Expr, SetTheory::RecSet &Elts, 1593 ArrayRef<SMLoc> Loc) override { 1594 SetTheory::RecSet Elts2; 1595 ST.evaluate(Expr->arg_begin() + 1, Expr->arg_end(), Elts2, Loc); 1596 1597 int64_t VectorSize = cast<IntInit>(Expr->getArg(0))->getValue(); 1598 VectorSize /= ElementSize; 1599 1600 std::vector<Record *> Revved; 1601 for (unsigned VI = 0; VI < Elts2.size(); VI += VectorSize) { 1602 for (int LI = VectorSize - 1; LI >= 0; --LI) { 1603 Revved.push_back(Elts2[VI + LI]); 1604 } 1605 } 1606 1607 Elts.insert(Revved.begin(), Revved.end()); 1608 } 1609 }; 1610 1611 class MaskExpander : public SetTheory::Expander { 1612 unsigned N; 1613 1614 public: 1615 MaskExpander(unsigned N) : N(N) {} 1616 1617 void expand(SetTheory &ST, Record *R, SetTheory::RecSet &Elts) override { 1618 unsigned Addend = 0; 1619 if (R->getName() == "mask0") 1620 Addend = 0; 1621 else if (R->getName() == "mask1") 1622 Addend = N; 1623 else 1624 return; 1625 for (unsigned I = 0; I < N; ++I) 1626 Elts.insert(R->getRecords().getDef("sv" + utostr(I + Addend))); 1627 } 1628 }; 1629 1630 // (shuffle arg1, arg2, sequence) 1631 std::pair<Type, std::string> Arg1 = 1632 emitDagArg(DI->getArg(0), std::string(DI->getArgNameStr(0))); 1633 std::pair<Type, std::string> Arg2 = 1634 emitDagArg(DI->getArg(1), std::string(DI->getArgNameStr(1))); 1635 assert_with_loc(Arg1.first == Arg2.first, 1636 "Different types in arguments to shuffle!"); 1637 1638 SetTheory ST; 1639 SetTheory::RecSet Elts; 1640 ST.addOperator("lowhalf", std::make_unique<LowHalf>()); 1641 ST.addOperator("highhalf", std::make_unique<HighHalf>()); 1642 ST.addOperator("rev", 1643 std::make_unique<Rev>(Arg1.first.getElementSizeInBits())); 1644 ST.addExpander("MaskExpand", 1645 std::make_unique<MaskExpander>(Arg1.first.getNumElements())); 1646 ST.evaluate(DI->getArg(2), Elts, None); 1647 1648 std::string S = "__builtin_shufflevector(" + Arg1.second + ", " + Arg2.second; 1649 for (auto &E : Elts) { 1650 StringRef Name = E->getName(); 1651 assert_with_loc(Name.startswith("sv"), 1652 "Incorrect element kind in shuffle mask!"); 1653 S += ", " + Name.drop_front(2).str(); 1654 } 1655 S += ")"; 1656 1657 // Recalculate the return type - the shuffle may have halved or doubled it. 1658 Type T(Arg1.first); 1659 if (Elts.size() > T.getNumElements()) { 1660 assert_with_loc( 1661 Elts.size() == T.getNumElements() * 2, 1662 "Can only double or half the number of elements in a shuffle!"); 1663 T.doubleLanes(); 1664 } else if (Elts.size() < T.getNumElements()) { 1665 assert_with_loc( 1666 Elts.size() == T.getNumElements() / 2, 1667 "Can only double or half the number of elements in a shuffle!"); 1668 T.halveLanes(); 1669 } 1670 1671 return std::make_pair(T, S); 1672 } 1673 1674 std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagDup(DagInit *DI) { 1675 assert_with_loc(DI->getNumArgs() == 1, "dup() expects one argument"); 1676 std::pair<Type, std::string> A = 1677 emitDagArg(DI->getArg(0), std::string(DI->getArgNameStr(0))); 1678 assert_with_loc(A.first.isScalar(), "dup() expects a scalar argument"); 1679 1680 Type T = Intr.getBaseType(); 1681 assert_with_loc(T.isVector(), "dup() used but default type is scalar!"); 1682 std::string S = "(" + T.str() + ") {"; 1683 for (unsigned I = 0; I < T.getNumElements(); ++I) { 1684 if (I != 0) 1685 S += ", "; 1686 S += A.second; 1687 } 1688 S += "}"; 1689 1690 return std::make_pair(T, S); 1691 } 1692 1693 std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagDupTyped(DagInit *DI) { 1694 assert_with_loc(DI->getNumArgs() == 2, "dup_typed() expects two arguments"); 1695 std::pair<Type, std::string> A = 1696 emitDagArg(DI->getArg(0), std::string(DI->getArgNameStr(0))); 1697 std::pair<Type, std::string> B = 1698 emitDagArg(DI->getArg(1), std::string(DI->getArgNameStr(1))); 1699 assert_with_loc(B.first.isScalar(), 1700 "dup_typed() requires a scalar as the second argument"); 1701 1702 Type T = A.first; 1703 assert_with_loc(T.isVector(), "dup_typed() used but target type is scalar!"); 1704 std::string S = "(" + T.str() + ") {"; 1705 for (unsigned I = 0; I < T.getNumElements(); ++I) { 1706 if (I != 0) 1707 S += ", "; 1708 S += B.second; 1709 } 1710 S += "}"; 1711 1712 return std::make_pair(T, S); 1713 } 1714 1715 std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagSplat(DagInit *DI) { 1716 assert_with_loc(DI->getNumArgs() == 2, "splat() expects two arguments"); 1717 std::pair<Type, std::string> A = 1718 emitDagArg(DI->getArg(0), std::string(DI->getArgNameStr(0))); 1719 std::pair<Type, std::string> B = 1720 emitDagArg(DI->getArg(1), std::string(DI->getArgNameStr(1))); 1721 1722 assert_with_loc(B.first.isScalar(), 1723 "splat() requires a scalar int as the second argument"); 1724 1725 std::string S = "__builtin_shufflevector(" + A.second + ", " + A.second; 1726 for (unsigned I = 0; I < Intr.getBaseType().getNumElements(); ++I) { 1727 S += ", " + B.second; 1728 } 1729 S += ")"; 1730 1731 return std::make_pair(Intr.getBaseType(), S); 1732 } 1733 1734 std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagSaveTemp(DagInit *DI) { 1735 assert_with_loc(DI->getNumArgs() == 2, "save_temp() expects two arguments"); 1736 std::pair<Type, std::string> A = 1737 emitDagArg(DI->getArg(1), std::string(DI->getArgNameStr(1))); 1738 1739 assert_with_loc(!A.first.isVoid(), 1740 "Argument to save_temp() must have non-void type!"); 1741 1742 std::string N = std::string(DI->getArgNameStr(0)); 1743 assert_with_loc(!N.empty(), 1744 "save_temp() expects a name as the first argument"); 1745 1746 assert_with_loc(Intr.Variables.find(N) == Intr.Variables.end(), 1747 "Variable already defined!"); 1748 Intr.Variables[N] = Variable(A.first, N + Intr.VariablePostfix); 1749 1750 std::string S = 1751 A.first.str() + " " + Intr.Variables[N].getName() + " = " + A.second; 1752 1753 return std::make_pair(Type::getVoid(), S); 1754 } 1755 1756 std::pair<Type, std::string> 1757 Intrinsic::DagEmitter::emitDagNameReplace(DagInit *DI) { 1758 std::string S = Intr.Name; 1759 1760 assert_with_loc(DI->getNumArgs() == 2, "name_replace requires 2 arguments!"); 1761 std::string ToReplace = cast<StringInit>(DI->getArg(0))->getAsUnquotedString(); 1762 std::string ReplaceWith = cast<StringInit>(DI->getArg(1))->getAsUnquotedString(); 1763 1764 size_t Idx = S.find(ToReplace); 1765 1766 assert_with_loc(Idx != std::string::npos, "name should contain '" + ToReplace + "'!"); 1767 S.replace(Idx, ToReplace.size(), ReplaceWith); 1768 1769 return std::make_pair(Type::getVoid(), S); 1770 } 1771 1772 std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagLiteral(DagInit *DI){ 1773 std::string Ty = cast<StringInit>(DI->getArg(0))->getAsUnquotedString(); 1774 std::string Value = cast<StringInit>(DI->getArg(1))->getAsUnquotedString(); 1775 return std::make_pair(Type::fromTypedefName(Ty), Value); 1776 } 1777 1778 std::pair<Type, std::string> 1779 Intrinsic::DagEmitter::emitDagArg(Init *Arg, std::string ArgName) { 1780 if (!ArgName.empty()) { 1781 assert_with_loc(!Arg->isComplete(), 1782 "Arguments must either be DAGs or names, not both!"); 1783 assert_with_loc(Intr.Variables.find(ArgName) != Intr.Variables.end(), 1784 "Variable not defined!"); 1785 Variable &V = Intr.Variables[ArgName]; 1786 return std::make_pair(V.getType(), V.getName()); 1787 } 1788 1789 assert(Arg && "Neither ArgName nor Arg?!"); 1790 DagInit *DI = dyn_cast<DagInit>(Arg); 1791 assert_with_loc(DI, "Arguments must either be DAGs or names!"); 1792 1793 return emitDag(DI); 1794 } 1795 1796 std::string Intrinsic::generate() { 1797 // Avoid duplicated code for big and little endian 1798 if (isBigEndianSafe()) { 1799 generateImpl(false, "", ""); 1800 return OS.str(); 1801 } 1802 // Little endian intrinsics are simple and don't require any argument 1803 // swapping. 1804 OS << "#ifdef __LITTLE_ENDIAN__\n"; 1805 1806 generateImpl(false, "", ""); 1807 1808 OS << "#else\n"; 1809 1810 // Big endian intrinsics are more complex. The user intended these 1811 // intrinsics to operate on a vector "as-if" loaded by (V)LDR, 1812 // but we load as-if (V)LD1. So we should swap all arguments and 1813 // swap the return value too. 1814 // 1815 // If we call sub-intrinsics, we should call a version that does 1816 // not re-swap the arguments! 1817 generateImpl(true, "", "__noswap_"); 1818 1819 // If we're needed early, create a non-swapping variant for 1820 // big-endian. 1821 if (NeededEarly) { 1822 generateImpl(false, "__noswap_", "__noswap_"); 1823 } 1824 OS << "#endif\n\n"; 1825 1826 return OS.str(); 1827 } 1828 1829 void Intrinsic::generateImpl(bool ReverseArguments, 1830 StringRef NamePrefix, StringRef CallPrefix) { 1831 CurrentRecord = R; 1832 1833 // If we call a macro, our local variables may be corrupted due to 1834 // lack of proper lexical scoping. So, add a globally unique postfix 1835 // to every variable. 1836 // 1837 // indexBody() should have set up the Dependencies set by now. 1838 for (auto *I : Dependencies) 1839 if (I->UseMacro) { 1840 VariablePostfix = "_" + utostr(Emitter.getUniqueNumber()); 1841 break; 1842 } 1843 1844 initVariables(); 1845 1846 emitPrototype(NamePrefix); 1847 1848 if (IsUnavailable) { 1849 OS << " __attribute__((unavailable));"; 1850 } else { 1851 emitOpeningBrace(); 1852 emitShadowedArgs(); 1853 if (ReverseArguments) 1854 emitArgumentReversal(); 1855 emitBody(CallPrefix); 1856 if (ReverseArguments) 1857 emitReturnReversal(); 1858 emitReturn(); 1859 emitClosingBrace(); 1860 } 1861 OS << "\n"; 1862 1863 CurrentRecord = nullptr; 1864 } 1865 1866 void Intrinsic::indexBody() { 1867 CurrentRecord = R; 1868 1869 initVariables(); 1870 emitBody(""); 1871 OS.str(""); 1872 1873 CurrentRecord = nullptr; 1874 } 1875 1876 //===----------------------------------------------------------------------===// 1877 // NeonEmitter implementation 1878 //===----------------------------------------------------------------------===// 1879 1880 Intrinsic &NeonEmitter::getIntrinsic(StringRef Name, ArrayRef<Type> Types, 1881 Optional<std::string> MangledName) { 1882 // First, look up the name in the intrinsic map. 1883 assert_with_loc(IntrinsicMap.find(Name.str()) != IntrinsicMap.end(), 1884 ("Intrinsic '" + Name + "' not found!").str()); 1885 auto &V = IntrinsicMap.find(Name.str())->second; 1886 std::vector<Intrinsic *> GoodVec; 1887 1888 // Create a string to print if we end up failing. 1889 std::string ErrMsg = "looking up intrinsic '" + Name.str() + "("; 1890 for (unsigned I = 0; I < Types.size(); ++I) { 1891 if (I != 0) 1892 ErrMsg += ", "; 1893 ErrMsg += Types[I].str(); 1894 } 1895 ErrMsg += ")'\n"; 1896 ErrMsg += "Available overloads:\n"; 1897 1898 // Now, look through each intrinsic implementation and see if the types are 1899 // compatible. 1900 for (auto &I : V) { 1901 ErrMsg += " - " + I.getReturnType().str() + " " + I.getMangledName(); 1902 ErrMsg += "("; 1903 for (unsigned A = 0; A < I.getNumParams(); ++A) { 1904 if (A != 0) 1905 ErrMsg += ", "; 1906 ErrMsg += I.getParamType(A).str(); 1907 } 1908 ErrMsg += ")\n"; 1909 1910 if (MangledName && MangledName != I.getMangledName(true)) 1911 continue; 1912 1913 if (I.getNumParams() != Types.size()) 1914 continue; 1915 1916 unsigned ArgNum = 0; 1917 bool MatchingArgumentTypes = 1918 std::all_of(Types.begin(), Types.end(), [&](const auto &Type) { 1919 return Type == I.getParamType(ArgNum++); 1920 }); 1921 1922 if (MatchingArgumentTypes) 1923 GoodVec.push_back(&I); 1924 } 1925 1926 assert_with_loc(!GoodVec.empty(), 1927 "No compatible intrinsic found - " + ErrMsg); 1928 assert_with_loc(GoodVec.size() == 1, "Multiple overloads found - " + ErrMsg); 1929 1930 return *GoodVec.front(); 1931 } 1932 1933 void NeonEmitter::createIntrinsic(Record *R, 1934 SmallVectorImpl<Intrinsic *> &Out) { 1935 std::string Name = std::string(R->getValueAsString("Name")); 1936 std::string Proto = std::string(R->getValueAsString("Prototype")); 1937 std::string Types = std::string(R->getValueAsString("Types")); 1938 Record *OperationRec = R->getValueAsDef("Operation"); 1939 bool BigEndianSafe = R->getValueAsBit("BigEndianSafe"); 1940 std::string Guard = std::string(R->getValueAsString("ArchGuard")); 1941 bool IsUnavailable = OperationRec->getValueAsBit("Unavailable"); 1942 std::string CartesianProductWith = std::string(R->getValueAsString("CartesianProductWith")); 1943 1944 // Set the global current record. This allows assert_with_loc to produce 1945 // decent location information even when highly nested. 1946 CurrentRecord = R; 1947 1948 ListInit *Body = OperationRec->getValueAsListInit("Ops"); 1949 1950 std::vector<TypeSpec> TypeSpecs = TypeSpec::fromTypeSpecs(Types); 1951 1952 ClassKind CK = ClassNone; 1953 if (R->getSuperClasses().size() >= 2) 1954 CK = ClassMap[R->getSuperClasses()[1].first]; 1955 1956 std::vector<std::pair<TypeSpec, TypeSpec>> NewTypeSpecs; 1957 if (!CartesianProductWith.empty()) { 1958 std::vector<TypeSpec> ProductTypeSpecs = TypeSpec::fromTypeSpecs(CartesianProductWith); 1959 for (auto TS : TypeSpecs) { 1960 Type DefaultT(TS, "."); 1961 for (auto SrcTS : ProductTypeSpecs) { 1962 Type DefaultSrcT(SrcTS, "."); 1963 if (TS == SrcTS || 1964 DefaultSrcT.getSizeInBits() != DefaultT.getSizeInBits()) 1965 continue; 1966 NewTypeSpecs.push_back(std::make_pair(TS, SrcTS)); 1967 } 1968 } 1969 } else { 1970 for (auto TS : TypeSpecs) { 1971 NewTypeSpecs.push_back(std::make_pair(TS, TS)); 1972 } 1973 } 1974 1975 llvm::sort(NewTypeSpecs); 1976 NewTypeSpecs.erase(std::unique(NewTypeSpecs.begin(), NewTypeSpecs.end()), 1977 NewTypeSpecs.end()); 1978 auto &Entry = IntrinsicMap[Name]; 1979 1980 for (auto &I : NewTypeSpecs) { 1981 Entry.emplace_back(R, Name, Proto, I.first, I.second, CK, Body, *this, 1982 Guard, IsUnavailable, BigEndianSafe); 1983 Out.push_back(&Entry.back()); 1984 } 1985 1986 CurrentRecord = nullptr; 1987 } 1988 1989 /// genBuiltinsDef: Generate the BuiltinsARM.def and BuiltinsAArch64.def 1990 /// declaration of builtins, checking for unique builtin declarations. 1991 void NeonEmitter::genBuiltinsDef(raw_ostream &OS, 1992 SmallVectorImpl<Intrinsic *> &Defs) { 1993 OS << "#ifdef GET_NEON_BUILTINS\n"; 1994 1995 // We only want to emit a builtin once, and we want to emit them in 1996 // alphabetical order, so use a std::set. 1997 std::set<std::string> Builtins; 1998 1999 for (auto *Def : Defs) { 2000 if (Def->hasBody()) 2001 continue; 2002 2003 std::string S = "BUILTIN(__builtin_neon_" + Def->getMangledName() + ", \""; 2004 2005 S += Def->getBuiltinTypeStr(); 2006 S += "\", \"n\")"; 2007 2008 Builtins.insert(S); 2009 } 2010 2011 for (auto &S : Builtins) 2012 OS << S << "\n"; 2013 OS << "#endif\n\n"; 2014 } 2015 2016 /// Generate the ARM and AArch64 overloaded type checking code for 2017 /// SemaChecking.cpp, checking for unique builtin declarations. 2018 void NeonEmitter::genOverloadTypeCheckCode(raw_ostream &OS, 2019 SmallVectorImpl<Intrinsic *> &Defs) { 2020 OS << "#ifdef GET_NEON_OVERLOAD_CHECK\n"; 2021 2022 // We record each overload check line before emitting because subsequent Inst 2023 // definitions may extend the number of permitted types (i.e. augment the 2024 // Mask). Use std::map to avoid sorting the table by hash number. 2025 struct OverloadInfo { 2026 uint64_t Mask; 2027 int PtrArgNum; 2028 bool HasConstPtr; 2029 OverloadInfo() : Mask(0ULL), PtrArgNum(0), HasConstPtr(false) {} 2030 }; 2031 std::map<std::string, OverloadInfo> OverloadMap; 2032 2033 for (auto *Def : Defs) { 2034 // If the def has a body (that is, it has Operation DAGs), it won't call 2035 // __builtin_neon_* so we don't need to generate a definition for it. 2036 if (Def->hasBody()) 2037 continue; 2038 // Functions which have a scalar argument cannot be overloaded, no need to 2039 // check them if we are emitting the type checking code. 2040 if (Def->protoHasScalar()) 2041 continue; 2042 2043 uint64_t Mask = 0ULL; 2044 Mask |= 1ULL << Def->getPolymorphicKeyType().getNeonEnum(); 2045 2046 // Check if the function has a pointer or const pointer argument. 2047 int PtrArgNum = -1; 2048 bool HasConstPtr = false; 2049 for (unsigned I = 0; I < Def->getNumParams(); ++I) { 2050 const auto &Type = Def->getParamType(I); 2051 if (Type.isPointer()) { 2052 PtrArgNum = I; 2053 HasConstPtr = Type.isConstPointer(); 2054 } 2055 } 2056 2057 // For sret builtins, adjust the pointer argument index. 2058 if (PtrArgNum >= 0 && Def->getReturnType().getNumVectors() > 1) 2059 PtrArgNum += 1; 2060 2061 std::string Name = Def->getName(); 2062 // Omit type checking for the pointer arguments of vld1_lane, vld1_dup, 2063 // and vst1_lane intrinsics. Using a pointer to the vector element 2064 // type with one of those operations causes codegen to select an aligned 2065 // load/store instruction. If you want an unaligned operation, 2066 // the pointer argument needs to have less alignment than element type, 2067 // so just accept any pointer type. 2068 if (Name == "vld1_lane" || Name == "vld1_dup" || Name == "vst1_lane") { 2069 PtrArgNum = -1; 2070 HasConstPtr = false; 2071 } 2072 2073 if (Mask) { 2074 std::string Name = Def->getMangledName(); 2075 OverloadMap.insert(std::make_pair(Name, OverloadInfo())); 2076 OverloadInfo &OI = OverloadMap[Name]; 2077 OI.Mask |= Mask; 2078 OI.PtrArgNum |= PtrArgNum; 2079 OI.HasConstPtr = HasConstPtr; 2080 } 2081 } 2082 2083 for (auto &I : OverloadMap) { 2084 OverloadInfo &OI = I.second; 2085 2086 OS << "case NEON::BI__builtin_neon_" << I.first << ": "; 2087 OS << "mask = 0x" << Twine::utohexstr(OI.Mask) << "ULL"; 2088 if (OI.PtrArgNum >= 0) 2089 OS << "; PtrArgNum = " << OI.PtrArgNum; 2090 if (OI.HasConstPtr) 2091 OS << "; HasConstPtr = true"; 2092 OS << "; break;\n"; 2093 } 2094 OS << "#endif\n\n"; 2095 } 2096 2097 void NeonEmitter::genIntrinsicRangeCheckCode(raw_ostream &OS, 2098 SmallVectorImpl<Intrinsic *> &Defs) { 2099 OS << "#ifdef GET_NEON_IMMEDIATE_CHECK\n"; 2100 2101 std::set<std::string> Emitted; 2102 2103 for (auto *Def : Defs) { 2104 if (Def->hasBody()) 2105 continue; 2106 // Functions which do not have an immediate do not need to have range 2107 // checking code emitted. 2108 if (!Def->hasImmediate()) 2109 continue; 2110 if (Emitted.find(Def->getMangledName()) != Emitted.end()) 2111 continue; 2112 2113 std::string LowerBound, UpperBound; 2114 2115 Record *R = Def->getRecord(); 2116 if (R->getValueAsBit("isVCVT_N")) { 2117 // VCVT between floating- and fixed-point values takes an immediate 2118 // in the range [1, 32) for f32 or [1, 64) for f64 or [1, 16) for f16. 2119 LowerBound = "1"; 2120 if (Def->getBaseType().getElementSizeInBits() == 16 || 2121 Def->getName().find('h') != std::string::npos) 2122 // VCVTh operating on FP16 intrinsics in range [1, 16) 2123 UpperBound = "15"; 2124 else if (Def->getBaseType().getElementSizeInBits() == 32) 2125 UpperBound = "31"; 2126 else 2127 UpperBound = "63"; 2128 } else if (R->getValueAsBit("isScalarShift")) { 2129 // Right shifts have an 'r' in the name, left shifts do not. Convert 2130 // instructions have the same bounds and right shifts. 2131 if (Def->getName().find('r') != std::string::npos || 2132 Def->getName().find("cvt") != std::string::npos) 2133 LowerBound = "1"; 2134 2135 UpperBound = utostr(Def->getReturnType().getElementSizeInBits() - 1); 2136 } else if (R->getValueAsBit("isShift")) { 2137 // Builtins which are overloaded by type will need to have their upper 2138 // bound computed at Sema time based on the type constant. 2139 2140 // Right shifts have an 'r' in the name, left shifts do not. 2141 if (Def->getName().find('r') != std::string::npos) 2142 LowerBound = "1"; 2143 UpperBound = "RFT(TV, true)"; 2144 } else if (Def->getClassKind(true) == ClassB) { 2145 // ClassB intrinsics have a type (and hence lane number) that is only 2146 // known at runtime. 2147 if (R->getValueAsBit("isLaneQ")) 2148 UpperBound = "RFT(TV, false, true)"; 2149 else 2150 UpperBound = "RFT(TV, false, false)"; 2151 } else { 2152 // The immediate generally refers to a lane in the preceding argument. 2153 assert(Def->getImmediateIdx() > 0); 2154 Type T = Def->getParamType(Def->getImmediateIdx() - 1); 2155 UpperBound = utostr(T.getNumElements() - 1); 2156 } 2157 2158 // Calculate the index of the immediate that should be range checked. 2159 unsigned Idx = Def->getNumParams(); 2160 if (Def->hasImmediate()) 2161 Idx = Def->getGeneratedParamIdx(Def->getImmediateIdx()); 2162 2163 OS << "case NEON::BI__builtin_neon_" << Def->getMangledName() << ": " 2164 << "i = " << Idx << ";"; 2165 if (!LowerBound.empty()) 2166 OS << " l = " << LowerBound << ";"; 2167 if (!UpperBound.empty()) 2168 OS << " u = " << UpperBound << ";"; 2169 OS << " break;\n"; 2170 2171 Emitted.insert(Def->getMangledName()); 2172 } 2173 2174 OS << "#endif\n\n"; 2175 } 2176 2177 /// runHeader - Emit a file with sections defining: 2178 /// 1. the NEON section of BuiltinsARM.def and BuiltinsAArch64.def. 2179 /// 2. the SemaChecking code for the type overload checking. 2180 /// 3. the SemaChecking code for validation of intrinsic immediate arguments. 2181 void NeonEmitter::runHeader(raw_ostream &OS) { 2182 std::vector<Record *> RV = Records.getAllDerivedDefinitions("Inst"); 2183 2184 SmallVector<Intrinsic *, 128> Defs; 2185 for (auto *R : RV) 2186 createIntrinsic(R, Defs); 2187 2188 // Generate shared BuiltinsXXX.def 2189 genBuiltinsDef(OS, Defs); 2190 2191 // Generate ARM overloaded type checking code for SemaChecking.cpp 2192 genOverloadTypeCheckCode(OS, Defs); 2193 2194 // Generate ARM range checking code for shift/lane immediates. 2195 genIntrinsicRangeCheckCode(OS, Defs); 2196 } 2197 2198 static void emitNeonTypeDefs(const std::string& types, raw_ostream &OS) { 2199 std::string TypedefTypes(types); 2200 std::vector<TypeSpec> TDTypeVec = TypeSpec::fromTypeSpecs(TypedefTypes); 2201 2202 // Emit vector typedefs. 2203 bool InIfdef = false; 2204 for (auto &TS : TDTypeVec) { 2205 bool IsA64 = false; 2206 Type T(TS, "."); 2207 if (T.isDouble()) 2208 IsA64 = true; 2209 2210 if (InIfdef && !IsA64) { 2211 OS << "#endif\n"; 2212 InIfdef = false; 2213 } 2214 if (!InIfdef && IsA64) { 2215 OS << "#ifdef __aarch64__\n"; 2216 InIfdef = true; 2217 } 2218 2219 if (T.isPoly()) 2220 OS << "typedef __attribute__((neon_polyvector_type("; 2221 else 2222 OS << "typedef __attribute__((neon_vector_type("; 2223 2224 Type T2 = T; 2225 T2.makeScalar(); 2226 OS << T.getNumElements() << "))) "; 2227 OS << T2.str(); 2228 OS << " " << T.str() << ";\n"; 2229 } 2230 if (InIfdef) 2231 OS << "#endif\n"; 2232 OS << "\n"; 2233 2234 // Emit struct typedefs. 2235 InIfdef = false; 2236 for (unsigned NumMembers = 2; NumMembers <= 4; ++NumMembers) { 2237 for (auto &TS : TDTypeVec) { 2238 bool IsA64 = false; 2239 Type T(TS, "."); 2240 if (T.isDouble()) 2241 IsA64 = true; 2242 2243 if (InIfdef && !IsA64) { 2244 OS << "#endif\n"; 2245 InIfdef = false; 2246 } 2247 if (!InIfdef && IsA64) { 2248 OS << "#ifdef __aarch64__\n"; 2249 InIfdef = true; 2250 } 2251 2252 const char Mods[] = { static_cast<char>('2' + (NumMembers - 2)), 0}; 2253 Type VT(TS, Mods); 2254 OS << "typedef struct " << VT.str() << " {\n"; 2255 OS << " " << T.str() << " val"; 2256 OS << "[" << NumMembers << "]"; 2257 OS << ";\n} "; 2258 OS << VT.str() << ";\n"; 2259 OS << "\n"; 2260 } 2261 } 2262 if (InIfdef) 2263 OS << "#endif\n"; 2264 } 2265 2266 /// run - Read the records in arm_neon.td and output arm_neon.h. arm_neon.h 2267 /// is comprised of type definitions and function declarations. 2268 void NeonEmitter::run(raw_ostream &OS) { 2269 OS << "/*===---- arm_neon.h - ARM Neon intrinsics " 2270 "------------------------------" 2271 "---===\n" 2272 " *\n" 2273 " * Permission is hereby granted, free of charge, to any person " 2274 "obtaining " 2275 "a copy\n" 2276 " * of this software and associated documentation files (the " 2277 "\"Software\")," 2278 " to deal\n" 2279 " * in the Software without restriction, including without limitation " 2280 "the " 2281 "rights\n" 2282 " * to use, copy, modify, merge, publish, distribute, sublicense, " 2283 "and/or sell\n" 2284 " * copies of the Software, and to permit persons to whom the Software " 2285 "is\n" 2286 " * furnished to do so, subject to the following conditions:\n" 2287 " *\n" 2288 " * The above copyright notice and this permission notice shall be " 2289 "included in\n" 2290 " * all copies or substantial portions of the Software.\n" 2291 " *\n" 2292 " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, " 2293 "EXPRESS OR\n" 2294 " * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF " 2295 "MERCHANTABILITY,\n" 2296 " * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT " 2297 "SHALL THE\n" 2298 " * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR " 2299 "OTHER\n" 2300 " * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, " 2301 "ARISING FROM,\n" 2302 " * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER " 2303 "DEALINGS IN\n" 2304 " * THE SOFTWARE.\n" 2305 " *\n" 2306 " *===-----------------------------------------------------------------" 2307 "---" 2308 "---===\n" 2309 " */\n\n"; 2310 2311 OS << "#ifndef __ARM_NEON_H\n"; 2312 OS << "#define __ARM_NEON_H\n\n"; 2313 2314 OS << "#if !defined(__ARM_NEON)\n"; 2315 OS << "#error \"NEON support not enabled\"\n"; 2316 OS << "#endif\n\n"; 2317 2318 OS << "#include <stdint.h>\n\n"; 2319 2320 OS << "#ifdef __ARM_FEATURE_BF16\n"; 2321 OS << "#include <arm_bf16.h>\n"; 2322 OS << "typedef __bf16 bfloat16_t;\n"; 2323 OS << "#endif\n\n"; 2324 2325 // Emit NEON-specific scalar typedefs. 2326 OS << "typedef float float32_t;\n"; 2327 OS << "typedef __fp16 float16_t;\n"; 2328 2329 OS << "#ifdef __aarch64__\n"; 2330 OS << "typedef double float64_t;\n"; 2331 OS << "#endif\n\n"; 2332 2333 // For now, signedness of polynomial types depends on target 2334 OS << "#ifdef __aarch64__\n"; 2335 OS << "typedef uint8_t poly8_t;\n"; 2336 OS << "typedef uint16_t poly16_t;\n"; 2337 OS << "typedef uint64_t poly64_t;\n"; 2338 OS << "typedef __uint128_t poly128_t;\n"; 2339 OS << "#else\n"; 2340 OS << "typedef int8_t poly8_t;\n"; 2341 OS << "typedef int16_t poly16_t;\n"; 2342 OS << "typedef int64_t poly64_t;\n"; 2343 OS << "#endif\n"; 2344 2345 emitNeonTypeDefs("cQcsQsiQilQlUcQUcUsQUsUiQUiUlQUlhQhfQfdQdPcQPcPsQPsPlQPl", OS); 2346 2347 OS << "#ifdef __ARM_FEATURE_BF16\n"; 2348 emitNeonTypeDefs("bQb", OS); 2349 OS << "#endif\n\n"; 2350 2351 OS << "#define __ai static __inline__ __attribute__((__always_inline__, " 2352 "__nodebug__))\n\n"; 2353 2354 SmallVector<Intrinsic *, 128> Defs; 2355 std::vector<Record *> RV = Records.getAllDerivedDefinitions("Inst"); 2356 for (auto *R : RV) 2357 createIntrinsic(R, Defs); 2358 2359 for (auto *I : Defs) 2360 I->indexBody(); 2361 2362 llvm::stable_sort(Defs, llvm::deref<std::less<>>()); 2363 2364 // Only emit a def when its requirements have been met. 2365 // FIXME: This loop could be made faster, but it's fast enough for now. 2366 bool MadeProgress = true; 2367 std::string InGuard; 2368 while (!Defs.empty() && MadeProgress) { 2369 MadeProgress = false; 2370 2371 for (SmallVector<Intrinsic *, 128>::iterator I = Defs.begin(); 2372 I != Defs.end(); /*No step*/) { 2373 bool DependenciesSatisfied = true; 2374 for (auto *II : (*I)->getDependencies()) { 2375 if (llvm::is_contained(Defs, II)) 2376 DependenciesSatisfied = false; 2377 } 2378 if (!DependenciesSatisfied) { 2379 // Try the next one. 2380 ++I; 2381 continue; 2382 } 2383 2384 // Emit #endif/#if pair if needed. 2385 if ((*I)->getGuard() != InGuard) { 2386 if (!InGuard.empty()) 2387 OS << "#endif\n"; 2388 InGuard = (*I)->getGuard(); 2389 if (!InGuard.empty()) 2390 OS << "#if " << InGuard << "\n"; 2391 } 2392 2393 // Actually generate the intrinsic code. 2394 OS << (*I)->generate(); 2395 2396 MadeProgress = true; 2397 I = Defs.erase(I); 2398 } 2399 } 2400 assert(Defs.empty() && "Some requirements were not satisfied!"); 2401 if (!InGuard.empty()) 2402 OS << "#endif\n"; 2403 2404 OS << "\n"; 2405 OS << "#undef __ai\n\n"; 2406 OS << "#endif /* __ARM_NEON_H */\n"; 2407 } 2408 2409 /// run - Read the records in arm_fp16.td and output arm_fp16.h. arm_fp16.h 2410 /// is comprised of type definitions and function declarations. 2411 void NeonEmitter::runFP16(raw_ostream &OS) { 2412 OS << "/*===---- arm_fp16.h - ARM FP16 intrinsics " 2413 "------------------------------" 2414 "---===\n" 2415 " *\n" 2416 " * Permission is hereby granted, free of charge, to any person " 2417 "obtaining a copy\n" 2418 " * of this software and associated documentation files (the " 2419 "\"Software\"), to deal\n" 2420 " * in the Software without restriction, including without limitation " 2421 "the rights\n" 2422 " * to use, copy, modify, merge, publish, distribute, sublicense, " 2423 "and/or sell\n" 2424 " * copies of the Software, and to permit persons to whom the Software " 2425 "is\n" 2426 " * furnished to do so, subject to the following conditions:\n" 2427 " *\n" 2428 " * The above copyright notice and this permission notice shall be " 2429 "included in\n" 2430 " * all copies or substantial portions of the Software.\n" 2431 " *\n" 2432 " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, " 2433 "EXPRESS OR\n" 2434 " * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF " 2435 "MERCHANTABILITY,\n" 2436 " * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT " 2437 "SHALL THE\n" 2438 " * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR " 2439 "OTHER\n" 2440 " * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, " 2441 "ARISING FROM,\n" 2442 " * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER " 2443 "DEALINGS IN\n" 2444 " * THE SOFTWARE.\n" 2445 " *\n" 2446 " *===-----------------------------------------------------------------" 2447 "---" 2448 "---===\n" 2449 " */\n\n"; 2450 2451 OS << "#ifndef __ARM_FP16_H\n"; 2452 OS << "#define __ARM_FP16_H\n\n"; 2453 2454 OS << "#include <stdint.h>\n\n"; 2455 2456 OS << "typedef __fp16 float16_t;\n"; 2457 2458 OS << "#define __ai static __inline__ __attribute__((__always_inline__, " 2459 "__nodebug__))\n\n"; 2460 2461 SmallVector<Intrinsic *, 128> Defs; 2462 std::vector<Record *> RV = Records.getAllDerivedDefinitions("Inst"); 2463 for (auto *R : RV) 2464 createIntrinsic(R, Defs); 2465 2466 for (auto *I : Defs) 2467 I->indexBody(); 2468 2469 llvm::stable_sort(Defs, llvm::deref<std::less<>>()); 2470 2471 // Only emit a def when its requirements have been met. 2472 // FIXME: This loop could be made faster, but it's fast enough for now. 2473 bool MadeProgress = true; 2474 std::string InGuard; 2475 while (!Defs.empty() && MadeProgress) { 2476 MadeProgress = false; 2477 2478 for (SmallVector<Intrinsic *, 128>::iterator I = Defs.begin(); 2479 I != Defs.end(); /*No step*/) { 2480 bool DependenciesSatisfied = true; 2481 for (auto *II : (*I)->getDependencies()) { 2482 if (llvm::is_contained(Defs, II)) 2483 DependenciesSatisfied = false; 2484 } 2485 if (!DependenciesSatisfied) { 2486 // Try the next one. 2487 ++I; 2488 continue; 2489 } 2490 2491 // Emit #endif/#if pair if needed. 2492 if ((*I)->getGuard() != InGuard) { 2493 if (!InGuard.empty()) 2494 OS << "#endif\n"; 2495 InGuard = (*I)->getGuard(); 2496 if (!InGuard.empty()) 2497 OS << "#if " << InGuard << "\n"; 2498 } 2499 2500 // Actually generate the intrinsic code. 2501 OS << (*I)->generate(); 2502 2503 MadeProgress = true; 2504 I = Defs.erase(I); 2505 } 2506 } 2507 assert(Defs.empty() && "Some requirements were not satisfied!"); 2508 if (!InGuard.empty()) 2509 OS << "#endif\n"; 2510 2511 OS << "\n"; 2512 OS << "#undef __ai\n\n"; 2513 OS << "#endif /* __ARM_FP16_H */\n"; 2514 } 2515 2516 void NeonEmitter::runBF16(raw_ostream &OS) { 2517 OS << "/*===---- arm_bf16.h - ARM BF16 intrinsics " 2518 "-----------------------------------===\n" 2519 " *\n" 2520 " *\n" 2521 " * Part of the LLVM Project, under the Apache License v2.0 with LLVM " 2522 "Exceptions.\n" 2523 " * See https://llvm.org/LICENSE.txt for license information.\n" 2524 " * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n" 2525 " *\n" 2526 " *===-----------------------------------------------------------------" 2527 "------===\n" 2528 " */\n\n"; 2529 2530 OS << "#ifndef __ARM_BF16_H\n"; 2531 OS << "#define __ARM_BF16_H\n\n"; 2532 2533 OS << "typedef __bf16 bfloat16_t;\n"; 2534 2535 OS << "#define __ai static __inline__ __attribute__((__always_inline__, " 2536 "__nodebug__))\n\n"; 2537 2538 SmallVector<Intrinsic *, 128> Defs; 2539 std::vector<Record *> RV = Records.getAllDerivedDefinitions("Inst"); 2540 for (auto *R : RV) 2541 createIntrinsic(R, Defs); 2542 2543 for (auto *I : Defs) 2544 I->indexBody(); 2545 2546 llvm::stable_sort(Defs, llvm::deref<std::less<>>()); 2547 2548 // Only emit a def when its requirements have been met. 2549 // FIXME: This loop could be made faster, but it's fast enough for now. 2550 bool MadeProgress = true; 2551 std::string InGuard; 2552 while (!Defs.empty() && MadeProgress) { 2553 MadeProgress = false; 2554 2555 for (SmallVector<Intrinsic *, 128>::iterator I = Defs.begin(); 2556 I != Defs.end(); /*No step*/) { 2557 bool DependenciesSatisfied = true; 2558 for (auto *II : (*I)->getDependencies()) { 2559 if (llvm::is_contained(Defs, II)) 2560 DependenciesSatisfied = false; 2561 } 2562 if (!DependenciesSatisfied) { 2563 // Try the next one. 2564 ++I; 2565 continue; 2566 } 2567 2568 // Emit #endif/#if pair if needed. 2569 if ((*I)->getGuard() != InGuard) { 2570 if (!InGuard.empty()) 2571 OS << "#endif\n"; 2572 InGuard = (*I)->getGuard(); 2573 if (!InGuard.empty()) 2574 OS << "#if " << InGuard << "\n"; 2575 } 2576 2577 // Actually generate the intrinsic code. 2578 OS << (*I)->generate(); 2579 2580 MadeProgress = true; 2581 I = Defs.erase(I); 2582 } 2583 } 2584 assert(Defs.empty() && "Some requirements were not satisfied!"); 2585 if (!InGuard.empty()) 2586 OS << "#endif\n"; 2587 2588 OS << "\n"; 2589 OS << "#undef __ai\n\n"; 2590 2591 OS << "#endif\n"; 2592 } 2593 2594 void clang::EmitNeon(RecordKeeper &Records, raw_ostream &OS) { 2595 NeonEmitter(Records).run(OS); 2596 } 2597 2598 void clang::EmitFP16(RecordKeeper &Records, raw_ostream &OS) { 2599 NeonEmitter(Records).runFP16(OS); 2600 } 2601 2602 void clang::EmitBF16(RecordKeeper &Records, raw_ostream &OS) { 2603 NeonEmitter(Records).runBF16(OS); 2604 } 2605 2606 void clang::EmitNeonSema(RecordKeeper &Records, raw_ostream &OS) { 2607 NeonEmitter(Records).runHeader(OS); 2608 } 2609 2610 void clang::EmitNeonTest(RecordKeeper &Records, raw_ostream &OS) { 2611 llvm_unreachable("Neon test generation no longer implemented!"); 2612 } 2613