[TableGen] Improve handling for dag op names (#149248)
There are currently no ways to add names to dag operators other than when defining them. Furthermore a !con operation as well as some others, drops the operator names. This patch propagates the name from the LHS dag for !con and adds a way to get and set the operator name for a dag (!getdagopname, !setdagopname). --------- Co-authored-by: Nemanja Ivanovic <nemanja@synopsys.com>
This commit is contained in:
parent
8c8749608b
commit
144ae251aa
@ -219,17 +219,17 @@ TableGen provides "bang operators" that have a wide variety of uses:
|
||||
|
||||
.. productionlist::
|
||||
BangOperator: one of
|
||||
: !add !and !cast !con !dag
|
||||
: !div !empty !eq !exists !filter
|
||||
: !find !foldl !foreach !ge !getdagarg
|
||||
: !getdagname !getdagop !gt !head !if
|
||||
: !initialized !instances !interleave !isa !le
|
||||
: !listconcat !listflatten !listremove !listsplat !logtwo
|
||||
: !lt !match !mul !ne !not
|
||||
: !or !range !repr !setdagarg !setdagname
|
||||
: !setdagop !shl !size !sra !srl
|
||||
: !strconcat !sub !subst !substr !tail
|
||||
: !tolower !toupper !xor
|
||||
: !add !and !cast !con !dag
|
||||
: !div !empty !eq !exists !filter
|
||||
: !find !foldl !foreach !ge !getdagarg
|
||||
: !getdagname !getdagop !getdagopname !gt !head
|
||||
: !if !initialized !instances !interleave !isa
|
||||
: !le !listconcat !listflatten !listremove !listsplat
|
||||
: !logtwo !lt !match !mul !ne
|
||||
: !not !or !range !repr !setdagarg
|
||||
: !setdagname !setdagop !setdagopname !shl !size
|
||||
: !sra !srl !strconcat !sub !subst
|
||||
: !substr !tail !tolower !toupper !xor
|
||||
|
||||
The ``!cond`` operator has a slightly different
|
||||
syntax compared to other bang operators, so it is defined separately:
|
||||
@ -1443,7 +1443,8 @@ DAG.
|
||||
|
||||
The following bang operators are useful for working with DAGs:
|
||||
``!con``, ``!dag``, ``!empty``, ``!foreach``, ``!getdagarg``, ``!getdagname``,
|
||||
``!getdagop``, ``!setdagarg``, ``!setdagname``, ``!setdagop``, ``!size``.
|
||||
``!getdagop``, ``!getdagopname``, ``!setdagarg``, ``!setdagname``, ``!setdagop``,
|
||||
``!setdagopname``, ``!size``.
|
||||
|
||||
Defvar in a record body
|
||||
-----------------------
|
||||
@ -1695,9 +1696,11 @@ and non-0 as true.
|
||||
This operator concatenates the DAG nodes *a*, *b*, etc. Their operations
|
||||
must equal.
|
||||
|
||||
``!con((op a1:$name1, a2:$name2), (op b1:$name3))``
|
||||
``!con((op:$lhs a1:$name1, a2:$name2), (op:$rhs b1:$name3))``
|
||||
|
||||
results in the DAG node ``(op a1:$name1, a2:$name2, b1:$name3)``.
|
||||
results in the DAG node ``(op:$lhs a1:$name1, a2:$name2, b1:$name3)``.
|
||||
The name of the dag operator is derived from the LHS DAG node if it is
|
||||
set, otherwise from the RHS DAG node.
|
||||
|
||||
``!cond(``\ *cond1* ``:`` *val1*\ ``,`` *cond2* ``:`` *val2*\ ``, ...,`` *condn* ``:`` *valn*\ ``)``
|
||||
This operator tests *cond1* and returns *val1* if the result is true.
|
||||
@ -1819,6 +1822,10 @@ and non-0 as true.
|
||||
|
||||
dag d = !dag(!getdagop(someDag), args, names);
|
||||
|
||||
``!getdagopname(``\ *dag*\ ``)``
|
||||
This operator retrieves the name of the given *dag* operator. If the operator
|
||||
has no name associated, ``?`` is returned.
|
||||
|
||||
``!gt(``\ *a*\ `,` *b*\ ``)``
|
||||
This operator produces 1 if *a* is greater than *b*; 0 otherwise.
|
||||
The arguments must be ``bit``, ``bits``, ``int``, or ``string`` values.
|
||||
@ -1949,6 +1956,10 @@ and non-0 as true.
|
||||
|
||||
Example: ``!setdagop((foo 1, 2), bar)`` results in ``(bar 1, 2)``.
|
||||
|
||||
``!setdagopname(``\ *dag*\ ``,``\ *name*\ ``)``
|
||||
This operator produces a DAG node with the same operator and arguments as
|
||||
*dag*, but replacing the name of the operator with *name*.
|
||||
|
||||
``!shl(``\ *a*\ ``,`` *count*\ ``)``
|
||||
This operator shifts *a* left logically by *count* bits and produces the resulting
|
||||
value. The operation is performed on a 64-bit integer; the result
|
||||
|
||||
@ -841,6 +841,7 @@ public:
|
||||
SIZE,
|
||||
EMPTY,
|
||||
GETDAGOP,
|
||||
GETDAGOPNAME,
|
||||
LOG2,
|
||||
REPR,
|
||||
LISTFLATTEN,
|
||||
@ -910,6 +911,7 @@ public:
|
||||
GETDAGARG,
|
||||
GETDAGNAME,
|
||||
SETDAGOP,
|
||||
SETDAGOPNAME
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
@ -985,6 +985,12 @@ const Init *UnOpInit::Fold(const Record *CurRec, bool IsFinal) const {
|
||||
}
|
||||
break;
|
||||
|
||||
case GETDAGOPNAME:
|
||||
if (const auto *Dag = dyn_cast<DagInit>(LHS)) {
|
||||
return Dag->getName();
|
||||
}
|
||||
break;
|
||||
|
||||
case LOG2:
|
||||
if (const auto *LHSi = dyn_cast_or_null<IntInit>(
|
||||
LHS->convertInitializerTo(IntRecTy::get(RK)))) {
|
||||
@ -1050,6 +1056,9 @@ std::string UnOpInit::getAsString() const {
|
||||
case SIZE: Result = "!size"; break;
|
||||
case EMPTY: Result = "!empty"; break;
|
||||
case GETDAGOP: Result = "!getdagop"; break;
|
||||
case GETDAGOPNAME:
|
||||
Result = "!getdagopname";
|
||||
break;
|
||||
case LOG2 : Result = "!logtwo"; break;
|
||||
case LISTFLATTEN:
|
||||
Result = "!listflatten";
|
||||
@ -1310,7 +1319,11 @@ const Init *BinOpInit::Fold(const Record *CurRec) const {
|
||||
SmallVector<std::pair<const Init *, const StringInit *>, 8> Args;
|
||||
llvm::append_range(Args, LHSs->getArgAndNames());
|
||||
llvm::append_range(Args, RHSs->getArgAndNames());
|
||||
return DagInit::get(Op, Args);
|
||||
// Use the name of the LHS DAG if it's set, otherwise the name of the RHS.
|
||||
const auto *NameInit = LHSs->getName();
|
||||
if (!NameInit)
|
||||
NameInit = RHSs->getName();
|
||||
return DagInit::get(Op, NameInit, Args);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -1508,6 +1521,14 @@ const Init *BinOpInit::Fold(const Record *CurRec) const {
|
||||
return DagInit::get(Op, Dag->getArgs(), Dag->getArgNames());
|
||||
break;
|
||||
}
|
||||
case SETDAGOPNAME: {
|
||||
const auto *Dag = dyn_cast<DagInit>(LHS);
|
||||
const auto *Op = dyn_cast<StringInit>(RHS);
|
||||
if (Dag && Op)
|
||||
return DagInit::get(Dag->getOperator(), Op, Dag->getArgs(),
|
||||
Dag->getArgNames());
|
||||
break;
|
||||
}
|
||||
case ADD:
|
||||
case SUB:
|
||||
case MUL:
|
||||
@ -1620,6 +1641,9 @@ std::string BinOpInit::getAsString() const {
|
||||
case STRCONCAT: Result = "!strconcat"; break;
|
||||
case INTERLEAVE: Result = "!interleave"; break;
|
||||
case SETDAGOP: Result = "!setdagop"; break;
|
||||
case SETDAGOPNAME:
|
||||
Result = "!setdagopname";
|
||||
break;
|
||||
case GETDAGARG:
|
||||
Result = "!getdagarg<" + getType()->getAsString() + ">";
|
||||
break;
|
||||
|
||||
@ -680,6 +680,8 @@ tgtok::TokKind TGLexer::LexExclaim() {
|
||||
.Case("find", tgtok::XFind)
|
||||
.Cases("setdagop", "setop", tgtok::XSetDagOp) // !setop is deprecated.
|
||||
.Cases("getdagop", "getop", tgtok::XGetDagOp) // !getop is deprecated.
|
||||
.Case("setdagopname", tgtok::XSetDagOpName)
|
||||
.Case("getdagopname", tgtok::XGetDagOpName)
|
||||
.Case("getdagarg", tgtok::XGetDagArg)
|
||||
.Case("getdagname", tgtok::XGetDagName)
|
||||
.Case("setdagarg", tgtok::XSetDagArg)
|
||||
|
||||
@ -150,6 +150,8 @@ enum TokKind {
|
||||
XGt,
|
||||
XSetDagOp,
|
||||
XGetDagOp,
|
||||
XSetDagOpName,
|
||||
XGetDagOpName,
|
||||
XExists,
|
||||
XListRemove,
|
||||
XToLower,
|
||||
|
||||
@ -11,6 +11,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "TGParser.h"
|
||||
#include "TGLexer.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/ADT/Twine.h"
|
||||
@ -1199,6 +1200,7 @@ const Init *TGParser::ParseOperation(Record *CurRec, const RecTy *ItemType) {
|
||||
case tgtok::XCast:
|
||||
case tgtok::XRepr:
|
||||
case tgtok::XGetDagOp:
|
||||
case tgtok::XGetDagOpName:
|
||||
case tgtok::XInitialized: { // Value ::= !unop '(' Value ')'
|
||||
UnOpInit::UnaryOp Code;
|
||||
const RecTy *Type = nullptr;
|
||||
@ -1287,6 +1289,11 @@ const Init *TGParser::ParseOperation(Record *CurRec, const RecTy *ItemType) {
|
||||
}
|
||||
Code = UnOpInit::GETDAGOP;
|
||||
break;
|
||||
case tgtok::XGetDagOpName:
|
||||
Lex.Lex(); // eat the operation
|
||||
Type = StringRecTy::get(Records);
|
||||
Code = UnOpInit::GETDAGOPNAME;
|
||||
break;
|
||||
case tgtok::XInitialized:
|
||||
Lex.Lex(); // eat the operation
|
||||
Code = UnOpInit::INITIALIZED;
|
||||
@ -1514,7 +1521,8 @@ const Init *TGParser::ParseOperation(Record *CurRec, const RecTy *ItemType) {
|
||||
case tgtok::XInterleave:
|
||||
case tgtok::XGetDagArg:
|
||||
case tgtok::XGetDagName:
|
||||
case tgtok::XSetDagOp: { // Value ::= !binop '(' Value ',' Value ')'
|
||||
case tgtok::XSetDagOp:
|
||||
case tgtok::XSetDagOpName: { // Value ::= !binop '(' Value ',' Value ')'
|
||||
tgtok::TokKind OpTok = Lex.getCode();
|
||||
SMLoc OpLoc = Lex.getLoc();
|
||||
Lex.Lex(); // eat the operation
|
||||
@ -1550,6 +1558,9 @@ const Init *TGParser::ParseOperation(Record *CurRec, const RecTy *ItemType) {
|
||||
case tgtok::XStrConcat: Code = BinOpInit::STRCONCAT; break;
|
||||
case tgtok::XInterleave: Code = BinOpInit::INTERLEAVE; break;
|
||||
case tgtok::XSetDagOp: Code = BinOpInit::SETDAGOP; break;
|
||||
case tgtok::XSetDagOpName:
|
||||
Code = BinOpInit::SETDAGOPNAME;
|
||||
break;
|
||||
case tgtok::XGetDagArg:
|
||||
Code = BinOpInit::GETDAGARG;
|
||||
break;
|
||||
@ -1580,6 +1591,10 @@ const Init *TGParser::ParseOperation(Record *CurRec, const RecTy *ItemType) {
|
||||
}
|
||||
ArgType = DagRecTy::get(Records);
|
||||
break;
|
||||
case tgtok::XSetDagOpName:
|
||||
Type = DagRecTy::get(Records);
|
||||
ArgType = DagRecTy::get(Records);
|
||||
break;
|
||||
case tgtok::XGetDagName:
|
||||
Type = StringRecTy::get(Records);
|
||||
ArgType = DagRecTy::get(Records);
|
||||
@ -1773,22 +1788,26 @@ const Init *TGParser::ParseOperation(Record *CurRec, const RecTy *ItemType) {
|
||||
// Deal with BinOps whose arguments have different types, by
|
||||
// rewriting ArgType in between them.
|
||||
switch (Code) {
|
||||
case BinOpInit::SETDAGOP:
|
||||
// After parsing the first dag argument, switch to expecting
|
||||
// a record, with no restriction on its superclasses.
|
||||
ArgType = RecordRecTy::get(Records, {});
|
||||
break;
|
||||
case BinOpInit::GETDAGARG:
|
||||
// After parsing the first dag argument, expect an index integer or a
|
||||
// name string.
|
||||
ArgType = nullptr;
|
||||
break;
|
||||
case BinOpInit::GETDAGNAME:
|
||||
// After parsing the first dag argument, expect an index integer.
|
||||
ArgType = IntRecTy::get(Records);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
case BinOpInit::SETDAGOPNAME:
|
||||
// After parsing the first dag argument, expect a string.
|
||||
ArgType = StringRecTy::get(Records);
|
||||
break;
|
||||
case BinOpInit::SETDAGOP:
|
||||
// After parsing the first dag argument, switch to expecting
|
||||
// a record, with no restriction on its superclasses.
|
||||
ArgType = RecordRecTy::get(Records, {});
|
||||
break;
|
||||
case BinOpInit::GETDAGARG:
|
||||
// After parsing the first dag argument, expect an index integer or a
|
||||
// name string.
|
||||
ArgType = nullptr;
|
||||
break;
|
||||
case BinOpInit::GETDAGNAME:
|
||||
// After parsing the first dag argument, expect an index integer.
|
||||
ArgType = IntRecTy::get(Records);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!consume(tgtok::comma))
|
||||
|
||||
@ -28,6 +28,7 @@ def bob : Super;
|
||||
def test {
|
||||
dag orig = (foo 1, 2:$a, $b);
|
||||
dag another = (qux "hello", $world);
|
||||
dag named = (foo:$root 1, 2:$a, $b);
|
||||
|
||||
// CHECK: dag replaceWithBar = (bar 1, 2:$a, ?:$b);
|
||||
dag replaceWithBar = !setop(orig, bar);
|
||||
@ -41,6 +42,19 @@ def test {
|
||||
// CHECK: dag getopToSetop = (foo "hello", ?:$world);
|
||||
dag getopToSetop = !setdagop(another, !getdagop(orig));
|
||||
|
||||
// CHECK: dag setOpName = (foo:$baz 1, 2:$a, ?:$b);
|
||||
dag setOpName = !setdagopname(orig, "baz");
|
||||
|
||||
// CHECK: dag getopNameToSetOpName = (foo:$root 1, 2:$a, ?:$b);
|
||||
dag getopNameToSetOpName = !setdagopname(orig, !getdagopname(named));
|
||||
|
||||
// CHECK: dag setOpNameExpl = (foo:$baz 1, 2:$a, ?:$b);
|
||||
dag setOpNameExpl = !setdagopname((foo 1, 2:$a, $b), "baz");
|
||||
|
||||
// CHECK: dag getopNameToSetOpNameExpl = (foo:$root 1, 2:$a, ?:$b);
|
||||
dag getopNameToSetOpNameExpl =
|
||||
!setdagopname(orig, !getdagopname((foo:$root 1, 2:$a, $b)));
|
||||
|
||||
// CHECK: dag getopToBangDag = (foo 1:$a, 2:$b, 3:$c);
|
||||
dag getopToBangDag = !dag(!getdagop(orig), [1, 2, 3], ["a", "b", "c"]);
|
||||
|
||||
|
||||
@ -16,6 +16,12 @@ def test {
|
||||
dag undefSecond = !con((op 1), (? 2));
|
||||
// CHECK: dag undefBoth = (? 1, 2);
|
||||
dag undefBoth = !con((? 1), (? 2));
|
||||
// CHECK: dag namedLHS = (op:$lhs 1, 2);
|
||||
dag namedLHS = !con((op:$lhs 1), (op 2));
|
||||
// CHECK: dag namedRHS = (op:$rhs 1, 2);
|
||||
dag namedRHS = !con((op 1), (op:$rhs 2));
|
||||
// CHECK: dag namedBoth = (op:$lhs 1, 2);
|
||||
dag namedBoth = !con((op:$lhs 1), (op:$rhs 2));
|
||||
|
||||
#ifdef ERROR
|
||||
// ERROR: Concatenated Dag operators do not match: '(op 1)' vs. '(otherop 2)'
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user