[llvm-commits] [llvm] r120763 - /llvm/trunk/utils/TableGen/NeonEmitter.cpp

Bob Wilson bob.wilson at apple.com
Thu Dec 2 16:34:09 PST 2010


Author: bwilson
Date: Thu Dec  2 18:34:09 2010
New Revision: 120763

URL: http://llvm.org/viewvc/llvm-project?rev=120763&view=rev
Log:
Support using macros for Neon intrinsics implemented without builtins.
Intrinsics implemented with Clang builtins could already be implemented as
either inline functions or macros, but intrinsics implemented directly
(without builtins) could only be inline functions.

Modified:
    llvm/trunk/utils/TableGen/NeonEmitter.cpp

Modified: llvm/trunk/utils/TableGen/NeonEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/NeonEmitter.cpp?rev=120763&r1=120762&r2=120763&view=diff
==============================================================================
--- llvm/trunk/utils/TableGen/NeonEmitter.cpp (original)
+++ llvm/trunk/utils/TableGen/NeonEmitter.cpp Thu Dec  2 18:34:09 2010
@@ -468,9 +468,14 @@
   s += "(";
   
   for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
-    if (!define) {
-      s += TypeString(proto[i], typestr);
-      s.push_back(' ');
+    if (define) {
+      // Immediate macro arguments are used directly instead of being assigned
+      // to local temporaries; prepend an underscore prefix to make their
+      // names consistent with the local temporaries.
+      if (proto[i] == 'i')
+        s += "__";
+    } else {
+      s += TypeString(proto[i], typestr) + " __";
     }
     s.push_back(arg);
     if ((i + 1) < e)
@@ -481,8 +486,8 @@
   return s;
 }
 
