[Tablegen] Add support for the !mul operator.

This is a small addition to arithmetic operations that improves
expressiveness of the language.

Differential Revision: https://reviews.llvm.org/D58775

llvm-svn: 355187
This commit is contained in:
Nicola Zaghen 2019-03-01 09:46:29 +00:00
parent 1ed7d8ae36
commit a896756955
8 changed files with 30 additions and 8 deletions

View File

@ -284,7 +284,7 @@ supported include:
The usual shift operators. Operations are on 64-bit integers, the result The usual shift operators. Operations are on 64-bit integers, the result
is undefined for shift counts outside [0, 63]. 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. The usual arithmetic and binary operators.
Note that all of the values have rules specifying how they convert to values Note that all of the values have rules specifying how they convert to values

View File

@ -100,7 +100,7 @@ wide variety of meanings:
:!or !empty !subst !foreach !strconcat :!or !empty !subst !foreach !strconcat
:!cast !listconcat !size !foldl :!cast !listconcat !size !foldl
:!isa !dag !le !lt !ge :!isa !dag !le !lt !ge
:!gt !ne :!gt !ne !mul
TableGen also has !cond operator that needs a slightly different TableGen also has !cond operator that needs a slightly different
syntax compared to other "bang operators": syntax compared to other "bang operators":

View File

@ -798,7 +798,7 @@ public:
/// !op (X, Y) - Combine two inits. /// !op (X, Y) - Combine two inits.
class BinOpInit : public OpInit, public FoldingSetNode { class BinOpInit : public OpInit, public FoldingSetNode {
public: 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 }; STRCONCAT, CONCAT, EQ, NE, LE, LT, GE, GT };
private: private:

View File

