[llvm] r352185 - [TblGen] Extend !if semantics through new feature !cond

Javed Absar via llvm-commits llvm-commits at lists.llvm.org
Fri Jan 25 02:25:25 PST 2019


Author: javed.absar
Date: Fri Jan 25 02:25:25 2019
New Revision: 352185

URL: http://llvm.org/viewvc/llvm-project?rev=352185&view=rev
Log:
[TblGen] Extend !if semantics through new feature !cond

This patch extends TableGen language with !cond operator.
Instead of embedding !if inside !if which can get cumbersome,
one can now use !cond.
Below is an example to convert an integer 'x' into a string:

    !cond(!lt(x,0) : "Negative",
          !eq(x,0) : "Zero",
          !eq(x,1) : "One,
          1        : "MoreThanOne")

Reviewed By: hfinkel, simon_tatham, greened
Differential Revision: https://reviews.llvm.org/D55758



Added:
    llvm/trunk/test/TableGen/cond-bitlist.td
    llvm/trunk/test/TableGen/cond-default.td
    llvm/trunk/test/TableGen/cond-empty-list-arg.td
    llvm/trunk/test/TableGen/cond-inheritance.td
    llvm/trunk/test/TableGen/cond-let.td
    llvm/trunk/test/TableGen/cond-list.td
    llvm/trunk/test/TableGen/cond-subclass.td
    llvm/trunk/test/TableGen/cond-type.td
    llvm/trunk/test/TableGen/cond-usage.td
    llvm/trunk/test/TableGen/condsbit.td
Modified:
    llvm/trunk/docs/TableGen/LangIntro.rst
    llvm/trunk/docs/TableGen/LangRef.rst
    llvm/trunk/include/llvm/TableGen/Record.h
    llvm/trunk/lib/TableGen/Record.cpp
    llvm/trunk/lib/TableGen/TGLexer.cpp
    llvm/trunk/lib/TableGen/TGLexer.h
    llvm/trunk/lib/TableGen/TGParser.cpp
    llvm/trunk/lib/TableGen/TGParser.h

Modified: llvm/trunk/docs/TableGen/LangIntro.rst
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/TableGen/LangIntro.rst?rev=352185&r1=352184&r2=352185&view=diff
==============================================================================
--- llvm/trunk/docs/TableGen/LangIntro.rst (original)
+++ llvm/trunk/docs/TableGen/LangIntro.rst Fri Jan 25 02:25:25 2019
@@ -258,6 +258,20 @@ supported include:
 ``!if(a,b,c)``
   'b' if the result of 'int' or 'bit' operator 'a' is nonzero, 'c' otherwise.
 
+``!cond(condition_1 : val1, condition_2 : val2, ..., condition_n : valn)``
+    Instead of embedding !if inside !if which can get cumbersome,
+    one can use !cond. !cond returns 'val1' if the result of 'int' or 'bit'
+    operator 'condition1' is nonzero. Otherwise, it checks 'condition2'.
+    If 'condition2' is nonzero, returns 'val2', and so on.
+    If all conditions are zero, it reports an error.
+
+    Below is an example to convert an integer 'x' into a string:
+
+    !cond(!lt(x,0) : "Negative",
+          !eq(x,0) : "Zero",
+          !eq(x,1) : "One,
+          1        : "MoreThanOne")
+
 ``!eq(a,b)``
     'bit 1' if string a is equal to string b, 0 otherwise.  This only operates
     on string, int and bit objects.  Use !cast<string> to compare other types of

Modified: llvm/trunk/docs/TableGen/LangRef.rst
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/TableGen/LangRef.rst?rev=352185&r1=352184&r2=352185&view=diff
==============================================================================
--- llvm/trunk/docs/TableGen/LangRef.rst (original)
+++ llvm/trunk/docs/TableGen/LangRef.rst Fri Jan 25 02:25:25 2019
@@ -102,6 +102,12 @@ wide variety of meanings:
                :!isa    !dag     !le      !lt        !ge
                :!gt     !ne
 
+TableGen also has !cond operator that needs a slightly different
+syntax compared to other "bang operators":
+
+.. productionlist::
+   CondOperator: !cond
+
 
 Syntax
 ======
@@ -140,7 +146,7 @@ considered to define the class if any of
 #. The :token:`Body` in the :token:`ObjectBody` is present and is not empty.
 #. The :token:`BaseClassList` in the :token:`ObjectBody` is present.
 