-// Generate the local temporaries used to provide type checking for macro
-// arguments.
+// Macro arguments are not type-checked like inline function arguments, so
+// assign them to local temporaries to get the right type checking.
 static std::string GenMacroLocals(const std::string &proto, StringRef typestr) {
   char arg = 'a';
   std::string s;
@@ -544,100 +549,105 @@
   bool quad;
   unsigned nElts = GetNumElements(typestr, quad);
   
+  // 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;
+
   std::string ts = TypeString(proto[0], typestr);
   std::string s;
   if (op == OpHi || op == OpLo) {
     s = "union { " + ts + " r; double d; } u; u.d = ";
-  } else {
+  } else if (!define) {
     s = "return ";
   }
   
   switch(op) {
   case OpAdd:
-    s += "a + b;";
+    s += "__a + __b;";
     break;
   case OpSub:
-    s += "a - b;";
+    s += "__a - __b;";
     break;
   case OpMulN:
-    s += "a * " + Duplicate(nElts, typestr, "b") + ";";
+    s += "__a * " + Duplicate(nElts, typestr, "__b") + ";";
     break;
   case OpMul:
-    s += "a * b;";
+    s += "__a * __b;";
     break;
   case OpMlaN:
-    s += "a + (b * " + Duplicate(nElts, typestr, "c") + ");";
+    s += "__a + (__b * " + Duplicate(nElts, typestr, "__c") + ");";
     break;
   case OpMla:
-    s += "a + (b * c);";
+    s += "__a + (__b * __c);";
     break;
   case OpMlsN:
-    s += "a - (b * " + Duplicate(nElts, typestr, "c") + ");";
+    s += "__a - (__b * " + Duplicate(nElts, typestr, "__c") + ");";
     break;
   case OpMls:
-    s += "a - (b * c);";
+    s += "__a - (__b * __c);";
     break;
   case OpEq:
-    s += "(" + ts + ")(a == b);";
+    s += "(" + ts + ")(__a == __b);";
     break;
   case OpGe:
-    s += "(" + ts + ")(a >= b);";
+    s += "(" + ts + ")(__a >= __b);";
     break;
   case OpLe:
-    s += "(" + ts + ")(a <= b);";
+    s += "(" + ts + ")(__a <= __b);";
     break;
   case OpGt:
-    s += "(" + ts + ")(a > b);";
+    s += "(" + ts + ")(__a > __b);";
     break;
   case OpLt:
-    s += "(" + ts + ")(a < b);";
+    s += "(" + ts + ")(__a < __b);";
     break;
   case OpNeg:
-    s += " -a;";
+    s += " -__a;";
     break;
   case OpNot:
-    s += " ~a;";
+    s += " ~__a;";
     break;
   case OpAnd:
-    s += "a & b;";
+    s += "__a & __b;";
     break;
   case OpOr:
-    s += "a | b;";
+    s += "__a | __b;";
     break;
   case OpXor:
-    s += "a ^ b;";
+    s += "__a ^ __b;";
     break;
   case OpAndNot:
-    s += "a & ~b;";
+    s += "__a & ~__b;";
     break;
   case OpOrNot:
-    s += "a | ~b;";
+    s += "__a | ~__b;";
     break;
   case OpCast:
-    s += "(" + ts + ")a;";
+    s += "(" + ts + ")__a;";
     break;
   case OpConcat:
-    s += "(" + ts + ")__builtin_shufflevector((int64x1_t)a";
-    s += ", (int64x1_t)b, 0, 1);";
+    s += "(" + ts + ")__builtin_shufflevector((int64x1_t)__a";
+    s += ", (int64x1_t)__b, 0, 1);";
     break;
   case OpHi:
-    s += "(((float64x2_t)a)[1]);";
+    s += "(((float64x2_t)__a)[1]);";
     break;
   case OpLo:
-    s += "(((float64x2_t)a)[0]);";
+    s += "(((float64x2_t)__a)[0]);";
     break;
   case OpDup:
-    s += Duplicate(nElts, typestr, "a") + ";";
+    s += Duplicate(nElts, typestr, "__a") + ";";
     break;
   case OpSelect:
     // ((0 & 1) | (~0 & 2))
     s += "(" + ts + ")";
     ts = TypeString(proto[1], typestr);
-    s += "((a & (" + ts + ")b) | ";
-    s += "(~a & (" + ts + ")c));";
+    s += "((__a & (" + ts + ")__b) | ";
+    s += "(~__a & (" + ts + ")__c));";
     break;
   case OpRev16:
-    s += "__builtin_shufflevector(a, a";
+    s += "__builtin_shufflevector(__a, __a";
     for (unsigned i = 2; i <= nElts; i += 2)
       for (unsigned j = 0; j != 2; ++j)
         s += ", " + utostr(i - j - 1);
@@ -645,7 +655,7 @@
     break;
   case OpRev32: {
     unsigned WordElts = nElts >> (1 + (int)quad);
-    s += "__builtin_shufflevector(a, a";
+    s += "__builtin_shufflevector(__a, __a";
     for (unsigned i = WordElts; i <= nElts; i += WordElts)
       for (unsigned j = 0; j != WordElts; ++j)
         s += ", " + utostr(i - j - 1);
@@ -654,7 +664,7 @@
   }
   case OpRev64: {
     unsigned DblWordElts = nElts >> (int)quad;
-    s += "__builtin_shufflevector(a, a";
+    s += "__builtin_shufflevector(__a, __a";
     for (unsigned i = DblWordElts; i <= nElts; i += DblWordElts)
       for (unsigned j = 0; j != DblWordElts; ++j)
         s += ", " + utostr(i - j - 1);
@@ -665,8 +675,11 @@
     throw "unknown OpKind!";
     break;
   }
-  if (op == OpHi || op == OpLo)
-    s += " return u.r;";
+  if (op == OpHi || op == OpLo) {
+    if (!define)
+      s += " return";
+    s += " u.r;";
+  }
   return s;
 }
 
@@ -741,11 +754,6 @@
   if (proto.find('s') == std::string::npos)
     ck = ClassB;
 
-  // Macro arguments are not type-checked like inline function arguments, so
-  // assign them to local temporaries to get the right type checking.
-  if (define)
-    s += GenMacroLocals(proto, typestr);
-
   if (proto[0] != 'v') {
     std::string ts = TypeString(proto[0], typestr);
     
@@ -782,9 +790,8 @@
   for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
     std::string args = std::string(&arg, 1);
 
-    // For macros, use the local temporaries instead of the macro arguments.
-    if (define && proto[i] != 'i')
-      args = "__" + args;
+    // Use the local temporaries instead of the macro arguments.
+    args = "__" + args;
 
     bool argQuad = false;
     bool argPoly = false;
@@ -970,10 +977,12 @@
       OS << GenArgs(Proto, TypeVec[ti]);
       
       // Definition.
-      if (define)
+      if (define) {
         OS << " __extension__ ({ \\\n  ";
-      else
+        OS << GenMacroLocals(Proto, TypeVec[ti]);
+      } else {
         OS << " { \\\n  ";
+      }
       
       if (k != OpNone) {
         OS << GenOpString(k, Proto, TypeVec[ti]);





More information about the llvm-commits mailing list