Implement new cast creation functions for both instructions and constant
[oota-llvm.git] / lib / VMCore / Constants.cpp
index bcfd3879dbe0ceb2e9f21cd2bdce2a94f95b9507..966108748b834c0cdfe55166f6ff75df53b51a26 100644 (file)
 #include "llvm/SymbolTable.h"
 #include "llvm/Module.h"
 #include "llvm/ADT/StringExtras.h"
-#include "llvm/Support/MathExtras.h"
 #include "llvm/Support/Compiler.h"
+#include "llvm/Support/Debug.h"
 #include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/MathExtras.h"
 #include <algorithm>
-#include <iostream>
 using namespace llvm;
 
 //===----------------------------------------------------------------------===//
@@ -42,9 +42,9 @@ void Constant::destroyConstantImpl() {
     Value *V = use_back();
 #ifndef NDEBUG      // Only in -g mode...
     if (!isa<Constant>(V))
-      std::cerr << "While deleting: " << *this
-                << "\n\nUse still stuck around after Def is destroyed: "
-                << *V << "\n\n";
+      DOUT << "While deleting: " << *this
+           << "\n\nUse still stuck around after Def is destroyed: "
+           << *V << "\n\n";
 #endif
     assert(isa<Constant>(V) && "References remain to Constant being destroyed");
     Constant *CV = cast<Constant>(V);
@@ -312,26 +312,27 @@ ConstantPacked::~ConstantPacked() {
   delete [] OperandList;
 }
 
+static bool isSetCC(unsigned Opcode) {
+  return Opcode == Instruction::SetEQ || Opcode == Instruction::SetNE ||
+         Opcode == Instruction::SetLT || Opcode == Instruction::SetGT ||
+         Opcode == Instruction::SetLE || Opcode == Instruction::SetGE;
+}
+
+// We declare several classes private to this file, so use an anonymous
+// namespace
+namespace {
+
 /// UnaryConstantExpr - This class is private to Constants.cpp, and is used
 /// behind the scenes to implement unary constant exprs.
-namespace {
 class VISIBILITY_HIDDEN UnaryConstantExpr : public ConstantExpr {
   Use Op;
 public:
   UnaryConstantExpr(unsigned Opcode, Constant *C, const Type *Ty)
     : ConstantExpr(Ty, Opcode, &Op, 1), Op(C, this) {}
 };
-}
-
-static bool isSetCC(unsigned Opcode) {
-  return Opcode == Instruction::SetEQ || Opcode == Instruction::SetNE ||
-         Opcode == Instruction::SetLT || Opcode == Instruction::SetGT ||
-         Opcode == Instruction::SetLE || Opcode == Instruction::SetGE;
-}
 
 /// BinaryConstantExpr - This class is private to Constants.cpp, and is used
 /// behind the scenes to implement binary constant exprs.
-namespace {
 class VISIBILITY_HIDDEN BinaryConstantExpr : public ConstantExpr {
   Use Ops[2];
 public:
@@ -342,11 +343,9 @@ public:
     Ops[1].init(C2, this);
   }
 };
-}
 
 /// SelectConstantExpr - This class is private to Constants.cpp, and is used
 /// behind the scenes to implement select constant exprs.
-namespace {
 class VISIBILITY_HIDDEN SelectConstantExpr : public ConstantExpr {
   Use Ops[3];
 public:
@@ -357,12 +356,10 @@ public:
     Ops[2].init(C3, this);
   }
 };
-}
 
 /// ExtractElementConstantExpr - This class is private to
 /// Constants.cpp, and is used behind the scenes to implement
 /// extractelement constant exprs.
-namespace {
 class VISIBILITY_HIDDEN ExtractElementConstantExpr : public ConstantExpr {
   Use Ops[2];
 public:
@@ -373,12 +370,10 @@ public:
     Ops[1].init(C2, this);
   }
 };
-}
 
 /// InsertElementConstantExpr - This class is private to
 /// Constants.cpp, and is used behind the scenes to implement
 /// insertelement constant exprs.
-namespace {
 class VISIBILITY_HIDDEN InsertElementConstantExpr : public ConstantExpr {
   Use Ops[3];
 public:
@@ -390,12 +385,10 @@ public:
     Ops[2].init(C3, this);
   }
 };
-}
 
 /// ShuffleVectorConstantExpr - This class is private to
 /// Constants.cpp, and is used behind the scenes to implement
 /// shufflevector constant exprs.
-namespace {
 class VISIBILITY_HIDDEN ShuffleVectorConstantExpr : public ConstantExpr {
   Use Ops[3];
 public:
@@ -407,11 +400,9 @@ public:
     Ops[2].init(C3, this);
   }
 };
-}
 
 /// GetElementPtrConstantExpr - This class is private to Constants.cpp, and is
 /// used behind the scenes to implement getelementpr constant exprs.
