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
diff --git a/utils/TableGen/NeonEmitter.cpp b/utils/TableGen/NeonEmitter.cpp
index 4443376..1c5794c 100644
--- a/utils/TableGen/NeonEmitter.cpp
+++ b/utils/TableGen/NeonEmitter.cpp
@@ -137,6 +137,7 @@
       usgn = true;
       break;
     case 's':
+    case 'a':
       scal = true;
       break;
     case 'k':
@@ -442,14 +443,7 @@
   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 @@
     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 @@
   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 @@
     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 @@
       
       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 @@
     // 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 @@
 
   // 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 @@
     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);