Packed types, brought to you by Brad Jones
authorBrian Gaeke <gaeke@uiuc.edu>
Fri, 20 Aug 2004 06:00:58 +0000 (06:00 +0000)
committerBrian Gaeke <gaeke@uiuc.edu>
Fri, 20 Aug 2004 06:00:58 +0000 (06:00 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@15938 91177308-0d34-0410-b5e6-96231b3b80d8

15 files changed:
docs/BytecodeFormat.html
include/llvm/Bytecode/BytecodeHandler.h
include/llvm/Constants.h
include/llvm/DerivedTypes.h
include/llvm/Type.def
include/llvm/Type.h
lib/AsmParser/llvmAsmParser.y
lib/Bytecode/Reader/Analyzer.cpp
lib/Bytecode/Reader/Reader.cpp
lib/Bytecode/Writer/Writer.cpp
lib/VMCore/AsmWriter.cpp
lib/VMCore/Constants.cpp
lib/VMCore/Instructions.cpp
lib/VMCore/Type.cpp
lib/VMCore/Verifier.cpp

index 51b56463bce1c0b20af3aaa73da1a3c8e477ae48..33450231125da9817ff650dcc61b9ce1da65a8c6 100644 (file)
@@ -888,6 +888,27 @@ missing otherwise.</td>
     </tr>
   </tbody>
 </table>
+<h3>Packed Types</h3>
+<table>
+  <tbody>
+    <tr>
+      <th><b>Type</b></th>
+      <th class="td_left"><b>Description</b></th>
+    </tr>
+    <tr>
+      <td><a href="#uint24_vbr">uint24_vbr</a></td>
+      <td class="td_left">Type ID for Packed Types (18)</td>
+    </tr>
+    <tr>
+      <td><a href="#uint24_vbr">uint24_vbr</a></td>
+      <td class="td_left">Slot number of packed vector's element type.</td>
+    </tr>
+    <tr>
+      <td><a href="#uint32_vbr">uint32_vbr</a></td>
+      <td class="td_left">The number of elements in the packed vector.</td>
+    </tr>
+  </tbody>
+</table>
 </div>
 <!-- _______________________________________________________________________ -->
 <div class="doc_subsection"><a name="globalinfo">Module Global Info</a>
index 687bf806e0eec2be74ace877a7c7b05d8b8f607b..5a022a04c09e3ef737ea96543f73ebb2defabb96 100644 (file)
@@ -23,6 +23,7 @@ namespace llvm {
 class ArrayType;
 class StructType;
 class PointerType;
+class PackedType;
 class ConstantArray;
 class Module;
 
@@ -250,6 +251,14 @@ public:
     Constant* Val                       ///< The constant value
   ) {}
 
+  /// @brief Handle a constant packed
+  virtual void handleConstantPacked( 
+    const PackedType* PT,                ///< Type of the array
+    std::vector<Constant*>& ElementSlots,///< Slot nums for packed values
+    unsigned TypeSlot,                  ///< Slot # of type
+    Constant* Val                       ///< The constant value
+  ) {}
+
   /// @brief Handle a constant pointer
   virtual void handleConstantPointer( 
     const PointerType* PT, ///< Type of the pointer
index 74541c9ef43fe4775622b9aa38df1f74162c46e3..5ef2cb013226c5b685c6a3413595386530f1a0d7 100644 (file)
@@ -24,6 +24,7 @@ namespace llvm {
 class ArrayType;
 class StructType;
 class PointerType;
+class PackedType;
 
 template<class ConstantClass, class TypeClass, class ValType>
 struct ConstantCreator;
@@ -425,6 +426,44 @@ public:
   }
 };
 
+//===---------------------------------------------------------------------------
+/// ConstantPacked - Constant Packed Declarations
+///
+class ConstantPacked : public Constant {
+  friend struct ConstantCreator<ConstantPacked, PackedType,
+                                    std::vector<Constant*> >;
+  ConstantPacked(const ConstantPacked &);      // DO NOT IMPLEMENT
+protected:
+  ConstantPacked(const PackedType *T, const std::vector<Constant*> &Val);
+public:
+  /// get() - Static factory methods - Return objects of the specified value
+  static Constant *get(const PackedType *T, const std::vector<Constant*> &);
+  static Constant *get(const std::vector<Constant*> &V);
+  
+  /// getType - Specialize the getType() method to always return an PackedType,
+  /// which reduces the amount of casting needed in parts of the compiler.
+  ///
+  inline const PackedType *getType() const {
+    return reinterpret_cast<const PackedType*>(Value::getType());
+  }
+
+  /// isNullValue - Return true if this is the value that would be returned by
+  /// getNullValue.  This always returns false because zero arrays are always
+  /// created as ConstantAggregateZero objects.
+  virtual bool isNullValue() const { return false; }
+
+  virtual void destroyConstant();
+  virtual void replaceUsesOfWithOnConstant(Value *From, Value *To,
+                                           bool DisableChecking = false);
+
+  /// Methods for support type inquiry through isa, cast, and dyn_cast:
+  static inline bool classof(const ConstantPacked *) { return true; }
+  static bool classof(const Value *V) {
+    return V->getValueType() == SimpleConstantVal &&
+           V->getType()->getTypeID() == Type::PackedTyID;
+  }
+};
+
 //===---------------------------------------------------------------------------
 /// ConstantPointerNull - a constant pointer value that points to null
 ///
index 8720ca6815b51a042c9d82359c7ed7f4008fe1a1..10f74dc4f0851a21ea0762add7cb62ddb62f2525 100644 (file)
@@ -28,6 +28,7 @@ class FunctionValType;
 class ArrayValType;
 class StructValType;
 class PointerValType;
+class PackedValType;
 
 class DerivedType : public Type, public AbstractTypeUser {
   // AbstractTypeUsers - Implement a list of the users that need to be notified
@@ -152,8 +153,8 @@ public:
 };
 
 
-/// CompositeType - Common super class of ArrayType, StructType, and PointerType
-///
+/// CompositeType - Common super class of ArrayType, StructType, PointerType
+/// and PackedType
 class CompositeType : public DerivedType {
 protected:
   inline CompositeType(TypeID id) : DerivedType(id) { }
@@ -170,7 +171,8 @@ public:
   static inline bool classof(const Type *T) {
     return T->getTypeID() == ArrayTyID || 
            T->getTypeID() == StructTyID ||
-           T->getTypeID() == PointerTyID;
+           T->getTypeID() == PointerTyID ||
+           T->getTypeID() == PackedTyID;
   }
 };
 
@@ -227,11 +229,13 @@ public:
 };
 
 
