Index: llvm/docs/TableGen/LangIntro.rst =================================================================== --- llvm/docs/TableGen/LangIntro.rst +++ llvm/docs/TableGen/LangIntro.rst @@ -284,7 +284,7 @@ The usual shift operators. Operations are on 64-bit integers, the result is undefined for shift counts outside [0, 63]. -``!add(a,b,...)`` ``!and(a,b,...)`` ``!or(a,b,...)`` +``!add(a,b,...)`` ``!mul(a,b,...)`` ``!and(a,b,...)`` ``!or(a,b,...)`` The usual arithmetic and binary operators. Note that all of the values have rules specifying how they convert to values Index: llvm/docs/TableGen/LangRef.rst =================================================================== --- llvm/docs/TableGen/LangRef.rst +++ llvm/docs/TableGen/LangRef.rst @@ -100,7 +100,7 @@ :!or !empty !subst !foreach !strconcat :!cast !listconcat !size !foldl :!isa !dag !le !lt !ge - :!gt !ne + :!gt !ne !mul TableGen also has !cond operator that needs a slightly different syntax compared to other "bang operators": Index: llvm/include/llvm/TableGen/Record.h =================================================================== --- llvm/include/llvm/TableGen/Record.h +++ llvm/include/llvm/TableGen/Record.h @@ -798,7 +798,7 @@ /// !op (X, Y) - Combine two inits. class BinOpInit : public OpInit, public FoldingSetNode { public: - enum BinaryOp : uint8_t { ADD, AND, OR, SHL, SRA, SRL, LISTCONCAT, + enum BinaryOp : uint8_t { ADD, MUL, AND, OR, SHL, SRA, SRL, LISTCONCAT, STRCONCAT, CONCAT, EQ, NE, LE, LT, GE, GT }; private: Index: llvm/lib/TableGen/Record.cpp =================================================================== --- llvm/lib/TableGen/Record.cpp +++ llvm/lib/TableGen/Record.cpp @@ -930,6 +930,7 @@ break; } case ADD: + case MUL: case AND: case OR: case SHL: @@ -945,6 +946,7 @@ switch (getOpcode()) { default: llvm_unreachable("Bad opcode!"); 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 SHL: Result = LHSv << RHSv; break; @@ -974,6 +976,7 @@ switch (getOpcode()) { case CONCAT: Result = "!con"; break; case ADD: Result = "!add"; break; + case MUL: Result = "!mul"; break; case AND: Result = "!and"; break; case OR: Result = "!or"; break; case SHL: Result = "!shl"; break; Index: llvm/lib/TableGen/TGLexer.h =================================================================== --- llvm/lib/TableGen/TGLexer.h +++ llvm/lib/TableGen/TGLexer.h @@ -49,9 +49,9 @@ MultiClass, String, Defset, // !keywords. - XConcat, XADD, XAND, XOR, XSRA, XSRL, XSHL, XListConcat, XStrConcat, XCast, - XSubst, XForEach, XFoldl, XHead, XTail, XSize, XEmpty, XIf, XCond, XEq, XIsA, XDag, - XNe, XLe, XLt, XGe, XGt, + XConcat, XADD, XMUL, XAND, XOR, XSRA, XSRL, XSHL, XListConcat, XStrConcat, + XCast, XSubst, XForEach, XFoldl, XHead, XTail, XSize, XEmpty, XIf, XCond, + XEq, XIsA, XDag, XNe, XLe, XLt, XGe, XGt, // Integer value. IntVal, Index: llvm/lib/TableGen/TGLexer.cpp =================================================================== --- llvm/lib/TableGen/TGLexer.cpp +++ llvm/lib/TableGen/TGLexer.cpp @@ -552,6 +552,7 @@ .Case("con", tgtok::XConcat) .Case("dag", tgtok::XDag) .Case("add", tgtok::XADD) + .Case("mul", tgtok::XMUL) .Case("and", tgtok::XAND) .Case("or", tgtok::XOR) .Case("shl", tgtok::XSHL) Index: llvm/lib/TableGen/TGParser.cpp =================================================================== --- llvm/lib/TableGen/TGParser.cpp +++ llvm/lib/TableGen/TGParser.cpp @@ -1023,6 +1023,7 @@ case tgtok::XConcat: case tgtok::XADD: + case tgtok::XMUL: case tgtok::XAND: case tgtok::XOR: case tgtok::XSRA: @@ -1045,6 +1046,7 @@ default: llvm_unreachable("Unhandled code!"); case tgtok::XConcat: Code = BinOpInit::CONCAT; break; case tgtok::XADD: Code = BinOpInit::ADD; break; + case tgtok::XMUL: Code = BinOpInit::MUL; break; case tgtok::XAND: Code = BinOpInit::AND; break; case tgtok::XOR: Code = BinOpInit::OR; break; case tgtok::XSRA: Code = BinOpInit::SRA; break; @@ -1075,6 +1077,7 @@ case tgtok::XSRL: case tgtok::XSHL: case tgtok::XADD: + case tgtok::XMUL: Type = IntRecTy::get(); ArgType = IntRecTy::get(); break; @@ -1154,7 +1157,8 @@ } if (Code != BinOpInit::ADD && Code != BinOpInit::AND && Code != BinOpInit::OR && Code != BinOpInit::SRA && - Code != BinOpInit::SRL && Code != BinOpInit::SHL) + Code != BinOpInit::SRL && Code != BinOpInit::SHL && + Code != BinOpInit::MUL) ArgType = Resolved; } @@ -1176,7 +1180,8 @@ // shorthand for nesting them. if (Code == BinOpInit::STRCONCAT || Code == BinOpInit::LISTCONCAT || Code == BinOpInit::CONCAT || Code == BinOpInit::ADD || - Code == BinOpInit::AND || Code == BinOpInit::OR) { + Code == BinOpInit::AND || Code == BinOpInit::OR || + Code == BinOpInit::MUL) { while (InitList.size() > 2) { Init *RHS = InitList.pop_back_val(); RHS = (BinOpInit::get(Code, InitList.back(), RHS, Type))->Fold(CurRec); @@ -2007,6 +2012,7 @@ case tgtok::XConcat: case tgtok::XDag: case tgtok::XADD: + case tgtok::XMUL: case tgtok::XAND: case tgtok::XOR: case tgtok::XSRA: Index: llvm/test/TableGen/math.td =================================================================== --- llvm/test/TableGen/math.td +++ llvm/test/TableGen/math.td @@ -35,6 +35,10 @@ // CHECK: def v1025 // CHECK: Value = 1025 +// CHECK: def v12 +// CHECK: Value = 12 +def v12 : Int; + // CHECK: def v1a // CHECK: Value = 1 @@ -62,3 +66,11 @@ def v4 : Int; def v7 : Int; def v1a : Int; + +// CHECK: def v84 +// CHECK: Value = 84 +def v84 : Int; + +// CHECK: def v924 +// CHECK: Value = 924 +def v924 : Int;