//
// The LLVM Compiler Infrastructure
//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Static constructor to create a '0' constant of arbitrary type...
Constant *Constant::getNullValue(const Type *Ty) {
+ static uint64_t zero[2] = {0, 0};
switch (Ty->getTypeID()) {
case Type::IntegerTyID:
return ConstantInt::get(Ty, 0);
case Type::FloatTyID:
+ return ConstantFP::get(APFloat(APInt(32, 0)));
case Type::DoubleTyID:
+ return ConstantFP::get(APFloat(APInt(64, 0)));
case Type::X86_FP80TyID:
- case Type::PPC_FP128TyID:
+ return ConstantFP::get(APFloat(APInt(80, 2, zero)));
case Type::FP128TyID:
- return ConstantFP::get(Ty, 0.0);
+ return ConstantFP::get(APFloat(APInt(128, 2, zero), true));
+ case Type::PPC_FP128TyID:
+ return ConstantFP::get(APFloat(APInt(128, 2, zero)));
case Type::PointerTyID:
return ConstantPointerNull::get(cast<PointerType>(Ty));
case Type::StructTyID:
static inline KeyTy getEmptyKey() { return KeyTy(APInt(1,0), 0); }
static inline KeyTy getTombstoneKey() { return KeyTy(APInt(1,1), 0); }
static unsigned getHashValue(const KeyTy &Key) {
- return DenseMapKeyInfo<void*>::getHashValue(Key.type) ^
+ return DenseMapInfo<void*>::getHashValue(Key.type) ^
Key.val.getHashValue();
}
- static bool isPod() { return true; }
+ static bool isEqual(const KeyTy &LHS, const KeyTy &RHS) {
+ return LHS == RHS;
+ }
+ static bool isPod() { return false; }
};
}
}
// Get a ConstantInt from an APInt. Note that the value stored in the DenseMap
-// as the key, is a DensMapAPIntKeyInfo::KeyTy which has provided the
+// as the key, is a DenseMapAPIntKeyInfo::KeyTy which has provided the
// operator== and operator!= to ensure that the DenseMap doesn't attempt to
// compare APInt's of different widths, which would violate an APInt class
// invariant which generates an assertion.
// ConstantFP
//===----------------------------------------------------------------------===//
+static const fltSemantics *TypeToFloatSemantics(const Type *Ty) {
+ if (Ty == Type::FloatTy)
+ return &APFloat::IEEEsingle;
+ if (Ty == Type::DoubleTy)
+ return &APFloat::IEEEdouble;
+ if (Ty == Type::X86_FP80Ty)
+ return &APFloat::x87DoubleExtended;
+ else if (Ty == Type::FP128Ty)
+ return &APFloat::IEEEquad;
+
+ assert(Ty == Type::PPC_FP128Ty && "Unknown FP format");
+ return &APFloat::PPCDoubleDouble;
+}
-ConstantFP::ConstantFP(const Type *Ty, double V)
- : Constant(Ty, ConstantFPVal, 0, 0) {
- Val = V;
+ConstantFP::ConstantFP(const Type *Ty, const APFloat& V)
+ : Constant(Ty, ConstantFPVal, 0, 0), Val(V) {
+ assert(&V.getSemantics() == TypeToFloatSemantics(Ty) &&
+ "FP type Mismatch");
}
bool ConstantFP::isNullValue() const {
- return DoubleToBits(Val) == 0;
+ return Val.isZero() && !Val.isNegative();
}
-bool ConstantFP::isExactlyValue(double V) const {
- return DoubleToBits(V) == DoubleToBits(Val);
+ConstantFP *ConstantFP::getNegativeZero(const Type *Ty) {
+ APFloat apf = cast <ConstantFP>(Constant::getNullValue(Ty))->getValueAPF();
+ apf.changeSign();
+ return ConstantFP::get(apf);
}
+bool ConstantFP::isExactlyValue(const APFloat& V) const {
+ return Val.bitwiseIsEqual(V);
+}
namespace {
- struct DenseMapInt64KeyInfo {
- typedef std::pair<uint64_t, const Type*> KeyTy;
- static inline KeyTy getEmptyKey() { return KeyTy(0, 0); }
- static inline KeyTy getTombstoneKey() { return KeyTy(1, 0); }
- static unsigned getHashValue(const KeyTy &Key) {
- return DenseMapKeyInfo<void*>::getHashValue(Key.second) ^ Key.first;
+ struct DenseMapAPFloatKeyInfo {
+ struct KeyTy {
+ APFloat val;
+ KeyTy(const APFloat& V) : val(V){}
+ KeyTy(const KeyTy& that) : val(that.val) {}
+ bool operator==(const KeyTy& that) const {
+ return this->val.bitwiseIsEqual(that.val);
+ }
+ bool operator!=(const KeyTy& that) const {
+ return !this->operator==(that);
+ }
+ };
+ static inline KeyTy getEmptyKey() {
+ return KeyTy(APFloat(APFloat::Bogus,1));
+ }
+ static inline KeyTy getTombstoneKey() {
+ return KeyTy(APFloat(APFloat::Bogus,2));
}
- static bool isPod() { return true; }
- };
- struct DenseMapInt32KeyInfo {
- typedef std::pair<uint32_t, const Type*> KeyTy;
- static inline KeyTy getEmptyKey() { return KeyTy(0, 0); }
- static inline KeyTy getTombstoneKey() { return KeyTy(1, 0); }
static unsigned getHashValue(const KeyTy &Key) {
- return DenseMapKeyInfo<void*>::getHashValue(Key.second) ^ Key.first;
+ return Key.val.getHashValue();
+ }
+ static bool isEqual(const KeyTy &LHS, const KeyTy &RHS) {
+ return LHS == RHS;
}
- static bool isPod() { return true; }
+ static bool isPod() { return false; }
};
}
//---- ConstantFP::get() implementation...
//
-typedef DenseMap<DenseMapInt32KeyInfo::KeyTy, ConstantFP*,
- DenseMapInt32KeyInfo> FloatMapTy;
-typedef DenseMap<DenseMapInt64KeyInfo::KeyTy, ConstantFP*,
- DenseMapInt64KeyInfo> DoubleMapTy;
+typedef DenseMap<DenseMapAPFloatKeyInfo::KeyTy, ConstantFP*,
+ DenseMapAPFloatKeyInfo> FPMapTy;
-static ManagedStatic<FloatMapTy> FloatConstants;
-static ManagedStatic<DoubleMapTy> DoubleConstants;
+static ManagedStatic<FPMapTy> FPConstants;
-ConstantFP *ConstantFP::get(const Type *Ty, double V) {
- if (Ty == Type::FloatTy) {
- uint32_t IntVal = FloatToBits((float)V);
-
- ConstantFP *&Slot = (*FloatConstants)[std::make_pair(IntVal, Ty)];
- if (Slot) return Slot;
- return Slot = new ConstantFP(Ty, (float)V);
- } else if (Ty == Type::DoubleTy) {
- uint64_t IntVal = DoubleToBits(V);
- ConstantFP *&Slot = (*DoubleConstants)[std::make_pair(IntVal, Ty)];
- if (Slot) return Slot;
- return Slot = new ConstantFP(Ty, V);
- // FIXME: Make long double constants work.
- } else if (Ty == Type::X86_FP80Ty ||
- Ty == Type::PPC_FP128Ty || Ty == Type::FP128Ty) {
- assert(0 && "Long double constants not handled yet.");
- } else {
- assert(0 && "Unknown FP Type!");
+ConstantFP *ConstantFP::get(const APFloat &V) {
+ DenseMapAPFloatKeyInfo::KeyTy Key(V);
+ ConstantFP *&Slot = (*FPConstants)[Key];
+ if (Slot) return Slot;
+
+ const Type *Ty;
+ if (&V.getSemantics() == &APFloat::IEEEsingle)
+ Ty = Type::FloatTy;
+ else if (&V.getSemantics() == &APFloat::IEEEdouble)
+ Ty = Type::DoubleTy;
+ else if (&V.getSemantics() == &APFloat::x87DoubleExtended)
+ Ty = Type::X86_FP80Ty;
+ else if (&V.getSemantics() == &APFloat::IEEEquad)
+ Ty = Type::FP128Ty;
+ else {
+ assert(&V.getSemantics() == &APFloat::PPCDoubleDouble&&"Unknown FP format");
+ Ty = Type::PPC_FP128Ty;
}
+
+ return Slot = new ConstantFP(Ty, V);
}
+/// get() - This returns a constant fp for the specified value in the
+/// specified type. This should only be used for simple constant values like
+/// 2.0/1.0 etc, that are known-valid both as double and as the target format.
+ConstantFP *ConstantFP::get(const Type *Ty, double V) {
+ APFloat FV(V);
+ FV.convert(*TypeToFloatSemantics(Ty), APFloat::rmNearestTiesToEven);
+ return get(FV);
+}
//===----------------------------------------------------------------------===//
// ConstantXXX Classes
ConstantArray::ConstantArray(const ArrayType *T,
const std::vector<Constant*> &V)
- : Constant(T, ConstantArrayVal, new Use[V.size()], V.size()) {
+ : Constant(T, ConstantArrayVal,
+ OperandTraits<ConstantArray>::op_end(this) - V.size(),
+ V.size()) {
assert(V.size() == T->getNumElements() &&
"Invalid initializer vector for constant array");
Use *OL = OperandList;
(T->isAbstract() &&
C->getType()->getTypeID() == T->getElementType()->getTypeID())) &&
"Initializer for array element doesn't match array element type!");
- OL->init(C, this);
+ *OL = C;
}
}
-ConstantArray::~ConstantArray() {
- delete [] OperandList;
-}
ConstantStruct::ConstantStruct(const StructType *T,
const std::vector<Constant*> &V)
- : Constant(T, ConstantStructVal, new Use[V.size()], V.size()) {
+ : Constant(T, ConstantStructVal,
+ OperandTraits<ConstantStruct>::op_end(this) - V.size(),
+ V.size()) {
assert(V.size() == T->getNumElements() &&
"Invalid initializer vector for constant structure");
Use *OL = OperandList;
T->getElementType(I-V.begin())->getTypeID() ==
C->getType()->getTypeID())) &&
"Initializer for struct element doesn't match struct element type!");
- OL->init(C, this);
+ *OL = C;
}
}
-ConstantStruct::~ConstantStruct() {
- delete [] OperandList;
-}
-
ConstantVector::ConstantVector(const VectorType *T,
const std::vector<Constant*> &V)
- : Constant(T, ConstantVectorVal, new Use[V.size()], V.size()) {
+ : Constant(T, ConstantVectorVal,
+ OperandTraits<ConstantVector>::op_end(this) - V.size(),
+ V.size()) {
Use *OL = OperandList;
for (std::vector<Constant*>::const_iterator I = V.begin(), E = V.end();
I != E; ++I, ++OL) {
(T->isAbstract() &&
C->getType()->getTypeID() == T->getElementType()->getTypeID())) &&
"Initializer for vector element doesn't match vector element type!");
- OL->init(C, this);
+ *OL = C;
}
}
-ConstantVector::~ConstantVector() {
- delete [] OperandList;
-}
+namespace llvm {
// 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.
class VISIBILITY_HIDDEN UnaryConstantExpr : public ConstantExpr {
- Use Op;
+ void *operator new(size_t, unsigned); // DO NOT IMPLEMENT
public:
+ // allocate space for exactly one operand
+ void *operator new(size_t s) {
+ return User::operator new(s, 1);
+ }
UnaryConstantExpr(unsigned Opcode, Constant *C, const Type *Ty)
- : ConstantExpr(Ty, Opcode, &Op, 1), Op(C, this) {}
+ : ConstantExpr(Ty, Opcode, &Op<0>(), 1) {
+ Op<0>() = C;
+ }
+ /// Transparently provide more efficient getOperand methods.
+ DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
};
/// BinaryConstantExpr - This class is private to Constants.cpp, and is used
/// behind the scenes to implement binary constant exprs.
class VISIBILITY_HIDDEN BinaryConstantExpr : public ConstantExpr {
- Use Ops[2];
+ void *operator new(size_t, unsigned); // DO NOT IMPLEMENT
public:
+ // allocate space for exactly two operands
+ void *operator new(size_t s) {
+ return User::operator new(s, 2);
+ }
BinaryConstantExpr(unsigned Opcode, Constant *C1, Constant *C2)
- : ConstantExpr(C1->getType(), Opcode, Ops, 2) {
- Ops[0].init(C1, this);
- Ops[1].init(C2, this);
+ : ConstantExpr(C1->getType(), Opcode, &Op<0>(), 2) {
+ Op<0>() = C1;
+ Op<1>() = C2;
}
+ /// Transparently provide more efficient getOperand methods.
+ DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
};
/// SelectConstantExpr - This class is private to Constants.cpp, and is used
/// behind the scenes to implement select constant exprs.
class VISIBILITY_HIDDEN SelectConstantExpr : public ConstantExpr {
- Use Ops[3];
+ void *operator new(size_t, unsigned); // DO NOT IMPLEMENT
public:
+ // allocate space for exactly three operands
+ void *operator new(size_t s) {
+ return User::operator new(s, 3);
+ }
SelectConstantExpr(Constant *C1, Constant *C2, Constant *C3)
- : ConstantExpr(C2->getType(), Instruction::Select, Ops, 3) {
- Ops[0].init(C1, this);
- Ops[1].init(C2, this);
- Ops[2].init(C3, this);
+ : ConstantExpr(C2->getType(), Instruction::Select, &Op<0>(), 3) {
+ Op<0>() = C1;
+ Op<1>() = C2;
+ Op<2>() = C3;
}
+ /// Transparently provide more efficient getOperand methods.
+ DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
};
/// ExtractElementConstantExpr - This class is private to
/// Constants.cpp, and is used behind the scenes to implement
/// extractelement constant exprs.
class VISIBILITY_HIDDEN ExtractElementConstantExpr : public ConstantExpr {
- Use Ops[2];
+ void *operator new(size_t, unsigned); // DO NOT IMPLEMENT
public:
+ // allocate space for exactly two operands
+ void *operator new(size_t s) {
+ return User::operator new(s, 2);
+ }
ExtractElementConstantExpr(Constant *C1, Constant *C2)
: ConstantExpr(cast<VectorType>(C1->getType())->getElementType(),
- Instruction::ExtractElement, Ops, 2) {
- Ops[0].init(C1, this);
- Ops[1].init(C2, this);
+ Instruction::ExtractElement, &Op<0>(), 2) {
+ Op<0>() = C1;
+ Op<1>() = C2;
}
+ /// Transparently provide more efficient getOperand methods.
+ DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
};
/// InsertElementConstantExpr - This class is private to
/// Constants.cpp, and is used behind the scenes to implement
/// insertelement constant exprs.
class VISIBILITY_HIDDEN InsertElementConstantExpr : public ConstantExpr {
- Use Ops[3];
+ void *operator new(size_t, unsigned); // DO NOT IMPLEMENT
public:
+ // allocate space for exactly three operands
+ void *operator new(size_t s) {
+ return User::operator new(s, 3);
+ }
InsertElementConstantExpr(Constant *C1, Constant *C2, Constant *C3)
: ConstantExpr(C1->getType(), Instruction::InsertElement,
- Ops, 3) {
- Ops[0].init(C1, this);
- Ops[1].init(C2, this);
- Ops[2].init(C3, this);
+ &Op<0>(), 3) {
+ Op<0>() = C1;
+ Op<1>() = C2;
+ Op<2>() = C3;
}
+ /// Transparently provide more efficient getOperand methods.
+ DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
};
/// ShuffleVectorConstantExpr - This class is private to
/// Constants.cpp, and is used behind the scenes to implement
/// shufflevector constant exprs.
class VISIBILITY_HIDDEN ShuffleVectorConstantExpr : public ConstantExpr {
- Use Ops[3];
+ void *operator new(size_t, unsigned); // DO NOT IMPLEMENT
public:
+ // allocate space for exactly three operands
+ void *operator new(size_t s) {
+ return User::operator new(s, 3);
+ }
ShuffleVectorConstantExpr(Constant *C1, Constant *C2, Constant *C3)
: ConstantExpr(C1->getType(), Instruction::ShuffleVector,
- Ops, 3) {
- Ops[0].init(C1, this);
- Ops[1].init(C2, this);
- Ops[2].init(C3, this);
+ &Op<0>(), 3) {
+ Op<0>() = C1;
+ Op<1>() = C2;
+ Op<2>() = C3;
}
+ /// Transparently provide more efficient getOperand methods.
+ DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
};
+/// ExtractValueConstantExpr - This class is private to
+/// Constants.cpp, and is used behind the scenes to implement
+/// extractvalue constant exprs.
+class VISIBILITY_HIDDEN ExtractValueConstantExpr : public ConstantExpr {
+ void *operator new(size_t, unsigned); // DO NOT IMPLEMENT
+public:
+ // allocate space for exactly one operand
+ void *operator new(size_t s) {
+ return User::operator new(s, 1);
+ }
+ ExtractValueConstantExpr(Constant *Agg,
+ const SmallVector<unsigned, 4> &IdxList,
+ const Type *DestTy)
+ : ConstantExpr(DestTy, Instruction::ExtractValue, &Op<0>(), 1),
+ Indices(IdxList) {
+ Op<0>() = Agg;
+ }
+
+ /// Indices - These identify which value to extract.
+ const SmallVector<unsigned, 4> Indices;
+
+ /// Transparently provide more efficient getOperand methods.
+ DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
+};
+
+/// InsertValueConstantExpr - This class is private to
+/// Constants.cpp, and is used behind the scenes to implement
+/// insertvalue constant exprs.
+class VISIBILITY_HIDDEN InsertValueConstantExpr : public ConstantExpr {
+ void *operator new(size_t, unsigned); // DO NOT IMPLEMENT
+public:
+ // allocate space for exactly one operand
+ void *operator new(size_t s) {
+ return User::operator new(s, 2);
+ }
+ InsertValueConstantExpr(Constant *Agg, Constant *Val,
+ const SmallVector<unsigned, 4> &IdxList,
+ const Type *DestTy)
+ : ConstantExpr(DestTy, Instruction::InsertValue, &Op<0>(), 2),
+ Indices(IdxList) {
+ Op<0>() = Agg;
+ Op<1>() = Val;
+ }
+
+ /// Indices - These identify the position for the insertion.
+ const SmallVector<unsigned, 4> Indices;
+
+ /// Transparently provide more efficient getOperand methods.
+ DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
+};
+
+
/// GetElementPtrConstantExpr - This class is private to Constants.cpp, and is
/// used behind the scenes to implement getelementpr constant exprs.
-struct VISIBILITY_HIDDEN GetElementPtrConstantExpr : public ConstantExpr {
+class VISIBILITY_HIDDEN GetElementPtrConstantExpr : public ConstantExpr {
GetElementPtrConstantExpr(Constant *C, const std::vector<Constant*> &IdxList,
- const Type *DestTy)
- : ConstantExpr(DestTy, Instruction::GetElementPtr,
- new Use[IdxList.size()+1], IdxList.size()+1) {
- OperandList[0].init(C, this);
- for (unsigned i = 0, E = IdxList.size(); i != E; ++i)
- OperandList[i+1].init(IdxList[i], this);
- }
- ~GetElementPtrConstantExpr() {
- delete [] OperandList;
+ const Type *DestTy);
+public:
+ static GetElementPtrConstantExpr *Create(Constant *C,
+ const std::vector<Constant*>&IdxList,
+ const Type *DestTy) {
+ return new(IdxList.size() + 1)
+ GetElementPtrConstantExpr(C, IdxList, DestTy);
}
+ /// Transparently provide more efficient getOperand methods.
+ DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
};
// 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 {
+ void *operator new(size_t, unsigned); // DO NOT IMPLEMENT
+ // allocate space for exactly two operands
+ void *operator new(size_t s) {
+ return User::operator new(s, 2);
+ }
unsigned short predicate;
- Use Ops[2];
- CompareConstantExpr(Instruction::OtherOps opc, unsigned short pred,
- Constant* LHS, Constant* RHS)
- : ConstantExpr(Type::Int1Ty, opc, Ops, 2), predicate(pred) {
- OperandList[0].init(LHS, this);
- OperandList[1].init(RHS, this);
+ CompareConstantExpr(const Type *ty, Instruction::OtherOps opc,
+ unsigned short pred, Constant* LHS, Constant* RHS)
+ : ConstantExpr(ty, opc, &Op<0>(), 2), predicate(pred) {
+ Op<0>() = LHS;
+ Op<1>() = RHS;
}
+ /// Transparently provide more efficient getOperand methods.
+ DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
};
} // end anonymous namespace
+template <>
+struct OperandTraits<UnaryConstantExpr> : FixedNumOperandTraits<1> {
+};
+DEFINE_TRANSPARENT_OPERAND_ACCESSORS(UnaryConstantExpr, Value)
+
+template <>
+struct OperandTraits<BinaryConstantExpr> : FixedNumOperandTraits<2> {
+};
+DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BinaryConstantExpr, Value)
+
+template <>
+struct OperandTraits<SelectConstantExpr> : FixedNumOperandTraits<3> {
+};
+DEFINE_TRANSPARENT_OPERAND_ACCESSORS(SelectConstantExpr, Value)
+
+template <>
+struct OperandTraits<ExtractElementConstantExpr> : FixedNumOperandTraits<2> {
+};
+DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ExtractElementConstantExpr, Value)
+
+template <>
+struct OperandTraits<InsertElementConstantExpr> : FixedNumOperandTraits<3> {
+};
+DEFINE_TRANSPARENT_OPERAND_ACCESSORS(InsertElementConstantExpr, Value)
+
+template <>
+struct OperandTraits<ShuffleVectorConstantExpr> : FixedNumOperandTraits<3> {
+};
+DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ShuffleVectorConstantExpr, Value)
+
+template <>
+struct OperandTraits<ExtractValueConstantExpr> : FixedNumOperandTraits<1> {
+};
+DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ExtractValueConstantExpr, Value)
+
+template <>
+struct OperandTraits<InsertValueConstantExpr> : FixedNumOperandTraits<2> {
+};
+DEFINE_TRANSPARENT_OPERAND_ACCESSORS(InsertValueConstantExpr, Value)
+
+template <>
+struct OperandTraits<GetElementPtrConstantExpr> : VariadicOperandTraits<1> {
+};
+
+GetElementPtrConstantExpr::GetElementPtrConstantExpr
+ (Constant *C,
+ const std::vector<Constant*> &IdxList,
+ const Type *DestTy)
+ : ConstantExpr(DestTy, Instruction::GetElementPtr,
+ OperandTraits<GetElementPtrConstantExpr>::op_end(this)
+ - (IdxList.size()+1),
+ IdxList.size()+1) {
+ OperandList[0] = C;
+ for (unsigned i = 0, E = IdxList.size(); i != E; ++i)
+ OperandList[i+1] = IdxList[i];
+}
+
+DEFINE_TRANSPARENT_OPERAND_ACCESSORS(GetElementPtrConstantExpr, Value)
+
+
+template <>
+struct OperandTraits<CompareConstantExpr> : FixedNumOperandTraits<2> {
+};
+DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CompareConstantExpr, Value)
+
+
+} // End llvm namespace
+
// Utility function for determining if a ConstantExpr is a CastOp or not. This
// can't be inline because we don't want to #include Instruction.h into
return getOpcode() == Instruction::ICmp || getOpcode() == Instruction::FCmp;
}
+bool ConstantExpr::hasIndices() const {
+ return getOpcode() == Instruction::ExtractValue ||
+ getOpcode() == Instruction::InsertValue;
+}
+
+const SmallVector<unsigned, 4> &ConstantExpr::getIndices() const {
+ if (const ExtractValueConstantExpr *EVCE =
+ dyn_cast<ExtractValueConstantExpr>(this))
+ return EVCE->Indices;
+ if (const InsertValueConstantExpr *IVCE =
+ dyn_cast<InsertValueConstantExpr>(this))
+ return IVCE->Indices;
+ assert(0 && "ConstantExpr does not have indices!");
+}
+
/// ConstantExpr::get* - Return some common constants without having to
/// specify the full Instruction::OPCODE identifier.
///
C);
}
Constant *ConstantExpr::getNot(Constant *C) {
- assert(isa<ConstantInt>(C) && "Cannot NOT a nonintegral type!");
+ assert(isa<IntegerType>(C->getType()) && "Cannot NOT a nonintegral value!");
return get(Instruction::Xor, C,
ConstantInt::getAllOnesValue(C->getType()));
}
return get(Instruction::Xor, C1, C2);
}
unsigned ConstantExpr::getPredicate() const {
- assert(getOpcode() == Instruction::FCmp || getOpcode() == Instruction::ICmp);
- return dynamic_cast<const CompareConstantExpr*>(this)->predicate;
+ assert(getOpcode() == Instruction::FCmp ||
+ getOpcode() == Instruction::ICmp ||
+ getOpcode() == Instruction::VFCmp ||
+ getOpcode() == Instruction::VICmp);
+ return ((const CompareConstantExpr*)this)->predicate;
}
Constant *ConstantExpr::getShl(Constant *C1, Constant *C2) {
return get(Instruction::Shl, C1, C2);
Op1 = (OpNo == 1) ? Op : getOperand(1);
Op2 = (OpNo == 2) ? Op : getOperand(2);
return ConstantExpr::getShuffleVector(Op0, Op1, Op2);
+ case Instruction::InsertValue: {
+ const SmallVector<unsigned, 4> Indices = getIndices();
+ Op0 = (OpNo == 0) ? Op : getOperand(0);
+ Op1 = (OpNo == 1) ? Op : getOperand(1);
+ return ConstantExpr::getInsertValue(Op0, Op1,
+ &Indices[0], Indices.size());
+ }
+ case Instruction::ExtractValue: {
+ assert(OpNo == 0 && "ExtractaValue has only one operand!");
+ const SmallVector<unsigned, 4> Indices = getIndices();
+ return
+ ConstantExpr::getExtractValue(Op, &Indices[0], Indices.size());
+ }
case Instruction::GetElementPtr: {
SmallVector<Constant*, 8> Ops;
- Ops.resize(getNumOperands());
+ Ops.resize(getNumOperands()-1);
for (unsigned i = 1, e = getNumOperands(); i != e; ++i)
- Ops[i] = getOperand(i);
+ Ops[i-1] = getOperand(i);
if (OpNo == 0)
return ConstantExpr::getGetElementPtr(Op, &Ops[0], Ops.size());
Ops[OpNo-1] = Op;
return ConstantExpr::getExtractElement(Ops[0], Ops[1]);
case Instruction::ShuffleVector:
return ConstantExpr::getShuffleVector(Ops[0], Ops[1], Ops[2]);
+ case Instruction::InsertValue: {
+ const SmallVector<unsigned, 4> Indices = getIndices();
+ return ConstantExpr::getInsertValue(Ops[0], Ops[1],
+ &Indices[0], Indices.size());
+ }
+ case Instruction::ExtractValue: {
+ const SmallVector<unsigned, 4> Indices = getIndices();
+ return ConstantExpr::getExtractValue(Ops[0],
+ &Indices[0], Indices.size());
+ }
case Instruction::GetElementPtr:
return ConstantExpr::getGetElementPtr(Ops[0], &Ops[1], Ops.size()-1);
case Instruction::ICmp:
return (Val >= Min && Val <= Max);
}
-bool ConstantFP::isValueValidForType(const Type *Ty, double Val) {
+bool ConstantFP::isValueValidForType(const Type *Ty, const APFloat& Val) {
+ // convert modifies in place, so make a copy.
+ APFloat Val2 = APFloat(Val);
switch (Ty->getTypeID()) {
default:
return false; // These can't be represented as floating point!
- // TODO: Figure out how to test if we can use a shorter type instead!
+ // FIXME rounding mode needs to be more flexible
case Type::FloatTyID:
+ return &Val2.getSemantics() == &APFloat::IEEEsingle ||
+ Val2.convert(APFloat::IEEEsingle, APFloat::rmNearestTiesToEven) ==
+ APFloat::opOK;
case Type::DoubleTyID:
+ return &Val2.getSemantics() == &APFloat::IEEEsingle ||
+ &Val2.getSemantics() == &APFloat::IEEEdouble ||
+ Val2.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven) ==
+ APFloat::opOK;
case Type::X86_FP80TyID:
- case Type::PPC_FP128TyID:
+ return &Val2.getSemantics() == &APFloat::IEEEsingle ||
+ &Val2.getSemantics() == &APFloat::IEEEdouble ||
+ &Val2.getSemantics() == &APFloat::x87DoubleExtended;
case Type::FP128TyID:
- return true;
+ return &Val2.getSemantics() == &APFloat::IEEEsingle ||
+ &Val2.getSemantics() == &APFloat::IEEEdouble ||
+ &Val2.getSemantics() == &APFloat::IEEEquad;
+ case Type::PPC_FP128TyID:
+ return &Val2.getSemantics() == &APFloat::IEEEsingle ||
+ &Val2.getSemantics() == &APFloat::IEEEdouble ||
+ &Val2.getSemantics() == &APFloat::PPCDoubleDouble;
}
}
//===----------------------------------------------------------------------===//
// Factory Function Implementation
+
+// The number of operands for each ConstantCreator::create method is
+// determined by the ConstantTraits template.
// ConstantCreator - A class that is used to create constants by
// ValueMap*. This class should be partially specialized if there is
// something strange that needs to be done to interface to the ctor for the
// constant.
//
namespace llvm {
+ template<class ValType>
+ struct ConstantTraits;
+
+ template<typename T, typename Alloc>
+ struct VISIBILITY_HIDDEN ConstantTraits< std::vector<T, Alloc> > {
+ static unsigned uses(const std::vector<T, Alloc>& v) {
+ return v.size();
+ }
+ };
+
template<class ConstantClass, class TypeClass, class ValType>
struct VISIBILITY_HIDDEN ConstantCreator {
static ConstantClass *create(const TypeClass *Ty, const ValType &V) {
- return new ConstantClass(Ty, V);
+ return new(ConstantTraits<ValType>::uses(V)) ConstantClass(Ty, V);
}
};
return true;
}
+/// getSplatValue - If this is a splat constant, where all of the
+/// elements have the same value, return that value. Otherwise return null.
+Constant *ConstantVector::getSplatValue() {
+ // Check out first element.
+ Constant *Elt = getOperand(0);
+ // Then make sure all remaining elements point to the same value.
+ for (unsigned I = 1, E = getNumOperands(); I < E; ++I)
+ if (getOperand(I) != Elt) return 0;
+ return Elt;
+}
+
//---- ConstantPointerNull::get() implementation...
//
//---- ConstantExpr::get() implementations...
//
+namespace {
+
struct ExprMapKeyType {
- explicit ExprMapKeyType(unsigned opc, std::vector<Constant*> ops,
- unsigned short pred = 0) : opcode(opc), predicate(pred), operands(ops) { }
+ typedef SmallVector<unsigned, 4> IndexList;
+
+ ExprMapKeyType(unsigned opc,
+ const std::vector<Constant*> &ops,
+ unsigned short pred = 0,
+ const IndexList &inds = IndexList())
+ : opcode(opc), predicate(pred), operands(ops), indices(inds) {}
uint16_t opcode;
uint16_t predicate;
std::vector<Constant*> operands;
+ IndexList indices;
bool operator==(const ExprMapKeyType& that) const {
return this->opcode == that.opcode &&
this->predicate == that.predicate &&
this->operands == that.operands;
+ this->indices == that.indices;
}
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);
+ this->operands < that.operands) ||
+ (this->opcode == that.opcode && this->predicate == that.predicate &&
+ this->operands == that.operands && this->indices < that.indices);
}
bool operator!=(const ExprMapKeyType& that) const {
}
};
+}
+
namespace llvm {
template<>
struct ConstantCreator<ConstantExpr, Type, ExprMapKeyType> {
if (V.opcode == Instruction::ShuffleVector)
return new ShuffleVectorConstantExpr(V.operands[0], V.operands[1],
V.operands[2]);
+ if (V.opcode == Instruction::InsertValue)
+ return new InsertValueConstantExpr(V.operands[0], V.operands[1],
+ V.indices, Ty);
+ if (V.opcode == Instruction::ExtractValue)
+ return new ExtractValueConstantExpr(V.operands[0], V.indices, Ty);
if (V.opcode == Instruction::GetElementPtr) {
std::vector<Constant*> IdxList(V.operands.begin()+1, V.operands.end());
- return new GetElementPtrConstantExpr(V.operands[0], IdxList, Ty);
+ return GetElementPtrConstantExpr::Create(V.operands[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,
+ return new CompareConstantExpr(Ty, Instruction::ICmp, V.predicate,
V.operands[0], V.operands[1]);
if (V.opcode == Instruction::FCmp)
- return new CompareConstantExpr(Instruction::FCmp, V.predicate,
+ return new CompareConstantExpr(Ty, Instruction::FCmp, V.predicate,
+ V.operands[0], V.operands[1]);
+ if (V.opcode == Instruction::VICmp)
+ return new CompareConstantExpr(Ty, Instruction::VICmp, V.predicate,
+ V.operands[0], V.operands[1]);
+ if (V.opcode == Instruction::VFCmp)
+ return new CompareConstantExpr(Ty, Instruction::VFCmp, V.predicate,
V.operands[0], V.operands[1]);
assert(0 && "Invalid ConstantExpr!");
return 0;
for (unsigned i = 0, e = CE->getNumOperands(); i != e; ++i)
Operands.push_back(cast<Constant>(CE->getOperand(i)));
return ExprMapKeyType(CE->getOpcode(), Operands,
- CE->isCompare() ? CE->getPredicate() : 0);
+ CE->isCompare() ? CE->getPredicate() : 0,
+ CE->hasIndices() ?
+ CE->getIndices() : SmallVector<unsigned, 4>());
}
static ManagedStatic<ValueMap<ExprMapKeyType, Type,
ConstantExpr> > ExprConstants;
/// 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.
+/// cast in the ExprConstants map. It is used by 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!");
}
Constant *ConstantExpr::getUIToFP(Constant *C, const Type *Ty) {
- assert(C->getType()->isInteger() && Ty->isFloatingPoint() &&
- "This is an illegal i32 to floating point cast!");
+ bool fromVec = C->getType()->getTypeID() == Type::VectorTyID;
+ bool toVec = Ty->getTypeID() == Type::VectorTyID;
+ assert((fromVec == toVec) && "Cannot convert from scalar to/from vector");
+ assert(C->getType()->isIntOrIntVector() && Ty->isFPOrFPVector() &&
+ "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()->isInteger() && Ty->isFloatingPoint() &&
+ bool fromVec = C->getType()->getTypeID() == Type::VectorTyID;
+ bool toVec = Ty->getTypeID() == Type::VectorTyID;
+ assert((fromVec == toVec) && "Cannot convert from scalar to/from vector");
+ assert(C->getType()->isIntOrIntVector() && Ty->isFPOrFPVector() &&
"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->isInteger() &&
- "This is an illegal floating point to i32 cast!");
+ bool fromVec = C->getType()->getTypeID() == Type::VectorTyID;
+ bool toVec = Ty->getTypeID() == Type::VectorTyID;
+ assert((fromVec == toVec) && "Cannot convert from scalar to/from vector");
+ assert(C->getType()->isFPOrFPVector() && Ty->isIntOrIntVector() &&
+ "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->isInteger() &&
- "This is an illegal floating point to i32 cast!");
+ bool fromVec = C->getType()->getTypeID() == Type::VectorTyID;
+ bool toVec = Ty->getTypeID() == Type::VectorTyID;
+ assert((fromVec == toVec) && "Cannot convert from scalar to/from vector");
+ assert(C->getType()->isFPOrFPVector() && Ty->isIntOrIntVector() &&
+ "This is an illegal floating point to sint cast!");
return getFoldedCast(Instruction::FPToSI, C, Ty);
}
}
Constant *ConstantExpr::getSizeOf(const Type *Ty) {
- // sizeof is implemented as: (ulong) gep (Ty*)null, 1
+ // sizeof is implemented as: (i64) gep (Ty*)null, 1
Constant *GEPIdx = ConstantInt::get(Type::Int32Ty, 1);
Constant *GEP =
- getGetElementPtr(getNullValue(PointerType::get(Ty)), &GEPIdx, 1);
+ getGetElementPtr(getNullValue(PointerType::getUnqual(Ty)), &GEPIdx, 1);
return getCast(Instruction::PtrToInt, GEP, Type::Int64Ty);
}
Constant *ConstantExpr::getGetElementPtrTy(const Type *ReqTy, Constant *C,
Value* const *Idxs,
unsigned NumIdx) {
- assert(GetElementPtrInst::getIndexedType(C->getType(), Idxs, NumIdx, true) &&
+ assert(GetElementPtrInst::getIndexedType(C->getType(), Idxs,
+ Idxs+NumIdx) ==
+ cast<PointerType>(ReqTy)->getElementType() &&
"GEP indices invalid!");
if (Constant *FC = ConstantFoldGetElementPtr(C, (Constant**)Idxs, NumIdx))
unsigned NumIdx) {
// Get the result type of the getelementptr!
const Type *Ty =
- GetElementPtrInst::getIndexedType(C->getType(), Idxs, NumIdx, true);
+ GetElementPtrInst::getIndexedType(C->getType(), Idxs, Idxs+NumIdx);
assert(Ty && "GEP indices invalid!");
- return getGetElementPtrTy(PointerType::get(Ty), C, Idxs, NumIdx);
+ unsigned As = cast<PointerType>(C->getType())->getAddressSpace();
+ return getGetElementPtrTy(PointerType::get(Ty, As), C, Idxs, NumIdx);
}
Constant *ConstantExpr::getGetElementPtr(Constant *C, Constant* const *Idxs,
return ExprConstants->getOrCreate(Type::Int1Ty, Key);
}
+Constant *
+ConstantExpr::getVICmp(unsigned short pred, Constant* LHS, Constant* RHS) {
+ assert(isa<VectorType>(LHS->getType()) &&
+ "Tried to create vicmp operation on non-vector type!");
+ assert(LHS->getType() == RHS->getType());
+ assert(pred >= ICmpInst::FIRST_ICMP_PREDICATE &&
+ pred <= ICmpInst::LAST_ICMP_PREDICATE && "Invalid VICmp Predicate");
+
+ const VectorType *VTy = cast<VectorType>(LHS->getType());
+ const Type *EltTy = VTy->getElementType();
+ unsigned NumElts = VTy->getNumElements();
+
+ SmallVector<Constant *, 8> Elts;
+ for (unsigned i = 0; i != NumElts; ++i) {
+ Constant *FC = ConstantFoldCompareInstruction(pred, LHS->getOperand(i),
+ RHS->getOperand(i));
+ if (FC) {
+ uint64_t Val = cast<ConstantInt>(FC)->getZExtValue();
+ if (Val != 0ULL)
+ Elts.push_back(ConstantInt::getAllOnesValue(EltTy));
+ else
+ Elts.push_back(ConstantInt::get(EltTy, 0ULL));
+ }
+ }
+ if (Elts.size() == NumElts)
+ return ConstantVector::get(&Elts[0], Elts.size());
+
+ // Look up the constant in the table first to ensure uniqueness
+ std::vector<Constant*> ArgVec;
+ ArgVec.push_back(LHS);
+ ArgVec.push_back(RHS);
+ // Get the key type with both the opcode and predicate
+ const ExprMapKeyType Key(Instruction::VICmp, ArgVec, pred);
+ return ExprConstants->getOrCreate(LHS->getType(), Key);
+}
+
+Constant *
+ConstantExpr::getVFCmp(unsigned short pred, Constant* LHS, Constant* RHS) {
+ assert(isa<VectorType>(LHS->getType()) &&
+ "Tried to create vfcmp operation on non-vector type!");
+ assert(LHS->getType() == RHS->getType());
+ assert(pred <= FCmpInst::LAST_FCMP_PREDICATE && "Invalid VFCmp Predicate");
+
+ const VectorType *VTy = cast<VectorType>(LHS->getType());
+ unsigned NumElts = VTy->getNumElements();
+ const Type *EltTy = VTy->getElementType();
+ const Type *REltTy = IntegerType::get(EltTy->getPrimitiveSizeInBits());
+ const Type *ResultTy = VectorType::get(REltTy, NumElts);
+
+ SmallVector<Constant *, 8> Elts;
+ for (unsigned i = 0; i != NumElts; ++i) {
+ Constant *FC = ConstantFoldCompareInstruction(pred, LHS->getOperand(i),
+ RHS->getOperand(i));
+ if (FC) {
+ uint64_t Val = cast<ConstantInt>(FC)->getZExtValue();
+ if (Val != 0ULL)
+ Elts.push_back(ConstantInt::getAllOnesValue(REltTy));
+ else
+ Elts.push_back(ConstantInt::get(REltTy, 0ULL));
+ }
+ }
+ if (Elts.size() == NumElts)
+ return ConstantVector::get(&Elts[0], Elts.size());
+
+ // Look up the constant in the table first to ensure uniqueness
+ std::vector<Constant*> ArgVec;
+ ArgVec.push_back(LHS);
+ ArgVec.push_back(RHS);
+ // Get the key type with both the opcode and predicate
+ const ExprMapKeyType Key(Instruction::VFCmp, ArgVec, pred);
+ return ExprConstants->getOrCreate(ResultTy, Key);
+}
+
Constant *ConstantExpr::getExtractElementTy(const Type *ReqTy, Constant *Val,
Constant *Idx) {
if (Constant *FC = ConstantFoldExtractElementInstruction(Val, Idx))
return getShuffleVectorTy(V1->getType(), V1, V2, Mask);
}
+Constant *ConstantExpr::getInsertValueTy(const Type *ReqTy, Constant *Agg,
+ Constant *Val,
+ const unsigned *Idxs, unsigned NumIdx) {
+ assert(ExtractValueInst::getIndexedType(Agg->getType(), Idxs,
+ Idxs+NumIdx) == Val->getType() &&
+ "insertvalue indices invalid!");
+ assert(Agg->getType() == ReqTy &&
+ "insertvalue type invalid!");
+ assert(Agg->getType()->isFirstClassType() &&
+ "Non-first-class type for constant InsertValue expression");
+ if (Constant *FC = ConstantFoldInsertValueInstruction(Agg, Val, Idxs, NumIdx))
+ 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(Agg);
+ ArgVec.push_back(Val);
+ SmallVector<unsigned, 4> Indices(Idxs, Idxs + NumIdx);
+ const ExprMapKeyType Key(Instruction::InsertValue, ArgVec, 0, Indices);
+ return ExprConstants->getOrCreate(ReqTy, Key);
+}
+
+Constant *ConstantExpr::getInsertValue(Constant *Agg, Constant *Val,
+ const unsigned *IdxList, unsigned NumIdx) {
+ assert(Agg->getType()->isFirstClassType() &&
+ "Tried to create insertelement operation on non-first-class type!");
+
+ const Type *ReqTy = Agg->getType();
+ const Type *ValTy =
+ ExtractValueInst::getIndexedType(Agg->getType(), IdxList, IdxList+NumIdx);
+ assert(ValTy == Val->getType() && "insertvalue indices invalid!");
+ return getInsertValueTy(ReqTy, Agg, Val, IdxList, NumIdx);
+}
+
+Constant *ConstantExpr::getExtractValueTy(const Type *ReqTy, Constant *Agg,
+ const unsigned *Idxs, unsigned NumIdx) {
+ assert(ExtractValueInst::getIndexedType(Agg->getType(), Idxs,
+ Idxs+NumIdx) == ReqTy &&
+ "extractvalue indices invalid!");
+ assert(Agg->getType()->isFirstClassType() &&
+ "Non-first-class type for constant extractvalue expression");
+ if (Constant *FC = ConstantFoldExtractValueInstruction(Agg, Idxs, NumIdx))
+ 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(Agg);
+ SmallVector<unsigned, 4> Indices(Idxs, Idxs + NumIdx);
+ const ExprMapKeyType Key(Instruction::ExtractValue, ArgVec, 0, Indices);
+ return ExprConstants->getOrCreate(ReqTy, Key);
+}
+
+Constant *ConstantExpr::getExtractValue(Constant *Agg,
+ const unsigned *IdxList, unsigned NumIdx) {
+ assert(Agg->getType()->isFirstClassType() &&
+ "Tried to create extractelement operation on non-first-class type!");
+
+ const Type *ReqTy =
+ ExtractValueInst::getIndexedType(Agg->getType(), IdxList, IdxList+NumIdx);
+ assert(ReqTy && "extractvalue indices invalid!");
+ return getExtractValueTy(ReqTy, Agg, IdxList, NumIdx);
+}
+
Constant *ConstantExpr::getZeroValueForNegationExpr(const Type *Ty) {
if (const VectorType *PTy = dyn_cast<VectorType>(Ty))
if (PTy->getElementType()->isFloatingPoint()) {
std::vector<Constant*> zeros(PTy->getNumElements(),
- ConstantFP::get(PTy->getElementType(),-0.0));
+ ConstantFP::getNegativeZero(PTy->getElementType()));
return ConstantVector::get(PTy, zeros);
}
- if (Ty->isFloatingPoint())
- return ConstantFP::get(Ty, -0.0);
+ if (Ty->isFloatingPoint())
+ return ConstantFP::getNegativeZero(Ty);
return Constant::getNullValue(Ty);
}
//===----------------------------------------------------------------------===//
// replaceUsesOfWithOnConstant implementations
+/// replaceUsesOfWithOnConstant - Update this constant array to change uses of
+/// 'From' to be uses of 'To'. This must update the uniquing data structures
+/// etc.
+///
+/// Note that we intentionally replace all uses of From with To here. Consider
+/// a large array that uses 'From' 1000 times. By handling this case all here,
+/// ConstantArray::replaceUsesOfWithOnConstant is only invoked once, and that
+/// single invocation handles all 1000 uses. Handling them one at a time would
+/// work, but would be really slow because it would have to unique each updated
+/// array instance.
void ConstantArray::replaceUsesOfWithOnConstant(Value *From, Value *To,
Use *U) {
assert(isa<Constant>(To) && "Cannot make Constant refer to non-constant!");
Constant *ToC = cast<Constant>(To);
- unsigned OperandToUpdate = U-OperandList;
- assert(getOperand(OperandToUpdate) == From && "ReplaceAllUsesWith broken!");
-
std::pair<ArrayConstantsTy::MapKey, Constant*> Lookup;
Lookup.first.first = getType();
Lookup.second = this;
// Fill values with the modified operands of the constant array. Also,
// compute whether this turns into an all-zeros array.
bool isAllZeros = false;
+ unsigned NumUpdated = 0;
if (!ToC->isNullValue()) {
- for (Use *O = OperandList, *E = OperandList+getNumOperands(); O != E; ++O)
- Values.push_back(cast<Constant>(O->get()));
+ for (Use *O = OperandList, *E = OperandList+getNumOperands(); O != E; ++O) {
+ Constant *Val = cast<Constant>(O->get());
+ if (Val == From) {
+ Val = ToC;
+ ++NumUpdated;
+ }
+ Values.push_back(Val);
+ }
} else {
isAllZeros = true;
for (Use *O = OperandList, *E = OperandList+getNumOperands(); O != E; ++O) {
Constant *Val = cast<Constant>(O->get());
+ if (Val == From) {
+ Val = ToC;
+ ++NumUpdated;
+ }
Values.push_back(Val);
if (isAllZeros) isAllZeros = Val->isNullValue();
}
}
- Values[OperandToUpdate] = ToC;
Constant *Replacement = 0;
if (isAllZeros) {
// in place!
ArrayConstants->MoveConstantToNewSlot(this, I);
- // Update to the new value.
- setOperand(OperandToUpdate, ToC);
+ // Update to the new value. Optimize for the case when we have a single
+ // operand that we're changing, but handle bulk updates efficiently.
+ if (NumUpdated == 1) {
+ unsigned OperandToUpdate = U-OperandList;
+ assert(getOperand(OperandToUpdate) == From &&
+ "ReplaceAllUsesWith broken!");
+ setOperand(OperandToUpdate, ToC);
+ } else {
+ for (unsigned i = 0, e = getNumOperands(); i != e; ++i)
+ if (getOperand(i) == From)
+ setOperand(i, ToC);
+ }
return;
}
}
}
Replacement = ConstantExpr::getGetElementPtr(Pointer,
&Indices[0], Indices.size());
+ } else if (getOpcode() == Instruction::ExtractValue) {
+ Constant *Agg = getOperand(0);
+ if (Agg == From) Agg = To;
+
+ const SmallVector<unsigned, 4> &Indices = getIndices();
+ Replacement = ConstantExpr::getExtractValue(Agg,
+ &Indices[0], Indices.size());
+ } else if (getOpcode() == Instruction::InsertValue) {
+ Constant *Agg = getOperand(0);
+ Constant *Val = getOperand(1);
+ if (Agg == From) Agg = To;
+ if (Val == From) Val = To;
+
+ const SmallVector<unsigned, 4> &Indices = getIndices();
+ Replacement = ConstantExpr::getInsertValue(Agg, Val,
+ &Indices[0], Indices.size());
} else if (isCast()) {
assert(getOperand(0) == From && "Cast only has one use!");
Replacement = ConstantExpr::getCast(getOpcode(), To, getType());
}
}
}
- } else if (Constant *C = dyn_cast<Constant>(this)) {
- if (GlobalValue *GV = dyn_cast<GlobalValue>(C))
- return GV->getStringValue(Chop, Offset);
- else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) {
- if (CE->getOpcode() == Instruction::GetElementPtr) {
- // Turn a gep into the specified offset.
- if (CE->getNumOperands() == 3 &&
- cast<Constant>(CE->getOperand(1))->isNullValue() &&
- isa<ConstantInt>(CE->getOperand(2))) {
- Offset += cast<ConstantInt>(CE->getOperand(2))->getZExtValue();
- return CE->getOperand(0)->getStringValue(Chop, Offset);
- }
+ } else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(this)) {
+ if (CE->getOpcode() == Instruction::GetElementPtr) {
+ // Turn a gep into the specified offset.
+ if (CE->getNumOperands() == 3 &&
+ cast<Constant>(CE->getOperand(1))->isNullValue() &&
+ isa<ConstantInt>(CE->getOperand(2))) {
+ Offset += cast<ConstantInt>(CE->getOperand(2))->getZExtValue();
+ return CE->getOperand(0)->getStringValue(Chop, Offset);
}
}
}