Index: llvm/docs/TableGen/ProgRef.rst =================================================================== --- llvm/docs/TableGen/ProgRef.rst +++ llvm/docs/TableGen/ProgRef.rst @@ -206,12 +206,13 @@ .. 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 different syntax compared to other bang operators, so it is defined separately: @@ -1399,7 +1400,8 @@ ``!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. @@ -1557,9 +1559,15 @@ The arguments must be ``bit``, ``int``, or ``string`` values. Use ``!cast`` 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 @@ -1607,6 +1615,11 @@ 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 ========================= Index: llvm/include/llvm/TableGen/Record.h =================================================================== --- llvm/include/llvm/TableGen/Record.h +++ llvm/include/llvm/TableGen/Record.h @@ -753,7 +753,7 @@ /// 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 @@ /// !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 }; Index: llvm/lib/TableGen/Record.cpp =================================================================== --- llvm/lib/TableGen/Record.cpp +++ llvm/lib/TableGen/Record.cpp @@ -761,6 +761,12 @@ return NewInit; break; + case NOT: + if (IntInit *LHSi = + dyn_cast_or_null(LHS->convertInitializerTo(IntRecTy::get()))) + return IntInit::get(LHSi->getValue() ? 0 : 1); + break; + case HEAD: if (ListInit *LHSl = dyn_cast(LHS)) { assert(!LHSl->empty() && "Empty list in head"); @@ -820,6 +826,7 @@ 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 @@ case MUL: case AND: case OR: + case XOR: case SHL: case SRA: case SRL: { @@ -1029,7 +1037,8 @@ 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 @@ 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; Index: llvm/lib/TableGen/TGLexer.h =================================================================== --- llvm/lib/TableGen/TGLexer.h +++ llvm/lib/TableGen/TGLexer.h @@ -51,9 +51,10 @@ 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, Index: llvm/lib/TableGen/TGLexer.cpp =================================================================== --- llvm/lib/TableGen/TGLexer.cpp +++ llvm/lib/TableGen/TGLexer.cpp @@ -563,8 +563,10 @@ .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) Index: llvm/lib/TableGen/TGParser.cpp =================================================================== --- llvm/lib/TableGen/TGParser.cpp +++ llvm/lib/TableGen/TGParser.cpp @@ -908,6 +908,7 @@ default: TokError("unknown operation"); return nullptr; + case tgtok::XNOT: case tgtok::XHead: case tgtok::XTail: case tgtok::XSize: @@ -930,6 +931,11 @@ 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 @@ 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 @@ 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 @@ break; case tgtok::XAND: case tgtok::XOR: + case tgtok::XXOR: case tgtok::XSRA: case tgtok::XSRL: case tgtok::XSHL: @@ -1239,9 +1248,9 @@ 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 @@ 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 @@ 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: Index: llvm/test/TableGen/arithmetic.td =================================================================== --- llvm/test/TableGen/arithmetic.td +++ 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 @@ 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); Index: llvm/test/TableGen/if.td =================================================================== --- llvm/test/TableGen/if.td +++ llvm/test/TableGen/if.td @@ -97,6 +97,39 @@ 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 first = [1, 2, 3]; // CHECK-NEXT: list rest = [1, 2, 3]; Index: llvm/test/TableGen/math.td =================================================================== --- llvm/test/TableGen/math.td +++ llvm/test/TableGen/math.td @@ -71,6 +71,12 @@ // CHECK: Value = 84 def v84 : Int; +// CHECK: def v9 +// CHECK: Value = 9 +def v9 : Int; + // CHECK: def v924 // CHECK: Value = 924 def v924 : Int; + +