-/// SequentialType - This is the superclass of the array and pointer type
-/// classes.  Both of these represent "arrays" in memory.  The array type
+/// SequentialType - This is the superclass of the array, pointer and packed 
+/// type classes.  All of these represent "arrays" in memory.  The array type
 /// represents a specifically sized array, pointer types are unsized/unknown
-/// size arrays.  SequentialType holds the common features of both, which stem
-/// from the fact that both lay their components out in memory identically.
+/// size arrays, packed types represent specifically sized arrays that 
+/// allow for use of SIMD instructions.  SequentialType holds the common 
+/// features of all, which stem from the fact that all three lay their 
+/// components out in memory identically.
 ///
 class SequentialType : public CompositeType {
   SequentialType(const SequentialType &);                  // Do not implement!
@@ -258,7 +262,8 @@ public:
   static inline bool classof(const SequentialType *T) { return true; }
   static inline bool classof(const Type *T) {
     return T->getTypeID() == ArrayTyID ||
-           T->getTypeID() == PointerTyID;
+           T->getTypeID() == PointerTyID ||
+           T->getTypeID() == PackedTyID;
   }
 };
 
@@ -299,6 +304,42 @@ public:
   }
 };
 
+/// PackedType - Class to represent packed types
+///
+class PackedType : public SequentialType {
+  friend class TypeMap<PackedValType, PackedType>;
+  unsigned NumElements;
+
+  PackedType(const PackedType &);                   // Do not implement
+  const PackedType &operator=(const PackedType &);  // Do not implement
+protected:
+  /// This should really be private, but it squelches a bogus warning
+  /// from GCC to make them protected:  warning: `class PackedType' only 
+  /// defines private constructors and has no friends
+  ///
+  /// Private ctor - Only can be created by a static member...
+  ///
+  PackedType(const Type *ElType, unsigned NumEl);
+
+public:
+  /// PackedType::get - This static method is the primary way to construct an
+  /// PackedType
+  ///
+  static PackedType *get(const Type *ElementType, unsigned NumElements);
+
+  inline unsigned    getNumElements() const { return NumElements; }
+
+  // Implement the AbstractTypeUser interface.
+  virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy);
+  virtual void typeBecameConcrete(const DerivedType *AbsTy);
+
+  // Methods for support type inquiry through isa, cast, and dyn_cast:
+  static inline bool classof(const PackedType *T) { return true; }
+  static inline bool classof(const Type *T) {
+    return T->getTypeID() == PackedTyID;
+  }
+};
+
 
 /// PointerType - Class to represent pointers
 ///
