Skip to content

Commit

Permalink
[TableGen] Add the !filter bang operator.
Browse files Browse the repository at this point in the history
Add a test. Update the Programmer's Reference.

Use it in some TableGen files.

Differential Revision: https://reviews.llvm.org/D91008
  • Loading branch information
Paul C. Anagnostopoulos committed Nov 9, 2020
1 parent 57e46e7 commit 91d2e5c
Show file tree
Hide file tree
Showing 12 changed files with 277 additions and 135 deletions.
26 changes: 20 additions & 6 deletions llvm/docs/TableGen/ProgRef.rst
Expand Up @@ -210,12 +210,12 @@ TableGen provides "bang operators" that have a wide variety of uses:
.. productionlist::
BangOperator: one of
: !add !and !cast !con !dag
: !empty !eq !foldl !foreach !ge
: !getdagop !gt !head !if !interleave
: !isa !le !listconcat !listsplat !lt
: !mul !ne !not !or !setdagop
: !shl !size !sra !srl !strconcat
: !sub !subst !tail !xor
: !empty !eq !foldl !foreach !filter
: !ge !getdagop !gt !head !if
: !interleave !isa !le !listconcat !listsplat
: !lt !mul !ne !not !or
: !setdagop !shl !size !sra !srl
: !strconcat !sub !subst !tail !xor

The ``!cond`` operator has a slightly different
syntax compared to other bang operators, so it is defined separately:
Expand Down Expand Up @@ -1563,6 +1563,17 @@ and non-0 as true.
The arguments must be ``bit``, ``bits``, ``int``, or ``string`` values.
Use ``!cast<string>`` to compare other types of objects.

``!filter(``\ *var*\ ``,`` *list*\ ``,`` *predicate*\ ``)``

This operator creates a new ``list`` by filtering the elements in
*list*. To perform the filtering, TableGen binds the variable *var* to each
element and then evaluates the *predicate* expression, which presumably
refers to *var*. The predicate must
produce a boolean value (``bit``, ``bits``, or ``int``). The value is
interpreted as with ``!if``:
if the value is 0, the element is not included in the new list. If the value
is anything else, the element is included.

``!foldl(``\ *init*\ ``,`` *list*\ ``,`` *acc*\ ``,`` *var*\ ``,`` *expr*\ ``)``
This operator performs a left-fold over the items in *list*. The
variable *acc* acts as the accumulator and is initialized to *init*.
Expand All @@ -1577,6 +1588,9 @@ and non-0 as true.

int x = !foldl(0, RecList, total, rec, !add(total, rec.Number));

If your goal is to filter the list and produce a new list that includes only
some of the elements, see ``!filter``.

``!foreach(``\ *var*\ ``,`` *sequence*\ ``,`` *expr*\ ``)``
This operator creates a new ``list``/``dag`` in which each element is a
function of the corresponding element in the *sequence* ``list``/``dag``.
Expand Down
6 changes: 2 additions & 4 deletions llvm/include/llvm/IR/IntrinsicsNVVM.td
Expand Up @@ -225,10 +225,8 @@ class NVVM_MMA_OPS<int _ = 0> {
ldst_bit_ab_ops,
ldst_subint_cd_ops);
// Separate A/B/C fragments (loads) from D (stores).
list<WMMA_REGS> all_ld_ops = !foldl([]<WMMA_REGS>, all_ldst_ops, a, b,
!listconcat(a, !if(!eq(b.frag,"d"), [],[b])));
list<WMMA_REGS> all_st_ops = !foldl([]<WMMA_REGS>, all_ldst_ops, a, b,
!listconcat(a, !if(!eq(b.frag,"d"), [b],[])));
list<WMMA_REGS> all_ld_ops = !filter(op, all_ldst_ops, !ne(op.frag, "d"));
list<WMMA_REGS> all_st_ops = !filter(op, all_ldst_ops, !eq(op.frag, "d"));
}

