aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBob Wilson <bob.wilson@apple.com>2010-12-07 01:12:23 +0000
committerBob Wilson <bob.wilson@apple.com>2010-12-07 01:12:23 +0000
commit3890e397c3fa6cc11f50ea5e32ca81afa1e653a5 (patch)
tree94159c35be4d3bb11f794338b66837029375fd89
parentd8b847066ea9fb287baaf6fcdb20934b7fb207fa (diff)
Add an OpReinterpret operation to TableGen's NeonEmitter.
An OpReinterpret entry is handled by translating it to OpCast intrinsics for all combinations of source and destination types with the same total size. This will be used to generate all the vreinterpret intrinsics. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@121087 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--utils/TableGen/NeonEmitter.cpp109
-rw-r--r--utils/TableGen/NeonEmitter.h4
2 files changed, 73 insertions, 40 deletions
diff --git a/utils/TableGen/NeonEmitter.cpp b/utils/TableGen/NeonEmitter.cpp
index 5f73d00898..3752db0f4d 100644
--- a/utils/TableGen/NeonEmitter.cpp
+++ b/utils/TableGen/NeonEmitter.cpp
@@ -897,6 +897,55 @@ static std::string GenBuiltinDef(const std::string &name,
return s;
}
+static std::string GenIntrinsic(const std::string &name,
+ const std::string &proto,
+ StringRef outTypeStr, StringRef inTypeStr,
+ OpKind kind, ClassKind classKind) {
+ assert(!proto.empty() && "");
+ bool define = proto.find('i') != std::string::npos;
+ std::string s;
+
+ // static always inline + return type
+ if (define)
+ s += "#define ";
+ else
+ s += "__ai " + TypeString(proto[0], outTypeStr) + " ";
+
+ // Function name with type suffix
+ std::string mangledName = MangleName(name, outTypeStr, ClassS);
+ if (outTypeStr != inTypeStr) {
+ // If the input type is different (e.g., for vreinterpret), append a suffix
+ // for the input type. String off a "Q" (quad) prefix so that MangleName
+ // does not insert another "q" in the name.
+ unsigned typeStrOff = (inTypeStr[0] == 'Q' ? 1 : 0);
+ StringRef inTypeNoQuad = inTypeStr.substr(typeStrOff);
+ mangledName = MangleName(mangledName, inTypeNoQuad, ClassS);
+ }
+ s += mangledName;
+
+ // Function arguments
+ s += GenArgs(proto, inTypeStr);
+
+ // Definition.
+ if (define) {
+ s += " __extension__ ({ \\\n ";
+ s += GenMacroLocals(proto, inTypeStr);
+ } else {
+ s += " { \\\n ";
+ }
+
+ if (kind != OpNone)
+ s += GenOpString(kind, proto, outTypeStr);
+ else
+ s += GenBuiltin(name, proto, outTypeStr, classKind);
+ if (define)
+ s += " })";
+ else
+ s += " }";
+ s += "\n";
+ return s;
+}
+
/// run - Read the records in arm_neon.td and output arm_neon.h. arm_neon.h
/// is comprised of type definitions and function declarations.
void NeonEmitter::run(raw_ostream &OS) {
@@ -975,50 +1024,32 @@ void NeonEmitter::run(raw_ostream &OS) {
SmallVector<StringRef, 16> TypeVec;
ParseTypes(R, Types, TypeVec);
- OpKind k = OpMap[R->getValueAsDef("Operand")->getName()];
+ OpKind kind = OpMap[R->getValueAsDef("Operand")->getName()];
- bool define = Proto.find('i') != std::string::npos;
+ ClassKind classKind = ClassNone;
+ if (R->getSuperClasses().size() >= 2)
+ classKind = ClassMap[R->getSuperClasses()[1]];
+ if (classKind == ClassNone && kind == OpNone)
+ throw TGError(R->getLoc(), "Builtin has no class kind");
for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
- assert(!Proto.empty() && "");
-
- // static always inline + return type
- if (define)
- OS << "#define";
- else
- OS << "__ai " << TypeString(Proto[0], TypeVec[ti]);
-
- // Function name with type suffix
- OS << " " << MangleName(name, TypeVec[ti], ClassS);
-
- // Function arguments
- OS << GenArgs(Proto, TypeVec[ti]);
-
- // Definition.
- if (define) {
- OS << " __extension__ ({ \\\n ";
- OS << GenMacroLocals(Proto, TypeVec[ti]);
- } else {
- OS << " { \\\n ";
- }
-
- if (k != OpNone) {
- OS << GenOpString(k, Proto, TypeVec[ti]);
+ if (kind == OpReinterpret) {
+ bool outQuad = false;
+ bool dummy = false;
+ (void)ClassifyType(TypeVec[ti], outQuad, dummy, dummy);
+ for (unsigned srcti = 0, srcte = TypeVec.size();
+ srcti != srcte; ++srcti) {
+ bool inQuad = false;
+ (void)ClassifyType(TypeVec[srcti], inQuad, dummy, dummy);
+ if (srcti == ti || inQuad != outQuad)
+ continue;
+ OS << GenIntrinsic(name, Proto, TypeVec[ti], TypeVec[srcti],
+ OpCast, ClassS);
+ }
} else {
- if (R->getSuperClasses().size() < 2)
- throw TGError(R->getLoc(), "Builtin has no class kind");
-
- ClassKind ck = ClassMap[R->getSuperClasses()[1]];
-
- if (ck == ClassNone)
- throw TGError(R->getLoc(), "Builtin has no class kind");
- OS << GenBuiltin(name, Proto, TypeVec[ti], ck);
+ OS << GenIntrinsic(name, Proto, TypeVec[ti], TypeVec[ti],
+ kind, classKind);
}
- if (define)
- OS << " })";
- else
- OS << " }";
- OS << "\n";
}
OS << "\n";
}
diff --git a/utils/TableGen/NeonEmitter.h b/utils/TableGen/NeonEmitter.h
index 67ad4ef1da..3d122ffbba 100644
--- a/utils/TableGen/NeonEmitter.h
+++ b/utils/TableGen/NeonEmitter.h
@@ -54,7 +54,8 @@ enum OpKind {
OpSelect,
OpRev16,
OpRev32,
- OpRev64
+ OpRev64,
+ OpReinterpret
};
enum ClassKind {
@@ -107,6 +108,7 @@ namespace llvm {
OpMap["OP_REV16"] = OpRev16;
OpMap["OP_REV32"] = OpRev32;
OpMap["OP_REV64"] = OpRev64;
+ OpMap["OP_REINT"] = OpReinterpret;
Record *SI = R.getClass("SInst");
Record *II = R.getClass("IInst");