index 8e59c7adb62fd70b7e3dd266588c5c883d97ee71..25ad5cd3bd52341b51e50eab764a6d4f6670ed54 100644 (file)
@@ -58,6 +58,7 @@ HANDLE_DERV_TYPE(Array   , ArrayType)
 HANDLE_DERV_TYPE(Pointer , PointerType)
 HANDLE_DERV_TYPE(Struct  , StructType)
 HANDLE_DERV_TYPE(Opaque  , OpaqueType)
+HANDLE_DERV_TYPE(Packed  , PackedType)
 
 // Kill the macros on exit...
 #undef HANDLE_PRIM_TYPE
index 273cd439c8c83b436059fbfa2fd455943fa3e01c..fcaa9f566905f0341c5e9cc03900f8691db5ebae 100644 (file)
@@ -48,6 +48,7 @@ class FunctionType;
 class OpaqueType;
 class PointerType;
 class StructType;
+class PackedType;
 
 struct Type {
   ///===-------------------------------------------------------------------===//
@@ -71,7 +72,7 @@ struct Type {
     FunctionTyID  , StructTyID,         // Functions... Structs...
     ArrayTyID     , PointerTyID,        // Array... pointer...
     OpaqueTyID,                         // Opaque type instances...
-    //PackedTyID  ,                     // SIMD 'packed' format... TODO
+    PackedTyID,                         // SIMD 'packed' format... 
     //...
 
     NumTypeIDs,                         // Must remain as last defined ID
@@ -189,7 +190,8 @@ public:
 
   /// isFirstClassType - Return true if the value is holdable in a register.
   inline bool isFirstClassType() const {
-    return (ID != VoidTyID && ID <= LastPrimitiveTyID) || ID == PointerTyID;
+    return (ID != VoidTyID && ID <= LastPrimitiveTyID) || 
+            ID == PointerTyID || ID == PackedTyID;
   }
 
   /// isSized - Return true if it makes sense to take the size of this type.  To
@@ -197,7 +199,7 @@ public:
   /// TargetData subsystem to do this.
   ///
   bool isSized() const {
-    return (ID >= BoolTyID && ID <= DoubleTyID) || ID == PointerTyID ||
+    return (ID >= BoolTyID && ID <= DoubleTyID) || ID == PointerTyID || 
            isSizedDerivedType();
   }
 
index e48d6cfc9fca95fb38e9f77242ddf6700d2fb9e6..1a4ad32a9724246717d8af9a77291533d5081345 100644 (file)
@@ -1033,6 +1033,17 @@ UpRTypes : '\\' EUINT64VAL {                   // Type UpReference
     $$ = new PATypeHolder(HandleUpRefs(ArrayType::get(*$4, (unsigned)$2)));
     delete $4;
   }
+  | '<' EUINT64VAL 'x' UpRTypes '>' {          // Packed array type?
+     const llvm::Type* ElemTy = $4->get();
+     if ((unsigned)$2 != $2) {
+        ThrowException("Unsigned result not equal to signed result");
+     }
+     if(!ElemTy->isPrimitiveType()) {
+        ThrowException("Elemental type of a PackedType must be primitive");
+     }
+     $$ = new PATypeHolder(HandleUpRefs(PackedType::get(*$4, (unsigned)$2)));
+     delete $4;
+  }
   | '{' TypeListI '}' {                        // Structure type?
     std::vector<const Type*> Elements;
     mapto($2->begin(), $2->end(), std::back_inserter(Elements), 
@@ -1144,6 +1155,31 @@ ConstVal: Types '[' ConstVector ']' { // Nonempty unsized arr
     $$ = ConstantArray::get(ATy, Vals);
     delete $1;
   }
+  | Types '<' ConstVector '>' { // Nonempty unsized arr
+    const PackedType *PTy = dyn_cast<PackedType>($1->get());
+    if (PTy == 0)
+      ThrowException("Cannot make packed constant with type: '" + 
+                     (*$1)->getDescription() + "'!");
+    const Type *ETy = PTy->getElementType();
+    int NumElements = PTy->getNumElements();
+
+    // Verify that we have the correct size...
+    if (NumElements != -1 && NumElements != (int)$3->size())
+      ThrowException("Type mismatch: constant sized packed initialized with " +
+                     utostr($3->size()) +  " arguments, but has size of " + 
+                     itostr(NumElements) + "!");
+
+    // Verify all elements are correct type!
+    for (unsigned i = 0; i < $3->size(); i++) {
+      if (ETy != (*$3)[i]->getType())
+        ThrowException("Element #" + utostr(i) + " is not of type '" + 
+           ETy->getDescription() +"' as required!\nIt is of type '"+
+           (*$3)[i]->getType()->getDescription() + "'.");
+    }
+
+    $$ = ConstantPacked::get(PTy, *$3);
+    delete $1; delete $3;
+  }
   | Types '{' ConstVector '}' {
     const StructType *STy = dyn_cast<StructType>($1->get());
     if (STy == 0)
@@ -1651,6 +1687,30 @@ ConstValueRef : ESINT64VAL {    // A reference to a direct constant
   | NULL_TOK {
     $$ = ValID::createNull();
   }
+  | '<' ConstVector '>' { // Nonempty unsized packed vector
+    const Type *ETy = (*$2)[0]->getType();
+    int NumElements = $2->size(); 
+    
+    PackedType* pt = PackedType::get(ETy, NumElements);
+    PATypeHolder* PTy = new PATypeHolder(
+                                         HandleUpRefs(
+                                            PackedType::get(
+                                                ETy, 
+                                                NumElements)
+                                            )
+                                         );
+    
+    // Verify all elements are correct type!
+    for (unsigned i = 0; i < $2->size(); i++) {
+      if (ETy != (*$2)[i]->getType())
+        ThrowException("Element #" + utostr(i) + " is not of type '" + 
+                     ETy->getDescription() +"' as required!\nIt is of type '" +
+                     (*$2)[i]->getType()->getDescription() + "'.");
+    }
+
+    $$ = ValID::create(ConstantPacked::get(pt, *$2));
+    delete PTy; delete $2;
+  }
   | ConstExpr {
     $$ = ValID::create($1);
   };
@@ -1852,8 +1912,14 @@ ValueRefList : ResolvedVal {    // Used for call statements, and memory insts...
 ValueRefListE : ValueRefList | /*empty*/ { $$ = 0; };
 
 InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
-    if (!(*$2)->isInteger() && !(*$2)->isFloatingPoint())
-      ThrowException("Arithmetic operator requires integer or FP operands!");
+    if (!(*$2)->isInteger() && !(*$2)->isFloatingPoint() && 
+        !isa<PackedType>((*$2).get()))
+      ThrowException(
+        "Arithmetic operator requires integer, FP, or packed operands!");
+    if(isa<PackedType>((*$2).get()) && $1 == Instruction::Rem) {
+      ThrowException(
+        "Rem not supported on packed types!");
+    }
     $$ = BinaryOperator::create($1, getVal(*$2, $3), getVal(*$2, $5));
     if ($$ == 0)
       ThrowException("binary operator returned null!");
index f6739ae3c6fbe3803bcd6799d84b9effcff18347..bc1f0c74cdde80fe0e2f9a4504d205001998dc14 100644 (file)
@@ -387,6 +387,27 @@ public:
     bca.numValues++;
   }
 
+  virtual void handleConstantPacked( 
+    const PackedType* PT,                
+    std::vector<Constant*>& Elements,
+    unsigned TypeSlot,                  
+    Constant* PackedVal) 
+  {
+    dump << "      PACKD: " << PT->getDescription() 
+         << " TypeSlot=" << TypeSlot << "\n";
+    for ( unsigned i = 0; i < Elements.size(); ++i ) {
+      dump << "        #" << i;
+      Elements[i]->print(dump);
+      dump << "\n";
+    }
+    dump << "        Value=";
+    PackedVal->print(dump);
+    dump << "\n";
+
+    bca.numConstants++;
+    bca.numValues++;
+  }
+
   virtual void handleConstantPointer( const PointerType* PT, 
       unsigned Slot, GlobalValue* GV ) {
     dump << "       PNTR: " << PT->getDescription() 
index 85a890dbc4327a67ecfe0e170d61a7aee8d849a7..a9dbe9d54550155a2684ceb48ac5017339bf4af9 100644 (file)
@@ -1170,6 +1170,12 @@ const Type *BytecodeReader::ParseType() {
     Result =  ArrayType::get(ElementType, NumElements);
     break;
   }
+  case Type::PackedTyID: {
+    const Type *ElementType = readSanitizedType();
+    unsigned NumElements = read_vbr_uint();
+    Result =  PackedType::get(ElementType, NumElements);
+    break;
+  }
   case Type::StructTyID: {
     std::vector<const Type*> Elements;
     unsigned Typ = 0;
@@ -1396,6 +1402,20 @@ Constant *BytecodeReader::ParseConstantValue(unsigned TypeID) {
     return Result;
   }    
 
+  case Type::PackedTyID: {
+    const PackedType *PT = cast<PackedType>(Ty);
+    unsigned NumElements = PT->getNumElements();
+    unsigned TypeSlot = getTypeSlot(PT->getElementType());
+    std::vector<Constant*> Elements;
+    Elements.reserve(NumElements);
+    while (NumElements--)     // Read all of the elements of the constant.
+      Elements.push_back(getConstantValue(TypeSlot,
+                                          read_vbr_uint()));
+    Constant* Result = ConstantPacked::get(PT, Elements);
+    if (Handler) Handler->handleConstantPacked(PT, Elements, TypeSlot, Result);
+    return Result;
+  }
+
   case Type::PointerTyID: {  // ConstantPointerRef value...
     const PointerType *PT = cast<PointerType>(Ty);
     unsigned Slot = read_vbr_uint();
index c3fad712f2bb00dc1dacc5379db18e6f6ab5c210..6654fd1b023bae8886d9e87593d3d99931c1223e 100644 (file)
@@ -243,6 +243,16 @@ void BytecodeWriter::outputType(const Type *T) {
     break;
   }
 
+ case Type::PackedTyID: {
+    const PackedType *PT = cast<PackedType>(T);
+    int Slot = Table.getSlot(PT->getElementType());
+    assert(Slot != -1 && "Type used but not available!!");
+    output_typeid((unsigned)Slot);
+    output_vbr(PT->getNumElements());
+    break;
+  }
+
+
   case Type::StructTyID: {
     const StructType *ST = cast<StructType>(T);
 
@@ -339,6 +349,17 @@ void BytecodeWriter::outputConstant(const Constant *CPV) {
     break;
   }
 
+  case Type::PackedTyID: {
+    const ConstantPacked *CP = cast<ConstantPacked>(CPV);
+
+    for (unsigned i = 0, e = CP->getNumOperands(); i != e; ++i) {
+      int Slot = Table.getSlot(CP->getOperand(i));
+      assert(Slot != -1 && "Constant used but not available!!");
+      output_vbr((unsigned)Slot);
+    }
+    break;
+  }
+
   case Type::StructTyID: {
     const ConstantStruct *CPS = cast<ConstantStruct>(CPV);
 
index 4cfba7668f5a9a2d7966287bff1eec6c033ffded..9fc772ecba56d4a59cceaf9bf0fd7c5439f77b7e 100644 (file)
@@ -323,6 +323,13 @@ static void calcTypeName(const Type *Ty,
     Result += "]";
     break;
   }
+  case Type::PackedTyID: {
+    const PackedType *PTy = cast<PackedType>(Ty);
+    Result += "<" + utostr(PTy->getNumElements()) + " x ";
+    calcTypeName(PTy->getElementType(), TypeStack, TypeNames, Result);
+    Result += ">";
+    break;
+  }
   case Type::OpaqueTyID:
     Result += "opaque";
     break;
@@ -492,6 +499,22 @@ static void WriteConstantInt(std::ostream &Out, const Constant *CV,
     }
 
     Out << " }";
+  } else if (const ConstantPacked *CP = dyn_cast<ConstantPacked>(CV)) {
+      const Type *ETy = CP->getType()->getElementType();
+      assert(CP->getNumOperands() > 0 && 
+             "Number of operands for a PackedConst must be > 0");
+      Out << '<';
+      Out << ' ';
+      printTypeInt(Out, ETy, TypeTable);
+      WriteAsOperandInternal(Out, CP->getOperand(0),
+                             PrintName, TypeTable, Machine);
+      for (unsigned i = 1, e = CP->getNumOperands(); i != e; ++i) {
+          Out << ", ";
+          printTypeInt(Out, ETy, TypeTable);
+          WriteAsOperandInternal(Out, CP->getOperand(i), PrintName,
+                                 TypeTable, Machine);
+      }
+      Out << " >";
   } else if (isa<ConstantPointerNull>(CV)) {
     Out << "null";
 
index 69f1a78412ed1de4f84996c26da2bb298aa5086f..8b28c0d3ff6c85a023ebfe76df18e8911262b50e 100644 (file)
@@ -120,6 +120,7 @@ Constant *Constant::getNullValue(const Type *Ty) {
 
   case Type::StructTyID:
   case Type::ArrayTyID:
+  case Type::PackedTyID:
     return ConstantAggregateZero::get(Ty);
   default:
     // Function, Label, or Opaque type?
@@ -268,6 +269,17 @@ ConstantStruct::ConstantStruct(const StructType *T,
   }
 }
 
+ConstantPacked::ConstantPacked(const PackedType *T,
+                               const std::vector<Constant*> &V) : Constant(T) {
+  Operands.reserve(V.size());
+  for (unsigned i = 0, e = V.size(); i != e; ++i) {
+    assert(V[i]->getType() == T->getElementType() ||
+           (T->isAbstract() &&
+            V[i]->getType()->getTypeID() == T->getElementType()->getTypeID()));
+    Operands.push_back(Use(V[i], this));
+  }
+}
+
 ConstantExpr::ConstantExpr(unsigned Opcode, Constant *C, const Type *Ty)
   : Constant(Ty, ConstantExprVal), iType(Opcode) {
   Operands.reserve(1);
@@ -484,6 +496,31 @@ void ConstantStruct::replaceUsesOfWithOnConstant(Value *From, Value *To,
   destroyConstant();
 }
 
+void ConstantPacked::replaceUsesOfWithOnConstant(Value *From, Value *To,
+                                                 bool DisableChecking) {
+  assert(isa<Constant>(To) && "Cannot make Constant refer to non-constant!");
+
+  std::vector<Constant*> Values;
+  Values.reserve(getNumOperands());  // Build replacement array...
+  for (unsigned i = 0, e = getNumOperands(); i != e; ++i) {
+    Constant *Val = getOperand(i);
+    if (Val == From) Val = cast<Constant>(To);
+    Values.push_back(Val);
+  }
+  
+  Constant *Replacement = ConstantPacked::get(getType(), Values);
+  assert(Replacement != this && "I didn't contain From!");
+
+  // Everyone using this now uses the replacement...
+  if (DisableChecking)
+    uncheckedReplaceAllUsesWith(Replacement);
+  else
+    replaceAllUsesWith(Replacement);
+  
+  // Delete the old constant!
+  destroyConstant();  
+}
+
 void ConstantExpr::replaceUsesOfWithOnConstant(Value *From, Value *ToV,
                                                bool DisableChecking) {
   assert(isa<Constant>(ToV) && "Cannot make Constant refer to non-constant!");
@@ -959,6 +996,61 @@ void ConstantStruct::destroyConstant() {
   destroyConstantImpl();
 }
 
+//---- ConstantPacked::get() implementation...
+//
+namespace llvm {
+  template<>
+  struct ConvertConstantType<ConstantPacked, PackedType> {
+    static void convert(ConstantPacked *OldC, const PackedType *NewTy) {
+      // Make everyone now use a constant of the new type...
+      std::vector<Constant*> C;
+      for (unsigned i = 0, e = OldC->getNumOperands(); i != e; ++i)
+        C.push_back(cast<Constant>(OldC->getOperand(i)));
+      Constant *New = ConstantPacked::get(NewTy, C);
+      assert(New != OldC && "Didn't replace constant??");
+      OldC->uncheckedReplaceAllUsesWith(New);
+      OldC->destroyConstant();    // This constant is now dead, destroy it.
+    }
+  };
+}
+
+static std::vector<Constant*> getValType(ConstantPacked *CP) {
+  std::vector<Constant*> Elements;
+  Elements.reserve(CP->getNumOperands());
+  for (unsigned i = 0, e = CP->getNumOperands(); i != e; ++i)
+    Elements.push_back(CP->getOperand(i));
+  return Elements;
+}
+
+static ValueMap<std::vector<Constant*>, PackedType,
+                ConstantPacked> PackedConstants;
+
+Constant *ConstantPacked::get(const PackedType *Ty,
+                              const std::vector<Constant*> &V) {
+  // If this is an all-zero packed, return a ConstantAggregateZero object
+  if (!V.empty()) {
+    Constant *C = V[0];
+    if (!C->isNullValue())
+      return PackedConstants.getOrCreate(Ty, V);
+    for (unsigned i = 1, e = V.size(); i != e; ++i)
+      if (V[i] != C)
+        return PackedConstants.getOrCreate(Ty, V);
+  }
+  return ConstantAggregateZero::get(Ty);
+}
+
+Constant *ConstantPacked::get(const std::vector<Constant*> &V) {
+  assert(!V.empty() && "Cannot infer type if V is empty");
+  return get(PackedType::get(V.front()->getType(),V.size()), V);
+}
+
+// destroyConstant - Remove the constant from the constant table...
+//
+void ConstantPacked::destroyConstant() {
+  PackedConstants.remove(this);
+  destroyConstantImpl();
+}
+
 //---- ConstantPointerNull::get() implementation...
 //
 
index 205f32b4605a128aaed06a062a50e216f2b739ff..74907dd7c44413171cc44a95fbb6b94c1d0d9d30 100644 (file)
@@ -564,8 +564,10 @@ void BinaryOperator::init(BinaryOps iType, Value *S1, Value *S2)
   case Rem:
     assert(getType() == S1->getType() &&
            "Arithmetic operation should return same type as operands!");
-    assert((getType()->isInteger() || getType()->isFloatingPoint()) && 
-           "Tried to create an arithmetic operation on a non-arithmetic type!");
+    assert((getType()->isInteger() || 
+            getType()->isFloatingPoint() || 
+            isa<PackedType>(getType()) ) && 
+          "Tried to create an arithmetic operation on a non-arithmetic type!");
     break;
   case And: case Or:
   case Xor:
index c6ce34701cf1907ae74061f2d0436d793877a81e..bd0da45f460f294c39f72ea786a39318f94e596e 100644 (file)
@@ -261,6 +261,14 @@ static std::string getTypeDescription(const Type *Ty,
     Result += getTypeDescription(ATy->getElementType(), TypeStack) + "]";
     break;
   }
+  case Type::PackedTyID: {
+    const PackedType *PTy = cast<PackedType>(Ty);
+    unsigned NumElements = PTy->getNumElements();
+    Result = "<";
+    Result += utostr(NumElements) + " x ";
+    Result += getTypeDescription(PTy->getElementType(), TypeStack) + ">";
+    break;
+  }
   default:
     Result = "<error>";
     assert(0 && "Unhandled type in getTypeDescription!");
@@ -397,6 +405,16 @@ ArrayType::ArrayType(const Type *ElType, unsigned NumEl)
   setAbstract(ElType->isAbstract());
 }
 
+PackedType::PackedType(const Type *ElType, unsigned NumEl)
+  : SequentialType(PackedTyID, ElType) {
+  NumElements = NumEl;
+
+  assert(NumEl > 0 && "NumEl of a PackedType must be greater than 0");
+  assert((ElType->isIntegral() || ElType->isFloatingPoint()) && 
+         "Elements of a PackedType must be a primitive type");
+}
+
+
 PointerType::PointerType(const Type *E) : SequentialType(PointerTyID, E) {
   // Calculate whether or not this type is abstract
   setAbstract(E->isAbstract());
@@ -503,6 +521,10 @@ static bool TypesEqual(const Type *Ty, const Type *Ty2,
     const ArrayType *ATy2 = cast<ArrayType>(Ty2);
     return ATy->getNumElements() == ATy2->getNumElements() &&
            TypesEqual(ATy->getElementType(), ATy2->getElementType(), EqTypes);
+  } else if (const PackedType *PTy = dyn_cast<PackedType>(Ty)) {
+    const PackedType *PTy2 = cast<PackedType>(Ty2);
+    return PTy->getNumElements() == PTy2->getNumElements() &&
+           TypesEqual(PTy->getElementType(), PTy2->getElementType(), EqTypes);
   } else if (const FunctionType *FTy = dyn_cast<FunctionType>(Ty)) {
     const FunctionType *FTy2 = cast<FunctionType>(Ty2);
     if (FTy->isVarArg() != FTy2->isVarArg() ||
@@ -846,6 +868,56 @@ ArrayType *ArrayType::get(const Type *ElementType, unsigned NumElements) {
   return AT;
 }
 
+
+//===----------------------------------------------------------------------===//
+// Packed Type Factory...
+//
+namespace llvm {
+class PackedValType {
+  const Type *ValTy;
+  unsigned Size;
+public:
+  PackedValType(const Type *val, int sz) : ValTy(val), Size(sz) {}
+
+  static PackedValType get(const PackedType *PT) {
+    return PackedValType(PT->getElementType(), PT->getNumElements());
+  }
+
+  static unsigned hashTypeStructure(const PackedType *PT) {
+    return PT->getNumElements();
+  }
+
+  // Subclass should override this... to update self as usual
+  void doRefinement(const DerivedType *OldType, const Type *NewType) {
+    assert(ValTy == OldType);
+    ValTy = NewType;
+  }
+
+  inline bool operator<(const PackedValType &MTV) const {
+    if (Size < MTV.Size) return true;
+    return Size == MTV.Size && ValTy < MTV.ValTy;
+  }
+};
+}
+static TypeMap<PackedValType, PackedType> PackedTypes;
+
+
+PackedType *PackedType::get(const Type *ElementType, unsigned NumElements) {
+  assert(ElementType && "Can't get packed of null types!");
+
+  PackedValType PVT(ElementType, NumElements);
+  PackedType *PT = PackedTypes.get(PVT);
+  if (PT) return PT;           // Found a match, return it!
+
+  // Value not found.  Derive a new type!
+  PackedTypes.add(PVT, PT = new PackedType(ElementType, NumElements));
+
+#ifdef DEBUG_MERGE_TYPES
+  std::cerr << "Derived new type: " << *PT << "\n";
+#endif
+  return PT;
+}
+
 //===----------------------------------------------------------------------===//
 // Struct Type Factory...
 //
@@ -1107,6 +1179,18 @@ void ArrayType::typeBecameConcrete(const DerivedType *AbsTy) {
   refineAbstractType(AbsTy, AbsTy);
 }
 
+// refineAbstractType - Called when a contained type is found to be more
+// concrete - this could potentially change us from an abstract type to a
+// concrete type.
+//
+void PackedType::refineAbstractType(const DerivedType *OldType,
+                                   const Type *NewType) {
+  PackedTypes.finishRefinement(this, OldType, NewType);
+}
+
+void PackedType::typeBecameConcrete(const DerivedType *AbsTy) {
+  refineAbstractType(AbsTy, AbsTy);
+}
 
 // refineAbstractType - Called when a contained type is found to be more
 // concrete - this could potentially change us from an abstract type to a
index 2005dbf584522e83b55487290c5e98b1d9667e02..9e99fe0136c39a60b77e1afbac1566abeaa22360 100644 (file)
@@ -488,8 +488,9 @@ void Verifier::visitBinaryOperator(BinaryOperator &B) {
     Assert1(B.getType() == B.getOperand(0)->getType(),
             "Arithmetic operators must have same type for operands and result!",
             &B);
-    Assert1(B.getType()->isInteger() || B.getType()->isFloatingPoint(),
-            "Arithmetic operators must have integer or fp type!", &B);
+    Assert1(B.getType()->isInteger() || B.getType()->isFloatingPoint() || 
+            isa<PackedType>(B.getType()),
+            "Arithmetic operators must have integer, fp, or packed type!", &B);
   }
   
   visitInstruction(B);