Index: docs/TableGen/LangIntro.rst =================================================================== --- docs/TableGen/LangIntro.rst +++ docs/TableGen/LangIntro.rst @@ -265,6 +265,10 @@ on string, int and bit objects. Use !cast to compare other types of objects. +``!le(a,b), !lt(a,b), !ge(a,b), !gt(a,b)`` + (Signed) comparison of integer values that returns bit 1 or 0 depending on + the result of the comparison. + ``!shl(a,b)`` ``!srl(a,b)`` ``!sra(a,b)`` ``!add(a,b)`` ``!and(a,b)`` The usual binary and arithmetic operators. Index: docs/TableGen/LangRef.rst =================================================================== --- docs/TableGen/LangRef.rst +++ docs/TableGen/LangRef.rst @@ -99,7 +99,8 @@ :!add !shl !sra !srl !and :!or !empty !subst !foreach !strconcat :!cast !listconcat !size !foldl - :!isa !dag + :!isa !dag !le !lt !ge + :!gt Syntax Index: include/llvm/TableGen/Record.h =================================================================== --- include/llvm/TableGen/Record.h +++ include/llvm/TableGen/Record.h @@ -803,7 +803,7 @@ class BinOpInit : public OpInit, public FoldingSetNode { public: enum BinaryOp : uint8_t { ADD, AND, OR, SHL, SRA, SRL, LISTCONCAT, - STRCONCAT, CONCAT, EQ }; + STRCONCAT, CONCAT, EQ, LE, LT, GE, GT }; private: Init *LHS, *RHS; Index: lib/TableGen/Record.cpp =================================================================== --- lib/TableGen/Record.cpp +++ lib/TableGen/Record.cpp @@ -898,23 +898,39 @@ return ConcatStringInits(LHSs, RHSs); break; } - case EQ: { + case EQ: + case LE: + case LT: + case GE: + case GT: { // try to fold eq comparison for 'bit' and 'int', otherwise fallback // to string objects. IntInit *L = - dyn_cast_or_null(LHS->convertInitializerTo(IntRecTy::get())); + dyn_cast_or_null(LHS->convertInitializerTo(IntRecTy::get())); IntInit *R = - dyn_cast_or_null(RHS->convertInitializerTo(IntRecTy::get())); + dyn_cast_or_null(RHS->convertInitializerTo(IntRecTy::get())); - if (L && R) - return IntInit::get(L->getValue() == R->getValue()); + if (L && R) { + bool Result; + switch (getOpcode()) { + case EQ: Result = L->getValue() == R->getValue(); break; + case LE: Result = L->getValue() <= R->getValue(); break; + case LT: Result = L->getValue() < R->getValue(); break; + case GE: Result = L->getValue() >= R->getValue(); break; + case GT: Result = L->getValue() > R->getValue(); break; + default: llvm_unreachable("unhandled comparison"); + } + return BitInit::get(Result); + } - StringInit *LHSs = dyn_cast(LHS); - StringInit *RHSs = dyn_cast(RHS); + if (getOpcode() == EQ) { + StringInit *LHSs = dyn_cast(LHS); + StringInit *RHSs = dyn_cast(RHS); - // Make sure we've resolved - if (LHSs && RHSs) - return IntInit::get(LHSs->getValue() == RHSs->getValue()); + // Make sure we've resolved + if (LHSs && RHSs) + return BitInit::get(LHSs->getValue() == RHSs->getValue()); + } break; } @@ -969,6 +985,10 @@ case SRA: Result = "!sra"; break; case SRL: Result = "!srl"; break; case EQ: Result = "!eq"; break; + case LE: Result = "!le"; break; + case LT: Result = "!lt"; break; + case GE: Result = "!ge"; break; + case GT: Result = "!gt"; break; case LISTCONCAT: Result = "!listconcat"; break; case STRCONCAT: Result = "!strconcat"; break; } Index: lib/TableGen/TGLexer.h =================================================================== --- lib/TableGen/TGLexer.h +++ lib/TableGen/TGLexer.h @@ -49,6 +49,7 @@ // !keywords. XConcat, XADD, XAND, XOR, XSRA, XSRL, XSHL, XListConcat, XStrConcat, XCast, XSubst, XForEach, XFoldl, XHead, XTail, XSize, XEmpty, XIf, XEq, XIsA, XDag, + XLe, XLt, XGe, XGt, // Integer value. IntVal, Index: lib/TableGen/TGLexer.cpp =================================================================== --- lib/TableGen/TGLexer.cpp +++ lib/TableGen/TGLexer.cpp @@ -467,6 +467,10 @@ tgtok::TokKind Kind = StringSwitch(StringRef(Start, CurPtr - Start)) .Case("eq", tgtok::XEq) + .Case("le", tgtok::XLe) + .Case("lt", tgtok::XLt) + .Case("ge", tgtok::XGe) + .Case("gt", tgtok::XGt) .Case("if", tgtok::XIf) .Case("isa", tgtok::XIsA) .Case("head", tgtok::XHead) Index: lib/TableGen/TGParser.cpp =================================================================== --- lib/TableGen/TGParser.cpp +++ lib/TableGen/TGParser.cpp @@ -974,6 +974,10 @@ case tgtok::XSRL: case tgtok::XSHL: case tgtok::XEq: + case tgtok::XLe: + case tgtok::XLt: + case tgtok::XGe: + case tgtok::XGt: case tgtok::XListConcat: case tgtok::XStrConcat: { // Value ::= !binop '(' Value ',' Value ')' tgtok::TokKind OpTok = Lex.getCode(); @@ -991,6 +995,10 @@ case tgtok::XSRL: Code = BinOpInit::SRL; break; case tgtok::XSHL: Code = BinOpInit::SHL; break; case tgtok::XEq: Code = BinOpInit::EQ; break; + case tgtok::XLe: Code = BinOpInit::LE; break; + case tgtok::XLt: Code = BinOpInit::LT; break; + case tgtok::XGe: Code = BinOpInit::GE; break; + case tgtok::XGt: Code = BinOpInit::GT; break; case tgtok::XListConcat: Code = BinOpInit::LISTCONCAT; break; case tgtok::XStrConcat: Code = BinOpInit::STRCONCAT; break; } @@ -1017,6 +1025,13 @@ Type = BitRecTy::get(); // ArgType for Eq is not known at this point break; + case tgtok::XLe: + case tgtok::XLt: + case tgtok::XGe: + case tgtok::XGt: + Type = BitRecTy::get(); + ArgType = IntRecTy::get(); + break; case tgtok::XListConcat: // We don't know the list type until we parse the first argument ArgType = ItemType; @@ -1830,6 +1845,10 @@ case tgtok::XSRL: case tgtok::XSHL: case tgtok::XEq: + case tgtok::XLe: + case tgtok::XLt: + case tgtok::XGe: + case tgtok::XGt: case tgtok::XListConcat: case tgtok::XStrConcat: // Value ::= !binop '(' Value ',' Value ')' case tgtok::XIf: Index: test/TableGen/compare.td =================================================================== --- /dev/null +++ test/TableGen/compare.td @@ -0,0 +1,49 @@ +// RUN: llvm-tblgen %s | FileCheck %s +// XFAIL: vg_leak + +// CHECK: --- Defs --- + +// CHECK: def A0 { +// CHECK: bit eq = 1; +// CHECK: bit le = 1; +// CHECK: bit lt = 0; +// CHECK: bit ge = 1; +// CHECK: bit gt = 0; +// CHECK: } + +// CHECK: def A1 { +// CHECK: bit eq = 0; +// CHECK: bit le = 1; +// CHECK: bit lt = 1; +// CHECK: bit ge = 0; +// CHECK: bit gt = 0; +// CHECK: } + +// CHECK: def A2 { +// CHECK: bit eq = 0; +// CHECK: bit le = 0; +// CHECK: bit lt = 0; +// CHECK: bit ge = 1; +// CHECK: bit gt = 1; +// CHECK: } + +// CHECK: def A3 { +// CHECK: bit eq = 0; +// CHECK: bit le = 0; +// CHECK: bit lt = 0; +// CHECK: bit ge = 1; +// CHECK: bit gt = 1; +// CHECK: } + +class A { + bit eq = !eq(x, y); + bit le = !le(x, y); + bit lt = !lt(x, y); + bit ge = !ge(x, y); + bit gt = !gt(x, y); +} + +def A0 : A<-3, -3>; +def A1 : A<-1, 4>; +def A2 : A<3, -2>; +def A3 : A<4, 2>;