summaryrefslogtreecommitdiff
path: root/utils
diff options
context:
space:
mode:
authorNate Begeman <natebegeman@mac.com>2010-06-10 00:16:56 +0000
committerNate Begeman <natebegeman@mac.com>2010-06-10 00:16:56 +0000
commit4b425a8caa86f1932247413b42ea6f94e9222b86 (patch)
treec9ccf2c94f0f8452d467c6a9af9342cf91d7e9f5 /utils
parentdb03adb34615331c6ef55ebbd80d8bc750deefe0 (diff)
downloadllvm-4b425a8caa86f1932247413b42ea6f94e9222b86.tar.gz
llvm-4b425a8caa86f1932247413b42ea6f94e9222b86.tar.bz2
llvm-4b425a8caa86f1932247413b42ea6f94e9222b86.tar.xz
NEON support for _lane ops, and multiplies by scalar.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@105769 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'utils')
-rw-r--r--utils/TableGen/NeonEmitter.cpp70
-rw-r--r--utils/TableGen/NeonEmitter.h54
2 files changed, 79 insertions, 45 deletions
diff --git a/utils/TableGen/NeonEmitter.cpp b/utils/TableGen/NeonEmitter.cpp
index 4443376995..1c5794c8c1 100644
--- a/utils/TableGen/NeonEmitter.cpp
+++ b/utils/TableGen/NeonEmitter.cpp
@@ -137,6 +137,7 @@ static char ModType(const char mod, char type, bool &quad, bool &poly,
usgn = true;
break;
case 's':
+ case 'a':
scal = true;
break;
case 'k':
@@ -442,14 +443,7 @@ static std::string GenArgs(const std::string &proto, StringRef typestr) {
return s;
}
-// Generate the definition for this intrinsic, e.g. "a + b" for OpAdd.
-// If structTypes is true, the NEON types are structs of vector types rather
-// than vector types, and the call becomes "a.val + b.val"
-static std::string GenOpString(OpKind op, const std::string &proto,
- StringRef typestr, bool structTypes = true) {
- std::string ts = TypeString(proto[0], typestr);
- std::string s = ts + " r; r";
-
+static std::string Duplicate(StringRef typestr, const std::string &a) {
bool dummy, quad = false;
char type = ClassifyType(typestr, quad, dummy, dummy);
unsigned nElts = 0;
@@ -462,6 +456,27 @@ static std::string GenOpString(OpKind op, const std::string &proto,
case 'f': nElts = 2; break;
}
nElts <<= quad;
+
+ std::string s;
+
+ s = "(__neon_" + TypeString('d', typestr) + "){ ";
+ for (unsigned i = 0; i != nElts; ++i) {
+ s += a;
+ if ((i + 1) < nElts)
+ s += ", ";
+ }
+ s += " }";
+
+ return s;
+}
+
+// Generate the definition for this intrinsic, e.g. "a + b" for OpAdd.
+// If structTypes is true, the NEON types are structs of vector types rather
+// than vector types, and the call becomes "a.val + b.val"
+static std::string GenOpString(OpKind op, const std::string &proto,
+ StringRef typestr, bool structTypes = true) {
+ std::string ts = TypeString(proto[0], typestr);
+ std::string s = ts + " r; r";
if (structTypes)
s += ".val";
@@ -481,12 +496,18 @@ static std::string GenOpString(OpKind op, const std::string &proto,
case OpSub:
s += a + " - " + b;
break;
+ case OpMulN:
+ b = Duplicate(typestr, "b");
case OpMul:
s += a + " * " + b;
break;
+ case OpMlaN:
+ c = Duplicate(typestr, "c");
case OpMla:
s += a + " + ( " + b + " * " + c + " )";
break;
+ case OpMlsN:
+ c = Duplicate(typestr, "c");
case OpMls:
s += a + " - ( " + b + " * " + c + " )";
break;
@@ -540,13 +561,7 @@ static std::string GenOpString(OpKind op, const std::string &proto,
s += "(__neon_int64x1_t)(((__neon_int64x2_t)" + a + ")[0])";
break;
case OpDup:
- s += "(__neon_" + ts + "){ ";
- for (unsigned i = 0; i != nElts; ++i) {
- s += a;
- if ((i + 1) < nElts)
- s += ", ";
- }
- s += " }";
+ s += Duplicate(typestr, a);
break;
default:
throw "unknown OpKind!";
@@ -647,10 +662,17 @@ static std::string GenBuiltin(const std::string &name, const std::string &proto,
s += " = ";
}
- }
+ }
+
+ bool splat = proto.find('a') != std::string::npos;
s += "__builtin_neon_";
- s += MangleName(name, typestr, ck);
+ if (splat) {
+ std::string vname(name, 0, name.size()-2);
+ s += MangleName(vname, typestr, ck);
+ } else {
+ s += MangleName(name, typestr, ck);
+ }
s += "(";
for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
@@ -672,12 +694,18 @@ static std::string GenBuiltin(const std::string &name, const std::string &proto,
// Parenthesize the args from the macro.
if (define)
s.push_back('(');
- s.push_back(arg);
+
+ if (splat && (i + 1) == e)
+ s += Duplicate(typestr, std::string(&arg, 1));
+ else
+ s.push_back(arg);
+
+ // Parenthesize the args from the macro.
if (define)
s.push_back(')');
if (structTypes && proto[i] != 's' && proto[i] != 'i' && proto[i] != 'l' &&
- proto[i] != 'p' && proto[i] != 'c') {
+ proto[i] != 'p' && proto[i] != 'c' && proto[i] != 'a') {
s += ".val";
}
if ((i + 1) < e)
@@ -748,7 +776,6 @@ void NeonEmitter::run(raw_ostream &OS) {
// Emit NEON-specific scalar typedefs.
// FIXME: probably need to do something better for polynomial types.
- // FIXME: is this the correct thing to do for float16?
OS << "typedef float float32_t;\n";
OS << "typedef uint8_t poly8_t;\n";
OS << "typedef uint16_t poly16_t;\n";
@@ -869,6 +896,9 @@ void NeonEmitter::runHeader(raw_ostream &OS) {
std::string Proto = R->getValueAsString("Prototype");
std::string Types = R->getValueAsString("Types");
+ if (Proto.find('a') != std::string::npos)
+ continue;
+
SmallVector<StringRef, 16> TypeVec;
ParseTypes(R, Types, TypeVec);
diff --git a/utils/TableGen/NeonEmitter.h b/utils/TableGen/NeonEmitter.h
index 941c23509c..7b9c50585e 100644
--- a/utils/TableGen/NeonEmitter.h
+++ b/utils/TableGen/NeonEmitter.h
@@ -28,6 +28,9 @@ enum OpKind {
OpMul,
OpMla,
OpMls,
+ OpMulN,
+ OpMlaN,
+ OpMlsN,
OpEq,
OpGe,
OpLe,
@@ -64,38 +67,39 @@ namespace llvm {
public:
NeonEmitter(RecordKeeper &R) : Records(R) {
- OpMap["OP_NONE"] = OpNone;
- OpMap["OP_ADD"] = OpAdd;
- OpMap["OP_SUB"] = OpSub;
- OpMap["OP_MUL"] = OpMul;
- OpMap["OP_MLA"] = OpMla;
- OpMap["OP_MLS"] = OpMls;
- OpMap["OP_EQ"] = OpEq;
- OpMap["OP_GE"] = OpGe;
- OpMap["OP_LE"] = OpLe;
- OpMap["OP_GT"] = OpGt;
- OpMap["OP_LT"] = OpLt;
- OpMap["OP_NEG"] = OpNeg;
- OpMap["OP_NOT"] = OpNot;
- OpMap["OP_AND"] = OpAnd;
- OpMap["OP_OR"] = OpOr;
- OpMap["OP_XOR"] = OpXor;
- OpMap["OP_ANDN"] = OpAndNot;
- OpMap["OP_ORN"] = OpOrNot;
- OpMap["OP_CAST"] = OpCast;
- OpMap["OP_CONC"] = OpConcat;
- OpMap["OP_HI"] = OpHi;
- OpMap["OP_LO"] = OpLo;
- OpMap["OP_DUP"] = OpDup;
+ OpMap["OP_NONE"] = OpNone;
+ OpMap["OP_ADD"] = OpAdd;
+ OpMap["OP_SUB"] = OpSub;
+ OpMap["OP_MUL"] = OpMul;
+ OpMap["OP_MLA"] = OpMla;
+ OpMap["OP_MLS"] = OpMls;
+ OpMap["OP_MUL_N"] = OpMulN;
+ OpMap["OP_MLA_N"] = OpMlaN;
+ OpMap["OP_MLS_N"] = OpMlsN;
+ OpMap["OP_EQ"] = OpEq;
+ OpMap["OP_GE"] = OpGe;
+ OpMap["OP_LE"] = OpLe;
+ OpMap["OP_GT"] = OpGt;
+ OpMap["OP_LT"] = OpLt;
+ OpMap["OP_NEG"] = OpNeg;
+ OpMap["OP_NOT"] = OpNot;
+ OpMap["OP_AND"] = OpAnd;
+ OpMap["OP_OR"] = OpOr;
+ OpMap["OP_XOR"] = OpXor;
+ OpMap["OP_ANDN"] = OpAndNot;
+ OpMap["OP_ORN"] = OpOrNot;
+ OpMap["OP_CAST"] = OpCast;
+ OpMap["OP_CONC"] = OpConcat;
+ OpMap["OP_HI"] = OpHi;
+ OpMap["OP_LO"] = OpLo;
+ OpMap["OP_DUP"] = OpDup;
Record *SI = R.getClass("SInst");
Record *II = R.getClass("IInst");
Record *WI = R.getClass("WInst");
- Record *BI = R.getClass("BInst");
ClassMap[SI] = ClassS;
ClassMap[II] = ClassI;
ClassMap[WI] = ClassW;
- ClassMap[BI] = ClassB;
}
// run - Emit arm_neon.h.inc