NEON support for _lane ops, and multiplies by scalar.
authorNate Begeman <natebegeman@mac.com>
Thu, 10 Jun 2010 00:16:56 +0000 (00:16 +0000)
committerNate Begeman <natebegeman@mac.com>
Thu, 10 Jun 2010 00:16:56 +0000 (00:16 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@105769 91177308-0d34-0410-b5e6-96231b3b80d8

utils/TableGen/NeonEmitter.cpp
utils/TableGen/NeonEmitter.h

index 4443376995f0a6edc853b5a6307dad3926f20d5e..1c5794c8c1743c5f26021c80a850be10c7c8e3f4 100644 (file)
@@ -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);
 
index 941c23509cb40affebf5448a6049601435e2e681..7b9c50585e2cd8edff9b240767142926a88d4e40 100644 (file)
@@ -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