-namespace {
 struct VISIBILITY_HIDDEN GetElementPtrConstantExpr : public ConstantExpr {
   GetElementPtrConstantExpr(Constant *C, const std::vector<Constant*> &IdxList,
                             const Type *DestTy)
@@ -425,6 +416,34 @@ struct VISIBILITY_HIDDEN GetElementPtrConstantExpr : public ConstantExpr {
     delete [] OperandList;
   }
 };
+
+// CompareConstantExpr - This class is private to Constants.cpp, and is used
+// behind the scenes to implement ICmp and FCmp constant expressions. This is
+// needed in order to store the predicate value for these instructions.
+struct VISIBILITY_HIDDEN CompareConstantExpr : public ConstantExpr {
+  unsigned short predicate;
+  Use Ops[2];
+  CompareConstantExpr(Instruction::OtherOps opc, unsigned short pred, 
+                      Constant* LHS, Constant* RHS)
+    : ConstantExpr(Type::BoolTy, Instruction::OtherOps(opc), Ops, 2),
+      predicate(pred) {
+    OperandList[0].init(LHS, this);
+    OperandList[1].init(RHS, this);
+  }
+};
+
+} // end anonymous namespace
+
+
+// Utility function for determining if a ConstantExpr is a CastOp or not. This
+// can't be inline because we don't want to #include Instruction.h into
+// Constant.h
+bool ConstantExpr::isCast() const {
+  return Instruction::isCast(getOpcode());
+}
+
+bool ConstantExpr::isCompare() const {
+  return getOpcode() == Instruction::ICmp || getOpcode() == Instruction::FCmp;
 }
 
 /// ConstantExpr::get* - Return some common constants without having to