-You can declare an empty class by giving and empty :token:`TemplateArgList`
+You can declare an empty class by giving an empty :token:`TemplateArgList`
 and an empty :token:`ObjectBody`. This can serve as a restricted form of
 forward declaration: note that records deriving from the forward-declared
 class will inherit no fields from it since the record expansion is done
@@ -315,6 +321,8 @@ The initial :token:`DagArg` is called th
 
 .. productionlist::
    SimpleValue: `BangOperator` ["<" `Type` ">"] "(" `ValueListNE` ")"
+              :| `CondOperator` "(" `CondVal` ("," `CondVal`)* ")"
+   CondVal: `Value` ":" `Value`
 
 Bodies
 ------

Modified: llvm/trunk/include/llvm/TableGen/Record.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/TableGen/Record.h?rev=352185&r1=352184&r2=352185&view=diff
==============================================================================
--- llvm/trunk/include/llvm/TableGen/Record.h (original)
+++ llvm/trunk/include/llvm/TableGen/Record.h Fri Jan 25 02:25:25 2019
@@ -315,6 +315,7 @@ protected:
     IK_TernOpInit,
     IK_UnOpInit,
     IK_LastOpInit,
+    IK_CondOpInit,
     IK_FoldOpInit,
     IK_IsAOpInit,
     IK_StringInit,
@@ -911,6 +912,83 @@ public:
   std::string getAsString() const override;
 };
 
+/// !cond(condition_1: value1, ... , condition_n: value)
+/// Selects the first value for which condition is true.
+/// Otherwise reports an error.
+class CondOpInit final : public TypedInit, public FoldingSetNode,
+                      public TrailingObjects<CondOpInit, Init *> {
+  unsigned NumConds;
+  RecTy *ValType;
+
+  CondOpInit(unsigned NC, RecTy *Type)
+    : TypedInit(IK_CondOpInit, Type),
+      NumConds(NC), ValType(Type) {}
+
+  size_t numTrailingObjects(OverloadToken<Init *>) const {
+    return 2*NumConds;
+  }
+
+public:
+  CondOpInit(const CondOpInit &) = delete;
+  CondOpInit &operator=(const CondOpInit &) = delete;
+
+  static bool classof(const Init *I) {
+    return I->getKind() == IK_CondOpInit;
+  }
+
+  static CondOpInit *get(ArrayRef<Init*> C, ArrayRef<Init*> V,
+                        RecTy *Type);
+
+  void Profile(FoldingSetNodeID &ID) const;
+
+  RecTy *getValType() const { return ValType; }
+
+  unsigned getNumConds() const { return NumConds; }
+
+  Init *getCond(unsigned Num) const {
+    assert(Num < NumConds && "Condition number out of range!");
+    return getTrailingObjects<Init *>()[Num];
+  }
+
+  Init *getVal(unsigned Num) const {
+    assert(Num < NumConds && "Val number out of range!");
+    return getTrailingObjects<Init *>()[Num+NumConds];
+  }
+
+  ArrayRef<Init *> getConds() const {
+    return makeArrayRef(getTrailingObjects<Init *>(), NumConds);
+  }
+
+  ArrayRef<Init *> getVals() const {
+    return makeArrayRef(getTrailingObjects<Init *>()+NumConds, NumConds);
+  }
+
+  Init *Fold(Record *CurRec) const;
+
+  Init *resolveReferences(Resolver &R) const override;
+
+  bool isConcrete() const override;
+  bool isComplete() const override;
+  std::string getAsString() const override;
+
+  using const_case_iterator = SmallVectorImpl<Init*>::const_iterator;
+  using const_val_iterator = SmallVectorImpl<Init*>::const_iterator;
+
+  inline const_case_iterator  arg_begin() const { return getConds().begin(); }
+  inline const_case_iterator  arg_end  () const { return getConds().end(); }
+
+  inline size_t              case_size () const { return NumConds; }
+  inline bool                case_empty() const { return NumConds == 0; }
+
+  inline const_val_iterator name_begin() const { return getVals().begin();}
+  inline const_val_iterator name_end  () const { return getVals().end(); }
+
+  inline size_t              val_size () const { return NumConds; }
+  inline bool                val_empty() const { return NumConds == 0; }
+
+  Init *getBit(unsigned Bit) const override;
+};
+
 /// !foldl (a, b, expr, start, lst) - Fold over a list.
 class FoldOpInit : public TypedInit, public FoldingSetNode {
 private:

Modified: llvm/trunk/lib/TableGen/Record.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/TableGen/Record.cpp?rev=352185&r1=352184&r2=352185&view=diff
==============================================================================
--- llvm/trunk/lib/TableGen/Record.cpp (original)
+++ llvm/trunk/lib/TableGen/Record.cpp Fri Jan 25 02:25:25 2019
@@ -1693,6 +1693,137 @@ Init *FieldInit::Fold(Record *CurRec) co
   return const_cast<FieldInit *>(this);
 }
 
