[llvm] 4767bb2 - [TableGen] Add the !not and !xor operators.

Paul C. Anagnostopoulos via llvm-commits llvm-commits at lists.llvm.org
Thu Oct 15 07:13:28 PDT 2020


Author: Paul C. Anagnostopoulos
Date: 2020-10-15T10:12:59-04:00
New Revision: 4767bb2c0c746eaf146927c8bcb0528bd36c7b8f

URL: https://github.com/llvm/llvm-project/commit/4767bb2c0c746eaf146927c8bcb0528bd36c7b8f
DIFF: https://github.com/llvm/llvm-project/commit/4767bb2c0c746eaf146927c8bcb0528bd36c7b8f.diff

LOG: [TableGen] Add the !not and !xor operators.
Update the TableGen Programmer's Reference.

Added: 
    

Modified: 
    llvm/docs/TableGen/ProgRef.rst
    llvm/include/llvm/TableGen/Record.h
    llvm/lib/TableGen/Record.cpp
    llvm/lib/TableGen/TGLexer.cpp
    llvm/lib/TableGen/TGLexer.h
    llvm/lib/TableGen/TGParser.cpp
    llvm/test/TableGen/arithmetic.td
    llvm/test/TableGen/if.td
    llvm/test/TableGen/math.td

Removed: 
    


################################################################################
diff  --git a/llvm/docs/TableGen/ProgRef.rst b/llvm/docs/TableGen/ProgRef.rst
index d59dc1b54d76..0454d5abbba6 100644
--- a/llvm/docs/TableGen/ProgRef.rst
+++ b/llvm/docs/TableGen/ProgRef.rst
@@ -206,12 +206,13 @@ TableGen provides "bang operators" that have a wide variety of uses:
 
 .. productionlist::
    BangOperator: one of
-               : !add    !and         !cast         !con         !dag
-               : !empty  !eq          !foldl        !foreach     !ge
-               : !getop  !gt          !head         !if          !isa
-               : !le     !listconcat  !listsplat    !lt          !mul
-               : !ne     !or          !setop        !shl         !size
-               : !sra    !srl         !strconcat    !subst       !tail
+               : !add     !and         !cast        !con         !dag
+               : !empty   !eq          !foldl       !foreach     !ge
+               : !getop   !gt          !head        !if          !isa
+               : !le      !listconcat  !listsplat   !lt          !mul
+               : !ne      !not         !or          !setop       !shl
+               : !size    !sra         !srl         !strconcat   !subst
+               : !tail    !xor
 
 The ``!cond`` operator has a slightly 
diff erent
 syntax compared to other bang operators, so it is defined separately:
@@ -1447,7 +1448,8 @@ and non-0 as true.
 
 ``!and(``\ *a*\ ``,`` *b*\ ``, ...)``
     This operator does a bitwise AND on *a*, *b*, etc., and produces the
-    result.
+    result. A logical AND can be performed if all the arguments are either
+    0 or 1.
 
 ``!cast<``\ *type*\ ``>(``\ *a*\ ``)``
     This operator performs a cast on *a* and produces the result.
@@ -1605,9 +1607,15 @@ and non-0 as true.
     The arguments must be ``bit``, ``int``, or ``string`` values.
     Use ``!cast<string>`` to compare other types of objects.
 
+``!not(``\ *a*\ ``)``
+    This operator performs a logical NOT on *a*, which must be
+    an integer. The argument 0 results in 1 (true); any other
+    argument results in 0 (false).
+
 ``!or(``\ *a*\ ``,`` *b*\ ``, ...)``
     This operator does a bitwise OR on *a*, *b*, etc., and produces the
-    result.
+    result. A logical OR can be performed if all the arguments are either
+    0 or 1.
 
 ``!setop(``\ *dag*\ ``,`` *op*\ ``)``
     This operator produces a DAG node with the same arguments as *dag*, but with its
@@ -1655,6 +1663,11 @@ and non-0 as true.
     This operator produces a new list with all the elements
     of the list *a* except for the zeroth one. (See also ``!head``.)
 
+``!xor(``\ *a*\ ``,`` *b*\ ``, ...)``
+    This operator does a bitwise EXCLUSIVE OR on *a*, *b*, etc., and produces
+    the result. A logical XOR can be performed if all the arguments are either
+    0 or 1.
+
 
 Appendix B: Sample Record
 =========================

