arm_neon.h emitter now mostly complete for the purposes of initial testing.
authorNate Begeman <natebegeman@mac.com>
Wed, 2 Jun 2010 21:53:00 +0000 (21:53 +0000)
committerNate Begeman <natebegeman@mac.com>
Wed, 2 Jun 2010 21:53:00 +0000 (21:53 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@105349 91177308-0d34-0410-b5e6-96231b3b80d8

utils/TableGen/NeonEmitter.cpp

index 7709637445b777f8e71f80ce7d0a31bab304599d..d0b3fc1f3b4926330ea59616dea574fdb816b87d 100644 (file)
@@ -300,12 +300,47 @@ static OpKind ParseOp(Record *R) {
   return OpNone;
 }
 
-static std::string GenOpstring(OpKind op) {
+// 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,
+                               bool structTypes = true) {
   return "";
 }
 
-static std::string GenBuiltin(std::string &name) {
-  return "";
+// Generate the definition for this intrinsic, e.g. __builtin_neon_cls(a)
+// If structTypes is true, the NEON types are structs of vector types rather
+// than vector types, and the call becomes __builtin_neon_cls(a.val)
+static std::string GenBuiltin(const std::string &name, const std::string &proto,
+                              StringRef typestr, bool structTypes = true) {
+  char arg = 'a';
+  std::string s("return ");
+  
+  // FIXME: if return type is 2/3/4, emit unioning code.
+  
+  if (structTypes) {
+    s += "(";
+    s += TypeString(proto[0], typestr);
+    s += "){";
+  }
+  
+  s += "__builtin_neon_";
+  s += name;
+  s += "(";
+  
+  for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
+    s.push_back(arg);
+    if (structTypes)
+      s += ".val";
+    if ((i + 1) < e)
+      s += ", ";
+  }
+  
+  s += ")";
+  if (structTypes)
+    s += "}";
+  s += ";";
+  return s;
 }
 
 void NeonEmitter::run(raw_ostream &OS) {
@@ -321,9 +356,45 @@ void NeonEmitter::run(raw_ostream &OS) {
   OS << "#endif\n\n";
 
   OS << "#include <stdint.h>\n\n";
+
+  // Emit NEON-specific scalar typedefs.
+  // FIXME: probably need to do something better for polynomial types.
+  OS << "typedef float float32_t;\n";
+  OS << "typedef uint8_t poly8_t;\n";
+  OS << "typedef uint16_t poly16_t;\n";
   
-  // EmitTypedefs(OS);
+  // Emit Neon vector typedefs.
+  std::string TypedefTypes("cQcsQsiQilQlUcQUcUsQUsUiQUiUlQUlhQhfQfPcQPcPsQPs");
+  SmallVector<StringRef, 24> TDTypeVec;
+  ParseTypes(0, TypedefTypes, TDTypeVec);
+
+  // Emit vector typedefs.
+  for (unsigned i = 0, e = TDTypeVec.size(); i != e; ++i) {
+    bool dummy, quad = false;
+    (void) ClassifyType(TDTypeVec[i], quad, dummy, dummy);
+    OS << "typedef __attribute__(( __vector_size__(";
+    OS << (quad ? "16) )) " : "8) ))  ");
+    OS << TypeString('s', TDTypeVec[i]);
+    OS << " __neon_";
+    OS << TypeString('d', TDTypeVec[i]) << "\n";
+  }
+  OS << "\n";
+
+  // Emit struct typedefs.
+  for (unsigned vi = 1; vi != 5; ++vi) {
+    for (unsigned i = 0, e = TDTypeVec.size(); i != e; ++i) {
+      std::string ts = TypeString('d', TDTypeVec[i]);
+      std::string vs = (vi > 1) ? TypeString('0' + vi, TDTypeVec[i]) : ts;
+      OS << "typedef struct __" << vs << " {\n";
+      OS << "  __neon_" << ts << " val";
+      if (vi > 1)
+        OS << "[" << utostr(vi) << "]";
+      OS << ";\n} " << vs << ";\n\n";
+    }
+  }
   
+  OS << "#define __ai static __attribute__((__always_inline__))\n\n";
+
   std::vector<Record*> RV = Records.getAllDerivedDefinitions("Inst");
   
   // Unique the return+pattern types, and assign them.
@@ -341,8 +412,8 @@ void NeonEmitter::run(raw_ostream &OS) {
     for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
       assert(!Proto.empty() && "");
       
-      // Return type
-      OS << TypeString(Proto[0], TypeVec[ti]);
+      // static always inline + return type
+      OS << "__ai " << TypeString(Proto[0], TypeVec[ti]);
       
       // Function name with type suffix
       OS << " " << MangleName(name, TypeVec[ti]);
@@ -354,11 +425,11 @@ void NeonEmitter::run(raw_ostream &OS) {
       OS << " { ";
       
       if (k != OpNone)
-        OS << GenOpstring(k);
+        OS << GenOpString(k, Proto);
       else
-        OS << GenBuiltin(name);
+        OS << GenBuiltin(name, Proto, TypeVec[ti]);
 
-      OS << "}\n";
+      OS << " }\n";
     }
     OS << "\n";
   }
@@ -368,5 +439,5 @@ void NeonEmitter::run(raw_ostream &OS) {
   // Emit a #define for each unique "type" of intrinsic declaring all variants.
   // Emit a #define for each intrinsic mapping it to a particular type.
   
-  OS << "\n#endif /* __ARM_NEON_H */\n";
+  OS << "#endif /* __ARM_NEON_H */\n";
 }