diff options
Diffstat (limited to 'llvm/lib/IR/Constants.cpp')
| -rw-r--r-- | llvm/lib/IR/Constants.cpp | 97 |
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); |
