Handle instructions which need to be #defines for the purpose of capturing constant arguments

Handle extract hi/lo with common code


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@105666 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Nate Begeman 2010-06-09 01:09:00 +00:00
parent c3c2517fed
commit 6c060dbf84
2 changed files with 62 additions and 24 deletions

View File

@ -411,14 +411,17 @@ static std::string MangleName(const std::string &name, StringRef typestr,
// Generate the string "(argtype a, argtype b, ...)" // Generate the string "(argtype a, argtype b, ...)"
static std::string GenArgs(const std::string &proto, StringRef typestr) { static std::string GenArgs(const std::string &proto, StringRef typestr) {
bool define = proto.find('i') != std::string::npos;
char arg = 'a'; char arg = 'a';
std::string s; std::string s;
s += "("; s += "(";
for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) { for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
if (!define) {
s += TypeString(proto[i], typestr); s += TypeString(proto[i], typestr);
s.push_back(' '); s.push_back(' ');
}
s.push_back(arg); s.push_back(arg);
if ((i + 1) < e) if ((i + 1) < e)
s += ", "; s += ", ";
@ -519,6 +522,12 @@ static std::string GenOpString(OpKind op, const std::string &proto,
s += "__builtin_shufflevector((__neon_int64x1_t)" + a; s += "__builtin_shufflevector((__neon_int64x1_t)" + a;
s += ", (__neon_int64x1_t)" + b + ", 0, 1)"; s += ", (__neon_int64x1_t)" + b + ", 0, 1)";
break; break;
case OpHi:
s += "(__neon_int64x1_t)(((__neon_int64x2_t)" + a + ")[1])";
break;
case OpLo:
s += "(__neon_int64x1_t)(((__neon_int64x2_t)" + a + ")[0])";
break;
case OpDup: case OpDup:
s += "(__neon_" + ts + "){ "; s += "(__neon_" + ts + "){ ";
for (unsigned i = 0; i != nElts; ++i) { for (unsigned i = 0; i != nElts; ++i) {
@ -597,6 +606,7 @@ static std::string GenBuiltin(const std::string &name, const std::string &proto,
std::string s; std::string s;
bool unioning = (proto[0] == '2' || proto[0] == '3' || proto[0] == '4'); bool unioning = (proto[0] == '2' || proto[0] == '3' || proto[0] == '4');
bool define = proto.find('i') != std::string::npos;
// If all types are the same size, bitcasting the args will take care // If all types are the same size, bitcasting the args will take care
// of arg checking. The actual signedness etc. will be taken care of with // of arg checking. The actual signedness etc. will be taken care of with
@ -605,13 +615,19 @@ static std::string GenBuiltin(const std::string &name, const std::string &proto,
ck = ClassB; ck = ClassB;
if (proto[0] != 'v') { if (proto[0] != 'v') {
std::string ts = TypeString(proto[0], typestr);
if (define) {
if (proto[0] != 's')
s += "(" + ts + "){(__neon_" + ts + ")";
} else {
if (unioning) { if (unioning) {
s += "union { "; s += "union { ";
s += TypeString(proto[0], typestr, true) + " val; "; s += TypeString(proto[0], typestr, true) + " val; ";
s += TypeString(proto[0], typestr, false) + " s; "; s += TypeString(proto[0], typestr, false) + " s; ";
s += "} r;"; s += "} r;";
} else { } else {
s += TypeString(proto[0], typestr); s += ts;
} }
s += " r; r"; s += " r; r";
@ -620,6 +636,7 @@ static std::string GenBuiltin(const std::string &name, const std::string &proto,
s += " = "; s += " = ";
} }
}
s += "__builtin_neon_"; s += "__builtin_neon_";
s += MangleName(name, typestr, ck); s += MangleName(name, typestr, ck);
@ -655,14 +672,22 @@ static std::string GenBuiltin(const std::string &name, const std::string &proto,
if (ck == ClassB) if (ck == ClassB)
s += ", " + utostr(GetNeonEnum(proto, typestr)); s += ", " + utostr(GetNeonEnum(proto, typestr));
if (define)
s += ")";
else
s += ");"; s += ");";
if (proto[0] != 'v') { if (proto[0] != 'v') {
if (define) {
if (proto[0] != 's')
s += "}";
} else {
if (unioning) if (unioning)
s += " return r.s;"; s += " return r.s;";
else else
s += " return r;"; s += " return r;";
} }
}
return s; return s;
} }
@ -767,10 +792,15 @@ void NeonEmitter::run(raw_ostream &OS) {
OpKind k = OpMap[R->getValueAsDef("Operand")->getName()]; OpKind k = OpMap[R->getValueAsDef("Operand")->getName()];
bool define = Proto.find('i') != std::string::npos;
for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) { for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
assert(!Proto.empty() && ""); assert(!Proto.empty() && "");
// static always inline + return type // static always inline + return type
if (define)
OS << "#define";
else
OS << "__ai " << TypeString(Proto[0], TypeVec[ti]); OS << "__ai " << TypeString(Proto[0], TypeVec[ti]);
// Function name with type suffix // Function name with type suffix
@ -780,6 +810,9 @@ void NeonEmitter::run(raw_ostream &OS) {
OS << GenArgs(Proto, TypeVec[ti]); OS << GenArgs(Proto, TypeVec[ti]);
// Definition. // Definition.
if (define)
OS << " ";
else
OS << " { "; OS << " { ";
if (k != OpNone) { if (k != OpNone) {
@ -794,8 +827,9 @@ void NeonEmitter::run(raw_ostream &OS) {
throw TGError(R->getLoc(), "Builtin has no class kind"); throw TGError(R->getLoc(), "Builtin has no class kind");
OS << GenBuiltin(name, Proto, TypeVec[ti], ck); OS << GenBuiltin(name, Proto, TypeVec[ti], ck);
} }
if (!define)
OS << " }\n"; OS << " }";
OS << "\n";
} }
OS << "\n"; OS << "\n";
} }

View File

@ -42,7 +42,9 @@ enum OpKind {
OpOrNot, OpOrNot,
OpCast, OpCast,
OpConcat, OpConcat,
OpDup OpDup,
OpHi,
OpLo
}; };
enum ClassKind { enum ClassKind {
@ -82,6 +84,8 @@ namespace llvm {
OpMap["OP_ORN"] = OpOrNot; OpMap["OP_ORN"] = OpOrNot;
OpMap["OP_CAST"] = OpCast; OpMap["OP_CAST"] = OpCast;
OpMap["OP_CONC"] = OpConcat; OpMap["OP_CONC"] = OpConcat;
OpMap["OP_HI"] = OpHi;
OpMap["OP_LO"] = OpLo;
OpMap["OP_DUP"] = OpDup; OpMap["OP_DUP"] = OpDup;
Record *SI = R.getClass("SInst"); Record *SI = R.getClass("SInst");