diff options
Diffstat (limited to 'clang/utils/TableGen/NeonEmitter.cpp')
| -rw-r--r-- | clang/utils/TableGen/NeonEmitter.cpp | 632 |
1 files changed, 224 insertions, 408 deletions
diff --git a/clang/utils/TableGen/NeonEmitter.cpp b/clang/utils/TableGen/NeonEmitter.cpp index 9d668a281534..a0f3fb2ddc08 100644 --- a/clang/utils/TableGen/NeonEmitter.cpp +++ b/clang/utils/TableGen/NeonEmitter.cpp @@ -140,7 +140,15 @@ class Type { private: TypeSpec TS; - bool Float, Signed, Immediate, Void, Poly, Constant, Pointer; + enum TypeKind { + Void, + Float, + SInt, + UInt, + Poly, + }; + TypeKind Kind; + bool Immediate, Constant, Pointer; // ScalarForMangling and NoManglingQ are really not suited to live here as // they are not related to the type. But they live in the TypeSpec (not the // prototype), so this is really the only place to store them. @@ -149,16 +157,15 @@ private: public: Type() - : Float(false), Signed(false), Immediate(false), Void(true), Poly(false), - Constant(false), Pointer(false), ScalarForMangling(false), - NoManglingQ(false), Bitwidth(0), ElementBitwidth(0), NumVectors(0) {} + : Kind(Void), Immediate(false), Constant(false), + Pointer(false), ScalarForMangling(false), NoManglingQ(false), + Bitwidth(0), ElementBitwidth(0), NumVectors(0) {} - Type(TypeSpec TS, char CharMod) - : TS(std::move(TS)), Float(false), Signed(false), Immediate(false), - Void(false), Poly(false), Constant(false), Pointer(false), - ScalarForMangling(false), NoManglingQ(false), Bitwidth(0), - ElementBitwidth(0), NumVectors(0) { - applyModifier(CharMod); + Type(TypeSpec TS, StringRef CharMods) + : TS(std::move(TS)), Kind(Void), Immediate(false), + Constant(false), Pointer(false), ScalarForMangling(false), + NoManglingQ(false), Bitwidth(0), ElementBitwidth(0), NumVectors(0) { + applyModifiers(CharMods); } /// Returns a type representing "void". @@ -174,21 +181,23 @@ public: bool noManglingQ() const { return NoManglingQ; } bool isPointer() const { return Pointer; } - bool isFloating() const { return Float; } - bool isInteger() const { return !Float && !Poly; } - bool isSigned() const { return Signed; } + bool isValue() const { return !isVoid() && !isPointer(); } + bool isScalar() const { return isValue() && NumVectors == 0; } + bool isVector() const { return isValue() && NumVectors > 0; } + bool isConstPointer() const { return Constant; } + bool isFloating() const { return Kind == Float; } + bool isInteger() const { return Kind == SInt || Kind == UInt; } + bool isPoly() const { return Kind == Poly; } + bool isSigned() const { return Kind == SInt; } bool isImmediate() const { return Immediate; } - bool isScalar() const { return NumVectors == 0; } - bool isVector() const { return NumVectors > 0; } - bool isFloat() const { return Float && ElementBitwidth == 32; } - bool isDouble() const { return Float && ElementBitwidth == 64; } - bool isHalf() const { return Float && ElementBitwidth == 16; } - bool isPoly() const { return Poly; } + bool isFloat() const { return isFloating() && ElementBitwidth == 32; } + bool isDouble() const { return isFloating() && ElementBitwidth == 64; } + bool isHalf() const { return isFloating() && ElementBitwidth == 16; } bool isChar() const { return ElementBitwidth == 8; } - bool isShort() const { return !Float && ElementBitwidth == 16; } - bool isInt() const { return !Float && ElementBitwidth == 32; } - bool isLong() const { return !Float && ElementBitwidth == 64; } - bool isVoid() const { return Void; } + bool isShort() const { return isInteger() && ElementBitwidth == 16; } + bool isInt() const { return isInteger() && ElementBitwidth == 32; } + bool isLong() const { return isInteger() && ElementBitwidth == 64; } + bool isVoid() const { return Kind == Void; } unsigned getNumElements() const { return Bitwidth / ElementBitwidth; } unsigned getSizeInBits() const { return Bitwidth; } unsigned getElementSizeInBits() const { return ElementBitwidth; } @@ -197,21 +206,24 @@ public: // // Mutator functions // - void makeUnsigned() { Signed = false; } - void makeSigned() { Signed = true; } + void makeUnsigned() { + assert(!isVoid() && "not a potentially signed type"); + Kind = UInt; + } + void makeSigned() { + assert(!isVoid() && "not a potentially signed type"); + Kind = SInt; + } void makeInteger(unsigned ElemWidth, bool Sign) { - Float = false; - Poly = false; - Signed = Sign; + assert(!isVoid() && "converting void to int probably not useful"); + Kind = Sign ? SInt : UInt; Immediate = false; ElementBitwidth = ElemWidth; } void makeImmediate(unsigned ElemWidth) { - Float = false; - Poly = false; - Signed = true; + Kind = SInt; Immediate = true; ElementBitwidth = ElemWidth; } @@ -257,8 +269,8 @@ private: /// seen. This is needed by applyModifier as some modifiers /// only take effect if the type size was changed by "Q" or "H". void applyTypespec(bool &Quad); - /// Applies a prototype modifier to the type. - void applyModifier(char Mod); + /// Applies prototype modifiers to the type. + void applyModifiers(StringRef Mods); }; //===----------------------------------------------------------------------===// @@ -289,8 +301,8 @@ class Intrinsic { /// The Record this intrinsic was created from. Record *R; - /// The unmangled name and prototype. - std::string Name, Proto; + /// The unmangled name. + std::string Name; /// The input and output typespecs. InTS == OutTS except when /// CartesianProductOfTypes is 1 - this is the case for vreinterpret. TypeSpec OutTS, InTS; @@ -313,6 +325,8 @@ class Intrinsic { /// The types of return value [0] and parameters [1..]. std::vector<Type> Types; + /// The index of the key type passed to CGBuiltin.cpp for polymorphic calls. + int PolymorphicKeyType; /// The local variables defined. std::map<std::string, Variable> Variables; /// NeededEarly - set if any other intrinsic depends on this intrinsic. @@ -348,34 +362,39 @@ public: Intrinsic(Record *R, StringRef Name, StringRef Proto, TypeSpec OutTS, TypeSpec InTS, ClassKind CK, ListInit *Body, NeonEmitter &Emitter, StringRef Guard, bool IsUnavailable, bool BigEndianSafe) - : R(R), Name(Name.str()), Proto(Proto.str()), OutTS(OutTS), InTS(InTS), - CK(CK), Body(Body), Guard(Guard.str()), IsUnavailable(IsUnavailable), - BigEndianSafe(BigEndianSafe), NeededEarly(false), UseMacro(false), - BaseType(OutTS, 'd'), InBaseType(InTS, 'd'), Emitter(Emitter) { - // If this builtin takes an immediate argument, we need to #define it rather - // than use a standard declaration, so that SemaChecking can range check - // the immediate passed by the user. - if (Proto.find('i') != std::string::npos) - UseMacro = true; - - // Pointer arguments need to use macros to avoid hiding aligned attributes - // from the pointer type. - if (Proto.find('p') != std::string::npos || - Proto.find('c') != std::string::npos) - UseMacro = true; - - // It is not permitted to pass or return an __fp16 by value, so intrinsics - // taking a scalar float16_t must be implemented as macros. - if (OutTS.find('h') != std::string::npos && - Proto.find('s') != std::string::npos) - UseMacro = true; - + : R(R), Name(Name.str()), OutTS(OutTS), InTS(InTS), CK(CK), Body(Body), + Guard(Guard.str()), IsUnavailable(IsUnavailable), + BigEndianSafe(BigEndianSafe), PolymorphicKeyType(0), NeededEarly(false), + UseMacro(false), BaseType(OutTS, "."), InBaseType(InTS, "."), + Emitter(Emitter) { // Modify the TypeSpec per-argument to get a concrete Type, and create // known variables for each. // Types[0] is the return value. - Types.emplace_back(OutTS, Proto[0]); - for (unsigned I = 1; I < Proto.size(); ++I) - Types.emplace_back(InTS, Proto[I]); + unsigned Pos = 0; + Types.emplace_back(OutTS, getNextModifiers(Proto, Pos)); + StringRef Mods = getNextModifiers(Proto, Pos); + while (!Mods.empty()) { + Types.emplace_back(InTS, Mods); + if (Mods.find("!") != StringRef::npos) + PolymorphicKeyType = Types.size() - 1; + + Mods = getNextModifiers(Proto, Pos); + } + + for (auto Type : Types) { + // If this builtin takes an immediate argument, we need to #define it rather + // than use a standard declaration, so that SemaChecking can range check + // the immediate passed by the user. + + // Pointer arguments need to use macros to avoid hiding aligned attributes + // from the pointer type. + + // It is not permitted to pass or return an __fp16 by value, so intrinsics + // taking a scalar float16_t must be implemented as macros. + if (Type.isImmediate() || Type.isPointer() || + (Type.isScalar() && Type.isHalf())) + UseMacro = true; + } } /// Get the Record that this intrinsic is based off. @@ -391,37 +410,26 @@ public: /// Return true if the intrinsic takes an immediate operand. bool hasImmediate() const { - return Proto.find('i') != std::string::npos; + return std::any_of(Types.begin(), Types.end(), + [](const Type &T) { return T.isImmediate(); }); } /// Return the parameter index of the immediate operand. unsigned getImmediateIdx() const { - assert(hasImmediate()); - unsigned Idx = Proto.find('i'); - assert(Idx > 0 && "Can't return an immediate!"); - return Idx - 1; + for (unsigned Idx = 0; Idx < Types.size(); ++Idx) + if (Types[Idx].isImmediate()) + return Idx - 1; + llvm_unreachable("Intrinsic has no immediate"); } - /// Return true if the intrinsic takes an splat operand. - bool hasSplat() const { return Proto.find('a') != std::string::npos; } - - /// Return the parameter index of the splat operand. - unsigned getSplatIdx() const { - assert(hasSplat()); - unsigned Idx = Proto.find('a'); - assert(Idx > 0 && "Can't return a splat!"); - return Idx - 1; - } - unsigned getNumParams() const { return Proto.size() - 1; } + unsigned getNumParams() const { return Types.size() - 1; } Type getReturnType() const { return Types[0]; } Type getParamType(unsigned I) const { return Types[I + 1]; } Type getBaseType() const { return BaseType; } - /// Return the raw prototype string. - std::string getProto() const { return Proto; } + Type getPolymorphicKeyType() const { return Types[PolymorphicKeyType]; } /// Return true if the prototype has a scalar argument. - /// This does not return true for the "splat" code ('a'). bool protoHasScalar() const; /// Return the index that parameter PIndex will sit at @@ -473,6 +481,8 @@ public: void indexBody(); private: + StringRef getNextModifiers(StringRef Proto, unsigned &Pos) const; + std::string mangleName(std::string Name, ClassKind CK) const; void initVariables(); @@ -582,16 +592,16 @@ public: //===----------------------------------------------------------------------===// std::string Type::str() const { - if (Void) + if (isVoid()) return "void"; std::string S; - if (!Signed && isInteger()) + if (isInteger() && !isSigned()) S += "u"; - if (Poly) + if (isPoly()) S += "poly"; - else if (Float) + else if (isFloating()) S += "float"; else S += "int"; @@ -616,10 +626,14 @@ std::string Type::builtin_str() const { if (isVoid()) return "v"; - if (Pointer) + if (isPointer()) { // All pointers are void pointers. - S += "v"; - else if (isInteger()) + S = "v"; + if (isConstPointer()) + S += "C"; + S += "*"; + return S; + } else if (isInteger()) switch (ElementBitwidth) { case 8: S += "c"; break; case 16: S += "s"; break; @@ -636,10 +650,11 @@ std::string Type::builtin_str() const { default: llvm_unreachable("Unhandled case!"); } - if (isChar() && !Pointer && Signed) + // FIXME: NECESSARY??????????????????????????????????????????????????????????????????????? + if (isChar() && !isPointer() && isSigned()) // Make chars explicitly signed. S = "S" + S; - else if (isInteger() && !Pointer && !Signed) + else if (isInteger() && !isSigned()) S = "U" + S; // Constant indices are "int", but have the "constant expression" modifier. @@ -648,11 +663,8 @@ std::string Type::builtin_str() const { S = "I" + S; } - if (isScalar()) { - if (Constant) S += "C"; - if (Pointer) S += "*"; + if (isScalar()) return S; - } std::string Ret; for (unsigned I = 0; I < NumVectors; ++I) @@ -673,20 +685,20 @@ unsigned Type::getNeonEnum() const { } unsigned Base = (unsigned)NeonTypeFlags::Int8 + Addend; - if (Poly) { + if (isPoly()) { // Adjustment needed because Poly32 doesn't exist. if (Addend >= 2) --Addend; Base = (unsigned)NeonTypeFlags::Poly8 + Addend; } - if (Float) { + if (isFloating()) { assert(Addend != 0 && "Float8 doesn't exist!"); Base = (unsigned)NeonTypeFlags::Float16 + (Addend - 1); } if (Bitwidth == 128) Base |= (unsigned)NeonTypeFlags::QuadFlag; - if (isInteger() && !Signed) + if (isInteger() && !isSigned()) Base |= (unsigned)NeonTypeFlags::UnsignedFlag; return Base; @@ -694,22 +706,18 @@ unsigned Type::getNeonEnum() const { Type Type::fromTypedefName(StringRef Name) { Type T; - T.Void = false; - T.Float = false; - T.Poly = false; + T.Kind = SInt; if (Name.front() == 'u') { - T.Signed = false; + T.Kind = UInt; Name = Name.drop_front(); - } else { - T.Signed = true; } if (Name.startswith("float")) { - T.Float = true; + T.Kind = Float; Name = Name.drop_front(5); } else if (Name.startswith("poly")) { - T.Poly = true; + T.Kind = Poly; Name = Name.drop_front(4); } else { assert(Name.startswith("int")); @@ -760,10 +768,8 @@ Type Type::fromTypedefName(StringRef Name) { void Type::applyTypespec(bool &Quad) { std::string S = TS; ScalarForMangling = false; - Void = false; - Poly = Float = false; + Kind = SInt; ElementBitwidth = ~0U; - Signed = true; NumVectors = 1; for (char I : S) { @@ -779,28 +785,28 @@ void Type::applyTypespec(bool &Quad) { Quad = true; break; case 'P': - Poly = true; + Kind = Poly; break; case 'U': - Signed = false; + Kind = UInt; break; case 'c': ElementBitwidth = 8; break; case 'h': - Float = true; + Kind = Float; LLVM_FALLTHROUGH; case 's': ElementBitwidth = 16; break; case 'f': - Float = true; + Kind = Float; LLVM_FALLTHROUGH; case 'i': ElementBitwidth = 32; break; case 'd': - Float = true; + Kind = Float; LLVM_FALLTHROUGH; case 'l': ElementBitwidth = 64; @@ -808,7 +814,7 @@ void Type::applyTypespec(bool &Quad) { case 'k': ElementBitwidth = 128; // Poly doesn't have a 128x1 type. - if (Poly) + if (isPoly()) NumVectors = 0; break; default: @@ -820,220 +826,77 @@ void Type::applyTypespec(bool &Quad) { Bitwidth = Quad ? 128 : 64; } -void Type::applyModifier(char Mod) { +void Type::applyModifiers(StringRef Mods) { bool AppliedQuad = false; applyTypespec(AppliedQuad); - switch (Mod) { - case 'v': - Void = true; - break; - case 't': - if (Poly) { - Poly = false; - Signed = false; + for (char Mod : Mods) { + switch (Mod) { + case '.': + break; + case 'v': + Kind = Void; + break; + case 'S': + Kind = SInt; + break; + case 'U': + Kind = UInt; + break; + case 'F': + Kind = Float; + break; + case 'P': + Kind = Poly; + break; + case '>': + assert(ElementBitwidth < 128); + ElementBitwidth *= 2; + break; + case '<': + assert(ElementBitwidth > 8); + ElementBitwidth /= 2; + break; + case '1': + NumVectors = 0; + break; + case '2': + NumVectors = 2; + break; + case '3': + NumVectors = 3; + break; + case '4': + NumVectors = 4; + break; + case '*': + Pointer = true; + break; + case 'c': + Constant = true; + break; + case 'Q': + Bitwidth = 128; + break; + case 'q': + Bitwidth = 64; + break; + case 'I': + Kind = SInt; + ElementBitwidth = Bitwidth = 32; + NumVectors = 0; + Immediate = true; + break; + case 'p': + if (isPoly()) + Kind = UInt; + break; + case '!': + // Key type, handled elsewhere. + break; + default: + llvm_unreachable("Unhandled character!"); } - break; - case 'b': - Signed = false; - Float = false; - Poly = false; - NumVectors = 0; - Bitwidth = ElementBitwidth; - break; - case '$': - Signed = true; - Float = false; - Poly = false; - NumVectors = 0; - Bitwidth = ElementBitwidth; - break; - case 'u': - Signed = false; - Poly = false; - Float = false; - break; - case 'x': - Signed = true; - assert(!Poly && "'u' can't be used with poly types!"); - Float = false; - break; - case 'o': - Bitwidth = ElementBitwidth = 64; - NumVectors = 0; - Float = true; - break; - case 'y': - Bitwidth = ElementBitwidth = 32; - NumVectors = 0; - Float = true; - break; - case 'Y': - Bitwidth = ElementBitwidth = 16; - NumVectors = 0; - Float = true; - break; - case 'I': - Bitwidth = ElementBitwidth = 32; - NumVectors = 0; - Float = false; - Signed = true; - break; - case 'L': - Bitwidth = ElementBitwidth = 64; - NumVectors = 0; - Float = false; - Signed = true; - break; - case 'U': - Bitwidth = ElementBitwidth = 32; - NumVectors = 0; - Float = false; - Signed = false; - break; - case 'O': - Bitwidth = ElementBitwidth = 64; - NumVectors = 0; - Float = false; - Signed = false; - break; - case 'f': - Float = true; - ElementBitwidth = 32; - break; - case 'F': - Float = true; - ElementBitwidth = 64; - break; - case 'H': - Float = true; - ElementBitwidth = 16; - break; - case '0': - Float = true; - if (AppliedQuad) - Bitwidth /= 2; - ElementBitwidth = 16; - break; - case '1': - Float = true; - if (!AppliedQuad) - Bitwidth *= 2; - ElementBitwidth = 16; - break; - case 'g': - if (AppliedQuad) - Bitwidth /= 2; - break; - case 'j': - if (!AppliedQuad) - Bitwidth *= 2; - break; - case 'w': - ElementBitwidth *= 2; - Bitwidth *= 2; - break; - case 'n': - ElementBitwidth *= 2; - break; - case 'i': - Float = false; - Poly = false; - ElementBitwidth = Bitwidth = 32; - NumVectors = 0; - Signed = true; - Immediate = true; - break; - case 'l': - Float = false; - Poly = false; - ElementBitwidth = Bitwidth = 64; - NumVectors = 0; - Signed = false; - Immediate = true; - break; - case 'z': - ElementBitwidth /= 2; - Bitwidth = ElementBitwidth; - NumVectors = 0; - break; - case 'r': - ElementBitwidth *= 2; - Bitwidth = ElementBitwidth; - NumVectors = 0; - break; - case 's': - case 'a': - Bitwidth = ElementBitwidth; - NumVectors = 0; - break; - case 'k': - Bitwidth *= 2; - break; - case 'c': - Constant = true; - LLVM_FALLTHROUGH; - case 'p': - Pointer = true; - Bitwidth = ElementBitwidth; - NumVectors = 0; - break; - case 'h': - ElementBitwidth /= 2; - break; - case 'q': - ElementBitwidth /= 2; - Bitwidth *= 2; - break; - case 'e': - ElementBitwidth /= 2; - Signed = false; - break; - case 'm': - ElementBitwidth /= 2; - Bitwidth /= 2; - break; - case 'd': - break; - case '2': - NumVectors = 2; - break; - case '3': - NumVectors = 3; - break; - case '4': - NumVectors = 4; - break; - case 'B': - NumVectors = 2; - if (!AppliedQuad) - Bitwidth *= 2; - break; - case 'C': - NumVectors = 3; - if (!AppliedQuad) - Bitwidth *= 2; - break; - case 'D': - NumVectors = 4; - if (!AppliedQuad) - Bitwidth *= 2; - break; - case '7': - if (AppliedQuad) - Bitwidth /= 2; - ElementBitwidth = 8; - break; - case '8': - ElementBitwidth = 8; - break; - case '9': - if (!AppliedQuad) - Bitwidth *= 2; - ElementBitwidth = 8; - break; - default: - llvm_unreachable("Unhandled character!"); } } @@ -1041,6 +904,19 @@ void Type::applyModifier(char Mod) { // Intrinsic implementation //===----------------------------------------------------------------------===// +StringRef Intrinsic::getNextModifiers(StringRef Proto, unsigned &Pos) const { + if (Proto.size() == Pos) + return StringRef(); + else if (Proto[Pos] != '(') + return Proto.substr(Pos++, 1); + + size_t Start = Pos + 1; + size_t End = Proto.find(')', Start); + assert_with_loc(End != StringRef::npos, "unmatched modifier group paren"); + Pos = End + 1; + return Proto.slice(Start, End); +} + std::string Intrinsic::getInstTypeCode(Type T, ClassKind CK) const { char typeCode = '\0'; bool printNumber = true; @@ -1079,10 +955,6 @@ std::string Intrinsic::getInstTypeCode(Type T, ClassKind CK) const { return S; } -static bool isFloatingPointProtoModifier(char Mod) { - return Mod == 'F' || Mod == 'f' || Mod == 'H' || Mod == 'Y' || Mod == 'I'; -} - std::string Intrinsic::getBuiltinTypeStr() { ClassKind LocalCK = getClassKind(true); std::string S; @@ -1101,11 +973,10 @@ std::string Intrinsic::getBuiltinTypeStr() { } else { if (RetT.isPoly()) RetT.makeInteger(RetT.getElementSizeInBits(), false); - if (!RetT.isScalar() && !RetT.isSigned()) + if (!RetT.isScalar() && RetT.isInteger() && !RetT.isSigned()) RetT.makeSigned(); - bool ForcedVectorFloatingType = isFloatingPointProtoModifier(Proto[0]); - if (LocalCK == ClassB && !RetT.isScalar() && !ForcedVectorFloatingType) + if (LocalCK == ClassB && RetT.isValue() && !RetT.isScalar()) // Cast to vector of 8-bit elements. RetT.makeInteger(8, true); @@ -1117,14 +988,13 @@ std::string Intrinsic::getBuiltinTypeStr() { if (T.isPoly()) T.makeInteger(T.getElementSizeInBits(), false); - bool ForcedFloatingType = isFloatingPointProtoModifier(Proto[I + 1]); - if (LocalCK == ClassB && !T.isScalar() && !ForcedFloatingType) + if (LocalCK == ClassB && !T.isScalar()) T.makeInteger(8, true); // Halves always get converted to 8-bit elements. if (T.isHalf() && T.isVector() && !T.isScalarForMangling()) T.makeInteger(8, true); - if (LocalCK == ClassI) + if (LocalCK == ClassI && T.isInteger()) T.makeSigned(); if (hasImmediate() && getImmediateIdx() == I) @@ -1222,7 +1092,7 @@ void Intrinsic::initVariables() { // Modify the TypeSpec per-argument to get a concrete Type, and create // known variables for each. - for (unsigned I = 1; I < Proto.size(); ++I) { + for (unsigned I = 1; I < Types.size(); ++I) { char NameC = '0' + (I - 1); std::string Name = "p"; Name.push_back(NameC); @@ -1343,7 +1213,7 @@ void Intrinsic::emitShadowedArgs() { for (unsigned I = 0; I < getNumParams(); ++I) { // Do not create a temporary for an immediate argument. // That would defeat the whole point of using a macro! - if (hasImmediate() && Proto[I+1] == 'i') + if (getParamType(I).isImmediate()) continue; // Do not create a temporary for pointer arguments. The input // pointer may have an alignment hint. @@ -1366,16 +1236,10 @@ void Intrinsic::emitShadowedArgs() { } } -// We don't check 'a' in this function, because for builtin function the -// argument matching to 'a' uses a vector type splatted from a scalar type. bool Intrinsic::protoHasScalar() const { - return (Proto.find('s') != std::string::npos || - Proto.find('z') != std::string::npos || - Proto.find('r') != std::string::npos || - Proto.find('b') != std::string::npos || - Proto.find('$') != std::string::npos || - Proto.find('y') != std::string::npos || - Proto.find('o') != std::string::npos); + return std::any_of(Types.begin(), Types.end(), [](const Type &T) { + return T.isScalar() && !T.isImmediate(); + }); } void Intrinsic::emitBodyAsBuiltinCall() { @@ -1386,12 +1250,6 @@ void Intrinsic::emitBodyAsBuiltinCall() { bool SRet = getReturnType().getNumVectors() >= 2; StringRef N = Name; - if (hasSplat()) { - // Call the non-splat builtin: chop off the "_n" suffix from the name. - assert(N.endswith("_n")); - N = N.drop_back(2); - } - ClassKind LocalCK = CK; if (!protoHasScalar()) LocalCK = ClassB; @@ -1425,21 +1283,8 @@ void Intrinsic::emitBodyAsBuiltinCall() { continue; } - std::string Arg; + std::string Arg = V.getName(); Type CastToType = T; - if (hasSplat() && I == getSplatIdx()) { - Arg = "(" + BaseType.str() + ") {"; - for (unsigned J = 0; J < BaseType.getNumElements(); ++J) { - if (J != 0) - Arg += ", "; - Arg += V.getName(); - } - Arg += "}"; - - CastToType = BaseType; - } else { - Arg = V.getName(); - } // Check if an explicit cast is needed. if (CastToType.isVector() && @@ -1447,7 +1292,8 @@ void Intrinsic::emitBodyAsBuiltinCall() { CastToType.makeInteger(8, true); Arg = "(" + CastToType.str() + ")" + Arg; } else if (CastToType.isVector() && LocalCK == ClassI) { - CastToType.makeSigned(); + if (CastToType.isInteger()) + CastToType.makeSigned(); Arg = "(" + CastToType.str() + ")" + Arg; } @@ -1456,13 +1302,7 @@ void Intrinsic::emitBodyAsBuiltinCall() { // Extra constant integer to hold type class enum for this function, e.g. s8 if (getClassKind(true) == ClassB) { - Type ThisTy = getReturnType(); - if (Proto[0] == 'v' || isFloatingPointProtoModifier(Proto[0])) - ThisTy = getParamType(0); - if (ThisTy.isPointer()) - ThisTy = getParamType(1); - - S += utostr(ThisTy.getNeonEnum()); + S += utostr(getPolymorphicKeyType().getNeonEnum()); } else { // Remove extraneous ", ". S.pop_back(); @@ -2067,9 +1907,9 @@ void NeonEmitter::createIntrinsic(Record *R, std::vector<std::pair<TypeSpec, TypeSpec>> NewTypeSpecs; for (auto TS : TypeSpecs) { if (CartesianProductOfTypes) { - Type DefaultT(TS, 'd'); + Type DefaultT(TS, "."); for (auto SrcTS : TypeSpecs) { - Type DefaultSrcT(SrcTS, 'd'); + Type DefaultSrcT(SrcTS, "."); if (TS == SrcTS || DefaultSrcT.getSizeInBits() != DefaultT.getSizeInBits()) continue; @@ -2107,10 +1947,6 @@ void NeonEmitter::genBuiltinsDef(raw_ostream &OS, for (auto *Def : Defs) { if (Def->hasBody()) continue; - // Functions with 'a' (the splat code) in the type prototype should not get - // their own builtin as they use the non-splat variant. - if (Def->hasSplat()) - continue; std::string S = "BUILTIN(__builtin_neon_" + Def->getMangledName() + ", \""; @@ -2147,41 +1983,25 @@ void NeonEmitter::genOverloadTypeCheckCode(raw_ostream &OS, // __builtin_neon_* so we don't need to generate a definition for it. if (Def->hasBody()) continue; - // Functions with 'a' (the splat code) in the type prototype should not get - // their own builtin as they use the non-splat variant. - if (Def->hasSplat()) - continue; // Functions which have a scalar argument cannot be overloaded, no need to // check them if we are emitting the type checking code. if (Def->protoHasScalar()) continue; uint64_t Mask = 0ULL; - Type Ty = Def->getReturnType(); - if (Def->getProto()[0] == 'v' || - isFloatingPointProtoModifier(Def->getProto()[0])) - Ty = Def->getParamType(0); - if (Ty.isPointer()) - Ty = Def->getParamType(1); - - Mask |= 1ULL << Ty.getNeonEnum(); + Mask |= 1ULL << Def->getPolymorphicKeyType().getNeonEnum(); // Check if the function has a pointer or const pointer argument. - std::string Proto = Def->getProto(); int PtrArgNum = -1; bool HasConstPtr = false; for (unsigned I = 0; I < Def->getNumParams(); ++I) { - char ArgType = Proto[I + 1]; - if (ArgType == 'c') { - HasConstPtr = true; + const auto &Type = Def->getParamType(I); + if (Type.isPointer()) { PtrArgNum = I; - break; - } - if (ArgType == 'p') { - PtrArgNum = I; - break; + HasConstPtr = Type.isConstPointer(); } } + // For sret builtins, adjust the pointer argument index. if (PtrArgNum >= 0 && Def->getReturnType().getNumVectors() > 1) PtrArgNum += 1; @@ -2231,10 +2051,6 @@ void NeonEmitter::genIntrinsicRangeCheckCode(raw_ostream &OS, for (auto *Def : Defs) { if (Def->hasBody()) continue; - // Functions with 'a' (the splat code) in the type prototype should not get - // their own builtin as they use the non-splat variant. - if (Def->hasSplat()) - continue; // Functions which do not have an immediate do not need to have range // checking code emitted. if (!Def->hasImmediate()) @@ -2409,8 +2225,8 @@ void NeonEmitter::run(raw_ostream &OS) { bool InIfdef = false; for (auto &TS : TDTypeVec) { bool IsA64 = false; - Type T(TS, 'd'); - if (T.isDouble() || (T.isPoly() && T.isLong())) + Type T(TS, "."); + if (T.isDouble() || (T.isPoly() && T.getElementSizeInBits() == 64)) IsA64 = true; if (InIfdef && !IsA64) { @@ -2442,8 +2258,8 @@ void NeonEmitter::run(raw_ostream &OS) { for (unsigned NumMembers = 2; NumMembers <= 4; ++NumMembers) { for (auto &TS : TDTypeVec) { bool IsA64 = false; - Type T(TS, 'd'); - if (T.isDouble() || (T.isPoly() && T.isLong())) + Type T(TS, "."); + if (T.isDouble() || (T.isPoly() && T.getElementSizeInBits() == 64)) IsA64 = true; if (InIfdef && !IsA64) { @@ -2455,8 +2271,8 @@ void NeonEmitter::run(raw_ostream &OS) { InIfdef = true; } - char M = '2' + (NumMembers - 2); - Type VT(TS, M); + const char Mods[] = { static_cast<char>('2' + (NumMembers - 2)), 0}; + Type VT(TS, Mods); OS << "typedef struct " << VT.str() << " {\n"; OS << " " << T.str() << " val"; OS << "[" << NumMembers << "]"; |