diff  --git a/llvm/include/llvm/TableGen/Record.h b/llvm/include/llvm/TableGen/Record.h
index c7009e400ebc..c0eb88b56be3 100644
--- a/llvm/include/llvm/TableGen/Record.h
+++ b/llvm/include/llvm/TableGen/Record.h
@@ -753,7 +753,7 @@ class OpInit : public TypedInit {
 ///
 class UnOpInit : public OpInit, public FoldingSetNode {
 public:
-  enum UnaryOp : uint8_t { CAST, HEAD, TAIL, SIZE, EMPTY, GETOP };
+  enum UnaryOp : uint8_t { CAST, NOT, HEAD, TAIL, SIZE, EMPTY, GETOP };
 
 private:
   Init *LHS;
@@ -802,7 +802,7 @@ class UnOpInit : public OpInit, public FoldingSetNode {
 /// !op (X, Y) - Combine two inits.
 class BinOpInit : public OpInit, public FoldingSetNode {
 public:
-  enum BinaryOp : uint8_t { ADD, MUL, AND, OR, SHL, SRA, SRL, LISTCONCAT,
+  enum BinaryOp : uint8_t { ADD, MUL, AND, OR, XOR, SHL, SRA, SRL, LISTCONCAT,
                             LISTSPLAT, STRCONCAT, CONCAT, EQ, NE, LE, LT, GE,
                             GT, SETOP };
 

diff  --git a/llvm/lib/TableGen/Record.cpp b/llvm/lib/TableGen/Record.cpp
index 2a46449b213f..f191638083c4 100644
--- a/llvm/lib/TableGen/Record.cpp
+++ b/llvm/lib/TableGen/Record.cpp
@@ -761,6 +761,12 @@ Init *UnOpInit::Fold(Record *CurRec, bool IsFinal) const {
       return NewInit;
     break;
 
+  case NOT:
+    if (IntInit *LHSi =
+            dyn_cast_or_null<IntInit>(LHS->convertInitializerTo(IntRecTy::get())))
+      return IntInit::get(LHSi->getValue() ? 0 : 1);
+    break;
+
   case HEAD:
     if (ListInit *LHSl = dyn_cast<ListInit>(LHS)) {
       assert(!LHSl->empty() && "Empty list in head");
@@ -820,6 +826,7 @@ std::string UnOpInit::getAsString() const {
   std::string Result;
   switch (getOpcode()) {
   case CAST: Result = "!cast<" + getType()->getAsString() + ">"; break;
+  case NOT: Result = "!not"; break;
   case HEAD: Result = "!head"; break;
   case TAIL: Result = "!tail"; break;
   case SIZE: Result = "!size"; break;
@@ -1014,6 +1021,7 @@ Init *BinOpInit::Fold(Record *CurRec) const {
   case MUL:
   case AND:
   case OR:
+  case XOR:
   case SHL:
   case SRA:
   case SRL: {
@@ -1029,7 +1037,8 @@ Init *BinOpInit::Fold(Record *CurRec) const {
       case ADD: Result = LHSv +  RHSv; break;
       case MUL: Result = LHSv *  RHSv; break;
       case AND: Result = LHSv &  RHSv; break;
-      case OR: Result = LHSv | RHSv; break;
+      case OR:  Result = LHSv | RHSv; break;
+      case XOR: Result = LHSv ^ RHSv; break;
       case SHL: Result = (uint64_t)LHSv << (uint64_t)RHSv; break;
       case SRA: Result = LHSv >> RHSv; break;
       case SRL: Result = (uint64_t)LHSv >> (uint64_t)RHSv; break;
@@ -1060,6 +1069,7 @@ std::string BinOpInit::getAsString() const {
   case MUL: Result = "!mul"; break;
   case AND: Result = "!and"; break;
   case OR: Result = "!or"; break;
+  case XOR: Result = "!xor"; break;
   case SHL: Result = "!shl"; break;
   case SRA: Result = "!sra"; break;
   case SRL: Result = "!srl"; break;

diff  --git a/llvm/lib/TableGen/TGLexer.cpp b/llvm/lib/TableGen/TGLexer.cpp
index d9111f0068c2..5db0ecb4b0ed 100644
--- a/llvm/lib/TableGen/TGLexer.cpp
+++ b/llvm/lib/TableGen/TGLexer.cpp
@@ -563,8 +563,10 @@ tgtok::TokKind TGLexer::LexExclaim() {
     .Case("dag", tgtok::XDag)
     .Case("add", tgtok::XADD)
     .Case("mul", tgtok::XMUL)
+    .Case("not", tgtok::XNOT)
     .Case("and", tgtok::XAND)
     .Case("or", tgtok::XOR)
+    .Case("xor", tgtok::XXOR)
     .Case("shl", tgtok::XSHL)
     .Case("sra", tgtok::XSRA)
     .Case("srl", tgtok::XSRL)

diff  --git a/llvm/lib/TableGen/TGLexer.h b/llvm/lib/TableGen/TGLexer.h
index 49f37890043f..534c31382f63 100644
--- a/llvm/lib/TableGen/TGLexer.h
+++ b/llvm/lib/TableGen/TGLexer.h
@@ -51,9 +51,10 @@ namespace tgtok {
     MultiClass, String, Defset, Defvar, If, Then, ElseKW,
 
     // !keywords.
-    XConcat, XADD, XMUL, XAND, XOR, XSRA, XSRL, XSHL, XListConcat, XListSplat,
-    XStrConcat, XCast, XSubst, XForEach, XFoldl, XHead, XTail, XSize, XEmpty,
-    XIf, XCond, XEq, XIsA, XDag, XNe, XLe, XLt, XGe, XGt, XSetOp, XGetOp,
+    XConcat, XADD, XMUL, XNOT, XAND, XOR, XXOR, XSRA, XSRL, XSHL,
+    XListConcat, XListSplat, XStrConcat, XCast, XSubst, XForEach, XFoldl,
+    XHead, XTail, XSize, XEmpty, XIf, XCond, XEq, XIsA, XDag, XNe, XLe,
+    XLt, XGe, XGt, XSetOp, XGetOp,
 
     // Integer value.
     IntVal,

diff  --git a/llvm/lib/TableGen/TGParser.cpp b/llvm/lib/TableGen/TGParser.cpp
index eb5053b9c480..98443c97a159 100644
--- a/llvm/lib/TableGen/TGParser.cpp
+++ b/llvm/lib/TableGen/TGParser.cpp
@@ -908,6 +908,7 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
   default:
     TokError("unknown operation");
     return nullptr;
+  case tgtok::XNOT:
   case tgtok::XHead:
   case tgtok::XTail:
   case tgtok::XSize:
@@ -930,6 +931,11 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
         return nullptr;
       }
 
+      break;
+    case tgtok::XNOT:
+      Lex.Lex();  // eat the operation
+      Code = UnOpInit::NOT;
+      Type = IntRecTy::get();
       break;
     case tgtok::XHead:
       Lex.Lex();  // eat the operation
@@ -1070,6 +1076,7 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
   case tgtok::XMUL:
   case tgtok::XAND:
   case tgtok::XOR:
+  case tgtok::XXOR:
   case tgtok::XSRA:
   case tgtok::XSRL:
   case tgtok::XSHL:
@@ -1095,6 +1102,7 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
     case tgtok::XMUL:    Code = BinOpInit::MUL; break;
     case tgtok::XAND:    Code = BinOpInit::AND; break;
     case tgtok::XOR:     Code = BinOpInit::OR; break;
+    case tgtok::XXOR:    Code = BinOpInit::XOR; break;
     case tgtok::XSRA:    Code = BinOpInit::SRA; break;
     case tgtok::XSRL:    Code = BinOpInit::SRL; break;
     case tgtok::XSHL:    Code = BinOpInit::SHL; break;
@@ -1122,6 +1130,7 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
       break;
     case tgtok::XAND:
     case tgtok::XOR:
+    case tgtok::XXOR:
     case tgtok::XSRA:
     case tgtok::XSRL:
     case tgtok::XSHL:
@@ -1239,9 +1248,9 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
           return nullptr;
         }
         if (Code != BinOpInit::ADD && Code != BinOpInit::AND &&
-            Code != BinOpInit::OR && Code != BinOpInit::SRA &&
-            Code != BinOpInit::SRL && Code != BinOpInit::SHL &&
-            Code != BinOpInit::MUL)
+            Code != BinOpInit::OR && Code != BinOpInit::XOR &&
+            Code != BinOpInit::SRA && Code != BinOpInit::SRL &&
+            Code != BinOpInit::SHL && Code != BinOpInit::MUL)
           ArgType = Resolved;
       }
 
@@ -1278,7 +1287,7 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
     if (Code == BinOpInit::STRCONCAT || Code == BinOpInit::LISTCONCAT ||
         Code == BinOpInit::CONCAT || Code == BinOpInit::ADD ||
         Code == BinOpInit::AND || Code == BinOpInit::OR ||
-        Code == BinOpInit::MUL) {
+        Code == BinOpInit::XOR || Code == BinOpInit::MUL) {
       while (InitList.size() > 2) {
         Init *RHS = InitList.pop_back_val();
         RHS = (BinOpInit::get(Code, InitList.back(), RHS, Type))->Fold(CurRec);
@@ -2084,8 +2093,10 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType,
   case tgtok::XDag:
   case tgtok::XADD:
   case tgtok::XMUL:
+  case tgtok::XNOT:
   case tgtok::XAND:
   case tgtok::XOR:
+  case tgtok::XXOR:
   case tgtok::XSRA:
   case tgtok::XSRL:
   case tgtok::XSHL:

diff  --git a/llvm/test/TableGen/arithmetic.td b/llvm/test/TableGen/arithmetic.td
index 50007c5f18a2..db268eef2f85 100644
--- a/llvm/test/TableGen/arithmetic.td
+++ b/llvm/test/TableGen/arithmetic.td
@@ -7,6 +7,7 @@
 // CHECK:   bits<8> add = { 0, 1, 0, 0, 0, 0, 0, 0 };
 // CHECK:   bits<8> and = { 0, 0, 0, 0, 0, 0, 0, 1 };
 // CHECK:   bits<8> or =  { 0, 0, 1, 1, 1, 1, 1, 1 };
+// CHECK:   bits<8> xor = { 0, 0, 1, 1, 1, 1, 1, 0 };
 // CHECK:   bits<8> srl = { 0, 0, 0, 1, 1, 1, 1, 1 };
 // CHECK:   bits<8> sra = { 0, 0, 0, 1, 1, 1, 1, 1 };
 // CHECK:   bits<8> shl = { 0, 1, 1, 1, 1, 1, 1, 0 };
@@ -17,6 +18,7 @@ class A<bits<8> a, bits<2> b> {
   bits<8> add = !add(a, b);
   bits<8> and = !and(a, b);
   bits<8> or = !or(a, b);
+  bits<8> xor = !xor(a, b);
   bits<8> srl = !srl(a, b);
   bits<8> sra = !sra(a, b);
   bits<8> shl = !shl(a, b);

diff  --git a/llvm/test/TableGen/if.td b/llvm/test/TableGen/if.td
index 1fbee6966ff3..a3148494dd13 100644
--- a/llvm/test/TableGen/if.td
+++ b/llvm/test/TableGen/if.td
@@ -97,6 +97,39 @@ def E2d : E2<0>;
 def EXd1 : EX<1, E1d, E2d>;
 def EXd2 : EX<0, E1d, E2d>;
 
+// CHECK: def Not1
+// CHECK: Result1a = "OK"
+// CHECK: Result1b = "OK"
+// CHECK: Result1c = "OK"
+// CHECK: Result1d = "OK"
+// CHECK: Result1e = "OK"
+// CHECK: def Not2
+// CHECK: Result2a = "OK"
+// CHECK: Result2b = "OK"
+// CHECK: Result2c = "OK"
+// CHECK: Result2d = "OK"
+
+def Not1 {
+  bit true = 1;
+  string Result1a = !if(true, "OK", "not OK");
+  string Result1b = !if(!not(true), "not OK", "OK");
+
+  bit false = 0;
+  string Result1c = !if(false, "not OK", "OK");
+  string Result1d = !if(!not(false), "OK", "not OK");
+  string Result1e = !if(!not(!not(false)), "not OK", "OK");
+}
+
+def Not2 {
+  int one = 1;
+  string Result2a = !if(one, "OK", "not OK");
+  string Result2b = !if(!not(one), "not OK", "OK");
+
+  int zero = 0;
+  string Result2c = !if(zero, "not OK", "OK");
+  string Result2d = !if(!not(zero), "OK", "not OK");
+}
+
 // CHECK:      def One
 // CHECK-NEXT: list<int> first = [1, 2, 3];
 // CHECK-NEXT: list<int> rest = [1, 2, 3];

diff  --git a/llvm/test/TableGen/math.td b/llvm/test/TableGen/math.td
index f7bda1ed1377..24a0e53a7916 100644
--- a/llvm/test/TableGen/math.td
+++ b/llvm/test/TableGen/math.td
@@ -71,6 +71,12 @@ def v1a : Int<!and(v7.Value, 5, v1.Value)>;
 // CHECK: Value = 84
 def v84   : Int<!mul(v12.Value, v7.Value)>;
 
+// CHECK: def v9
+// CHECK: Value = 9
+def v9 : Int<!xor(v7.Value, 0x0E)>;
+
 // CHECK: def v924
 // CHECK: Value = 924
 def v924   : Int<!mul(v84.Value, 11)>;
+
+


        


More information about the llvm-commits mailing list