Index: include/llvm/GlobalVariable.h
===================================================================
--- include/llvm/GlobalVariable.h	(Revision 50410)
+++ include/llvm/GlobalVariable.h	(Arbeitskopie)
@@ -21,6 +21,7 @@
 #define LLVM_GLOBAL_VARIABLE_H
 
 #include "llvm/GlobalValue.h"
+#include "llvm/OperandTraits.h"
 
 namespace llvm {
 
@@ -44,26 +45,32 @@
 
   bool isConstantGlobal : 1;           // Is this a global constant?
   bool isThreadLocalSymbol : 1;        // Is this symbol "Thread Local"?
-  Use Initializer;
 
 public:
-  // allocate space for exactly zero operands
+  // allocate space for exactly one operand
   void *operator new(size_t s) {
-    return User::operator new(s, 0);
+    return User::operator new(s, 1);
   }
   /// GlobalVariable ctor - If a parent module is specified, the global is
   /// automatically inserted into the end of the specified modules global list.
   GlobalVariable(const Type *Ty, bool isConstant, LinkageTypes Linkage,
                  Constant *Initializer = 0, const std::string &Name = "",
-                 Module *Parent = 0, bool ThreadLocal = false, 
+                 Module *Parent = 0, bool ThreadLocal = false,
                  unsigned AddressSpace = 0);
   /// GlobalVariable ctor - This creates a global and inserts it before the
   /// specified other global.
   GlobalVariable(const Type *Ty, bool isConstant, LinkageTypes Linkage,
                  Constant *Initializer, const std::string &Name,
-                 GlobalVariable *InsertBefore, bool ThreadLocal = false, 
+                 GlobalVariable *InsertBefore, bool ThreadLocal = false,
                  unsigned AddressSpace = 0);
-  
+
+  ~GlobalVariable() {
+    NumOperands = 1; // FIXME: needed by operator delete
+  }
+
+  /// Provide fast operand accessors
+  DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
+
   /// isDeclaration - Is this global variable lacking an initializer?  If so, 
   /// the global variable is defined in some other translation unit, and is thus
   /// only a declaration here.
@@ -79,24 +86,24 @@
   /// illegal to call this method if the global is external, because we cannot
   /// tell what the value is initialized to!
   ///
-  inline Constant *getInitializer() const {
+  inline /*const FIXME*/ Constant *getInitializer() const {
     assert(hasInitializer() && "GV doesn't have initializer!");
-    return reinterpret_cast<Constant*>(Initializer.get());
+    return static_cast<Constant*>(Op<0>().get());
   }
   inline Constant *getInitializer() {
     assert(hasInitializer() && "GV doesn't have initializer!");
-    return reinterpret_cast<Constant*>(Initializer.get());
+    return static_cast<Constant*>(Op<0>().get());
   }
   inline void setInitializer(Constant *CPV) {
     if (CPV == 0) {
       if (hasInitializer()) {
-        Initializer.set(0);
+        Op<0>().set(0);
         NumOperands = 0;
       }
     } else {
       if (!hasInitializer())
         NumOperands = 1;
-      Initializer.set(CPV);
+      Op<0>().set(CPV);
     }
   }
 
@@ -141,6 +148,12 @@
   const GlobalVariable *getPrev() const { return Prev; }
 };
 
+template <>
+struct OperandTraits<GlobalVariable> : OptionalOperandTraits<> {
+};
+
+DEFINE_TRANSPARENT_OPERAND_ACCESSORS(GlobalVariable, Value)
+
 } // End llvm namespace
 
 #endif
Index: include/llvm/Value.h
===================================================================
--- include/llvm/Value.h	(Revision 50410)
+++ include/llvm/Value.h	(Arbeitskopie)
@@ -223,10 +223,9 @@
   return OS;
 }
 
-void Use::init(Value *v, User *user) {
-  Val = v;
-  U = user;
-  if (Val) Val->addUse(*this);
+void Use::init(Value *V, User *user) {
+  Val = V;
+  if (V) V->addUse(*this);
 }
 
 void Use::set(Value *V) {
Index: include/llvm/Use.h
===================================================================
--- include/llvm/Use.h	(Revision 50410)
+++ include/llvm/Use.h	(Arbeitskopie)
@@ -26,6 +26,40 @@
 
 
 //===----------------------------------------------------------------------===//
+//                          Generic Tagging Functions
+//===----------------------------------------------------------------------===//
+
+/// Tag - generic tag type for (at least 32 bit) pointers
+enum Tag { noTag, tagOne, tagTwo, tagThree };
+
+/// addTag - insert tag bits into an (untagged) pointer
+template <typename T, typename TAG>
+inline T *addTag(const T *P, TAG Tag) {
+    return reinterpret_cast<T*>(ptrdiff_t(P) | Tag);
+}
+
+/// stripTag - remove tag bits from a pointer,
+/// making it dereferencable
+template <ptrdiff_t MASK, typename T>
+inline T *stripTag(const T *P) {
+  return reinterpret_cast<T*>(ptrdiff_t(P) & ~MASK);
+}
+
+/// extractTag - extract tag bits from a pointer
+template <typename TAG, TAG MASK, typename T>
+inline TAG extractTag(const T *P) {
+  return TAG(ptrdiff_t(P) & MASK);
+}
+
+/// transferTag - transfer tag bits from a pointer,
+/// to an untagged pointer
+template <ptrdiff_t MASK, typename T>
+inline T *transferTag(const T *From, const T *To) {
+  return reinterpret_cast<T*>((ptrdiff_t(From) & MASK) | ptrdiff_t(To));
+}
+
+
+//===----------------------------------------------------------------------===//
 //                                  Use Class
 //===----------------------------------------------------------------------===//
 
@@ -35,20 +69,36 @@
 public:
   inline void init(Value *V, User *U);
 
-  Use(Value *V, User *U) { init(V, U); }
-  Use(const Use &U) { init(U.Val, U.U); }
+private:
+  /// Allow std::swap some intimacy
+  template <typename U> friend void std::swap(U&, U&);
+
+  /// Copy ctor - Only for std::swap
+  Use(const Use &U) { init(U.get(), 0); }
+
+  /// Destructor - Only for zap() and std::swap
   inline ~Use() {
-    if (Val) removeFromList();
+    if (get()) removeFromList();
   }
 
-  /// Default ctor - This leaves the Use completely unitialized.  The only thing
+  /// Default ctor - This leaves the Use completely uninitialized.  The only thing
   /// that is valid to do with this use is to call the "init" method.
-  inline Use() : Val(0) {}
 
+  inline Use() {}
+  enum PrevPtrTag { zeroDigitTag = noTag
+                  , oneDigitTag = tagOne
+                  , stopTag = tagTwo
+                  , fullStopTag = tagThree };
 
+public:
+
+
   operator Value*() const { return Val; }
   Value *get() const { return Val; }
-  User *getUser() const { return U; }
+  User *getUser() const;
+  const Use* getImpliedUser() const;
+  static Use *initTags(Use *Start, Use *Stop, ptrdiff_t Done = 0);
+  static void zap(Use *Start, const Use *Stop, bool del = false);
 
   inline void set(Value *Val);
 
@@ -57,7 +107,7 @@
     return RHS;
   }
   const Use &operator=(const Use &RHS) {
-    set(RHS.Val);
+    set(RHS.get());
     return *this;
   }
 
@@ -66,19 +116,22 @@
 
   Use *getNext() const { return Next; }
 private:
+  Value *Val;
   Use *Next, **Prev;
-  Value *Val;
-  User *U;
 
+  void setPrev(Use **NewPrev) {
+    Prev = transferTag<fullStopTag>(Prev, NewPrev);
+  }
   void addToList(Use **List) {
     Next = *List;
-    if (Next) Next->Prev = &Next;
-    Prev = List;
+    if (Next) Next->setPrev(&Next);
+    setPrev(List);
     *List = this;
   }
   void removeFromList() {
-    *Prev = Next;
-    if (Next) Next->Prev = Prev;
+    Use **StrippedPrev = stripTag<fullStopTag>(Prev);
+    *StrippedPrev = Next;
+    if (Next) Next->setPrev(StrippedPrev);
   }
 
   friend class Value;
Index: include/llvm/Instructions.h
===================================================================
--- include/llvm/Instructions.h	(Revision 50410)
+++ include/llvm/Instructions.h	(Arbeitskopie)
@@ -21,10 +21,10 @@
 #include "llvm/InstrTypes.h"
 #include "llvm/DerivedTypes.h"
 #include "llvm/ParameterAttributes.h"
+#include "llvm/BasicBlock.h"
 
 namespace llvm {
 
-class BasicBlock;
 class ConstantInt;
 class PointerType;
 class VectorType;
@@ -288,11 +288,10 @@
 ///
 class StoreInst : public Instruction {
   void *operator new(size_t, unsigned);  // DO NOT IMPLEMENT
-  Use Ops[2];
   
-  StoreInst(const StoreInst &SI) : Instruction(SI.getType(), Store, Ops, 2) {
-    Ops[0].init(SI.Ops[0], this);
-    Ops[1].init(SI.Ops[1], this);
+  StoreInst(const StoreInst &SI) : Instruction(SI.getType(), Store, &Op<0>(), 2) {
+    Op<0>().init(SI.Op<0>(), this);
+    Op<1>().init(SI.Op<1>(), this);
     setVolatile(SI.isVolatile());
     setAlignment(SI.getAlignment());
     
@@ -329,15 +328,7 @@
   }
 
   /// Transparently provide more efficient getOperand methods.
-  Value *getOperand(unsigned i) const {
-    assert(i < 2 && "getOperand() out of range!");
-    return Ops[i];
-  }
-  void setOperand(unsigned i, Value *Val) {
-    assert(i < 2 && "setOperand() out of range!");
-    Ops[i] = Val;
-  }
-  unsigned getNumOperands() const { return 2; }
+  DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
 
   /// getAlignment - Return the alignment of the access that is being performed
   ///
@@ -363,7 +354,12 @@
   }
 };
 
+template <>
+struct OperandTraits<StoreInst> : FixedNumOperandTraits<2> {
+};
 
+DEFINE_TRANSPARENT_OPERAND_ACCESSORS(StoreInst, Value)
+
 //===----------------------------------------------------------------------===//
 //                             GetElementPtrInst Class
 //===----------------------------------------------------------------------===//
@@ -380,14 +376,7 @@
 /// access elements of arrays and structs
 ///
 class GetElementPtrInst : public Instruction {
-  GetElementPtrInst(const GetElementPtrInst &GEPI)
-    : Instruction(reinterpret_cast<const Type*>(GEPI.getType()), GetElementPtr,
-                  0, GEPI.getNumOperands()) {
-    Use *OL = OperandList = new Use[NumOperands];
-    Use *GEPIOL = GEPI.OperandList;
-    for (unsigned i = 0, E = NumOperands; i != E; ++i)
-      OL[i].init(GEPIOL[i], this);
-  }
+  inline GetElementPtrInst(const GetElementPtrInst &GEPI);
   void init(Value *Ptr, Value* const *Idx, unsigned NumIdx);
   void init(Value *Ptr, Value *Idx);
 
@@ -401,8 +390,9 @@
       std::distance(IdxBegin, IdxEnd);
     
     if (NumIdx > 0) {
-      // This requires that the itoerator points to contiguous memory.
-      init(Ptr, &*IdxBegin, NumIdx);
+      // This requires that the iterator points to contiguous memory.
+      init(Ptr, &*IdxBegin, NumIdx); // FIXME: for the general case
+                                     // we have to build an array here
     }
     else {
       init(Ptr, 0, NumIdx);
@@ -448,29 +438,15 @@
   /// instruction, the second appends the new instruction to the specified
   /// BasicBlock.
   template<typename InputIterator>
-  GetElementPtrInst(Value *Ptr, InputIterator IdxBegin, 
-                    InputIterator IdxEnd,
-                    const std::string &Name = "",
-                    Instruction *InsertBefore = 0)
-      : Instruction(PointerType::get(
-                      checkType(getIndexedType(Ptr->getType(),
-                                               IdxBegin, IdxEnd, true)),
-                      cast<PointerType>(Ptr->getType())->getAddressSpace()),
-                    GetElementPtr, 0, 0, InsertBefore) {
-    init(Ptr, IdxBegin, IdxEnd, Name,
-         typename std::iterator_traits<InputIterator>::iterator_category());
-  }
+  inline GetElementPtrInst(Value *Ptr, InputIterator IdxBegin, 
+                           InputIterator IdxEnd,
+                           unsigned Values,
+                           const std::string &Name,
+                           Instruction *InsertBefore);
   template<typename InputIterator>
-  GetElementPtrInst(Value *Ptr, InputIterator IdxBegin, InputIterator IdxEnd,
-                    const std::string &Name, BasicBlock *InsertAtEnd)
-      : Instruction(PointerType::get(
-                      checkType(getIndexedType(Ptr->getType(),
-                                               IdxBegin, IdxEnd, true)),
-                      cast<PointerType>(Ptr->getType())->getAddressSpace()),
-                    GetElementPtr, 0, 0, InsertAtEnd) {
-    init(Ptr, IdxBegin, IdxEnd, Name,
-         typename std::iterator_traits<InputIterator>::iterator_category());
-  }
+  inline GetElementPtrInst(Value *Ptr, InputIterator IdxBegin, InputIterator IdxEnd,
+                           unsigned Values,
+                           const std::string &Name, BasicBlock *InsertAtEnd);
 
   /// Constructors - These two constructors are convenience methods because one
   /// and two index getelementptr instructions are so common.
@@ -484,28 +460,35 @@
                                    InputIterator IdxEnd,
                                    const std::string &Name = "",
                                    Instruction *InsertBefore = 0) {
-    return new(0/*FIXME*/) GetElementPtrInst(Ptr, IdxBegin, IdxEnd, Name, InsertBefore);
+    typename std::iterator_traits<InputIterator>::difference_type Values = 
+      1 + std::distance(IdxBegin, IdxEnd);
+    return new(Values) GetElementPtrInst(Ptr, IdxBegin, IdxEnd, Values, Name, InsertBefore);
   }
   template<typename InputIterator>
   static GetElementPtrInst *Create(Value *Ptr, InputIterator IdxBegin, InputIterator IdxEnd,
                                    const std::string &Name, BasicBlock *InsertAtEnd) {
-    return new(0/*FIXME*/) GetElementPtrInst(Ptr, IdxBegin, IdxEnd, Name, InsertAtEnd);
+    typename std::iterator_traits<InputIterator>::difference_type Values = 
+      1 + std::distance(IdxBegin, IdxEnd);
+    return new(Values) GetElementPtrInst(Ptr, IdxBegin, IdxEnd, Values, Name, InsertAtEnd);
   }
 
   /// Constructors - These two constructors are convenience methods because one
   /// and two index getelementptr instructions are so common.
   static GetElementPtrInst *Create(Value *Ptr, Value *Idx,
                                    const std::string &Name = "", Instruction *InsertBefore = 0) {
-    return new(2/*FIXME*/) GetElementPtrInst(Ptr, Idx, Name, InsertBefore);
+    return new(2) GetElementPtrInst(Ptr, Idx, Name, InsertBefore);
   }
   static GetElementPtrInst *Create(Value *Ptr, Value *Idx,
                                    const std::string &Name, BasicBlock *InsertAtEnd) {
-    return new(2/*FIXME*/) GetElementPtrInst(Ptr, Idx, Name, InsertAtEnd);
+    return new(2) GetElementPtrInst(Ptr, Idx, Name, InsertAtEnd);
   }
   ~GetElementPtrInst();
 
   virtual GetElementPtrInst *clone() const;
 
+  /// Transparently provide more efficient getOperand methods.
+  DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
+
   // getType - Overload to return most specific pointer type...
   const PointerType *getType() const {
     return reinterpret_cast<const PointerType*>(Instruction::getType());
@@ -572,6 +555,57 @@
   }
 };
 
+template <>
+struct OperandTraits<GetElementPtrInst> : VariadicOperandTraits<1> {
+};
+
+GetElementPtrInst::GetElementPtrInst(const GetElementPtrInst &GEPI)
+  : Instruction(reinterpret_cast<const Type*>(GEPI.getType()), GetElementPtr,
+                OperandTraits<GetElementPtrInst>::op_end(this) - GEPI.getNumOperands(),
+                GEPI.getNumOperands()) {
+  Use *OL = OperandList;
+  Use *GEPIOL = GEPI.OperandList;
+  for (unsigned i = 0, E = NumOperands; i != E; ++i)
+    OL[i].init(GEPIOL[i], this);
+}
+
+template<typename InputIterator>
+GetElementPtrInst::GetElementPtrInst(Value *Ptr,
+                                     InputIterator IdxBegin, 
+                                     InputIterator IdxEnd,
+                                     unsigned Values,
+                                     const std::string &Name,
+                                     Instruction *InsertBefore)
+  : Instruction(PointerType::get(
+                                 checkType(getIndexedType(Ptr->getType(),
+                                                          IdxBegin, IdxEnd, true)),
+                                 cast<PointerType>(Ptr->getType())->getAddressSpace()),
+                GetElementPtr, OperandTraits<GetElementPtrInst>::op_end(this) - Values,
+                Values, InsertBefore) {
+  init(Ptr, IdxBegin, IdxEnd, Name,
+       typename std::iterator_traits<InputIterator>::iterator_category());
+}
+template<typename InputIterator>
+GetElementPtrInst::GetElementPtrInst(Value *Ptr,
+                                     InputIterator IdxBegin,
+                                     InputIterator IdxEnd,
+                                     unsigned Values,
+                                     const std::string &Name,
+                                     BasicBlock *InsertAtEnd)
+  : Instruction(PointerType::get(
+                                 checkType(getIndexedType(Ptr->getType(),
+                                                          IdxBegin, IdxEnd, true)),
+                                 cast<PointerType>(Ptr->getType())->getAddressSpace()),
+                GetElementPtr, OperandTraits<GetElementPtrInst>::op_end(this) - Values,
+                Values, InsertAtEnd) {
+  init(Ptr, IdxBegin, IdxEnd, Name,
+       typename std::iterator_traits<InputIterator>::iterator_category());
+}
+
+
+DEFINE_TRANSPARENT_OPERAND_ACCESSORS(GetElementPtrInst, Value)
+
+
 //===----------------------------------------------------------------------===//
 //                               ICmpInst Class
 //===----------------------------------------------------------------------===//
@@ -725,7 +759,7 @@
   /// @brief Swap operands and adjust predicate.
   void swapOperands() {
     SubclassData = getSwappedPredicate();
-    std::swap(Ops[0], Ops[1]);
+    std::swap(Op<0>(), Op<1>());
   }
 
   virtual ICmpInst *clone() const;
@@ -849,7 +883,7 @@
   /// @brief Swap operands and adjust predicate.
   void swapOperands() {
     SubclassData = getSwappedPredicate();
-    std::swap(Ops[0], Ops[1]);
+    std::swap(Op<0>(), Op<1>());
   }
 
   virtual FCmpInst *clone() const;
@@ -902,13 +936,7 @@
   /// @brief Construct a CallInst from a range of arguments
   template<typename InputIterator>
   CallInst(Value *Func, InputIterator ArgBegin, InputIterator ArgEnd,
-           const std::string &Name = "", Instruction *InsertBefore = 0)
-      : Instruction(cast<FunctionType>(cast<PointerType>(Func->getType())
-                                       ->getElementType())->getReturnType(),
-                    Instruction::Call, 0, 0, InsertBefore) {
-    init(Func, ArgBegin, ArgEnd, Name, 
-         typename std::iterator_traits<InputIterator>::iterator_category());
-  }
+           const std::string &Name, Instruction *InsertBefore);
 
   /// Construct a CallInst given a range of arguments.  InputIterator
   /// must be a random-access iterator pointing to contiguous storage
@@ -917,21 +945,15 @@
   /// incur runtime overhead.
   /// @brief Construct a CallInst from a range of arguments
   template<typename InputIterator>
-  CallInst(Value *Func, InputIterator ArgBegin, InputIterator ArgEnd,
-           const std::string &Name, BasicBlock *InsertAtEnd)
-      : Instruction(cast<FunctionType>(cast<PointerType>(Func->getType())
-                                       ->getElementType())->getReturnType(),
-                    Instruction::Call, 0, 0, InsertAtEnd) {
-    init(Func, ArgBegin, ArgEnd, Name,
-         typename std::iterator_traits<InputIterator>::iterator_category());
-  }
+  inline CallInst(Value *Func, InputIterator ArgBegin, InputIterator ArgEnd,
+                  const std::string &Name, BasicBlock *InsertAtEnd);
 
-  CallInst(Value *F, Value *Actual, const std::string& Name = "",
-           Instruction *InsertBefore = 0);
   CallInst(Value *F, Value *Actual, const std::string& Name,
+           Instruction *InsertBefore);
+  CallInst(Value *F, Value *Actual, const std::string& Name,
            BasicBlock *InsertAtEnd);
-  explicit CallInst(Value *F, const std::string &Name = "",
-                    Instruction *InsertBefore = 0);
+  explicit CallInst(Value *F, const std::string &Name,
+                    Instruction *InsertBefore);
   CallInst(Value *F, const std::string &Name, BasicBlock *InsertAtEnd);
 public:
   template<typename InputIterator>
@@ -963,6 +985,9 @@
   ~CallInst();
 
   virtual CallInst *clone() const;
+
+  /// Provide fast operand accessors
+  DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
   
   bool isTailCall() const           { return SubclassData & 1; }
   void setTailCall(bool isTailCall = true) {
@@ -1046,6 +1071,39 @@
   }
 };
 
