summaryrefslogtreecommitdiffstats
path: root/llvm/lib/IR/Constants.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/IR/Constants.cpp')
-rw-r--r--llvm/lib/IR/Constants.cpp97
1 files changed, 88 insertions, 9 deletions
diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp
index cbce8bd73610..87f2952ed5d2 100644
--- a/llvm/lib/IR/Constants.cpp
+++ b/llvm/lib/IR/Constants.cpp
@@ -72,17 +72,35 @@ bool Constant::isNegativeZeroValue() const {
}
// Return true iff this constant is positive zero (floating point), negative
-// zero (floating point), or a null value.
+// zero (floating point), zero-value pointer, or a null value.
bool Constant::isZeroValue() const {
+ // We can no longer safely say that a ConstantPointerNull is a zero value.
+ if (isa<ConstantPointerNull>(this))
+ return false;
+
// Floating point values have an explicit -0.0 value.
if (const ConstantFP *CFP = dyn_cast<ConstantFP>(this))
return CFP->isZero();
+ // Zero value pointer is a constant expression of inttoptr(0).
+ if (const auto *CE = dyn_cast<ConstantExpr>(this)) {
+ if (CE->getOpcode() == Instruction::IntToPtr) {
+ Constant *SrcCI = cast<Constant>(CE->getOperand(0));
+ // We don't need to check the bitwise value since it is zext or truncate
+ // for inttoptr(0) so it doesn't matter.
+ if (SrcCI->isZeroValue())
+ return true;
+ }
+ }
+
// Check for constant splat vectors of 1 values.
if (getType()->isVectorTy())
if (const auto *SplatCFP = dyn_cast_or_null<ConstantFP>(getSplatValue()))
return SplatCFP->isZero();
+ if (isa<ConstantAggregateZero>(this))
+ return true;
+
// Otherwise, just use +0.0.
return isNullValue();
}
@@ -100,8 +118,14 @@ bool Constant::isNullValue() const {
// constant zero is zero for aggregates, cpnull is null for pointers, none for
// tokens.
- return isa<ConstantAggregateZero>(this) || isa<ConstantPointerNull>(this) ||
- isa<ConstantTokenNone>(this) || isa<ConstantTargetNone>(this);
+ if (isa<ConstantPointerNull>(this) || isa<ConstantTokenNone>(this) ||
+ isa<ConstantTargetNone>(this))
+ return true;
+
+ if (auto *CA = dyn_cast<ConstantAggregate>(this))
+ return CA->isNullValue();
+
+ return false;
}
bool Constant::isAllOnesValue() const {
@@ -369,7 +393,10 @@ bool Constant::containsConstantExpression() const {
return false;
}
-/// Constructor to create a '0' constant of arbitrary type.
+/// Constructor that creates a null constant of any type. For most types, this
+/// means a constant with value '0', but for pointer types, it represents a
+/// nullptr constant. A nullptr isn't always a zero-value pointer in certain
+/// address spaces on some targets.
Constant *Constant::getNullValue(Type *Ty) {
switch (Ty->getTypeID()) {
case Type::IntegerTyID:
@@ -386,10 +413,12 @@ Constant *Constant::getNullValue(Type *Ty) {
case Type::PointerTyID:
return ConstantPointerNull::get(cast<PointerType>(Ty));
case Type::StructTyID:
+ return ConstantStruct::getNullValue(cast<StructType>(Ty));
case Type::ArrayTyID:
+ return ConstantArray::getNullValue(cast<ArrayType>(Ty));
case Type::FixedVectorTyID:
case Type::ScalableVectorTyID:
- return ConstantAggregateZero::get(Ty);
+ return ConstantVector::getNullValue(cast<VectorType>(Ty));
case Type::TokenTyID:
return ConstantTokenNone::get(Ty->getContext());
case Type::TargetExtTyID:
@@ -400,6 +429,24 @@ Constant *Constant::getNullValue(Type *Ty) {
}
}
+/// Constructor that creates a zero constant of any type. For most types, this
+/// is equivalent to getNullValue. For pointer types, it creates an inttoptr
+/// constant expression.
+Constant *Constant::getZeroValue(Type *Ty) {
+ switch (Ty->getTypeID()) {
+ case Type::PointerTyID:
+ return ConstantExpr::getIntToPtr(
+ ConstantInt::get(Type::getInt8Ty(Ty->getContext()), 0), Ty);
+ case Type::StructTyID:
+ case Type::ArrayTyID:
+ case Type::FixedVectorTyID:
+ case Type::ScalableVectorTyID:
+ return ConstantAggregateZero::get(Ty);
+ default:
+ return Constant::getNullValue(Ty);
+ }
+}
+
Constant *Constant::getIntegerValue(Type *Ty, const APInt &V) {
Type *ScalarTy = Ty->getScalarType();
@@ -735,7 +782,7 @@ static bool constantIsDead(const Constant *C, bool RemoveDeadUsers) {
ReplaceableMetadataImpl::SalvageDebugInfo(*C);
const_cast<Constant *>(C)->destroyConstant();
}
-
+
return true;
}
@@ -1307,6 +1354,19 @@ ConstantAggregate::ConstantAggregate(Type *T, ValueTy VT,
}
}
+bool ConstantAggregate::isNullValue() const {
+ if (getType()->isVectorTy()) {
+ Constant *V = getSplatValue();
+ return V && V->isNullValue();
+ }
+
+ for (unsigned I = 0; I < getNumOperands(); ++I) {
+ if (!getOperand(I)->isNullValue())
+ return false;
+ }
+ return true;
+}
+
ConstantArray::ConstantArray(ArrayType *T, ArrayRef<Constant *> V,
AllocInfo AllocInfo)
: ConstantAggregate(T, ConstantArrayVal, V, AllocInfo) {
@@ -1392,11 +1452,11 @@ Constant *ConstantStruct::get(StructType *ST, ArrayRef<Constant*> V) {
if (!V.empty()) {
isUndef = isa<UndefValue>(V[0]);
isPoison = isa<PoisonValue>(V[0]);
- isZero = V[0]->isNullValue();
+ isZero = V[0]->isZeroValue();
// PoisonValue inherits UndefValue, so its check is not necessary.
if (isUndef || isZero) {
for (Constant *C : V) {
- if (!C->isNullValue())
+ if (!C->isZeroValue())
isZero = false;
if (!isa<PoisonValue>(C))
isPoison = false;
@@ -1437,7 +1497,7 @@ Constant *ConstantVector::getImpl(ArrayRef<Constant*> V) {
// If this is an all-undef or all-zero vector, return a
// ConstantAggregateZero or UndefValue.
Constant *C = V[0];
- bool isZero = C->isNullValue();
+ bool isZero = C->isZeroValue();
bool isUndef = isa<UndefValue>(C);
bool isPoison = isa<PoisonValue>(C);
bool isSplatFP = UseConstantFPForFixedLengthSplat && isa<ConstantFP>(C);
@@ -3329,6 +3389,12 @@ Value *ConstantArray::handleOperandChangeImpl(Value *From, Value *To) {
Values, this, From, ToC, NumUpdated, OperandNo);
}
+Constant *ConstantArray::getNullValue(ArrayType *T) {
+ return ConstantArray::get(
+ T, SmallVector<Constant *>(T->getNumElements(),
+ Constant::getNullValue(T->getElementType())));
+}
+
Value *ConstantStruct::handleOperandChangeImpl(Value *From, Value *To) {
assert(isa<Constant>(To) && "Cannot make Constant refer to non-constant!");
Constant *ToC = cast<Constant>(To);
@@ -3365,6 +3431,14 @@ Value *ConstantStruct::handleOperandChangeImpl(Value *From, Value *To) {
Values, this, From, ToC, NumUpdated, OperandNo);
}
+Constant *ConstantStruct::getNullValue(StructType *T) {
+ SmallVector<Constant *> Values;
+ Values.reserve(T->getNumElements());
+ for (unsigned I = 0; I < T->getNumElements(); ++I)
+ Values.push_back(Constant::getNullValue(T->getElementType(I)));
+ return ConstantStruct::get(T, Values);
+}
+
Value *ConstantVector::handleOperandChangeImpl(Value *From, Value *To) {
assert(isa<Constant>(To) && "Cannot make Constant refer to non-constant!");
Constant *ToC = cast<Constant>(To);
@@ -3391,6 +3465,11 @@ Value *ConstantVector::handleOperandChangeImpl(Value *From, Value *To) {
Values, this, From, ToC, NumUpdated, OperandNo);
}
+Constant *ConstantVector::getNullValue(VectorType *T) {
+ return ConstantVector::getSplat(T->getElementCount(),
+ Constant::getNullValue(T->getElementType()));
+}
+
Value *ConstantExpr::handleOperandChangeImpl(Value *From, Value *ToV) {
assert(isa<Constant>(ToV) && "Cannot make Constant refer to non-constant!");
Constant *To = cast<Constant>(ToV);