Support getelementptr instructions which use uint's to index into structure
types and can have arbitrary 32- and 64-bit integer types indexing into
sequential types.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@12653 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Analysis/BasicAliasAnalysis.cpp b/lib/Analysis/BasicAliasAnalysis.cpp
index 4a8a680..f9c63cd 100644
--- a/lib/Analysis/BasicAliasAnalysis.cpp
+++ b/lib/Analysis/BasicAliasAnalysis.cpp
@@ -353,6 +353,19 @@
   return MayAlias;
 }
 
+static bool ValuesEqual(Value *V1, Value *V2) {
+  if (V1->getType() == V2->getType())
+    return V1 == V2;
+  if (Constant *C1 = dyn_cast<Constant>(V1))
+    if (Constant *C2 = dyn_cast<Constant>(V2)) {
+      // Sign extend the constants to long types.
+      C1 = ConstantExpr::getSignExtend(C1, Type::LongTy);
+      C2 = ConstantExpr::getSignExtend(C2, Type::LongTy);
+      return C1 == C2;
+    }
+  return false;
+}
+
 /// CheckGEPInstructions - Check two GEP instructions with known must-aliasing
 /// base pointers.  This checks to see if the index expressions preclude the
 /// pointers from aliasing...
@@ -376,7 +389,7 @@
   unsigned MaxOperands = std::max(NumGEP1Operands, NumGEP2Operands);
   unsigned UnequalOper = 0;
   while (UnequalOper != MinOperands &&
-         GEP1Ops[UnequalOper] == GEP2Ops[UnequalOper]) {
+         ValuesEqual(GEP1Ops[UnequalOper], GEP2Ops[UnequalOper])) {
     // Advance through the type as we go...
     ++UnequalOper;
     if (const CompositeType *CT = dyn_cast<CompositeType>(BasePtr1Ty))
@@ -418,7 +431,7 @@
   if (SizeMax == ~0U) return MayAlias; // Avoid frivolous work...
 
   // Scan for the first operand that is constant and unequal in the
-  // two getelemenptrs...
+  // two getelementptrs...
   unsigned FirstConstantOper = UnequalOper;
   for (; FirstConstantOper != MinOperands; ++FirstConstantOper) {
     const Value *G1Oper = GEP1Ops[FirstConstantOper];
@@ -427,13 +440,23 @@
     if (G1Oper != G2Oper)   // Found non-equal constant indexes...
       if (Constant *G1OC = dyn_cast<Constant>(const_cast<Value*>(G1Oper)))
         if (Constant *G2OC = dyn_cast<Constant>(const_cast<Value*>(G2Oper))) {
-          // Make sure they are comparable (ie, not constant expressions)...
-          // and make sure the GEP with the smaller leading constant is GEP1.
-          Constant *Compare = ConstantExpr::get(Instruction::SetGT, G1OC, G2OC);
-          if (ConstantBool *CV = dyn_cast<ConstantBool>(Compare)) {
-            if (CV->getValue())   // If they are comparable and G2 > G1
-              std::swap(GEP1Ops, GEP2Ops);  // Make GEP1 < GEP2
-            break;
+          if (G1OC->getType() != G2OC->getType()) {
+            // Sign extend both operands to long.
+            G1OC = ConstantExpr::getSignExtend(G1OC, Type::LongTy);
+            G2OC = ConstantExpr::getSignExtend(G2OC, Type::LongTy);
+            GEP1Ops[FirstConstantOper] = G1OC;
+            GEP2Ops[FirstConstantOper] = G2OC;
+          }
+
+          if (G1OC != G2OC) {
+            // Make sure they are comparable (ie, not constant expressions)...
+            // and make sure the GEP with the smaller leading constant is GEP1.
+            Constant *Compare = ConstantExpr::getSetGT(G1OC, G2OC);
+            if (ConstantBool *CV = dyn_cast<ConstantBool>(Compare)) {
+              if (CV->getValue())   // If they are comparable and G2 > G1
+                std::swap(GEP1Ops, GEP2Ops);  // Make GEP1 < GEP2
+              break;
+            }
           }
         }
     BasePtr1Ty = cast<CompositeType>(BasePtr1Ty)->getTypeAtIndex(G1Oper);
@@ -443,7 +466,7 @@
   // point, the GEP instructions have run through all of their operands, and we
   // haven't found evidence that there are any deltas between the GEP's.
   // However, one GEP may have more operands than the other.  If this is the
-  // case, there may still be hope.  This this now.
+  // case, there may still be hope.  Check this now.
   if (FirstConstantOper == MinOperands) {
     // Make GEP1Ops be the longer one if there is a longer one.
     if (GEP1Ops.size() < GEP2Ops.size())
@@ -494,10 +517,8 @@
   // initial equal sequence of variables into constant zeros to start with.
   for (unsigned i = 0; i != FirstConstantOper; ++i) {
     if (!isa<Constant>(GEP1Ops[i]) || isa<ConstantExpr>(GEP1Ops[i]) ||
-        !isa<Constant>(GEP2Ops[i]) || isa<ConstantExpr>(GEP2Ops[i])) {
-      GEP1Ops[i] = Constant::getNullValue(GEP1Ops[i]->getType());
-      GEP2Ops[i] = Constant::getNullValue(GEP2Ops[i]->getType());
-    }
+        !isa<Constant>(GEP2Ops[i]) || isa<ConstantExpr>(GEP2Ops[i]))
+      GEP1Ops[i] = GEP2Ops[i] = Constant::getNullValue(Type::UIntTy);
   }
 
   // We know that GEP1Ops[FirstConstantOper] & GEP2Ops[FirstConstantOper] are ok
diff --git a/lib/Analysis/DataStructure/Local.cpp b/lib/Analysis/DataStructure/Local.cpp
index 26bd17b..c969cc6 100644
--- a/lib/Analysis/DataStructure/Local.cpp
+++ b/lib/Analysis/DataStructure/Local.cpp
@@ -350,7 +350,8 @@
 #if 0
   // Handle the pointer index specially...
   if (GEP.getNumOperands() > 1 &&
-      GEP.getOperand(1) != ConstantSInt::getNullValue(Type::LongTy)) {
+      (!isa<Constant>(GEP.getOperand(1)) ||
+       !cast<Constant>(GEP.getOperand(1))->isNullValue())) {
 
     // If we already know this is an array being accessed, don't do anything...
     if (!TopTypeRec.isArray) {
diff --git a/lib/Target/TargetData.cpp b/lib/Target/TargetData.cpp
index 271b6d8..78d5d2e 100644
--- a/lib/Target/TargetData.cpp
+++ b/lib/Target/TargetData.cpp
@@ -20,6 +20,7 @@
 #include "llvm/Module.h"
 #include "llvm/DerivedTypes.h"
 #include "llvm/Constants.h"
+#include "llvm/Support/GetElementPtrTypeIterator.h"
 using namespace llvm;
 
 // Handle the Pass registration stuff necessary to use TargetData's.
@@ -218,17 +219,11 @@
   assert(isa<PointerType>(Ty) && "Illegal argument for getIndexedOffset()");
   uint64_t Result = 0;
 
-  for (unsigned CurIDX = 0; CurIDX != Idx.size(); ++CurIDX) {
-    if (Idx[CurIDX]->getType() == Type::LongTy) {
-      // Update Ty to refer to current element
-      Ty = cast<SequentialType>(Ty)->getElementType();
-
-      // Get the array index and the size of each array element.
-      int64_t arrayIdx = cast<ConstantSInt>(Idx[CurIDX])->getValue();
-      Result += arrayIdx * (int64_t)getTypeSize(Ty);
-    } else {
-      const StructType *STy = cast<StructType>(Ty);
-      assert(Idx[CurIDX]->getType() == Type::UByteTy && "Illegal struct idx");
+  generic_gep_type_iterator<std::vector<Value*>::const_iterator>
+    TI = gep_type_begin(ptrTy, Idx.begin(), Idx.end());
+  for (unsigned CurIDX = 0; CurIDX != Idx.size(); ++CurIDX, ++TI) {
+    if (const StructType *STy = dyn_cast<StructType>(*TI)) {
+      assert(Idx[CurIDX]->getType() == Type::UIntTy && "Illegal struct idx");
       unsigned FieldNo = cast<ConstantUInt>(Idx[CurIDX])->getValue();
 
       // Get structure layout information...
@@ -240,6 +235,13 @@
 
       // Update Ty to refer to current element
       Ty = STy->getElementType(FieldNo);
+    } else {
+      // Update Ty to refer to current element
+      Ty = cast<SequentialType>(Ty)->getElementType();
+
+      // Get the array index and the size of each array element.
+      int64_t arrayIdx = cast<ConstantInt>(Idx[CurIDX])->getRawValue();
+      Result += arrayIdx * (int64_t)getTypeSize(Ty);
     }
   }
 
diff --git a/lib/Target/X86/InstSelectSimple.cpp b/lib/Target/X86/InstSelectSimple.cpp
index fa7eef1..ad52353 100644
--- a/lib/Target/X86/InstSelectSimple.cpp
+++ b/lib/Target/X86/InstSelectSimple.cpp
@@ -2704,12 +2704,13 @@
       // idx is the index into the array.  Unlike with structure
       // indices, we may not know its actual value at code-generation
       // time.
-      assert(idx->getType() == Type::LongTy && "Bad GEP array index!");
 
       // If idx is a constant, fold it into the offset.
       unsigned TypeSize = TD.getTypeSize(SqTy->getElementType());
       if (ConstantSInt *CSI = dyn_cast<ConstantSInt>(idx)) {
         Disp += TypeSize*CSI->getValue();
+      } else if (ConstantUInt *CUI = dyn_cast<ConstantUInt>(idx)) {
+        Disp += TypeSize*CUI->getValue();
       } else {
         // If the index reg is already taken, we can't handle this index.
         if (IndexReg) return;
@@ -2833,12 +2834,7 @@
       GEPOps.pop_back();        // Consume a GEP operand
       GEPTypes.pop_back();
 
-      // idx is the index into the array.  Unlike with structure
-      // indices, we may not know its actual value at code-generation
-      // time.
-      assert(idx->getType() == Type::LongTy && "Bad GEP array index!");
-
-      // Most GEP instructions use a [cast (int/uint) to LongTy] as their
+      // Many GEP instructions use a [cast (int/uint) to LongTy] as their
       // operand on X86.  Handle this case directly now...
       if (CastInst *CI = dyn_cast<CastInst>(idx))
         if (CI->getOperand(0)->getType() == Type::IntTy ||
@@ -2852,9 +2848,9 @@
       unsigned elementSize = TD.getTypeSize(ElTy);
 
       // If idxReg is a constant, we don't need to perform the multiply!
-      if (ConstantSInt *CSI = dyn_cast<ConstantSInt>(idx)) {
+      if (ConstantInt *CSI = dyn_cast<ConstantInt>(idx)) {
         if (!CSI->isNullValue()) {
-          unsigned Offset = elementSize*CSI->getValue();
+          unsigned Offset = elementSize*CSI->getRawValue();
           unsigned Reg = makeAnotherReg(Type::UIntTy);
           BuildMI(*MBB, IP, X86::ADD32ri, 2, TargetReg)
                                 .addReg(Reg).addImm(Offset);
diff --git a/lib/Target/X86/X86ISelSimple.cpp b/lib/Target/X86/X86ISelSimple.cpp
index fa7eef1..ad52353 100644
--- a/lib/Target/X86/X86ISelSimple.cpp
+++ b/lib/Target/X86/X86ISelSimple.cpp
@@ -2704,12 +2704,13 @@
       // idx is the index into the array.  Unlike with structure
       // indices, we may not know its actual value at code-generation
       // time.
-      assert(idx->getType() == Type::LongTy && "Bad GEP array index!");
 
       // If idx is a constant, fold it into the offset.
       unsigned TypeSize = TD.getTypeSize(SqTy->getElementType());
       if (ConstantSInt *CSI = dyn_cast<ConstantSInt>(idx)) {
         Disp += TypeSize*CSI->getValue();
+      } else if (ConstantUInt *CUI = dyn_cast<ConstantUInt>(idx)) {
+        Disp += TypeSize*CUI->getValue();
       } else {
         // If the index reg is already taken, we can't handle this index.
         if (IndexReg) return;
@@ -2833,12 +2834,7 @@
       GEPOps.pop_back();        // Consume a GEP operand
       GEPTypes.pop_back();
 
-      // idx is the index into the array.  Unlike with structure
-      // indices, we may not know its actual value at code-generation
-      // time.
-      assert(idx->getType() == Type::LongTy && "Bad GEP array index!");
-
-      // Most GEP instructions use a [cast (int/uint) to LongTy] as their
+      // Many GEP instructions use a [cast (int/uint) to LongTy] as their
       // operand on X86.  Handle this case directly now...
       if (CastInst *CI = dyn_cast<CastInst>(idx))
         if (CI->getOperand(0)->getType() == Type::IntTy ||
@@ -2852,9 +2848,9 @@
       unsigned elementSize = TD.getTypeSize(ElTy);
 
       // If idxReg is a constant, we don't need to perform the multiply!
-      if (ConstantSInt *CSI = dyn_cast<ConstantSInt>(idx)) {
+      if (ConstantInt *CSI = dyn_cast<ConstantInt>(idx)) {
         if (!CSI->isNullValue()) {
-          unsigned Offset = elementSize*CSI->getValue();
+          unsigned Offset = elementSize*CSI->getRawValue();
           unsigned Reg = makeAnotherReg(Type::UIntTy);
           BuildMI(*MBB, IP, X86::ADD32ri, 2, TargetReg)
                                 .addReg(Reg).addImm(Offset);
diff --git a/lib/Transforms/ExprTypeConvert.cpp b/lib/Transforms/ExprTypeConvert.cpp
index b30ddf1..bde24f0 100644
--- a/lib/Transforms/ExprTypeConvert.cpp
+++ b/lib/Transforms/ExprTypeConvert.cpp
@@ -797,10 +797,13 @@
       // stream, so we have to delete it when we're done.
       //
       if (DataSize != 1) {
-        // FIXME, PR82
-        TempScale = BinaryOperator::create(Instruction::Mul, Index,
-                                           ConstantSInt::get(Type::LongTy,
-                                                             DataSize));
+        Value *CST;
+        if (Index->getType()->isSigned())
+          CST = ConstantSInt::get(Index->getType(), DataSize);
+        else
+          CST = ConstantUInt::get(Index->getType(), DataSize);
+                                  
+        TempScale = BinaryOperator::create(Instruction::Mul, Index, CST);
         Index = TempScale;
       }
 
@@ -1012,8 +1015,7 @@
 
     if (const CompositeType *CT = dyn_cast<CompositeType>(LoadedTy)) {
       std::vector<Value*> Indices;
-      // FIXME, PR82
-      Indices.push_back(ConstantSInt::get(Type::LongTy, 0));
+      Indices.push_back(Constant::getNullValue(Type::UIntTy));
 
       unsigned Offset = 0;   // No offset, get first leaf.
       LoadedTy = getStructOffsetType(CT, Offset, Indices, TD, false);
@@ -1049,8 +1051,7 @@
           const StructType *SElTy = cast<StructType>(ElTy);
           
           std::vector<Value*> Indices;
-          // FIXME, PR82
-          Indices.push_back(Constant::getNullValue(Type::LongTy));
+          Indices.push_back(Constant::getNullValue(Type::UIntTy));
 
           unsigned Offset = 0;
           const Type *Ty = getStructOffsetType(ElTy, Offset, Indices, TD,false);
@@ -1079,8 +1080,7 @@
 
       if (isa<StructType>(ValTy)) {
         std::vector<Value*> Indices;
-        // FIXME: PR82
-        Indices.push_back(Constant::getNullValue(Type::LongTy));
+        Indices.push_back(Constant::getNullValue(Type::UIntTy));
 
         unsigned Offset = 0;
         ValTy = getStructOffsetType(ValTy, Offset, Indices, TD, false);
@@ -1112,10 +1112,13 @@
 
     if (DataSize != 1) {
       // Insert a multiply of the old element type is not a unit size...
-      Index = BinaryOperator::create(Instruction::Mul, Index,
-                                     // FIXME: PR82
-                                     ConstantSInt::get(Type::LongTy, DataSize),
-                                     "scale", It);
+      Value *CST;
+      if (Index->getType()->isSigned())
+        CST = ConstantSInt::get(Index->getType(), DataSize);
+      else
+        CST = ConstantUInt::get(Index->getType(), DataSize);
+
+      Index = BinaryOperator::create(Instruction::Mul, Index, CST, "scale", It);
     }
 
     // Perform the conversion now...
diff --git a/lib/Transforms/Instrumentation/ProfilingUtils.cpp b/lib/Transforms/Instrumentation/ProfilingUtils.cpp
index 5baefe9..4cdcb9e 100644
--- a/lib/Transforms/Instrumentation/ProfilingUtils.cpp
+++ b/lib/Transforms/Instrumentation/ProfilingUtils.cpp
@@ -40,7 +40,7 @@
   while (isa<AllocaInst>(InsertPos)) ++InsertPos;
 
   ConstantPointerRef *ArrayCPR = ConstantPointerRef::get(Array);
-  std::vector<Constant*> GEPIndices(2, Constant::getNullValue(Type::LongTy));
+  std::vector<Constant*> GEPIndices(2, Constant::getNullValue(Type::IntTy));
   Args[2] = ConstantExpr::getGetElementPtr(ArrayCPR, GEPIndices);
   
   unsigned NumElements =
@@ -89,8 +89,8 @@
 
   // Create the getelementptr constant expression
   std::vector<Constant*> Indices(2);
-  Indices[0] = Constant::getNullValue(Type::LongTy);
-  Indices[1] = ConstantSInt::get(Type::LongTy, CounterNum);
+  Indices[0] = Constant::getNullValue(Type::IntTy);
+  Indices[1] = ConstantSInt::get(Type::IntTy, CounterNum);
   Constant *ElementPtr = ConstantExpr::getGetElementPtr(CounterArray, Indices);
 
   // Load, increment and store the value back.
diff --git a/lib/Transforms/LevelRaise.cpp b/lib/Transforms/LevelRaise.cpp
index edc42b7..aeb836d 100644
--- a/lib/Transforms/LevelRaise.cpp
+++ b/lib/Transforms/LevelRaise.cpp
@@ -370,9 +370,8 @@
           // Build the index vector, full of all zeros
           std::vector<Value*> Indices;
 
-          Indices.push_back(ConstantSInt::get(Type::LongTy, 0)); // FIXME, PR82
+          Indices.push_back(Constant::getNullValue(Type::UIntTy));
           while (CurCTy && !isa<PointerType>(CurCTy)) {
-            const Type *IdxType;
             if (const StructType *CurSTy = dyn_cast<StructType>(CurCTy)) {
               // Check for a zero element struct type... if we have one, bail.
               if (CurSTy->getNumElements() == 0) break;
@@ -381,14 +380,12 @@
               // offset zero in the struct.
               //
               ElTy = CurSTy->getElementType(0);
-              IdxType = Type::UByteTy;   // FIXME when PR82 is fixed.
             } else {
               ElTy = cast<ArrayType>(CurCTy)->getElementType();
-              IdxType = Type::LongTy;    // FIXME when PR82 is fixed.
             }
 
             // Insert a zero to index through this type...
-            Indices.push_back(Constant::getNullValue(IdxType));
+            Indices.push_back(Constant::getNullValue(Type::UIntTy));
 
             // Did we find what we're looking for?
             if (ElTy->isLosslesslyConvertibleTo(DestPointedTy)) break;
diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp
index 13c6b26..a1e6c99 100644
--- a/lib/Transforms/Scalar/InstructionCombining.cpp
+++ b/lib/Transforms/Scalar/InstructionCombining.cpp
@@ -44,9 +44,10 @@
 #include "llvm/Target/TargetData.h"
 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
 #include "llvm/Transforms/Utils/Local.h"
+#include "llvm/Support/CallSite.h"
+#include "llvm/Support/GetElementPtrTypeIterator.h"
 #include "llvm/Support/InstIterator.h"
 #include "llvm/Support/InstVisitor.h"
-#include "llvm/Support/CallSite.h"
 #include "Support/Debug.h"
 #include "Support/Statistic.h"
 #include <algorithm>
@@ -92,6 +93,8 @@
       AU.setPreservesCFG();
     }
 
+    TargetData &getTargetData() const { return *TD; }
+
     // Visitation implementation - Implement instruction combining for different
     // instruction types.  The semantics are as follows:
     // Return Value:
@@ -127,6 +130,7 @@
     Instruction *visitCallSite(CallSite CS);
     bool transformConstExprCastCall(CallSite CS);
 
+  public:
     // InsertNewInstBefore - insert an instruction New before instruction Old
     // in the program.  Add the new instruction to the worklist.
     //
@@ -139,7 +143,6 @@
       return New;
     }
 
-  public:
     // ReplaceInstUsesWith - This method is to be used when an instruction is
     // found to be dead, replacable with another preexisting expression.  Here
     // we add all uses of I to the worklist, replace all uses of I with the new
@@ -2272,6 +2275,20 @@
   return 0;
 }
 
+static Value *InsertSignExtendToPtrTy(Value *V, const Type *DTy,
+                                      Instruction *InsertPoint,
+                                      InstCombiner *IC) {
+  unsigned PS = IC->getTargetData().getPointerSize();
+  const Type *VTy = V->getType();
+  Instruction *Cast;
+  if (!VTy->isSigned() && VTy->getPrimitiveSize() < PS)
+    // We must insert a cast to ensure we sign-extend.
+    V = IC->InsertNewInstBefore(new CastInst(V, VTy->getSignedVersion(),
+                                             V->getName()), *InsertPoint);
+  return IC->InsertNewInstBefore(new CastInst(V, DTy, V->getName()),
+                                 *InsertPoint);
+}
+
 
 Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst &GEP) {
   // Is it 'getelementptr %P, long 0'  or 'getelementptr %P'
@@ -2286,6 +2303,37 @@
   if (GEP.getNumOperands() == 2 && HasZeroPointerIndex)
     return ReplaceInstUsesWith(GEP, GEP.getOperand(0));
 
+  // Eliminate unneeded casts for indices.
+  bool MadeChange = false;
+  for (unsigned i = 1, e = GEP.getNumOperands(); i != e; ++i)
+    if (CastInst *CI = dyn_cast<CastInst>(GEP.getOperand(i))) {
+      Value *Src = CI->getOperand(0);
+      const Type *SrcTy = Src->getType();
+      const Type *DestTy = CI->getType();
+      if (Src->getType()->isInteger()) {
+        if (SrcTy->getPrimitiveSize() == DestTy->getPrimitiveSize()) {
+          // We can always eliminate a cast from ulong or long to the other.  We
+          // can always eliminate a cast from uint to int or the other on 32-bit
+          // pointer platforms.
+          if (DestTy->getPrimitiveSize() >= TD->getPointerSize()) {
+            MadeChange = true;
+            GEP.setOperand(i, Src);
+          }
+        } else if (SrcTy->getPrimitiveSize() < DestTy->getPrimitiveSize() &&
+                   SrcTy->getPrimitiveSize() == 4) {
+          // We can always eliminate a cast from int to [u]long.  We can
+          // eliminate a cast from uint to [u]long iff the target is a 32-bit
+          // pointer target.
+          if (SrcTy->isSigned() || 
+              SrcTy->getPrimitiveSize() >= TD->getPointerSize()) {
+            MadeChange = true;
+            GEP.setOperand(i, Src);
+          }
+        }
+      }
+    }
+  if (MadeChange) return &GEP;
+
   // Combine Indices - If the source pointer to this getelementptr instruction
   // is a getelementptr instruction, combine the indices of the two
   // getelementptr instructions into a single instruction.
@@ -2304,14 +2352,17 @@
     // Can we combine the two pointer arithmetics offsets?
     if (SrcGEPOperands.size() == 2 && isa<Constant>(SrcGEPOperands[1]) &&
         isa<Constant>(GEP.getOperand(1))) {
+      Constant *SGC = cast<Constant>(SrcGEPOperands[1]);
+      Constant *GC  = cast<Constant>(GEP.getOperand(1));
+      if (SGC->getType() != GC->getType()) {
+        SGC = ConstantExpr::getSignExtend(SGC, Type::LongTy);
+        GC = ConstantExpr::getSignExtend(GC, Type::LongTy);
+      }
+      
       // Replace: gep (gep %P, long C1), long C2, ...
       // With:    gep %P, long (C1+C2), ...
-      Value *Sum = ConstantExpr::get(Instruction::Add,
-                                     cast<Constant>(SrcGEPOperands[1]),
-                                     cast<Constant>(GEP.getOperand(1)));
-      assert(Sum && "Constant folding of longs failed!?");
       GEP.setOperand(0, SrcGEPOperands[0]);
-      GEP.setOperand(1, Sum);
+      GEP.setOperand(1, ConstantExpr::getAdd(SGC, GC));
       if (Instruction *I = dyn_cast<Instruction>(GEP.getOperand(0)))
         AddUsersToWorkList(*I);   // Reduce use count of Src
       return &GEP;
@@ -2327,29 +2378,65 @@
           cast<Instruction>(SrcGEPOperands[0])->getNumOperands() == 2)
         return 0;   // Wait until our source is folded to completion.
 
-      Value *Sum = BinaryOperator::create(Instruction::Add, SrcGEPOperands[1],
-                                          GEP.getOperand(1),
-                                          GEP.getOperand(0)->getName()+".sum",
-                                          &GEP);
+      Value *Sum, *SO1 = SrcGEPOperands[1], *GO1 = GEP.getOperand(1);
+      if (SO1 == Constant::getNullValue(SO1->getType())) {
+        Sum = GO1;
+      } else if (GO1 == Constant::getNullValue(GO1->getType())) {
+        Sum = SO1;
+      } else {
+        // If they aren't the same type, convert both to an integer of the
+        // target's pointer size.
+        if (SO1->getType() != GO1->getType()) {
+          if (Constant *SO1C = dyn_cast<Constant>(SO1)) {
+            SO1 = ConstantExpr::getCast(SO1C, GO1->getType());
+          } else if (Constant *GO1C = dyn_cast<Constant>(GO1)) {
+            GO1 = ConstantExpr::getCast(GO1C, SO1->getType());
+          } else {
+            unsigned PS = TD->getPointerSize();
+            Instruction *Cast;
+            if (SO1->getType()->getPrimitiveSize() == PS) {
+              // Convert GO1 to SO1's type.
+              GO1 = InsertSignExtendToPtrTy(GO1, SO1->getType(), &GEP, this);
+
+            } else if (GO1->getType()->getPrimitiveSize() == PS) {
+              // Convert SO1 to GO1's type.
+              SO1 = InsertSignExtendToPtrTy(SO1, GO1->getType(), &GEP, this);
+            } else {
+              const Type *PT = TD->getIntPtrType();
+              SO1 = InsertSignExtendToPtrTy(SO1, PT, &GEP, this);
+              GO1 = InsertSignExtendToPtrTy(GO1, PT, &GEP, this);
+            }
+          }
+        }
+        Sum = BinaryOperator::create(Instruction::Add, SO1, GO1,
+                                     GEP.getOperand(0)->getName()+".sum", &GEP);
+      }
       GEP.setOperand(0, SrcGEPOperands[0]);
       GEP.setOperand(1, Sum);
       WorkList.push_back(cast<Instruction>(Sum));
       return &GEP;
-    } else if (*GEP.idx_begin() == Constant::getNullValue(Type::LongTy) &&
+    } else if (isa<Constant>(*GEP.idx_begin()) && 
+               cast<Constant>(*GEP.idx_begin())->isNullValue() &&
                SrcGEPOperands.size() != 1) { 
       // Otherwise we can do the fold if the first index of the GEP is a zero
       Indices.insert(Indices.end(), SrcGEPOperands.begin()+1,
                      SrcGEPOperands.end());
       Indices.insert(Indices.end(), GEP.idx_begin()+1, GEP.idx_end());
-    } else if (SrcGEPOperands.back() == Constant::getNullValue(Type::LongTy)) {
-      // FIXME: when we allow indices to be non-long values, support this for
-      // other types!
-
-      // If the src gep ends with a constant array index, merge this get into
-      // it, even if we have a non-zero array index.
-      Indices.insert(Indices.end(), SrcGEPOperands.begin()+1,
-                     SrcGEPOperands.end()-1);
-      Indices.insert(Indices.end(), GEP.idx_begin(), GEP.idx_end());
+    } else if (SrcGEPOperands.back() ==
+               Constant::getNullValue(SrcGEPOperands.back()->getType())) {
+      // We have to check to make sure this really is an ARRAY index we are
+      // ending up with, not a struct index.
+      generic_gep_type_iterator<std::vector<Value*>::iterator>
+        GTI = gep_type_begin(SrcGEPOperands[0]->getType(),
+                             SrcGEPOperands.begin()+1, SrcGEPOperands.end());
+      std::advance(GTI, SrcGEPOperands.size()-2);
+      if (isa<SequentialType>(*GTI)) {
+        // If the src gep ends with a constant array index, merge this get into
+        // it, even if we have a non-zero array index.
+        Indices.insert(Indices.end(), SrcGEPOperands.begin()+1,
+                       SrcGEPOperands.end()-1);
+        Indices.insert(Indices.end(), GEP.idx_begin(), GEP.idx_end());
+      }
     }
 
     if (!Indices.empty())
@@ -2428,7 +2515,7 @@
       // Now that I is pointing to the first non-allocation-inst in the block,
       // insert our getelementptr instruction...
       //
-      std::vector<Value*> Idx(2, Constant::getNullValue(Type::LongTy));
+      std::vector<Value*> Idx(2, Constant::getNullValue(Type::IntTy));
       Value *V = new GetElementPtrInst(New, Idx, New->getName()+".sub", It);
 
       // Now make everything use the getelementptr instead of the original
@@ -2469,7 +2556,7 @@
 /// expression, or null if something is funny.
 ///
 static Constant *GetGEPGlobalInitializer(Constant *C, ConstantExpr *CE) {
-  if (CE->getOperand(1) != Constant::getNullValue(Type::LongTy))
+  if (CE->getOperand(1) != Constant::getNullValue(CE->getOperand(1)->getType()))
     return 0;  // Do not allow stepping over the value!
 
   // Loop over all of the operands, tracking down which value we are
diff --git a/lib/Transforms/Scalar/SCCP.cpp b/lib/Transforms/Scalar/SCCP.cpp
index 75be397..8d550b8 100644
--- a/lib/Transforms/Scalar/SCCP.cpp
+++ b/lib/Transforms/Scalar/SCCP.cpp
@@ -712,7 +712,7 @@
 /// null if something is funny.
 ///
 static Constant *GetGEPGlobalInitializer(Constant *C, ConstantExpr *CE) {
-  if (CE->getOperand(1) != Constant::getNullValue(Type::LongTy))
+  if (CE->getOperand(1) != Constant::getNullValue(CE->getOperand(1)->getType()))
     return 0;  // Do not allow stepping over the value!
 
   // Loop over all of the operands, tracking down which value we are
diff --git a/lib/Transforms/Scalar/ScalarReplAggregates.cpp b/lib/Transforms/Scalar/ScalarReplAggregates.cpp
index c1c4759..9598918 100644
--- a/lib/Transforms/Scalar/ScalarReplAggregates.cpp
+++ b/lib/Transforms/Scalar/ScalarReplAggregates.cpp
@@ -193,7 +193,7 @@
           //
           std::string OldName = GEPI->getName();  // Steal the old name...
           std::vector<Value*> NewArgs;
-          NewArgs.push_back(Constant::getNullValue(Type::LongTy));
+          NewArgs.push_back(Constant::getNullValue(Type::IntTy));
           NewArgs.insert(NewArgs.end(), GEPI->op_begin()+3, GEPI->op_end());
           GEPI->setName("");
           RepValue =
diff --git a/lib/Transforms/TransformInternals.cpp b/lib/Transforms/TransformInternals.cpp
index 9039f59..971a58d 100644
--- a/lib/Transforms/TransformInternals.cpp
+++ b/lib/Transforms/TransformInternals.cpp
@@ -35,8 +35,7 @@
          (i == SL->MemberOffsets.size()-1 || Offset < SL->MemberOffsets[i+1]));
   
   // Make sure to save the current index...
-  // FIXME for PR82
-  Indices.push_back(ConstantUInt::get(Type::UByteTy, i));
+  Indices.push_back(ConstantUInt::get(Type::UIntTy, i));
   Offset = SL->MemberOffsets[i];
   return STy->getContainedType(i);
 }
@@ -75,8 +74,10 @@
 
     NextType = ATy->getElementType();
     unsigned ChildSize = TD.getTypeSize(NextType);
-    // FIXME for PR82
-    Indices.push_back(ConstantSInt::get(Type::LongTy, Offset/ChildSize));
+    if (ConstantSInt::isValueValidForType(Type::IntTy, Offset/ChildSize))
+      Indices.push_back(ConstantSInt::get(Type::IntTy, Offset/ChildSize));
+    else
+      Indices.push_back(ConstantSInt::get(Type::LongTy, Offset/ChildSize));
     ThisOffset = (Offset/ChildSize)*ChildSize;
   } else {
     Offset = 0;   // Return the offset that we were able to achieve
@@ -99,105 +100,6 @@
                                    std::vector<Value*> &Indices,
                                    const TargetData &TD,
                                    BasicBlock::iterator *BI) {
-  const CompositeType *CompTy = dyn_cast<CompositeType>(Ty);
-  if (CompTy == 0) return 0;
-
-  // See if the cast is of an integer expression that is either a constant,
-  // or a value scaled by some amount with a possible offset.
-  //
-  ExprType Expr = ClassifyExpr(OffsetVal);
-
-  // Get the offset and scale values if they exists...
-  // A scale of zero with Expr.Var != 0 means a scale of 1.
-  //
-  int64_t Offset = Expr.Offset ? getConstantValue(Expr.Offset) : 0;
-  int64_t Scale  = Expr.Scale  ? getConstantValue(Expr.Scale)  : 0;
-
-  if (Expr.Var && Scale == 0) Scale = 1;   // Scale != 0 if Expr.Var != 0
- 
-  // Loop over the Scale and Offset values, filling in the Indices vector for
-  // our final getelementptr instruction.
-  //
-  const Type *NextTy = CompTy;
-  do {
-    if (!isa<CompositeType>(NextTy))
-      return 0;  // Type must not be ready for processing...
-    CompTy = cast<CompositeType>(NextTy);
-
-    if (const StructType *StructTy = dyn_cast<StructType>(CompTy)) {
-      // Step into the appropriate element of the structure...
-      uint64_t ActualOffset = (Offset < 0) ? 0 : (uint64_t)Offset;
-      NextTy = getStructOffsetStep(StructTy, ActualOffset, Indices, TD);
-      Offset -= ActualOffset;
-    } else {
-      const Type *ElTy = cast<SequentialType>(CompTy)->getElementType();
-      if (!ElTy->isSized() || (isa<PointerType>(CompTy) && !Indices.empty()))
-        return 0; // Type is unreasonable... escape!
-      unsigned ElSize = TD.getTypeSize(ElTy);
-      if (ElSize == 0) return 0;   // Avoid division by zero...
-      int64_t ElSizeS = ElSize;
-
-      // See if the user is indexing into a different cell of this array...
-      if (Scale && (Scale >= ElSizeS || -Scale >= ElSizeS)) {
-        // A scale n*ElSize might occur if we are not stepping through
-        // array by one.  In this case, we will have to insert math to munge
-        // the index.
-        //
-        int64_t ScaleAmt = Scale/ElSizeS;
-        if (Scale-ScaleAmt*ElSizeS)
-          return 0;  // Didn't scale by a multiple of element size, bail out
-        Scale = 0;   // Scale is consumed
-
-        int64_t Index = Offset/ElSize;        // is zero unless Offset > ElSize
-        Offset -= Index*ElSize;               // Consume part of the offset
-
-        if (BI) {              // Generate code?
-          BasicBlock *BB = (*BI)->getParent();
-          if (Expr.Var->getType() != Type::LongTy)    // FIXME for PR82
-            Expr.Var = new CastInst(Expr.Var, Type::LongTy,    // FIXME for PR82
-                                    Expr.Var->getName()+"-idxcast", *BI);
-
-          if (ScaleAmt && ScaleAmt != 1) {
-            // If we have to scale up our index, do so now
-            // FIXME for PR82
-            Value *ScaleAmtVal = ConstantSInt::get(Type::LongTy, ScaleAmt);
-            Expr.Var = BinaryOperator::create(Instruction::Mul, Expr.Var,
-                                              ScaleAmtVal,
-                                              Expr.Var->getName()+"-scale",*BI);
-          }
-
-          if (Index) {  // Add an offset to the index
-            // FIXME for PR82
-            Value *IndexAmt = ConstantSInt::get(Type::LongTy, Index);
-            Expr.Var = BinaryOperator::create(Instruction::Add, Expr.Var,
-                                              IndexAmt,
-                                              Expr.Var->getName()+"-offset",
-                                              *BI);
-          }
-        }
-
-        Indices.push_back(Expr.Var);
-        Expr.Var = 0;
-      } else if (Offset >= (int64_t)ElSize || -Offset >= (int64_t)ElSize) {
-        // Calculate the index that we are entering into the array cell with
-        uint64_t Index = Offset/ElSize;
-        // FIXME for PR82
-        Indices.push_back(ConstantSInt::get(Type::LongTy, Index));
-        Offset -= (int64_t)(Index*ElSize);        // Consume part of the offset
-
-      } else if (isa<ArrayType>(CompTy) || Indices.empty()) {
-        // Must be indexing a small amount into the first cell of the array
-        // Just index into element zero of the array here.
-        //
-        // FIXME for PR82
-        Indices.push_back(ConstantSInt::get(Type::LongTy, 0));
-      } else {
-        return 0;  // Hrm. wierd, can't handle this case.  Bail
-      }
-      NextTy = ElTy;
-    }
-  } while (Offset || Scale);    // Go until we're done!
-
-  return NextTy;
+  return 0;
 }
 
diff --git a/lib/Transforms/Utils/LowerInvoke.cpp b/lib/Transforms/Utils/LowerInvoke.cpp
index 2349d76..c486633 100644
--- a/lib/Transforms/Utils/LowerInvoke.cpp
+++ b/lib/Transforms/Utils/LowerInvoke.cpp
@@ -277,14 +277,14 @@
       // Store this old value as our 'next' field, and store our alloca as the
       // current jblist.
       std::vector<Value*> Idx;
-      Idx.push_back(Constant::getNullValue(Type::LongTy));
-      Idx.push_back(ConstantUInt::get(Type::UByteTy, 0));
+      Idx.push_back(Constant::getNullValue(Type::IntTy));
+      Idx.push_back(ConstantUInt::get(Type::UIntTy, 0));
       Value *NextFieldPtr = new GetElementPtrInst(JmpBuf, Idx, "NextField", II);
       new StoreInst(OldEntry, NextFieldPtr, II);
       new StoreInst(JmpBuf, JBListHead, II);
       
       // Call setjmp, passing in the address of the jmpbuffer.
-      Idx[1] = ConstantUInt::get(Type::UByteTy, 1);
+      Idx[1] = ConstantUInt::get(Type::UIntTy, 1);
       Value *JmpBufPtr = new GetElementPtrInst(JmpBuf, Idx, "TheJmpBuf", II);
       Value *SJRet = new CallInst(SetJmpFn, JmpBufPtr, "sjret", II);
 
@@ -369,14 +369,14 @@
     // JBList.
     std::vector<Value*> Idx;
     Idx.push_back(Constant::getNullValue(Type::LongTy));
-    Idx.push_back(ConstantUInt::get(Type::UByteTy, 0));
+    Idx.push_back(ConstantUInt::get(Type::UIntTy, 0));
     Value *NextFieldPtr = new GetElementPtrInst(RecPtr, Idx, "NextField", RI);
     Value *NextRec = new LoadInst(NextFieldPtr, "NextRecord", RI);
     new StoreInst(NextRec, JBListHead, RI);
 
     // Now that we popped the top of the JBList, get a pointer to the jmpbuf and
     // longjmp.
-    Idx[1] = ConstantUInt::get(Type::UByteTy, 1);
+    Idx[1] = ConstantUInt::get(Type::UIntTy, 1);
     Idx[0] = new GetElementPtrInst(RecPtr, Idx, "JmpBuf", RI);
     Idx[1] = ConstantInt::get(Type::IntTy, 1);
     new CallInst(LongJmpFn, Idx, "", RI);
diff --git a/lib/VMCore/ConstantFold.cpp b/lib/VMCore/ConstantFold.cpp
index db21bd3..1fee501 100644
--- a/lib/VMCore/ConstantFold.cpp
+++ b/lib/VMCore/ConstantFold.cpp
@@ -608,10 +608,10 @@
   if (!isa<ConstantInt>(C1) || !isa<ConstantInt>(C2))
     return -2; // don't know!
   
-  // Ok, we have two differing integer indices.  Convert them to
-  // be the same type.  Long is always big enough, so we use it.
-  C1 = ConstantExpr::getCast(C1, Type::LongTy);
-  C2 = ConstantExpr::getCast(C2, Type::LongTy);
+  // Ok, we have two differing integer indices.  Sign extend them to be the same
+  // type.  Long is always big enough, so we use it.
+  C1 = ConstantExpr::getSignExtend(C1, Type::LongTy);
+  C2 = ConstantExpr::getSignExtend(C2, Type::LongTy);
   if (C1 == C2) return 0;  // Are they just differing types?
 
   // If they are really different, now that they are the same type, then we
diff --git a/lib/VMCore/Type.cpp b/lib/VMCore/Type.cpp
index 1e2d741..b7d7181 100644
--- a/lib/VMCore/Type.cpp
+++ b/lib/VMCore/Type.cpp
@@ -295,8 +295,9 @@
 
 bool StructType::indexValid(const Value *V) const {
   // Structure indexes require unsigned integer constants.
-  if (const ConstantUInt *CU = dyn_cast<ConstantUInt>(V))
-    return CU->getValue() < ContainedTys.size();
+  if (V->getType() == Type::UIntTy)
+    if (const ConstantUInt *CU = dyn_cast<ConstantUInt>(V))
+      return CU->getValue() < ContainedTys.size();
   return false;
 }
 
@@ -304,10 +305,8 @@
 // element.  For a structure type, this must be a constant value...
 //
 const Type *StructType::getTypeAtIndex(const Value *V) const {
-  assert(isa<Constant>(V) && "Structure index must be a constant!!");
+  assert(indexValid(V) && "Invalid structure index!");
   unsigned Idx = cast<ConstantUInt>(V)->getValue();
-  assert(Idx < ContainedTys.size() && "Structure index out of range!");
-  assert(indexValid(V) && "Invalid structure index!"); // Duplicate check
   return ContainedTys[Idx];
 }
 
diff --git a/lib/VMCore/iMemory.cpp b/lib/VMCore/iMemory.cpp
index 7c8f665..1fc1df8 100644
--- a/lib/VMCore/iMemory.cpp
+++ b/lib/VMCore/iMemory.cpp
@@ -137,7 +137,12 @@
   if (!isa<PointerType>(Ptr)) return 0;   // Type isn't a pointer type!
 
   // Handle the special case of the empty set index set...
-  if (Idx.empty()) return cast<PointerType>(Ptr)->getElementType();
+  if (Idx.empty())
+    if (AllowCompositeLeaf ||
+        cast<PointerType>(Ptr)->getElementType()->isFirstClassType())
+      return cast<PointerType>(Ptr)->getElementType();
+    else
+      return 0;
  
   unsigned CurIdx = 0;
   while (const CompositeType *CT = dyn_cast<CompositeType>(Ptr)) {