diff options
author | Roman Lebedev <lebedev.ri@gmail.com> | 2019-04-10 18:26:36 +0000 |
---|---|---|
committer | Roman Lebedev <lebedev.ri@gmail.com> | 2019-04-10 18:26:36 +0000 |
commit | 5d9f656bb75ed4d0b9eb628115edd785fc61473b (patch) | |
tree | 93e4700dbe04370215abb1b899597bb1b7e97b83 /llvm/lib | |
parent | 163157378ee8ff2975cec933ab9ae31761b6ffff (diff) | |
download | bcm5719-llvm-5d9f656bb75ed4d0b9eb628115edd785fc61473b.tar.gz bcm5719-llvm-5d9f656bb75ed4d0b9eb628115edd785fc61473b.zip |
[TableGen] Introduce !listsplat 'binary' operator
Summary:
```
``!listsplat(a, size)``
A list value that contains the value ``a`` ``size`` times.
Example: ``!listsplat(0, 2)`` results in ``[0, 0]``.
```
I plan to use this in X86ScheduleBdVer2.td for LoadRes handling.
This is a little bit controversial because unlike every other binary operator
the types aren't identical.
Reviewers: stoklund, javed.absar, nhaehnle, craig.topper
Reviewed By: javed.absar
Subscribers: llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D60367
llvm-svn: 358117
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/TableGen/Record.cpp | 14 | ||||
-rw-r--r-- | llvm/lib/TableGen/TGLexer.cpp | 1 | ||||
-rw-r--r-- | llvm/lib/TableGen/TGLexer.h | 6 | ||||
-rw-r--r-- | llvm/lib/TableGen/TGParser.cpp | 38 |
4 files changed, 56 insertions, 3 deletions
diff --git a/llvm/lib/TableGen/Record.cpp b/llvm/lib/TableGen/Record.cpp index 7577f0b8571..27d1bdc7f4c 100644 --- a/llvm/lib/TableGen/Record.cpp +++ b/llvm/lib/TableGen/Record.cpp @@ -875,6 +875,10 @@ Init *BinOpInit::getListConcat(TypedInit *LHS, Init *RHS) { return BinOpInit::get(BinOpInit::LISTCONCAT, LHS, RHS, LHS->getType()); } +Init *BinOpInit::getListSplat(TypedInit *LHS, Init *RHS) { + return BinOpInit::get(BinOpInit::LISTSPLAT, LHS, RHS, LHS->getType()); +} + Init *BinOpInit::Fold(Record *CurRec) const { switch (getOpcode()) { case CONCAT: { @@ -915,6 +919,15 @@ Init *BinOpInit::Fold(Record *CurRec) const { } break; } + case LISTSPLAT: { + TypedInit *Value = dyn_cast<TypedInit>(LHS); + IntInit *Size = dyn_cast<IntInit>(RHS); + if (Value && Size) { + SmallVector<Init *, 8> Args(Size->getValue(), Value); + return ListInit::get(Args, Value->getType()); + } + break; + } case STRCONCAT: { StringInit *LHSs = dyn_cast<StringInit>(LHS); StringInit *RHSs = dyn_cast<StringInit>(RHS); @@ -1022,6 +1035,7 @@ std::string BinOpInit::getAsString() const { case GE: Result = "!ge"; break; case GT: Result = "!gt"; break; case LISTCONCAT: Result = "!listconcat"; break; + case LISTSPLAT: Result = "!listsplat"; break; case STRCONCAT: Result = "!strconcat"; break; } return Result + "(" + LHS->getAsString() + ", " + RHS->getAsString() + ")"; diff --git a/llvm/lib/TableGen/TGLexer.cpp b/llvm/lib/TableGen/TGLexer.cpp index 9ffcc7ae5c7..b9420253b2b 100644 --- a/llvm/lib/TableGen/TGLexer.cpp +++ b/llvm/lib/TableGen/TGLexer.cpp @@ -564,6 +564,7 @@ tgtok::TokKind TGLexer::LexExclaim() { .Case("foldl", tgtok::XFoldl) .Case("foreach", tgtok::XForEach) .Case("listconcat", tgtok::XListConcat) + .Case("listsplat", tgtok::XListSplat) .Case("strconcat", tgtok::XStrConcat) .Default(tgtok::Error); diff --git a/llvm/lib/TableGen/TGLexer.h b/llvm/lib/TableGen/TGLexer.h index 49bdea4e2ae..4b42d31de53 100644 --- a/llvm/lib/TableGen/TGLexer.h +++ b/llvm/lib/TableGen/TGLexer.h @@ -49,9 +49,9 @@ namespace tgtok { MultiClass, String, Defset, // !keywords. - 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, + 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, // Integer value. IntVal, diff --git a/llvm/lib/TableGen/TGParser.cpp b/llvm/lib/TableGen/TGParser.cpp index f9486d4469d..937de9e5c52 100644 --- a/llvm/lib/TableGen/TGParser.cpp +++ b/llvm/lib/TableGen/TGParser.cpp @@ -1042,6 +1042,7 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) { case tgtok::XGe: case tgtok::XGt: case tgtok::XListConcat: + case tgtok::XListSplat: case tgtok::XStrConcat: { // Value ::= !binop '(' Value ',' Value ')' tgtok::TokKind OpTok = Lex.getCode(); SMLoc OpLoc = Lex.getLoc(); @@ -1065,6 +1066,7 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) { case tgtok::XGe: Code = BinOpInit::GE; break; case tgtok::XGt: Code = BinOpInit::GT; break; case tgtok::XListConcat: Code = BinOpInit::LISTCONCAT; break; + case tgtok::XListSplat: Code = BinOpInit::LISTSPLAT; break; case tgtok::XStrConcat: Code = BinOpInit::STRCONCAT; break; } @@ -1103,6 +1105,9 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) { // We don't know the list type until we parse the first argument ArgType = ItemType; break; + case tgtok::XListSplat: + // Can't do any typechecking until we parse the first argument. + break; case tgtok::XStrConcat: Type = StringRecTy::get(); ArgType = StringRecTy::get(); @@ -1142,6 +1147,33 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) { return nullptr; } break; + case BinOpInit::LISTSPLAT: + if (ItemType && InitList.size() == 1) { + if (!isa<ListRecTy>(ItemType)) { + Error(OpLoc, + Twine("expected output type to be a list, got type '") + + ItemType->getAsString() + "'"); + return nullptr; + } + if (!ArgType->getListTy()->typeIsConvertibleTo(ItemType)) { + Error(OpLoc, Twine("expected first arg type to be '") + + ArgType->getAsString() + + "', got value of type '" + + cast<ListRecTy>(ItemType) + ->getElementType() + ->getAsString() + + "'"); + return nullptr; + } + } + if (InitList.size() == 2 && !isa<IntRecTy>(ArgType)) { + Error(InitLoc, Twine("expected second parameter to be an int, got " + "value of type '") + + ArgType->getAsString() + "'"); + return nullptr; + } + ArgType = nullptr; // Broken invariant: types not identical. + break; case BinOpInit::EQ: case BinOpInit::NE: if (!ArgType->typeIsConvertibleTo(IntRecTy::get()) && @@ -1179,8 +1211,12 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) { } Lex.Lex(); // eat the ')' + // listconcat returns a list with type of the argument. if (Code == BinOpInit::LISTCONCAT) Type = ArgType; + // listsplat returns a list of type of the *first* argument. + if (Code == BinOpInit::LISTSPLAT) + Type = cast<TypedInit>(InitList.front())->getType()->getListTy(); // We allow multiple operands to associative operators like !strconcat as // shorthand for nesting them. @@ -1718,6 +1754,7 @@ Init *TGParser::ParseOperationCond(Record *CurRec, RecTy *ItemType) { /// SimpleValue ::= SRATOK '(' Value ',' Value ')' /// SimpleValue ::= SRLTOK '(' Value ',' Value ')' /// SimpleValue ::= LISTCONCATTOK '(' Value ',' Value ')' +/// SimpleValue ::= LISTSPLATTOK '(' Value ',' Value ')' /// SimpleValue ::= STRCONCATTOK '(' Value ',' Value ')' /// SimpleValue ::= COND '(' [Value ':' Value,]+ ')' /// @@ -2031,6 +2068,7 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType, case tgtok::XGe: case tgtok::XGt: case tgtok::XListConcat: + case tgtok::XListSplat: case tgtok::XStrConcat: // Value ::= !binop '(' Value ',' Value ')' case tgtok::XIf: case tgtok::XCond: |