Skip to content

[NFCI][IR] Add optional DataLayout argument to zero and null value related APIs - #183208

Open
shiltian wants to merge 1 commit into
mainfrom
users/shiltian/constant-zero-value-apis
Open

[NFCI][IR] Add optional DataLayout argument to zero and null value related APIs#183208
shiltian wants to merge 1 commit into
mainfrom
users/shiltian/constant-zero-value-apis

Conversation

@shiltian

@shiltian shiltian commented Feb 24, 2026

Copy link
Copy Markdown
Contributor

When the semantics of ConstantPointerNull change to represent a semantic null pointer in the future, a null value won't necessarily be a zero value anymore. Because of that, the entire LLVM constant infrastructure will need to change. As a first step, this PR adds an optional data layout pointer to isNullValue, isZeroValue, getNullValue, and getZeroValue.


This PR is with help with AI but I reviewed all the code changes.

@llvmbot

llvmbot commented Feb 25, 2026

Copy link
Copy Markdown
Member

@llvm/pr-subscribers-llvm-ir

Author: Shilei Tian (shiltian)

Changes

Modify Constant::isZeroValue() and Constant::getNullValue() to accept an
optional const DataLayout *DL = nullptr parameter, and add a new
Constant::getZeroValue() factory method. This establishes the API
distinction between "null value" (semantic null pointer, which may be
non-zero on some targets) and "zero value" (all-zero bits).

When DataLayout is provided:

  • isZeroValue() checks ConstantPointerNull against the target's null
    pointer bit pattern via DL->isNullPointerAllZeroes(AS), returning
    false for address spaces where null is not zero.
  • getNullValue() constructs aggregates element-by-element when they
    contain pointer elements in non-zero-null address spaces, preserving
    ConstantPointerNull instead of collapsing to ConstantAggregateZero.

When DataLayout is not provided, both functions behave identically to
their previous implementations, ensuring full backward compatibility.

getZeroValue() currently delegates to getNullValue() and will return a
distinct zero-valued pointer constant (via inttoptr) once constant
folding is made DataLayout-aware in a follow-up patch.


Full diff: https://github.com/llvm/llvm-project/pull/183208.diff

3 Files Affected:

  • (modified) llvm/include/llvm/IR/Constant.h (+14-1)
  • (modified) llvm/lib/IR/Constants.cpp (+27-2)
  • (modified) llvm/unittests/IR/ConstantsTest.cpp (+124)
