[llvm-commits] [llvm] r121666 - in /llvm/trunk: test/TableGen/if.td utils/TableGen/Record.cpp utils/TableGen/Record.h utils/TableGen/TGParser.cpp

Bill Wendling isanbard at gmail.com
Sun Dec 12 17:46:19 PST 2010


Author: void
Date: Sun Dec 12 19:46:19 2010
New Revision: 121666

URL: http://llvm.org/viewvc/llvm-project?rev=121666&view=rev
Log:
Add support for using the `!if' operator when initializing variables:

  class A<bit a, bits<3> x, bits<3> y> {
    bits<3> z;
    let z = !if(a, x, y);
  }

The variable z will get the value of x when 'a' is 1 and 'y' when a is '0'.

Modified:
    llvm/trunk/test/TableGen/if.td
    llvm/trunk/utils/TableGen/Record.cpp
    llvm/trunk/utils/TableGen/Record.h
    llvm/trunk/utils/TableGen/TGParser.cpp

Modified: llvm/trunk/test/TableGen/if.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/TableGen/if.td?rev=121666&r1=121665&r2=121666&view=diff
==============================================================================
--- llvm/trunk/test/TableGen/if.td (original)
+++ llvm/trunk/test/TableGen/if.td Sun Dec 12 19:46:19 2010
@@ -1,14 +1,38 @@
-// RUN: tblgen %s | grep {\\\[1, 2, 3\\\]} | count 4
-// RUN: tblgen %s | grep {\\\[4, 5, 6\\\]} | count 2
+// RUN: tblgen %s | FileCheck %s
 // XFAIL: vg_leak
 
+// Support for an `!if' operator as part of a `let' statement.
+// CHECK:      class C
+// CHECK-NEXT: bits<16> n = { ?, ?, ?, ?, ?, ?, ?, !if({ C:x{2} }, 0, 1), !if({ C:x{2} }, 1, 1), !if({ C:x{2} }, 0, 0), !if({ C:x{1} }, C:y{3}, 0), !if({ C:x{1} }, C:y{2}, 1), !if({ C:x{0} }, C:y{3}, C:z), !if({ C:x{0} }, C:y{2}, C:y{2}), !if({ C:x{0} }, C:y{1}, C:y{1}), !if({ C:x{0} }, C:y{0}, C:y{0}) };
+class C<bits<3> x, bits<4> y, bit z> {
+  bits<16> n;
+
+  let n{8-6} = !if(x{2}, 0b010, 0b110);
+  let n{5-4} = !if(x{1}, y{3-2}, {0, 1});
+  let n{3-0} = !if(x{0}, y{3-0}, {z, y{2}, y{1}, y{0}});
+}
+
+// CHECK:      def One
+// CHECK-NEXT: list<int> first = [1, 2, 3];
+// CHECK-NEXT: list<int> rest = [1, 2, 3];
+
+// CHECK:      def OneB
+// CHECK-NEXT: list<int> vals = [1, 2, 3];
+
+// CHECK:      def Two
+// CHECK-NEXT: list<int> first = [1, 2, 3];
+// CHECK-NEXT: list<int> rest = [4, 5, 6];
+
+// CHECK:      def TwoB
+// CHECK-NEXT: list<int> vals = [4, 5, 6];
+
 class A<list<list<int>> vals> {
   list<int> first = vals[0];
   list<int> rest  = !if(!null(!cdr(vals)), vals[0], vals[1]);
 }
 
 def One : A<[[1,2,3]]>;
-def Two : A<[[1,2,3],[4,5,6]]>;
+def Two : A<[[1,2,3], [4,5,6]]>;
 
 class B<list<int> v> {
   list<int> vals = v;

Modified: llvm/trunk/utils/TableGen/Record.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/Record.cpp?rev=121666&r1=121665&r2=121666&view=diff
==============================================================================
--- llvm/trunk/utils/TableGen/Record.cpp (original)
+++ llvm/trunk/utils/TableGen/Record.cpp Sun Dec 12 19:46:19 2010
@@ -65,19 +65,27 @@
   return Ret;
 }
 
-// convertValue from Int initializer to bits type: Split the integer up into the
-// appropriate bits.
-//
+/// canFitInBitfield - Return true if the number of bits is large enough to hold
+/// the integer value.
+static bool canFitInBitfield(int64_t Value, unsigned NumBits) {
+  if (Value >= 0) {
+    if (Value & ~((1LL << NumBits) - 1))
+      return false;
+  } else if ((Value >> NumBits) != -1 || (Value & (1LL << (NumBits-1))) == 0) {
+    return false;
+  }
+
+  return true;
+}
+
+/// convertValue from Int initializer to bits type: Split the integer up into the
+/// appropriate bits.
+///
 Init *BitsRecTy::convertValue(IntInit *II) {
   int64_t Value = II->getValue();
   // Make sure this bitfield is large enough to hold the integer value.
-  if (Value >= 0) {
-    if (Value & ~((1LL << Size)-1))
-      return 0;
-  } else {
-    if ((Value >> Size) != -1 || ((Value & (1LL << (Size-1))) == 0))
-      return 0;
-  }
+  if (!canFitInBitfield(Value, Size))
+    return 0;
 
   BitsInit *Ret = new BitsInit(Size);
   for (unsigned i = 0; i != Size; ++i)
@@ -101,12 +109,56 @@
         Ret->setBit(i, new VarBitInit(VI, i));
       return Ret;
     }