+template <>
+struct OperandTraits<CallInst> : VariadicOperandTraits<1> {
+};
+
+template<typename InputIterator>
+CallInst::CallInst(Value *Func, InputIterator ArgBegin, InputIterator ArgEnd,
+                   const std::string &Name, BasicBlock *InsertAtEnd)
+  : Instruction(cast<FunctionType>(cast<PointerType>(Func->getType())
+                                   ->getElementType())->getReturnType(),
+                Instruction::Call,
+                OperandTraits<CallInst>::op_end(this) - (ArgEnd - ArgBegin + 1),
+                ArgEnd - ArgBegin + 1, InsertAtEnd) {
+  init(Func, ArgBegin, ArgEnd, Name,
+       typename std::iterator_traits<InputIterator>::iterator_category());
+}
+
+template<typename InputIterator>
+CallInst::CallInst(Value *Func, InputIterator ArgBegin, InputIterator ArgEnd,
+                   const std::string &Name, Instruction *InsertBefore)
+  : Instruction(cast<FunctionType>(cast<PointerType>(Func->getType())
+                                   ->getElementType())->getReturnType(),
+                Instruction::Call,
+                OperandTraits<CallInst>::op_end(this) - (ArgEnd - ArgBegin + 1),
+                ArgEnd - ArgBegin + 1, InsertBefore) {
+  init(Func, ArgBegin, ArgEnd, Name, 
+       typename std::iterator_traits<InputIterator>::iterator_category());
+}
+
+DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CallInst, Value)
+//void CallInst::operator delete(void *it) {
+//  OperandTraits<CallInst>::op_begin(static_cast<CallInst*>(it));
+//}
+
 //===----------------------------------------------------------------------===//
 //                               SelectInst Class
 //===----------------------------------------------------------------------===//
@@ -1053,54 +1111,44 @@
 /// SelectInst - This class represents the LLVM 'select' instruction.
 ///
 class SelectInst : public Instruction {
-  Use Ops[3];
-
   void init(Value *C, Value *S1, Value *S2) {
-    Ops[0].init(C, this);
-    Ops[1].init(S1, this);
-    Ops[2].init(S2, this);
+    Op<0>() = C;
+    Op<1>() = S1;
+    Op<2>() = S2;
   }
 
   SelectInst(const SelectInst &SI)
-    : Instruction(SI.getType(), SI.getOpcode(), Ops, 3) {
-    init(SI.Ops[0], SI.Ops[1], SI.Ops[2]);
+    : Instruction(SI.getType(), SI.getOpcode(), &Op<0>(), 3) {
+    init(SI.Op<0>(), SI.Op<1>(), SI.Op<2>());
   }
-  SelectInst(Value *C, Value *S1, Value *S2, const std::string &Name = "",
-             Instruction *InsertBefore = 0)
-    : Instruction(S1->getType(), Instruction::Select, Ops, 3, InsertBefore) {
+  SelectInst(Value *C, Value *S1, Value *S2, const std::string &Name,
+             Instruction *InsertBefore)
+    : Instruction(S1->getType(), Instruction::Select, &Op<0>(), 3, InsertBefore) {
     init(C, S1, S2);
     setName(Name);
   }
   SelectInst(Value *C, Value *S1, Value *S2, const std::string &Name,
              BasicBlock *InsertAtEnd)
-    : Instruction(S1->getType(), Instruction::Select, Ops, 3, InsertAtEnd) {
+    : Instruction(S1->getType(), Instruction::Select, &Op<0>(), 3, InsertAtEnd) {
     init(C, S1, S2);
     setName(Name);
   }
 public:
   static SelectInst *Create(Value *C, Value *S1, Value *S2, const std::string &Name = "",
-             Instruction *InsertBefore = 0) {
+                            Instruction *InsertBefore = 0) {
     return new(3) SelectInst(C, S1, S2, Name, InsertBefore);
   }
   static SelectInst *Create(Value *C, Value *S1, Value *S2, const std::string &Name,
-             BasicBlock *InsertAtEnd) {
+                            BasicBlock *InsertAtEnd) {
     return new(3) SelectInst(C, S1, S2, Name, InsertAtEnd);
   }
 
-  Value *getCondition() const { return Ops[0]; }
-  Value *getTrueValue() const { return Ops[1]; }
-  Value *getFalseValue() const { return Ops[2]; }
+  Value *getCondition() const { return Op<0>(); }
+  Value *getTrueValue() const { return Op<1>(); }
+  Value *getFalseValue() const { return Op<2>(); }
 
   /// Transparently provide more efficient getOperand methods.
-  Value *getOperand(unsigned i) const {
-    assert(i < 3 && "getOperand() out of range!");
-    return Ops[i];
-  }
-  void setOperand(unsigned i, Value *Val) {
-    assert(i < 3 && "setOperand() out of range!");
-    Ops[i] = Val;
-  }
-  unsigned getNumOperands() const { return 3; }
+  DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
 
   OtherOps getOpcode() const {
     return static_cast<OtherOps>(Instruction::getOpcode());
@@ -1118,6 +1166,12 @@
   }
 };
 
+template <>
+struct OperandTraits<SelectInst> : FixedNumOperandTraits<3> {
+};
+
+DEFINE_TRANSPARENT_OPERAND_ACCESSORS(SelectInst, Value)
+
 //===----------------------------------------------------------------------===//
 //                                VAArgInst Class
 //===----------------------------------------------------------------------===//
@@ -1160,11 +1214,10 @@
 /// element from a VectorType value
 ///
 class ExtractElementInst : public Instruction {
-  Use Ops[2];
   ExtractElementInst(const ExtractElementInst &EE) :
-    Instruction(EE.getType(), ExtractElement, Ops, 2) {
-    Ops[0].init(EE.Ops[0], this);
-    Ops[1].init(EE.Ops[1], this);
+    Instruction(EE.getType(), ExtractElement, &Op<0>(), 2) {
+    Op<0>().init(EE.Op<0>(), this);
+    Op<1>().init(EE.Op<1>(), this);
   }
 
 public:
@@ -1188,15 +1241,7 @@
   virtual ExtractElementInst *clone() const;
 
   /// Transparently provide more efficient getOperand methods.
-  Value *getOperand(unsigned i) const {
-    assert(i < 2 && "getOperand() out of range!");
-    return Ops[i];
-  }
-  void setOperand(unsigned i, Value *Val) {
-    assert(i < 2 && "setOperand() out of range!");
-    Ops[i] = Val;
-  }
-  unsigned getNumOperands() const { return 2; }
+  DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
 
   // Methods for support type inquiry through isa, cast, and dyn_cast:
   static inline bool classof(const ExtractElementInst *) { return true; }
@@ -1208,6 +1253,12 @@
   }
 };
 
+template <>
+struct OperandTraits<ExtractElementInst> : FixedNumOperandTraits<2> {
+};
+
+DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ExtractElementInst, Value)
+
 //===----------------------------------------------------------------------===//
 //                                InsertElementInst Class
 //===----------------------------------------------------------------------===//
@@ -1216,7 +1267,6 @@
 /// element into a VectorType value
 ///
 class InsertElementInst : public Instruction {
-  Use Ops[3];
   InsertElementInst(const InsertElementInst &IE);
   InsertElementInst(Value *Vec, Value *NewElt, Value *Idx,
                     const std::string &Name = "",Instruction *InsertBefore = 0);
@@ -1236,7 +1286,7 @@
   }
   static InsertElementInst *Create(Value *Vec, Value *NewElt, unsigned Idx,
                                    const std::string &Name = "",Instruction *InsertBefore = 0) {
-    return new(3/*FIXME*/) InsertElementInst(Vec, NewElt, Idx, Name, InsertBefore);
+    return new(3) InsertElementInst(Vec, NewElt, Idx, Name, InsertBefore);
   }
   static InsertElementInst *Create(Value *Vec, Value *NewElt, Value *Idx,
                                    const std::string &Name, BasicBlock *InsertAtEnd) {
@@ -1244,7 +1294,7 @@
   }
   static InsertElementInst *Create(Value *Vec, Value *NewElt, unsigned Idx,
                                    const std::string &Name, BasicBlock *InsertAtEnd) {
-    return new(3/*FIXME*/) InsertElementInst(Vec, NewElt, Idx, Name, InsertAtEnd);
+    return new(3) InsertElementInst(Vec, NewElt, Idx, Name, InsertAtEnd);
   }
 
   /// isValidOperands - Return true if an insertelement instruction can be
@@ -1261,15 +1311,7 @@
   }
 
   /// Transparently provide more efficient getOperand methods.
-  Value *getOperand(unsigned i) const {
-    assert(i < 3 && "getOperand() out of range!");
-    return Ops[i];
-  }
-  void setOperand(unsigned i, Value *Val) {
-    assert(i < 3 && "setOperand() out of range!");
-    Ops[i] = Val;
-  }
-  unsigned getNumOperands() const { return 3; }
+  DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
 
   // Methods for support type inquiry through isa, cast, and dyn_cast:
   static inline bool classof(const InsertElementInst *) { return true; }
@@ -1281,6 +1323,12 @@
   }
 };
 
+template <>
+struct OperandTraits<InsertElementInst> : FixedNumOperandTraits<3> {
+};
+
+DEFINE_TRANSPARENT_OPERAND_ACCESSORS(InsertElementInst, Value)
+
 //===----------------------------------------------------------------------===//
 //                           ShuffleVectorInst Class
 //===----------------------------------------------------------------------===//
@@ -1289,7 +1337,6 @@
 /// input vectors.
 ///
 class ShuffleVectorInst : public Instruction {
-  Use Ops[3];
   ShuffleVectorInst(const ShuffleVectorInst &IE);
 public:
   // allocate space for exactly three operands
@@ -1315,19 +1362,7 @@
   }
 
   /// Transparently provide more efficient getOperand methods.
-  const Value *getOperand(unsigned i) const {
-    assert(i < 3 && "getOperand() out of range!");
-    return Ops[i];
-  }
-  Value *getOperand(unsigned i) {
-    assert(i < 3 && "getOperand() out of range!");
-    return Ops[i];
-  }
-  void setOperand(unsigned i, Value *Val) {
-    assert(i < 3 && "setOperand() out of range!");
-    Ops[i] = Val;
-  }
-  unsigned getNumOperands() const { return 3; }
+  DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
   
   /// getMaskValue - Return the index from the shuffle mask for the specified
   /// output result.  This is either -1 if the element is undef or a number less
@@ -1344,7 +1379,12 @@
   }
 };
 
+template <>
+struct OperandTraits<ShuffleVectorInst> : FixedNumOperandTraits<3> {
+};
 
+DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ShuffleVectorInst, Value)
+
 //===----------------------------------------------------------------------===//
 //                               PHINode Class
 //===----------------------------------------------------------------------===//
@@ -1395,6 +1435,9 @@
 
   virtual PHINode *clone() const;
 
+  /// Provide fast operand accessors
+  DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
+
   /// getNumIncomingValues - Return the number of incoming edges
   ///
   unsigned getNumIncomingValues() const { return getNumOperands()/2; }
@@ -1416,10 +1459,10 @@
   /// getIncomingBlock - Return incoming basic block number x
   ///
   BasicBlock *getIncomingBlock(unsigned i) const {
-    return reinterpret_cast<BasicBlock*>(getOperand(i*2+1));
+    return static_cast<BasicBlock*>(getOperand(i*2+1));
   }
   void setIncomingBlock(unsigned i, BasicBlock *BB) {
-    setOperand(i*2+1, reinterpret_cast<Value*>(BB));
+    setOperand(i*2+1, BB);
   }
   unsigned getOperandNumForIncomingBlock(unsigned i) {
     return i*2+1;
@@ -1438,7 +1481,7 @@
     // Initialize some new operands.
     NumOperands = OpNo+2;
     OperandList[OpNo].init(V, this);
-    OperandList[OpNo+1].init(reinterpret_cast<Value*>(BB), this);
+    OperandList[OpNo+1].init(BB, this);
   }
 
   /// removeIncomingValue - Remove an incoming value.  This is useful if a
@@ -1463,7 +1506,7 @@
   int getBasicBlockIndex(const BasicBlock *BB) const {
     Use *OL = OperandList;
     for (unsigned i = 0, e = getNumOperands(); i != e; i += 2)
-      if (OL[i+1] == reinterpret_cast<const Value*>(BB)) return i/2;
+      if (OL[i+1].get() == BB) return i/2;
     return -1;
   }
 
@@ -1488,6 +1531,13 @@
   void resizeOperands(unsigned NumOperands);
 };
 
+template <>
+struct OperandTraits<PHINode> : HungoffOperandTraits<2> {
+};
+
+DEFINE_TRANSPARENT_OPERAND_ACCESSORS(PHINode, Value)  
+
+
 //===----------------------------------------------------------------------===//
 //                               ReturnInst Class
 //===----------------------------------------------------------------------===//
