diff options
Diffstat (limited to 'utils/TableGen/NeonEmitter.cpp')
-rw-r--r-- | utils/TableGen/NeonEmitter.cpp | 91 |
1 files changed, 57 insertions, 34 deletions
diff --git a/utils/TableGen/NeonEmitter.cpp b/utils/TableGen/NeonEmitter.cpp index 66845ccacb32..e6f2e53aa706 100644 --- a/utils/TableGen/NeonEmitter.cpp +++ b/utils/TableGen/NeonEmitter.cpp @@ -28,6 +28,7 @@ #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/Support/ErrorHandling.h" #include <string> using namespace llvm; @@ -56,7 +57,6 @@ static void ParseTypes(Record *r, std::string &s, default: throw TGError(r->getLoc(), "Unexpected letter: " + std::string(data + len, 1)); - break; } TV.push_back(StringRef(data, len + 1)); data += len + 1; @@ -78,7 +78,6 @@ static char Widen(const char t) { return 'f'; default: throw "unhandled type in widen!"; } - return '\0'; } /// Narrow - Convert a type code into the next smaller type. short -> char, @@ -95,7 +94,6 @@ static char Narrow(const char t) { return 'h'; default: throw "unhandled type in narrow!"; } - return '\0'; } /// For a particular StringRef, return the base type code, and whether it has @@ -266,7 +264,6 @@ static std::string TypeString(const char mod, StringRef typestr) { break; default: throw "unhandled type!"; - break; } if (mod == '2') @@ -449,7 +446,6 @@ static std::string MangleName(const std::string &name, StringRef typestr, break; default: throw "unhandled type!"; - break; } if (ck == ClassB) s += "_v"; @@ -526,12 +522,6 @@ static std::string GenMacroLocals(const std::string &proto, StringRef typestr) { for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) { // Do not create a temporary for an immediate argument. // That would defeat the whole point of using a macro! - // FIXME: For other (non-immediate) arguments that are used directly, a - // local temporary (or some other method) is still needed to get the - // correct type checking, even if that temporary is not used for anything. - // This is omitted for now because it turns out the the use of - // "__extension__" in the macro disables any warnings from the pointer - // assignment. if (MacroArgUsedDirectly(proto, i)) continue; generatedLocal = true; @@ -594,7 +584,6 @@ static unsigned GetNumElements(StringRef typestr, bool &quad) { case 'f': nElts = 2; break; default: throw "unhandled type!"; - break; } if (quad) nElts <<= 1; return nElts; @@ -826,14 +815,12 @@ static std::string GenOpString(OpKind op, const std::string &proto, } default: throw "unknown OpKind!"; - break; } return s; } static unsigned GetNeonEnum(const std::string &proto, StringRef typestr) { unsigned mod = proto[0]; - unsigned ret = 0; if (mod == 'v' || mod == 'f') mod = proto[1]; @@ -851,35 +838,31 @@ static unsigned GetNeonEnum(const std::string &proto, StringRef typestr) { // Based on the modifying character, change the type and width if necessary. type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr); - if (usgn) - ret |= 0x08; - if (quad && proto[1] != 'g') - ret |= 0x10; - + NeonTypeFlags::EltType ET; switch (type) { case 'c': - ret |= poly ? 5 : 0; + ET = poly ? NeonTypeFlags::Poly8 : NeonTypeFlags::Int8; break; case 's': - ret |= poly ? 6 : 1; + ET = poly ? NeonTypeFlags::Poly16 : NeonTypeFlags::Int16; break; case 'i': - ret |= 2; + ET = NeonTypeFlags::Int32; break; case 'l': - ret |= 3; + ET = NeonTypeFlags::Int64; break; case 'h': - ret |= 7; + ET = NeonTypeFlags::Float16; break; case 'f': - ret |= 4; + ET = NeonTypeFlags::Float32; break; default: throw "unhandled type!"; - break; } - return ret; + NeonTypeFlags Flags(ET, usgn, quad && proto[1] != 'g'); + return Flags.getFlags(); } // Generate the definition for this intrinsic, e.g. __builtin_neon_cls(a) @@ -1249,10 +1232,7 @@ static unsigned RangeFromType(const char mod, StringRef typestr) { return (1 << (int)quad) - 1; default: throw "unhandled type!"; - break; } - assert(0 && "unreachable"); - return 0; } /// runHeader - Emit a file with sections defining: @@ -1346,14 +1326,57 @@ void NeonEmitter::runHeader(raw_ostream &OS) { mask |= 1 << GetNeonEnum(Proto, TypeVec[ti]); } } - if (mask) + + // Check if the builtin function has a pointer or const pointer argument. + int PtrArgNum = -1; + bool HasConstPtr = false; + for (unsigned arg = 1, arge = Proto.size(); arg != arge; ++arg) { + char ArgType = Proto[arg]; + if (ArgType == 'c') { + HasConstPtr = true; + PtrArgNum = arg - 1; + break; + } + if (ArgType == 'p') { + PtrArgNum = arg - 1; + break; + } + } + // For sret builtins, adjust the pointer argument index. + if (PtrArgNum >= 0 && (Proto[0] >= '2' && Proto[0] <= '4')) + PtrArgNum += 1; + + // Omit type checking for the pointer arguments of vld1_lane, vld1_dup, + // and vst1_lane intrinsics. Using a pointer to the vector element + // type with one of those operations causes codegen to select an aligned + // load/store instruction. If you want an unaligned operation, + // the pointer argument needs to have less alignment than element type, + // so just accept any pointer type. + if (name == "vld1_lane" || name == "vld1_dup" || name == "vst1_lane") { + PtrArgNum = -1; + HasConstPtr = false; + } + + if (mask) { OS << "case ARM::BI__builtin_neon_" << MangleName(name, TypeVec[si], ClassB) - << ": mask = " << "0x" << utohexstr(mask) << "; break;\n"; - if (qmask) + << ": mask = " << "0x" << utohexstr(mask); + if (PtrArgNum >= 0) + OS << "; PtrArgNum = " << PtrArgNum; + if (HasConstPtr) + OS << "; HasConstPtr = true"; + OS << "; break;\n"; + } + if (qmask) { OS << "case ARM::BI__builtin_neon_" << MangleName(name, TypeVec[qi], ClassB) - << ": mask = " << "0x" << utohexstr(qmask) << "; break;\n"; + << ": mask = " << "0x" << utohexstr(qmask); + if (PtrArgNum >= 0) + OS << "; PtrArgNum = " << PtrArgNum; + if (HasConstPtr) + OS << "; HasConstPtr = true"; + OS << "; break;\n"; + } } OS << "#endif\n\n"; |