diff options
| author | Shilei Tian <i@tianshilei.me> | 2025-11-15 23:19:05 -0500 |
|---|---|---|
| committer | Shilei Tian <i@tianshilei.me> | 2025-11-17 00:16:27 -0500 |
| commit | c52a3b6b8b1cd3fa4c7e58d4d27265482ea837d2 (patch) | |
| tree | f9a9b09e2f9a9e9f12706b6d6761dcecb99b3432 /llvm/lib | |
| parent | 49d5bb0ad0cb31410184c462801c5049ad671517 (diff) | |
[WIP][IR][Constants] Change the semantic of `ConstantPointerNull` to represent an actual `nullptr` instead of a zero-value pointerupstream/users/shiltian/ptr-zeroinitializer-to-inttoptr
The value of a `nullptr` is not always `0`. For example, on AMDGPU, the `nullptr` in address spaces 3 and 5 is `0xffffffff`. Currently, there is no target-independent way to get this information, making it difficult and error-prone to handle null pointers in target-agnostic code.
We do have `ConstantPointerNull`, but it might be a little confusing and misleading. It represents a pointer with an all-zero value rather than necessarily a real `nullptr`. Therefore, to represent a real `nullptr` in address space `N`, we need to use `addrspacecast ptr null to ptr addrspace(N)` and it can't be folded.
In this PR, we change the semantic of `ConstantPointerNull` to represent an actual `nullptr` instead of a zero-value pointer. Here is the detailed changes.
* `ptr addrspace(N) null` will represent the actual `nullptr` in address space `N`.
* `ptr addrspace(N) zeroinitializer` will represent a zero-value pointer in address space `N`.
* `Constant::getNullValue` will return a _null_ value. It is same as the current semantics except for the `PointerType`, which will return a real `nullptr` pointer.
* `Constant::getZeroValue` will return a zero value constant. It is completely same as the current semantics. To represent a zero-value pointer, a `ConstantExpr` will be used (effectively `inttoptr i8 0 to ptr addrspace(N)`).
* Correspondingly, there will be both `Constant::isNullValue` and `Constant::isZeroValue`.
The RFC is https://discourse.llvm.org/t/rfc-introduce-sentinel-pointer-value-to-datalayout/85265. It is a little bit old and the title might look different, but everything eventually converges to this change. An early attempt can be found in https://github.com/llvm/llvm-project/pull/131557, which has many valuable discussion as well.
This PR is still WIP but any early feedback is welcome. I'll include as many necessary code changes as possible in this PR, but eventually this needs to be carefully split into multiple PRs, and I'll do it after the changes look good to every one.
Diffstat (limited to 'llvm/lib')
| -rwxr-xr-x | llvm/lib/Analysis/ConstantFolding.cpp | 41 | ||||
| -rw-r--r-- | llvm/lib/AsmParser/LLParser.cpp | 2 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 11 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp | 15 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp | 14 | ||||
| -rw-r--r-- | llvm/lib/IR/AsmWriter.cpp | 9 | ||||
| -rw-r--r-- | llvm/lib/IR/ConstantFold.cpp | 34 | ||||
| -rw-r--r-- | llvm/lib/IR/Constants.cpp | 97 | ||||
| -rw-r--r-- | llvm/lib/IR/DataLayout.cpp | 41 | ||||
| -rw-r--r-- | llvm/lib/IR/Verifier.cpp | 2 | ||||
| -rw-r--r-- | llvm/lib/TargetParser/TargetDataLayout.cpp | 8 | ||||
| -rw-r--r-- | llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp | 4 |
12 files changed, 246 insertions, 32 deletions
diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp index da32542cf787..adb09e37c4cc 100755 --- a/llvm/lib/Analysis/ConstantFolding.cpp +++ b/llvm/lib/Analysis/ConstantFolding.cpp @@ -1497,6 +1497,21 @@ Constant *llvm::ConstantFoldCastOperand(unsigned Opcode, Constant *C, llvm_unreachable("Missing case"); case Instruction::PtrToAddr: case Instruction::PtrToInt: + // If the input is a nullptr, we can fold it to the corresponding nullptr + // value. + if (Opcode == Instruction::PtrToInt && C->isNullValue()) { + if (std::optional<APInt> NullPtrValue = DL.getNullPtrValue( + C->getType()->getScalarType()->getPointerAddressSpace())) { + if (NullPtrValue->isZero()) { + return Constant::getZeroValue(DestTy); + } else if (NullPtrValue->isAllOnes()) { + return ConstantInt::get( + DestTy, NullPtrValue->zextOrTrunc(DestTy->getScalarSizeInBits())); + } else { + llvm_unreachable("invalid nullptr value"); + } + } + } if (auto *CE = dyn_cast<ConstantExpr>(C)) { Constant *FoldedValue = nullptr; // If the input is an inttoptr, eliminate the pair. This requires knowing @@ -1543,6 +1558,13 @@ Constant *llvm::ConstantFoldCastOperand(unsigned Opcode, Constant *C, } break; case Instruction::IntToPtr: + // We can fold it to a null pointer if the input is the nullptr value. + if (std::optional<APInt> NullPtrValue = DL.getNullPtrValue( + DestTy->getScalarType()->getPointerAddressSpace())) { + if ((NullPtrValue->isZero() && C->isZeroValue()) || + (NullPtrValue->isAllOnes() && C->isAllOnesValue())) + return Constant::getNullValue(DestTy); + } // If the input is a ptrtoint, turn the pair into a ptr to ptr bitcast if // the int size is >= the ptr size and the address spaces are the same. // This requires knowing the width of a pointer, so it can't be done in @@ -1561,6 +1583,24 @@ Constant *llvm::ConstantFoldCastOperand(unsigned Opcode, Constant *C, } } break; + case Instruction::AddrSpaceCast: + // A null pointer (`ptr addrspace(N) null` in IR presentation, + // `ConstantPointerNull` in LLVM class, not `nullptr` in C/C++) used to + // represent a zero-value pointer in the corresponding address space. + // Therefore, we can't simply fold an address space cast of a null pointer + // from one address space to another, because on some targets, the nullptr + // of an address space could be non-zero. + // + // Recently, the semantic of `ptr addrspace(N) null` is changed to represent + // the actual nullptr in the corresponding address space. It can be zero or + // non-zero, depending on the target. Therefore, we can fold an address + // space cast of a nullptr from one address space to another. + + // If the input is a nullptr, we can fold it to the corresponding + // nullptr in the destination address space. + if (C->isNullValue()) + return Constant::getNullValue(DestTy); + [[fallthrough]]; case Instruction::Trunc: case Instruction::ZExt: case Instruction::SExt: @@ -1570,7 +1610,6 @@ Constant *llvm::ConstantFoldCastOperand(unsigned Opcode, Constant *C, case Instruction::SIToFP: case Instruction::FPToUI: case Instruction::FPToSI: - case Instruction::AddrSpaceCast: break; case Instruction::BitCast: return FoldBitCast(C, DestTy, DL); diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp index 8e3ce4990f43..00748a7151d2 100644 --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -6575,7 +6575,7 @@ bool LLParser::convertValIDToValue(Type *Ty, ValID &ID, Value *&V, if (auto *TETy = dyn_cast<TargetExtType>(Ty)) if (!TETy->hasProperty(TargetExtType::HasZeroInit)) return error(ID.Loc, "invalid type for null constant"); - V = Constant::getNullValue(Ty); + V = Constant::getZeroValue(Ty); return false; case ValID::t_None: if (!Ty->isTokenTy()) diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 3aa245b7f3f1..35e1920027a8 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -4275,8 +4275,15 @@ static void emitGlobalConstantImpl(const DataLayout &DL, const Constant *CV, return emitGlobalConstantFP(CFP, AP); } - if (isa<ConstantPointerNull>(CV)) { - AP.OutStreamer->emitIntValue(0, Size); + if (auto *NullPtr = dyn_cast<ConstantPointerNull>(CV)) { + if (std::optional<APInt> NullPtrVal = + DL.getNullPtrValue(NullPtr->getType()->getPointerAddressSpace())) { + AP.OutStreamer->emitIntValue(NullPtrVal->getSExtValue(), Size); + } else { + // We fall back to the default behavior of emitting a zero value if we + // can't get the null pointer value from the data layout. + AP.OutStreamer->emitIntValue(0, Size); + } return; } diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp index 2ec138b6e186..f339226e7040 100644 --- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp +++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp @@ -3768,9 +3768,18 @@ bool IRTranslator::translate(const Constant &C, Register Reg) { EntryBuilder->buildFConstant(Reg, *CF); } else if (isa<UndefValue>(C)) EntryBuilder->buildUndef(Reg); - else if (isa<ConstantPointerNull>(C)) - EntryBuilder->buildConstant(Reg, 0); - else if (auto GV = dyn_cast<GlobalValue>(&C)) + else if (auto *NullPtr = dyn_cast<ConstantPointerNull>(&C)) { + const DataLayout &DL = EntryBuilder->getMF().getDataLayout(); + if (std::optional<APInt> NullPtrValue = + DL.getNullPtrValue(NullPtr->getType()->getAddressSpace())) { + if (NullPtrValue->isZero()) + EntryBuilder->buildConstant(Reg, 0); + else if (NullPtrValue->isAllOnes()) + EntryBuilder->buildConstant(Reg, -1); + else + llvm_unreachable("unknown null pointer value"); + } + } else if (auto GV = dyn_cast<GlobalValue>(&C)) EntryBuilder->buildGlobalValue(Reg, GV); else if (auto CPA = dyn_cast<ConstantPtrAuth>(&C)) { Register Addr = getOrCreateVReg(*CPA->getPointer()); diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index 4f13f3b128ea..d0caf1dfebc4 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -1872,8 +1872,18 @@ SDValue SelectionDAGBuilder::getValueImpl(const Value *V) { getValue(CPA->getDiscriminator())); } - if (isa<ConstantPointerNull>(C)) - return DAG.getConstant(0, getCurSDLoc(), VT); + if (auto *NullPtr = dyn_cast<ConstantPointerNull>(C)) { + const DataLayout &DL = DAG.getDataLayout(); + if (std::optional<APInt> NullPtrValue = + DL.getNullPtrValue(NullPtr->getType()->getAddressSpace())) { + if (NullPtrValue->isZero()) + return DAG.getConstant(0, getCurSDLoc(), VT); + else if (NullPtrValue->isAllOnes()) + return DAG.getAllOnesConstant(getCurSDLoc(), VT); + else + llvm_unreachable("unknown null pointer value"); + } + } if (match(C, m_VScale())) return DAG.getVScale(getCurSDLoc(), VT, APInt(VT.getSizeInBits(), 1)); diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp index 4d4ffe93a806..b7106fea2248 100644 --- a/llvm/lib/IR/AsmWriter.cpp +++ b/llvm/lib/IR/AsmWriter.cpp @@ -1806,6 +1806,15 @@ static void writeConstantInternal(raw_ostream &Out, const Constant *CV, } } + // Use zeroinitializer for inttoptr(0) constant expression. + if (CE->getOpcode() == Instruction::IntToPtr) { + Constant *SrcCI = cast<Constant>(CE->getOperand(0)); + if (SrcCI->isZeroValue()) { + Out << "zeroinitializer"; + return; + } + } + Out << CE->getOpcodeName(); writeOptimizationInfo(Out, CE); Out << " ("; diff --git a/llvm/lib/IR/ConstantFold.cpp b/llvm/lib/IR/ConstantFold.cpp index 6a9ef2efa321..c77f47c2ed99 100644 --- a/llvm/lib/IR/ConstantFold.cpp +++ b/llvm/lib/IR/ConstantFold.cpp @@ -126,6 +126,40 @@ Constant *llvm::ConstantFoldCastInstruction(unsigned opc, Constant *V, if (isa<PoisonValue>(V)) return PoisonValue::get(DestTy); + if (opc == Instruction::IntToPtr) { + // We can't fold inttoptr(0) to ConstantPointerNull without checking the + // target data layout. However, since data layout is not available here, we + // can't do this. + if (V->isZeroValue()) + return nullptr; + // If the input is a ptrtoint(0), we can fold it to the corresponding zero + // value pointer. + if (auto *CE = dyn_cast<ConstantExpr>(V)) { + if (CE->getOpcode() == Instruction::PtrToInt) { + if (CE->getOperand(0)->isZeroValue()) + return Constant::getZeroValue(DestTy); + } + } + } + if (opc == Instruction::PtrToInt) { + // Similarly, we can't fold ptrtoint(nullptr) to null. + if (V->isNullValue()) + return nullptr; + // If the input is a inttoptr(0), we can fold it to the corresponding + // zero value. + if (auto *CE = dyn_cast<ConstantExpr>(V)) { + if (CE->getOpcode() == Instruction::IntToPtr) { + if (CE->getOperand(0)->isZeroValue()) + return Constant::getZeroValue(DestTy); + } + } + } + // However, since the recent change of the semantic of `ptr addrspace(N) + // null`, we can fold address space cast of a nullptr to the corresponding + // nullptr in the destination address space. + if (opc == Instruction::AddrSpaceCast && V->isNullValue()) + return Constant::getNullValue(DestTy); + if (isa<UndefValue>(V)) { // zext(undef) = 0, because the top bits will be zero. // sext(undef) = 0, because the top bits will all be the same. 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); diff --git a/llvm/lib/IR/DataLayout.cpp b/llvm/lib/IR/DataLayout.cpp index 49e1f898ca59..86573c8e0942 100644 --- a/llvm/lib/IR/DataLayout.cpp +++ b/llvm/lib/IR/DataLayout.cpp @@ -193,9 +193,12 @@ constexpr DataLayout::PrimitiveSpec DefaultVectorSpecs[] = { }; // Default pointer type specifications. -constexpr DataLayout::PointerSpec DefaultPointerSpecs[] = { +const DataLayout::PointerSpec DefaultPointerSpecs[] = { // p0:64:64:64:64 - {0, 64, Align::Constant<8>(), Align::Constant<8>(), 64, false, false}, + {/*AddrSpace=*/0, /*BitWidth=*/64, /*ABIAlign=*/Align::Constant<8>(), + /*PrefAlign=*/Align::Constant<8>(), /*IndexBitWidth=*/64, + /*NullPtrValue=*/APInt(64, 0), /*HasUnstableRepr=*/false, + /*HasExternalState=*/false}, }; DataLayout::DataLayout() @@ -408,6 +411,15 @@ Error DataLayout::parsePointerSpec(StringRef Spec) { unsigned AddrSpace = 0; bool ExternalState = false; bool UnstableRepr = false; + // Default nullptr value kind is all-zeros, which is same as the previous + // behavior. + enum { + AllZeros, + AllOnes, + // The nullptr value is neither all-zeros nor all-ones. LLVM doesn't accept + // arbitrary bit patterns, so it will not be able to fold nullptr. + Custom + } NullPtrValueKind = AllZeros; StringRef AddrSpaceStr = Components[0]; while (!AddrSpaceStr.empty()) { char C = AddrSpaceStr.front(); @@ -415,6 +427,12 @@ Error DataLayout::parsePointerSpec(StringRef Spec) { ExternalState = true; } else if (C == 'u') { UnstableRepr = true; + } else if (C == 'z') { + NullPtrValueKind = AllZeros; + } else if (C == 'o') { + NullPtrValueKind = AllOnes; + } else if (C == 'c') { + NullPtrValueKind = Custom; } else if (isAlpha(C)) { return createStringError("'%c' is not a valid pointer specification flag", C); @@ -461,8 +479,14 @@ Error DataLayout::parsePointerSpec(StringRef Spec) { return createStringError( "index size cannot be larger than the pointer size"); + std::optional<APInt> NullPtrValue; + if (NullPtrValueKind == AllZeros) + NullPtrValue = APInt::getZero(BitWidth); + else if (NullPtrValueKind == AllOnes) + NullPtrValue = APInt::getAllOnes(BitWidth); + setPointerSpec(AddrSpace, BitWidth, ABIAlign, PrefAlign, IndexBitWidth, - UnstableRepr, ExternalState); + NullPtrValue, UnstableRepr, ExternalState); return Error::success(); } @@ -638,6 +662,7 @@ Error DataLayout::parseLayoutString(StringRef LayoutString) { // the spec for AS0, and we then update that to mark it non-integral. const PointerSpec &PS = getPointerSpec(AS); setPointerSpec(AS, PS.BitWidth, PS.ABIAlign, PS.PrefAlign, PS.IndexBitWidth, + PS.NullPtrValue, /*HasUnstableRepr=*/true, /*HasExternalState=*/false); } @@ -686,18 +711,20 @@ DataLayout::getPointerSpec(uint32_t AddrSpace) const { void DataLayout::setPointerSpec(uint32_t AddrSpace, uint32_t BitWidth, Align ABIAlign, Align PrefAlign, - uint32_t IndexBitWidth, bool HasUnstableRepr, - bool HasExternalState) { + uint32_t IndexBitWidth, + std::optional<APInt> NullPtrValue, + bool HasUnstableRepr, bool HasExternalState) { auto I = lower_bound(PointerSpecs, AddrSpace, LessPointerAddrSpace()); if (I == PointerSpecs.end() || I->AddrSpace != AddrSpace) { PointerSpecs.insert(I, PointerSpec{AddrSpace, BitWidth, ABIAlign, PrefAlign, - IndexBitWidth, HasUnstableRepr, - HasExternalState}); + IndexBitWidth, NullPtrValue, + HasUnstableRepr, HasExternalState}); } else { I->BitWidth = BitWidth; I->ABIAlign = ABIAlign; I->PrefAlign = PrefAlign; I->IndexBitWidth = IndexBitWidth; + I->NullPtrValue = NullPtrValue; I->HasUnstableRepresentation = HasUnstableRepr; I->HasExternalState = HasExternalState; } diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index fa18c3cd0f40..e99c5e5056bb 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -842,7 +842,7 @@ void Verifier::visitGlobalVariable(const GlobalVariable &GV) { // If the global has common linkage, it must have a zero initializer and // cannot be constant. if (GV.hasCommonLinkage()) { - Check(GV.getInitializer()->isNullValue(), + Check(GV.getInitializer()->isZeroValue(), "'common' global must have a zero initializer!", &GV); Check(!GV.isConstant(), "'common' global may not be marked constant!", &GV); diff --git a/llvm/lib/TargetParser/TargetDataLayout.cpp b/llvm/lib/TargetParser/TargetDataLayout.cpp index d7359234b02f..6b4dd7a73382 100644 --- a/llvm/lib/TargetParser/TargetDataLayout.cpp +++ b/llvm/lib/TargetParser/TargetDataLayout.cpp @@ -269,10 +269,10 @@ static std::string computeAMDDataLayout(const Triple &TT) { // (address space 7), and 128-bit non-integral buffer resourcees (address // space 8) which cannot be non-trivilally accessed by LLVM memory operations // like getelementptr. - return "e-m:e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32" - "-p7:160:256:256:32-p8:128:128:128:48-p9:192:256:256:32-i64:64-" - "v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-" - "v1024:1024-v2048:2048-n32:64-S32-A5-G1-ni:7:8:9"; + return "e-m:e-p:64:64-p1:64:64-po2:32:32-po3:32:32-p4:64:64-po5:32:32-p6:32:" + "32-p7:160:256:256:32-p8:128:128:128:48-p9:192:256:256:32-i64:64-v16:" + "16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:" + "1024-v2048:2048-n32:64-S32-A5-G1-ni:7:8:9"; } static std::string computeRISCVDataLayout(const Triple &TT, StringRef ABIName) { diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp index ff7149044d19..0b3c95e946c1 100644 --- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp +++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp @@ -25493,8 +25493,8 @@ private: dbgs() << "> of " << VectorizedValue << ". (HorRdx)\n"); if (NeedShuffle) VectorizedValue = Builder.CreateShuffleVector( - VectorizedValue, - ConstantVector::getNullValue(VectorizedValue->getType()), Mask); + VectorizedValue, Constant::getNullValue(VectorizedValue->getType()), + Mask); return VectorizedValue; } case RecurKind::FAdd: { |