@@ -1497,7 +1547,6 @@
 /// does not continue in this function any longer.
 ///
 class ReturnInst : public TerminatorInst {
-  Use RetVal;
   ReturnInst(const ReturnInst &RI);
   void init(Value * const* retVals, unsigned N);
 
@@ -1506,20 +1555,19 @@
   // ReturnInst()                  - 'ret void' instruction
   // ReturnInst(    null)          - 'ret void' instruction
   // ReturnInst(Value* X)          - 'ret X'    instruction
-  // ReturnInst(    null, Inst *)  - 'ret void' instruction, insert before I
+  // ReturnInst(    null, Inst *I) - 'ret void' instruction, insert before I
   // ReturnInst(Value* X, Inst *I) - 'ret X'    instruction, insert before I
-  // ReturnInst(    null, BB *B)   - 'ret void' instruction, insert @ end of BB
-  // ReturnInst(Value* X, BB *B)   - 'ret X'    instruction, insert @ end of BB
+  // ReturnInst(    null, BB *B)   - 'ret void' instruction, insert @ end of B
+  // ReturnInst(Value* X, BB *B)   - 'ret X'    instruction, insert @ end of B
   // ReturnInst(Value* X, N)          - 'ret X,X+1...X+N-1' instruction
-  // ReturnInst(Value* X, N, Inst *)  - 'ret X,X+1...X+N-1', insert before I
-  // ReturnInst(Value* X, N, BB *)    - 'ret X,X+1...X+N-1', insert @ end of BB
+  // ReturnInst(Value* X, N, Inst *I) - 'ret X,X+1...X+N-1', insert before I
+  // ReturnInst(Value* X, N, BB *B)   - 'ret X,X+1...X+N-1', insert @ end of B
   //
   // NOTE: If the Value* passed is of type void then the constructor behaves as
   // if it was passed NULL.
   explicit ReturnInst(Value *retVal = 0, Instruction *InsertBefore = 0);
   ReturnInst(Value *retVal, BasicBlock *InsertAtEnd);
-  ReturnInst(Value * const* retVals, unsigned N);
-  ReturnInst(Value * const* retVals, unsigned N, Instruction *InsertBefore);
+  ReturnInst(Value * const* retVals, unsigned N, Instruction *InsertBefore = 0);
   ReturnInst(Value * const* retVals, unsigned N, BasicBlock *InsertAtEnd);
   explicit ReturnInst(BasicBlock *InsertAtEnd);
 public:
@@ -1529,10 +1577,7 @@
   static ReturnInst* Create(Value *retVal, BasicBlock *InsertAtEnd) {
     return new(!!retVal) ReturnInst(retVal, InsertAtEnd);
   }
-  static ReturnInst* Create(Value * const* retVals, unsigned N) {
-    return new(N) ReturnInst(retVals, N);
-  }
-  static ReturnInst* Create(Value * const* retVals, unsigned N, Instruction *InsertBefore) {
+  static ReturnInst* Create(Value * const* retVals, unsigned N, Instruction *InsertBefore = 0) {
     return new(N) ReturnInst(retVals, N, InsertBefore);
   }
   static ReturnInst* Create(Value * const* retVals, unsigned N, BasicBlock *InsertAtEnd) {
@@ -1542,18 +1587,18 @@
     return new(0) ReturnInst(InsertAtEnd);
   }
   virtual ~ReturnInst();
+  inline void operator delete(void*);
 
   virtual ReturnInst *clone() const;
 
-  Value *getOperand(unsigned n = 0) const {
-    if (getNumOperands() > 1)
-      return TerminatorInst::getOperand(n);
-    else
-      return RetVal;
-  }
+  /// Provide fast operand accessors
+  DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
 
+  /// Convenience accessor
   Value *getReturnValue(unsigned n = 0) const {
-    return getOperand(n);
+    return n < getNumOperands()
+      ? getOperand(n)
+      : 0;
   }
 
   unsigned getNumSuccessors() const { return 0; }
@@ -1572,6 +1617,18 @@
   virtual void setSuccessorV(unsigned idx, BasicBlock *B);
 };
 
+template <>
+struct OperandTraits<ReturnInst> : VariadicOperandTraits<> {
+};
+
+DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ReturnInst, Value)
+void ReturnInst::operator delete(void *it) {
+  ReturnInst* me(static_cast<ReturnInst*>(it));
+  Use::zap(OperandTraits<ReturnInst>::op_begin(me),
+           OperandTraits<ReturnInst>::op_end(me),
+           true);
+}
+
 //===----------------------------------------------------------------------===//
 //                               BranchInst Class
 //===----------------------------------------------------------------------===//
@@ -1583,7 +1640,6 @@
   /// Ops list - Branches are strange.  The operands are ordered:
   ///  TrueDest, FalseDest, Cond.  This makes some accessors faster because
   /// they don't have to check for cond/uncond branchness.
-  Use Ops[3];
   BranchInst(const BranchInst &BI);
   void AssertOK();
   // BranchInst constructors (where {B, T, F} are blocks, and C is a condition):
@@ -1615,16 +1671,17 @@
     return new(3) BranchInst(IfTrue, IfFalse, Cond, InsertAtEnd);
   }
 
-  /// Transparently provide more efficient getOperand methods.
-  Value *getOperand(unsigned i) const {
-    assert(i < getNumOperands() && "getOperand() out of range!");
-    return Ops[i];
+  ~BranchInst()
+  {
+    if (NumOperands == 1)
+      {
+        NumOperands = (Use*)this - OperandList;
+      }
   }
-  void setOperand(unsigned i, Value *Val) {
-    assert(i < getNumOperands() && "setOperand() out of range!");
-    Ops[i] = Val;
-  }
 
+  /// Transparently provide more efficient getOperand methods.
+  DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
+
   virtual BranchInst *clone() const;
 
   bool isUnconditional() const { return getNumOperands() == 1; }
@@ -1644,12 +1701,12 @@
   // targeting the specified block.
   // FIXME: Eliminate this ugly method.
   void setUnconditionalDest(BasicBlock *Dest) {
+    Op<0>() = Dest;
     if (isConditional()) {  // Convert this to an uncond branch.
+      Op<1>().set(0);
+      Op<2>().set(0);
       NumOperands = 1;
-      Ops[1].set(0);
-      Ops[2].set(0);
     }
-    setOperand(0, reinterpret_cast<Value*>(Dest));
   }
 
   unsigned getNumSuccessors() const { return 1+isConditional(); }
@@ -1661,7 +1718,7 @@
 
   void setSuccessor(unsigned idx, BasicBlock *NewSucc) {
     assert(idx < getNumSuccessors() && "Successor # out of range for Branch!");
-    setOperand(idx, reinterpret_cast<Value*>(NewSucc));
+    setOperand(idx, NewSucc);
   }
 
   // Methods for support type inquiry through isa, cast, and dyn_cast:
@@ -1678,6 +1735,15 @@
   virtual void setSuccessorV(unsigned idx, BasicBlock *B);
 };
 
+template <>
+struct OperandTraits<BranchInst> : HungoffOperandTraits<> {
+  // we need to access operands via OperandList, since
+  // the NumOperands may change from 3 to 1
+  static inline void *allocate(unsigned); // FIXME
+};
+
+DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BranchInst, Value)
+
 //===----------------------------------------------------------------------===//
 //                               SwitchInst Class
 //===----------------------------------------------------------------------===//
@@ -1686,6 +1752,7 @@
 /// SwitchInst - Multiway switch
 ///
 class SwitchInst : public TerminatorInst {
+  void *operator new(size_t, unsigned);  // DO NOT IMPLEMENT
   unsigned ReservedSpace;
   // Operand[0]    = Value to switch on
   // Operand[1]    = Default basic block destination
@@ -1694,6 +1761,10 @@
   SwitchInst(const SwitchInst &RI);
   void init(Value *Value, BasicBlock *Default, unsigned NumCases);
   void resizeOperands(unsigned No);
+  // allocate space for exactly zero operands
+  void *operator new(size_t s) {
+    return User::operator new(s, 0);
+  }
   /// SwitchInst ctor - Create a new switch instruction, specifying a value to
   /// switch on and a default destination.  The number of additional cases can
   /// be specified here to make memory allocation more efficient.  This
@@ -1710,14 +1781,17 @@
 public:
   static SwitchInst *Create(Value *Value, BasicBlock *Default, unsigned NumCases,
                             Instruction *InsertBefore = 0) {
-    return new(NumCases/*FIXME*/) SwitchInst(Value, Default, NumCases, InsertBefore);
+    return new SwitchInst(Value, Default, NumCases, InsertBefore);
   }
   static SwitchInst *Create(Value *Value, BasicBlock *Default, unsigned NumCases,
                             BasicBlock *InsertAtEnd) {
-    return new(NumCases/*FIXME*/) SwitchInst(Value, Default, NumCases, InsertAtEnd);
+    return new SwitchInst(Value, Default, NumCases, InsertAtEnd);
   }
   ~SwitchInst();
 
+  /// Provide fast operand accessors
+  DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
+
   // Accessor Methods for Switch stmt
   Value *getCondition() const { return getOperand(0); }
   void setCondition(Value *V) { setOperand(0, V); }
@@ -1790,7 +1864,7 @@
   }
   void setSuccessor(unsigned idx, BasicBlock *NewSucc) {
     assert(idx < getNumSuccessors() && "Successor # out of range for switch!");
-    setOperand(idx*2+1, reinterpret_cast<Value*>(NewSucc));
+    setOperand(idx*2+1, NewSucc);
   }
 
   // getSuccessorValue - Return the value associated with the specified
@@ -1814,6 +1888,13 @@
   virtual void setSuccessorV(unsigned idx, BasicBlock *B);
 };
 
+template <>
+struct OperandTraits<SwitchInst> : HungoffOperandTraits<2> {
+};
+
+DEFINE_TRANSPARENT_OPERAND_ACCESSORS(SwitchInst, Value)  
+
+
 //===----------------------------------------------------------------------===//
 //                               InvokeInst Class
 //===----------------------------------------------------------------------===//
@@ -1851,15 +1932,10 @@
   ///
   /// @brief Construct an InvokeInst from a range of arguments
   template<typename InputIterator>
-  InvokeInst(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException,
-             InputIterator ArgBegin, InputIterator ArgEnd,
-             const std::string &Name = "", Instruction *InsertBefore = 0)
-      : TerminatorInst(cast<FunctionType>(cast<PointerType>(Func->getType())
-                                          ->getElementType())->getReturnType(),
-                       Instruction::Invoke, 0, 0, InsertBefore) {
-    init(Func, IfNormal, IfException, ArgBegin, ArgEnd, Name,
-         typename std::iterator_traits<InputIterator>::iterator_category());
-  }
+  inline InvokeInst(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException,
+                    InputIterator ArgBegin, InputIterator ArgEnd,
+                    unsigned Values,
+                    const std::string &Name, Instruction *InsertBefore);
 
   /// Construct an InvokeInst given a range of arguments.
   /// InputIterator must be a random-access iterator pointing to
@@ -1869,33 +1945,35 @@
   ///
   /// @brief Construct an InvokeInst from a range of arguments
   template<typename InputIterator>
-  InvokeInst(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException,
-             InputIterator ArgBegin, InputIterator ArgEnd,
-             const std::string &Name, BasicBlock *InsertAtEnd)
-      : TerminatorInst(cast<FunctionType>(cast<PointerType>(Func->getType())
-                                          ->getElementType())->getReturnType(),
-                       Instruction::Invoke, 0, 0, InsertAtEnd) {
-    init(Func, IfNormal, IfException, ArgBegin, ArgEnd, Name,
-         typename std::iterator_traits<InputIterator>::iterator_category());
-  }
+  inline InvokeInst(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException,
+                    InputIterator ArgBegin, InputIterator ArgEnd,
+                    unsigned Values,
+                    const std::string &Name, BasicBlock *InsertAtEnd);
 public:
   template<typename InputIterator>
   static InvokeInst *Create(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException,
                             InputIterator ArgBegin, InputIterator ArgEnd,
                             const std::string &Name = "", Instruction *InsertBefore = 0) {
-    return new(ArgEnd - ArgBegin + 3) InvokeInst(Func, IfNormal, IfException, ArgBegin, ArgEnd, Name, InsertBefore);
+    unsigned Values(ArgEnd - ArgBegin + 3);
+    return new(Values) InvokeInst(Func, IfNormal, IfException, ArgBegin, ArgEnd,
+                                  Values, Name, InsertBefore);
   }
   template<typename InputIterator>
   static InvokeInst *Create(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException,
                             InputIterator ArgBegin, InputIterator ArgEnd,
                             const std::string &Name, BasicBlock *InsertAtEnd) {
-    return new(ArgEnd - ArgBegin + 3) InvokeInst(Func, IfNormal, IfException, ArgBegin, ArgEnd, Name, InsertAtEnd);
+    unsigned Values(ArgEnd - ArgBegin + 3);
+    return new(Values) InvokeInst(Func, IfNormal, IfException, ArgBegin, ArgEnd,
+                                  Values, Name, InsertAtEnd);
   }
 
   ~InvokeInst();
 
   virtual InvokeInst *clone() const;
 
+  /// Provide fast operand accessors
+  DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
+  
   /// getCallingConv/setCallingConv - Get or set the calling convention of this
   /// function call.
   unsigned getCallingConv() const { return SubclassData; }
@@ -1965,11 +2043,11 @@
     return cast<BasicBlock>(getOperand(2));
   }
   void setNormalDest(BasicBlock *B) {
-    setOperand(1, reinterpret_cast<Value*>(B));
+    setOperand(1, B);
   }
 
   void setUnwindDest(BasicBlock *B) {
-    setOperand(2, reinterpret_cast<Value*>(B));
+    setOperand(2, B);
   }
 
   BasicBlock *getSuccessor(unsigned i) const {
@@ -1979,7 +2057,7 @@
 
   void setSuccessor(unsigned idx, BasicBlock *NewSucc) {
     assert(idx < 2 && "Successor # out of range for invoke!");
-    setOperand(idx+1, reinterpret_cast<Value*>(NewSucc));
+    setOperand(idx+1, NewSucc);
   }
 
   unsigned getNumSuccessors() const { return 2; }
@@ -1998,7 +2076,39 @@
   virtual void setSuccessorV(unsigned idx, BasicBlock *B);
 };
 
+template <>
+struct OperandTraits<InvokeInst> : VariadicOperandTraits<3> {
+};
 
+template<typename InputIterator>
+InvokeInst::InvokeInst(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException,
+                       InputIterator ArgBegin, InputIterator ArgEnd,
+                       unsigned Values,
+                       const std::string &Name, Instruction *InsertBefore)
+  : TerminatorInst(cast<FunctionType>(cast<PointerType>(Func->getType())
+                                      ->getElementType())->getReturnType(),
+                   Instruction::Invoke,
+                   OperandTraits<InvokeInst>::op_end(this) - Values,
+                   Values, InsertBefore) {
+  init(Func, IfNormal, IfException, ArgBegin, ArgEnd, Name,
+       typename std::iterator_traits<InputIterator>::iterator_category());
+}
+template<typename InputIterator>
+InvokeInst::InvokeInst(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException,
+                       InputIterator ArgBegin, InputIterator ArgEnd,
+                       unsigned Values,
+                       const std::string &Name, BasicBlock *InsertAtEnd)
+  : TerminatorInst(cast<FunctionType>(cast<PointerType>(Func->getType())
+                                      ->getElementType())->getReturnType(),
+                   Instruction::Invoke,
+                   OperandTraits<InvokeInst>::op_end(this) - Values,
+                   Values, InsertAtEnd) {
+  init(Func, IfNormal, IfException, ArgBegin, ArgEnd, Name,
+       typename std::iterator_traits<InputIterator>::iterator_category());
+}
+
+DEFINE_TRANSPARENT_OPERAND_ACCESSORS(InvokeInst, Value)
+
 //===----------------------------------------------------------------------===//
 //                              UnwindInst Class
 //===----------------------------------------------------------------------===//
@@ -2552,11 +2662,10 @@
 ///
 class GetResultInst : public /*FIXME: Unary*/Instruction {
   void *operator new(size_t, unsigned);  // DO NOT IMPLEMENT
-  Use Aggr;
   unsigned Idx;
   GetResultInst(const GetResultInst &GRI) :
-    Instruction(GRI.getType(), Instruction::GetResult, &Aggr, 1) {
-    Aggr.init(GRI.Aggr, this);
+    Instruction(GRI.getType(), Instruction::GetResult, &Op<0>(), 1) {
+    Op<0>().init(GRI.Op<0>(), this);
     Idx = GRI.Idx;
   }
 
@@ -2565,9 +2674,9 @@
   void *operator new(size_t s) {
     return User::operator new(s, 1);
   }
-  explicit GetResultInst(Value *Aggr, unsigned index,
-                         const std::string &Name = "",
-                         Instruction *InsertBefore = 0);
+  GetResultInst(Value *Aggr, unsigned index,
+                const std::string &Name = "",
+                Instruction *InsertBefore = 0);
 
   /// isValidOperands - Return true if an getresult instruction can be
   /// formed with the specified operands.
@@ -2587,7 +2696,8 @@
     return Idx;
   }
 
-  unsigned getNumOperands() const { return 1; }
+  /// Provide fast operand accessors
+  DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
 
   // Methods for support type inquiry through isa, cast, and dyn_cast:
   static inline bool classof(const GetResultInst *) { return true; }
@@ -2599,6 +2709,14 @@
   }
 };
 
+// FIXME: these are redundant if GetResultInst < UnaryInstruction
+template <>
+struct OperandTraits<GetResultInst> : FixedNumOperandTraits<1> {
+};
+
+DEFINE_TRANSPARENT_OPERAND_ACCESSORS(GetResultInst, Value)
+
+
 } // End llvm namespace
 
 #endif
Index: include/llvm/GlobalAlias.h
===================================================================
--- include/llvm/GlobalAlias.h	(Revision 50410)
+++ include/llvm/GlobalAlias.h	(Arbeitskopie)
@@ -16,6 +16,7 @@
 #define LLVM_GLOBAL_ALIAS_H
 
 #include "llvm/GlobalValue.h"