def NVVM_MMA_OPS : NVVM_MMA_OPS;
Expand Down
2 changes: 1 addition & 1 deletion llvm/include/llvm/TableGen/Record.h
Expand Up @@ -865,7 +865,7 @@ class BinOpInit : public OpInit, public FoldingSetNode {
/// !op (X, Y, Z) - Combine two inits.
class TernOpInit : public OpInit, public FoldingSetNode {
public:
enum TernaryOp : uint8_t { SUBST, FOREACH, IF, DAG };
enum TernaryOp : uint8_t { SUBST, FOREACH, FILTER, IF, DAG };

private:
Init *LHS, *MHS, *RHS;
Expand Down
42 changes: 37 additions & 5 deletions llvm/lib/TableGen/Record.cpp
Expand Up @@ -1162,7 +1162,7 @@ void TernOpInit::Profile(FoldingSetNodeID &ID) const {
ProfileTernOpInit(ID, getOpcode(), getLHS(), getMHS(), getRHS(), getType());
}

static Init *ForeachApply(Init *LHS, Init *MHSe, Init *RHS, Record *CurRec) {
static Init *ItemApply(Init *LHS, Init *MHSe, Init *RHS, Record *CurRec) {
MapResolver R(CurRec);
R.set(LHS, MHSe);
return RHS->resolveReferences(R);
Expand All @@ -1171,7 +1171,7 @@ static Init *ForeachApply(Init *LHS, Init *MHSe, Init *RHS, Record *CurRec) {
static Init *ForeachDagApply(Init *LHS, DagInit *MHSd, Init *RHS,
Record *CurRec) {
bool Change = false;
Init *Val = ForeachApply(LHS, MHSd->getOperator(), RHS, CurRec);
Init *Val = ItemApply(LHS, MHSd->getOperator(), RHS, CurRec);
if (Val != MHSd->getOperator())
Change = true;

Expand All @@ -1184,7 +1184,7 @@ static Init *ForeachDagApply(Init *LHS, DagInit *MHSd, Init *RHS,
if (DagInit *Argd = dyn_cast<DagInit>(Arg))
NewArg = ForeachDagApply(LHS, Argd, RHS, CurRec);
else
NewArg = ForeachApply(LHS, Arg, RHS, CurRec);
NewArg = ItemApply(LHS, Arg, RHS, CurRec);

NewArgs.push_back(std::make_pair(NewArg, ArgName));
if (Arg != NewArg)
Expand All @@ -1206,7 +1206,7 @@ static Init *ForeachHelper(Init *LHS, Init *MHS, Init *RHS, RecTy *Type,
SmallVector<Init *, 8> NewList(MHSl->begin(), MHSl->end());

for (Init *&Item : NewList) {
Init *NewItem = ForeachApply(LHS, Item, RHS, CurRec);
Init *NewItem = ItemApply(LHS, Item, RHS, CurRec);
if (NewItem != Item)
Item = NewItem;
}
Expand All @@ -1216,6 +1216,31 @@ static Init *ForeachHelper(Init *LHS, Init *MHS, Init *RHS, RecTy *Type,
return nullptr;
}

// Evaluates RHS for all elements of MHS, using LHS as a temp variable.
// Creates a new list with the elements that evaluated to true.
static Init *FilterHelper(Init *LHS, Init *MHS, Init *RHS, RecTy *Type,
Record *CurRec) {
if (ListInit *MHSl = dyn_cast<ListInit>(MHS)) {
SmallVector<Init *, 8> NewList;

for (Init *Item : MHSl->getValues()) {
Init *Include = ItemApply(LHS, Item, RHS, CurRec);
if (!Include)
return nullptr;
if (IntInit *IncludeInt = dyn_cast_or_null<IntInit>(
Include->convertInitializerTo(IntRecTy::get()))) {
if (IncludeInt->getValue())
NewList.push_back(Item);
} else {
return nullptr;
}
}
return ListInit::get(NewList, cast<ListRecTy>(Type)->getElementType());
}

return nullptr;
}

Init *TernOpInit::Fold(Record *CurRec) const {
switch (getOpcode()) {
case SUBST: {
Expand Down Expand Up @@ -1268,6 +1293,12 @@ Init *TernOpInit::Fold(Record *CurRec) const {
break;
}

case FILTER: {
if (Init *Result = FilterHelper(LHS, MHS, RHS, getType(), CurRec))
return Result;
break;
}

case IF: {
if (IntInit *LHSi = dyn_cast_or_null<IntInit>(
LHS->convertInitializerTo(IntRecTy::get()))) {
Expand Down Expand Up @@ -1322,7 +1353,7 @@ Init *TernOpInit::resolveReferences(Resolver &R) const {
Init *mhs = MHS->resolveReferences(R);
Init *rhs;

if (getOpcode() == FOREACH) {
if (getOpcode() == FOREACH || getOpcode() == FILTER) {
ShadowResolver SR(R);
SR.addShadow(lhs);
rhs = RHS->resolveReferences(SR);
Expand All @@ -1342,6 +1373,7 @@ std::string TernOpInit::getAsString() const {
switch (getOpcode()) {
case SUBST: Result = "!subst"; break;
case FOREACH: Result = "!foreach"; UnquotedLHS = true; break;
case FILTER: Result = "!filter"; UnquotedLHS = true; break;
case IF: Result = "!if"; break;
case DAG: Result = "!dag"; break;
}
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/TableGen/TGLexer.cpp
Expand Up @@ -584,6 +584,7 @@ tgtok::TokKind TGLexer::LexExclaim() {
.Case("subst", tgtok::XSubst)
.Case("foldl", tgtok::XFoldl)
.Case("foreach", tgtok::XForEach)
.Case("filter", tgtok::XFilter)
.Case("listconcat", tgtok::XListConcat)
.Case("listsplat", tgtok::XListSplat)
.Case("strconcat", tgtok::XStrConcat)
Expand Down
4 changes: 2 additions & 2 deletions llvm/lib/TableGen/TGLexer.h
Expand Up @@ -54,8 +54,8 @@ namespace tgtok {
// Bang operators.
XConcat, XADD, XSUB, XMUL, XNOT, XAND, XOR, XXOR, XSRA, XSRL, XSHL,
XListConcat, XListSplat, XStrConcat, XInterleave, XCast, XSubst, XForEach,
XFoldl, XHead, XTail, XSize, XEmpty, XIf, XCond, XEq, XIsA, XDag, XNe,
XLe, XLt, XGe, XGt, XSetDagOp, XGetDagOp,
XFilter, XFoldl, XHead, XTail, XSize, XEmpty, XIf, XCond, XEq, XIsA,
XDag, XNe, XLe, XLt, XGe, XGt, XSetDagOp, XGetDagOp,

// Boolean literals.
TrueVal, FalseVal,
Expand Down

0 comments on commit 91d2e5c

Please sign in to comment.