[llvm-branch-commits] [llvm] [NFCI][IR] Thread `DataLayout` through aggregate construction for collapse checks (PR #183211)

Shilei Tian via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Tue Feb 24 15:55:40 PST 2026


https://github.com/shiltian created https://github.com/llvm/llvm-project/pull/183211

Add `const DataLayout *DL = nullptr` to `ConstantArray::get`,
`ConstantStruct::get`, `ConstantVector::get`, and `ConstantVector::getSplat`
so the collapse-to-`ConstantAggregateZero` check uses `isZeroValue(DL)`
instead of `isZeroValue()`.

This is preparatory work for the upcoming `ConstantPointerNull` semantic
change, where `getZeroValue(ptrTy)` will diverge from
`ConstantPointerNull`. Without DL-aware collapse, aggregates containing
CPN would stop collapsing to CAZ, causing widespread test churn. With
this change, callers that pass DL will see correct collapse behavior,
while callers without DL fall back to a conservative identity check.

>From abc165cb326f4bf9049768367814761bb7355c6c Mon Sep 17 00:00:00 2001
From: Shilei Tian <i at tianshilei.me>
Date: Sun, 15 Feb 2026 10:28:09 -0500
Subject: [PATCH] [NFCI][IR] Thread `DataLayout` through aggregate construction
 for collapse checks

Add `const DataLayout *DL = nullptr` to `ConstantArray::get`,
`ConstantStruct::get`, `ConstantVector::get`, and `ConstantVector::getSplat`
so the collapse-to-`ConstantAggregateZero` check uses `isZeroValue(DL)`
instead of `isZeroValue()`.

This is preparatory work for the upcoming `ConstantPointerNull` semantic
change, where `getZeroValue(ptrTy)` will diverge from
`ConstantPointerNull`. Without DL-aware collapse, aggregates containing
CPN would stop collapsing to CAZ, causing widespread test churn. With
this change, callers that pass DL will see correct collapse behavior,
while callers without DL fall back to a conservative identity check.
---
 llvm/include/llvm/IR/Constants.h | 28 +++++++++++++++++----------
 llvm/lib/IR/ConstantFold.cpp     | 10 +++++-----
 llvm/lib/IR/Constants.cpp        | 33 ++++++++++++++++++--------------
 3 files changed, 42 insertions(+), 29 deletions(-)

diff --git a/llvm/include/llvm/IR/Constants.h b/llvm/include/llvm/IR/Constants.h
index a1f667353b26e..d923398f34395 100644
--- a/llvm/include/llvm/IR/Constants.h
+++ b/llvm/include/llvm/IR/Constants.h
@@ -446,10 +446,12 @@ class ConstantArray final : public ConstantAggregate {
 
 public:
   // ConstantArray accessors
-  LLVM_ABI static Constant *get(ArrayType *T, ArrayRef<Constant *> V);
+  LLVM_ABI static Constant *get(ArrayType *T, ArrayRef<Constant *> V,
+                                const DataLayout *DL = nullptr);
 
 private:
-  static Constant *getImpl(ArrayType *T, ArrayRef<Constant *> V);
+  static Constant *getImpl(ArrayType *T, ArrayRef<Constant *> V,
+                           const DataLayout *DL = nullptr);
 
 public:
   /// Specialize the getType() method to always return an ArrayType,
@@ -478,7 +480,8 @@ class ConstantStruct final : public ConstantAggregate {
 
 public:
   // ConstantStruct accessors
-  LLVM_ABI static Constant *get(StructType *T, ArrayRef<Constant *> V);
+  LLVM_ABI static Constant *get(StructType *T, ArrayRef<Constant *> V,
+                                const DataLayout *DL = nullptr);
 
   template <typename... Csts>
   static std::enable_if_t<are_base_of<Constant, Csts...>::value, Constant *>
@@ -488,12 +491,14 @@ class ConstantStruct final : public ConstantAggregate {
 
   /// Return an anonymous struct that has the specified elements.
   /// If the struct is possibly empty, then you must specify a context.
-  static Constant *getAnon(ArrayRef<Constant *> V, bool Packed = false) {
-    return get(getTypeForElements(V, Packed), V);
+  static Constant *getAnon(ArrayRef<Constant *> V, bool Packed = false,
+                           const DataLayout *DL = nullptr) {
+    return get(getTypeForElements(V, Packed), V, DL);
   }
   static Constant *getAnon(LLVMContext &Ctx, ArrayRef<Constant *> V,
-                           bool Packed = false) {
-    return get(getTypeForElements(Ctx, V, Packed), V);
+                           bool Packed = false,
+                           const DataLayout *DL = nullptr) {
+    return get(getTypeForElements(Ctx, V, Packed), V, DL);
   }
 
   /// Return an anonymous struct type to use for a constant with the specified
@@ -530,15 +535,18 @@ class ConstantVector final : public ConstantAggregate {
 
 public:
   // ConstantVector accessors
-  LLVM_ABI static Constant *get(ArrayRef<Constant *> V);
+  LLVM_ABI static Constant *get(ArrayRef<Constant *> V,
+                                const DataLayout *DL = nullptr);
 
 private:
-  static Constant *getImpl(ArrayRef<Constant *> V);
+  static Constant *getImpl(ArrayRef<Constant *> V,
+                           const DataLayout *DL = nullptr);
 
 public:
   /// Return a ConstantVector with the specified constant in each element.
   /// Note that this might not return an instance of ConstantVector
-  LLVM_ABI static Constant *getSplat(ElementCount EC, Constant *Elt);
+  LLVM_ABI static Constant *getSplat(ElementCount EC, Constant *Elt,
+                                     const DataLayout *DL = nullptr);
 
   /// Specialize the getType() method to always return a FixedVectorType,
   /// which reduces the amount of casting needed in parts of the compiler.
diff --git a/llvm/lib/IR/ConstantFold.cpp b/llvm/lib/IR/ConstantFold.cpp
index ba47600dcf0e1..42a85d3ca2d99 100644
--- a/llvm/lib/IR/ConstantFold.cpp
+++ b/llvm/lib/IR/ConstantFold.cpp
@@ -188,7 +188,7 @@ Constant *llvm::ConstantFoldCastInstruction(unsigned opc, Constant *V,
       if (!Res)
         return nullptr;
       return ConstantVector::getSplat(
-          cast<VectorType>(DestTy)->getElementCount(), Res);
+          cast<VectorType>(DestTy)->getElementCount(), Res, DL);
     }
     if (isa<ScalableVectorType>(DestTy))
       return nullptr;
@@ -203,7 +203,7 @@ Constant *llvm::ConstantFoldCastInstruction(unsigned opc, Constant *V,
         return nullptr;
       res.push_back(Casted);
     }
-    return ConstantVector::get(res);
+    return ConstantVector::get(res, DL);
   }
 
   // We actually have to do a cast now. Perform the cast according to the
@@ -1207,7 +1207,7 @@ Constant *llvm::ConstantFoldCompareInstruction(CmpInst::Predicate Predicate,
       if (Constant *C2Splat = C2->getSplatValue())
         if (Constant *Elt =
                 ConstantFoldCompareInstruction(Predicate, C1Splat, C2Splat, DL))
-          return ConstantVector::getSplat(C1VTy->getElementCount(), Elt);
+          return ConstantVector::getSplat(C1VTy->getElementCount(), Elt, DL);
 
     // Do not iterate on scalable vector. The number of elements is unknown at
     // compile-time.
@@ -1232,7 +1232,7 @@ Constant *llvm::ConstantFoldCompareInstruction(CmpInst::Predicate Predicate,
       ResElts.push_back(Elt);
     }
 
-    return ConstantVector::get(ResElts);
+    return ConstantVector::get(ResElts, DL);
   }
 
   if (C1->getType()->isFPOrFPVectorTy()) {
@@ -1371,7 +1371,7 @@ Constant *llvm::ConstantFoldGetElementPtr(Type *PointeeTy, Constant *C,
   if (IsNoOp())
     return GEPTy->isVectorTy() && !C->getType()->isVectorTy()
                ? ConstantVector::getSplat(
-                     cast<VectorType>(GEPTy)->getElementCount(), C)
+                     cast<VectorType>(GEPTy)->getElementCount(), C, DL)
                : C;
 
   return nullptr;
diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp
index 53a627bd6a980..0ded9be53a003 100644
--- a/llvm/lib/IR/Constants.cpp
+++ b/llvm/lib/IR/Constants.cpp
@@ -1341,13 +1341,15 @@ ConstantArray::ConstantArray(ArrayType *T, ArrayRef<Constant *> V,
          "Invalid initializer for constant array");
 }
 
-Constant *ConstantArray::get(ArrayType *Ty, ArrayRef<Constant*> V) {
-  if (Constant *C = getImpl(Ty, V))
+Constant *ConstantArray::get(ArrayType *Ty, ArrayRef<Constant *> V,
+                             const DataLayout *DL) {
+  if (Constant *C = getImpl(Ty, V, DL))
     return C;
   return Ty->getContext().pImpl->ArrayConstants.getOrCreate(Ty, V);
 }
 
-Constant *ConstantArray::getImpl(ArrayType *Ty, ArrayRef<Constant*> V) {
+Constant *ConstantArray::getImpl(ArrayType *Ty, ArrayRef<Constant *> V,
+                                 const DataLayout *DL) {
   // Empty arrays are canonicalized to ConstantAggregateZero.
   if (V.empty())
     return ConstantAggregateZero::get(Ty);
@@ -1368,7 +1370,7 @@ Constant *ConstantArray::getImpl(ArrayType *Ty, ArrayRef<Constant*> V) {
   if (isa<UndefValue>(C) && rangeOnlyContains(V.begin(), V.end(), C))
     return UndefValue::get(Ty);
 
-  if (C->isZeroValue() && rangeOnlyContains(V.begin(), V.end(), C))
+  if (C->isZeroValue(DL) && rangeOnlyContains(V.begin(), V.end(), C))
     return ConstantAggregateZero::get(Ty);
 
   // Check to see if all of the elements are ConstantFP or ConstantInt and if
@@ -1407,7 +1409,8 @@ ConstantStruct::ConstantStruct(StructType *T, ArrayRef<Constant *> V,
 }
 
 // ConstantStruct accessors.
-Constant *ConstantStruct::get(StructType *ST, ArrayRef<Constant*> V) {
+Constant *ConstantStruct::get(StructType *ST, ArrayRef<Constant *> V,
+                              const DataLayout *DL) {
   assert((ST->isOpaque() || ST->getNumElements() == V.size()) &&
          "Incorrect # elements specified to ConstantStruct::get");
 
@@ -1419,11 +1422,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]->isZeroValue();
+    isZero = V[0]->isZeroValue(DL);
     // PoisonValue inherits UndefValue, so its check is not necessary.
     if (isUndef || isZero) {
       for (Constant *C : V) {
-        if (!C->isZeroValue())
+        if (!C->isZeroValue(DL))
           isZero = false;
         if (!isa<PoisonValue>(C))
           isPoison = false;
@@ -1450,21 +1453,22 @@ ConstantVector::ConstantVector(VectorType *T, ArrayRef<Constant *> V,
 }
 
 // ConstantVector accessors.
-Constant *ConstantVector::get(ArrayRef<Constant*> V) {
-  if (Constant *C = getImpl(V))
+Constant *ConstantVector::get(ArrayRef<Constant *> V, const DataLayout *DL) {
+  if (Constant *C = getImpl(V, DL))
     return C;
   auto *Ty = FixedVectorType::get(V.front()->getType(), V.size());
   return Ty->getContext().pImpl->VectorConstants.getOrCreate(Ty, V);
 }
 
-Constant *ConstantVector::getImpl(ArrayRef<Constant*> V) {
+Constant *ConstantVector::getImpl(ArrayRef<Constant *> V,
+                                  const DataLayout *DL) {
   assert(!V.empty() && "Vectors can't be empty");
   auto *T = FixedVectorType::get(V.front()->getType(), V.size());
 
   // If this is an all-undef or all-zero vector, return a
   // ConstantAggregateZero or UndefValue.
   Constant *C = V[0];
-  bool isZero = C->isZeroValue();
+  bool isZero = C->isZeroValue(DL);
   bool isUndef = isa<UndefValue>(C);
   bool isPoison = isa<PoisonValue>(C);
   bool isSplatFP = UseConstantFPForFixedLengthSplat && isa<ConstantFP>(C);
@@ -1501,7 +1505,8 @@ Constant *ConstantVector::getImpl(ArrayRef<Constant*> V) {
   return nullptr;
 }
 
-Constant *ConstantVector::getSplat(ElementCount EC, Constant *V) {
+Constant *ConstantVector::getSplat(ElementCount EC, Constant *V,
+                                   const DataLayout *DL) {
   if (!EC.isScalable()) {
     // Maintain special handling of zero.
     if (!V->isNullValue()) {
@@ -1520,7 +1525,7 @@ Constant *ConstantVector::getSplat(ElementCount EC, Constant *V) {
       return ConstantDataVector::getSplat(EC.getKnownMinValue(), V);
 
     SmallVector<Constant *, 32> Elts(EC.getKnownMinValue(), V);
-    return get(Elts);
+    return get(Elts, DL);
   }
 
   // Maintain special handling of zero.
@@ -1535,7 +1540,7 @@ Constant *ConstantVector::getSplat(ElementCount EC, Constant *V) {
 
   Type *VTy = VectorType::get(V->getType(), EC);
 
-  if (V->isZeroValue())
+  if (V->isZeroValue(DL))
     return ConstantAggregateZero::get(VTy);
   if (isa<PoisonValue>(V))
     return PoisonValue::get(VTy);



More information about the llvm-branch-commits mailing list