+#include "llvm/OperandTraits.h"
 
 namespace llvm {
 
@@ -42,17 +43,19 @@
         GlobalAlias *getPrev()       { return Prev; }
   const GlobalAlias *getPrev() const { return Prev; }
 
-  Use Aliasee;
 public:
-  // allocate space for exactly zero operands
+  // allocate space for exactly one operand
   void *operator new(size_t s) {
-    return User::operator new(s, 0);
+    return User::operator new(s, 1);
   }
   /// GlobalAlias ctor - If a parent module is specified, the alias is
   /// automatically inserted into the end of the specified module's alias list.
   GlobalAlias(const Type *Ty, LinkageTypes Linkage, const std::string &Name = "",
               Constant* Aliasee = 0, Module *Parent = 0);
 
+  /// Provide fast operand accessors
+  DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
+
   /// isDeclaration - Is this global variable lacking an initializer?  If so, 
   /// the global variable is defined in some other translation unit, and is thus
   /// only a declaration here.
@@ -95,6 +98,12 @@
   }
 };
 
+template <>
+struct OperandTraits<GlobalAlias> : FixedNumOperandTraits<1> {
+};
+
+DEFINE_TRANSPARENT_OPERAND_ACCESSORS(GlobalAlias, Value)
+
 } // End llvm namespace
 
 #endif
Index: include/llvm/Constants.h
===================================================================
--- include/llvm/Constants.h	(Revision 50410)
+++ include/llvm/Constants.h	(Arbeitskopie)
@@ -22,6 +22,7 @@
 
 #include "llvm/Constant.h"
 #include "llvm/Type.h"
+#include "llvm/OperandTraits.h"
 #include "llvm/ADT/APInt.h"
 #include "llvm/ADT/APFloat.h"
 
@@ -321,7 +322,6 @@
   ConstantArray(const ConstantArray &);      // DO NOT IMPLEMENT
 protected:
   ConstantArray(const ArrayType *T, const std::vector<Constant*> &Val);
-  ~ConstantArray();
 public:
   /// get() - Static factory methods - Return objects of the specified value
   static Constant *get(const ArrayType *T, const std::vector<Constant*> &);
@@ -339,6 +339,9 @@
   /// null termination. 
   static Constant *get(const std::string &Initializer, bool AddNull = true);
 
+  /// Transparently provide more efficient getOperand methods.
+  DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant);
+
   /// getType - Specialize the getType() method to always return an ArrayType,
   /// which reduces the amount of casting needed in parts of the compiler.
   ///
@@ -377,7 +380,12 @@
   }
 };
 
+template <>
+struct OperandTraits<ConstantArray> : VariadicOperandTraits<> {
+};
 
+DEFINE_TRANSPARENT_CASTED_OPERAND_ACCESSORS(ConstantArray, Constant)
+
 //===----------------------------------------------------------------------===//
 // ConstantStruct - Constant Struct Declarations
 //
@@ -387,7 +395,6 @@
   ConstantStruct(const ConstantStruct &);      // DO NOT IMPLEMENT
 protected:
   ConstantStruct(const StructType *T, const std::vector<Constant*> &Val);
-  ~ConstantStruct();
 public:
   /// get() - Static factory methods - Return objects of the specified value
   ///
@@ -399,6 +406,9 @@
     return get(std::vector<Constant*>(Vals, Vals+NumVals), Packed);
   }
   
+  /// Transparently provide more efficient getOperand methods.
+  DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant);
+
   /// getType() specialization - Reduce amount of casting...
   ///
   inline const StructType *getType() const {
@@ -422,6 +432,12 @@
   }
 };
 
+template <>
+struct OperandTraits<ConstantStruct> : VariadicOperandTraits<> {
+};
+
+DEFINE_TRANSPARENT_CASTED_OPERAND_ACCESSORS(ConstantStruct, Constant)
+
 //===----------------------------------------------------------------------===//
 /// ConstantVector - Constant Vector Declarations
 ///
@@ -431,7 +447,6 @@
   ConstantVector(const ConstantVector &);      // DO NOT IMPLEMENT
 protected:
   ConstantVector(const VectorType *T, const std::vector<Constant*> &Val);
-  ~ConstantVector();
 public:
   /// get() - Static factory methods - Return objects of the specified value
   static Constant *get(const VectorType *T, const std::vector<Constant*> &);
@@ -441,6 +456,9 @@
     return get(std::vector<Constant*>(Vals, Vals+NumVals));
   }
   
+  /// Transparently provide more efficient getOperand methods.
+  DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant);
+
   /// getType - Specialize the getType() method to always return a VectorType,
   /// which reduces the amount of casting needed in parts of the compiler.
   ///
@@ -478,6 +496,12 @@
   }
 };
 
+template <>
+struct OperandTraits<ConstantVector> : VariadicOperandTraits<> {
+};
+
+DEFINE_TRANSPARENT_CASTED_OPERAND_ACCESSORS(ConstantVector, Constant)
+
 //===----------------------------------------------------------------------===//
 /// ConstantPointerNull - a constant pointer value that points to null
 ///
@@ -576,6 +600,9 @@
   static Constant *getIntToPtr(Constant *C, const Type *Ty);
   static Constant *getBitCast (Constant *C, const Type *Ty);
 
+  /// Transparently provide more efficient getOperand methods.
+  DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant);
+
   // @brief Convenience function for getting one of the casting operations
   // using a CastOps opcode.
   static Constant *getCast(
@@ -712,13 +739,13 @@
   virtual void destroyConstant();
   virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U);
 
-  /// Override methods to provide more type information...
+/*  /// Override methods to provide more type information...
   inline Constant *getOperand(unsigned i) {
     return cast<Constant>(User::getOperand(i));
   }
   inline Constant *getOperand(unsigned i) const {
     return const_cast<Constant*>(cast<Constant>(User::getOperand(i)));
-  }
+  }*/
 
 
   /// Methods for support type inquiry through isa, cast, and dyn_cast:
@@ -728,7 +755,12 @@
   }
 };
 
+template <>
+struct OperandTraits<ConstantExpr> : VariadicOperandTraits<1> {
+};
 
+DEFINE_TRANSPARENT_CASTED_OPERAND_ACCESSORS(ConstantExpr, Constant)
+
 //===----------------------------------------------------------------------===//
 /// UndefValue - 'undef' values are things that do not have specified contents.
 /// These are used for a variety of purposes, including global variable
Index: include/llvm/User.h
===================================================================
--- include/llvm/User.h	(Revision 50410)
+++ include/llvm/User.h	(Arbeitskopie)
@@ -23,15 +23,203 @@
 
 namespace llvm {
 
+/*==============================================================================
+
+
+   -----------------------------------------------------------------
+   --- Interaction and relationship between User and Use objects ---
+   -----------------------------------------------------------------
+
+
+A subclass of User can choose between incorporating its Use objects
+or refer to them out-of-line by means of a pointer. A mixed variant
+(some Uses inline others hung off) is impractical and breaks the invariant
+that the Use objects belonging to the same User form a contiguous array.
+
+We have 2 different layouts in the User (sub)classes:
+
+Layout a)
+The Use object(s) are inside (resp. at fixed offset) of the User
+object and there are a fixed number of them.
+
+Layout b)
+The Use object(s) are referenced by a pointer to an
+array from the User object and there may be a variable
+number of them.
+
+Initially each layout will possess a direct pointer to the
+start of the array of Uses. Though not mandatory for layout a),
+we stick to this redundancy for the sake of simplicity.
+The User object will also store the number of Use objects it
+has. (Theoretically this information can also be calculated
+given the scheme presented below.)
+
+Special forms of allocation operators (operator new)
+will enforce the following memory layouts:
+
+
+#  Layout a) will be modelled by prepending the User object
+#  by the Use[] array.
+#      
+#      ...---.---.---.---.-------...
+#        | P | P | P | P | User
+#      '''---'---'---'---'-------'''
+
+
+#  Layout b) will be modelled by pointing at the Use[] array.
+#      
+#      .-------...
+#      | User
+#      '-------'''
+#          |
+#          v
+#          .---.---.---.---...
+#          | P | P | P | P |
+#          '---'---'---'---'''
+
+   (In the above figures 'P' stands for the Use** that
+    is stored in each Use object in the member Use::Prev)
+
+
+Since the Use objects will be deprived of the direct pointer to
+their User objects, there must be a fast and exact method to
+recover it. This is accomplished by the following scheme:
+
+A bit-encoding in the 2 LSBits of the Use::Prev will allow to find the
+start of the User object:
+
+00 --> binary digit 0
+01 --> binary digit 1
+10 --> stop and calc (s)
+11 --> full stop (S)
+
+Given a Use*, all we have to do is to walk till we get
+a stop and we either have a User immediately behind or
+we have to walk to the next stop picking up digits
+and calculating the offset:
+
+.---.---.---.---.---.---.---.---.---.---.---.---.---.---.---.---.----------------
+| 1 | s | 1 | 0 | 1 | 0 | s | 1 | 1 | 0 | s | 1 | 1 | s | 1 | S | User (or User*)
+'---'---'---'---'---'---'---'---'---'---'---'---'---'---'---'---'----------------
+    |+15                |+10            |+6         |+3     |+1
+    |                   |               |           |       |__>
+    |                   |               |           |__________>
+    |                   |               |______________________>
+    |                   |______________________________________>
+    |__________________________________________________________>
+
+
+Only the significant number of bits need to be stored between the
+stops, so that the worst case is 20 memory accesses when there are
+1000 Use objects.
+
+The following literate Haskell fragment demonstrates the concept:
+
+> import Test.QuickCheck
+> 
+> digits :: Int -> [Char] -> [Char]
+> digits 0 acc = '0' : acc
+> digits 1 acc = '1' : acc
+> digits n acc = digits (n `div` 2) $ digits (n `mod` 2) acc
+> 
+> dist :: Int -> [Char] -> [Char]
+> dist 0 [] = ['S']
+> dist 0 acc = acc
+> dist 1 acc = let r = dist 0 acc in 's' : digits (length r) r
+> dist n acc = dist (n - 1) $ dist 1 acc
+> 
+> takeLast n ss = reverse $ take n $ reverse ss
+> 
+> test = takeLast 40 $ dist 20 []
+> 
+
+Printing <test> gives: "1s100000s11010s10100s1111s1010s110s11s1S"
+
+The reverse algorithm computes the
+length of the string just by examining
+a certain prefix:
+
+> pref :: [Char] -> Int
+> pref "S" = 1
+> pref ('s':'1':rest) = decode 2 1 rest
+> pref (_:rest) = 1 + pref rest
+> 
+> decode walk acc ('0':rest) = decode (walk + 1) (acc * 2) rest
+> decode walk acc ('1':rest) = decode (walk + 1) (acc * 2 + 1) rest
+> decode walk acc _ = walk + acc
+> 
+
+Now, as expected, printing <pref test> gives 40.
+
+We can quickCheck this with following property:
+
+> testcase = dist 2000 []
+> testcaseLength = length testcase
+> 
+> identityProp n = n > 0 && n <= testcaseLength ==> length arr == pref arr
+>     where arr = takeLast n testcase
+
+As expected <quickCheck identityProp> gives:
+
+*Main> quickCheck identityProp
+OK, passed 100 tests.
+
+Let's be a bit more exhaustive:
+
+> 
+> deepCheck p = check (defaultConfig { configMaxTest = 500 }) p
+> 
+
+And here is the result of <deepCheck identityProp>:
+
+*Main> deepCheck identityProp
+OK, passed 500 tests.
+
+
+To maintain the invariant that the 2 LSBits of each Use** in Use
+never change after being set up, setters of Use::Prev must re-tag the
+new Use** on every modification. Accordingly getters must strip the
+tag bits.
+
+For layout b) instead of the User we will find a pointer (User* with LSBit set).
+Following this pointer brings us to the User. A portable trick will ensure
+that the first bytes of User (if interpreted as a pointer) will never have
+the LSBit set.
+
+==============================================================================*/
+
+/// OperandTraits - Compile-time customization of
+/// operand-related allocators and accessors
+/// for use of the User class
+template <class>
+struct OperandTraits;
+
+class User;
+
+/// OperandTraits<User> - specialization to User
+template <>
+struct OperandTraits<User> {
+  static inline Use *op_begin(User*);
+  static inline Use *op_end(User*);
+  static inline unsigned operands(const User*);
+  template <class U>
+  struct Layout {
+    typedef U overlay;
+  };
+  static inline void *allocate(unsigned);
+};
+
 class User : public Value {
   User(const User &);             // Do not implement
   void *operator new(size_t);     // Do not implement
+  template <unsigned>
+  friend struct HungoffOperandTraits;
 protected:
   /// OperandList - This is a pointer to the array of Users for this operand.
   /// For nodes of fixed arity (e.g. a binary operator) this array will live
-  /// embedded into the derived class.  For nodes of variable arity
-  /// (e.g. ConstantArrays, CallInst, PHINodes, ReturnInst etc), this memory 
-  /// will be dynamically allocated and should be destroyed by the classes 
+  /// prefixed to the derived class.  For nodes of resizable variable arity
+  /// (e.g. PHINodes, SwitchInst etc.), this memory will be dynamically
+  /// allocated and should be destroyed by the classes' 
   /// virtual dtor.
   Use *OperandList;
 
@@ -39,13 +227,45 @@
   ///
   unsigned NumOperands;
 
-  void *operator new(size_t s, unsigned) {
-    return ::operator new(s);
+  void *operator new(size_t s, unsigned Us) {
+    void *Storage = ::operator new(s + sizeof(Use) * Us);
+    Use *Start = static_cast<Use*>(Storage);
+    Use *End = Start + Us;
+    User *Obj = reinterpret_cast<User*>(End);
+    Obj->OperandList = Start;
+    Obj->NumOperands = Us;
+    Use::initTags(Start, End);
+    return Obj;
   }
   User(const Type *Ty, unsigned vty, Use *OpList, unsigned NumOps)
     : Value(Ty, vty), OperandList(OpList), NumOperands(NumOps) {}
+public:
+  ~User() {
+    Use::zap(OperandList, OperandList + NumOperands);
+  }
+  void operator delete(void *Usr) {
+    User *Start = static_cast<User*>(Usr);
+    Use *Storage = static_cast<Use*>(Usr) - Start->NumOperands;
+    ::operator delete(Storage == Start->OperandList
+                      ? Storage
+                      : Usr);
+  }
+public:
+  template <unsigned Idx> Use &Op() {
+    return OperandTraits<User>::op_begin(this)[Idx];
+  }
+  template <unsigned Idx> const Use &Op() const {
+    return OperandTraits<User>::op_begin(const_cast<User*>(this))[Idx];
+  }
+  Use *allocHungoffUses(unsigned) const;
+  void dropHungoffUses(Use *U) {
+    if (OperandList == U) {
+      OperandList = 0;
+      NumOperands = 0;
+    }
+    Use::zap(U, U->getImpliedUser(), true);
+  }
 
-public:
   Value *getOperand(unsigned i) const {
     assert(i < NumOperands && "getOperand() out of range!");
     return OperandList[i];
@@ -93,6 +313,18 @@
   }
 };
 
+inline Use *OperandTraits<User>::op_begin(User *U) {
+  return U->op_begin();
+}
+
+inline Use *OperandTraits<User>::op_end(User *U) {
+  return U->op_end();
+}
+
+inline unsigned OperandTraits<User>::operands(const User *U) {
+  return U->getNumOperands();
+}
+
 template<> struct simplify_type<User::op_iterator> {
   typedef Value* SimpleType;
 
Index: include/llvm/Instruction.h
===================================================================
--- include/llvm/Instruction.h	(Revision 50410)
+++ include/llvm/Instruction.h	(Arbeitskopie)
@@ -20,7 +20,6 @@
 namespace llvm {
 
 struct AssemblyAnnotationWriter;
-class BinaryOperator;
 
 template<typename ValueSubClass, typename ItemParentClass>
   class SymbolTableListTraits;
Index: include/llvm/InstrTypes.h
===================================================================
--- include/llvm/InstrTypes.h	(Revision 50410)
+++ include/llvm/InstrTypes.h	(Arbeitskopie)
@@ -17,6 +17,7 @@
 #define LLVM_INSTRUCTION_TYPES_H
 
 #include "llvm/Instruction.h"
+#include "llvm/OperandTraits.h"
 
 namespace llvm {
 
@@ -78,22 +79,22 @@
   }
 };
 
+
 //===----------------------------------------------------------------------===//
 //                          UnaryInstruction Class
 //===----------------------------------------------------------------------===//
 
 class UnaryInstruction : public Instruction {
   void *operator new(size_t, unsigned); // Do not implement
-  Use Op;
   
-  // avoiding warning: 'this' : used in base member initializer list
-  UnaryInstruction* this_() { return this; }
 protected:
-  UnaryInstruction(const Type *Ty, unsigned iType, Value *V, Instruction *IB =0)
-    : Instruction(Ty, iType, &Op, 1, IB), Op(V, this_()) {
+  UnaryInstruction(const Type *Ty, unsigned iType, Value *V, Instruction *IB = 0)
+    : Instruction(Ty, iType, &Op<0>(), 1, IB) {
+    Op<0>() = V;
   }
   UnaryInstruction(const Type *Ty, unsigned iType, Value *V, BasicBlock *IAE)
-    : Instruction(Ty, iType, &Op, 1, IAE), Op(V, this_()) {
+    : Instruction(Ty, iType, &Op<0>(), 1, IAE) {
+    Op<0>() = V;
   }
 public:
   // allocate space for exactly one operand
@@ -104,16 +105,8 @@
   // Out of line virtual method, so the vtable, etc has a home.
   ~UnaryInstruction();
 
-  // Transparently provide more efficient getOperand methods.
-  Value *getOperand(unsigned i) const {
-    assert(i == 0 && "getOperand() out of range!");
-    return Op;
-  }
-  void setOperand(unsigned i, Value *Val) {
-    assert(i == 0 && "setOperand() out of range!");
-    Op = Val;
-  }
-  unsigned getNumOperands() const { return 1; }
+  /// Transparently provide more efficient getOperand methods.
+  DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
   
   // Methods for support type inquiry through isa, cast, and dyn_cast:
   static inline bool classof(const UnaryInstruction *) { return true; }
@@ -130,13 +123,18 @@
   }
 };
 
+template <>
+struct OperandTraits<UnaryInstruction> : FixedNumOperandTraits<1> {
+};
+
+DEFINE_TRANSPARENT_OPERAND_ACCESSORS(UnaryInstruction, Value)
+
 //===----------------------------------------------------------------------===//
 //                           BinaryOperator Class
 //===----------------------------------------------------------------------===//
 
 class BinaryOperator : public Instruction {
   void *operator new(size_t, unsigned); // Do not implement
-  Use Ops[2];
 protected:
   void init(BinaryOps iType);
   BinaryOperator(BinaryOps iType, Value *S1, Value *S2, const Type *Ty,
@@ -150,15 +148,7 @@
   }
 
   /// Transparently provide more efficient getOperand methods.
-  Value *getOperand(unsigned i) const {
-    assert(i < 2 && "getOperand() out of range!");
-    return Ops[i];
-  }
-  void setOperand(unsigned i, Value *Val) {
-    assert(i < 2 && "setOperand() out of range!");
-    Ops[i] = Val;
-  }
-  unsigned getNumOperands() const { return 2; }
+  DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
 
   /// create() - Construct a binary instruction, given the opcode and the two
   /// operands.  Optionally (if InstBefore is specified) insert the instruction
@@ -253,6 +243,12 @@
   }
 };
 
+template <>
+struct OperandTraits<BinaryOperator> : FixedNumOperandTraits<2> {
+};
+
+DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BinaryOperator, Value)
+
 //===----------------------------------------------------------------------===//
 //                               CastInst Class
 //===----------------------------------------------------------------------===//
@@ -499,6 +495,7 @@
 
 /// This class is the base class for the comparison instructions. 
 /// @brief Abstract base class of comparison instructions.
+// FIXME: why not derive from BinaryOperator?
 class CmpInst: public Instruction {
   void *operator new(size_t, unsigned);  // DO NOT IMPLEMENT
   CmpInst(); // do not implement
@@ -509,8 +506,6 @@
   CmpInst(Instruction::OtherOps op, unsigned short pred, Value *LHS, Value *RHS,
           const std::string &Name, BasicBlock *InsertAtEnd);
 
-  Use Ops[2]; // CmpInst instructions always have 2 operands, optimize
-
 public:
   // allocate space for exactly two operands
   void *operator new(size_t s) {
@@ -550,18 +545,8 @@
   }
 
   /// @brief Provide more efficient getOperand methods.
-  Value *getOperand(unsigned i) const {
-    assert(i < 2 && "getOperand() out of range!");
-    return Ops[i];
-  }
-  void setOperand(unsigned i, Value *Val) {
-    assert(i < 2 && "setOperand() out of range!");
-    Ops[i] = Val;
-  }
+  DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
 
-  /// @brief CmpInst instructions always have 2 operands.
-  unsigned getNumOperands() const { return 2; }
-
   /// This is just a convenience that dispatches to the subclasses.
   /// @brief Swap the operands and adjust predicate accordingly to retain
   /// the same comparison.
@@ -600,6 +585,14 @@
   }
 };
 
+
+// FIXME: these are redundant if CmpInst < BinaryOperator
+template <>
+struct OperandTraits<CmpInst> : FixedNumOperandTraits<2> {
+};
+
+DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CmpInst, Value)
+
 } // End llvm namespace
 
 #endif
Index: lib/Bitcode/Reader/BitcodeReader.h
===================================================================
--- lib/Bitcode/Reader/BitcodeReader.h	(Revision 50410)
+++ lib/Bitcode/Reader/BitcodeReader.h	(Arbeitskopie)
@@ -17,7 +17,7 @@
 #include "llvm/ModuleProvider.h"
 #include "llvm/ParameterAttributes.h"
 #include "llvm/Type.h"
-#include "llvm/User.h"
+#include "llvm/OperandTraits.h"
 #include "llvm/Bitcode/BitstreamReader.h"
 #include "llvm/Bitcode/LLVMBitCodes.h"
 #include "llvm/ADT/DenseMap.h"
@@ -26,32 +26,43 @@
 namespace llvm {
   class MemoryBuffer;
   
+//===----------------------------------------------------------------------===//
+//                          BitcodeReaderValueList Class
+//===----------------------------------------------------------------------===//
+
 class BitcodeReaderValueList : public User {
-  std::vector<Use> Uses;
+  unsigned Capacity;
 public:
-  BitcodeReaderValueList() : User(Type::VoidTy, Value::ArgumentVal, 0, 0) {}
-  
+  BitcodeReaderValueList() : User(Type::VoidTy, Value::ArgumentVal, 0, 0)
+                           , Capacity(0) {}
+
+  /// Provide fast operand accessors
+  DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
+
   // vector compatibility methods
   unsigned size() const { return getNumOperands(); }
+  void resize(unsigned);
   void push_back(Value *V) {
-    Uses.push_back(Use(V, this));
-    OperandList = &Uses[0];
-    ++NumOperands;
+    unsigned OldOps(NumOperands), NewOps(NumOperands + 1);
+    resize(NewOps);
+    NumOperands = NewOps;
+    OperandList[OldOps] = V;
   }
   
   void clear() {
-    std::vector<Use>().swap(Uses);
+    if (OperandList) dropHungoffUses(OperandList);
+    Capacity = 0;
   }
   
   Value *operator[](unsigned i) const { return getOperand(i); }
   
-  Value *back() const { return Uses.back(); }
-  void pop_back() { Uses.pop_back(); --NumOperands; }
+  Value *back() const { return getOperand(size() - 1); }
+  void pop_back() { setOperand(size() - 1, 0); --NumOperands; }
   bool empty() const { return NumOperands == 0; }
   void shrinkTo(unsigned N) {
     assert(N <= NumOperands && "Invalid shrinkTo request!");
-    Uses.resize(N);
-    NumOperands = N;
+    while (NumOperands > N)
+      pop_back();
   }
   virtual void print(std::ostream&) const {}
   
@@ -73,12 +84,21 @@
   
 private:
   void initVal(unsigned Idx, Value *V) {
-    assert(Uses[Idx] == 0 && "Cannot init an already init'd Use!");
-    Uses[Idx].init(V, this);
+    if (Idx >= size()) {
+      // Insert a bunch of null values.
+        resize(Idx * 2 + 1);
+    }
+    assert(getOperand(Idx) == 0 && "Cannot init an already init'd Use!");
+    OperandList[Idx].init(V, this);
   }
 };
-  
 
+template <>
+struct OperandTraits<BitcodeReaderValueList> : HungoffOperandTraits</*16 FIXME*/> {
+};
+
+DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BitcodeReaderValueList, Value)  
+
 class BitcodeReader : public ModuleProvider {
   MemoryBuffer *Buffer;
   BitstreamReader Stream;
Index: lib/Bitcode/Reader/BitcodeReader.cpp
===================================================================
--- lib/Bitcode/Reader/BitcodeReader.cpp	(Revision 50410)
+++ lib/Bitcode/Reader/BitcodeReader.cpp	(Arbeitskopie)
@@ -23,6 +23,7 @@
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/Support/MathExtras.h"
 #include "llvm/Support/MemoryBuffer.h"
+#include "llvm/OperandTraits.h"
 using namespace llvm;
 
 void BitcodeReader::FreeState() {
@@ -115,55 +116,82 @@
   }
 }
 
-
+namespace llvm {
 namespace {
   /// @brief A class for maintaining the slot number definition
   /// as a placeholder for the actual definition for forward constants defs.
   class ConstantPlaceHolder : public ConstantExpr {
     ConstantPlaceHolder();                       // DO NOT IMPLEMENT
     void operator=(const ConstantPlaceHolder &); // DO NOT IMPLEMENT
-    Use Op;
   public:
     // allocate space for exactly one operand
     void *operator new(size_t s) {
       return User::operator new(s, 1);
     }
     explicit ConstantPlaceHolder(const Type *Ty)
-      : ConstantExpr(Ty, Instruction::UserOp1, &Op, 1),
-        Op(UndefValue::get(Type::Int32Ty), this) {
+      : ConstantExpr(Ty, Instruction::UserOp1, &Op<0>(), 1) {
+      Op<0>() = UndefValue::get(Type::Int32Ty);
     }
+    /// Provide fast operand accessors
+    DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
   };
 }
 
+
+  // FIXME: can we inherit this from ConstantExpr?
+template <>
+struct OperandTraits<ConstantPlaceHolder> : FixedNumOperandTraits<1> {
+};
+
+DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantPlaceHolder, Value)
+}
+
+void BitcodeReaderValueList::resize(unsigned Desired) {
+  if (Desired > Capacity)
+  {
+    // Since we expect many values to come from the bitcode file we better
+    // allocate the double amount, so that the array size grows exponentially
+    // at each reallocation.  Also, add a small amount of 100 extra elements
+    // each time, to reallocate less frequently when the array is still small.
+    //
+    Capacity = Desired * 2 + 100;
+    Use *New = allocHungoffUses(Capacity);
+    Use *Old = OperandList;
+    unsigned Ops = getNumOperands();
+    for (int i(Ops - 1); i >= 0; --i)
+      New[i] = Old[i].get();
+    OperandList = New;
+    if (Old) Use::zap(Old, Old + Ops, true);
+  }
+}
+
 Constant *BitcodeReaderValueList::getConstantFwdRef(unsigned Idx,
                                                     const Type *Ty) {
   if (Idx >= size()) {
     // Insert a bunch of null values.
-    Uses.resize(Idx+1);
-    OperandList = &Uses[0];
+    resize(Idx + 1);
     NumOperands = Idx+1;
   }
 
-  if (Value *V = Uses[Idx]) {
+  if (Value *V = OperandList[Idx]) {
     assert(Ty == V->getType() && "Type mismatch in constant table!");
     return cast<Constant>(V);
   }
 
   // Create and return a placeholder, which will later be RAUW'd.
   Constant *C = new ConstantPlaceHolder(Ty);
-  Uses[Idx].init(C, this);
+  OperandList[Idx].init(C, this);
   return C;
 }
 
 Value *BitcodeReaderValueList::getValueFwdRef(unsigned Idx, const Type *Ty) {
   if (Idx >= size()) {
     // Insert a bunch of null values.
-    Uses.resize(Idx+1);
-    OperandList = &Uses[0];
+    resize(Idx + 1);
     NumOperands = Idx+1;
   }
   
-  if (Value *V = Uses[Idx]) {
+  if (Value *V = OperandList[Idx]) {
     assert((Ty == 0 || Ty == V->getType()) && "Type mismatch in value table!");
     return V;
   }
@@ -173,7 +201,7 @@
   
   // Create and return a placeholder, which will later be RAUW'd.
   Value *V = new Argument(Ty);
-  Uses[Idx].init(V, this);
+  OperandList[Idx].init(V, this);
   return V;
 }
 
Index: lib/VMCore/ConstantFold.cpp
===================================================================
--- lib/VMCore/ConstantFold.cpp	(Revision 50410)
+++ lib/VMCore/ConstantFold.cpp	(Arbeitskopie)
@@ -332,10 +332,10 @@
   
   if (const ConstantVector *CVal = dyn_cast<ConstantVector>(Val)) {
     if (const ConstantInt *CIdx = dyn_cast<ConstantInt>(Idx)) {
-      return const_cast<Constant*>(CVal->getOperand(CIdx->getZExtValue()));
+      return CVal->getOperand(CIdx->getZExtValue());
     } else if (isa<UndefValue>(Idx)) {
       // ee({w,x,y,z}, undef) -> w (an arbitrary value).
-      return const_cast<Constant*>(CVal->getOperand(0));
+      return CVal->getOperand(0);
     }
   }
   return 0;
@@ -401,7 +401,7 @@
 /// return the specified element value.  Otherwise return null.
 static Constant *GetVectorElement(const Constant *C, unsigned EltNo) {
   if (const ConstantVector *CV = dyn_cast<ConstantVector>(C))
-    return const_cast<Constant*>(CV->getOperand(EltNo));
+    return CV->getOperand(EltNo);
   
   const Type *EltTy = cast<VectorType>(C->getType())->getElementType();
   if (isa<ConstantAggregateZero>(C))
@@ -1222,9 +1222,9 @@
     if (const ConstantVector *CP2 = dyn_cast<ConstantVector>(C2)) {
       if (pred == FCmpInst::FCMP_OEQ || pred == FCmpInst::FCMP_UEQ) {
         for (unsigned i = 0, e = CP1->getNumOperands(); i != e; ++i) {
-          Constant *C= ConstantExpr::getFCmp(FCmpInst::FCMP_OEQ,
-              const_cast<Constant*>(CP1->getOperand(i)),
-              const_cast<Constant*>(CP2->getOperand(i)));
+          Constant *C = ConstantExpr::getFCmp(FCmpInst::FCMP_OEQ,
+                                              CP1->getOperand(i),
+                                              CP2->getOperand(i));
           if (ConstantInt *CB = dyn_cast<ConstantInt>(C))
             return CB;
         }
@@ -1233,8 +1233,8 @@
       } else if (pred == ICmpInst::ICMP_EQ) {
         for (unsigned i = 0, e = CP1->getNumOperands(); i != e; ++i) {
           Constant *C = ConstantExpr::getICmp(ICmpInst::ICMP_EQ,
-              const_cast<Constant*>(CP1->getOperand(i)),
-              const_cast<Constant*>(CP2->getOperand(i)));
+                                              CP1->getOperand(i),
+                                              CP2->getOperand(i));
           if (ConstantInt *CB = dyn_cast<ConstantInt>(C))
             return CB;
         }
Index: lib/VMCore/Instructions.cpp
===================================================================
--- lib/VMCore/Instructions.cpp	(Revision 50410)
+++ lib/VMCore/Instructions.cpp	(Arbeitskopie)
@@ -100,18 +100,21 @@
 TerminatorInst::~TerminatorInst() {
 }
 
+//===----------------------------------------------------------------------===//
+//                           UnaryInstruction Class
+//===----------------------------------------------------------------------===//
+
 // Out of line virtual method, so the vtable, etc has a home.
 UnaryInstruction::~UnaryInstruction() {
 }
 
-
 //===----------------------------------------------------------------------===//
 //                               PHINode Class
 //===----------------------------------------------------------------------===//
 
 PHINode::PHINode(const PHINode &PN)
   : Instruction(PN.getType(), Instruction::PHI,
-                new Use[PN.getNumOperands()], PN.getNumOperands()),
+                allocHungoffUses(PN.getNumOperands()), PN.getNumOperands()),
     ReservedSpace(PN.getNumOperands()) {
   Use *OL = OperandList;
   for (unsigned i = 0, e = PN.getNumOperands(); i != e; i+=2) {
@@ -121,7 +124,7 @@
 }
 
 PHINode::~PHINode() {
-  delete [] OperandList;
+  dropHungoffUses(OperandList);
 }
 
 // removeIncomingValue - Remove an incoming value.  This is useful if a
@@ -164,8 +167,9 @@
 ///   3. If NumOps == NumOperands, trim the reserved space.
 ///
 void PHINode::resizeOperands(unsigned NumOps) {
+  unsigned e = getNumOperands();
   if (NumOps == 0) {
-    NumOps = (getNumOperands())*3/2;
+    NumOps = e*3/2;
     if (NumOps < 4) NumOps = 4;      // 4 op PHI nodes are VERY common.
   } else if (NumOps*2 > NumOperands) {
     // No resize needed.
@@ -177,14 +181,13 @@
   }
 
   ReservedSpace = NumOps;
-  Use *NewOps = new Use[NumOps];
   Use *OldOps = OperandList;
-  for (unsigned i = 0, e = getNumOperands(); i != e; ++i) {
+  Use *NewOps = allocHungoffUses(NumOps);
+  for (unsigned i = 0; i != e; ++i) {
       NewOps[i].init(OldOps[i], this);
-      OldOps[i].set(0);
   }
-  delete [] OldOps;
   OperandList = NewOps;
+  if (OldOps) Use::zap(OldOps, OldOps + e, true);
 }
 
 /// hasConstantValue - If the specified PHI node always merges together the same
@@ -241,12 +244,11 @@
 //===----------------------------------------------------------------------===//
 
 CallInst::~CallInst() {
-  delete [] OperandList;
 }
 
 void CallInst::init(Value *Func, Value* const *Params, unsigned NumParams) {
-  NumOperands = NumParams+1;
-  Use *OL = OperandList = new Use[NumParams+1];
+  assert(NumOperands == NumParams+1 && "NumOperands not set up?");
+  Use *OL = OperandList;
   OL[0].init(Func, this);
 
   const FunctionType *FTy =
@@ -265,8 +267,8 @@
 }
 
 void CallInst::init(Value *Func, Value *Actual1, Value *Actual2) {
-  NumOperands = 3;
-  Use *OL = OperandList = new Use[3];
+  assert(NumOperands == 3 && "NumOperands not set up?");
+  Use *OL = OperandList;
   OL[0].init(Func, this);
   OL[1].init(Actual1, this);
   OL[2].init(Actual2, this);
@@ -287,8 +289,8 @@
 }
 
 void CallInst::init(Value *Func, Value *Actual) {
-  NumOperands = 2;
-  Use *OL = OperandList = new Use[2];
+  assert(NumOperands == 2 && "NumOperands not set up?");
+  Use *OL = OperandList;
   OL[0].init(Func, this);
   OL[1].init(Actual, this);
 
@@ -305,8 +307,8 @@
 }
 
 void CallInst::init(Value *Func) {
-  NumOperands = 1;
-  Use *OL = OperandList = new Use[1];
+  assert(NumOperands == 1 && "NumOperands not set up?");
+  Use *OL = OperandList;
   OL[0].init(Func, this);
 
   const FunctionType *FTy =
@@ -320,7 +322,9 @@
                    Instruction *InsertBefore)
   : Instruction(cast<FunctionType>(cast<PointerType>(Func->getType())
                                    ->getElementType())->getReturnType(),
-                Instruction::Call, 0, 0, InsertBefore) {
+                Instruction::Call,
+                OperandTraits<CallInst>::op_end(this) - 2,
+                2, InsertBefore) {
   init(Func, Actual);
   setName(Name);
 }
@@ -329,7 +333,9 @@
                    BasicBlock  *InsertAtEnd)
   : Instruction(cast<FunctionType>(cast<PointerType>(Func->getType())
                                    ->getElementType())->getReturnType(),
-                Instruction::Call, 0, 0, InsertAtEnd) {
+                Instruction::Call,
+                OperandTraits<CallInst>::op_end(this) - 2,
+                2, InsertAtEnd) {
   init(Func, Actual);
   setName(Name);
 }
@@ -337,7 +343,9 @@
                    Instruction *InsertBefore)
   : Instruction(cast<FunctionType>(cast<PointerType>(Func->getType())
                                    ->getElementType())->getReturnType(),
-                Instruction::Call, 0, 0, InsertBefore) {
+                Instruction::Call,
+                OperandTraits<CallInst>::op_end(this) - 1,
+                1, InsertBefore) {
   init(Func);
   setName(Name);
 }
@@ -346,13 +354,16 @@
                    BasicBlock *InsertAtEnd)
   : Instruction(cast<FunctionType>(cast<PointerType>(Func->getType())
                                    ->getElementType())->getReturnType(),
-                Instruction::Call, 0, 0, InsertAtEnd) {
+                Instruction::Call,
+                OperandTraits<CallInst>::op_end(this) - 1,
+                1, InsertAtEnd) {
   init(Func);
   setName(Name);
 }
 
 CallInst::CallInst(const CallInst &CI)
-  : Instruction(CI.getType(), Instruction::Call, new Use[CI.getNumOperands()],
+  : Instruction(CI.getType(), Instruction::Call,
+                OperandTraits<CallInst>::op_end(this) - CI.getNumOperands(),
                 CI.getNumOperands()) {
   setParamAttrs(CI.getParamAttrs());
   SubclassData = CI.SubclassData;
@@ -385,13 +396,13 @@
 //===----------------------------------------------------------------------===//
 
 InvokeInst::~InvokeInst() {
-  delete [] OperandList;
+//  delete [] OperandList;
 }
 
 void InvokeInst::init(Value *Fn, BasicBlock *IfNormal, BasicBlock *IfException,
                       Value* const *Args, unsigned NumArgs) {
-  NumOperands = 3+NumArgs;
-  Use *OL = OperandList = new Use[3+NumArgs];
+  assert(NumOperands == 3+NumArgs && "NumOperands not set up?");
+  Use *OL = OperandList;
   OL[0].init(Fn, this);
   OL[1].init(IfNormal, this);
   OL[2].init(IfException, this);
@@ -414,7 +425,8 @@
 
 InvokeInst::InvokeInst(const InvokeInst &II)
   : TerminatorInst(II.getType(), Instruction::Invoke,
-                   new Use[II.getNumOperands()], II.getNumOperands()) {
+                   OperandTraits<InvokeInst>::op_end(this) - II.getNumOperands(),
+                   II.getNumOperands()) {
   setParamAttrs(II.getParamAttrs());
   SubclassData = II.SubclassData;
   Use *OL = OperandList, *InOL = II.OperandList;
@@ -456,48 +468,54 @@
 
 ReturnInst::ReturnInst(const ReturnInst &RI)
   : TerminatorInst(Type::VoidTy, Instruction::Ret,
-                   &RetVal, RI.getNumOperands()) {
+                   OperandTraits<ReturnInst>::op_end(this) - RI.getNumOperands(),
+                   RI.getNumOperands()) {
   unsigned N = RI.getNumOperands();
-  if (N == 1) 
-    RetVal.init(RI.RetVal, this);
+  if (N == 1)
+    Op<0>().init(RI.Op<0>(), this);
   else if (N) {
-    Use *OL = OperandList = new Use[N];
+    Use *OL = OperandList;
     for (unsigned i = 0; i < N; ++i)
       OL[i].init(RI.getOperand(i), this);
   }
 }
 
 ReturnInst::ReturnInst(Value *retVal, Instruction *InsertBefore)
-  : TerminatorInst(Type::VoidTy, Instruction::Ret, &RetVal, 0, InsertBefore) {
+  : TerminatorInst(Type::VoidTy, Instruction::Ret,
+                   OperandTraits<ReturnInst>::op_end(this) - (retVal != 0),
+                   retVal != 0, InsertBefore) {
   if (retVal)
     init(&retVal, 1);
 }
 ReturnInst::ReturnInst(Value *retVal, BasicBlock *InsertAtEnd)
-  : TerminatorInst(Type::VoidTy, Instruction::Ret, &RetVal, 0, InsertAtEnd) {
+  : TerminatorInst(Type::VoidTy, Instruction::Ret,
+                   OperandTraits<ReturnInst>::op_end(this) - (retVal != 0),
+                   retVal != 0, InsertAtEnd) {
   if (retVal)
     init(&retVal, 1);
 }
 ReturnInst::ReturnInst(BasicBlock *InsertAtEnd)
-  : TerminatorInst(Type::VoidTy, Instruction::Ret, &RetVal, 0, InsertAtEnd) {
+  : TerminatorInst(Type::VoidTy, Instruction::Ret,
+                   OperandTraits<ReturnInst>::op_end(this),
+                   0, InsertAtEnd) {
 }
 
 ReturnInst::ReturnInst(Value * const* retVals, unsigned N,
                        Instruction *InsertBefore)
-  : TerminatorInst(Type::VoidTy, Instruction::Ret, &RetVal, N, InsertBefore) {
+  : TerminatorInst(Type::VoidTy, Instruction::Ret,
+                   OperandTraits<ReturnInst>::op_end(this) - N,
+                   N, InsertBefore) {
   if (N != 0)
     init(retVals, N);
 }
 ReturnInst::ReturnInst(Value * const* retVals, unsigned N,
                        BasicBlock *InsertAtEnd)
-  : TerminatorInst(Type::VoidTy, Instruction::Ret, &RetVal, N, InsertAtEnd) {
+  : TerminatorInst(Type::VoidTy, Instruction::Ret,
+                   OperandTraits<ReturnInst>::op_end(this) - N,
+                   N, InsertAtEnd) {
   if (N != 0)
     init(retVals, N);
 }
-ReturnInst::ReturnInst(Value * const* retVals, unsigned N)
-  : TerminatorInst(Type::VoidTy, Instruction::Ret, &RetVal, N) {
-  if (N != 0)
-    init(retVals, N);
-}
 
 void ReturnInst::init(Value * const* retVals, unsigned N) {
   assert (N > 0 && "Invalid operands numbers in ReturnInst init");
@@ -507,11 +525,11 @@
     Value *V = *retVals;
     if (V->getType() == Type::VoidTy)
       return;
-    RetVal.init(V, this);
+    Op<0>().init(V, this);
     return;
   }
 
-  Use *OL = OperandList = new Use[NumOperands];
+  Use *OL = OperandList;
   for (unsigned i = 0; i < NumOperands; ++i) {
     Value *V = *retVals++;
     assert(!isa<BasicBlock>(V) &&
@@ -537,8 +555,6 @@
 }
 
 ReturnInst::~ReturnInst() {
-  if (NumOperands > 1)
-    delete [] OperandList;
 }
 
 //===----------------------------------------------------------------------===//
@@ -603,33 +619,41 @@
 }
 
 BranchInst::BranchInst(BasicBlock *IfTrue, Instruction *InsertBefore)
-  : TerminatorInst(Type::VoidTy, Instruction::Br, Ops, 1, InsertBefore) {
+  : TerminatorInst(Type::VoidTy, Instruction::Br,
+                   OperandTraits<BranchInst>::op_end(this) - 1,
+                   1, InsertBefore) {
   assert(IfTrue != 0 && "Branch destination may not be null!");
-  Ops[0].init(reinterpret_cast<Value*>(IfTrue), this);
+  Op<0>().init(reinterpret_cast<Value*>(IfTrue), this);
 }
 BranchInst::BranchInst(BasicBlock *IfTrue, BasicBlock *IfFalse, Value *Cond,
                        Instruction *InsertBefore)
-: TerminatorInst(Type::VoidTy, Instruction::Br, Ops, 3, InsertBefore) {
-  Ops[0].init(reinterpret_cast<Value*>(IfTrue), this);
-  Ops[1].init(reinterpret_cast<Value*>(IfFalse), this);
-  Ops[2].init(Cond, this);
+  : TerminatorInst(Type::VoidTy, Instruction::Br,
+                   OperandTraits<BranchInst>::op_end(this) - 3,
+                   3, InsertBefore) {
+  Op<0>().init(reinterpret_cast<Value*>(IfTrue), this);
+  Op<1>().init(reinterpret_cast<Value*>(IfFalse), this);
+  Op<2>().init(Cond, this);
 #ifndef NDEBUG
   AssertOK();
 #endif
 }
 
 BranchInst::BranchInst(BasicBlock *IfTrue, BasicBlock *InsertAtEnd)
-  : TerminatorInst(Type::VoidTy, Instruction::Br, Ops, 1, InsertAtEnd) {
+  : TerminatorInst(Type::VoidTy, Instruction::Br,
+                   OperandTraits<BranchInst>::op_end(this) - 1,
+                   1, InsertAtEnd) {
   assert(IfTrue != 0 && "Branch destination may not be null!");
-  Ops[0].init(reinterpret_cast<Value*>(IfTrue), this);
+  Op<0>().init(reinterpret_cast<Value*>(IfTrue), this);
 }
 
 BranchInst::BranchInst(BasicBlock *IfTrue, BasicBlock *IfFalse, Value *Cond,
            BasicBlock *InsertAtEnd)
-  : TerminatorInst(Type::VoidTy, Instruction::Br, Ops, 3, InsertAtEnd) {
-  Ops[0].init(reinterpret_cast<Value*>(IfTrue), this);
-  Ops[1].init(reinterpret_cast<Value*>(IfFalse), this);
-  Ops[2].init(Cond, this);
+  : TerminatorInst(Type::VoidTy, Instruction::Br,
+                   OperandTraits<BranchInst>::op_end(this) - 3,
+                   3, InsertAtEnd) {
+  Op<0>().init(reinterpret_cast<Value*>(IfTrue), this);
+  Op<1>().init(reinterpret_cast<Value*>(IfFalse), this);
+  Op<2>().init(Cond, this);
 #ifndef NDEBUG
   AssertOK();
 #endif
@@ -637,7 +661,9 @@
 
 
 BranchInst::BranchInst(const BranchInst &BI) :
-  TerminatorInst(Type::VoidTy, Instruction::Br, Ops, BI.getNumOperands()) {
+  TerminatorInst(Type::VoidTy, Instruction::Br,
+                 OperandTraits<BranchInst>::op_end(this) - BI.getNumOperands(),
+                 BI.getNumOperands()) {
   OperandList[0].init(BI.getOperand(0), this);
   if (BI.getNumOperands() != 1) {
     assert(BI.getNumOperands() == 3 && "BR can have 1 or 3 operands!");
@@ -869,18 +895,24 @@
 
 
 StoreInst::StoreInst(Value *val, Value *addr, Instruction *InsertBefore)
-  : Instruction(Type::VoidTy, Store, Ops, 2, InsertBefore) {
-  Ops[0].init(val, this);
-  Ops[1].init(addr, this);
+  : Instruction(Type::VoidTy, Store,
+                OperandTraits<StoreInst>::op_begin(this),
+                OperandTraits<StoreInst>::operands(this),
+                InsertBefore) {
+  Op<0>().init(val, this);
+  Op<1>().init(addr, this);
   setVolatile(false);
   setAlignment(0);
   AssertOK();
 }
 
 StoreInst::StoreInst(Value *val, Value *addr, BasicBlock *InsertAtEnd)
-  : Instruction(Type::VoidTy, Store, Ops, 2, InsertAtEnd) {
-  Ops[0].init(val, this);
-  Ops[1].init(addr, this);
+  : Instruction(Type::VoidTy, Store,
+                OperandTraits<StoreInst>::op_begin(this),
+                OperandTraits<StoreInst>::operands(this),
+                InsertAtEnd) {
+  Op<0>().init(val, this);
+  Op<1>().init(addr, this);
   setVolatile(false);
   setAlignment(0);
   AssertOK();
@@ -888,9 +920,12 @@
 
 StoreInst::StoreInst(Value *val, Value *addr, bool isVolatile,
                      Instruction *InsertBefore)
-  : Instruction(Type::VoidTy, Store, Ops, 2, InsertBefore) {
-  Ops[0].init(val, this);
-  Ops[1].init(addr, this);
+  : Instruction(Type::VoidTy, Store,
+                OperandTraits<StoreInst>::op_begin(this),
+                OperandTraits<StoreInst>::operands(this),
+                InsertBefore) {
+  Op<0>().init(val, this);
+  Op<1>().init(addr, this);
   setVolatile(isVolatile);
   setAlignment(0);
   AssertOK();
@@ -898,9 +933,12 @@
 
 StoreInst::StoreInst(Value *val, Value *addr, bool isVolatile,
                      unsigned Align, Instruction *InsertBefore)
-  : Instruction(Type::VoidTy, Store, Ops, 2, InsertBefore) {
-  Ops[0].init(val, this);
-  Ops[1].init(addr, this);
+  : Instruction(Type::VoidTy, Store,
+                OperandTraits<StoreInst>::op_begin(this),
+                OperandTraits<StoreInst>::operands(this),
+                InsertBefore) {
+  Op<0>().init(val, this);
+  Op<1>().init(addr, this);
   setVolatile(isVolatile);
   setAlignment(Align);
   AssertOK();
@@ -908,9 +946,12 @@
 
 StoreInst::StoreInst(Value *val, Value *addr, bool isVolatile,
                      unsigned Align, BasicBlock *InsertAtEnd)
-  : Instruction(Type::VoidTy, Store, Ops, 2, InsertAtEnd) {
-  Ops[0].init(val, this);
-  Ops[1].init(addr, this);
+  : Instruction(Type::VoidTy, Store,
+                OperandTraits<StoreInst>::op_begin(this),
+                OperandTraits<StoreInst>::operands(this),
+                InsertAtEnd) {
+  Op<0>().init(val, this);
+  Op<1>().init(addr, this);
   setVolatile(isVolatile);
   setAlignment(Align);
   AssertOK();
@@ -918,9 +959,12 @@
 
 StoreInst::StoreInst(Value *val, Value *addr, bool isVolatile,
                      BasicBlock *InsertAtEnd)
-  : Instruction(Type::VoidTy, Store, Ops, 2, InsertAtEnd) {
-  Ops[0].init(val, this);
-  Ops[1].init(addr, this);
+  : Instruction(Type::VoidTy, Store,
+                OperandTraits<StoreInst>::op_begin(this),
+                OperandTraits<StoreInst>::operands(this),
+                InsertAtEnd) {
+  Op<0>().init(val, this);
+  Op<1>().init(addr, this);
   setVolatile(isVolatile);
   setAlignment(0);
   AssertOK();
@@ -940,8 +984,8 @@
 }
 
 void GetElementPtrInst::init(Value *Ptr, Value* const *Idx, unsigned NumIdx) {
-  NumOperands = 1+NumIdx;
-  Use *OL = OperandList = new Use[NumOperands];
+  assert(NumOperands == 1+NumIdx && "NumOperands not initialized?");
+  Use *OL = OperandList;
   OL[0].init(Ptr, this);
 
   for (unsigned i = 0; i != NumIdx; ++i)
@@ -949,8 +993,8 @@
 }
 
 void GetElementPtrInst::init(Value *Ptr, Value *Idx) {
-  NumOperands = 2;
-  Use *OL = OperandList = new Use[2];
+  assert(NumOperands == 2 && "NumOperands not initialized?");
+  Use *OL = OperandList;
   OL[0].init(Ptr, this);
   OL[1].init(Idx, this);
 }
@@ -959,7 +1003,9 @@
                                      const std::string &Name, Instruction *InBe)
   : Instruction(PointerType::get(checkType(getIndexedType(Ptr->getType(),Idx)),
                                  retrieveAddrSpace(Ptr)),
-                GetElementPtr, 0, 0, InBe) {
+                GetElementPtr,
+                OperandTraits<GetElementPtrInst>::op_end(this) - 2,
+                2, InBe) {
   init(Ptr, Idx);
   setName(Name);
 }
@@ -968,13 +1014,15 @@
                                      const std::string &Name, BasicBlock *IAE)
   : Instruction(PointerType::get(checkType(getIndexedType(Ptr->getType(),Idx)),
                                  retrieveAddrSpace(Ptr)),
-                GetElementPtr, 0, 0, IAE) {
+                GetElementPtr,
+                OperandTraits<GetElementPtrInst>::op_end(this) - 2,
+                2, IAE) {
   init(Ptr, Idx);
   setName(Name);
 }
 
 GetElementPtrInst::~GetElementPtrInst() {
-  delete[] OperandList;
+  //  delete[] OperandList;
 }
 
 // getIndexedType - Returns the type of the element that would be loaded with
@@ -1067,11 +1115,13 @@
                                        const std::string &Name,
                                        Instruction *InsertBef)
   : Instruction(cast<VectorType>(Val->getType())->getElementType(),
-                ExtractElement, Ops, 2, InsertBef) {
+                ExtractElement,
+                OperandTraits<ExtractElementInst>::op_begin(this),
+                2, InsertBef) {
   assert(isValidOperands(Val, Index) &&
          "Invalid extractelement instruction operands!");
-  Ops[0].init(Val, this);
-  Ops[1].init(Index, this);
+  Op<0>().init(Val, this);
+  Op<1>().init(Index, this);
   setName(Name);
 }
 
@@ -1079,12 +1129,14 @@
                                        const std::string &Name,
                                        Instruction *InsertBef)
   : Instruction(cast<VectorType>(Val->getType())->getElementType(),
-                ExtractElement, Ops, 2, InsertBef) {
+                ExtractElement,
+                OperandTraits<ExtractElementInst>::op_begin(this),
+                2, InsertBef) {
   Constant *Index = ConstantInt::get(Type::Int32Ty, IndexV);
   assert(isValidOperands(Val, Index) &&
          "Invalid extractelement instruction operands!");
-  Ops[0].init(Val, this);
-  Ops[1].init(Index, this);
+  Op<0>().init(Val, this);
+  Op<1>().init(Index, this);
   setName(Name);
 }
 
@@ -1093,12 +1145,14 @@
                                        const std::string &Name,
                                        BasicBlock *InsertAE)
   : Instruction(cast<VectorType>(Val->getType())->getElementType(),
-                ExtractElement, Ops, 2, InsertAE) {
+                ExtractElement,
+                OperandTraits<ExtractElementInst>::op_begin(this),
+                2, InsertAE) {
   assert(isValidOperands(Val, Index) &&
          "Invalid extractelement instruction operands!");
 
-  Ops[0].init(Val, this);
-  Ops[1].init(Index, this);
+  Op<0>().init(Val, this);
+  Op<1>().init(Index, this);
   setName(Name);
 }
 
@@ -1106,13 +1160,15 @@
                                        const std::string &Name,
                                        BasicBlock *InsertAE)
   : Instruction(cast<VectorType>(Val->getType())->getElementType(),
-                ExtractElement, Ops, 2, InsertAE) {
+                ExtractElement,
+                OperandTraits<ExtractElementInst>::op_begin(this),
+                2, InsertAE) {
   Constant *Index = ConstantInt::get(Type::Int32Ty, IndexV);
   assert(isValidOperands(Val, Index) &&
          "Invalid extractelement instruction operands!");
   
-  Ops[0].init(Val, this);
-  Ops[1].init(Index, this);
+  Op<0>().init(Val, this);
+  Op<1>().init(Index, this);
   setName(Name);
 }
 
@@ -1129,33 +1185,38 @@
 //===----------------------------------------------------------------------===//
 
 InsertElementInst::InsertElementInst(const InsertElementInst &IE)
-    : Instruction(IE.getType(), InsertElement, Ops, 3) {
-  Ops[0].init(IE.Ops[0], this);
-  Ops[1].init(IE.Ops[1], this);
-  Ops[2].init(IE.Ops[2], this);
+    : Instruction(IE.getType(), InsertElement,
+                  OperandTraits<InsertElementInst>::op_begin(this), 3) {
+  Op<0>().init(IE.Op<0>(), this);
+  Op<1>().init(IE.Op<1>(), this);
+  Op<2>().init(IE.Op<2>(), this);
 }
 InsertElementInst::InsertElementInst(Value *Vec, Value *Elt, Value *Index,
                                      const std::string &Name,
                                      Instruction *InsertBef)
-  : Instruction(Vec->getType(), InsertElement, Ops, 3, InsertBef) {
+  : Instruction(Vec->getType(), InsertElement,
+                OperandTraits<InsertElementInst>::op_begin(this),
+                3, InsertBef) {
   assert(isValidOperands(Vec, Elt, Index) &&
          "Invalid insertelement instruction operands!");
-  Ops[0].init(Vec, this);
-  Ops[1].init(Elt, this);
-  Ops[2].init(Index, this);
+  Op<0>().init(Vec, this);
+  Op<1>().init(Elt, this);
+  Op<2>().init(Index, this);
   setName(Name);
 }
 
 InsertElementInst::InsertElementInst(Value *Vec, Value *Elt, unsigned IndexV,
                                      const std::string &Name,
                                      Instruction *InsertBef)
-  : Instruction(Vec->getType(), InsertElement, Ops, 3, InsertBef) {
+  : Instruction(Vec->getType(), InsertElement,
+                OperandTraits<InsertElementInst>::op_begin(this),
+                3, InsertBef) {
   Constant *Index = ConstantInt::get(Type::Int32Ty, IndexV);
   assert(isValidOperands(Vec, Elt, Index) &&
          "Invalid insertelement instruction operands!");
-  Ops[0].init(Vec, this);
-  Ops[1].init(Elt, this);
-  Ops[2].init(Index, this);
+  Op<0>().init(Vec, this);
+  Op<1>().init(Elt, this);
+  Op<2>().init(Index, this);
   setName(Name);
 }
 
@@ -1163,27 +1224,31 @@
 InsertElementInst::InsertElementInst(Value *Vec, Value *Elt, Value *Index,
                                      const std::string &Name,
                                      BasicBlock *InsertAE)
-  : Instruction(Vec->getType(), InsertElement, Ops, 3, InsertAE) {
+  : Instruction(Vec->getType(), InsertElement,
+                OperandTraits<InsertElementInst>::op_begin(this),
+                3, InsertAE) {
   assert(isValidOperands(Vec, Elt, Index) &&
          "Invalid insertelement instruction operands!");
 
-  Ops[0].init(Vec, this);
-  Ops[1].init(Elt, this);
-  Ops[2].init(Index, this);
+  Op<0>().init(Vec, this);
+  Op<1>().init(Elt, this);
+  Op<2>().init(Index, this);
   setName(Name);
 }
 
 InsertElementInst::InsertElementInst(Value *Vec, Value *Elt, unsigned IndexV,
                                      const std::string &Name,
                                      BasicBlock *InsertAE)
-: Instruction(Vec->getType(), InsertElement, Ops, 3, InsertAE) {
+: Instruction(Vec->getType(), InsertElement,
+              OperandTraits<InsertElementInst>::op_begin(this),
+              3, InsertAE) {
   Constant *Index = ConstantInt::get(Type::Int32Ty, IndexV);
   assert(isValidOperands(Vec, Elt, Index) &&
          "Invalid insertelement instruction operands!");
   
-  Ops[0].init(Vec, this);
-  Ops[1].init(Elt, this);
-  Ops[2].init(Index, this);
+  Op<0>().init(Vec, this);
+  Op<1>().init(Elt, this);
+  Op<2>().init(Index, this);
   setName(Name);
 }
 
@@ -1206,34 +1271,42 @@
 //===----------------------------------------------------------------------===//
 
 ShuffleVectorInst::ShuffleVectorInst(const ShuffleVectorInst &SV) 
-    : Instruction(SV.getType(), ShuffleVector, Ops, 3) {
-  Ops[0].init(SV.Ops[0], this);
-  Ops[1].init(SV.Ops[1], this);
-  Ops[2].init(SV.Ops[2], this);
+  : Instruction(SV.getType(), ShuffleVector,
+                OperandTraits<ShuffleVectorInst>::op_begin(this),
+                OperandTraits<ShuffleVectorInst>::operands(this)) {
+  Op<0>().init(SV.Op<0>(), this);
+  Op<1>().init(SV.Op<1>(), this);
+  Op<2>().init(SV.Op<2>(), this);
 }
 
 ShuffleVectorInst::ShuffleVectorInst(Value *V1, Value *V2, Value *Mask,
                                      const std::string &Name,
                                      Instruction *InsertBefore)
-  : Instruction(V1->getType(), ShuffleVector, Ops, 3, InsertBefore) {
+  : Instruction(V1->getType(), ShuffleVector,
+                OperandTraits<ShuffleVectorInst>::op_begin(this),
+                OperandTraits<ShuffleVectorInst>::operands(this),
+                InsertBefore) {
   assert(isValidOperands(V1, V2, Mask) &&
          "Invalid shuffle vector instruction operands!");
-  Ops[0].init(V1, this);
-  Ops[1].init(V2, this);
-  Ops[2].init(Mask, this);
+  Op<0>().init(V1, this);
+  Op<1>().init(V2, this);
+  Op<2>().init(Mask, this);
   setName(Name);
 }
 
 ShuffleVectorInst::ShuffleVectorInst(Value *V1, Value *V2, Value *Mask,
                                      const std::string &Name, 
                                      BasicBlock *InsertAtEnd)
-  : Instruction(V1->getType(), ShuffleVector, Ops, 3, InsertAtEnd) {
+  : Instruction(V1->getType(), ShuffleVector,
+                OperandTraits<ShuffleVectorInst>::op_begin(this),
+                OperandTraits<ShuffleVectorInst>::operands(this),
+                InsertAtEnd) {
   assert(isValidOperands(V1, V2, Mask) &&
          "Invalid shuffle vector instruction operands!");
 
-  Ops[0].init(V1, this);
-  Ops[1].init(V2, this);
-  Ops[2].init(Mask, this);
+  Op<0>().init(V1, this);
+  Op<1>().init(V2, this);
+  Op<2>().init(Mask, this);
   setName(Name);
 }
 
@@ -1275,9 +1348,12 @@
 BinaryOperator::BinaryOperator(BinaryOps iType, Value *S1, Value *S2,
                                const Type *Ty, const std::string &Name,
                                Instruction *InsertBefore)
-  : Instruction(Ty, iType, Ops, 2, InsertBefore) {
-  Ops[0].init(S1, this);
-  Ops[1].init(S2, this);
+  : Instruction(Ty, iType,
+                OperandTraits<BinaryOperator>::op_begin(this),
+                OperandTraits<BinaryOperator>::operands(this),
+                InsertBefore) {
+  Op<0>().init(S1, this);
+  Op<1>().init(S2, this);
   init(iType);
   setName(Name);
 }
@@ -1285,9 +1361,12 @@
 BinaryOperator::BinaryOperator(BinaryOps iType, Value *S1, Value *S2, 
                                const Type *Ty, const std::string &Name,
                                BasicBlock *InsertAtEnd)
-  : Instruction(Ty, iType, Ops, 2, InsertAtEnd) {
-  Ops[0].init(S1, this);
-  Ops[1].init(S2, this);
+  : Instruction(Ty, iType,
+                OperandTraits<BinaryOperator>::op_begin(this),
+                OperandTraits<BinaryOperator>::operands(this),
+                InsertAtEnd) {
+  Op<0>().init(S1, this);
+  Op<1>().init(S2, this);
   init(iType);
   setName(Name);
 }
@@ -1482,7 +1561,7 @@
 bool BinaryOperator::swapOperands() {
   if (!isCommutative())
     return true; // Can't commute operands
-  std::swap(Ops[0], Ops[1]);
+  std::swap(Op<0>(), Op<1>());
   return false;
 }
 
@@ -2254,9 +2333,12 @@
 
 CmpInst::CmpInst(OtherOps op, unsigned short predicate, Value *LHS, Value *RHS,
                  const std::string &Name, Instruction *InsertBefore)
-  : Instruction(Type::Int1Ty, op, Ops, 2, InsertBefore) {
-    Ops[0].init(LHS, this);
-    Ops[1].init(RHS, this);
+  : Instruction(Type::Int1Ty, op,
+                OperandTraits<CmpInst>::op_begin(this),
+                OperandTraits<CmpInst>::operands(this),
+                InsertBefore) {
+    Op<0>().init(LHS, this);
+    Op<1>().init(RHS, this);
   SubclassData = predicate;
   setName(Name);
   if (op == Instruction::ICmp) {
@@ -2283,12 +2365,15 @@
   assert(Op0Ty->isFloatingPoint() &&
          "Invalid operand types for FCmp instruction");
 }
-  
+
 CmpInst::CmpInst(OtherOps op, unsigned short predicate, Value *LHS, Value *RHS,
                  const std::string &Name, BasicBlock *InsertAtEnd)
-  : Instruction(Type::Int1Ty, op, Ops, 2, InsertAtEnd) {
-  Ops[0].init(LHS, this);
-  Ops[1].init(RHS, this);
+  : Instruction(Type::Int1Ty, op,
+                OperandTraits<CmpInst>::op_begin(this),
+                OperandTraits<CmpInst>::operands(this),
+                InsertAtEnd) {
+  Op<0>().init(LHS, this);
+  Op<1>().init(RHS, this);
   SubclassData = predicate;
   setName(Name);
   if (op == Instruction::ICmp) {
@@ -2548,7 +2633,7 @@
   assert(Value && Default);
   ReservedSpace = 2+NumCases*2;
   NumOperands = 2;
-  OperandList = new Use[ReservedSpace];
+  OperandList = allocHungoffUses(ReservedSpace);
 
   OperandList[0].init(Value, this);
   OperandList[1].init(Default, this);
@@ -2576,7 +2661,7 @@
 
 SwitchInst::SwitchInst(const SwitchInst &SI)
   : TerminatorInst(Type::VoidTy, Instruction::Switch,
-                   new Use[SI.getNumOperands()], SI.getNumOperands()) {
+                   allocHungoffUses(SI.getNumOperands()), SI.getNumOperands()) {
   Use *OL = OperandList, *InOL = SI.OperandList;
   for (unsigned i = 0, E = SI.getNumOperands(); i != E; i+=2) {
     OL[i].init(InOL[i], this);
@@ -2585,7 +2670,7 @@
 }
 
 SwitchInst::~SwitchInst() {
-  delete [] OperandList;
+  dropHungoffUses(OperandList);
 }
 
 
@@ -2632,13 +2717,14 @@
 /// resizeOperands - resize operands - This adjusts the length of the operands
 /// list according to the following behavior:
 ///   1. If NumOps == 0, grow the operand list in response to a push_back style
-///      of operation.  This grows the number of ops by 1.5 times.
+///      of operation.  This grows the number of ops by 3 times.
 ///   2. If NumOps > NumOperands, reserve space for NumOps operands.
 ///   3. If NumOps == NumOperands, trim the reserved space.
 ///
 void SwitchInst::resizeOperands(unsigned NumOps) {
+  unsigned e = getNumOperands();
   if (NumOps == 0) {
-    NumOps = getNumOperands()/2*6;
+    NumOps = e*3;
   } else if (NumOps*2 > NumOperands) {
     // No resize needed.
     if (ReservedSpace >= NumOps) return;
@@ -2649,14 +2735,13 @@
   }
 
   ReservedSpace = NumOps;
-  Use *NewOps = new Use[NumOps];
+  Use *NewOps = allocHungoffUses(NumOps);
   Use *OldOps = OperandList;
-  for (unsigned i = 0, e = getNumOperands(); i != e; ++i) {
+  for (unsigned i = 0; i != e; ++i) {
       NewOps[i].init(OldOps[i], this);
-      OldOps[i].set(0);
   }
-  delete [] OldOps;
   OperandList = NewOps;
+  if (OldOps) Use::zap(OldOps, OldOps + e, true);
 }
 
 
@@ -2678,9 +2763,12 @@
                              const std::string &Name,
                              Instruction *InsertBef)
   : Instruction(cast<StructType>(Aggregate->getType())->getElementType(Index),
-                GetResult, &Aggr, 1, InsertBef) {
+                GetResult,
+                OperandTraits<GetResultInst>::op_begin(this),
+                OperandTraits<GetResultInst>::operands(this),
+                InsertBef) {
   assert(isValidOperands(Aggregate, Index) && "Invalid GetResultInst operands!");
-  Aggr.init(Aggregate, this);
+  Op<0>().init(Aggregate, this);
   Idx = Index;
   setName(Name);
 }
@@ -2714,14 +2802,14 @@
 }
 
 BinaryOperator *BinaryOperator::clone() const {
-  return create(getOpcode(), Ops[0], Ops[1]);
+  return create(getOpcode(), Op<0>(), Op<1>());
 }
 
 FCmpInst* FCmpInst::clone() const {
-  return new FCmpInst(getPredicate(), Ops[0], Ops[1]);
+  return new FCmpInst(getPredicate(), Op<0>(), Op<1>());
 }
 ICmpInst* ICmpInst::clone() const {
-  return new ICmpInst(getPredicate(), Ops[0], Ops[1]);
+  return new ICmpInst(getPredicate(), Op<0>(), Op<1>());
 }
 
 MallocInst *MallocInst::clone()   const { return new MallocInst(*this); }
@@ -2757,7 +2845,7 @@
 PHINode    *PHINode::clone()    const { return new PHINode(*this); }
 ReturnInst *ReturnInst::clone() const { return new(getNumOperands()) ReturnInst(*this); }
 BranchInst *BranchInst::clone() const { return new(getNumOperands()) BranchInst(*this); }
-SwitchInst *SwitchInst::clone() const { return new(getNumOperands()) SwitchInst(*this); }
+SwitchInst *SwitchInst::clone() const { return new SwitchInst(*this); }
 InvokeInst *InvokeInst::clone() const { return new(getNumOperands()) InvokeInst(*this); }
 UnwindInst *UnwindInst::clone() const { return new UnwindInst(); }
 UnreachableInst *UnreachableInst::clone() const { return new UnreachableInst();}
Index: lib/VMCore/Constants.cpp
===================================================================
--- lib/VMCore/Constants.cpp	(Revision 50410)
+++ lib/VMCore/Constants.cpp	(Arbeitskopie)
@@ -354,7 +354,9 @@
 
 ConstantArray::ConstantArray(const ArrayType *T,
                              const std::vector<Constant*> &V)
-  : Constant(T, ConstantArrayVal, new Use[V.size()], V.size()) {
+  : Constant(T, ConstantArrayVal,
+             OperandTraits<ConstantArray>::op_end(this) - V.size(),
+             V.size()) {
   assert(V.size() == T->getNumElements() &&
          "Invalid initializer vector for constant array");
   Use *OL = OperandList;
@@ -369,13 +371,12 @@
   }
 }
 
-ConstantArray::~ConstantArray() {
-  delete [] OperandList;
-}
 
 ConstantStruct::ConstantStruct(const StructType *T,
                                const std::vector<Constant*> &V)
-  : Constant(T, ConstantStructVal, new Use[V.size()], V.size()) {
+  : Constant(T, ConstantStructVal,
+             OperandTraits<ConstantStruct>::op_end(this) - V.size(),
+             V.size()) {
   assert(V.size() == T->getNumElements() &&
          "Invalid initializer vector for constant structure");
   Use *OL = OperandList;
@@ -392,14 +393,12 @@
   }
 }
 
-ConstantStruct::~ConstantStruct() {
-  delete [] OperandList;
-}
 
-
 ConstantVector::ConstantVector(const VectorType *T,
                                const std::vector<Constant*> &V)
-  : Constant(T, ConstantVectorVal, new Use[V.size()], V.size()) {
+  : Constant(T, ConstantVectorVal,
+             OperandTraits<ConstantVector>::op_end(this) - V.size(),
+             V.size()) {
   Use *OL = OperandList;
     for (std::vector<Constant*>::const_iterator I = V.begin(), E = V.end();
          I != E; ++I, ++OL) {
@@ -412,10 +411,8 @@
   }
 }
 
-ConstantVector::~ConstantVector() {
-  delete [] OperandList;
-}
 
+namespace llvm {
 // We declare several classes private to this file, so use an anonymous
 // namespace
 namespace {
@@ -424,49 +421,54 @@
 /// behind the scenes to implement unary constant exprs.
 class VISIBILITY_HIDDEN UnaryConstantExpr : public ConstantExpr {
   void *operator new(size_t, unsigned);  // DO NOT IMPLEMENT
-  Use Op;
 public:
   // allocate space for exactly one operand
   void *operator new(size_t s) {
     return User::operator new(s, 1);
   }
   UnaryConstantExpr(unsigned Opcode, Constant *C, const Type *Ty)
-    : ConstantExpr(Ty, Opcode, &Op, 1), Op(C, this) {}
+    : ConstantExpr(Ty, Opcode, &Op<0>(), 1) {
+    Op<0>() = C;
+  }
+  /// Transparently provide more efficient getOperand methods.
+  DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
 };
 
 /// BinaryConstantExpr - This class is private to Constants.cpp, and is used
 /// behind the scenes to implement binary constant exprs.
 class VISIBILITY_HIDDEN BinaryConstantExpr : public ConstantExpr {
   void *operator new(size_t, unsigned);  // DO NOT IMPLEMENT
-  Use Ops[2];
 public:
   // allocate space for exactly two operands
   void *operator new(size_t s) {
     return User::operator new(s, 2);
   }
   BinaryConstantExpr(unsigned Opcode, Constant *C1, Constant *C2)
-    : ConstantExpr(C1->getType(), Opcode, Ops, 2) {
-    Ops[0].init(C1, this);
-    Ops[1].init(C2, this);
+    : ConstantExpr(C1->getType(), Opcode, &Op<0>(), 2) {
+    Op<0>().init(C1, this);
+    Op<1>().init(C2, this);
   }
+  /// Transparently provide more efficient getOperand methods.
+  DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
 };
 
 /// SelectConstantExpr - This class is private to Constants.cpp, and is used
 /// behind the scenes to implement select constant exprs.
 class VISIBILITY_HIDDEN SelectConstantExpr : public ConstantExpr {
   void *operator new(size_t, unsigned);  // DO NOT IMPLEMENT
-  Use Ops[3];
 public:
   // allocate space for exactly three operands
   void *operator new(size_t s) {
     return User::operator new(s, 3);
   }
   SelectConstantExpr(Constant *C1, Constant *C2, Constant *C3)
-    : ConstantExpr(C2->getType(), Instruction::Select, Ops, 3) {
-    Ops[0].init(C1, this);
-    Ops[1].init(C2, this);
-    Ops[2].init(C3, this);
+    : ConstantExpr(C2->getType(), Instruction::Select, &Op<0>(), 3) {
+    Op<0>().init(C1, this);
+    Op<1>().init(C2, this);
+    Op<2>().init(C3, this);
   }
+  /// Transparently provide more efficient getOperand methods.
+  DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
 };
 
 /// ExtractElementConstantExpr - This class is private to
@@ -474,7 +476,6 @@
 /// extractelement constant exprs.
 class VISIBILITY_HIDDEN ExtractElementConstantExpr : public ConstantExpr {
   void *operator new(size_t, unsigned);  // DO NOT IMPLEMENT
-  Use Ops[2];
 public:
   // allocate space for exactly two operands
   void *operator new(size_t s) {
@@ -482,10 +483,12 @@
   }
   ExtractElementConstantExpr(Constant *C1, Constant *C2)
     : ConstantExpr(cast<VectorType>(C1->getType())->getElementType(), 
-                   Instruction::ExtractElement, Ops, 2) {
-    Ops[0].init(C1, this);
-    Ops[1].init(C2, this);
+                   Instruction::ExtractElement, &Op<0>(), 2) {
+    Op<0>().init(C1, this);
+    Op<1>().init(C2, this);
   }
+  /// Transparently provide more efficient getOperand methods.
+  DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
 };
 
 /// InsertElementConstantExpr - This class is private to
@@ -493,7 +496,6 @@
 /// insertelement constant exprs.
 class VISIBILITY_HIDDEN InsertElementConstantExpr : public ConstantExpr {
   void *operator new(size_t, unsigned);  // DO NOT IMPLEMENT
-  Use Ops[3];
 public:
   // allocate space for exactly three operands
   void *operator new(size_t s) {
@@ -501,11 +503,13 @@
   }
   InsertElementConstantExpr(Constant *C1, Constant *C2, Constant *C3)
     : ConstantExpr(C1->getType(), Instruction::InsertElement, 
-                   Ops, 3) {
-    Ops[0].init(C1, this);
-    Ops[1].init(C2, this);
-    Ops[2].init(C3, this);
+                   &Op<0>(), 3) {
+    Op<0>().init(C1, this);
+    Op<1>().init(C2, this);
+    Op<2>().init(C3, this);
   }
+  /// Transparently provide more efficient getOperand methods.
+  DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
 };
 
 /// ShuffleVectorConstantExpr - This class is private to
@@ -513,7 +517,6 @@
 /// shufflevector constant exprs.
 class VISIBILITY_HIDDEN ShuffleVectorConstantExpr : public ConstantExpr {
   void *operator new(size_t, unsigned);  // DO NOT IMPLEMENT
-  Use Ops[3];
 public:
   // allocate space for exactly three operands
   void *operator new(size_t s) {
@@ -521,32 +524,27 @@
   }
   ShuffleVectorConstantExpr(Constant *C1, Constant *C2, Constant *C3)
   : ConstantExpr(C1->getType(), Instruction::ShuffleVector, 
-                 Ops, 3) {
-    Ops[0].init(C1, this);
-    Ops[1].init(C2, this);
-    Ops[2].init(C3, this);
+                 &Op<0>(), 3) {
+    Op<0>().init(C1, this);
+    Op<1>().init(C2, this);
+    Op<2>().init(C3, this);
   }
+  /// Transparently provide more efficient getOperand methods.
+  DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
 };
 
 /// GetElementPtrConstantExpr - This class is private to Constants.cpp, and is
 /// used behind the scenes to implement getelementpr constant exprs.
 class VISIBILITY_HIDDEN GetElementPtrConstantExpr : public ConstantExpr {
   GetElementPtrConstantExpr(Constant *C, const std::vector<Constant*> &IdxList,
-                            const Type *DestTy)
-    : ConstantExpr(DestTy, Instruction::GetElementPtr,
-                   new Use[IdxList.size()+1], IdxList.size()+1) {
-    OperandList[0].init(C, this);
-    for (unsigned i = 0, E = IdxList.size(); i != E; ++i)
-      OperandList[i+1].init(IdxList[i], this);
-  }
+                            const Type *DestTy);
 public:
   static GetElementPtrConstantExpr *Create(Constant *C, const std::vector<Constant*> &IdxList,
-                                    const Type *DestTy) {
-    return new(IdxList.size() + 1/*FIXME*/) GetElementPtrConstantExpr(C, IdxList, DestTy);
+                                           const Type *DestTy) {
+    return new(IdxList.size() + 1) GetElementPtrConstantExpr(C, IdxList, DestTy);
   }
-  ~GetElementPtrConstantExpr() {
-    delete [] OperandList;
-  }
+  /// Transparently provide more efficient getOperand methods.
+  DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
 };
 
 // CompareConstantExpr - This class is private to Constants.cpp, and is used
@@ -559,18 +557,78 @@
     return User::operator new(s, 2);
   }
   unsigned short predicate;
-  Use Ops[2];
   CompareConstantExpr(Instruction::OtherOps opc, unsigned short pred, 
                       Constant* LHS, Constant* RHS)
-    : ConstantExpr(Type::Int1Ty, opc, Ops, 2), predicate(pred) {
-    OperandList[0].init(LHS, this);
-    OperandList[1].init(RHS, this);
+    : ConstantExpr(Type::Int1Ty, opc, &Op<0>(), 2), predicate(pred) {
+    Op<0>().init(LHS, this);
+    Op<1>().init(RHS, this);
   }
+  /// Transparently provide more efficient getOperand methods.
+  DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
 };
 
 } // end anonymous namespace
 
+template <>
+struct OperandTraits<UnaryConstantExpr> : FixedNumOperandTraits<1> {
+};
+DEFINE_TRANSPARENT_OPERAND_ACCESSORS(UnaryConstantExpr, Value)
 
+template <>
+struct OperandTraits<BinaryConstantExpr> : FixedNumOperandTraits<2> {
+};
+DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BinaryConstantExpr, Value)
+
+template <>
+struct OperandTraits<SelectConstantExpr> : FixedNumOperandTraits<3> {
+};
+DEFINE_TRANSPARENT_OPERAND_ACCESSORS(SelectConstantExpr, Value)
+
+template <>
+struct OperandTraits<ExtractElementConstantExpr> : FixedNumOperandTraits<2> {
+};
+DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ExtractElementConstantExpr, Value)
+
+template <>
+struct OperandTraits<InsertElementConstantExpr> : FixedNumOperandTraits<3> {
+};
+DEFINE_TRANSPARENT_OPERAND_ACCESSORS(InsertElementConstantExpr, Value)
+
+template <>
+struct OperandTraits<ShuffleVectorConstantExpr> : FixedNumOperandTraits<3> {
+};
+DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ShuffleVectorConstantExpr, Value)
+
+
+template <>
+struct OperandTraits<GetElementPtrConstantExpr> : VariadicOperandTraits<1> {
+};
+
+GetElementPtrConstantExpr::GetElementPtrConstantExpr
+  (Constant *C,
+   const std::vector<Constant*> &IdxList,
+   const Type *DestTy)
+    : ConstantExpr(DestTy, Instruction::GetElementPtr,
+                   OperandTraits<GetElementPtrConstantExpr>::op_end(this)
+                   - (IdxList.size()+1),
+                   IdxList.size()+1) {
+  OperandList[0].init(C, this);
+  for (unsigned i = 0, E = IdxList.size(); i != E; ++i)
+    OperandList[i+1].init(IdxList[i], this);
+}
+
+DEFINE_TRANSPARENT_OPERAND_ACCESSORS(GetElementPtrConstantExpr, Value)
+
+
+template <>
+struct OperandTraits<CompareConstantExpr> : FixedNumOperandTraits<2> {
+};
+DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CompareConstantExpr, Value)
+
+
+} // End llvm namespace
+
+
 // Utility function for determining if a ConstantExpr is a CastOp or not. This
 // can't be inline because we don't want to #include Instruction.h into
 // Constant.h
@@ -815,17 +873,29 @@
 //===----------------------------------------------------------------------===//
 //                      Factory Function Implementation
 
+
+// The number of operands for each ConstantCreator::create method is
+// determined by the ConstantTraits template.
 // ConstantCreator - A class that is used to create constants by
 // ValueMap*.  This class should be partially specialized if there is
 // something strange that needs to be done to interface to the ctor for the
 // constant.
 //
 namespace llvm {
+  template<class ValType>
+  struct ConstantTraits;
+
+  template<typename T, typename Alloc>
+  struct VISIBILITY_HIDDEN ConstantTraits< std::vector<T, Alloc> > {
+    static unsigned uses(const std::vector<T, Alloc>& v) {
+      return v.size();
+    }
+  };
+
   template<class ConstantClass, class TypeClass, class ValType>
   struct VISIBILITY_HIDDEN ConstantCreator {
     static ConstantClass *create(const TypeClass *Ty, const ValType &V) {
-      unsigned FIXME = 0; // = traits<ValType>::uses(V)
-      return new(FIXME) ConstantClass(Ty, V);
+      return new(ConstantTraits<ValType>::uses(V)) ConstantClass(Ty, V);
     }
   };
 
Index: lib/VMCore/Globals.cpp
===================================================================
--- lib/VMCore/Globals.cpp	(Revision 50410)
+++ lib/VMCore/Globals.cpp	(Arbeitskopie)
@@ -89,14 +89,13 @@
                                Module *ParentModule, bool ThreadLocal, 
                                unsigned AddressSpace)
   : GlobalValue(PointerType::get(Ty, AddressSpace), Value::GlobalVariableVal,
-                &Initializer, InitVal != 0, Link, Name),
+                OperandTraits<GlobalVariable>::op_begin(this),
+                InitVal != 0, Link, Name),
     isConstantGlobal(constant), isThreadLocalSymbol(ThreadLocal) {
   if (InitVal) {
     assert(InitVal->getType() == Ty &&
            "Initializer should be the same type as the GlobalVariable!");
-    Initializer.init(InitVal, this);
-  } else {
-    Initializer.init(0, this);
+    Op<0>().init(InitVal, this);
   }
 
   LeakDetector::addGarbageObject(this);
@@ -110,14 +109,13 @@
                                GlobalVariable *Before, bool ThreadLocal,
                                unsigned AddressSpace)
   : GlobalValue(PointerType::get(Ty, AddressSpace), Value::GlobalVariableVal,
-                &Initializer, InitVal != 0, Link, Name), 
+                OperandTraits<GlobalVariable>::op_begin(this),
+                InitVal != 0, Link, Name),
     isConstantGlobal(constant), isThreadLocalSymbol(ThreadLocal) {
   if (InitVal) {
     assert(InitVal->getType() == Ty &&
            "Initializer should be the same type as the GlobalVariable!");
-    Initializer.init(InitVal, this);
-  } else {
-    Initializer.init(0, this);
+    Op<0>().init(InitVal, this);
   }
   
   LeakDetector::addGarbageObject(this);
@@ -169,12 +167,12 @@
 GlobalAlias::GlobalAlias(const Type *Ty, LinkageTypes Link,
                          const std::string &Name, Constant* aliasee,
                          Module *ParentModule)
-  : GlobalValue(Ty, Value::GlobalAliasVal, &Aliasee, 1, Link, Name) {
+  : GlobalValue(Ty, Value::GlobalAliasVal, &Op<0>(), 1, Link, Name) {
   LeakDetector::addGarbageObject(this);
 
   if (aliasee)
     assert(aliasee->getType() == Ty && "Alias and aliasee types should match!");
-  Aliasee.init(aliasee, this);
+  Op<0>().init(aliasee, this);
 
   if (ParentModule)
     ParentModule->getAliasList().push_back(this);
Index: lib/Support/MemoryBuffer.cpp
===================================================================
--- lib/Support/MemoryBuffer.cpp	(Revision 50410)
+++ lib/Support/MemoryBuffer.cpp	(Arbeitskopie)
@@ -26,11 +26,10 @@
 #if !defined(_MSC_VER) && !defined(__MINGW32__)
 #include <unistd.h>
 #include <sys/uio.h>
-#include <sys/fcntl.h>
 #else
 #include <io.h>
-#include <fcntl.h>
 #endif
+#include <fcntl.h>
 using namespace llvm;
 
 //===----------------------------------------------------------------------===//
Index: CREDITS.TXT
===================================================================
--- CREDITS.TXT	(Revision 50410)
+++ CREDITS.TXT	(Arbeitskopie)
@@ -110,6 +110,10 @@
 D: Miscellaneous bug fixes
 D: Register allocation refactoring
 
+N: Gabor Greif
+E: ggreif@gmail.com
+D: Improvements for space efficiency
+
 N: Gordon Henriksen
 E: gordonhenriksen@mac.com
 D: Pluggable GC support