@@ -495,29 +514,24 @@ Constant *ConstantExpr::getSetLE(Constant *C1, Constant *C2) {
 Constant *ConstantExpr::getSetGE(Constant *C1, Constant *C2) {
   return get(Instruction::SetGE, C1, C2);
 }
+unsigned ConstantExpr::getPredicate() const {
+  assert(getOpcode() == Instruction::FCmp || getOpcode() == Instruction::ICmp);
+  return dynamic_cast<const CompareConstantExpr*>(this)->predicate;
+}
 Constant *ConstantExpr::getShl(Constant *C1, Constant *C2) {
   return get(Instruction::Shl, C1, C2);
 }
-Constant *ConstantExpr::getShr(Constant *C1, Constant *C2) {
-  return get(Instruction::Shr, C1, C2);
+Constant *ConstantExpr::getLShr(Constant *C1, Constant *C2) {
+  return get(Instruction::LShr, C1, C2);
 }
-
-Constant *ConstantExpr::getUShr(Constant *C1, Constant *C2) {
-  if (C1->getType()->isUnsigned()) return getShr(C1, C2);
-  return getCast(getShr(getCast(C1,
-                    C1->getType()->getUnsignedVersion()), C2), C1->getType());
-}
-
-Constant *ConstantExpr::getSShr(Constant *C1, Constant *C2) {
-  if (C1->getType()->isSigned()) return getShr(C1, C2);
-  return getCast(getShr(getCast(C1,
-                        C1->getType()->getSignedVersion()), C2), C1->getType());
+Constant *ConstantExpr::getAShr(Constant *C1, Constant *C2) {
+  return get(Instruction::AShr, C1, C2);
 }
 
 /// getWithOperandReplaced - Return a constant expression identical to this
 /// one, but with the specified operand set to the specified value.
-Constant *ConstantExpr::getWithOperandReplaced(unsigned OpNo,
-                                               Constant *Op) const {
+Constant *
+ConstantExpr::getWithOperandReplaced(unsigned OpNo, Constant *Op) const {
   assert(OpNo < getNumOperands() && "Operand num is out of range!");
   assert(Op->getType() == getOperand(OpNo)->getType() &&
          "Replacing operand with value of different type!");
@@ -526,8 +540,19 @@ Constant *ConstantExpr::getWithOperandReplaced(unsigned OpNo,
   
   Constant *Op0, *Op1, *Op2;
   switch (getOpcode()) {
-  case Instruction::Cast:
-    return ConstantExpr::getCast(Op, getType());
+  case Instruction::Trunc:
+  case Instruction::ZExt:
+  case Instruction::SExt:
+  case Instruction::FPTrunc:
+  case Instruction::FPExt:
+  case Instruction::UIToFP:
+  case Instruction::SIToFP:
+  case Instruction::FPToUI:
+  case Instruction::FPToSI:
+  case Instruction::PtrToInt:
+  case Instruction::IntToPtr:
+  case Instruction::BitCast:
+    return ConstantExpr::getCast(getOpcode(), Op, getType());
   case Instruction::Select:
     Op0 = (OpNo == 0) ? Op : getOperand(0);
     Op1 = (OpNo == 1) ? Op : getOperand(1);
@@ -580,8 +605,19 @@ getWithOperands(const std::vector<Constant*> &Ops) const {
     return const_cast<ConstantExpr*>(this);
 
   switch (getOpcode()) {
-  case Instruction::Cast:
-    return ConstantExpr::getCast(Ops[0], getType());
+  case Instruction::Trunc:
+  case Instruction::ZExt:
+  case Instruction::SExt:
+  case Instruction::FPTrunc:
+  case Instruction::FPExt:
+  case Instruction::UIToFP:
+  case Instruction::SIToFP:
+  case Instruction::FPToUI:
+  case Instruction::FPToSI:
+  case Instruction::PtrToInt:
+  case Instruction::IntToPtr:
+  case Instruction::BitCast:
+    return ConstantExpr::getCast(getOpcode(), Ops[0], getType());
   case Instruction::Select:
     return ConstantExpr::getSelect(Ops[0], Ops[1], Ops[2]);
   case Instruction::InsertElement:
@@ -879,7 +915,7 @@ public:
     }
 
     void dump() const {
-      std::cerr << "Constant.cpp: ValueMap\n";
+      DOUT << "Constant.cpp: ValueMap\n";
     }
   };
 }
@@ -908,9 +944,12 @@ static ManagedStatic<ValueMap<uint64_t, Type, ConstantInt> > IntConstants;
 // just return the stored value while getSExtValue has to convert back to sign
 // extended. getZExtValue is more common in LLVM than getSExtValue().
 ConstantInt *ConstantInt::get(const Type *Ty, int64_t V) {
-  unsigned Size = Ty->getPrimitiveSizeInBits();
-  uint64_t ZeroExtendedCanonicalization = V & (~uint64_t(0UL) >> (64-Size));
-  return IntConstants->getOrCreate(Ty, ZeroExtendedCanonicalization );
+  return IntConstants->getOrCreate(Ty, V & Ty->getIntegralTypeMask());
+}
+
+ConstantIntegral *ConstantIntegral::get(const Type *Ty, int64_t V) {
+  if (Ty == Type::BoolTy) return ConstantBool::get(V&1);
+  return IntConstants->getOrCreate(Ty, V & Ty->getIntegralTypeMask());
 }
 
 //---- ConstantFP::get() implementation...
@@ -1316,37 +1355,70 @@ void UndefValue::destroyConstant() {
 }
 
 
-
-
 //---- ConstantExpr::get() implementations...
 //
-typedef std::pair<unsigned, std::vector<Constant*> > ExprMapKeyType;
+struct ExprMapKeyType {
+  explicit ExprMapKeyType(unsigned opc, std::vector<Constant*> ops,
+      unsigned short pred = 0) : opcode(opc), predicate(pred), operands(ops) { }
+  uint16_t opcode;
+  uint16_t predicate;
+  std::vector<Constant*> operands;
+  bool operator==(const ExprMapKeyType& that) const {
+    return this->opcode == that.opcode &&
+           this->predicate == that.predicate &&
+           this->operands == that.operands;
+  }
+  bool operator<(const ExprMapKeyType & that) const {
+    return this->opcode < that.opcode ||
+      (this->opcode == that.opcode && this->predicate < that.predicate) ||
+      (this->opcode == that.opcode && this->predicate == that.predicate &&
+       this->operands < that.operands);
+  }
+
+  bool operator!=(const ExprMapKeyType& that) const {
+    return !(*this == that);
+  }
+};
 
 namespace llvm {
   template<>
   struct ConstantCreator<ConstantExpr, Type, ExprMapKeyType> {
-    static ConstantExpr *create(const Type *Ty, const ExprMapKeyType &V) {
-      if (V.first == Instruction::Cast)
-        return new UnaryConstantExpr(Instruction::Cast, V.second[0], Ty);
-      if ((V.first >= Instruction::BinaryOpsBegin &&
-           V.first < Instruction::BinaryOpsEnd) ||
-          V.first == Instruction::Shl || V.first == Instruction::Shr)
-        return new BinaryConstantExpr(V.first, V.second[0], V.second[1]);
-      if (V.first == Instruction::Select)
-        return new SelectConstantExpr(V.second[0], V.second[1], V.second[2]);
-      if (V.first == Instruction::ExtractElement)
-        return new ExtractElementConstantExpr(V.second[0], V.second[1]);
-      if (V.first == Instruction::InsertElement)
-        return new InsertElementConstantExpr(V.second[0], V.second[1],
-                                             V.second[2]);
-      if (V.first == Instruction::ShuffleVector)
-        return new ShuffleVectorConstantExpr(V.second[0], V.second[1],
-                                             V.second[2]);
-      
-      assert(V.first == Instruction::GetElementPtr && "Invalid ConstantExpr!");
+    static ConstantExpr *create(const Type *Ty, const ExprMapKeyType &V,
+        unsigned short pred = 0) {
+      if (Instruction::isCast(V.opcode))
+        return new UnaryConstantExpr(V.opcode, V.operands[0], Ty);
+      if ((V.opcode >= Instruction::BinaryOpsBegin &&
+           V.opcode < Instruction::BinaryOpsEnd) ||
+          V.opcode == Instruction::Shl           || 
+          V.opcode == Instruction::LShr          ||
+          V.opcode == Instruction::AShr)
+        return new BinaryConstantExpr(V.opcode, V.operands[0], V.operands[1]);
+      if (V.opcode == Instruction::Select)
+        return new SelectConstantExpr(V.operands[0], V.operands[1], 
+                                      V.operands[2]);
+      if (V.opcode == Instruction::ExtractElement)
+        return new ExtractElementConstantExpr(V.operands[0], V.operands[1]);
+      if (V.opcode == Instruction::InsertElement)
+        return new InsertElementConstantExpr(V.operands[0], V.operands[1],
+                                             V.operands[2]);
+      if (V.opcode == Instruction::ShuffleVector)
+        return new ShuffleVectorConstantExpr(V.operands[0], V.operands[1],
+                                             V.operands[2]);
+      if (V.opcode == Instruction::GetElementPtr) {
+        std::vector<Constant*> IdxList(V.operands.begin()+1, V.operands.end());
+        return new GetElementPtrConstantExpr(V.operands[0], IdxList, Ty);
+      }
 
-      std::vector<Constant*> IdxList(V.second.begin()+1, V.second.end());
-      return new GetElementPtrConstantExpr(V.second[0], IdxList, Ty);
+      // The compare instructions are weird. We have to encode the predicate
+      // value and it is combined with the instruction opcode by multiplying
+      // the opcode by one hundred. We must decode this to get the predicate.
+      if (V.opcode == Instruction::ICmp)
+        return new CompareConstantExpr(Instruction::ICmp, V.predicate, 
+                                       V.operands[0], V.operands[1]);
+      if (V.opcode == Instruction::FCmp) 
+        return new CompareConstantExpr(Instruction::FCmp, V.predicate, 
+                                       V.operands[0], V.operands[1]);
+      assert(0 && "Invalid ConstantExpr!");
     }
   };
 
@@ -1355,8 +1427,20 @@ namespace llvm {
     static void convert(ConstantExpr *OldC, const Type *NewTy) {
       Constant *New;
       switch (OldC->getOpcode()) {
-      case Instruction::Cast:
-        New = ConstantExpr::getCast(OldC->getOperand(0), NewTy);
+      case Instruction::Trunc:
+      case Instruction::ZExt:
+      case Instruction::SExt:
+      case Instruction::FPTrunc:
+      case Instruction::FPExt:
+      case Instruction::UIToFP:
+      case Instruction::SIToFP:
+      case Instruction::FPToUI:
+      case Instruction::FPToSI:
+      case Instruction::PtrToInt:
+      case Instruction::IntToPtr:
+      case Instruction::BitCast:
+        New = ConstantExpr::getCast(
+            OldC->getOpcode(), OldC->getOperand(0), NewTy);
         break;
       case Instruction::Select:
         New = ConstantExpr::getSelectTy(NewTy, OldC->getOperand(0),
@@ -1364,7 +1448,8 @@ namespace llvm {
                                         OldC->getOperand(2));
         break;
       case Instruction::Shl:
-      case Instruction::Shr:
+      case Instruction::LShr:
+      case Instruction::AShr:
         New = ConstantExpr::getShiftTy(NewTy, OldC->getOpcode(),
                                      OldC->getOperand(0), OldC->getOperand(1));
         break;
@@ -1394,54 +1479,177 @@ static ExprMapKeyType getValType(ConstantExpr *CE) {
   Operands.reserve(CE->getNumOperands());
   for (unsigned i = 0, e = CE->getNumOperands(); i != e; ++i)
     Operands.push_back(cast<Constant>(CE->getOperand(i)));
-  return ExprMapKeyType(CE->getOpcode(), Operands);
+  return ExprMapKeyType(CE->getOpcode(), Operands, 
+      CE->isCompare() ? CE->getPredicate() : 0);
 }
 
 static ManagedStatic<ValueMap<ExprMapKeyType, Type,
                               ConstantExpr> > ExprConstants;
 
-Constant *ConstantExpr::getCast(Constant *C, const Type *Ty) {
+/// This is a utility function to handle folding of casts and lookup of the
+/// cast in the ExprConstants map. It is usedby the various get* methods below.
+static inline Constant *getFoldedCast(
+  Instruction::CastOps opc, Constant *C, const Type *Ty) {
   assert(Ty->isFirstClassType() && "Cannot cast to an aggregate type!");
-
-  if (Constant *FC = ConstantFoldCastInstruction(C, Ty))
-    return FC;          // Fold a few common cases...
+  // Fold a few common cases
+  if (Constant *FC = ConstantFoldCastInstruction(opc, C, Ty))
+    return FC;
 
   // Look up the constant in the table first to ensure uniqueness
   std::vector<Constant*> argVec(1, C);
-  ExprMapKeyType Key = std::make_pair(Instruction::Cast, argVec);
+  ExprMapKeyType Key(opc, argVec);
   return ExprConstants->getOrCreate(Ty, Key);
 }
 
-Constant *ConstantExpr::getSignExtend(Constant *C, const Type *Ty) {
-  assert(C->getType()->isIntegral() && Ty->isIntegral() &&
-         C->getType()->getPrimitiveSize() <= Ty->getPrimitiveSize() &&
-         "This is an illegal sign extension!");
-  if (C->getType() != Type::BoolTy) {
-    C = ConstantExpr::getCast(C, C->getType()->getSignedVersion());
-    return ConstantExpr::getCast(C, Ty);
-  } else {
-    if (C == ConstantBool::getTrue())
-      return ConstantIntegral::getAllOnesValue(Ty);
-    else
-      return ConstantIntegral::getNullValue(Ty);
+Constant *ConstantExpr::getInferredCast(Constant *C, bool SrcIsSigned, 
+                                const Type *Ty, bool DestIsSigned) {
+  // Note: we can't inline this because it requires the Instructions.h header
+  return getCast(
+    CastInst::getCastOpcode(C, SrcIsSigned, Ty, DestIsSigned), C, Ty);
+}
+
+Constant *ConstantExpr::getCast(unsigned oc, Constant *C, const Type *Ty) {
+  Instruction::CastOps opc = Instruction::CastOps(oc);
+  assert(Instruction::isCast(opc) && "opcode out of range");
+  assert(C && Ty && "Null arguments to getCast");
+  assert(Ty->isFirstClassType() && "Cannot cast to an aggregate type!");
+
+  switch (opc) {
+    default:
+      assert(0 && "Invalid cast opcode");
+      break;
+    case Instruction::Trunc:    return getTrunc(C, Ty);
+    case Instruction::ZExt:     return getZeroExtend(C, Ty);
+    case Instruction::SExt:     return getSignExtend(C, Ty);
+    case Instruction::FPTrunc:  return getFPTrunc(C, Ty);
+    case Instruction::FPExt:    return getFPExtend(C, Ty);
+    case Instruction::UIToFP:   return getUIToFP(C, Ty);
+    case Instruction::SIToFP:   return getSIToFP(C, Ty);
+    case Instruction::FPToUI:   return getFPToUI(C, Ty);
+    case Instruction::FPToSI:   return getFPToSI(C, Ty);
+    case Instruction::PtrToInt: return getPtrToInt(C, Ty);
+    case Instruction::IntToPtr: return getIntToPtr(C, Ty);
+    case Instruction::BitCast:  return getBitCast(C, Ty);
   }
+  return 0;
+}
+
+Constant *ConstantExpr::getZExtOrBitCast(Constant *C, const Type *Ty) {
+  if (C->getType()->getPrimitiveSizeInBits() == Ty->getPrimitiveSizeInBits())
+    return getCast(Instruction::BitCast, C, Ty);
+  return getCast(Instruction::ZExt, C, Ty);
+}
+
+Constant *ConstantExpr::getSExtOrBitCast(Constant *C, const Type *Ty) {
+  if (C->getType()->getPrimitiveSizeInBits() == Ty->getPrimitiveSizeInBits())
+    return getCast(Instruction::BitCast, C, Ty);
+  return getCast(Instruction::SExt, C, Ty);
+}
+
+Constant *ConstantExpr::getTruncOrBitCast(Constant *C, const Type *Ty) {
+  if (C->getType()->getPrimitiveSizeInBits() == Ty->getPrimitiveSizeInBits())
+    return getCast(Instruction::BitCast, C, Ty);
+  return getCast(Instruction::Trunc, C, Ty);
+}
+
+Constant *ConstantExpr::getTrunc(Constant *C, const Type *Ty) {
+  assert(C->getType()->isInteger() && "Trunc operand must be integer");
+  assert(Ty->isIntegral() && "Trunc produces only integral");
+  assert(C->getType()->getPrimitiveSizeInBits() > Ty->getPrimitiveSizeInBits()&&
+         "SrcTy must be larger than DestTy for Trunc!");
+
+  return getFoldedCast(Instruction::Trunc, C, Ty);
+}
+
+Constant *ConstantExpr::getSignExtend(Constant *C, const Type *Ty) {
+  assert(C->getType()->isIntegral() && "SEXt operand must be integral");
+  assert(Ty->isInteger() && "SExt produces only integer");
+  assert(C->getType()->getPrimitiveSizeInBits() < Ty->getPrimitiveSizeInBits()&&
+         "SrcTy must be smaller than DestTy for SExt!");
+
+  return getFoldedCast(Instruction::SExt, C, Ty);
 }
 
 Constant *ConstantExpr::getZeroExtend(Constant *C, const Type *Ty) {
-  assert(C->getType()->isIntegral() && Ty->isIntegral() &&
-         C->getType()->getPrimitiveSize() <= Ty->getPrimitiveSize() &&
-         "This is an illegal zero extension!");
-  if (C->getType() != Type::BoolTy)
-    C = ConstantExpr::getCast(C, C->getType()->getUnsignedVersion());
-  return ConstantExpr::getCast(C, Ty);
+  assert(C->getType()->isIntegral() && "ZEXt operand must be integral");
+  assert(Ty->isInteger() && "ZExt produces only integer");
+  assert(C->getType()->getPrimitiveSizeInBits() < Ty->getPrimitiveSizeInBits()&&
+         "SrcTy must be smaller than DestTy for ZExt!");
+
+  return getFoldedCast(Instruction::ZExt, C, Ty);
+}
+
+Constant *ConstantExpr::getFPTrunc(Constant *C, const Type *Ty) {
+  assert(C->getType()->isFloatingPoint() && Ty->isFloatingPoint() &&
+         C->getType()->getPrimitiveSizeInBits() > Ty->getPrimitiveSizeInBits()&&
+         "This is an illegal floating point truncation!");
+  return getFoldedCast(Instruction::FPTrunc, C, Ty);
+}
+
+Constant *ConstantExpr::getFPExtend(Constant *C, const Type *Ty) {
+  assert(C->getType()->isFloatingPoint() && Ty->isFloatingPoint() &&
+         C->getType()->getPrimitiveSizeInBits() < Ty->getPrimitiveSizeInBits()&&
+         "This is an illegal floating point extension!");
+  return getFoldedCast(Instruction::FPExt, C, Ty);
+}
+
+Constant *ConstantExpr::getUIToFP(Constant *C, const Type *Ty) {
+  assert(C->getType()->isIntegral() && Ty->isFloatingPoint() &&
+         "This is an illegal uint to floating point cast!");
+  return getFoldedCast(Instruction::UIToFP, C, Ty);
+}
+
+Constant *ConstantExpr::getSIToFP(Constant *C, const Type *Ty) {
+  assert(C->getType()->isIntegral() && Ty->isFloatingPoint() &&
+         "This is an illegal sint to floating point cast!");
+  return getFoldedCast(Instruction::SIToFP, C, Ty);
+}
+
+Constant *ConstantExpr::getFPToUI(Constant *C, const Type *Ty) {
+  assert(C->getType()->isFloatingPoint() && Ty->isIntegral() &&
+         "This is an illegal floating point to uint cast!");
+  return getFoldedCast(Instruction::FPToUI, C, Ty);
+}
+
+Constant *ConstantExpr::getFPToSI(Constant *C, const Type *Ty) {
+  assert(C->getType()->isFloatingPoint() && Ty->isIntegral() &&
+         "This is an illegal floating point to sint cast!");
+  return getFoldedCast(Instruction::FPToSI, C, Ty);
+}
+
+Constant *ConstantExpr::getPtrToInt(Constant *C, const Type *DstTy) {
+  assert(isa<PointerType>(C->getType()) && "PtrToInt source must be pointer");
+  assert(DstTy->isIntegral() && "PtrToInt destination must be integral");
+  return getFoldedCast(Instruction::PtrToInt, C, DstTy);
+}
+
+Constant *ConstantExpr::getIntToPtr(Constant *C, const Type *DstTy) {
+  assert(C->getType()->isIntegral() && "IntToPtr source must be integral");
+  assert(isa<PointerType>(DstTy) && "IntToPtr destination must be a pointer");
+  return getFoldedCast(Instruction::IntToPtr, C, DstTy);
+}
+
+Constant *ConstantExpr::getBitCast(Constant *C, const Type *DstTy) {
+  // BitCast implies a no-op cast of type only. No bits change.  However, you 
+  // can't cast pointers to anything but pointers.
+  const Type *SrcTy = C->getType();
+  assert((isa<PointerType>(SrcTy) == isa<PointerType>(DstTy)) &&
+         "BitCast cannot cast pointer to non-pointer and vice versa");
+
+  // Now we know we're not dealing with mismatched pointer casts (ptr->nonptr
+  // or nonptr->ptr). For all the other types, the cast is okay if source and 
+  // destination bit widths are identical.
+  unsigned SrcBitSize = SrcTy->getPrimitiveSizeInBits();
+  unsigned DstBitSize = DstTy->getPrimitiveSizeInBits();
+  assert(SrcBitSize == DstBitSize && "BitCast requies types of same width");
+  return getFoldedCast(Instruction::BitCast, C, DstTy);
 }
 
 Constant *ConstantExpr::getSizeOf(const Type *Ty) {
   // sizeof is implemented as: (ulong) gep (Ty*)null, 1
-  return getCast(
-    getGetElementPtr(getNullValue(PointerType::get(Ty)),
-                 std::vector<Constant*>(1, ConstantInt::get(Type::UIntTy, 1))),
-    Type::ULongTy);
+  return getCast(Instruction::PtrToInt, getGetElementPtr(getNullValue(
+    PointerType::get(Ty)), std::vector<Constant*>(1, 
+    ConstantInt::get(Type::UIntTy, 1))), Type::ULongTy);
 }
 
 Constant *ConstantExpr::getPtrPtrFromArrayPtr(Constant *C) {
@@ -1452,9 +1660,15 @@ Constant *ConstantExpr::getPtrPtrFromArrayPtr(Constant *C) {
 }
 
 Constant *ConstantExpr::getTy(const Type *ReqTy, unsigned Opcode,
-                              Constant *C1, Constant *C2) {
-  if (Opcode == Instruction::Shl || Opcode == Instruction::Shr)
+                              Constant *C1, Constant *C2, unsigned short pred) {
+  if (Opcode == Instruction::Shl || Opcode == Instruction::LShr ||
+      Opcode == Instruction::AShr)
     return getShiftTy(ReqTy, Opcode, C1, C2);
+  if (Opcode == Instruction::ICmp)
+    return getICmp(pred, C1, C2);
+  if (Opcode == Instruction::FCmp)
+    return getFCmp(pred, C1, C2);
+
   // Check the operands for consistency first
   assert(Opcode >= Instruction::BinaryOpsBegin &&
          Opcode <  Instruction::BinaryOpsEnd   &&
@@ -1468,11 +1682,11 @@ Constant *ConstantExpr::getTy(const Type *ReqTy, unsigned Opcode,
       return FC;          // Fold a few common cases...
 
   std::vector<Constant*> argVec(1, C1); argVec.push_back(C2);
-  ExprMapKeyType Key = std::make_pair(Opcode, argVec);
+  ExprMapKeyType Key(Opcode, argVec, pred);
   return ExprConstants->getOrCreate(ReqTy, Key);
 }
 
-Constant *ConstantExpr::get(unsigned Opcode, Constant *C1, Constant *C2) {
+Constant *ConstantExpr::get(unsigned Opcode, Constant *C1, Constant *C2, unsigned short pred) {
 #ifndef NDEBUG
   switch (Opcode) {
   case Instruction::Add: 
@@ -1520,10 +1734,15 @@ Constant *ConstantExpr::get(unsigned Opcode, Constant *C1, Constant *C2) {
   case Instruction::SetGE: case Instruction::SetEQ: case Instruction::SetNE:
     assert(C1->getType() == C2->getType() && "Op types should be identical!");
     break;
+  case Instruction::FCmp:
+  case Instruction::ICmp:
+    assert(C1->getType() == C2->getType() && "Op types should be identical!");
+    break;
   case Instruction::Shl:
-  case Instruction::Shr:
+  case Instruction::LShr:
+  case Instruction::AShr:
     assert(C2->getType() == Type::UByteTy && "Shift should be by ubyte!");
-    assert((C1->getType()->isInteger() || isa<PackedType>(C1->getType())) &&
+    assert(C1->getType()->isInteger() &&
            "Tried to create a shift operation on a non-integer type!");
     break;
   default:
@@ -1532,9 +1751,9 @@ Constant *ConstantExpr::get(unsigned Opcode, Constant *C1, Constant *C2) {
 #endif
 
   if (Instruction::isComparison(Opcode))
-    return getTy(Type::BoolTy, Opcode, C1, C2);
+    return getTy(Type::BoolTy, Opcode, C1, C2, pred);
   else
-    return getTy(C1->getType(), Opcode, C1, C2);
+    return getTy(C1->getType(), Opcode, C1, C2, pred);
 }
 
 Constant *ConstantExpr::getSelectTy(const Type *ReqTy, Constant *C,
@@ -1550,7 +1769,7 @@ Constant *ConstantExpr::getSelectTy(const Type *ReqTy, Constant *C,
   std::vector<Constant*> argVec(3, C);
   argVec[1] = V1;
   argVec[2] = V2;
-  ExprMapKeyType Key = std::make_pair(Instruction::Select, argVec);
+  ExprMapKeyType Key(Instruction::Select, argVec);
   return ExprConstants->getOrCreate(ReqTy, Key);
 }
 
@@ -1558,8 +1777,9 @@ Constant *ConstantExpr::getSelectTy(const Type *ReqTy, Constant *C,
 Constant *ConstantExpr::getShiftTy(const Type *ReqTy, unsigned Opcode,
                                    Constant *C1, Constant *C2) {
   // Check the operands for consistency first
-  assert((Opcode == Instruction::Shl ||
-          Opcode == Instruction::Shr) &&
+  assert((Opcode == Instruction::Shl   ||
+          Opcode == Instruction::LShr  ||
+          Opcode == Instruction::AShr) &&
          "Invalid opcode in binary constant expression");
   assert(C1->getType()->isIntegral() && C2->getType() == Type::UByteTy &&
          "Invalid operand types for Shift constant expr!");
@@ -1569,7 +1789,7 @@ Constant *ConstantExpr::getShiftTy(const Type *ReqTy, unsigned Opcode,
 
   // Look up the constant in the table first to ensure uniqueness
   std::vector<Constant*> argVec(1, C1); argVec.push_back(C2);
-  ExprMapKeyType Key = std::make_pair(Opcode, argVec);
+  ExprMapKeyType Key(Opcode, argVec);
   return ExprConstants->getOrCreate(ReqTy, Key);
 }
 
@@ -1590,7 +1810,7 @@ Constant *ConstantExpr::getGetElementPtrTy(const Type *ReqTy, Constant *C,
   ArgVec.push_back(C);
   for (unsigned i = 0, e = IdxList.size(); i != e; ++i)
     ArgVec.push_back(cast<Constant>(IdxList[i]));
-  const ExprMapKeyType &Key = std::make_pair(Instruction::GetElementPtr,ArgVec);
+  const ExprMapKeyType Key(Instruction::GetElementPtr,ArgVec);
   return ExprConstants->getOrCreate(ReqTy, Key);
 }
 
@@ -1614,6 +1834,41 @@ Constant *ConstantExpr::getGetElementPtr(Constant *C,
   return getGetElementPtrTy(PointerType::get(Ty), C, IdxList);
 }
 
+Constant *
+ConstantExpr::getICmp(unsigned short pred, Constant* LHS, Constant* RHS) {
+  assert(LHS->getType() == RHS->getType());
+  assert(pred >= ICmpInst::FIRST_ICMP_PREDICATE && 
+         pred <= ICmpInst::LAST_ICMP_PREDICATE && "Invalid ICmp Predicate");
+
+  if (Constant *FC = ConstantFoldCompare(Instruction::ICmp, LHS, RHS, pred))
+    return FC;          // Fold a few common cases...
+
+  // Look up the constant in the table first to ensure uniqueness
+  std::vector<Constant*> ArgVec;
+  ArgVec.push_back(LHS);
+  ArgVec.push_back(RHS);
+  // Fake up an opcode value that encodes both the opcode and predicate
+  const ExprMapKeyType Key(Instruction::ICmp, ArgVec, pred);
+  return ExprConstants->getOrCreate(Type::BoolTy, Key);
+}
+
+Constant *
+ConstantExpr::getFCmp(unsigned short pred, Constant* LHS, Constant* RHS) {
+  assert(LHS->getType() == RHS->getType());
+  assert(pred <= FCmpInst::LAST_FCMP_PREDICATE && "Invalid FCmp Predicate");
+
+  if (Constant *FC = ConstantFoldCompare(Instruction::FCmp, LHS, RHS, pred))
+    return FC;          // Fold a few common cases...
+
+  // Look up the constant in the table first to ensure uniqueness
+  std::vector<Constant*> ArgVec;
+  ArgVec.push_back(LHS);
+  ArgVec.push_back(RHS);
+  // Fake up an opcode value that encodes both the opcode and predicate
+  const ExprMapKeyType Key(Instruction::FCmp, ArgVec, pred);
+  return ExprConstants->getOrCreate(Type::BoolTy, Key);
+}
+
 Constant *ConstantExpr::getExtractElementTy(const Type *ReqTy, Constant *Val,
                                             Constant *Idx) {
   if (Constant *FC = ConstantFoldExtractElementInstruction(Val, Idx))
@@ -1621,7 +1876,7 @@ Constant *ConstantExpr::getExtractElementTy(const Type *ReqTy, Constant *Val,
   // Look up the constant in the table first to ensure uniqueness
   std::vector<Constant*> ArgVec(1, Val);
   ArgVec.push_back(Idx);
-  const ExprMapKeyType &Key = std::make_pair(Instruction::ExtractElement,ArgVec);
+  const ExprMapKeyType Key(Instruction::ExtractElement,ArgVec);
   return ExprConstants->getOrCreate(ReqTy, Key);
 }
 
@@ -1642,7 +1897,7 @@ Constant *ConstantExpr::getInsertElementTy(const Type *ReqTy, Constant *Val,
   std::vector<Constant*> ArgVec(1, Val);
   ArgVec.push_back(Elt);
   ArgVec.push_back(Idx);
-  const ExprMapKeyType &Key = std::make_pair(Instruction::InsertElement,ArgVec);
+  const ExprMapKeyType Key(Instruction::InsertElement,ArgVec);
   return ExprConstants->getOrCreate(ReqTy, Key);
 }
 
@@ -1666,7 +1921,7 @@ Constant *ConstantExpr::getShuffleVectorTy(const Type *ReqTy, Constant *V1,
   std::vector<Constant*> ArgVec(1, V1);
   ArgVec.push_back(V2);
   ArgVec.push_back(Mask);
-  const ExprMapKeyType &Key = std::make_pair(Instruction::ShuffleVector,ArgVec);
+  const ExprMapKeyType Key(Instruction::ShuffleVector,ArgVec);
   return ExprConstants->getOrCreate(ReqTy, Key);
 }
 
@@ -1677,7 +1932,6 @@ Constant *ConstantExpr::getShuffleVector(Constant *V1, Constant *V2,
   return getShuffleVectorTy(V1->getType(), V1, V2, Mask);
 }
 
-
 // destroyConstant - Remove the constant from the constant table...
 //
 void ConstantExpr::destroyConstant() {
@@ -1861,9 +2115,9 @@ void ConstantExpr::replaceUsesOfWithOnConstant(Value *From, Value *ToV,
       Indices.push_back(Val);
     }
     Replacement = ConstantExpr::getGetElementPtr(Pointer, Indices);
-  } else if (getOpcode() == Instruction::Cast) {
+  } else if (isCast()) {
     assert(getOperand(0) == From && "Cast only has one use!");
-    Replacement = ConstantExpr::getCast(To, getType());
+    Replacement = ConstantExpr::getCast(getOpcode(), To, getType());
   } else if (getOpcode() == Instruction::Select) {
     Constant *C1 = getOperand(0);
     Constant *C2 = getOperand(1);
@@ -1894,6 +2148,15 @@ void ConstantExpr::replaceUsesOfWithOnConstant(Value *From, Value *ToV,
     if (C2 == From) C2 = To;
     if (C3 == From) C3 = To;
     Replacement = ConstantExpr::getShuffleVector(C1, C2, C3);
+  } else if (isCompare()) {
+    Constant *C1 = getOperand(0);
+    Constant *C2 = getOperand(1);
+    if (C1 == From) C1 = To;
+    if (C2 == From) C2 = To;
+    if (getOpcode() == Instruction::ICmp)
+      Replacement = ConstantExpr::getICmp(getPredicate(), C1, C2);
+    else
+      Replacement = ConstantExpr::getFCmp(getPredicate(), C1, C2);
   } else if (getNumOperands() == 2) {
     Constant *C1 = getOperand(0);
     Constant *C2 = getOperand(1);