@ -930,6 +930,7 @@ Init *BinOpInit::Fold(Record *CurRec) const {
break; break;
} }
case ADD: case ADD:
case MUL:
case AND: case AND:
case OR: case OR:
case SHL: case SHL:
@ -945,6 +946,7 @@ Init *BinOpInit::Fold(Record *CurRec) const {
switch (getOpcode()) { switch (getOpcode()) {
default: llvm_unreachable("Bad opcode!"); default: llvm_unreachable("Bad opcode!");
case ADD: Result = LHSv + RHSv; break; case ADD: Result = LHSv + RHSv; break;
case MUL: Result = LHSv * RHSv; break;
case AND: Result = LHSv & RHSv; break; case AND: Result = LHSv & RHSv; break;
case OR: Result = LHSv | RHSv; break; case OR: Result = LHSv | RHSv; break;
case SHL: Result = LHSv << RHSv; break; case SHL: Result = LHSv << RHSv; break;
@ -974,6 +976,7 @@ std::string BinOpInit::getAsString() const {
switch (getOpcode()) { switch (getOpcode()) {
case CONCAT: Result = "!con"; break; case CONCAT: Result = "!con"; break;
case ADD: Result = "!add"; break; case ADD: Result = "!add"; break;
case MUL: Result = "!mul"; break;
case AND: Result = "!and"; break; case AND: Result = "!and"; break;
case OR: Result = "!or"; break; case OR: Result = "!or"; break;
case SHL: Result = "!shl"; break; case SHL: Result = "!shl"; break;

View File

@ -552,6 +552,7 @@ tgtok::TokKind TGLexer::LexExclaim() {
.Case("con", tgtok::XConcat) .Case("con", tgtok::XConcat)
.Case("dag", tgtok::XDag) .Case("dag", tgtok::XDag)
.Case("add", tgtok::XADD) .Case("add", tgtok::XADD)
.Case("mul", tgtok::XMUL)
.Case("and", tgtok::XAND) .Case("and", tgtok::XAND)
.Case("or", tgtok::XOR) .Case("or", tgtok::XOR)
.Case("shl", tgtok::XSHL) .Case("shl", tgtok::XSHL)

View File

@ -49,9 +49,9 @@ namespace tgtok {
MultiClass, String, Defset, MultiClass, String, Defset,
// !keywords. // !keywords.
XConcat, XADD, XAND, XOR, XSRA, XSRL, XSHL, XListConcat, XStrConcat, XCast, XConcat, XADD, XMUL, XAND, XOR, XSRA, XSRL, XSHL, XListConcat, XStrConcat,
XSubst, XForEach, XFoldl, XHead, XTail, XSize, XEmpty, XIf, XCond, XEq, XIsA, XDag, XCast, XSubst, XForEach, XFoldl, XHead, XTail, XSize, XEmpty, XIf, XCond,
XNe, XLe, XLt, XGe, XGt, XEq, XIsA, XDag, XNe, XLe, XLt, XGe, XGt,
// Integer value. // Integer value.
IntVal, IntVal,

View File

@ -1023,6 +1023,7 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
case tgtok::XConcat: case tgtok::XConcat:
case tgtok::XADD: case tgtok::XADD:
case tgtok::XMUL:
case tgtok::XAND: case tgtok::XAND:
case tgtok::XOR: case tgtok::XOR:
case tgtok::XSRA: case tgtok::XSRA:
@ -1045,6 +1046,7 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
default: llvm_unreachable("Unhandled code!"); default: llvm_unreachable("Unhandled code!");
case tgtok::XConcat: Code = BinOpInit::CONCAT; break; case tgtok::XConcat: Code = BinOpInit::CONCAT; break;
case tgtok::XADD: Code = BinOpInit::ADD; break; case tgtok::XADD: Code = BinOpInit::ADD; break;
case tgtok::XMUL: Code = BinOpInit::MUL; break;
case tgtok::XAND: Code = BinOpInit::AND; break; case tgtok::XAND: Code = BinOpInit::AND; break;
case tgtok::XOR: Code = BinOpInit::OR; break; case tgtok::XOR: Code = BinOpInit::OR; break;
case tgtok::XSRA: Code = BinOpInit::SRA; break; case tgtok::XSRA: Code = BinOpInit::SRA; break;
@ -1075,6 +1077,7 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
case tgtok::XSRL: case tgtok::XSRL:
case tgtok::XSHL: case tgtok::XSHL:
case tgtok::XADD: case tgtok::XADD:
case tgtok::XMUL:
Type = IntRecTy::get(); Type = IntRecTy::get();
ArgType = IntRecTy::get(); ArgType = IntRecTy::get();
break; break;
@ -1154,7 +1157,8 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
} }
if (Code != BinOpInit::ADD && Code != BinOpInit::AND && if (Code != BinOpInit::ADD && Code != BinOpInit::AND &&
Code != BinOpInit::OR && Code != BinOpInit::SRA && Code != BinOpInit::OR && Code != BinOpInit::SRA &&
Code != BinOpInit::SRL && Code != BinOpInit::SHL) Code != BinOpInit::SRL && Code != BinOpInit::SHL &&
Code != BinOpInit::MUL)
ArgType = Resolved; ArgType = Resolved;
} }
@ -1176,7 +1180,8 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
// shorthand for nesting them. // shorthand for nesting them.
if (Code == BinOpInit::STRCONCAT || Code == BinOpInit::LISTCONCAT || if (Code == BinOpInit::STRCONCAT || Code == BinOpInit::LISTCONCAT ||
Code == BinOpInit::CONCAT || Code == BinOpInit::ADD || 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) { while (InitList.size() > 2) {
Init *RHS = InitList.pop_back_val(); Init *RHS = InitList.pop_back_val();
RHS = (BinOpInit::get(Code, InitList.back(), RHS, Type))->Fold(CurRec); RHS = (BinOpInit::get(Code, InitList.back(), RHS, Type))->Fold(CurRec);
@ -2007,6 +2012,7 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType,
case tgtok::XConcat: case tgtok::XConcat:
case tgtok::XDag: case tgtok::XDag:
case tgtok::XADD: case tgtok::XADD:
case tgtok::XMUL:
case tgtok::XAND: case tgtok::XAND:
case tgtok::XOR: case tgtok::XOR:
case tgtok::XSRA: case tgtok::XSRA:

View File

@ -35,6 +35,10 @@ def v1025 : Int<!add(v1024.Value, 1)>;
// CHECK: def v1025 // CHECK: def v1025
// CHECK: Value = 1025 // CHECK: Value = 1025
// CHECK: def v12
// CHECK: Value = 12
def v12 : Int<!mul(4, 3)>;
// CHECK: def v1a // CHECK: def v1a
// CHECK: Value = 1 // CHECK: Value = 1
@ -62,3 +66,11 @@ def v3072 : Int<!or(v1024.Value, v2048.Value)>;
def v4 : Int<!add(v2.Value, 1, v1.Value)>; def v4 : Int<!add(v2.Value, 1, v1.Value)>;
def v7 : Int<!or(v1.Value, v2.Value, v4.Value)>; def v7 : Int<!or(v1.Value, v2.Value, v4.Value)>;
def v1a : Int<!and(v7.Value, 5, v1.Value)>; def v1a : Int<!and(v7.Value, 5, v1.Value)>;
// CHECK: def v84
// CHECK: Value = 84
def v84 : Int<!mul(v12.Value, v7.Value)>;
// CHECK: def v924
// CHECK: Value = 924
def v924 : Int<!mul(v84.Value, 11)>;