+
   if (Size == 1 && dynamic_cast<BitRecTy*>(VI->getType())) {
     BitsInit *Ret = new BitsInit(1);
     Ret->setBit(0, VI);
     return Ret;
   }
 
+  if (TernOpInit *Tern = dynamic_cast<TernOpInit*>(VI)) {
+    if (Tern->getOpcode() == TernOpInit::IF) {
+      Init *LHS = Tern->getLHS();
+      Init *MHS = Tern->getMHS();
+      Init *RHS = Tern->getRHS();
+
+      IntInit *MHSi = dynamic_cast<IntInit*>(MHS);
+      IntInit *RHSi = dynamic_cast<IntInit*>(RHS);
+
+      if (MHSi && RHSi) {
+        int64_t MHSVal = MHSi->getValue();
+        int64_t RHSVal = RHSi->getValue();
+
+        if (canFitInBitfield(MHSVal, Size) && canFitInBitfield(RHSVal, Size)) {
+          BitsInit *Ret = new BitsInit(Size);
+
+          for (unsigned i = 0; i != Size; ++i)
+            Ret->setBit(i, new TernOpInit(TernOpInit::IF, LHS,
+                                          new IntInit((MHSVal & (1LL << i)) ? 1 : 0),
+                                          new IntInit((RHSVal & (1LL << i)) ? 1 : 0),
+                                          VI->getType()));
+
+          return Ret;
+        }
+      } else {
+        BitsInit *MHSbs = dynamic_cast<BitsInit*>(MHS);
+        BitsInit *RHSbs = dynamic_cast<BitsInit*>(RHS);
+
+        if (MHSbs && RHSbs) {
+          BitsInit *Ret = new BitsInit(Size);
+
+          for (unsigned i = 0; i != Size; ++i)
+            Ret->setBit(i, new TernOpInit(TernOpInit::IF, LHS,
+                                          MHSbs->getBit(i),
+                                          RHSbs->getBit(i),
+                                          VI->getType()));
+
+          return Ret;
+        }
+      }
+    }
+  }
+
   return 0;
 }
 

Modified: llvm/trunk/utils/TableGen/Record.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/Record.h?rev=121666&r1=121665&r2=121666&view=diff
==============================================================================
--- llvm/trunk/utils/TableGen/Record.h (original)
+++ llvm/trunk/utils/TableGen/Record.h Sun Dec 12 19:46:19 2010
@@ -931,6 +931,8 @@
   // possible to fold.
   Init *Fold(Record *CurRec, MultiClass *CurMultiClass);
 
+  virtual bool isComplete() const { return false; }
+
   virtual Init *resolveReferences(Record &R, const RecordVal *RV);
 
   virtual std::string getAsString() const;

Modified: llvm/trunk/utils/TableGen/TGParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/TGParser.cpp?rev=121666&r1=121665&r2=121666&view=diff
==============================================================================
--- llvm/trunk/utils/TableGen/TGParser.cpp (original)
+++ llvm/trunk/utils/TableGen/TGParser.cpp Sun Dec 12 19:46:19 2010
@@ -868,7 +868,6 @@
     TernOpInit::TernaryOp Code;
     RecTy *Type = 0;
 
-
     tgtok::TokKind LexCode = Lex.getCode();
     Lex.Lex();  // eat the operation
     switch (LexCode) {
@@ -919,16 +918,45 @@
     switch (LexCode) {
     default: assert(0 && "Unhandled code!");
     case tgtok::XIf: {
-      TypedInit *MHSt = dynamic_cast<TypedInit *>(MHS);
-      TypedInit *RHSt = dynamic_cast<TypedInit *>(RHS);
-      if (MHSt == 0 || RHSt == 0) {
+      // FIXME: The `!if' operator doesn't handle non-TypedInit well at
+      // all. This can be made much more robust.
+      TypedInit *MHSt = dynamic_cast<TypedInit*>(MHS);
+      TypedInit *RHSt = dynamic_cast<TypedInit*>(RHS);
+
+      RecTy *MHSTy = 0;
+      RecTy *RHSTy = 0;
+
+      if (MHSt == 0 && RHSt == 0) {
+        BitsInit *MHSbits = dynamic_cast<BitsInit*>(MHS);
+        BitsInit *RHSbits = dynamic_cast<BitsInit*>(RHS);
+
+        if (MHSbits && RHSbits &&
+            MHSbits->getNumBits() == RHSbits->getNumBits()) {
+          Type = new BitRecTy();
+          break;
+        } else {
+          BitInit *MHSbit = dynamic_cast<BitInit*>(MHS);
+          BitInit *RHSbit = dynamic_cast<BitInit*>(RHS);
+
+          if (MHSbit && RHSbit) {
+            Type = new BitRecTy();
+            break;
+          }
+        }
+      } else if (MHSt != 0 && RHSt != 0) {
+        MHSTy = MHSt->getType();
+        RHSTy = RHSt->getType();
+      }
+
+      if (!MHSTy || !RHSTy) {
         TokError("could not get type for !if");
         return 0;
       }
-      if (MHSt->getType()->typeIsConvertibleTo(RHSt->getType())) {
-        Type = RHSt->getType();
-      } else if (RHSt->getType()->typeIsConvertibleTo(MHSt->getType())) {
-        Type = MHSt->getType();
+
+      if (MHSTy->typeIsConvertibleTo(RHSTy)) {
+        Type = RHSTy;
+      } else if (RHSTy->typeIsConvertibleTo(MHSTy)) {
+        Type = MHSTy;
       } else {
         TokError("inconsistent types for !if");
         return 0;





More information about the llvm-commits mailing list