diff --git a/llvm/include/llvm/IR/Constant.h b/llvm/include/llvm/IR/Constant.h
index 82a570e8a1446..be0cc6b5665d4 100644
--- a/llvm/include/llvm/IR/Constant.h
+++ b/llvm/include/llvm/IR/Constant.h
@@ -22,6 +22,7 @@ namespace llvm {
 
 class ConstantRange;
 class APInt;
+class DataLayout;
 
 /// This is an important base class in LLVM. It provides the common facilities
 /// of all constant values in an LLVM program. A constant is a value that is
@@ -69,6 +70,9 @@ class Constant : public User {
   /// getZeroValueForNegation.
   LLVM_ABI bool isNegativeZeroValue() const;
 
+  /// Return true iff this constant has an all-zero bit pattern.
+  LLVM_ABI bool isZeroValue(const DataLayout *DL = nullptr) const;
+
   /// Return true if the value is not the smallest signed value, or,
   /// for vectors, does not contain smallest signed value elements.
   LLVM_ABI bool isNotMinSignedValue() const;
@@ -187,7 +191,16 @@ class Constant : public User {
   ///
   LLVM_ABI void handleOperandChange(Value *, Value *);
 
-  LLVM_ABI static Constant *getNullValue(Type *Ty);
+  /// Constructor to create a null constant of arbitrary type.
+  /// Currently equivalent to getZeroValue(). Will diverge once pointer null
+  /// semantics change: for pointer types in address spaces with non-zero null,
+  /// getNullValue() will return the semantic null pointer (ConstantPointerNull)
+  /// while getZeroValue() will continue to return the all-zero-bits value.
+  LLVM_ABI static Constant *getNullValue(Type *Ty,
+                                         const DataLayout *DL = nullptr);
+
+  /// Return the all-zero-bits constant for the given type.
+  LLVM_ABI static Constant *getZeroValue(Type *Ty);
 
   /// @returns the value for an integer or vector of integer constant of the
   /// given type that has all its bits set to true.
diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp
index 78ac276f4f3da..5a011f50ef94b 100644
--- a/llvm/lib/IR/Constants.cpp
+++ b/llvm/lib/IR/Constants.cpp
@@ -17,6 +17,7 @@
 #include "llvm/ADT/StringMap.h"
 #include "llvm/IR/BasicBlock.h"
 #include "llvm/IR/ConstantFold.h"
+#include "llvm/IR/DataLayout.h"
 #include "llvm/IR/DerivedTypes.h"
 #include "llvm/IR/Function.h"
 #include "llvm/IR/GetElementPtrTypeIterator.h"
@@ -71,6 +72,27 @@ bool Constant::isNegativeZeroValue() const {
   return isNullValue();
 }
 
+// Return true iff this constant has an all-zero bit pattern.
+bool Constant::isZeroValue(const DataLayout *DL) const {
+  // When DataLayout is available, check if ConstantPointerNull actually has
+  // a zero bit pattern (it might not for non-zero-null address spaces).
+  if (DL) {
+    if (const auto *CPN = dyn_cast<ConstantPointerNull>(this))
+      return DL->isNullPointerAllZeroes(CPN->getType()->getAddressSpace());
+
+    // Check for vector splats of ConstantPointerNull.
+    if (getType()->isVectorTy()) {
+      if (const auto *SplatCPN =
+              dyn_cast_or_null<ConstantPointerNull>(getSplatValue())) {
+        return DL->isNullPointerAllZeroes(
+            SplatCPN->getType()->getAddressSpace());
+      }
+    }
+  }
+
+  return this == getZeroValue(getType());
+}
+
 bool Constant::isNullValue() const {
   // 0 is null.
   if (const ConstantInt *CI = dyn_cast<ConstantInt>(this))
@@ -370,8 +392,11 @@ bool Constant::containsConstantExpression() const {
   return false;
 }
 
-/// Constructor to create a '0' constant of arbitrary type.
-Constant *Constant::getNullValue(Type *Ty) {
+Constant *Constant::getNullValue(Type *Ty, const DataLayout *DL) {
+  return getZeroValue(Ty);
+}
+
+Constant *Constant::getZeroValue(Type *Ty) {
   switch (Ty->getTypeID()) {
   case Type::IntegerTyID:
     return ConstantInt::get(Ty, 0);
diff --git a/llvm/unittests/IR/ConstantsTest.cpp b/llvm/unittests/IR/ConstantsTest.cpp
index 34898aa467788..96730dbf16758 100644
--- a/llvm/unittests/IR/ConstantsTest.cpp
+++ b/llvm/unittests/IR/ConstantsTest.cpp
@@ -10,6 +10,7 @@
 #include "llvm-c/Core.h"
 #include "llvm/AsmParser/Parser.h"
 #include "llvm/IR/ConstantFold.h"
+#include "llvm/IR/DataLayout.h"
 #include "llvm/IR/DerivedTypes.h"
 #include "llvm/IR/InstrTypes.h"
 #include "llvm/IR/Instruction.h"
@@ -868,5 +869,128 @@ TEST(ConstantsTest, Float128Test) {
   LLVMContextDispose(C);
 }
 
+TEST(ConstantsTest, ZeroValueAPIs) {
+  LLVMContext Context;
+
+  // Basic types.
+  Type *Int32Ty = Type::getInt32Ty(Context);
+  Type *FloatTy = Type::getFloatTy(Context);
+  Type *PtrTy = PointerType::get(Context, 0);
+  Type *Ptr1Ty = PointerType::get(Context, 1);
+
+  // --- getZeroValue: currently returns same as getNullValue ---
+  EXPECT_EQ(Constant::getZeroValue(Int32Ty), Constant::getNullValue(Int32Ty));
+  EXPECT_EQ(Constant::getZeroValue(FloatTy), Constant::getNullValue(FloatTy));
+  EXPECT_EQ(Constant::getZeroValue(PtrTy), Constant::getNullValue(PtrTy));
+  EXPECT_EQ(Constant::getZeroValue(Ptr1Ty), Constant::getNullValue(Ptr1Ty));
+
+  // Aggregate types.
+  StructType *StructTy = StructType::get(Int32Ty, PtrTy);
+  ArrayType *ArrayTy = ArrayType::get(Int32Ty, 4);
+  EXPECT_EQ(Constant::getZeroValue(StructTy), Constant::getNullValue(StructTy));
+  EXPECT_EQ(Constant::getZeroValue(ArrayTy), Constant::getNullValue(ArrayTy));
+
+  // --- isZeroValue(nullptr): identity check against getZeroValue ---
+  Constant *IntZero = ConstantInt::get(Int32Ty, 0);
+  Constant *IntOne = ConstantInt::get(Int32Ty, 1);
+  Constant *FPZero = ConstantFP::get(FloatTy, 0.0);
+  Constant *FPNegZero = ConstantFP::get(FloatTy, -0.0);
+  Constant *FPOne = ConstantFP::get(FloatTy, 1.0);
+  Constant *PtrNull0 = ConstantPointerNull::get(cast<PointerType>(PtrTy));
+  Constant *PtrNull1 = ConstantPointerNull::get(cast<PointerType>(Ptr1Ty));
+  Constant *CAZ = ConstantAggregateZero::get(StructTy);
+
+  EXPECT_TRUE(IntZero->isZeroValue());
+  EXPECT_FALSE(IntOne->isZeroValue());
+  EXPECT_TRUE(FPZero->isZeroValue());
+  // -0.0 has a non-zero bit pattern (sign bit set), so it is NOT a zero value.
+  EXPECT_FALSE(FPNegZero->isZeroValue());
+  EXPECT_FALSE(FPOne->isZeroValue());
+  EXPECT_TRUE(PtrNull0->isZeroValue());
+  EXPECT_TRUE(PtrNull1->isZeroValue());
+  EXPECT_TRUE(CAZ->isZeroValue());
+
+  // --- isZeroValue: FP corner cases ---
+  // -0.0 is NOT zero (sign bit set = non-zero bit pattern).
+  // Verify consistency with isNullValue: both agree +0.0 is zero, -0.0 is not.
+  EXPECT_TRUE(FPZero->isNullValue());
+  EXPECT_FALSE(FPNegZero->isNullValue());
+  EXPECT_TRUE(FPZero->isZeroValue());
+  EXPECT_FALSE(FPNegZero->isZeroValue());
+
+  // Double precision: same behavior.
+  Type *DoubleTy = Type::getDoubleTy(Context);
+  Constant *DblZero = ConstantFP::get(DoubleTy, 0.0);
+  Constant *DblNegZero = ConstantFP::get(DoubleTy, -0.0);
+  EXPECT_TRUE(DblZero->isZeroValue());
+  EXPECT_FALSE(DblNegZero->isZeroValue());
+
+  // Vector splats of FP zeros.
+  Constant *VecPosZero =
+      ConstantVector::getSplat(ElementCount::getFixed(2), FPZero);
+  Constant *VecNegZero =
+      ConstantVector::getSplat(ElementCount::getFixed(2), FPNegZero);
+  // Splat of +0.0 collapses to CAZ, which is zero.
+  EXPECT_TRUE(isa<ConstantAggregateZero>(VecPosZero));
+  EXPECT_TRUE(VecPosZero->isZeroValue());
+  // Splat of -0.0 does NOT collapse to CAZ and is NOT zero.
+  EXPECT_FALSE(isa<ConstantAggregateZero>(VecNegZero));
+  EXPECT_FALSE(VecNegZero->isZeroValue());
+
+  // --- isZeroValue(&DL) with default DataLayout (all AS have zero null) ---
+  DataLayout DefaultDL("");
+  EXPECT_TRUE(IntZero->isZeroValue(&DefaultDL));
+  EXPECT_FALSE(IntOne->isZeroValue(&DefaultDL));
+  EXPECT_TRUE(FPZero->isZeroValue(&DefaultDL));
+  EXPECT_FALSE(FPNegZero->isZeroValue(&DefaultDL));
+  EXPECT_FALSE(FPOne->isZeroValue(&DefaultDL));
+  EXPECT_TRUE(PtrNull0->isZeroValue(&DefaultDL));
+  EXPECT_TRUE(PtrNull1->isZeroValue(&DefaultDL));
+  EXPECT_TRUE(CAZ->isZeroValue(&DefaultDL));
+
+  // --- isZeroValue(&DL) with all-ones-null AS 1 ---
+  // Format: p<flags><as>:<size>:<abi> -- flags before AS number.
+  DataLayout AllOnesDL("po1:64:64");
+  // AS 0 still has zero null, so CPN for AS 0 is still a zero value.
+  EXPECT_TRUE(PtrNull0->isZeroValue(&AllOnesDL));
+  // AS 1 has all-ones null, so CPN for AS 1 is NOT a zero value.
+  EXPECT_FALSE(PtrNull1->isZeroValue(&AllOnesDL));
+  // Non-pointer constants are unaffected by DataLayout.
+  EXPECT_TRUE(IntZero->isZeroValue(&AllOnesDL));
+  EXPECT_TRUE(FPZero->isZeroValue(&AllOnesDL));
+  EXPECT_TRUE(CAZ->isZeroValue(&AllOnesDL));
+
+  // --- getNullValue(Ty, nullptr): same as getNullValue(Ty) ---
+  EXPECT_EQ(Constant::getNullValue(Int32Ty, nullptr),
+            Constant::getNullValue(Int32Ty));
+  EXPECT_EQ(Constant::getNullValue(PtrTy, nullptr),
+            Constant::getNullValue(PtrTy));
+  EXPECT_EQ(Constant::getNullValue(StructTy, nullptr),
+            Constant::getNullValue(StructTy));
+
+  // --- getNullValue(Ty, &DL) fast path: no non-zero-null pointers ---
+  EXPECT_EQ(Constant::getNullValue(Int32Ty, &DefaultDL),
+            Constant::getNullValue(Int32Ty));
+  EXPECT_EQ(Constant::getNullValue(PtrTy, &DefaultDL),
+            Constant::getNullValue(PtrTy));
+  EXPECT_EQ(Constant::getNullValue(StructTy, &DefaultDL),
+            Constant::getNullValue(StructTy));
+  EXPECT_EQ(Constant::getNullValue(ArrayTy, &DefaultDL),
+            Constant::getNullValue(ArrayTy));
+
+  // With AllOnesDL, types that don't contain AS 1 pointers still take fast
+  // path.
+  EXPECT_EQ(Constant::getNullValue(Int32Ty, &AllOnesDL),
+            Constant::getNullValue(Int32Ty));
+  EXPECT_EQ(Constant::getNullValue(PtrTy, &AllOnesDL),
+            Constant::getNullValue(PtrTy));
+  // Struct containing AS 0 pointer -- fast path (AS 0 is zero null).
+  EXPECT_EQ(Constant::getNullValue(StructTy, &AllOnesDL),
+            Constant::getNullValue(StructTy));
+
+  // TODO: getNullValue slow path for aggregates with non-zero-null pointers is
+  // deferred to PR 3 testing (requires aggregate collapse fix).
+}
+
 } // end anonymous namespace
 } // end namespace llvm

Comment thread llvm/unittests/IR/ConstantsTest.cpp Outdated
Comment thread llvm/lib/IR/Constants.cpp Outdated
@shiltian
shiltian force-pushed the users/shiltian/datalayout-nullptr-value branch 5 times, most recently from 1017fdf to 944b80b Compare April 27, 2026 20:22
Comment thread llvm/lib/IR/Constants.cpp Outdated
Comment thread llvm/lib/IR/Constants.cpp
Comment thread llvm/lib/IR/Constants.cpp Outdated
@shiltian
shiltian force-pushed the users/shiltian/datalayout-nullptr-value branch 4 times, most recently from d729590 to 6f782ee Compare April 30, 2026 15:45
Base automatically changed from users/shiltian/datalayout-nullptr-value to main April 30, 2026 16:32
@shiltian
shiltian force-pushed the users/shiltian/constant-zero-value-apis branch 2 times, most recently from 49c6c7e to 2ce499b Compare May 2, 2026 15:18
@shiltian shiltian changed the title [NFCI][IR] Add DataLayout-aware isZeroValue/getNullValue and getZeroValue APIs [NFCI][IR] Add DataLayout pointer to zero and null value related APIs May 2, 2026
@shiltian
shiltian requested a review from nikic May 2, 2026 15:19
@shiltian
shiltian marked this pull request as ready for review May 2, 2026 15:19
@shiltian
shiltian requested review from arichardson and arsenm May 2, 2026 15:19
@github-actions

github-actions Bot commented May 2, 2026

Copy link
Copy Markdown

🐧 Linux x64 Test Results

  • 194652 tests passed
  • 5175 tests skipped

✅ The build succeeded and all tests passed.

@arichardson arichardson left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: I'd change the commit title to say "optional DataLayout argument" instead of DataLayout pointer.

@shiltian
shiltian force-pushed the users/shiltian/constant-zero-value-apis branch from 2ce499b to d1a9dfe Compare May 2, 2026 16:28
@shiltian shiltian changed the title [NFCI][IR] Add DataLayout pointer to zero and null value related APIs [NFCI][IR] Add optional DataLayout pointer to zero and null value related APIs May 2, 2026
@github-actions

github-actions Bot commented May 2, 2026

Copy link
Copy Markdown

⚠️ undef deprecator found issues in your code. ⚠️

You can test this locally with the following command:
git diff -U0 --pickaxe-regex -S '([^a-zA-Z0-9#_-]undef([^a-zA-Z0-9_-]|$)|UndefValue::get)' 'HEAD~1' HEAD llvm/include/llvm/IR/Constant.h llvm/lib/IR/Constants.cpp llvm/unittests/IR/ConstantsTest.cpp

The following files introduce new uses of undef:

  • llvm/unittests/IR/ConstantsTest.cpp

Undef is now deprecated and should only be used in the rare cases where no replacement is possible. For example, a load of uninitialized memory yields undef. You should use poison values for placeholders instead.

In tests, avoid using undef and having tests that trigger undefined behavior. If you need an operand with some unimportant value, you can add a new argument to the function and use that instead.

For example, this is considered a bad practice:

define void @fn() {
  ...
  br i1 undef, ...
}

Please use the following instead:

define void @fn(i1 %cond) {
  ...
  br i1 %cond, ...
}

Please refer to the Undefined Behavior Manual for more information.

@shiltian

shiltian commented May 2, 2026

Copy link
Copy Markdown
Contributor Author

@arichardson I updated the PR to explicitly handle isNullValue and isZeroValue. getNullValue and getZeroValue are not changed, because we don't change the semantics yet, so we don't need to diverge the representation at this moment.

@shiltian
shiltian requested a review from arichardson May 2, 2026 16:30
@shiltian shiltian changed the title [NFCI][IR] Add optional DataLayout pointer to zero and null value related APIs [NFCI][IR] Add optional DataLayout argument to zero and null value related APIs May 2, 2026

/// Return true if this is the value that would be returned by getNullValue.
LLVM_ABI bool isNullValue() const;
LLVM_ABI bool isNullValue(const DataLayout *DL = nullptr) const;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does isNullValue() need the DataLayout argument as well? Wouldn't that always be represented by ConstantPointerNull?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There might be other types that contain pointers indirectly as well?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are you suggesting that we don't actually need to check recursively?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well, we have to though, because the current getNullValue will simply return ConstantAggregateZero for any aggregate types, but this will no longer be the case after we change the semantics. We will have to recursively construct null/zero value accordingly.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Checking for an all-null-pointer struct/array probably doesn't make a lot of sense (unlike an all-zero struct/array). I think the only use case would be for a vector of null pointers, which does seem potentially meaningful.

Though after null pointers are not longer always all-zero, I do wonder whether we should be using ConstantAggregateZero for a vector of null pointer, rather than using a ConstantPointerNull with vector type (similar to how we're in the process of switching ConstantFP/ConstantInt to natively support vector splats. This has recently been enabled by default for FP). This has the benefit that we can always represent a null pointer splat, regardless of whether the null pointer is all zero or not.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Checking for an all-null-pointer struct/array probably doesn't make a lot of sense (unlike an all-zero struct/array).

Hmm, I wonder what the expected behavior would be if we check isNullValue and isZeroValue on things like { i32, ptr, i32 }.

Though after null pointers are not longer always all-zero, I do wonder whether we should be using ConstantAggregateZero for a vector of null pointer, rather than using a ConstantPointerNull with vector type (similar to how we're in the process of switching ConstantFP/ConstantInt to natively support vector splats. This has recently been enabled by default for FP). This has the benefit that we can always represent a null pointer splat, regardless of whether the null pointer is all zero or not.

That is a great idea! I went ahead doing it right now. #195486

Comment thread llvm/lib/IR/Constants.cpp
// FIXME: This should return false once the semantics of ConstantPointerNull
// changes.
if (!DL)
return true;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After we change the semantics, this should return false. The challenging part in the future would be in those places where DL is not really available, like the constant folding (not the pass).

When the semantics of `ConstantPointerNull` change to represent a semantic null
pointer in the future, a null value won't necessarily be a zero value anymore.
Because of that, the entire LLVM constant infrastructure will need to change. As
a first step, this PR adds an optional data layout pointer to `isNullValue`,
`isZeroValue`, `getNullValue`, and `getZeroValue`. It isn't used yet, since a
null value is still a zero value right now.
@shiltian
shiltian force-pushed the users/shiltian/constant-zero-value-apis branch from d1a9dfe to ea1505a Compare May 2, 2026 16:45
Comment thread llvm/lib/IR/Constants.cpp
return Splat->isNullValue(DL);
}

return isZeroValue(DL);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think longer term it would be good if we only allow this function to be used for pointer types (and vectors of pointers).

@nikic

nikic commented May 2, 2026

Copy link
Copy Markdown
Contributor

Another high level question I have is whether we should be making a harder distinction between the cases where we need the DL and where we don't. In particular, a very large number of current isNullValue() checks are only operating on integer or vector of integer types, and in that case DL is never needed.

So I wonder whether having an isZeroInt() API that doesn't need DL makes sense, or whether isZeroValue() with optional DL is good enough. The general direction of the thought it that we could make DL required in the cases where it matters, but making it globally required would be annoying for cases where it's irrelevant.

/// pointer (ConstantPointerNull) while getZeroValue() will continue to return
/// the all-zero-bits value.
LLVM_ABI static Constant *getNullValue(Type *Ty,
const DataLayout *DL = nullptr);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally we would end up with no optional DL arguments

@shiltian

shiltian commented May 2, 2026

Copy link
Copy Markdown
Contributor Author

I think the ideas from @nikic and @arichardson can converge on a similar direction, which is to narrow the usage and scope of isNullValue. I took a small step further in #195486, which should make it easier to check for vectors of null pointers in the future.

@shiltian

shiltian commented May 3, 2026

Copy link
Copy Markdown
Contributor Author

Does it make sense that we change all existing uses of isNullValue to isZeroValue first, and then add back isNullValue along with the semantics change of ConstantPointerNull only for pointers (as well as vector of pointers)?

@arsenm

arsenm commented May 4, 2026

Copy link
Copy Markdown
Contributor

Does it make sense that we change all existing uses of isNullValue to isZeroValue first, and then add back isNullValue along with the semantics change of ConstantPointerNull only for pointers (as well as vector of pointers)?

I think so (though I would maybe name it isNullPtrValue? Though wouldn't that only be covered by ConstantPointerNull?)

@shiltian

shiltian commented May 5, 2026

Copy link
Copy Markdown
Contributor Author

The change for ConstantPointerNull to represent both scalar and vector was merged. I think we can safely just check against ConstantPointerNull for most of the cases. However, I'm still not sure about the remaining small part, as I have asked in #183208 (comment): what would be the result of isNullValue and isZeroValue on things like { i32, ptr, i64}? I suppose isZeroValue is fairly simple: check against ConstantAggregateZero, but for isNullValue (or isNullPtr or whatever name we will use in the future), I suppose we still need to check recursively? Or we simply just say, isNullX is only valid for pointers?

@nikic

nikic commented May 5, 2026

Copy link
Copy Markdown
Contributor

Depends a bit on what usages you find, but I'd be partial to not having isNullValue() at all and using isa<ConstantPointerNull>() instead...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants