[llvm-commits] [parallel] CVS: llvm/lib/VMCore/AsmWriter.cpp BasicBlock.cpp ConstantFolding.cpp Constants.cpp Function.cpp Instruction.cpp IntrinsicLowering.cpp ModuleProvider.cpp Pass.cpp PassManagerT.h SlotCalculator.cpp Type.cpp Verifier.cpp iCall.cpp iOperators.cpp

Misha Brukman brukman at cs.uiuc.edu
Mon Mar 1 18:04:44 PST 2004


Changes in directory llvm/lib/VMCore:

AsmWriter.cpp updated: 1.116 -> 1.116.2.1
BasicBlock.cpp updated: 1.38 -> 1.38.4.1
ConstantFolding.cpp updated: 1.50 -> 1.50.2.1
Constants.cpp updated: 1.71 -> 1.71.2.1
Function.cpp updated: 1.62.2.1 -> 1.62.2.2
Instruction.cpp updated: 1.33.2.1 -> 1.33.2.2
IntrinsicLowering.cpp updated: 1.5.2.1 -> 1.5.2.2
ModuleProvider.cpp updated: 1.8 -> 1.8.4.1
Pass.cpp updated: 1.54 -> 1.54.4.1
PassManagerT.h updated: 1.46 -> 1.46.4.1
SlotCalculator.cpp updated: 1.50 -> 1.50.2.1
Type.cpp updated: 1.87 -> 1.87.2.1
Verifier.cpp updated: 1.78.2.2 -> 1.78.2.3
iCall.cpp updated: 1.22 -> 1.22.4.1
iOperators.cpp updated: 1.25 -> 1.25.4.1

---
Log message:

Merge from trunk

---
Diffs of the changes:  (+583 -446)

Index: llvm/lib/VMCore/AsmWriter.cpp
diff -u llvm/lib/VMCore/AsmWriter.cpp:1.116 llvm/lib/VMCore/AsmWriter.cpp:1.116.2.1
--- llvm/lib/VMCore/AsmWriter.cpp:1.116	Tue Jan 20 13:50:22 2004
+++ llvm/lib/VMCore/AsmWriter.cpp	Mon Mar  1 17:58:16 2004
@@ -142,7 +142,6 @@
   // This is another base case for the recursion.  In this case, we know 
   // that we have looped back to a type that we have previously visited.
   // Generate the appropriate upreference to handle this.
-  // 
   if (Slot < CurSize)
     return "\\" + utostr(CurSize-Slot);       // Here's the upreference
 
@@ -153,15 +152,14 @@
   case Type::FunctionTyID: {
     const FunctionType *FTy = cast<FunctionType>(Ty);
     Result = calcTypeName(FTy->getReturnType(), TypeStack, TypeNames) + " (";
-    for (FunctionType::ParamTypes::const_iterator
-           I = FTy->getParamTypes().begin(),
-           E = FTy->getParamTypes().end(); I != E; ++I) {
-      if (I != FTy->getParamTypes().begin())
+    for (FunctionType::param_iterator I = FTy->param_begin(),
+           E = FTy->param_end(); I != E; ++I) {
+      if (I != FTy->param_begin())
         Result += ", ";
       Result += calcTypeName(*I, TypeStack, TypeNames);
     }
     if (FTy->isVarArg()) {
-      if (!FTy->getParamTypes().empty()) Result += ", ";
+      if (FTy->getNumParams()) Result += ", ";
       Result += "...";
     }
     Result += ")";
@@ -170,10 +168,9 @@
   case Type::StructTyID: {
     const StructType *STy = cast<StructType>(Ty);
     Result = "{ ";
-    for (StructType::ElementTypes::const_iterator
-           I = STy->getElementTypes().begin(),
-           E = STy->getElementTypes().end(); I != E; ++I) {
-      if (I != STy->getElementTypes().begin())
+    for (StructType::element_iterator I = STy->element_begin(),
+           E = STy->element_end(); I != E; ++I) {
+      if (I != STy->element_begin())
         Result += ", ";
       Result += calcTypeName(*I, TypeStack, TypeNames);
     }
@@ -202,9 +199,9 @@
 }
 
 
-// printTypeInt - The internal guts of printing out a type that has a
-// potentially named portion.
-//
+/// printTypeInt - The internal guts of printing out a type that has a
+/// potentially named portion.
+///
 static std::ostream &printTypeInt(std::ostream &Out, const Type *Ty,
                               std::map<const Type *, std::string> &TypeNames) {
   // Primitive types always print out their description, regardless of whether
@@ -228,10 +225,10 @@
 }
 
 
-// WriteTypeSymbolic - This attempts to write the specified type as a symbolic
-// type, iff there is an entry in the modules symbol table for the specified
-// type or one of it's component types.  This is slower than a simple x << Type;
-//
+/// WriteTypeSymbolic - This attempts to write the specified type as a symbolic
+/// type, iff there is an entry in the modules symbol table for the specified
+/// type or one of it's component types. This is slower than a simple x << Type
+///
 std::ostream &llvm::WriteTypeSymbolic(std::ostream &Out, const Type *Ty,
                                       const Module *M) {
   Out << " "; 
@@ -290,12 +287,9 @@
            "assuming that double is 64 bits!");
     Out << "0x" << utohexstr(*(uint64_t*)Ptr);
 
+  } else if (isa<ConstantAggregateZero>(CV)) {
+    Out << "zeroinitializer";
   } else if (const ConstantArray *CA = dyn_cast<ConstantArray>(CV)) {
-    if (CA->getNumOperands() > 5 && CA->isNullValue()) {
-      Out << "zeroinitializer";
-      return;
-    }
-
     // As a special case, print the array as a string if it is an array of
     // ubytes or an array of sbytes with positive values.
     // 
@@ -341,11 +335,6 @@
       Out << " ]";
     }
   } else if (const ConstantStruct *CS = dyn_cast<ConstantStruct>(CV)) {
-    if (CS->getNumOperands() > 5 && CS->isNullValue()) {
-      Out << "zeroinitializer";
-      return;
-    }
-
     Out << "{";
     if (CS->getNumOperands()) {
       Out << " ";
@@ -424,20 +413,23 @@
       }
       if (Slot >= 0)  Out << "%" << Slot;
       else if (PrintName)
-        Out << "<badref>";     // Not embedded into a location?
+        if (V->hasName())
+          Out << "<badref: " << getLLVMName(V->getName()) << ">";
+        else
+          Out << "<badref>";     // Not embedded into a location?
     }
   }
 }
 
 
 
-// WriteAsOperand - Write the name of the specified value out to the specified
-// ostream.  This can be useful when you just want to print int %reg126, not the
-// whole instruction that generated it.
-//
+/// WriteAsOperand - Write the name of the specified value out to the specified
+/// ostream.  This can be useful when you just want to print int %reg126, not
+/// the whole instruction that generated it.
+///
 std::ostream &llvm::WriteAsOperand(std::ostream &Out, const Value *V,
-                                   bool PrintType, 
-                             bool PrintName, const Module *Context) {
+                                   bool PrintType, bool PrintName, 
+                                   const Module *Context) {
   std::map<const Type *, std::string> TypeNames;
   if (Context == 0) Context = getModuleFromVal(V);
 
@@ -517,24 +509,22 @@
 std::ostream &AssemblyWriter::printTypeAtLeastOneLevel(const Type *Ty) {
   if (const FunctionType *FTy = dyn_cast<FunctionType>(Ty)) {
     printType(FTy->getReturnType()) << " (";
-    for (FunctionType::ParamTypes::const_iterator
-           I = FTy->getParamTypes().begin(),
-           E = FTy->getParamTypes().end(); I != E; ++I) {
-      if (I != FTy->getParamTypes().begin())
+    for (FunctionType::param_iterator I = FTy->param_begin(),
+           E = FTy->param_end(); I != E; ++I) {
+      if (I != FTy->param_begin())
         Out << ", ";
       printType(*I);
     }
     if (FTy->isVarArg()) {
-      if (!FTy->getParamTypes().empty()) Out << ", ";
+      if (FTy->getNumParams()) Out << ", ";
       Out << "...";
     }
     Out << ")";
   } else if (const StructType *STy = dyn_cast<StructType>(Ty)) {
     Out << "{ ";
-    for (StructType::ElementTypes::const_iterator
-           I = STy->getElementTypes().begin(),
-           E = STy->getElementTypes().end(); I != E; ++I) {
-      if (I != STy->getElementTypes().begin())
+    for (StructType::element_iterator I = STy->element_begin(),
+           E = STy->element_end(); I != E; ++I) {
+      if (I != STy->element_begin())
         Out << ", ";
       printType(*I);
     }
@@ -689,7 +679,7 @@
 
   // Finish printing arguments...
   if (FT->isVarArg()) {
-    if (FT->getParamTypes().size()) Out << ", ";
+    if (FT->getNumParams()) Out << ", ";
     Out << "...";  // Output varargs portion of signature!
   }
   Out << ")";
@@ -894,8 +884,8 @@
 
     Out << " )\n\t\t\tto";
     writeOperand(II->getNormalDest(), true);
-    Out << " except";
-    writeOperand(II->getExceptionalDest(), true);
+    Out << " unwind";
+    writeOperand(II->getUnwindDest(), true);
 
   } else if (const AllocationInst *AI = dyn_cast<AllocationInst>(&I)) {
     Out << " ";


Index: llvm/lib/VMCore/BasicBlock.cpp
diff -u llvm/lib/VMCore/BasicBlock.cpp:1.38 llvm/lib/VMCore/BasicBlock.cpp:1.38.4.1
--- llvm/lib/VMCore/BasicBlock.cpp:1.38	Fri Nov 21 10:52:05 2003
+++ llvm/lib/VMCore/BasicBlock.cpp	Mon Mar  1 17:58:16 2004
@@ -61,25 +61,8 @@
 template class SymbolTableListTraits<Instruction, BasicBlock, Function>;
 
 
-// BasicBlock ctor - If the function parameter is specified, the basic block is
-// automatically inserted at the end of the function.
-//
-BasicBlock::BasicBlock(const std::string &name, Function *Parent)
-  : Value(Type::LabelTy, Value::BasicBlockVal, name) {
-  // Initialize the instlist...
-  InstList.setItemParent(this);
-
-  // Make sure that we get added to a function
-  LeakDetector::addGarbageObject(this);
-
-  if (Parent)
-    Parent->getBasicBlockList().push_back(this);
-}
-
-/// BasicBlock ctor - If the InsertBefore parameter is specified, the basic
-/// block is automatically inserted right before the specified block.
-///
-BasicBlock::BasicBlock(const std::string &Name, BasicBlock *InsertBefore)
+BasicBlock::BasicBlock(const std::string &Name, Function *Parent,
+                       BasicBlock *InsertBefore)
   : Value(Type::LabelTy, Value::BasicBlockVal, Name) {
   // Initialize the instlist...
   InstList.setItemParent(this);
@@ -88,10 +71,11 @@
   LeakDetector::addGarbageObject(this);
 
   if (InsertBefore) {
-    assert(InsertBefore->getParent() &&
-           "Cannot insert block before another block that is not embedded into"
-           " a function yet!");
-    InsertBefore->getParent()->getBasicBlockList().insert(InsertBefore, this);
+    assert(Parent &&
+           "Cannot insert block before another block with no function!");
+    Parent->getBasicBlockList().insert(InsertBefore, this);
+  } else if (Parent) {
+    Parent->getBasicBlockList().push_back(this);
   }
 }
 
@@ -136,19 +120,6 @@
     I->dropAllReferences();
 }
 
-// hasConstantReferences() - This predicate is true if there is a 
-// reference to this basic block in the constant pool for this method.  For
-// example, if a block is reached through a switch table, that table resides
-// in the constant pool, and the basic block is reference from it.
-//
-bool BasicBlock::hasConstantReferences() const {
-  for (use_const_iterator I = use_begin(), E = use_end(); I != E; ++I)
-    if (isa<Constant>((Value*)*I))
-      return true;
-
-  return false;
-}
-
 // removePredecessor - This method is used to notify a BasicBlock that the
 // specified Predecessor of the block is no longer able to reach it.  This is
 // actually not used to update the Predecessor list, but is actually used to 
@@ -231,16 +202,11 @@
   assert(I != InstList.end() && 
 	 "Trying to get me to create degenerate basic block!");
 
-  BasicBlock *New = new BasicBlock(BBName, getParent());
+  BasicBlock *New = new BasicBlock(BBName, getParent(), getNext());
 
-  // Go from the end of the basic block through to the iterator pointer, moving
-  // to the new basic block...
-  Instruction *Inst = 0;
-  do {
-    iterator EndIt = end();
-    Inst = InstList.remove(--EndIt);                  // Remove from end
-    New->InstList.push_front(Inst);                   // Add to front
-  } while (Inst != &*I);   // Loop until we move the specified instruction.
+  // Move all of the specified instructions from the original basic block into
+  // the new basic block.
+  New->getInstList().splice(New->end(), this->getInstList(), I, end());
 
   // Add a branch instruction to the newly formed basic block.
   new BranchInst(New, this);


Index: llvm/lib/VMCore/ConstantFolding.cpp
diff -u llvm/lib/VMCore/ConstantFolding.cpp:1.50 llvm/lib/VMCore/ConstantFolding.cpp:1.50.2.1
--- llvm/lib/VMCore/ConstantFolding.cpp:1.50	Mon Jan 12 23:51:55 2004
+++ llvm/lib/VMCore/ConstantFolding.cpp	Mon Mar  1 17:58:16 2004
@@ -20,9 +20,7 @@
 
 #include "ConstantFolding.h"
 #include "llvm/Constants.h"
-#include "llvm/iPHINode.h"
-#include "llvm/iOperators.h"
-#include "llvm/InstrTypes.h"
+#include "llvm/Instructions.h"
 #include "llvm/DerivedTypes.h"
 #include "llvm/Support/GetElementPtrTypeIterator.h"
 #include <cmath>
@@ -625,11 +623,18 @@
     // If the first operand is simple, swap operands.
     assert((isa<ConstantPointerRef>(V2) || isa<ConstantExpr>(V2)) &&
            "Simple cases should have been handled by caller!");
-    return SetCondInst::getSwappedCondition(evaluateRelation(V2, V1));
+    Instruction::BinaryOps SwappedRelation = evaluateRelation(V2, V1);
+    if (SwappedRelation != Instruction::BinaryOpsEnd)
+      return SetCondInst::getSwappedCondition(SwappedRelation);
 
   } else if (const ConstantPointerRef *CPR1 = dyn_cast<ConstantPointerRef>(V1)){
-    if (isa<ConstantExpr>(V2))   // Swap as necessary.
-      return SetCondInst::getSwappedCondition(evaluateRelation(V2, V1));
+    if (isa<ConstantExpr>(V2)) {  // Swap as necessary.
+    Instruction::BinaryOps SwappedRelation = evaluateRelation(V2, V1);
+    if (SwappedRelation != Instruction::BinaryOpsEnd)
+      return SetCondInst::getSwappedCondition(SwappedRelation);
+    else
+      return Instruction::BinaryOpsEnd;
+    }
 
     // Now we know that the RHS is a ConstantPointerRef or simple constant,
     // which (since the types must match) means that it's a ConstantPointerNull.
@@ -920,8 +925,21 @@
       (IdxList.size() == 1 && IdxList[0]->isNullValue()))
     return const_cast<Constant*>(C);
 
-  // TODO If C is null and all idx's are null, return null of the right type.
-
+  if (C->isNullValue()) {
+    bool isNull = true;
+    for (unsigned i = 0, e = IdxList.size(); i != e; ++i)
+      if (!IdxList[i]->isNullValue()) {
+        isNull = false;
+        break;
+      }
+    if (isNull) {
+      std::vector<Value*> VIdxList(IdxList.begin(), IdxList.end());
+      const Type *Ty = GetElementPtrInst::getIndexedType(C->getType(), VIdxList,
+                                                         true);
+      assert(Ty != 0 && "Invalid indices for GEP!");
+      return ConstantPointerNull::get(PointerType::get(Ty));
+    }
+  }
 
   if (ConstantExpr *CE = dyn_cast<ConstantExpr>(const_cast<Constant*>(C))) {
     // Combine Indices - If the source pointer to this getelementptr instruction


Index: llvm/lib/VMCore/Constants.cpp
diff -u llvm/lib/VMCore/Constants.cpp:1.71 llvm/lib/VMCore/Constants.cpp:1.71.2.1
--- llvm/lib/VMCore/Constants.cpp:1.71	Wed Jan 14 11:51:53 2004
+++ llvm/lib/VMCore/Constants.cpp	Mon Mar  1 17:58:16 2004
@@ -116,21 +116,9 @@
   case Type::PointerTyID: 
     return ConstantPointerNull::get(cast<PointerType>(Ty));
 
-  case Type::StructTyID: {
-    const StructType *ST = cast<StructType>(Ty);
-    const StructType::ElementTypes &ETs = ST->getElementTypes();
-    std::vector<Constant*> Elements;
-    Elements.resize(ETs.size());
-    for (unsigned i = 0, e = ETs.size(); i != e; ++i)
-      Elements[i] = Constant::getNullValue(ETs[i]);
-    return ConstantStruct::get(ST, Elements);
-  }
-  case Type::ArrayTyID: {
-    const ArrayType *AT = cast<ArrayType>(Ty);
-    Constant *El = Constant::getNullValue(AT->getElementType());
-    unsigned NumElements = AT->getNumElements();
-    return ConstantArray::get(AT, std::vector<Constant*>(NumElements, El));
-  }
+  case Type::StructTyID:
+  case Type::ArrayTyID:
+    return ConstantAggregateZero::get(Ty);
   default:
     // Function, Type, Label, or Opaque type?
     assert(0 && "Cannot create a null constant of that type!");
@@ -263,14 +251,15 @@
 
 ConstantStruct::ConstantStruct(const StructType *T,
                                const std::vector<Constant*> &V) : Constant(T) {
-  const StructType::ElementTypes &ETypes = T->getElementTypes();
-  assert(V.size() == ETypes.size() &&
+  assert(V.size() == T->getNumElements() &&
          "Invalid initializer vector for constant structure");
   Operands.reserve(V.size());
   for (unsigned i = 0, e = V.size(); i != e; ++i) {
-    assert((V[i]->getType() == ETypes[i] ||
-            ((ETypes[i]->isAbstract() || V[i]->getType()->isAbstract()) &&
-             ETypes[i]->getPrimitiveID()==V[i]->getType()->getPrimitiveID())) &&
+    assert((V[i]->getType() == T->getElementType(i) ||
+            ((T->getElementType(i)->isAbstract() ||
+              V[i]->getType()->isAbstract()) &&
+             T->getElementType(i)->getPrimitiveID() == 
+                      V[i]->getType()->getPrimitiveID())) &&
            "Initializer for struct element doesn't match struct element type!");
     Operands.push_back(Use(V[i], this));
   }
@@ -330,11 +319,15 @@
   return ((Ty == Type::FloatTy || Ty == Type::DoubleTy) &&
           !isa<ConstantExpr>(CPV));
 }
+bool ConstantAggregateZero::classof(const Constant *CPV) {
+  return (isa<ArrayType>(CPV->getType()) || isa<StructType>(CPV->getType())) &&
+         CPV->isNullValue();
+}
 bool ConstantArray::classof(const Constant *CPV) {
-  return isa<ArrayType>(CPV->getType()) && !isa<ConstantExpr>(CPV);
+  return isa<ArrayType>(CPV->getType()) && !CPV->isNullValue();
 }
 bool ConstantStruct::classof(const Constant *CPV) {
-  return isa<StructType>(CPV->getType()) && !isa<ConstantExpr>(CPV);
+  return isa<StructType>(CPV->getType()) && !CPV->isNullValue();
 }
 
 bool ConstantPointerNull::classof(const Constant *CPV) {
@@ -417,7 +410,7 @@
     Values.push_back(Val);
   }
   
-  ConstantArray *Replacement = ConstantArray::get(getType(), Values);
+  Constant *Replacement = ConstantArray::get(getType(), Values);
   assert(Replacement != this && "I didn't contain From!");
 
   // Everyone using this now uses the replacement...
@@ -442,7 +435,7 @@
     Values.push_back(Val);
   }
   
-  ConstantStruct *Replacement = ConstantStruct::get(getType(), Values);
+  Constant *Replacement = ConstantStruct::get(getType(), Values);
   assert(Replacement != this && "I didn't contain From!");
 
   // Everyone using this now uses the replacement...
@@ -698,12 +691,100 @@
 
 //---- ConstantFP::get() implementation...
 //
-static ValueMap<double, Type, ConstantFP> FPConstants;
+namespace llvm {
+  template<>
+  struct ConstantCreator<ConstantFP, Type, uint64_t> {
+    static ConstantFP *create(const Type *Ty, uint64_t V) {
+      assert(Ty == Type::DoubleTy);
+      union {
+        double F;
+        uint64_t I;
+      } T;
+      T.I = V;
+      return new ConstantFP(Ty, T.F);
+    }
+  };
+  template<>
+  struct ConstantCreator<ConstantFP, Type, uint32_t> {
+    static ConstantFP *create(const Type *Ty, uint32_t V) {
+      assert(Ty == Type::FloatTy);
+      union {
+        float F;
+        uint32_t I;
+      } T;
+      T.I = V;
+      return new ConstantFP(Ty, T.F);
+    }
+  };
+}
+
+static ValueMap<uint64_t, Type, ConstantFP> DoubleConstants;
+static ValueMap<uint32_t, Type, ConstantFP> FloatConstants;
 
 ConstantFP *ConstantFP::get(const Type *Ty, double V) {
-  return FPConstants.getOrCreate(Ty, V);
+  if (Ty == Type::FloatTy) {
+    // Force the value through memory to normalize it.
+    union {
+      float F;
+      uint32_t I;
+    } T;
+    T.F = (float)V;
+    return FloatConstants.getOrCreate(Ty, T.I);
+  } else {
+    assert(Ty == Type::DoubleTy);
+    union {
+      double F;
+      uint64_t I;
+    } T;
+    T.F = V;
+    return DoubleConstants.getOrCreate(Ty, T.I);
+  }
+}
+
+//---- ConstantAggregateZero::get() implementation...
+//
+namespace llvm {
+  // ConstantAggregateZero does not take extra "value" argument...
+  template<class ValType>
+  struct ConstantCreator<ConstantAggregateZero, Type, ValType> {
+    static ConstantAggregateZero *create(const Type *Ty, const ValType &V){
+      return new ConstantAggregateZero(Ty);
+    }
+  };
+
+  template<>
+  struct ConvertConstantType<ConstantAggregateZero, Type> {
+    static void convert(ConstantAggregateZero *OldC, const Type *NewTy) {
+      // Make everyone now use a constant of the new type...
+      Constant *New = ConstantAggregateZero::get(NewTy);
+      assert(New != OldC && "Didn't replace constant??");
+      OldC->uncheckedReplaceAllUsesWith(New);
+      OldC->destroyConstant();     // This constant is now dead, destroy it.
+    }
+  };
+}
+
+static ValueMap<char, Type, ConstantAggregateZero> AggZeroConstants;
+
+Constant *ConstantAggregateZero::get(const Type *Ty) {
+  return AggZeroConstants.getOrCreate(Ty, 0);
+}
+
+// destroyConstant - Remove the constant from the constant table...
+//
+void ConstantAggregateZero::destroyConstant() {
+  AggZeroConstants.remove(this);
+  destroyConstantImpl();
+}
+
+void ConstantAggregateZero::replaceUsesOfWithOnConstant(Value *From, Value *To,
+                                                        bool DisableChecking) {
+  assert(0 && "No uses!");
+  abort();
 }
 
+
+
 //---- ConstantArray::get() implementation...
 //
 namespace llvm {
@@ -725,9 +806,18 @@
 static ValueMap<std::vector<Constant*>, ArrayType,
                 ConstantArray> ArrayConstants;
 
-ConstantArray *ConstantArray::get(const ArrayType *Ty,
-                                  const std::vector<Constant*> &V) {
-  return ArrayConstants.getOrCreate(Ty, V);
+Constant *ConstantArray::get(const ArrayType *Ty,
+                             const std::vector<Constant*> &V) {
+  // If this is an all-zero array, return a ConstantAggregateZero object
+  if (!V.empty()) {
+    Constant *C = V[0];
+    if (!C->isNullValue())
+      return ArrayConstants.getOrCreate(Ty, V);
+    for (unsigned i = 1, e = V.size(); i != e; ++i)
+      if (V[i] != C)
+        return ArrayConstants.getOrCreate(Ty, V);
+  }
+  return ConstantAggregateZero::get(Ty);
 }
 
 // destroyConstant - Remove the constant from the constant table...
@@ -741,7 +831,7 @@
 // contain the specified string.  A null terminator is added to the specified
 // string so that it may be used in a natural way...
 //
-ConstantArray *ConstantArray::get(const std::string &Str) {
+Constant *ConstantArray::get(const std::string &Str) {
   std::vector<Constant*> ElementVals;
 
   for (unsigned i = 0; i < Str.length(); ++i)
@@ -805,9 +895,14 @@
 static ValueMap<std::vector<Constant*>, StructType, 
                 ConstantStruct> StructConstants;
 
-ConstantStruct *ConstantStruct::get(const StructType *Ty,
-                                    const std::vector<Constant*> &V) {
-  return StructConstants.getOrCreate(Ty, V);
+Constant *ConstantStruct::get(const StructType *Ty,
+                              const std::vector<Constant*> &V) {
+  // Create a ConstantAggregateZero value if all elements are zeros...
+  for (unsigned i = 0, e = V.size(); i != e; ++i)
+    if (!V[i]->isNullValue())
+      return StructConstants.getOrCreate(Ty, V);
+
+  return ConstantAggregateZero::get(Ty);
 }
 
 // destroyConstant - Remove the constant from the constant table...
@@ -986,11 +1081,15 @@
 
 Constant *ConstantExpr::getGetElementPtrTy(const Type *ReqTy, Constant *C,
                                         const std::vector<Constant*> &IdxList) {
+  assert(GetElementPtrInst::getIndexedType(C->getType(),
+                   std::vector<Value*>(IdxList.begin(), IdxList.end()), true) &&
+         "GEP indices invalid!");
+
   if (Constant *FC = ConstantFoldGetElementPtr(C, IdxList))
     return FC;          // Fold a few common cases...
+
   assert(isa<PointerType>(C->getType()) &&
          "Non-pointer type for constant GetElementPtr expression");
-
   // Look up the constant in the table first to ensure uniqueness
   std::vector<Constant*> argVec(1, C);
   argVec.insert(argVec.end(), IdxList.begin(), IdxList.end());
@@ -1006,17 +1105,6 @@
   const Type *Ty = GetElementPtrInst::getIndexedType(C->getType(), VIdxList,
                                                      true);
   assert(Ty && "GEP indices invalid!");
-
-  if (C->isNullValue()) {
-    bool isNull = true;
-    for (unsigned i = 0, e = IdxList.size(); i != e; ++i)
-      if (!IdxList[i]->isNullValue()) {
-        isNull = false;
-        break;
-      }
-    if (isNull) return ConstantPointerNull::get(PointerType::get(Ty));
-  }
-
   return getGetElementPtrTy(PointerType::get(Ty), C, IdxList);
 }
 


Index: llvm/lib/VMCore/Function.cpp
diff -u llvm/lib/VMCore/Function.cpp:1.62.2.1 llvm/lib/VMCore/Function.cpp:1.62.2.2
--- llvm/lib/VMCore/Function.cpp:1.62.2.1	Mon Feb  2 16:33:06 2004
+++ llvm/lib/VMCore/Function.cpp	Mon Mar  1 17:58:16 2004
@@ -214,11 +214,22 @@
     if (getName() == "llvm.dbg.func.start")  return Intrinsic::dbg_func_start;
     if (getName() == "llvm.dbg.declare")     return Intrinsic::dbg_declare;
     break;
+  case 'f':
+    if (getName() == "llvm.frameaddress")  return Intrinsic::frameaddress;
+    break;
   case 'j':
     if (getName() == "llvm.join")  return Intrinsic::join;
     break;
   case 'l':
     if (getName() == "llvm.longjmp")  return Intrinsic::longjmp;
+    break;
+  case 'm':
+    if (getName() == "llvm.memcpy")  return Intrinsic::memcpy;
+    if (getName() == "llvm.memmove")  return Intrinsic::memmove;
+    if (getName() == "llvm.memset")  return Intrinsic::memset;
+    break;
+  case 'r':
+    if (getName() == "llvm.returnaddress")  return Intrinsic::returnaddress;
     break;
   case 's':
     if (getName() == "llvm.setjmp")     return Intrinsic::setjmp;


Index: llvm/lib/VMCore/Instruction.cpp
diff -u llvm/lib/VMCore/Instruction.cpp:1.33.2.1 llvm/lib/VMCore/Instruction.cpp:1.33.2.2
--- llvm/lib/VMCore/Instruction.cpp:1.33.2.1	Thu Jan 29 19:28:20 2004
+++ llvm/lib/VMCore/Instruction.cpp	Mon Mar  1 17:58:16 2004
@@ -35,13 +35,13 @@
 }
 
 void Instruction::setParent(BasicBlock *P) {
-  if (getParent())
-    LeakDetector::addGarbageObject(this);
+  if (getParent()) {
+    if (!P) LeakDetector::addGarbageObject(this);
+  } else {
+    if (P) LeakDetector::removeGarbageObject(this);
+  }
 
   Parent = P;
-
-  if (getParent())
-    LeakDetector::removeGarbageObject(this);
 }
 
 // Specialize setName to take care of symbol table majik


Index: llvm/lib/VMCore/IntrinsicLowering.cpp
diff -u llvm/lib/VMCore/IntrinsicLowering.cpp:1.5.2.1 llvm/lib/VMCore/IntrinsicLowering.cpp:1.5.2.2
--- llvm/lib/VMCore/IntrinsicLowering.cpp:1.5.2.1	Mon Feb  2 16:33:06 2004
+++ llvm/lib/VMCore/IntrinsicLowering.cpp	Mon Mar  1 17:58:16 2004
@@ -12,12 +12,55 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/IntrinsicLowering.h"
-#include "llvm/Constant.h"
+#include "llvm/Constants.h"
+#include "llvm/DerivedTypes.h"
 #include "llvm/Module.h"
-#include "llvm/Type.h"
 #include "llvm/iOther.h"
 using namespace llvm;
 
+/// ReplaceCallWith - This function is used when we want to lower an intrinsic
+/// call to a call of an external function.  This handles hard cases such as
+/// when there was already a prototype for the external function, and if that
+/// prototype doesn't match the arguments we expect to pass in.
+template <class ArgIt>
+static CallInst *ReplaceCallWith(const char *NewFn, CallInst *CI,
+                                 ArgIt ArgBegin, ArgIt ArgEnd,
+                                 const Type *RetTy, Function *&FCache) {
+  if (!FCache) {
+    // If we haven't already looked up this function, check to see if the
+    // program already contains a function with this name.
+    Module *M = CI->getParent()->getParent()->getParent();
+    FCache = M->getNamedFunction(NewFn);
+    if (!FCache) {
+      // It doesn't already exist in the program, insert a new definition now.
+      std::vector<const Type *> ParamTys;
+      for (ArgIt I = ArgBegin; I != ArgEnd; ++I)
+        ParamTys.push_back((*I)->getType());
+      FCache = M->getOrInsertFunction(NewFn,
+                                     FunctionType::get(RetTy, ParamTys, false));
+    }
+  }
+
+  const FunctionType *FT = FCache->getFunctionType();
+  std::vector<Value*> Operands;
+  unsigned ArgNo = 0;
+  for (ArgIt I = ArgBegin; I != ArgEnd && ArgNo != FT->getNumParams();
+       ++I, ++ArgNo) {
+    Value *Arg = *I;
+    if (Arg->getType() != FT->getParamType(ArgNo))
+      Arg = new CastInst(Arg, FT->getParamType(ArgNo), Arg->getName(), CI);
+    Operands.push_back(Arg);
+  }
+  // Pass nulls into any additional arguments...
+  for (; ArgNo != FT->getNumParams(); ++ArgNo)
+    Operands.push_back(Constant::getNullValue(FT->getParamType(ArgNo)));
+
+  std::string Name = CI->getName(); CI->setName("");
+  if (FT->getReturnType() == Type::VoidTy) Name.clear();
+  return new CallInst(FCache, Operands, Name, CI);
+}
+
+
 void DefaultIntrinsicLowering::LowerIntrinsicCall(CallInst *CI) {
   Function *Callee = CI->getCalledFunction();
   assert(Callee && "Cannot lower an indirect call!");
@@ -34,19 +77,43 @@
               << Callee->getName() << "'!\n";
     abort();
 
-    // The default implementation of setjmp/longjmp transforms setjmp into a
-    // noop that always returns zero and longjmp into a call to abort.  This
-    // allows code that never longjmps to work correctly.
-  case Intrinsic::setjmp:
-  case Intrinsic::sigsetjmp:
+    // The setjmp/longjmp intrinsics should only exist in the code if it was
+    // never optimized (ie, right out of the CFE), or if it has been hacked on
+    // by the lowerinvoke pass.  In both cases, the right thing to do is to
+    // convert the call to an explicit setjmp or longjmp call.
+  case Intrinsic::setjmp: {
+    static Function *SetjmpFCache = 0;
+    Value *V = ReplaceCallWith("setjmp", CI, CI->op_begin()+1, CI->op_end(),
+                               Type::IntTy, SetjmpFCache);
     if (CI->getType() != Type::VoidTy)
-      CI->replaceAllUsesWith(Constant::getNullValue(CI->getType()));
+      CI->replaceAllUsesWith(V);
     break;
+  }
+  case Intrinsic::sigsetjmp: 
+     if (CI->getType() != Type::VoidTy)
+       CI->replaceAllUsesWith(Constant::getNullValue(CI->getType()));
+     break;
 
   case Intrinsic::longjmp:
+    static Function *LongjmpFCache = 0;
+    ReplaceCallWith("longjmp", CI, CI->op_begin()+1, CI->op_end(),
+                    Type::VoidTy, LongjmpFCache);
+    break;
+
   case Intrinsic::siglongjmp:
     // Insert the call to abort
-    new CallInst(M->getOrInsertFunction("abort", Type::VoidTy, 0), "", CI);
+    static Function *AbortFCache = 0;
+    ReplaceCallWith("abort", CI, CI->op_end(), CI->op_end(), Type::VoidTy,
+                    AbortFCache);
+    break;
+
+  case Intrinsic::returnaddress:
+  case Intrinsic::frameaddress:
+    std::cerr << "WARNING: this target does not support the llvm."
+              << (Callee->getIntrinsicID() == Intrinsic::returnaddress ? 
+                  "return" : "frame") << "address intrinsic.\n";
+    CI->replaceAllUsesWith(ConstantPointerNull::get(
+                                            cast<PointerType>(CI->getType())));
     break;
 
   case Intrinsic::dbg_stoppoint:
@@ -62,8 +129,30 @@
     // Insert the call to abort
     new CallInst(M->getOrInsertFunction("abort", Type::VoidTy, 0), "", CI);
     break;    
-  }
 
+  case Intrinsic::memcpy:
+    // The memcpy intrinsic take an extra alignment argument that the memcpy
+    // libc function does not.
+    static Function *MemcpyFCache = 0;
+    ReplaceCallWith("memcpy", CI, CI->op_begin()+1, CI->op_end()-1,
+                    (*(CI->op_begin()+1))->getType(), MemcpyFCache);
+    break;
+  case Intrinsic::memmove:
+    // The memmove intrinsic take an extra alignment argument that the memmove
+    // libc function does not.
+    static Function *MemmoveFCache = 0;
+    ReplaceCallWith("memmove", CI, CI->op_begin()+1, CI->op_end()-1,
+                    (*(CI->op_begin()+1))->getType(), MemmoveFCache);
+    break;
+  case Intrinsic::memset:
+    // The memset intrinsic take an extra alignment argument that the memset
+    // libc function does not.
+    static Function *MemsetFCache = 0;
+    ReplaceCallWith("memset", CI, CI->op_begin()+1, CI->op_end()-1,
+                    (*(CI->op_begin()+1))->getType(), MemsetFCache);
+    break;
+  }
+  
   assert(CI->use_empty() &&
          "Lowering should have eliminated any uses of the intrinsic call!");
   CI->getParent()->getInstList().erase(CI);


Index: llvm/lib/VMCore/ModuleProvider.cpp
diff -u llvm/lib/VMCore/ModuleProvider.cpp:1.8 llvm/lib/VMCore/ModuleProvider.cpp:1.8.4.1
--- llvm/lib/VMCore/ModuleProvider.cpp:1.8	Fri Nov 21 14:23:48 2003
+++ llvm/lib/VMCore/ModuleProvider.cpp	Mon Mar  1 17:58:16 2004
@@ -24,15 +24,3 @@
 ModuleProvider::~ModuleProvider() {
   delete TheModule;
 }
-
-/// materializeFunction - make sure the given function is fully read.
-///
-Module* ModuleProvider::materializeModule() {
-  assert(TheModule && "Attempting to materialize an invalid module!");
-
-  for (Module::iterator i = TheModule->begin(), e = TheModule->end();
-       i != e; ++i)
-    materializeFunction(i);
-
-  return TheModule;
-}


Index: llvm/lib/VMCore/Pass.cpp
diff -u llvm/lib/VMCore/Pass.cpp:1.54 llvm/lib/VMCore/Pass.cpp:1.54.4.1
--- llvm/lib/VMCore/Pass.cpp:1.54	Fri Nov 21 14:23:48 2003
+++ llvm/lib/VMCore/Pass.cpp	Mon Mar  1 17:58:16 2004
@@ -91,8 +91,6 @@
 void FunctionPassManager::add(FunctionPass *P) { PM->add(P); }
 void FunctionPassManager::add(ImmutablePass *IP) { PM->add(IP); }
 bool FunctionPassManager::run(Function &F) { 
-  Function *mF = MP->getModule()->getNamedFunction(F.getName());
-  assert((&F == mF) && "ModuleProvider does not contain this function!");
   MP->materializeFunction(&F);
   return PM->run(F); 
 }
@@ -135,22 +133,31 @@
 }
 
 void PMDebug::PrintPassInformation(unsigned Depth, const char *Action,
-                                   Pass *P, Annotable *V) {
+                                   Pass *P, Module *M) {
   if (PassDebugging >= Executions) {
     std::cerr << (void*)P << std::string(Depth*2+1, ' ') << Action << " '" 
               << P->getPassName();
-    if (V) {
-      std::cerr << "' on ";
+    if (M) std::cerr << "' on Module '" << M->getModuleIdentifier() << "'\n";
+    std::cerr << "'...\n";
+  }
+}
 
-      if (dynamic_cast<Module*>(V)) {
-        std::cerr << "Module\n"; return;
-      } else if (Function *F = dynamic_cast<Function*>(V))
-        std::cerr << "Function '" << F->getName();
-      else if (BasicBlock *BB = dynamic_cast<BasicBlock*>(V))
-        std::cerr << "BasicBlock '" << BB->getName();
-      else if (Value *Val = dynamic_cast<Value*>(V))
-        std::cerr << typeid(*Val).name() << " '" << Val->getName();
-    }
+void PMDebug::PrintPassInformation(unsigned Depth, const char *Action,
+                                   Pass *P, Function *F) {
+  if (PassDebugging >= Executions) {
+    std::cerr << (void*)P << std::string(Depth*2+1, ' ') << Action << " '" 
+              << P->getPassName();
+    if (F) std::cerr << "' on Function '" << F->getName();
+    std::cerr << "'...\n";
+  }
+}
+
+void PMDebug::PrintPassInformation(unsigned Depth, const char *Action,
+                                   Pass *P, BasicBlock *BB) {
+  if (PassDebugging >= Executions) {
+    std::cerr << (void*)P << std::string(Depth*2+1, ' ') << Action << " '" 
+              << P->getPassName();
+    if (BB) std::cerr << "' on BasicBlock '" << BB->getName();
     std::cerr << "'...\n";
   }
 }
@@ -184,7 +191,7 @@
   std::cerr << std::string(Offset*2, ' ') << getPassName() << "\n";
 }
 
-// getPassName - Use C++ RTTI to get a SOMEWHAT intelligable name for the pass.
+// getPassName - Use C++ RTTI to get a SOMEWHAT intelligible name for the pass.
 //
 const char *Pass::getPassName() const {
   if (const PassInfo *PI = getPassInfo())


Index: llvm/lib/VMCore/PassManagerT.h
diff -u llvm/lib/VMCore/PassManagerT.h:1.46 llvm/lib/VMCore/PassManagerT.h:1.46.4.1
--- llvm/lib/VMCore/PassManagerT.h:1.46	Tue Nov 11 16:41:34 2003
+++ llvm/lib/VMCore/PassManagerT.h	Mon Mar  1 17:58:16 2004
@@ -31,8 +31,6 @@
 
 namespace llvm {
 
-class Annotable;
-
 //===----------------------------------------------------------------------===//
 // Pass debugging information.  Often it is useful to find out what pass is
 // running when a crash occurs in a utility.  When this library is compiled with
@@ -75,7 +73,9 @@
   }
 
   static void PrintArgumentInformation(const Pass *P);
-  static void PrintPassInformation(unsigned,const char*,Pass *, Annotable *);
+  static void PrintPassInformation(unsigned,const char*,Pass *, Module *);
+  static void PrintPassInformation(unsigned,const char*,Pass *, Function *);
+  static void PrintPassInformation(unsigned,const char*,Pass *, BasicBlock *);
   static void PrintAnalysisSetInfo(unsigned,const char*,Pass *P,
                                    const std::vector<AnalysisID> &);
 };
@@ -216,8 +216,7 @@
     for (unsigned i = 0, e = Passes.size(); i < e; ++i) {
       PassClass *P = Passes[i];
       
-      PMDebug::PrintPassInformation(getDepth(), "Executing Pass", P,
-                                    (Annotable*)M);
+      PMDebug::PrintPassInformation(getDepth(), "Executing Pass", P, M);
 
       // Get information about what analyses the pass uses...
       AnalysisUsage AnUsage;
@@ -259,8 +258,7 @@
                                     P->getPassName() + "'");
 
       if (Changed)
-        PMDebug::PrintPassInformation(getDepth()+1, "Made Modification", P,
-                                      (Annotable*)M);
+        PMDebug::PrintPassInformation(getDepth()+1, "Made Modification", P, M);
       PMDebug::PrintAnalysisSetInfo(getDepth(), "Preserved", P,
                                     AnUsage.getPreservedSet());
 
@@ -301,8 +299,7 @@
       std::vector<Pass*> &DeadPass = LastUserOf[P];
       for (std::vector<Pass*>::iterator I = DeadPass.begin(),E = DeadPass.end();
            I != E; ++I) {
-        PMDebug::PrintPassInformation(getDepth()+1, "Freeing Pass", *I,
-                                      (Annotable*)M);
+        PMDebug::PrintPassInformation(getDepth()+1, "Freeing Pass", *I, M);
         (*I)->releaseMemory();
       }
 


Index: llvm/lib/VMCore/SlotCalculator.cpp
diff -u llvm/lib/VMCore/SlotCalculator.cpp:1.50 llvm/lib/VMCore/SlotCalculator.cpp:1.50.2.1
--- llvm/lib/VMCore/SlotCalculator.cpp:1.50	Tue Jan 20 13:50:23 2004
+++ llvm/lib/VMCore/SlotCalculator.cpp	Mon Mar  1 17:58:16 2004
@@ -146,7 +146,8 @@
           TypePlane &Plane = Table[plane];
           unsigned FirstNonStringID = 0;
           for (unsigned i = 0, e = Plane.size(); i != e; ++i)
-            if (cast<ConstantArray>(Plane[i])->isString()) {
+            if (isa<ConstantAggregateZero>(Plane[i]) ||
+                cast<ConstantArray>(Plane[i])->isString()) {
               // Check to see if we have to shuffle this string around.  If not,
               // don't do anything.
               if (i != FirstNonStringID) {
@@ -381,6 +382,8 @@
 /// getOrCreateCompactionTableSlot - This method is used to build up the initial
 /// approximation of the compaction table.
 unsigned SlotCalculator::getOrCreateCompactionTableSlot(const Value *V) {
+  if (const ConstantPointerRef *CPR = dyn_cast<ConstantPointerRef>(V))
+    V = CPR->getValue();
   std::map<const Value*, unsigned>::iterator I =
     CompactionNodeMap.lower_bound(V);
   if (I != CompactionNodeMap.end() && I->first == V)


Index: llvm/lib/VMCore/Type.cpp
diff -u llvm/lib/VMCore/Type.cpp:1.87 llvm/lib/VMCore/Type.cpp:1.87.2.1
--- llvm/lib/VMCore/Type.cpp:1.87	Tue Dec 30 21:19:37 2003
+++ llvm/lib/VMCore/Type.cpp	Mon Mar  1 17:58:16 2004
@@ -18,7 +18,6 @@
 #include "Support/StringExtras.h"
 #include "Support/STLExtras.h"
 #include <algorithm>
-
 using namespace llvm;
 
 // DEBUG_MERGE_TYPES - Enable this #define to see how and when derived types are
@@ -27,6 +26,7 @@
 //
 //#define DEBUG_MERGE_TYPES 1
 
+AbstractTypeUser::~AbstractTypeUser() {}
 
 //===----------------------------------------------------------------------===//
 //                         Type Class Implementation
@@ -43,7 +43,7 @@
 static std::map<const Type*, std::string> AbstractTypeDescriptions;
 
 Type::Type(const std::string &name, PrimitiveID id)
-  : Value(Type::TypeTy, Value::TypeVal), ForwardType(0) {
+  : Value(Type::TypeTy, Value::TypeVal), RefCount(0), ForwardType(0) {
   if (!name.empty())
     ConcreteTypeDescriptions[this] = name;
   ID = id;
@@ -190,15 +190,14 @@
   case Type::FunctionTyID: {
     const FunctionType *FTy = cast<FunctionType>(Ty);
     Result = getTypeDescription(FTy->getReturnType(), TypeStack) + " (";
-    for (FunctionType::ParamTypes::const_iterator
-           I = FTy->getParamTypes().begin(),
-           E = FTy->getParamTypes().end(); I != E; ++I) {
-      if (I != FTy->getParamTypes().begin())
+    for (FunctionType::param_iterator I = FTy->param_begin(),
+           E = FTy->param_end(); I != E; ++I) {
+      if (I != FTy->param_begin())
         Result += ", ";
       Result += getTypeDescription(*I, TypeStack);
     }
     if (FTy->isVarArg()) {
-      if (!FTy->getParamTypes().empty()) Result += ", ";
+      if (FTy->getNumParams()) Result += ", ";
       Result += "...";
     }
     Result += ")";
@@ -207,10 +206,9 @@
   case Type::StructTyID: {
     const StructType *STy = cast<StructType>(Ty);
     Result = "{ ";
-    for (StructType::ElementTypes::const_iterator
-           I = STy->getElementTypes().begin(),
-           E = STy->getElementTypes().end(); I != E; ++I) {
-      if (I != STy->getElementTypes().begin())
+    for (StructType::element_iterator I = STy->element_begin(),
+           E = STy->element_end(); I != E; ++I) {
+      if (I != STy->element_begin())
         Result += ", ";
       Result += getTypeDescription(*I, TypeStack);
     }
@@ -263,7 +261,7 @@
 bool StructType::indexValid(const Value *V) const {
   // Structure indexes require unsigned integer constants.
   if (const ConstantUInt *CU = dyn_cast<ConstantUInt>(V))
-    return CU->getValue() < ETypes.size();
+    return CU->getValue() < ContainedTys.size();
   return false;
 }
 
@@ -273,9 +271,9 @@
 const Type *StructType::getTypeAtIndex(const Value *V) const {
   assert(isa<Constant>(V) && "Structure index must be a constant!!");
   unsigned Idx = cast<ConstantUInt>(V)->getValue();
-  assert(Idx < ETypes.size() && "Structure index out of range!");
+  assert(Idx < ContainedTys.size() && "Structure index out of range!");
   assert(indexValid(V) && "Invalid structure index!"); // Duplicate check
-  return ETypes[Idx];
+  return ContainedTys[Idx];
 }
 
 
@@ -360,12 +358,13 @@
 FunctionType::FunctionType(const Type *Result,
                            const std::vector<const Type*> &Params, 
                            bool IsVarArgs) : DerivedType(FunctionTyID), 
-    ResultType(PATypeHandle(Result, this)),
-    isVarArgs(IsVarArgs) {
+                                             isVarArgs(IsVarArgs) {
   bool isAbstract = Result->isAbstract();
-  ParamTys.reserve(Params.size());
-  for (unsigned i = 0; i < Params.size(); ++i) {
-    ParamTys.push_back(PATypeHandle(Params[i], this));
+  ContainedTys.reserve(Params.size()+1);
+  ContainedTys.push_back(PATypeHandle(Result, this));
+
+  for (unsigned i = 0; i != Params.size(); ++i) {
+    ContainedTys.push_back(PATypeHandle(Params[i], this));
     isAbstract |= Params[i]->isAbstract();
   }
 
@@ -375,11 +374,11 @@
 
 StructType::StructType(const std::vector<const Type*> &Types)
   : CompositeType(StructTyID) {
-  ETypes.reserve(Types.size());
+  ContainedTys.reserve(Types.size());
   bool isAbstract = false;
   for (unsigned i = 0; i < Types.size(); ++i) {
     assert(Types[i] != Type::VoidTy && "Void type in method prototype!!");
-    ETypes.push_back(PATypeHandle(Types[i], this));
+    ContainedTys.push_back(PATypeHandle(Types[i], this));
     isAbstract |= Types[i]->isAbstract();
   }
 
@@ -407,44 +406,22 @@
 #endif
 }
 
-
-// getAlwaysOpaqueTy - This function returns an opaque type.  It doesn't matter
-// _which_ opaque type it is, but the opaque type must never get resolved.
-//
-static Type *getAlwaysOpaqueTy() {
-  static Type *AlwaysOpaqueTy = OpaqueType::get();
-  static PATypeHolder Holder(AlwaysOpaqueTy);
-  return AlwaysOpaqueTy;
-}
-
-
-//===----------------------------------------------------------------------===//
-// dropAllTypeUses methods - These methods eliminate any possibly recursive type
-// references from a derived type.  The type must remain abstract, so we make
-// sure to use an always opaque type as an argument.
-//
-
-void FunctionType::dropAllTypeUses() {
-  ResultType = getAlwaysOpaqueTy();
-  ParamTys.clear();
-}
-
-void ArrayType::dropAllTypeUses() {
-  ElementType = getAlwaysOpaqueTy();
-}
-
-void StructType::dropAllTypeUses() {
-  ETypes.clear();
-  ETypes.push_back(PATypeHandle(getAlwaysOpaqueTy(), this));
-}
-
-void PointerType::dropAllTypeUses() {
-  ElementType = getAlwaysOpaqueTy();
+// dropAllTypeUses - When this (abstract) type is resolved to be equal to
+// another (more concrete) type, we must eliminate all references to other
+// types, to avoid some circular reference problems.
+void DerivedType::dropAllTypeUses() {
+  if (!ContainedTys.empty()) {
+    while (ContainedTys.size() > 1)
+      ContainedTys.pop_back();
+    
+    // The type must stay abstract.  To do this, we insert a pointer to a type
+    // that will never get resolved, thus will always be abstract.
+    static Type *AlwaysOpaqueTy = OpaqueType::get();
+    static PATypeHolder Holder(AlwaysOpaqueTy);
+    ContainedTys[0] = AlwaysOpaqueTy;
+  }
 }
 
-
-
-
 // isTypeAbstract - This is a recursive function that walks a type hierarchy
 // calculating whether or not a type is abstract.  Worst case it will have to do
 // a lot of traversing if you have some whacko opaque types, but in most cases,
@@ -467,7 +444,7 @@
   // one!
   for (Type::subtype_iterator I = subtype_begin(), E = subtype_end();
        I != E; ++I)
-    if (const_cast<Type*>(*I)->isTypeAbstract()) {
+    if (const_cast<Type*>(I->get())->isTypeAbstract()) {
       setAbstract(true);        // Restore the abstract bit.
       return true;              // This type is abstract if subtype is abstract!
     }
@@ -513,12 +490,10 @@
     return TypesEqual(PTy->getElementType(),
                       cast<PointerType>(Ty2)->getElementType(), EqTypes);
   } else if (const StructType *STy = dyn_cast<StructType>(Ty)) {
-    const StructType::ElementTypes &STyE = STy->getElementTypes();
-    const StructType::ElementTypes &STyE2 =
-      cast<StructType>(Ty2)->getElementTypes();
-    if (STyE.size() != STyE2.size()) return false;
-    for (unsigned i = 0, e = STyE.size(); i != e; ++i)
-      if (!TypesEqual(STyE[i], STyE2[i], EqTypes))
+    const StructType *STy2 = cast<StructType>(Ty2);
+    if (STy->getNumElements() != STy2->getNumElements()) return false;
+    for (unsigned i = 0, e = STy2->getNumElements(); i != e; ++i)
+      if (!TypesEqual(STy->getElementType(i), STy2->getElementType(i), EqTypes))
         return false;
     return true;
   } else if (const ArrayType *ATy = dyn_cast<ArrayType>(Ty)) {
@@ -528,13 +503,11 @@
   } else if (const FunctionType *FTy = dyn_cast<FunctionType>(Ty)) {
     const FunctionType *FTy2 = cast<FunctionType>(Ty2);
     if (FTy->isVarArg() != FTy2->isVarArg() ||
-        FTy->getParamTypes().size() != FTy2->getParamTypes().size() ||
+        FTy->getNumParams() != FTy2->getNumParams() ||
         !TypesEqual(FTy->getReturnType(), FTy2->getReturnType(), EqTypes))
       return false;
-    const FunctionType::ParamTypes &FTyP = FTy->getParamTypes();
-    const FunctionType::ParamTypes &FTy2P = FTy2->getParamTypes();
-    for (unsigned i = 0, e = FTyP.size(); i != e; ++i)
-      if (!TypesEqual(FTyP[i], FTy2P[i], EqTypes))
+    for (unsigned i = 0, e = FTy2->getNumParams(); i != e; ++i)
+      if (!TypesEqual(FTy->getParamType(i), FTy2->getParamType(i), EqTypes))
         return false;
     return true;
   } else {
@@ -548,6 +521,38 @@
   return TypesEqual(Ty, Ty2, EqTypes);
 }
 
+// TypeHasCycleThrough - Return true there is a path from CurTy to TargetTy in
+// the type graph.  We know that Ty is an abstract type, so if we ever reach a
+// non-abstract type, we know that we don't need to search the subgraph.
+static bool TypeHasCycleThrough(const Type *TargetTy, const Type *CurTy,
+                                std::set<const Type*> &VisitedTypes) {
+  if (TargetTy == CurTy) return true;
+  if (!CurTy->isAbstract()) return false;
+
+  std::set<const Type*>::iterator VTI = VisitedTypes.lower_bound(CurTy);
+  if (VTI != VisitedTypes.end() && *VTI == CurTy)
+    return false;
+  VisitedTypes.insert(VTI, CurTy);
+
+  for (Type::subtype_iterator I = CurTy->subtype_begin(),
+         E = CurTy->subtype_end(); I != E; ++I)
+    if (TypeHasCycleThrough(TargetTy, *I, VisitedTypes))
+      return true;
+  return false;
+}
+
+
+/// TypeHasCycleThroughItself - Return true if the specified type has a cycle
+/// back to itself.
+static bool TypeHasCycleThroughItself(const Type *Ty) {
+  assert(Ty->isAbstract() && "This code assumes that Ty was abstract!");
+  std::set<const Type*> VisitedTypes;
+  for (Type::subtype_iterator I = Ty->subtype_begin(), E = Ty->subtype_end();
+       I != E; ++I)
+    if (TypeHasCycleThrough(Ty, *I, VisitedTypes))
+      return true;
+  return false;
+}
 
 
 //===----------------------------------------------------------------------===//
@@ -556,15 +561,18 @@
 
 // TypeMap - Make sure that only one instance of a particular type may be
 // created on any given run of the compiler... note that this involves updating
-// our map if an abstract type gets refined somehow...
+// our map if an abstract type gets refined somehow.
 //
 namespace llvm {
 template<class ValType, class TypeClass>
 class TypeMap {
-  typedef std::map<ValType, PATypeHolder> MapTy;
-  MapTy Map;
+  std::map<ValType, PATypeHolder> Map;
+
+  /// TypesByHash - Keep track of each type by its structure hash value.
+  ///
+  std::multimap<unsigned, PATypeHolder> TypesByHash;
 public:
-  typedef typename MapTy::iterator iterator;
+  typedef typename std::map<ValType, PATypeHolder>::iterator iterator;
   ~TypeMap() { print("ON EXIT"); }
 
   inline TypeClass *get(const ValType &V) {
@@ -572,58 +580,65 @@
     return I != Map.end() ? cast<TypeClass>((Type*)I->second.get()) : 0;
   }
 
-  inline void add(const ValType &V, TypeClass *T) {
-    Map.insert(std::make_pair(V, T));
+  inline void add(const ValType &V, TypeClass *Ty) {
+    Map.insert(std::make_pair(V, Ty));
+
+    // If this type has a cycle, remember it.
+    TypesByHash.insert(std::make_pair(ValType::hashTypeStructure(Ty), Ty));
     print("add");
   }
 
-  iterator getEntryForType(TypeClass *Ty) {
-    iterator I = Map.find(ValType::get(Ty));
-    if (I == Map.end()) print("ERROR!");
-    assert(I != Map.end() && "Didn't find type entry!");
-    assert(I->second.get() == (const Type*)Ty && "Type entry wrong?");
-    return I;
+  void RemoveFromTypesByHash(unsigned Hash, const Type *Ty) {
+    std::multimap<unsigned, PATypeHolder>::iterator I = 
+      TypesByHash.lower_bound(Hash);
+    while (I->second != Ty) {
+      ++I;
+      assert(I != TypesByHash.end() && I->first == Hash);
+    }
+    TypesByHash.erase(I);
   }
 
   /// finishRefinement - This method is called after we have updated an existing
   /// type with its new components.  We must now either merge the type away with
   /// some other type or reinstall it in the map with it's new configuration.
   /// The specified iterator tells us what the type USED to look like.
-  void finishRefinement(iterator TyIt) {
+  void finishRefinement(TypeClass *Ty, const DerivedType *OldType,
+                        const Type *NewType) {
+    assert((Ty->isAbstract() || !OldType->isAbstract()) &&
+           "Refining a non-abstract type!");
+#ifdef DEBUG_MERGE_TYPES
+    std::cerr << "refineAbstractTy(" << (void*)OldType << "[" << *OldType
+              << "], " << (void*)NewType << " [" << *NewType << "])\n";
+#endif
+
     // Make a temporary type holder for the type so that it doesn't disappear on
     // us when we erase the entry from the map.
-    PATypeHolder TyHolder = TyIt->second;
-    TypeClass *Ty = cast<TypeClass>((Type*)TyHolder.get());
+    PATypeHolder TyHolder = Ty;
 
     // The old record is now out-of-date, because one of the children has been
     // updated.  Remove the obsolete entry from the map.
-    Map.erase(TyIt);
+    Map.erase(ValType::get(Ty));
 
-    // Determine whether there is a cycle through the type graph which passes
-    // back through this type.  Other cycles are ok though.
-    bool HasTypeCycle = false;
-    {
-      std::set<const Type*> VisitedTypes;
-      for (Type::subtype_iterator I = Ty->subtype_begin(),
-             E = Ty->subtype_end(); I != E; ++I) {
-        for (df_ext_iterator<const Type *, std::set<const Type*> > 
-               DFI = df_ext_begin(*I, VisitedTypes),
-               E = df_ext_end(*I, VisitedTypes); DFI != E; ++DFI)
-          if (*DFI == Ty) {
-            HasTypeCycle = true;
-            goto FoundCycle;
-          }
+    // Remember the structural hash for the type before we start hacking on it,
+    // in case we need it later.  Also, check to see if the type HAD a cycle
+    // through it, if so, we know it will when we hack on it.
+    unsigned OldTypeHash = ValType::hashTypeStructure(Ty);
+
+    // Find the type element we are refining... and change it now!
+    for (unsigned i = 0, e = Ty->ContainedTys.size(); i != e; ++i)
+      if (Ty->ContainedTys[i] == OldType) {
+        Ty->ContainedTys[i].removeUserFromConcrete();
+        Ty->ContainedTys[i] = NewType;
       }
-    }
-  FoundCycle:
-
-    ValType Key = ValType::get(Ty);
 
+    unsigned TypeHash = ValType::hashTypeStructure(Ty);
+    
     // If there are no cycles going through this node, we can do a simple,
     // efficient lookup in the map, instead of an inefficient nasty linear
     // lookup.
-    if (!HasTypeCycle) {
-      iterator I = Map.find(Key);
+    bool TypeHasCycle = Ty->isAbstract() && TypeHasCycleThroughItself(Ty);
+    if (!TypeHasCycle) {
+      iterator I = Map.find(ValType::get(Ty));
       if (I != Map.end()) {
         // We already have this type in the table.  Get rid of the newly refined
         // type.
@@ -631,6 +646,7 @@
         TypeClass *NewTy = cast<TypeClass>((Type*)I->second.get());
         
         // Refined to a different type altogether?
+        RemoveFromTypesByHash(TypeHash, Ty);
         Ty->refineAbstractTypeTo(NewTy);
         return;
       }
@@ -640,20 +656,46 @@
       // structurally identical to the newly refined type.  If so, this type
       // gets refined to the pre-existing type.
       //
-      for (iterator I = Map.begin(), E = Map.end(); I != E; ++I)
-        if (TypesEqual(Ty, I->second)) {
-          assert(Ty->isAbstract() && "Replacing a non-abstract type?");
-          TypeClass *NewTy = cast<TypeClass>((Type*)I->second.get());
-          
-          // Refined to a different type altogether?
-          Ty->refineAbstractTypeTo(NewTy);
-          return;
+      std::multimap<unsigned, PATypeHolder>::iterator I,E, Entry;
+      tie(I, E) = TypesByHash.equal_range(TypeHash);
+      Entry = E;
+      for (; I != E; ++I) {
+        if (I->second != Ty) {
+          if (TypesEqual(Ty, I->second)) {
+            assert(Ty->isAbstract() && "Replacing a non-abstract type?");
+            TypeClass *NewTy = cast<TypeClass>((Type*)I->second.get());
+            
+            if (Entry == E) {
+              // Find the location of Ty in the TypesByHash structure.
+              while (I->second != Ty) {
+                ++I;
+                assert(I != E && "Structure doesn't contain type??");
+              }
+              Entry = I;
+            }
+
+            TypesByHash.erase(Entry);
+            Ty->refineAbstractTypeTo(NewTy);
+            return;
+          }
+        } else {
+          // Remember the position of 
+          Entry = I;
         }
+      }
+    }
+
+    // If we succeeded, we need to insert the type into the cycletypes table.
+    // There are several cases here, depending on whether the original type
+    // had the same hash code and was itself cyclic.
+    if (TypeHash != OldTypeHash) {
+      RemoveFromTypesByHash(OldTypeHash, Ty);
+      TypesByHash.insert(std::make_pair(TypeHash, Ty));
     }
 
     // If there is no existing type of the same structure, we reinsert an
     // updated record into the map.
-    Map.insert(std::make_pair(Key, Ty));
+    Map.insert(std::make_pair(ValType::get(Ty), Ty));
 
     // If the type is currently thought to be abstract, rescan all of our
     // subtypes to see if the type has just become concrete!
@@ -666,23 +708,12 @@
     }
   }
   
-  void remove(const ValType &OldVal) {
-    iterator I = Map.find(OldVal);
-    assert(I != Map.end() && "TypeMap::remove, element not found!");
-    Map.erase(I);
-  }
-
-  void remove(iterator I) {
-    assert(I != Map.end() && "Cannot remove invalid iterator pointer!");
-    Map.erase(I);
-  }
-
   void print(const char *Arg) const {
 #ifdef DEBUG_MERGE_TYPES
     std::cerr << "TypeMap<>::" << Arg << " table contents:\n";
     unsigned i = 0;
-    for (typename MapTy::const_iterator I = Map.begin(), E = Map.end();
-         I != E; ++I)
+    for (typename std::map<ValType, PATypeHolder>::const_iterator I
+           = Map.begin(), E = Map.end(); I != E; ++I)
       std::cerr << " " << (++i) << ". " << (void*)I->second.get() << " " 
                 << *I->second.get() << "\n";
 #endif
@@ -713,6 +744,10 @@
 
   static FunctionValType get(const FunctionType *FT);
 
+  static unsigned hashTypeStructure(const FunctionType *FT) {
+    return FT->getNumParams()*2+FT->isVarArg();
+  }
+
   // Subclass should override this... to update self as usual
   void doRefinement(const DerivedType *OldType, const Type *NewType) {
     if (RetTy == OldType) RetTy = NewType;
@@ -736,8 +771,8 @@
 FunctionValType FunctionValType::get(const FunctionType *FT) {
   // Build up a FunctionValType
   std::vector<const Type *> ParamTypes;
-  ParamTypes.reserve(FT->getParamTypes().size());
-  for (unsigned i = 0, e = FT->getParamTypes().size(); i != e; ++i)
+  ParamTypes.reserve(FT->getNumParams());
+  for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i)
     ParamTypes.push_back(FT->getParamType(i));
   return FunctionValType(FT->getReturnType(), ParamTypes, FT->isVarArg());
 }
@@ -773,6 +808,10 @@
     return ArrayValType(AT->getElementType(), AT->getNumElements());
   }
 
+  static unsigned hashTypeStructure(const ArrayType *AT) {
+    return AT->getNumElements();
+  }
+
   // Subclass should override this... to update self as usual
   void doRefinement(const DerivedType *OldType, const Type *NewType) {
     assert(ValTy == OldType);
@@ -818,13 +857,17 @@
 
   static StructValType get(const StructType *ST) {
     std::vector<const Type *> ElTypes;
-    ElTypes.reserve(ST->getElementTypes().size());
-    for (unsigned i = 0, e = ST->getElementTypes().size(); i != e; ++i)
-      ElTypes.push_back(ST->getElementTypes()[i]);
+    ElTypes.reserve(ST->getNumElements());
+    for (unsigned i = 0, e = ST->getNumElements(); i != e; ++i)
+      ElTypes.push_back(ST->getElementType(i));
     
     return StructValType(ElTypes);
   }
 
+  static unsigned hashTypeStructure(const StructType *ST) {
+    return ST->getNumElements();
+  }
+
   // Subclass should override this... to update self as usual
   void doRefinement(const DerivedType *OldType, const Type *NewType) {
     for (unsigned i = 0; i < ElTypes.size(); ++i)
@@ -871,6 +914,10 @@
     return PointerValType(PT->getElementType());
   }
 
+  static unsigned hashTypeStructure(const PointerType *PT) {
+    return 0;
+  }
+
   // Subclass should override this... to update self as usual
   void doRefinement(const DerivedType *OldType, const Type *NewType) {
     assert(ValTy == OldType);
@@ -901,14 +948,6 @@
   return PT;
 }
 
-namespace llvm {
-void debug_type_tables() {
-  FunctionTypes.dump();
-  ArrayTypes.dump();
-  StructTypes.dump();
-  PointerTypes.dump();
-}
-}
 
 //===----------------------------------------------------------------------===//
 //                     Derived Type Refinement Functions
@@ -938,7 +977,7 @@
             << *this << "][" << i << "] User = " << U << "\n";
 #endif
     
-  if (AbstractTypeUsers.empty() && RefCount == 0 && isAbstract()) {
+  if (AbstractTypeUsers.empty() && getRefCount() == 0 && isAbstract()) {
 #ifdef DEBUG_MERGE_TYPES
     std::cerr << "DELETEing unused abstract type: <" << *this
               << ">[" << (void*)this << "]" << "\n";
@@ -1044,30 +1083,7 @@
 //
 void FunctionType::refineAbstractType(const DerivedType *OldType,
                                       const Type *NewType) {
-  assert((isAbstract() || !OldType->isAbstract()) &&
-         "Refining a non-abstract type!");
-#ifdef DEBUG_MERGE_TYPES
-  std::cerr << "FunctionTy::refineAbstractTy(" << (void*)OldType << "[" 
-            << *OldType << "], " << (void*)NewType << " [" 
-            << *NewType << "])\n";
-#endif
-
-  // Look up our current type map entry..
-  TypeMap<FunctionValType, FunctionType>::iterator TMI =
-    FunctionTypes.getEntryForType(this);
-
-  // Find the type element we are refining...
-  if (ResultType == OldType) {
-    ResultType.removeUserFromConcrete();
-    ResultType = NewType;
-  }
-  for (unsigned i = 0, e = ParamTys.size(); i != e; ++i)
-    if (ParamTys[i] == OldType) {
-      ParamTys[i].removeUserFromConcrete();
-      ParamTys[i] = NewType;
-    }
-
-  FunctionTypes.finishRefinement(TMI);
+  FunctionTypes.finishRefinement(this, OldType, NewType);
 }
 
 void FunctionType::typeBecameConcrete(const DerivedType *AbsTy) {
@@ -1081,23 +1097,7 @@
 //
 void ArrayType::refineAbstractType(const DerivedType *OldType,
 				   const Type *NewType) {
-  assert((isAbstract() || !OldType->isAbstract()) &&
-         "Refining a non-abstract type!");
-#ifdef DEBUG_MERGE_TYPES
-  std::cerr << "ArrayTy::refineAbstractTy(" << (void*)OldType << "[" 
-            << *OldType << "], " << (void*)NewType << " [" 
-            << *NewType << "])\n";
-#endif
-
-  // Look up our current type map entry..
-  TypeMap<ArrayValType, ArrayType>::iterator TMI =
-    ArrayTypes.getEntryForType(this);
-
-  assert(getElementType() == OldType);
-  ElementType.removeUserFromConcrete();
-  ElementType = NewType;
-
-  ArrayTypes.finishRefinement(TMI);
+  ArrayTypes.finishRefinement(this, OldType, NewType);
 }
 
 void ArrayType::typeBecameConcrete(const DerivedType *AbsTy) {
@@ -1111,27 +1111,7 @@
 //
 void StructType::refineAbstractType(const DerivedType *OldType,
 				    const Type *NewType) {
-  assert((isAbstract() || !OldType->isAbstract()) &&
-         "Refining a non-abstract type!");
-#ifdef DEBUG_MERGE_TYPES
-  std::cerr << "StructTy::refineAbstractTy(" << (void*)OldType << "[" 
-            << *OldType << "], " << (void*)NewType << " [" 
-            << *NewType << "])\n";
-#endif
-
-  // Look up our current type map entry..
-  TypeMap<StructValType, StructType>::iterator TMI =
-    StructTypes.getEntryForType(this);
-
-  for (int i = ETypes.size()-1; i >= 0; --i)
-    if (ETypes[i] == OldType) {
-      ETypes[i].removeUserFromConcrete();
-
-      // Update old type to new type in the array...
-      ETypes[i] = NewType;
-    }
-
-  StructTypes.finishRefinement(TMI);
+  StructTypes.finishRefinement(this, OldType, NewType);
 }
 
 void StructType::typeBecameConcrete(const DerivedType *AbsTy) {
@@ -1144,23 +1124,7 @@
 //
 void PointerType::refineAbstractType(const DerivedType *OldType,
 				     const Type *NewType) {
-  assert((isAbstract() || !OldType->isAbstract()) &&
-         "Refining a non-abstract type!");
-#ifdef DEBUG_MERGE_TYPES
-  std::cerr << "PointerTy::refineAbstractTy(" << (void*)OldType << "[" 
-            << *OldType << "], " << (void*)NewType << " [" 
-            << *NewType << "])\n";
-#endif
-
-  // Look up our current type map entry..
-  TypeMap<PointerValType, PointerType>::iterator TMI =
-    PointerTypes.getEntryForType(this);
-
-  assert(ElementType == OldType);
-  ElementType.removeUserFromConcrete();
-  ElementType = NewType;
-
-  PointerTypes.finishRefinement(TMI);
+  PointerTypes.finishRefinement(this, OldType, NewType);
 }
 
 void PointerType::typeBecameConcrete(const DerivedType *AbsTy) {


Index: llvm/lib/VMCore/Verifier.cpp
diff -u llvm/lib/VMCore/Verifier.cpp:1.78.2.2 llvm/lib/VMCore/Verifier.cpp:1.78.2.3
--- llvm/lib/VMCore/Verifier.cpp:1.78.2.2	Sat Feb  7 17:55:02 2004
+++ llvm/lib/VMCore/Verifier.cpp	Mon Mar  1 17:58:16 2004
@@ -41,17 +41,14 @@
 
 #include "llvm/Analysis/Verifier.h"
 #include "llvm/Assembly/Writer.h"
+#include "llvm/Constants.h"
 #include "llvm/Pass.h"
 #include "llvm/Module.h"
 #include "llvm/DerivedTypes.h"
-#include "llvm/iPHINode.h"
-#include "llvm/iTerminators.h"
-#include "llvm/iOther.h"
-#include "llvm/iOperators.h"
-#include "llvm/iMemory.h"
-#include "llvm/SymbolTable.h"
-#include "llvm/PassManager.h"
+#include "llvm/Instructions.h"
 #include "llvm/Intrinsics.h"
+#include "llvm/PassManager.h"
+#include "llvm/SymbolTable.h"
 #include "llvm/Analysis/Dominators.h"
 #include "llvm/Support/CFG.h"
 #include "llvm/Support/InstVisitor.h"
@@ -389,9 +386,9 @@
 
   // Verify that all arguments to the call match the function type...
   for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i)
-    Assert2(CI.getOperand(i+1)->getType() == FTy->getParamType(i),
+    Assert3(CI.getOperand(i+1)->getType() == FTy->getParamType(i),
             "Call parameter type does not match function signature!",
-            CI.getOperand(i+1), FTy->getParamType(i));
+            CI.getOperand(i+1), FTy->getParamType(i), &CI);
 
   if (Function *F = CI.getCalledFunction())
     if (Intrinsic::ID ID = (Intrinsic::ID)F->getIntrinsicID())
@@ -477,7 +474,8 @@
   if (!isa<PHINode>(I)) {   // Check that non-phi nodes are not self referential
     for (Value::use_iterator UI = I.use_begin(), UE = I.use_end();
          UI != UE; ++UI)
-      Assert1(*UI != (User*)&I,
+      Assert1(*UI != (User*)&I ||
+              !DS->dominates(&BB->getParent()->getEntryBlock(), BB),
               "Only PHI nodes may reference their own value!", &I);
   }
 
@@ -551,6 +549,16 @@
   case Intrinsic::va_end:          NumArgs = 1; break;
   case Intrinsic::va_copy:         NumArgs = 1; break;
 
+  case Intrinsic::returnaddress:
+  case Intrinsic::frameaddress:
+    Assert1(isa<PointerType>(FT->getReturnType()),
+            "llvm.(frame|return)address must return pointers", IF);
+    Assert1(FT->getNumParams() == 1 && isa<ConstantInt>(CI.getOperand(1)),
+       "llvm.(frame|return)address require a single constant integer argument",
+            &CI);
+    NumArgs = 1;
+    break;
+
   case Intrinsic::setjmp:          NumArgs = 1; break;
   case Intrinsic::longjmp:         NumArgs = 2; break;
   case Intrinsic::sigsetjmp:       NumArgs = 2; break;
@@ -564,6 +572,10 @@
 
   // Join takes a single parameter which is returned by pbr
   case Intrinsic::join:            NumArgs = 1; break;
+
+  case Intrinsic::memcpy:          NumArgs = 4; break;
+  case Intrinsic::memmove:         NumArgs = 4; break;
+  case Intrinsic::memset:          NumArgs = 4; break;
  
   case Intrinsic::alpha_ctlz:      NumArgs = 1; break;
   case Intrinsic::alpha_cttz:      NumArgs = 1; break;


Index: llvm/lib/VMCore/iCall.cpp
diff -u llvm/lib/VMCore/iCall.cpp:1.22 llvm/lib/VMCore/iCall.cpp:1.22.4.1
--- llvm/lib/VMCore/iCall.cpp:1.22	Thu Nov 20 11:45:12 2003
+++ llvm/lib/VMCore/iCall.cpp	Mon Mar  1 17:58:16 2004
@@ -31,14 +31,13 @@
   Operands.reserve(1+params.size());
   Operands.push_back(Use(Func, this));
 
-  const FunctionType *MTy = 
+  const FunctionType *FTy = 
     cast<FunctionType>(cast<PointerType>(Func->getType())->getElementType());
 
-  const FunctionType::ParamTypes &PL = MTy->getParamTypes();
-  assert(params.size() == PL.size() || 
-	 (MTy->isVarArg() && params.size() > PL.size()) &&
+  assert((params.size() == FTy->getNumParams() || 
+          (FTy->isVarArg() && params.size() > FTy->getNumParams())) &&
 	 "Calling a function with bad signature");
-  for (unsigned i = 0; i < params.size(); i++)
+  for (unsigned i = 0; i != params.size(); i++)
     Operands.push_back(Use(params[i], this));
 }
 
@@ -53,8 +52,7 @@
   const FunctionType *MTy = 
     cast<FunctionType>(cast<PointerType>(Func->getType())->getElementType());
 
-  const FunctionType::ParamTypes &PL = MTy->getParamTypes();
-  assert(PL.empty() && "Calling a function with bad signature");
+  assert(MTy->getNumParams() == 0 && "Calling a function with bad signature");
 }
 
 CallInst::CallInst(Value *Func, Value* A, const std::string &Name,
@@ -68,8 +66,8 @@
   const FunctionType *MTy = 
     cast<FunctionType>(cast<PointerType>(Func->getType())->getElementType());
 
-  const FunctionType::ParamTypes &PL = MTy->getParamTypes();
-  assert(PL.size() == 1 || (MTy->isVarArg() && PL.empty()) &&
+  assert((MTy->getNumParams() == 1 ||
+          (MTy->isVarArg() && MTy->getNumParams() == 0)) &&
 	 "Calling a function with bad signature");
   Operands.push_back(Use(A, this));
 }
@@ -115,9 +113,8 @@
   const FunctionType *MTy = 
     cast<FunctionType>(cast<PointerType>(Func->getType())->getElementType());
   
-  const FunctionType::ParamTypes &PL = MTy->getParamTypes();
-  assert((params.size() == PL.size()) || 
-	 (MTy->isVarArg() && params.size() > PL.size()) &&
+  assert((params.size() == MTy->getNumParams()) || 
+	 (MTy->isVarArg() && params.size() > MTy->getNumParams()) &&
 	 "Calling a function with bad signature");
   
   for (unsigned i = 0; i < params.size(); i++)
@@ -138,9 +135,8 @@
   const FunctionType *MTy = 
     cast<FunctionType>(cast<PointerType>(Func->getType())->getElementType());
   
-  const FunctionType::ParamTypes &PL = MTy->getParamTypes();
-  assert((params.size() == PL.size()) || 
-	 (MTy->isVarArg() && params.size() > PL.size()) &&
+  assert((params.size() == MTy->getNumParams()) || 
+	 (MTy->isVarArg() && params.size() > MTy->getNumParams()) &&
 	 "Calling a function with bad signature");
   
   for (unsigned i = 0; i < params.size(); i++)


Index: llvm/lib/VMCore/iOperators.cpp
diff -u llvm/lib/VMCore/iOperators.cpp:1.25 llvm/lib/VMCore/iOperators.cpp:1.25.4.1
--- llvm/lib/VMCore/iOperators.cpp:1.25	Thu Nov 20 11:45:12 2003
+++ llvm/lib/VMCore/iOperators.cpp	Mon Mar  1 17:58:16 2004
@@ -78,9 +78,14 @@
 
 BinaryOperator *BinaryOperator::createNeg(Value *Op, const std::string &Name,
                                           Instruction *InsertBefore) {
-  return new BinaryOperator(Instruction::Sub,
-                            Constant::getNullValue(Op->getType()), Op,
-                            Op->getType(), Name, InsertBefore);
+  if (!Op->getType()->isFloatingPoint())
+    return new BinaryOperator(Instruction::Sub,
+                              Constant::getNullValue(Op->getType()), Op,
+                              Op->getType(), Name, InsertBefore);
+  else
+    return new BinaryOperator(Instruction::Sub,
+                              ConstantFP::get(Op->getType(), -0.0), Op,
+                              Op->getType(), Name, InsertBefore);
 }
 
 BinaryOperator *BinaryOperator::createNot(Value *Op, const std::string &Name,
@@ -98,8 +103,11 @@
 
 bool BinaryOperator::isNeg(const Value *V) {
   if (const BinaryOperator *Bop = dyn_cast<BinaryOperator>(V))
-    return Bop->getOpcode() == Instruction::Sub &&
-      Bop->getOperand(0) == Constant::getNullValue(Bop->getType());
+    if (Bop->getOpcode() == Instruction::Sub)
+      if (!V->getType()->isFloatingPoint())
+        return Bop->getOperand(0) == Constant::getNullValue(Bop->getType());
+      else
+        return Bop->getOperand(0) == ConstantFP::get(Bop->getType(), -0.0);
   return false;
 }
 





More information about the llvm-commits mailing list