+static void ProfileCondOpInit(FoldingSetNodeID &ID,
+                             ArrayRef<Init *> CondRange,
+                             ArrayRef<Init *> ValRange,
+                             const RecTy *ValType) {
+  assert(CondRange.size() == ValRange.size() &&
+         "Number of conditions and values must match!");
+  ID.AddPointer(ValType);
+  ArrayRef<Init *>::iterator Case = CondRange.begin();
+  ArrayRef<Init *>::iterator Val = ValRange.begin();
+
+  while (Case != CondRange.end()) {
+    ID.AddPointer(*Case++);
+    ID.AddPointer(*Val++);
+  }
+}
+
+void CondOpInit::Profile(FoldingSetNodeID &ID) const {
+  ProfileCondOpInit(ID,
+      makeArrayRef(getTrailingObjects<Init *>(), NumConds),
+      makeArrayRef(getTrailingObjects<Init *>() + NumConds, NumConds),
+      ValType);
+}
+
+CondOpInit *
+CondOpInit::get(ArrayRef<Init *> CondRange,
+                ArrayRef<Init *> ValRange, RecTy *Ty) {
+  assert(CondRange.size() == ValRange.size() &&
+         "Number of conditions and values must match!");
+
+  static FoldingSet<CondOpInit> ThePool;
+  FoldingSetNodeID ID;
+  ProfileCondOpInit(ID, CondRange, ValRange, Ty);
+
+  void *IP = nullptr;
+  if (CondOpInit *I = ThePool.FindNodeOrInsertPos(ID, IP))
+    return I;
+
+  void *Mem = Allocator.Allocate(totalSizeToAlloc<Init *>(2*CondRange.size()),
+                                 alignof(BitsInit));
+  CondOpInit *I = new(Mem) CondOpInit(CondRange.size(), Ty);
+
+  std::uninitialized_copy(CondRange.begin(), CondRange.end(),
+                          I->getTrailingObjects<Init *>());
+  std::uninitialized_copy(ValRange.begin(), ValRange.end(),
+                          I->getTrailingObjects<Init *>()+CondRange.size());
+  ThePool.InsertNode(I, IP);
+  return I;
+}
+
+Init *CondOpInit::resolveReferences(Resolver &R) const {
+  SmallVector<Init*, 4> NewConds;
+  bool Changed = false;
+  for (const Init *Case : getConds()) {
+    Init *NewCase = Case->resolveReferences(R);
+    NewConds.push_back(NewCase);
+    Changed |= NewCase != Case;
+  }
+
+  SmallVector<Init*, 4> NewVals;
+  for (const Init *Val : getVals()) {
+    Init *NewVal = Val->resolveReferences(R);
+    NewVals.push_back(NewVal);
+    Changed |= NewVal != Val;
+  }
+
+  if (Changed)
+    return (CondOpInit::get(NewConds, NewVals,
+            getValType()))->Fold(R.getCurrentRecord());
+
+  return const_cast<CondOpInit *>(this);
+}
+
+Init *CondOpInit::Fold(Record *CurRec) const {
+  for ( unsigned i = 0; i < NumConds; ++i) {
+    Init *Cond = getCond(i);
+    Init *Val = getVal(i);
+
+    if (IntInit *CondI = dyn_cast_or_null<IntInit>(
+            Cond->convertInitializerTo(IntRecTy::get()))) {
+      if (CondI->getValue())
+        return Val->convertInitializerTo(getValType());
+    } else
+     return const_cast<CondOpInit *>(this);
+  }
+
+  PrintFatalError(CurRec->getLoc(),
+                  CurRec->getName() +
+                  " does not have any true condition in:" +
+                  this->getAsString());
+  return nullptr;
+}
+
+bool CondOpInit::isConcrete() const {
+  for (const Init *Case : getConds())
+    if (!Case->isConcrete())
+      return false;
+
+  for (const Init *Val : getVals())
+    if (!Val->isConcrete())
+      return false;
+
+  return true;
+}
+
+bool CondOpInit::isComplete() const {
+  for (const Init *Case : getConds())
+    if (!Case->isComplete())
+      return false;
+
+  for (const Init *Val : getVals())
+    if (!Val->isConcrete())
+      return false;
+
+  return true;
+}
+
+std::string CondOpInit::getAsString() const {
+  std::string Result = "!cond(";
+  for (unsigned i = 0; i < getNumConds(); i++) {
+    Result += getCond(i)->getAsString() + ": ";
+    Result += getVal(i)->getAsString();
+    if (i != getNumConds()-1)
+      Result += ", ";
+  }
+  return Result + ")";
+}
+
+Init *CondOpInit::getBit(unsigned Bit) const {
+  return VarBitInit::get(const_cast<CondOpInit *>(this), Bit);
+}
+
 static void ProfileDagInit(FoldingSetNodeID &ID, Init *V, StringInit *VN,
                            ArrayRef<Init *> ArgRange,
                            ArrayRef<StringInit *> NameRange) {

Modified: llvm/trunk/lib/TableGen/TGLexer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/TableGen/TGLexer.cpp?rev=352185&r1=352184&r2=352185&view=diff
==============================================================================
--- llvm/trunk/lib/TableGen/TGLexer.cpp (original)
+++ llvm/trunk/lib/TableGen/TGLexer.cpp Fri Jan 25 02:25:25 2019
@@ -544,6 +544,7 @@ tgtok::TokKind TGLexer::LexExclaim() {
     .Case("ge", tgtok::XGe)
     .Case("gt", tgtok::XGt)
     .Case("if", tgtok::XIf)
+    .Case("cond", tgtok::XCond)
     .Case("isa", tgtok::XIsA)
     .Case("head", tgtok::XHead)
     .Case("tail", tgtok::XTail)

Modified: llvm/trunk/lib/TableGen/TGLexer.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/TableGen/TGLexer.h?rev=352185&r1=352184&r2=352185&view=diff
==============================================================================
--- llvm/trunk/lib/TableGen/TGLexer.h (original)
+++ llvm/trunk/lib/TableGen/TGLexer.h Fri Jan 25 02:25:25 2019
@@ -50,7 +50,7 @@ namespace tgtok {
 
     // !keywords.
     XConcat, XADD, XAND, XOR, XSRA, XSRL, XSHL, XListConcat, XStrConcat, XCast,
-    XSubst, XForEach, XFoldl, XHead, XTail, XSize, XEmpty, XIf, XEq, XIsA, XDag,
+    XSubst, XForEach, XFoldl, XHead, XTail, XSize, XEmpty, XIf, XCond, XEq, XIsA, XDag,
     XNe, XLe, XLt, XGe, XGt,
 
     // Integer value.

Modified: llvm/trunk/lib/TableGen/TGParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/TableGen/TGParser.cpp?rev=352185&r1=352184&r2=352185&view=diff
==============================================================================
--- llvm/trunk/lib/TableGen/TGParser.cpp (original)
+++ llvm/trunk/lib/TableGen/TGParser.cpp Fri Jan 25 02:25:25 2019
@@ -1444,6 +1444,9 @@ Init *TGParser::ParseOperation(Record *C
     return (TernOpInit::get(Code, LHS, MHS, RHS, Type))->Fold(CurRec);
   }
 
+  case tgtok::XCond:
+    return ParseOperationCond(CurRec, ItemType);
+
   case tgtok::XFoldl: {
     // Value ::= !foldl '(' Id ',' Id ',' Value ',' Value ',' Value ')'
     Lex.Lex(); // eat the operation
@@ -1602,6 +1605,91 @@ RecTy *TGParser::ParseOperatorType() {
   return Type;
 }
 
+Init *TGParser::ParseOperationCond(Record *CurRec, RecTy *ItemType) {
+  Lex.Lex();  // eat the operation 'cond'
+
+  if (Lex.getCode() != tgtok::l_paren) {
+     TokError("expected '(' after !cond operator");
+     return nullptr;
+  }
+  Lex.Lex();  // eat the '('
+
+  // Parse through '[Case: Val,]+'
+  SmallVector<Init *, 4> Case;
+  SmallVector<Init *, 4> Val;
+  while (true) {
+    if (Lex.getCode() == tgtok::r_paren) {
+      Lex.Lex(); // eat the ')'
+      break;
+    }
+
+    Init *V = ParseValue(CurRec);
+    if (!V)
+      return nullptr;
+    Case.push_back(V);
+
+    if (Lex.getCode() != tgtok::colon) {
+      TokError("expected ':'  following a condition in !cond operator");
+      return nullptr;
+    }
+    Lex.Lex(); // eat the ':'
+
+    V = ParseValue(CurRec, ItemType);
+    if (!V)
+      return nullptr;
+    Val.push_back(V);
+
+    if (Lex.getCode() == tgtok::r_paren) {
+      Lex.Lex(); // eat the ')'
+      break;
+    }
+
+    if (Lex.getCode() != tgtok::comma) {
+      TokError("expected ',' or ')' following a value in !cond operator");
+      return nullptr;
+    }
+    Lex.Lex();  // eat the ','
+  }
+
+  if (Case.size() < 1) {
+    TokError("there should be at least 1 'condition : value' in the !cond operator");
+    return nullptr;
+  }
+
+  // resolve type
+  RecTy *Type = nullptr;
+  for (Init *V : Val) {
+    RecTy *VTy = nullptr;
+    if (TypedInit *Vt = dyn_cast<TypedInit>(V))
+      VTy = Vt->getType();
+    if (BitsInit *Vbits = dyn_cast<BitsInit>(V))
+      VTy = BitsRecTy::get(Vbits->getNumBits());
+    if (isa<BitInit>(V))
+      VTy = BitRecTy::get();
+
+    if (Type == nullptr) {
+      if (!isa<UnsetInit>(V))
+        Type = VTy;
+    } else {
+      if (!isa<UnsetInit>(V)) {
+        RecTy *RType = resolveTypes(Type, VTy);
+        if (!RType) {
+          TokError(Twine("inconsistent types '") + Type->getAsString() +
+                         "' and '" + VTy->getAsString() + "' for !cond");
+          return nullptr;
+        }
+        Type = RType;
+      }
+    }
+  }
+
+  if (!Type) {
+    TokError("could not determine type for !cond from its arguments");
+    return nullptr;
+  }
+  return CondOpInit::get(Case, Val, Type)->Fold(CurRec);
+}
+
 /// ParseSimpleValue - Parse a tblgen value.  This returns null on error.
 ///
 ///   SimpleValue ::= IDValue
@@ -1620,6 +1708,7 @@ RecTy *TGParser::ParseOperatorType() {
 ///   SimpleValue ::= SRLTOK '(' Value ',' Value ')'
 ///   SimpleValue ::= LISTCONCATTOK '(' Value ',' Value ')'
 ///   SimpleValue ::= STRCONCATTOK '(' Value ',' Value ')'
+///   SimpleValue ::= COND '(' [Value ':' Value,]+ ')'
 ///
 Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType,
                                  IDParseMode Mode) {
@@ -1932,6 +2021,7 @@ Init *TGParser::ParseSimpleValue(Record
   case tgtok::XListConcat:
   case tgtok::XStrConcat:   // Value ::= !binop '(' Value ',' Value ')'
   case tgtok::XIf:
+  case tgtok::XCond:
   case tgtok::XFoldl:
   case tgtok::XForEach:
   case tgtok::XSubst: {  // Value ::= !ternop '(' Value ',' Value ',' Value ')'

Modified: llvm/trunk/lib/TableGen/TGParser.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/TableGen/TGParser.h?rev=352185&r1=352184&r2=352185&view=diff
==============================================================================
--- llvm/trunk/lib/TableGen/TGParser.h (original)
+++ llvm/trunk/lib/TableGen/TGParser.h Fri Jan 25 02:25:25 2019
@@ -193,6 +193,7 @@ private:  // Parser methods.
   bool ParseRangePiece(SmallVectorImpl<unsigned> &Ranges);
   RecTy *ParseType();
   Init *ParseOperation(Record *CurRec, RecTy *ItemType);
+  Init *ParseOperationCond(Record *CurRec, RecTy *ItemType);
   RecTy *ParseOperatorType();
   Init *ParseObjectName(MultiClass *CurMultiClass);
   Record *ParseClassID();

Added: llvm/trunk/test/TableGen/cond-bitlist.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/TableGen/cond-bitlist.td?rev=352185&view=auto
==============================================================================
--- llvm/trunk/test/TableGen/cond-bitlist.td (added)
+++ llvm/trunk/test/TableGen/cond-bitlist.td Fri Jan 25 02:25:25 2019
@@ -0,0 +1,27 @@
+// RUN: llvm-tblgen %s | FileCheck %s
+// XFAIL: vg_leak
+
+class S<int s> {
+  bits<2> val = !cond(!eq(s, 8):  {0, 0},
+                      !eq(s, 16): 0b01,
+                      !eq(s, 32): 2,
+                      !eq(s, 64): {1, 1},
+                              1 : ?);
+}
+
+def D8  : S<8>;
+def D16 : S<16>;
+def D32 : S<32>;
+def D64 : S<64>;
+def D128: S<128>;
+// CHECK: def D128
+// CHECK-NEXT: bits<2> val = { ?, ? };
+// CHECK: def D16
+// CHECK-NEXT: bits<2> val = { 0, 1 };
+// CHECK: def D32
+// CHECK-NEXT: bits<2> val = { 1, 0 };
+// CHECK: def D64
+// CHECK-NEXT: bits<2> val = { 1, 1 };
+// CHECK: def D8
+// CHECK-NEXT: bits<2> val = { 0, 0 };
+

Added: llvm/trunk/test/TableGen/cond-default.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/TableGen/cond-default.td?rev=352185&view=auto
==============================================================================
--- llvm/trunk/test/TableGen/cond-default.td (added)
+++ llvm/trunk/test/TableGen/cond-default.td Fri Jan 25 02:25:25 2019
@@ -0,0 +1,11 @@
+// Check that not specifying a valid condition results in error
+
+// RUN: not llvm-tblgen %s 2>&1 | FileCheck %s
+// XFAIL: vg_leak
+
+class C<int x> {
+  string s  = !cond(!lt(x,0) : "negative", !gt(x,0) : "positive");
+}
+
+def Zero : C<0>;
+//CHECK: error: Zero does not have any true condition in:!cond(0: "negative", 0: "positive")

Added: llvm/trunk/test/TableGen/cond-empty-list-arg.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/TableGen/cond-empty-list-arg.td?rev=352185&view=auto
==============================================================================
--- llvm/trunk/test/TableGen/cond-empty-list-arg.td (added)
+++ llvm/trunk/test/TableGen/cond-empty-list-arg.td Fri Jan 25 02:25:25 2019
@@ -0,0 +1,8 @@
+// RUN: llvm-tblgen %s
+// XFAIL: vg_leak
+
+class C<bit cond> {
+  bit true = 1;
+  list<int> X = !cond(cond: [1, 2, 3], true : []);
+  list<int> Y = !cond(cond: [], true : [4, 5, 6]);
+}

Added: llvm/trunk/test/TableGen/cond-inheritance.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/TableGen/cond-inheritance.td?rev=352185&view=auto
==============================================================================
--- llvm/trunk/test/TableGen/cond-inheritance.td (added)
+++ llvm/trunk/test/TableGen/cond-inheritance.td Fri Jan 25 02:25:25 2019
@@ -0,0 +1,22 @@
+// Make sure !cond gets propagated across multiple layers of inheritance.
+// RUN: llvm-tblgen %s | FileCheck %s
+// XFAIL: vg_leak
+
+class getInt<int c> {
+  int ret = !cond(c: 0, 1 : 1);
+}
+
+class I1<int c> {
+  int i = getInt<c>.ret;
+}
+
+class I2<int c> : I1<c>;
+
+def DI1: I1<1>;
+// CHECK: def DI1 {     // I1
+// CHECK-NEXT: int i = 0;
+
+// CHECK: def DI2 {     // I1 I2
+// CHECK-NEXT: int i = 0;
+def DI2: I2<1>;
+

Added: llvm/trunk/test/TableGen/cond-let.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/TableGen/cond-let.td?rev=352185&view=auto
==============================================================================
--- llvm/trunk/test/TableGen/cond-let.td (added)
+++ llvm/trunk/test/TableGen/cond-let.td Fri Jan 25 02:25:25 2019
@@ -0,0 +1,36 @@
+// Check support for `!cond' operator as part of a `let' statement.
+// RUN: llvm-tblgen %s | FileCheck %s
+// XFAIL: vg_leak
+
+
+class C<bits<3> x, bits<4> y, bit z> {
+  bits<16> n;
+
+  let n{11}  = !cond(y{3}: 1,
+                     y{2}: x{0},
+                     y{1}: x{1},
+                     y{0}: x{2},
+                     {1} :?);
+  let n{10-9}= !cond(x{2}: y{3-2},
+                     x{1}: y{2-1},
+                     x{1}: y{1-0},
+                     {1} : ?);
+  let n{8-6} = !cond(x{2}: 0b010,  1 : 0b110);
+  let n{5-4} = !cond(x{1}: y{3-2}, 1 :  {0, 1});
+  let n{3-0} = !cond(x{0}: y{3-0}, 1 : {z, y{2}, y{1}, y{0}});
+}
+
+
+def C1 : C<{1, 0, 1}, {0, 1, 0, 1}, 0>;
+def C2 : C<{0, 1, 0}, {1, 0, 1, 0}, 1>;
+def C3 : C<{0, 0, 0}, {1, 0, 1, 0}, 0>;
+def C4 : C<{0, 0, 0}, {0, 0, 0, 0}, 0>;
+
+// CHECK: def C1
+// CHECK-NEXT: bits<16> n = { ?, ?, ?, ?, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1 };
+// CHECK: def C2
+// CHECK-NEXT: bits<16> n = { ?, ?, ?, ?, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0 };
+// CHECK: def C3
+// CHECK-NEXT: bits<16> n = { ?, ?, ?, ?, 1, ?, ?, 1, 1, 0, 0, 1, 0, 0, 1, 0 };
+// CHECK: def C4
+// CHECK-NEXT: bits<16> n = { ?, ?, ?, ?, ?, ?, ?, 1, 1, 0, 0, 1, 0, 0, 0, 0 };

Added: llvm/trunk/test/TableGen/cond-list.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/TableGen/cond-list.td?rev=352185&view=auto
==============================================================================
--- llvm/trunk/test/TableGen/cond-list.td (added)
+++ llvm/trunk/test/TableGen/cond-list.td Fri Jan 25 02:25:25 2019
@@ -0,0 +1,38 @@
+// RUN: llvm-tblgen %s | FileCheck %s
+// XFAIL: vg_leak
+
+
+class A<list<list<int>> vals> {
+  list<int> first = vals[0];
+  list<int> rest  = !cond(!empty(!tail(vals)): vals[0],
+                          1                 : vals[1]);
+}
+
+def A_OneEl : A<[[1,2,3]]>;
+// CHECK:      def A_OneEl {  // A
+// CHECK-NEXT: list<int> first = [1, 2, 3];
+// CHECK-NEXT: list<int> rest = [1, 2, 3];
+// CHECK-NEXT: }
+
+def A_TwoEl : A<[[1,2,3], [4,5,6]]>;
+// CHECK:      def A_TwoEl { // A
+// CHECK-NEXT: list<int> first = [1, 2, 3];
+// CHECK-NEXT: list<int> rest = [4, 5, 6];
+// CHECK-NEXT: }
+
+
+class B<list<int> v> {
+  list<int> vals = v;
+}
+class BB<list<list<int>> vals> : B<!cond(!empty(!tail(vals)): vals[0],  1 : vals[1])>;
+class BBB<list<list<int>> vals> : BB<vals>;
+
+def B_OneEl : BBB<[[1,2,3]]>;
+// CHECK:      def B_OneEl { //  B BB BBB
+// CHECK-NEXT: list<int> vals = [1, 2, 3];
+// CHECK-NEXT: }
+
+def B_TwoEl : BBB<[[1,2,3],[4,5,6]]>;
+// CHECK:      def B_TwoEl { // B BB BBB
+// CHECK-NEXT: list<int> vals = [4, 5, 6];
+// CHECK-NEXT: }

Added: llvm/trunk/test/TableGen/cond-subclass.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/TableGen/cond-subclass.td?rev=352185&view=auto
==============================================================================
--- llvm/trunk/test/TableGen/cond-subclass.td (added)
+++ llvm/trunk/test/TableGen/cond-subclass.td Fri Jan 25 02:25:25 2019
@@ -0,0 +1,27 @@
+// Check that !cond with operands of different subtypes can
+// initialize a supertype variable.
+// RUN: llvm-tblgen %s | FileCheck %s
+// XFAIL: vg_leak
+
+class E<int dummy> {}
+class E1<int dummy> : E<dummy> {}
+class E2<int dummy> : E<dummy> {}
+
+class EX<int cc, E1 b, E2 c> {
+  E x = !cond(cc: b, 1 : c);
+}
+
+def E1d : E1<0>;
+def E2d : E2<0>;
+
+def EXd1 : EX<1, E1d, E2d>;
+def EXd2 : EX<0, E1d, E2d>;
+
+// CHECK: def EXd1 {
+// CHECK:   E x = E1d;
+// CHECK: }
+//
+// CHECK: def EXd2 {
+// CHECK:   E x = E2d;
+// CHECK: }
+

Added: llvm/trunk/test/TableGen/cond-type.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/TableGen/cond-type.td?rev=352185&view=auto
==============================================================================
--- llvm/trunk/test/TableGen/cond-type.td (added)
+++ llvm/trunk/test/TableGen/cond-type.td Fri Jan 25 02:25:25 2019
@@ -0,0 +1,11 @@
+// RUN: not llvm-tblgen %s 2>&1 | FileCheck %s
+// XFAIL: vg_leak
+
+class A<int dummy> {}
+class B<int dummy> : A<dummy> {}
+class C<int dummy> : A<dummy> {}
+
+// CHECK: Value 'x' of type 'C' is incompatible with initializer '{{.*}}' of type 'A'
+class X<int cc, B b, C c> {
+  C x = !cond(cc: b, 1 : c);
+}

Added: llvm/trunk/test/TableGen/cond-usage.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/TableGen/cond-usage.td?rev=352185&view=auto
==============================================================================
--- llvm/trunk/test/TableGen/cond-usage.td (added)
+++ llvm/trunk/test/TableGen/cond-usage.td Fri Jan 25 02:25:25 2019
@@ -0,0 +1,29 @@
+// RUN: llvm-tblgen %s | FileCheck %s
+// XFAIL: vg_leak
+
+// Check that !cond picks the first true value
+// CHECK:       class A
+// CHECK-NEXT:  string S = !cond(!eq(A:x, 10): "ten", !eq(A:x, 11): "eleven", !eq(A:x, 10): "TEN", !gt(A:x, 9): "MoreThanNine", 1: "unknown"); 
+// CHECK: B1
+// CHECK-NEXT: string S = "unknown"
+// CHECK: B10
+// CHECK-NEXT: string S = "ten";
+// CHECK: def B11
+// CHECK-NEXT: string S = "eleven";
+// CHECK: def B12
+// CHECK-NEXT:  string S = "MoreThanNine";
+// CHECK: def B9
+// CHECK-NEXT: string S = "unknown"
+
+class A<int x> {
+  string S = !cond(!eq(x,10) : "ten",
+                   !eq(x,11) : "eleven",
+                   !eq(x,10) : "TEN",
+                   !gt(x,9) : "MoreThanNine",
+                   !eq(1,1) : "unknown");
+}
+def B1  : A<1>;
+def B9  : A<9>;
+def B10 : A<10>;
+def B11 : A<11>;
+def B12 : A<12>;

Added: llvm/trunk/test/TableGen/condsbit.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/TableGen/condsbit.td?rev=352185&view=auto
==============================================================================
--- llvm/trunk/test/TableGen/condsbit.td (added)
+++ llvm/trunk/test/TableGen/condsbit.td Fri Jan 25 02:25:25 2019
@@ -0,0 +1,15 @@
+// check that !cond works well with bit conditional values
+// RUN: llvm-tblgen %s | FileCheck %s
+// XFAIL: vg_leak
+// CHECK: a = 6
+// CHECK: a = 5
+
+class A<bit b = 1> {
+  bit true = 1;
+  int a = !cond(b: 5, true : 6);
+  bit c = !cond(b: 0, true : 1);
+  bits<1> d = !cond(b: 0, true : 1);
+}
+
+def X : A<0>;
+def Y : A;




More information about the llvm-commits mailing list