#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;
//===----------------------------------------------------------------------===//
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);
case Instruction::UDiv:
case Instruction::SDiv:
case Instruction::FDiv:
- case Instruction::Rem:
+ case Instruction::URem:
+ case Instruction::SRem:
+ case Instruction::FRem:
// Div and rem can trap if the RHS is not known to be non-zero.
if (!isa<ConstantInt>(getOperand(1)) || getOperand(1)->isNullValue())
return true;
}
}
-// Static constructor to create the maximum constant of an integral type...
-ConstantIntegral *ConstantIntegral::getMaxValue(const Type *Ty) {
- switch (Ty->getTypeID()) {
- case Type::BoolTyID: return ConstantBool::getTrue();
- case Type::SByteTyID:
- case Type::ShortTyID:
- case Type::IntTyID:
- case Type::LongTyID: {
- // Calculate 011111111111111...
- unsigned TypeBits = Ty->getPrimitiveSize()*8;
- int64_t Val = INT64_MAX; // All ones
- Val >>= 64-TypeBits; // Shift out unwanted 1 bits...
- return ConstantInt::get(Ty, Val);
- }
-
- case Type::UByteTyID:
- case Type::UShortTyID:
- case Type::UIntTyID:
- case Type::ULongTyID: return getAllOnesValue(Ty);
-
- default: return 0;
- }
-}
-
-// Static constructor to create the minimum constant for an integral type...
-ConstantIntegral *ConstantIntegral::getMinValue(const Type *Ty) {
- switch (Ty->getTypeID()) {
- case Type::BoolTyID: return ConstantBool::getFalse();
- case Type::SByteTyID:
- case Type::ShortTyID:
- case Type::IntTyID:
- case Type::LongTyID: {
- // Calculate 1111111111000000000000
- unsigned TypeBits = Ty->getPrimitiveSize()*8;
- int64_t Val = -1; // All ones
- Val <<= TypeBits-1; // Shift over to the right spot
- return ConstantInt::get(Ty, Val);
- }
-
- case Type::UByteTyID:
- case Type::UShortTyID:
- case Type::UIntTyID:
- case Type::ULongTyID: return ConstantInt::get(Ty, 0);
-
- default: return 0;
- }
-}
// Static constructor to create an integral constant with all bits set
ConstantIntegral *ConstantIntegral::getAllOnesValue(const Type *Ty) {
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:
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:
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:
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:
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:
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)
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
Constant *ConstantExpr::getFDiv(Constant *C1, Constant *C2) {
return get(Instruction::FDiv, C1, C2);
}
-Constant *ConstantExpr::getRem(Constant *C1, Constant *C2) {
- return get(Instruction::Rem, C1, C2);
+Constant *ConstantExpr::getURem(Constant *C1, Constant *C2) {
+ return get(Instruction::URem, C1, C2);
+}
+Constant *ConstantExpr::getSRem(Constant *C1, Constant *C2) {
+ return get(Instruction::SRem, C1, C2);
+}
+Constant *ConstantExpr::getFRem(Constant *C1, Constant *C2) {
+ return get(Instruction::FRem, C1, C2);
}
Constant *ConstantExpr::getAnd(Constant *C1, Constant *C2) {
return get(Instruction::And, C1, 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!");
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);
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:
}
void dump() const {
- std::cerr << "Constant.cpp: ValueMap\n";
+ DOUT << "Constant.cpp: ValueMap\n";
}
};
}
// 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...
return true;
}
+/// isCString - This method returns true if the array is a string (see
+/// isString) and it ends in a null byte \0 and does not contains any other
+/// null bytes except its terminator.
+bool ConstantArray::isCString() const {
+ // Check the element type for sbyte or ubyte...
+ if (getType()->getElementType() != Type::UByteTy &&
+ getType()->getElementType() != Type::SByteTy)
+ return false;
+ Constant *Zero = Constant::getNullValue(getOperand(0)->getType());
+ // Last element must be a null.
+ if (getOperand(getNumOperands()-1) != Zero)
+ return false;
+ // Other elements must be non-null integers.
+ for (unsigned i = 0, e = getNumOperands()-1; i != e; ++i) {
+ if (!isa<ConstantInt>(getOperand(i)))
+ return false;
+ if (getOperand(i) == Zero)
+ return false;
+ }
+ return true;
+}
+
+
// getAsString - If the sub-element type of this array is either sbyte or ubyte,
// then this method converts the array to an std::string and returns it.
// Otherwise, it asserts out.
}
-
-
//---- 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!");
}
};
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),
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;
default:
assert(OldC->getOpcode() >= Instruction::BinaryOpsBegin &&
- OldC->getOpcode() < Instruction::BinaryOpsEnd);
+ OldC->getOpcode() < Instruction::BinaryOpsEnd);
New = ConstantExpr::getTy(NewTy, OldC->getOpcode(), OldC->getOperand(0),
OldC->getOperand(1));
break;
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::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!");
-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);
+ 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::getCast(Constant *C, const Type *Ty) {
+ // Note: we can't inline this because it requires the Instructions.h header
+ return getCast(CastInst::getCastOpcode(
+ C, C->getType()->isSigned(), Ty, Ty->isSigned()), C, Ty);
+}
+
+
+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::getPointerCast(Constant *S, const Type *Ty) {
+ assert(isa<PointerType>(S->getType()) && "Invalid cast");
+ assert((Ty->isIntegral() || Ty->getTypeID() == Type::PointerTyID) &&
+ "Invalid cast");
+
+ if (Ty->isIntegral())
+ return getCast(Instruction::PtrToInt, S, Ty);
+ return getCast(Instruction::BitCast, S, 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) {
Constant *ConstantExpr::getTy(const Type *ReqTy, unsigned Opcode,
Constant *C1, Constant *C2) {
- if (Opcode == Instruction::Shl || Opcode == Instruction::Shr)
+ if (Opcode == Instruction::Shl || Opcode == Instruction::LShr ||
+ Opcode == Instruction::AShr)
return getShiftTy(ReqTy, Opcode, C1, C2);
+
// Check the operands for consistency first
- assert((Opcode >= Instruction::BinaryOpsBegin &&
- Opcode < Instruction::BinaryOpsEnd) &&
+ assert(Opcode >= Instruction::BinaryOpsBegin &&
+ Opcode < Instruction::BinaryOpsEnd &&
"Invalid opcode in binary constant expression");
assert(C1->getType() == C2->getType() &&
"Operand types in binary constant expression should match");
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);
return ExprConstants->getOrCreate(ReqTy, Key);
}
+Constant *ConstantExpr::getCompareTy(unsigned Opcode, unsigned short predicate,
+ Constant *C1, Constant *C2) {
+ if (Opcode == Instruction::ICmp)
+ return getICmp(predicate, C1, C2);
+ return getFCmp(predicate, C1, C2);
+}
+
Constant *ConstantExpr::get(unsigned Opcode, Constant *C1, Constant *C2) {
#ifndef NDEBUG
switch (Opcode) {
- case Instruction::Add: case Instruction::Sub:
+ case Instruction::Add:
+ case Instruction::Sub:
case Instruction::Mul:
- case Instruction::Rem:
assert(C1->getType() == C2->getType() && "Op types should be identical!");
assert((C1->getType()->isInteger() || C1->getType()->isFloatingPoint() ||
isa<PackedType>(C1->getType())) &&
"Tried to create an arithmetic operation on a non-arithmetic type!");
break;
-
case Instruction::UDiv:
case Instruction::SDiv:
assert(C1->getType() == C2->getType() && "Op types should be identical!");
&& cast<PackedType>(C1->getType())->getElementType()->isFloatingPoint()))
&& "Tried to create an arithmetic operation on a non-arithmetic type!");
break;
+ case Instruction::URem:
+ case Instruction::SRem:
+ assert(C1->getType() == C2->getType() && "Op types should be identical!");
+ assert((C1->getType()->isInteger() || (isa<PackedType>(C1->getType()) &&
+ cast<PackedType>(C1->getType())->getElementType()->isInteger())) &&
+ "Tried to create an arithmetic operation on a non-arithmetic type!");
+ break;
+ case Instruction::FRem:
+ assert(C1->getType() == C2->getType() && "Op types should be identical!");
+ assert((C1->getType()->isFloatingPoint() || (isa<PackedType>(C1->getType())
+ && cast<PackedType>(C1->getType())->getElementType()->isFloatingPoint()))
+ && "Tried to create an arithmetic operation on a non-arithmetic type!");
+ break;
case Instruction::And:
case Instruction::Or:
case Instruction::Xor:
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:
}
#endif
- if (Instruction::isComparison(Opcode))
- return getTy(Type::BoolTy, Opcode, C1, C2);
- else
- return getTy(C1->getType(), Opcode, C1, C2);
+ return getTy(C1->getType(), Opcode, C1, C2);
+}
+
+Constant *ConstantExpr::getCompare(unsigned Opcode, unsigned short pred,
+ Constant *C1, Constant *C2) {
+ assert(C1->getType() == C2->getType() && "Op types should be identical!");
+ return getCompareTy(Opcode, pred, C1, C2);
}
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);
}
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!");
// 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);
}
-
Constant *ConstantExpr::getGetElementPtrTy(const Type *ReqTy, Constant *C,
const std::vector<Value*> &IdxList) {
assert(GetElementPtrInst::getIndexedType(C->getType(), IdxList, true) &&
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);
}
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))
// 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);
}
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);
}
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);
}
return getShuffleVectorTy(V1->getType(), V1, V2, Mask);
}
-
// destroyConstant - Remove the constant from the constant table...
//
void ConstantExpr::destroyConstant() {
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);
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);