summaryrefslogtreecommitdiff
path: root/utils
diff options
context:
space:
mode:
authorNate Begeman <natebegeman@mac.com>2010-06-20 21:09:52 +0000
committerNate Begeman <natebegeman@mac.com>2010-06-20 21:09:52 +0000
commitc4a1b652b2e717ab69637ad4e91d59f3b88fd0a2 (patch)
treefe6ee3c189791b94753835766d142dd98e282ce6 /utils
parent2a3ee5e8e95ac4f1572776b257f83fdee9fdb29e (diff)
downloadllvm-c4a1b652b2e717ab69637ad4e91d59f3b88fd0a2.tar.gz
llvm-c4a1b652b2e717ab69637ad4e91d59f3b88fd0a2.tar.bz2
llvm-c4a1b652b2e717ab69637ad4e91d59f3b88fd0a2.tar.xz
Add support for returning multiple vectors via sret, which is how the ARM target expects the intrinsics to work.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@106406 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'utils')
-rw-r--r--utils/TableGen/NeonEmitter.cpp72
1 files changed, 42 insertions, 30 deletions
diff --git a/utils/TableGen/NeonEmitter.cpp b/utils/TableGen/NeonEmitter.cpp
index 689db653cb..29930402da 100644
--- a/utils/TableGen/NeonEmitter.cpp
+++ b/utils/TableGen/NeonEmitter.cpp
@@ -167,8 +167,6 @@ static char ModType(const char mod, char type, bool &quad, bool &poly,
case 'c':
cnst = true;
case 'p':
- usgn = false;
- poly = false;
pntr = true;
scal = true;
break;
@@ -302,9 +300,11 @@ static std::string BuiltinTypeString(const char mod, 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 (pntr)
+ if (pntr) {
+ usgn = false;
+ poly = false;
type = 'v';
-
+ }
if (type == 'h') {
type = 's';
usgn = true;
@@ -330,14 +330,12 @@ static std::string BuiltinTypeString(const char mod, StringRef typestr,
}
// Since the return value must be one type, return a vector type of the
- // appropriate width which we will bitcast.
+ // appropriate width which we will bitcast. An exception is made for
+ // returning structs of 2, 3, or 4 vectors which are returned in a sret-like
+ // fashion, storing them to a pointer arg.
if (ret) {
- if (mod == '2')
- return quad ? "V32c" : "V16c";
- if (mod == '3')
- return quad ? "V48c" : "V24c";
- if (mod == '4')
- return quad ? "V64c" : "V32c";
+ if (mod == '2' || mod == '3' || mod == '4')
+ return "vv*";
if (mod == 'f' || (ck != ClassB && type == 'f'))
return quad ? "V4f" : "V2f";
if (ck != ClassB && type == 's')
@@ -701,7 +699,13 @@ static std::string GenBuiltin(const std::string &name, const std::string &proto,
char arg = 'a';
std::string s;
- bool unioning = (proto[0] == '2' || proto[0] == '3' || proto[0] == '4');
+ // If this builtin returns a struct 2, 3, or 4 vectors, pass it as an implicit
+ // sret-like argument.
+ bool sret = (proto[0] == '2' || proto[0] == '3' || proto[0] == '4');
+
+ // 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.
bool define = proto.find('i') != std::string::npos;
// If all types are the same size, bitcasting the args will take care
@@ -714,19 +718,14 @@ static std::string GenBuiltin(const std::string &name, const std::string &proto,
std::string ts = TypeString(proto[0], typestr);
if (define) {
- if (proto[0] != 's')
+ if (sret)
+ s += "({ " + ts + " r; ";
+ else if (proto[0] != 's')
s += "(" + ts + "){(__neon_" + ts + ")";
+ } else if (sret) {
+ s += ts + " r; ";
} else {
- if (unioning) {
- s += "union { ";
- s += TypeString(proto[0], typestr, true) + " val; ";
- s += TypeString(proto[0], typestr, false) + " s; ";
- s += "} r;";
- } else {
- s += ts;
- }
-
- s += " r; r";
+ s += ts + " r; r";
if (structTypes && proto[0] != 's' && proto[0] != 'i' && proto[0] != 'l')
s += ".val";
@@ -744,6 +743,11 @@ static std::string GenBuiltin(const std::string &name, const std::string &proto,
s += MangleName(name, typestr, ck);
}
s += "(";
+
+ // Pass the address of the return variable as the first argument to sret-like
+ // builtins.
+ if (sret)
+ s += "&r, ";
for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
std::string args = std::string(&arg, 1);
@@ -788,13 +792,12 @@ static std::string GenBuiltin(const std::string &name, const std::string &proto,
if (proto[0] != 'v') {
if (define) {
- if (proto[0] != 's')
+ if (sret)
+ s += "; r; })";
+ else if (proto[0] != 's')
s += "}";
} else {
- if (unioning)
- s += " return r.s;";
- else
- s += " return r;";
+ s += " return r;";
}
}
return s;
@@ -1119,13 +1122,22 @@ void NeonEmitter::runHeader(raw_ostream &OS) {
} else {
rangestr = "u = " + utostr(RangeFromType(TypeVec[ti]));
}
- // Make sure cases appear only once.
+ // Make sure cases appear only once by uniquing them in a string map.
namestr = MangleName(name, TypeVec[ti], ck);
if (EmittedMap.count(namestr))
continue;
EmittedMap[namestr] = OpNone;
-
+
+ // Calculate the index of the immediate that should be range checked.
unsigned immidx = 0;
+
+ // Builtins that return a struct of multiple vectors have an extra
+ // leading arg for the struct return.
+ if (Proto[0] == '2' || Proto[0] == '3' || Proto[0] == '4')
+ ++immidx;
+
+ // Add one to the index for each argument until we reach the immediate
+ // to be checked. Structs of vectors are passed as multiple arguments.
for (unsigned ii = 1, ie = Proto.size(); ii != ie; ++ii) {
switch (Proto[ii]) {
default: immidx += 1; break;