Skip to content

Comments

[RFC][IR] Remove Constant::isZeroValue#181521

Merged
shiltian merged 1 commit intomainfrom
users/shiltian/remove-isZeroValue
Feb 15, 2026
Merged

[RFC][IR] Remove Constant::isZeroValue#181521
shiltian merged 1 commit intomainfrom
users/shiltian/remove-isZeroValue

Conversation

@shiltian
Copy link
Contributor

@shiltian shiltian commented Feb 15, 2026

Constant::isZeroValue currently behaves same as Constant::isNullValue for all types except floating-point, where it additionally returns true for negative zero (-0.0). However, in practice, almost all callers operate on integer/pointer types where the two are equivalent, and the few FP-relevant callers have no meaningful dependence on the -0.0 behavior.

This PR removes isZeroValue to eliminate the confusing API. All callers are changed to isNullValue with no test failures.

isZeroValue will be reintroduced in a future change with clearer semantics: when null pointers may have non-zero bit patterns, isZeroValue will check for bitwise-all-zeros, while isNullValue will check for the semantic null (which
may be non-zero).

`Constant::isZeroValue` currently behaves same as `Constant::isNullValue` for
all types except floating-point, where it additionally returns true for negative
zero (`-0.0`). However, in practice, almost all callers operate on
integer/pointer types where the two are equivalent, and the few FP-relevant
callers have no meaningful dependence on the `-0.0` behavior.

This PR removes `isZeroValue` to eliminate the confusing API surface. All
callers are changed to `isNullValue` with no test failures.

`isZeroValue` will be reintroduced in a future change with clearer semantics:
when null pointers may have non-zero bit patterns, `isZeroValue` will check for
bitwise-all-zeros, while `isNullValue` will check for the semantic null (which
may be non-zero).
Copy link
Contributor Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

@shiltian shiltian marked this pull request as ready for review February 15, 2026 04:07
@shiltian shiltian requested a review from nikic as a code owner February 15, 2026 04:07
@llvmbot llvmbot added backend:AArch64 backend:AMDGPU backend:Hexagon backend:X86 clang:codegen IR generation bugs: mangling, exceptions, etc. llvm:codegen debuginfo mlir:llvm PGO Profile Guided Optimizations mlir llvm:instcombine Covers the InstCombine, InstSimplify and AggressiveInstCombine passes backend:DirectX compiler-rt:sanitizer llvm:ir function-specialization llvm:analysis Includes value tracking, cost tables and constant folding llvm:transforms labels Feb 15, 2026
@llvmbot
Copy link
Member

llvmbot commented Feb 15, 2026

@llvm/pr-subscribers-function-specialization
@llvm/pr-subscribers-pgo
@llvm/pr-subscribers-backend-directx
@llvm/pr-subscribers-mlir-llvm
@llvm/pr-subscribers-compiler-rt-sanitizer

@llvm/pr-subscribers-backend-aarch64

Author: Shilei Tian (shiltian)

Changes

Constant::isZeroValue currently behaves same as Constant::isNullValue for
all types except floating-point, where it additionally returns true for negative
zero (-0.0). However, in practice, almost all callers operate on
integer/pointer types where the two are equivalent, and the few FP-relevant
callers have no meaningful dependence on the -0.0 behavior.

This PR removes isZeroValue to eliminate the confusing API surface. All
callers are changed to isNullValue with no test failures.

isZeroValue will be reintroduced in a future change with clearer semantics:
when null pointers may have non-zero bit patterns, isZeroValue will check for
bitwise-all-zeros, while isNullValue will check for the semantic null (which
may be non-zero).


Patch is 30.80 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/181521.diff

36 Files Affected:

  • (modified) clang/lib/CodeGen/CGDecl.cpp (+2-2)
  • (modified) clang/lib/CodeGen/ItaniumCXXABI.cpp (+1-1)
  • (modified) llvm/docs/ReleaseNotes.md (+6)
  • (modified) llvm/include/llvm/IR/Constant.h (-3)
  • (modified) llvm/lib/Analysis/BranchProbabilityInfo.cpp (+2-3)
  • (modified) llvm/lib/Analysis/ConstantFolding.cpp (+2-2)
  • (modified) llvm/lib/Analysis/Lint.cpp (+1-1)
  • (modified) llvm/lib/Analysis/Local.cpp (+1-1)
  • (modified) llvm/lib/Analysis/MustExecute.cpp (+1-1)
  • (modified) llvm/lib/Analysis/ScalarEvolution.cpp (+1-1)
  • (modified) llvm/lib/Analysis/ValueTracking.cpp (+1-1)
  • (modified) llvm/lib/CodeGen/ComplexDeinterleavingPass.cpp (+1-1)
  • (modified) llvm/lib/CodeGen/InterleavedAccessPass.cpp (+2-2)
  • (modified) llvm/lib/FuzzMutate/IRMutator.cpp (+1-1)
  • (modified) llvm/lib/IR/AutoUpgrade.cpp (+2-2)
  • (modified) llvm/lib/IR/Constants.cpp (+1-17)
  • (modified) llvm/lib/IR/DebugInfo.cpp (+1-1)
  • (modified) llvm/lib/Target/AArch64/AArch64PromoteConstant.cpp (+1-1)
  • (modified) llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp (+1-1)
  • (modified) llvm/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp (+2-2)
  • (modified) llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp (+1-1)
  • (modified) llvm/lib/Target/Hexagon/HexagonISelLowering.cpp (+1-1)
  • (modified) llvm/lib/Target/Hexagon/HexagonVectorCombine.cpp (+1-1)
  • (modified) llvm/lib/Target/X86/X86LowerAMXType.cpp (+1-1)
  • (modified) llvm/lib/Transforms/IPO/AttributorAttributes.cpp (+1-1)
  • (modified) llvm/lib/Transforms/IPO/FunctionSpecialization.cpp (+2-2)
  • (modified) llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp (+2-2)
  • (modified) llvm/lib/Transforms/InstCombine/InstructionCombining.cpp (+1-1)
  • (modified) llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp (+2-2)
  • (modified) llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp (+2-2)
  • (modified) llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp (+3-3)
  • (modified) llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp (+1-1)
  • (modified) llvm/unittests/Analysis/ValueLatticeTest.cpp (+9-9)
  • (modified) mlir/lib/Target/LLVMIR/ModuleTranslation.cpp (+1-1)
  • (modified) polly/lib/Support/SCEVValidator.cpp (+1-1)
  • (modified) polly/lib/Transform/ZoneAlgo.cpp (+1-1)
diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp
index 81697e02e8f3f..a7bd2f0470cc0 100644
--- a/clang/lib/CodeGen/CGDecl.cpp
+++ b/clang/lib/CodeGen/CGDecl.cpp
@@ -1070,7 +1070,7 @@ static llvm::Constant *constStructWithPadding(CodeGenModule &CGM,
       Values.push_back(patternOrZeroFor(CGM, isPattern, PadTy));
     }
     llvm::Constant *CurOp;
-    if (constant->isZeroValue())
+    if (constant->isNullValue())
       CurOp = llvm::Constant::getNullValue(STy->getElementType(i));
     else
       CurOp = cast<llvm::Constant>(constant->getAggregateElement(i));
@@ -2023,7 +2023,7 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) {
       D.mightBeUsableInConstantExpressions(getContext())) {
     assert(!capturedByInit && "constant init contains a capturing block?");
     constant = ConstantEmitter(*this).tryEmitAbstractForInitializer(D);
-    if (constant && !constant->isZeroValue() &&
+    if (constant && !constant->isNullValue() &&
         (trivialAutoVarInit !=
          LangOptions::TrivialAutoVarInitKind::Uninitialized)) {
       IsPattern isPattern =
diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp
index e3e071d827b92..759e512ed0719 100644
--- a/clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -916,7 +916,7 @@ static llvm::Constant *pointerAuthResignConstant(
     return nullptr;
 
   assert(CPA->getKey()->getZExtValue() == CurAuthInfo.getKey() &&
-         CPA->getAddrDiscriminator()->isZeroValue() &&
+         CPA->getAddrDiscriminator()->isNullValue() &&
          CPA->getDiscriminator() == CurAuthInfo.getDiscriminator() &&
          "unexpected key or discriminators");
 
diff --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md
index 6ddd4ec14804c..dffdb4291f87a 100644
--- a/llvm/docs/ReleaseNotes.md
+++ b/llvm/docs/ReleaseNotes.md
@@ -72,6 +72,12 @@ Changes to the LLVM IR
 Changes to LLVM infrastructure
 ------------------------------
 
+* Removed ``Constant::isZeroValue``. It was functionally identical to
+  ``Constant::isNullValue`` for all types except floating-point negative
+  zero. All callers should use ``isNullValue`` instead. ``isZeroValue``
+  will be reintroduced in the future with bitwise-all-zeros semantics
+  to support non-zero null pointers.
+
 * Removed TypePromoteFloat legalization from SelectionDAG
 
 Changes to building LLVM
diff --git a/llvm/include/llvm/IR/Constant.h b/llvm/include/llvm/IR/Constant.h
index e8ce453559ed7..82a570e8a1446 100644
--- a/llvm/include/llvm/IR/Constant.h
+++ b/llvm/include/llvm/IR/Constant.h
@@ -69,9 +69,6 @@ class Constant : public User {
   /// getZeroValueForNegation.
   LLVM_ABI bool isNegativeZeroValue() const;
 
-  /// Return true if the value is negative zero or null value.
-  LLVM_ABI bool isZeroValue() 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;
diff --git a/llvm/lib/Analysis/BranchProbabilityInfo.cpp b/llvm/lib/Analysis/BranchProbabilityInfo.cpp
index 4a99a40e0d2cc..412211eb72243 100644
--- a/llvm/lib/Analysis/BranchProbabilityInfo.cpp
+++ b/llvm/lib/Analysis/BranchProbabilityInfo.cpp
@@ -630,9 +630,8 @@ computeUnlikelySuccessors(const BasicBlock *BB, Loop *L,
           CI->getPredicate(), CmpLHSConst, CmpConst, DL);
       // If the result means we don't branch to the block then that block is
       // unlikely.
-      if (Result &&
-          ((Result->isZeroValue() && B == BI->getSuccessor(0)) ||
-           (Result->isOneValue() && B == BI->getSuccessor(1))))
+      if (Result && ((Result->isNullValue() && B == BI->getSuccessor(0)) ||
+                     (Result->isOneValue() && B == BI->getSuccessor(1))))
         UnlikelyBlocks.insert(B);
     }
   }
diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp
index ab060b1b9320a..04200d41dfab0 100644
--- a/llvm/lib/Analysis/ConstantFolding.cpp
+++ b/llvm/lib/Analysis/ConstantFolding.cpp
@@ -3133,7 +3133,7 @@ static Constant *ConstantFoldScalarCall1(StringRef Name,
       break;
 
     case Intrinsic::wasm_anytrue:
-      return Op->isZeroValue() ? ConstantInt::get(Ty, 0)
+      return Op->isNullValue() ? ConstantInt::get(Ty, 0)
                                : ConstantInt::get(Ty, 1);
 
     case Intrinsic::wasm_alltrue:
@@ -3142,7 +3142,7 @@ static Constant *ConstantFoldScalarCall1(StringRef Name,
       for (unsigned I = 0; I != E; ++I) {
         Constant *Elt = Op->getAggregateElement(I);
         // Return false as soon as we find a non-true element.
-        if (Elt && Elt->isZeroValue())
+        if (Elt && Elt->isNullValue())
           return ConstantInt::get(Ty, 0);
         // Bail as soon as we find an element we cannot prove to be true.
         if (!Elt || !isa<ConstantInt>(Elt))
diff --git a/llvm/lib/Analysis/Lint.cpp b/llvm/lib/Analysis/Lint.cpp
index 09fc47e622f75..26e78826848e7 100644
--- a/llvm/lib/Analysis/Lint.cpp
+++ b/llvm/lib/Analysis/Lint.cpp
@@ -553,7 +553,7 @@ static bool isZero(Value *V, const DataLayout &DL, DominatorTree *DT,
   if (!C)
     return false;
 
-  if (C->isZeroValue())
+  if (C->isNullValue())
     return true;
 
   // For a vector, KnownZero will only be true if all values are zero, so check
diff --git a/llvm/lib/Analysis/Local.cpp b/llvm/lib/Analysis/Local.cpp
index a668beabbb294..c08ed4b739d43 100644
--- a/llvm/lib/Analysis/Local.cpp
+++ b/llvm/lib/Analysis/Local.cpp
@@ -41,7 +41,7 @@ Value *llvm::emitGEPOffset(IRBuilderBase *Builder, const DataLayout &DL,
        ++i, ++GTI) {
     Value *Op = *i;
     if (Constant *OpC = dyn_cast<Constant>(Op)) {
-      if (OpC->isZeroValue())
+      if (OpC->isNullValue())
         continue;
 
       // Handle a struct index, which adds its field offset to the pointer.
diff --git a/llvm/lib/Analysis/MustExecute.cpp b/llvm/lib/Analysis/MustExecute.cpp
index fde6bbf9eb181..b08e1a4b2db0d 100644
--- a/llvm/lib/Analysis/MustExecute.cpp
+++ b/llvm/lib/Analysis/MustExecute.cpp
@@ -152,7 +152,7 @@ static bool CanProveNotTakenFirstIteration(const BasicBlock *ExitBlock,
   if (!SimpleCst)
     return false;
   if (ExitBlock == BI->getSuccessor(0))
-    return SimpleCst->isZeroValue();
+    return SimpleCst->isNullValue();
   assert(ExitBlock == BI->getSuccessor(1) && "implied by above");
   return SimpleCst->isAllOnesValue();
 }
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index ae9ce311ec08f..b613fdeab0f8d 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -9641,7 +9641,7 @@ ScalarEvolution::ExitLimit ScalarEvolution::computeShiftCompareExitLimit(
   assert(Result->getType()->isIntegerTy(1) &&
          "Otherwise cannot be an operand to a branch instruction");
 
-  if (Result->isZeroValue()) {
+  if (Result->isNullValue()) {
     unsigned BitWidth = getTypeSizeInBits(RHS->getType());
     const SCEV *UpperBound =
         getConstant(getEffectiveSCEVType(RHS->getType()), BitWidth);
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 8761b7bcb51a2..2d78aa4be3455 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -1725,7 +1725,7 @@ static void computeKnownBitsFromOperator(const Operator *I,
 
       // Handle case when index is zero.
       Constant *CIndex = dyn_cast<Constant>(Index);
-      if (CIndex && CIndex->isZeroValue())
+      if (CIndex && CIndex->isNullValue())
         continue;
 
       if (StructType *STy = GTI.getStructTypeOrNull()) {
diff --git a/llvm/lib/CodeGen/ComplexDeinterleavingPass.cpp b/llvm/lib/CodeGen/ComplexDeinterleavingPass.cpp
index a169eb5e58c02..d6d2917e83a4d 100644
--- a/llvm/lib/CodeGen/ComplexDeinterleavingPass.cpp
+++ b/llvm/lib/CodeGen/ComplexDeinterleavingPass.cpp
@@ -2431,7 +2431,7 @@ void ComplexDeinterleavingGraph::processReductionSingle(
 
   Value *NewInit = nullptr;
   if (auto *C = dyn_cast<Constant>(Init)) {
-    if (C->isZeroValue())
+    if (C->isNullValue())
       NewInit = Constant::getNullValue(NewVTy);
   }
 
diff --git a/llvm/lib/CodeGen/InterleavedAccessPass.cpp b/llvm/lib/CodeGen/InterleavedAccessPass.cpp
index 24394addfa44a..9df7d53c63ff3 100644
--- a/llvm/lib/CodeGen/InterleavedAccessPass.cpp
+++ b/llvm/lib/CodeGen/InterleavedAccessPass.cpp
@@ -572,7 +572,7 @@ static void getGapMask(const Constant &MaskConst, unsigned Factor,
     bool AllZero = true;
     for (unsigned Idx = 0U; Idx < LeafMaskLen; ++Idx) {
       Constant *C = MaskConst.getAggregateElement(F + Idx * Factor);
-      if (!C->isZeroValue()) {
+      if (!C->isNullValue()) {
         AllZero = false;
         break;
       }
@@ -594,7 +594,7 @@ static std::pair<Value *, APInt> getMask(Value *WideMask, unsigned Factor,
       // Check if all the intrinsic arguments are the same, except those that
       // are zeros, which we mark as gaps in the gap mask.
       for (auto [Idx, Arg] : enumerate(IMI->args())) {
-        if (auto *C = dyn_cast<Constant>(Arg); C && C->isZeroValue()) {
+        if (auto *C = dyn_cast<Constant>(Arg); C && C->isNullValue()) {
           GapMask.clearBit(Idx);
           continue;
         }
diff --git a/llvm/lib/FuzzMutate/IRMutator.cpp b/llvm/lib/FuzzMutate/IRMutator.cpp
index d1abf78222c8c..702afe28503b2 100644
--- a/llvm/lib/FuzzMutate/IRMutator.cpp
+++ b/llvm/lib/FuzzMutate/IRMutator.cpp
@@ -338,7 +338,7 @@ void InstModificationIRStrategy::mutate(Instruction &Inst,
     // constant 0.
     Value *Operand = Inst.getOperand(0);
     if (Constant *C = dyn_cast<Constant>(Operand)) {
-      if (!C->isZeroValue()) {
+      if (!C->isNullValue()) {
         ShuffleItems = {0, 1};
       }
     }
diff --git a/llvm/lib/IR/AutoUpgrade.cpp b/llvm/lib/IR/AutoUpgrade.cpp
index 0463bacca350f..790ecb40dc87b 100644
--- a/llvm/lib/IR/AutoUpgrade.cpp
+++ b/llvm/lib/IR/AutoUpgrade.cpp
@@ -4871,7 +4871,7 @@ static void upgradeDbgIntrinsicToDbgRecord(StringRef Name, CallBase *CI) {
     if (CI->arg_size() == 4) {
       auto *Offset = dyn_cast_or_null<Constant>(CI->getArgOperand(1));
       // Nonzero offset dbg.values get dropped without a replacement.
-      if (!Offset || !Offset->isZeroValue())
+      if (!Offset || !Offset->isNullValue())
         return;
       VarOp = 2;
       ExprOp = 3;
@@ -5195,7 +5195,7 @@ void llvm::UpgradeIntrinsicCall(CallBase *CI, Function *NewFn) {
     assert(CI->arg_size() == 4);
     // Drop nonzero offsets instead of attempting to upgrade them.
     if (auto *Offset = dyn_cast_or_null<Constant>(CI->getArgOperand(1)))
-      if (Offset->isZeroValue()) {
+      if (Offset->isNullValue()) {
         NewCall = Builder.CreateCall(
             NewFn,
             {CI->getArgOperand(0), CI->getArgOperand(2), CI->getArgOperand(3)});
diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp
index 76152fe91a532..78ac276f4f3da 100644
--- a/llvm/lib/IR/Constants.cpp
+++ b/llvm/lib/IR/Constants.cpp
@@ -71,22 +71,6 @@ bool Constant::isNegativeZeroValue() const {
   return isNullValue();
 }
 
-// Return true iff this constant is positive zero (floating point), negative
-// zero (floating point), or a null value.
-bool Constant::isZeroValue() const {
-  // Floating point values have an explicit -0.0 value.
-  if (const ConstantFP *CFP = dyn_cast<ConstantFP>(this))
-    return CFP->isZero();
-
-  // Check for constant splat vectors of 1 values.
-  if (getType()->isVectorTy())
-    if (const auto *SplatCFP = dyn_cast_or_null<ConstantFP>(getSplatValue()))
-      return SplatCFP->isZero();
-
-  // Otherwise, just use +0.0.
-  return isNullValue();
-}
-
 bool Constant::isNullValue() const {
   // 0 is null.
   if (const ConstantInt *CI = dyn_cast<ConstantInt>(this))
@@ -752,7 +736,7 @@ static bool constantIsDead(const Constant *C, bool RemoveDeadUsers) {
     ReplaceableMetadataImpl::SalvageDebugInfo(*C);
     const_cast<Constant *>(C)->destroyConstant();
   }
-  
+
   return true;
 }
 
diff --git a/llvm/lib/IR/DebugInfo.cpp b/llvm/lib/IR/DebugInfo.cpp
index 1a83a29ec24e7..d27c3a9a1548a 100644
--- a/llvm/lib/IR/DebugInfo.cpp
+++ b/llvm/lib/IR/DebugInfo.cpp
@@ -2374,7 +2374,7 @@ static void setAssignmentTrackingModuleFlag(Module &M) {
 
 static bool getAssignmentTrackingModuleFlag(const Module &M) {
   Metadata *Value = M.getModuleFlag(AssignmentTrackingModuleFlag);
-  return Value && !cast<ConstantAsMetadata>(Value)->getValue()->isZeroValue();
+  return Value && !cast<ConstantAsMetadata>(Value)->getValue()->isNullValue();
 }
 
 bool llvm::isAssignmentTrackingEnabled(const Module &M) {
diff --git a/llvm/lib/Target/AArch64/AArch64PromoteConstant.cpp b/llvm/lib/Target/AArch64/AArch64PromoteConstant.cpp
index 3f45d55063b50..1a9ce869f5dfa 100644
--- a/llvm/lib/Target/AArch64/AArch64PromoteConstant.cpp
+++ b/llvm/lib/Target/AArch64/AArch64PromoteConstant.cpp
@@ -342,7 +342,7 @@ static bool shouldConvertImpl(const Constant *Cst) {
   // instances of Cst.
   // Ideally, we could promote this into a global and rematerialize the constant
   // when it was a bad idea.
-  if (Cst->isZeroValue())
+  if (Cst->isNullValue())
     return false;
 
   // Globals cannot be or contain scalable vectors.
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp b/llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp
index 376184e81c738..0ebe69de56fa9 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp
@@ -1454,7 +1454,7 @@ GCNTTIImpl::instCombineIntrinsic(InstCombiner &IC, IntrinsicInst &II) const {
     auto *BC = cast<ConstantInt>(II.getArgOperand(5));
     auto *RM = cast<ConstantInt>(II.getArgOperand(3));
     auto *BM = cast<ConstantInt>(II.getArgOperand(4));
-    if (BC->isZeroValue() || RM->getZExtValue() != 0xF ||
+    if (BC->isNullValue() || RM->getZExtValue() != 0xF ||
         BM->getZExtValue() != 0xF || isa<PoisonValue>(Old))
       break;
 
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp b/llvm/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp
index ed676c3fde2f8..4f85c49bff433 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp
@@ -618,7 +618,7 @@ static Value *promoteAllocaUserToVector(Instruction *Inst, const DataLayout &DL,
     Type *AccessTy = Inst->getType();
     TypeSize AccessSize = DL.getTypeStoreSize(AccessTy);
     if (Constant *CI = dyn_cast<Constant>(Index)) {
-      if (CI->isZeroValue() && AccessSize == VecStoreSize) {
+      if (CI->isNullValue() && AccessSize == VecStoreSize) {
         Inst->replaceAllUsesWith(
             Builder.CreateBitPreservingCastChain(DL, CurVal, AccessTy));
         return nullptr;
@@ -696,7 +696,7 @@ static Value *promoteAllocaUserToVector(Instruction *Inst, const DataLayout &DL,
     Type *AccessTy = Val->getType();
     TypeSize AccessSize = DL.getTypeStoreSize(AccessTy);
     if (Constant *CI = dyn_cast<Constant>(Index))
-      if (CI->isZeroValue() && AccessSize == VecStoreSize)
+      if (CI->isNullValue() && AccessSize == VecStoreSize)
         return Builder.CreateBitPreservingCastChain(DL, Val, AA.Vector.Ty);
 
     // Storing a subvector.
diff --git a/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp b/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp
index b1723f77b0e69..c4bf097e5a0f8 100644
--- a/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp
+++ b/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp
@@ -277,7 +277,7 @@ static Value *expandVecReduceAdd(CallInst *Orig, Intrinsic::ID IntrinsicId) {
   // Handle the initial start value for floating-point addition.
   if (IsFAdd) {
     Constant *StartValue = dyn_cast<Constant>(Orig->getOperand(0));
-    if (StartValue && !StartValue->isZeroValue())
+    if (StartValue && !StartValue->isNullValue())
       Sum = Builder.CreateFAdd(Sum, StartValue);
   }
 
diff --git a/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp b/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp
index 1a4be036d4d45..a626de6302b91 100644
--- a/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp
@@ -1172,7 +1172,7 @@ HexagonTargetLowering::LowerConstantPool(SDValue Op, SelectionDAG &DAG) const {
       assert(isPowerOf2_32(VecLen) &&
              "conversion only supported for pow2 VectorSize");
       for (unsigned i = 0; i < VecLen; ++i)
-        NewConst.push_back(IRB.getInt8(CV->getOperand(i)->isZeroValue()));
+        NewConst.push_back(IRB.getInt8(CV->getOperand(i)->isNullValue()));
 
       CVal = ConstantVector::get(NewConst);
       isVTi1Type = true;
diff --git a/llvm/lib/Target/Hexagon/HexagonVectorCombine.cpp b/llvm/lib/Target/Hexagon/HexagonVectorCombine.cpp
index 93cb628becc6e..1bb135a9e5c87 100644
--- a/llvm/lib/Target/Hexagon/HexagonVectorCombine.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonVectorCombine.cpp
@@ -3349,7 +3349,7 @@ auto HexagonVectorCombine::getConstInt(int Val, unsigned Width) const
 
 auto HexagonVectorCombine::isZero(const Value *Val) const -> bool {
   if (auto *C = dyn_cast<Constant>(Val))
-    return C->isZeroValue();
+    return C->isNullValue();
   return false;
 }
 
diff --git a/llvm/lib/Target/X86/X86LowerAMXType.cpp b/llvm/lib/Target/X86/X86LowerAMXType.cpp
index ff93971f81985..df42d1f4388ba 100644
--- a/llvm/lib/Target/X86/X86LowerAMXType.cpp
+++ b/llvm/lib/Target/X86/X86LowerAMXType.cpp
@@ -813,7 +813,7 @@ bool X86LowerAMXCast::optimizeAMXCastFromPhi(
       // might support const.
       if (isa<Constant>(IncValue)) {
         auto *IncConst = dyn_cast<Constant>(IncValue);
-        if (!isa<UndefValue>(IncValue) && !IncConst->isZeroValue())
+        if (!isa<UndefValue>(IncValue) && !IncConst->isNullValue())
           return false;
         Value *Row = nullptr, *Col = nullptr;
         std::tie(Row, Col) = getShape(OldPN);
diff --git a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp
index 37bf2b9c1a966..b80a514b68246 100644
--- a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp
+++ b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp
@@ -10050,7 +10050,7 @@ struct AAPotentialConstantValuesFloating : AAPotentialConstantValuesImpl {
     bool OnlyLeft = false, OnlyRight = false;
     if (C && *C && (*C)->isOneValue())
       OnlyLeft = true;
-    else if (C && *C && (*C)->isZeroValue())
+    else if (C && *C && (*C)->isNullValue())
       OnlyRight = true;
 
     bool LHSContainsUndef = false, RHSContainsUndef = false;
diff --git a/llvm/lib/Transforms/IPO/FunctionSpecialization.cpp b/llvm/lib/Transforms/IPO/FunctionSpecialization.cpp
index 1e1b198c60bef..5a53017f478d6 100644
--- a/llvm/lib/Transforms/IPO/FunctionSpecialization.cpp
+++ b/llvm/lib/Transforms/IPO/FunctionSpecialization.cpp
@@ -455,13 +455,13 @@ Constant *InstCostVisitor::visitSelectInst(SelectInst &I) {
   assert(LastVisited != KnownConstants.end() && "Invalid iterator!");
 
   if (I.getCondition() == LastVisited->first) {
-    Value *V = LastVisited->second->isZeroValue() ? I.getFalseValue()
+    Value *V = LastVisited->second->isNullValue() ? I.getFalseValue()
                                                   : I.getTrueValue();
     return findConstantFor(V);
   }
   if (Constant *Condition = findConstantFor(I.getCondition()))
     if ((I.getTrueValue() == LastVisited->first && Condition->isOneValue()) ||
-        (I.getFalseValue() == LastVisited->first && Condition->isZeroValue()))
+        (I.getFalseValue() == LastVisited->first && Condition->isNullValue()))
       return LastVisited->second;
   return nullptr;
 }
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index 13118b189dab0..3710e143913fa 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -2660,7 +2660,7 @@ Instruction *InstCombinerImpl::visitAnd(BinaryOperator &I) {
         Constant *Log2C1 = ConstantExpr::getExactLogBase2(C1);
         Constant *Cmp =
             ConstantFoldCompareInstOperands(ICmpInst::ICMP_ULT, Log2C3, C2, DL);
-        if (Cmp && Cmp->isZeroValue()) {
+        if (Cmp && Cmp->isNullValue()) {
           // iff C1,C3 is pow2 and Log2(C3) >= C2:
           // ((C1 >> X) << C2) & C3 -> X == (cttz(C1)+C2-cttz(C3)) ? C3 : 0
           Constant *ShlC = ConstantExpr::getAdd(C2, Log2C1);
@@ -532...
[truncated]

@llvmbot
Copy link
Member

llvmbot commented Feb 15, 2026

@llvm/pr-subscribers-backend-x86

Author: Shilei Tian (shiltian)

Changes

Constant::isZeroValue currently behaves same as Constant::isNullValue for
all types except floating-point, where it additionally returns true for negative
zero (-0.0). However, in practice, almost all callers operate on
integer/pointer types where the two are equivalent, and the few FP-relevant
callers have no meaningful dependence on the -0.0 behavior.

This PR removes isZeroValue to eliminate the confusing API surface. All
callers are changed to isNullValue with no test failures.

isZeroValue will be reintroduced in a future change with clearer semantics:
when null pointers may have non-zero bit patterns, isZeroValue will check for
bitwise-all-zeros, while isNullValue will check for the semantic null (which
may be non-zero).


Patch is 30.80 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/181521.diff

36 Files Affected:

  • (modified) clang/lib/CodeGen/CGDecl.cpp (+2-2)
  • (modified) clang/lib/CodeGen/ItaniumCXXABI.cpp (+1-1)
  • (modified) llvm/docs/ReleaseNotes.md (+6)
  • (modified) llvm/include/llvm/IR/Constant.h (-3)
  • (modified) llvm/lib/Analysis/BranchProbabilityInfo.cpp (+2-3)
  • (modified) llvm/lib/Analysis/ConstantFolding.cpp (+2-2)
  • (modified) llvm/lib/Analysis/Lint.cpp (+1-1)
  • (modified) llvm/lib/Analysis/Local.cpp (+1-1)
  • (modified) llvm/lib/Analysis/MustExecute.cpp (+1-1)
  • (modified) llvm/lib/Analysis/ScalarEvolution.cpp (+1-1)
  • (modified) llvm/lib/Analysis/ValueTracking.cpp (+1-1)
  • (modified) llvm/lib/CodeGen/ComplexDeinterleavingPass.cpp (+1-1)
  • (modified) llvm/lib/CodeGen/InterleavedAccessPass.cpp (+2-2)
  • (modified) llvm/lib/FuzzMutate/IRMutator.cpp (+1-1)
  • (modified) llvm/lib/IR/AutoUpgrade.cpp (+2-2)
  • (modified) llvm/lib/IR/Constants.cpp (+1-17)
  • (modified) llvm/lib/IR/DebugInfo.cpp (+1-1)
  • (modified) llvm/lib/Target/AArch64/AArch64PromoteConstant.cpp (+1-1)
  • (modified) llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp (+1-1)
  • (modified) llvm/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp (+2-2)
  • (modified) llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp (+1-1)
  • (modified) llvm/lib/Target/Hexagon/HexagonISelLowering.cpp (+1-1)
  • (modified) llvm/lib/Target/Hexagon/HexagonVectorCombine.cpp (+1-1)
  • (modified) llvm/lib/Target/X86/X86LowerAMXType.cpp (+1-1)
  • (modified) llvm/lib/Transforms/IPO/AttributorAttributes.cpp (+1-1)
  • (modified) llvm/lib/Transforms/IPO/FunctionSpecialization.cpp (+2-2)
  • (modified) llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp (+2-2)
  • (modified) llvm/lib/Transforms/InstCombine/InstructionCombining.cpp (+1-1)
  • (modified) llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp (+2-2)
  • (modified) llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp (+2-2)
  • (modified) llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp (+3-3)
  • (modified) llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp (+1-1)
  • (modified) llvm/unittests/Analysis/ValueLatticeTest.cpp (+9-9)
  • (modified) mlir/lib/Target/LLVMIR/ModuleTranslation.cpp (+1-1)
  • (modified) polly/lib/Support/SCEVValidator.cpp (+1-1)
  • (modified) polly/lib/Transform/ZoneAlgo.cpp (+1-1)
diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp
index 81697e02e8f3f..a7bd2f0470cc0 100644
--- a/clang/lib/CodeGen/CGDecl.cpp
+++ b/clang/lib/CodeGen/CGDecl.cpp
@@ -1070,7 +1070,7 @@ static llvm::Constant *constStructWithPadding(CodeGenModule &CGM,
       Values.push_back(patternOrZeroFor(CGM, isPattern, PadTy));
     }
     llvm::Constant *CurOp;
-    if (constant->isZeroValue())
+    if (constant->isNullValue())
       CurOp = llvm::Constant::getNullValue(STy->getElementType(i));
     else
       CurOp = cast<llvm::Constant>(constant->getAggregateElement(i));
@@ -2023,7 +2023,7 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) {
       D.mightBeUsableInConstantExpressions(getContext())) {
     assert(!capturedByInit && "constant init contains a capturing block?");
     constant = ConstantEmitter(*this).tryEmitAbstractForInitializer(D);
-    if (constant && !constant->isZeroValue() &&
+    if (constant && !constant->isNullValue() &&
         (trivialAutoVarInit !=
          LangOptions::TrivialAutoVarInitKind::Uninitialized)) {
       IsPattern isPattern =
diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp
index e3e071d827b92..759e512ed0719 100644
--- a/clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -916,7 +916,7 @@ static llvm::Constant *pointerAuthResignConstant(
     return nullptr;
 
   assert(CPA->getKey()->getZExtValue() == CurAuthInfo.getKey() &&
-         CPA->getAddrDiscriminator()->isZeroValue() &&
+         CPA->getAddrDiscriminator()->isNullValue() &&
          CPA->getDiscriminator() == CurAuthInfo.getDiscriminator() &&
          "unexpected key or discriminators");
 
diff --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md
index 6ddd4ec14804c..dffdb4291f87a 100644
--- a/llvm/docs/ReleaseNotes.md
+++ b/llvm/docs/ReleaseNotes.md
@@ -72,6 +72,12 @@ Changes to the LLVM IR
 Changes to LLVM infrastructure
 ------------------------------
 
+* Removed ``Constant::isZeroValue``. It was functionally identical to
+  ``Constant::isNullValue`` for all types except floating-point negative
+  zero. All callers should use ``isNullValue`` instead. ``isZeroValue``
+  will be reintroduced in the future with bitwise-all-zeros semantics
+  to support non-zero null pointers.
+
 * Removed TypePromoteFloat legalization from SelectionDAG
 
 Changes to building LLVM
diff --git a/llvm/include/llvm/IR/Constant.h b/llvm/include/llvm/IR/Constant.h
index e8ce453559ed7..82a570e8a1446 100644
--- a/llvm/include/llvm/IR/Constant.h
+++ b/llvm/include/llvm/IR/Constant.h
@@ -69,9 +69,6 @@ class Constant : public User {
   /// getZeroValueForNegation.
   LLVM_ABI bool isNegativeZeroValue() const;
 
-  /// Return true if the value is negative zero or null value.
-  LLVM_ABI bool isZeroValue() 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;
diff --git a/llvm/lib/Analysis/BranchProbabilityInfo.cpp b/llvm/lib/Analysis/BranchProbabilityInfo.cpp
index 4a99a40e0d2cc..412211eb72243 100644
--- a/llvm/lib/Analysis/BranchProbabilityInfo.cpp
+++ b/llvm/lib/Analysis/BranchProbabilityInfo.cpp
@@ -630,9 +630,8 @@ computeUnlikelySuccessors(const BasicBlock *BB, Loop *L,
           CI->getPredicate(), CmpLHSConst, CmpConst, DL);
       // If the result means we don't branch to the block then that block is
       // unlikely.
-      if (Result &&
-          ((Result->isZeroValue() && B == BI->getSuccessor(0)) ||
-           (Result->isOneValue() && B == BI->getSuccessor(1))))
+      if (Result && ((Result->isNullValue() && B == BI->getSuccessor(0)) ||
+                     (Result->isOneValue() && B == BI->getSuccessor(1))))
         UnlikelyBlocks.insert(B);
     }
   }
diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp
index ab060b1b9320a..04200d41dfab0 100644
--- a/llvm/lib/Analysis/ConstantFolding.cpp
+++ b/llvm/lib/Analysis/ConstantFolding.cpp
@@ -3133,7 +3133,7 @@ static Constant *ConstantFoldScalarCall1(StringRef Name,
       break;
 
     case Intrinsic::wasm_anytrue:
-      return Op->isZeroValue() ? ConstantInt::get(Ty, 0)
+      return Op->isNullValue() ? ConstantInt::get(Ty, 0)
                                : ConstantInt::get(Ty, 1);
 
     case Intrinsic::wasm_alltrue:
@@ -3142,7 +3142,7 @@ static Constant *ConstantFoldScalarCall1(StringRef Name,
       for (unsigned I = 0; I != E; ++I) {
         Constant *Elt = Op->getAggregateElement(I);
         // Return false as soon as we find a non-true element.
-        if (Elt && Elt->isZeroValue())
+        if (Elt && Elt->isNullValue())
           return ConstantInt::get(Ty, 0);
         // Bail as soon as we find an element we cannot prove to be true.
         if (!Elt || !isa<ConstantInt>(Elt))
diff --git a/llvm/lib/Analysis/Lint.cpp b/llvm/lib/Analysis/Lint.cpp
index 09fc47e622f75..26e78826848e7 100644
--- a/llvm/lib/Analysis/Lint.cpp
+++ b/llvm/lib/Analysis/Lint.cpp
@@ -553,7 +553,7 @@ static bool isZero(Value *V, const DataLayout &DL, DominatorTree *DT,
   if (!C)
     return false;
 
-  if (C->isZeroValue())
+  if (C->isNullValue())
     return true;
 
   // For a vector, KnownZero will only be true if all values are zero, so check
diff --git a/llvm/lib/Analysis/Local.cpp b/llvm/lib/Analysis/Local.cpp
index a668beabbb294..c08ed4b739d43 100644
--- a/llvm/lib/Analysis/Local.cpp
+++ b/llvm/lib/Analysis/Local.cpp
@@ -41,7 +41,7 @@ Value *llvm::emitGEPOffset(IRBuilderBase *Builder, const DataLayout &DL,
        ++i, ++GTI) {
     Value *Op = *i;
     if (Constant *OpC = dyn_cast<Constant>(Op)) {
-      if (OpC->isZeroValue())
+      if (OpC->isNullValue())
         continue;
 
       // Handle a struct index, which adds its field offset to the pointer.
diff --git a/llvm/lib/Analysis/MustExecute.cpp b/llvm/lib/Analysis/MustExecute.cpp
index fde6bbf9eb181..b08e1a4b2db0d 100644
--- a/llvm/lib/Analysis/MustExecute.cpp
+++ b/llvm/lib/Analysis/MustExecute.cpp
@@ -152,7 +152,7 @@ static bool CanProveNotTakenFirstIteration(const BasicBlock *ExitBlock,
   if (!SimpleCst)
     return false;
   if (ExitBlock == BI->getSuccessor(0))
-    return SimpleCst->isZeroValue();
+    return SimpleCst->isNullValue();
   assert(ExitBlock == BI->getSuccessor(1) && "implied by above");
   return SimpleCst->isAllOnesValue();
 }
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index ae9ce311ec08f..b613fdeab0f8d 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -9641,7 +9641,7 @@ ScalarEvolution::ExitLimit ScalarEvolution::computeShiftCompareExitLimit(
   assert(Result->getType()->isIntegerTy(1) &&
          "Otherwise cannot be an operand to a branch instruction");
 
-  if (Result->isZeroValue()) {
+  if (Result->isNullValue()) {
     unsigned BitWidth = getTypeSizeInBits(RHS->getType());
     const SCEV *UpperBound =
         getConstant(getEffectiveSCEVType(RHS->getType()), BitWidth);
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 8761b7bcb51a2..2d78aa4be3455 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -1725,7 +1725,7 @@ static void computeKnownBitsFromOperator(const Operator *I,
 
       // Handle case when index is zero.
       Constant *CIndex = dyn_cast<Constant>(Index);
-      if (CIndex && CIndex->isZeroValue())
+      if (CIndex && CIndex->isNullValue())
         continue;
 
       if (StructType *STy = GTI.getStructTypeOrNull()) {
diff --git a/llvm/lib/CodeGen/ComplexDeinterleavingPass.cpp b/llvm/lib/CodeGen/ComplexDeinterleavingPass.cpp
index a169eb5e58c02..d6d2917e83a4d 100644
--- a/llvm/lib/CodeGen/ComplexDeinterleavingPass.cpp
+++ b/llvm/lib/CodeGen/ComplexDeinterleavingPass.cpp
@@ -2431,7 +2431,7 @@ void ComplexDeinterleavingGraph::processReductionSingle(
 
   Value *NewInit = nullptr;
   if (auto *C = dyn_cast<Constant>(Init)) {
-    if (C->isZeroValue())
+    if (C->isNullValue())
       NewInit = Constant::getNullValue(NewVTy);
   }
 
diff --git a/llvm/lib/CodeGen/InterleavedAccessPass.cpp b/llvm/lib/CodeGen/InterleavedAccessPass.cpp
index 24394addfa44a..9df7d53c63ff3 100644
--- a/llvm/lib/CodeGen/InterleavedAccessPass.cpp
+++ b/llvm/lib/CodeGen/InterleavedAccessPass.cpp
@@ -572,7 +572,7 @@ static void getGapMask(const Constant &MaskConst, unsigned Factor,
     bool AllZero = true;
     for (unsigned Idx = 0U; Idx < LeafMaskLen; ++Idx) {
       Constant *C = MaskConst.getAggregateElement(F + Idx * Factor);
-      if (!C->isZeroValue()) {
+      if (!C->isNullValue()) {
         AllZero = false;
         break;
       }
@@ -594,7 +594,7 @@ static std::pair<Value *, APInt> getMask(Value *WideMask, unsigned Factor,
       // Check if all the intrinsic arguments are the same, except those that
       // are zeros, which we mark as gaps in the gap mask.
       for (auto [Idx, Arg] : enumerate(IMI->args())) {
-        if (auto *C = dyn_cast<Constant>(Arg); C && C->isZeroValue()) {
+        if (auto *C = dyn_cast<Constant>(Arg); C && C->isNullValue()) {
           GapMask.clearBit(Idx);
           continue;
         }
diff --git a/llvm/lib/FuzzMutate/IRMutator.cpp b/llvm/lib/FuzzMutate/IRMutator.cpp
index d1abf78222c8c..702afe28503b2 100644
--- a/llvm/lib/FuzzMutate/IRMutator.cpp
+++ b/llvm/lib/FuzzMutate/IRMutator.cpp
@@ -338,7 +338,7 @@ void InstModificationIRStrategy::mutate(Instruction &Inst,
     // constant 0.
     Value *Operand = Inst.getOperand(0);
     if (Constant *C = dyn_cast<Constant>(Operand)) {
-      if (!C->isZeroValue()) {
+      if (!C->isNullValue()) {
         ShuffleItems = {0, 1};
       }
     }
diff --git a/llvm/lib/IR/AutoUpgrade.cpp b/llvm/lib/IR/AutoUpgrade.cpp
index 0463bacca350f..790ecb40dc87b 100644
--- a/llvm/lib/IR/AutoUpgrade.cpp
+++ b/llvm/lib/IR/AutoUpgrade.cpp
@@ -4871,7 +4871,7 @@ static void upgradeDbgIntrinsicToDbgRecord(StringRef Name, CallBase *CI) {
     if (CI->arg_size() == 4) {
       auto *Offset = dyn_cast_or_null<Constant>(CI->getArgOperand(1));
       // Nonzero offset dbg.values get dropped without a replacement.
-      if (!Offset || !Offset->isZeroValue())
+      if (!Offset || !Offset->isNullValue())
         return;
       VarOp = 2;
       ExprOp = 3;
@@ -5195,7 +5195,7 @@ void llvm::UpgradeIntrinsicCall(CallBase *CI, Function *NewFn) {
     assert(CI->arg_size() == 4);
     // Drop nonzero offsets instead of attempting to upgrade them.
     if (auto *Offset = dyn_cast_or_null<Constant>(CI->getArgOperand(1)))
-      if (Offset->isZeroValue()) {
+      if (Offset->isNullValue()) {
         NewCall = Builder.CreateCall(
             NewFn,
             {CI->getArgOperand(0), CI->getArgOperand(2), CI->getArgOperand(3)});
diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp
index 76152fe91a532..78ac276f4f3da 100644
--- a/llvm/lib/IR/Constants.cpp
+++ b/llvm/lib/IR/Constants.cpp
@@ -71,22 +71,6 @@ bool Constant::isNegativeZeroValue() const {
   return isNullValue();
 }
 
-// Return true iff this constant is positive zero (floating point), negative
-// zero (floating point), or a null value.
-bool Constant::isZeroValue() const {
-  // Floating point values have an explicit -0.0 value.
-  if (const ConstantFP *CFP = dyn_cast<ConstantFP>(this))
-    return CFP->isZero();
-
-  // Check for constant splat vectors of 1 values.
-  if (getType()->isVectorTy())
-    if (const auto *SplatCFP = dyn_cast_or_null<ConstantFP>(getSplatValue()))
-      return SplatCFP->isZero();
-
-  // Otherwise, just use +0.0.
-  return isNullValue();
-}
-
 bool Constant::isNullValue() const {
   // 0 is null.
   if (const ConstantInt *CI = dyn_cast<ConstantInt>(this))
@@ -752,7 +736,7 @@ static bool constantIsDead(const Constant *C, bool RemoveDeadUsers) {
     ReplaceableMetadataImpl::SalvageDebugInfo(*C);
     const_cast<Constant *>(C)->destroyConstant();
   }
-  
+
   return true;
 }
 
diff --git a/llvm/lib/IR/DebugInfo.cpp b/llvm/lib/IR/DebugInfo.cpp
index 1a83a29ec24e7..d27c3a9a1548a 100644
--- a/llvm/lib/IR/DebugInfo.cpp
+++ b/llvm/lib/IR/DebugInfo.cpp
@@ -2374,7 +2374,7 @@ static void setAssignmentTrackingModuleFlag(Module &M) {
 
 static bool getAssignmentTrackingModuleFlag(const Module &M) {
   Metadata *Value = M.getModuleFlag(AssignmentTrackingModuleFlag);
-  return Value && !cast<ConstantAsMetadata>(Value)->getValue()->isZeroValue();
+  return Value && !cast<ConstantAsMetadata>(Value)->getValue()->isNullValue();
 }
 
 bool llvm::isAssignmentTrackingEnabled(const Module &M) {
diff --git a/llvm/lib/Target/AArch64/AArch64PromoteConstant.cpp b/llvm/lib/Target/AArch64/AArch64PromoteConstant.cpp
index 3f45d55063b50..1a9ce869f5dfa 100644
--- a/llvm/lib/Target/AArch64/AArch64PromoteConstant.cpp
+++ b/llvm/lib/Target/AArch64/AArch64PromoteConstant.cpp
@@ -342,7 +342,7 @@ static bool shouldConvertImpl(const Constant *Cst) {
   // instances of Cst.
   // Ideally, we could promote this into a global and rematerialize the constant
   // when it was a bad idea.
-  if (Cst->isZeroValue())
+  if (Cst->isNullValue())
     return false;
 
   // Globals cannot be or contain scalable vectors.
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp b/llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp
index 376184e81c738..0ebe69de56fa9 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp
@@ -1454,7 +1454,7 @@ GCNTTIImpl::instCombineIntrinsic(InstCombiner &IC, IntrinsicInst &II) const {
     auto *BC = cast<ConstantInt>(II.getArgOperand(5));
     auto *RM = cast<ConstantInt>(II.getArgOperand(3));
     auto *BM = cast<ConstantInt>(II.getArgOperand(4));
-    if (BC->isZeroValue() || RM->getZExtValue() != 0xF ||
+    if (BC->isNullValue() || RM->getZExtValue() != 0xF ||
         BM->getZExtValue() != 0xF || isa<PoisonValue>(Old))
       break;
 
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp b/llvm/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp
index ed676c3fde2f8..4f85c49bff433 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp
@@ -618,7 +618,7 @@ static Value *promoteAllocaUserToVector(Instruction *Inst, const DataLayout &DL,
     Type *AccessTy = Inst->getType();
     TypeSize AccessSize = DL.getTypeStoreSize(AccessTy);
     if (Constant *CI = dyn_cast<Constant>(Index)) {
-      if (CI->isZeroValue() && AccessSize == VecStoreSize) {
+      if (CI->isNullValue() && AccessSize == VecStoreSize) {
         Inst->replaceAllUsesWith(
             Builder.CreateBitPreservingCastChain(DL, CurVal, AccessTy));
         return nullptr;
@@ -696,7 +696,7 @@ static Value *promoteAllocaUserToVector(Instruction *Inst, const DataLayout &DL,
     Type *AccessTy = Val->getType();
     TypeSize AccessSize = DL.getTypeStoreSize(AccessTy);
     if (Constant *CI = dyn_cast<Constant>(Index))
-      if (CI->isZeroValue() && AccessSize == VecStoreSize)
+      if (CI->isNullValue() && AccessSize == VecStoreSize)
         return Builder.CreateBitPreservingCastChain(DL, Val, AA.Vector.Ty);
 
     // Storing a subvector.
diff --git a/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp b/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp
index b1723f77b0e69..c4bf097e5a0f8 100644
--- a/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp
+++ b/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp
@@ -277,7 +277,7 @@ static Value *expandVecReduceAdd(CallInst *Orig, Intrinsic::ID IntrinsicId) {
   // Handle the initial start value for floating-point addition.
   if (IsFAdd) {
     Constant *StartValue = dyn_cast<Constant>(Orig->getOperand(0));
-    if (StartValue && !StartValue->isZeroValue())
+    if (StartValue && !StartValue->isNullValue())
       Sum = Builder.CreateFAdd(Sum, StartValue);
   }
 
diff --git a/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp b/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp
index 1a4be036d4d45..a626de6302b91 100644
--- a/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp
@@ -1172,7 +1172,7 @@ HexagonTargetLowering::LowerConstantPool(SDValue Op, SelectionDAG &DAG) const {
       assert(isPowerOf2_32(VecLen) &&
              "conversion only supported for pow2 VectorSize");
       for (unsigned i = 0; i < VecLen; ++i)
-        NewConst.push_back(IRB.getInt8(CV->getOperand(i)->isZeroValue()));
+        NewConst.push_back(IRB.getInt8(CV->getOperand(i)->isNullValue()));
 
       CVal = ConstantVector::get(NewConst);
       isVTi1Type = true;
diff --git a/llvm/lib/Target/Hexagon/HexagonVectorCombine.cpp b/llvm/lib/Target/Hexagon/HexagonVectorCombine.cpp
index 93cb628becc6e..1bb135a9e5c87 100644
--- a/llvm/lib/Target/Hexagon/HexagonVectorCombine.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonVectorCombine.cpp
@@ -3349,7 +3349,7 @@ auto HexagonVectorCombine::getConstInt(int Val, unsigned Width) const
 
 auto HexagonVectorCombine::isZero(const Value *Val) const -> bool {
   if (auto *C = dyn_cast<Constant>(Val))
-    return C->isZeroValue();
+    return C->isNullValue();
   return false;
 }
 
diff --git a/llvm/lib/Target/X86/X86LowerAMXType.cpp b/llvm/lib/Target/X86/X86LowerAMXType.cpp
index ff93971f81985..df42d1f4388ba 100644
--- a/llvm/lib/Target/X86/X86LowerAMXType.cpp
+++ b/llvm/lib/Target/X86/X86LowerAMXType.cpp
@@ -813,7 +813,7 @@ bool X86LowerAMXCast::optimizeAMXCastFromPhi(
       // might support const.
       if (isa<Constant>(IncValue)) {
         auto *IncConst = dyn_cast<Constant>(IncValue);
-        if (!isa<UndefValue>(IncValue) && !IncConst->isZeroValue())
+        if (!isa<UndefValue>(IncValue) && !IncConst->isNullValue())
           return false;
         Value *Row = nullptr, *Col = nullptr;
         std::tie(Row, Col) = getShape(OldPN);
diff --git a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp
index 37bf2b9c1a966..b80a514b68246 100644
--- a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp
+++ b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp
@@ -10050,7 +10050,7 @@ struct AAPotentialConstantValuesFloating : AAPotentialConstantValuesImpl {
     bool OnlyLeft = false, OnlyRight = false;
     if (C && *C && (*C)->isOneValue())
       OnlyLeft = true;
-    else if (C && *C && (*C)->isZeroValue())
+    else if (C && *C && (*C)->isNullValue())
       OnlyRight = true;
 
     bool LHSContainsUndef = false, RHSContainsUndef = false;
diff --git a/llvm/lib/Transforms/IPO/FunctionSpecialization.cpp b/llvm/lib/Transforms/IPO/FunctionSpecialization.cpp
index 1e1b198c60bef..5a53017f478d6 100644
--- a/llvm/lib/Transforms/IPO/FunctionSpecialization.cpp
+++ b/llvm/lib/Transforms/IPO/FunctionSpecialization.cpp
@@ -455,13 +455,13 @@ Constant *InstCostVisitor::visitSelectInst(SelectInst &I) {
   assert(LastVisited != KnownConstants.end() && "Invalid iterator!");
 
   if (I.getCondition() == LastVisited->first) {
-    Value *V = LastVisited->second->isZeroValue() ? I.getFalseValue()
+    Value *V = LastVisited->second->isNullValue() ? I.getFalseValue()
                                                   : I.getTrueValue();
     return findConstantFor(V);
   }
   if (Constant *Condition = findConstantFor(I.getCondition()))
     if ((I.getTrueValue() == LastVisited->first && Condition->isOneValue()) ||
-        (I.getFalseValue() == LastVisited->first && Condition->isZeroValue()))
+        (I.getFalseValue() == LastVisited->first && Condition->isNullValue()))
       return LastVisited->second;
   return nullptr;
 }
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index 13118b189dab0..3710e143913fa 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -2660,7 +2660,7 @@ Instruction *InstCombinerImpl::visitAnd(BinaryOperator &I) {
         Constant *Log2C1 = ConstantExpr::getExactLogBase2(C1);
         Constant *Cmp =
             ConstantFoldCompareInstOperands(ICmpInst::ICMP_ULT, Log2C3, C2, DL);
-        if (Cmp && Cmp->isZeroValue()) {
+        if (Cmp && Cmp->isNullValue()) {
           // iff C1,C3 is pow2 and Log2(C3) >= C2:
           // ((C1 >> X) << C2) & C3 -> X == (cttz(C1)+C2-cttz(C3)) ? C3 : 0
           Constant *ShlC = ConstantExpr::getAdd(C2, Log2C1);
@@ -532...
[truncated]

@llvmbot
Copy link
Member

llvmbot commented Feb 15, 2026

@llvm/pr-subscribers-debuginfo

Author: Shilei Tian (shiltian)

Changes

Constant::isZeroValue currently behaves same as Constant::isNullValue for
all types except floating-point, where it additionally returns true for negative
zero (-0.0). However, in practice, almost all callers operate on
integer/pointer types where the two are equivalent, and the few FP-relevant
callers have no meaningful dependence on the -0.0 behavior.

This PR removes isZeroValue to eliminate the confusing API surface. All
callers are changed to isNullValue with no test failures.

isZeroValue will be reintroduced in a future change with clearer semantics:
when null pointers may have non-zero bit patterns, isZeroValue will check for
bitwise-all-zeros, while isNullValue will check for the semantic null (which
may be non-zero).


Patch is 30.80 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/181521.diff

36 Files Affected:

  • (modified) clang/lib/CodeGen/CGDecl.cpp (+2-2)
  • (modified) clang/lib/CodeGen/ItaniumCXXABI.cpp (+1-1)
  • (modified) llvm/docs/ReleaseNotes.md (+6)
  • (modified) llvm/include/llvm/IR/Constant.h (-3)
  • (modified) llvm/lib/Analysis/BranchProbabilityInfo.cpp (+2-3)
  • (modified) llvm/lib/Analysis/ConstantFolding.cpp (+2-2)
  • (modified) llvm/lib/Analysis/Lint.cpp (+1-1)
  • (modified) llvm/lib/Analysis/Local.cpp (+1-1)
  • (modified) llvm/lib/Analysis/MustExecute.cpp (+1-1)
  • (modified) llvm/lib/Analysis/ScalarEvolution.cpp (+1-1)
  • (modified) llvm/lib/Analysis/ValueTracking.cpp (+1-1)
  • (modified) llvm/lib/CodeGen/ComplexDeinterleavingPass.cpp (+1-1)
  • (modified) llvm/lib/CodeGen/InterleavedAccessPass.cpp (+2-2)
  • (modified) llvm/lib/FuzzMutate/IRMutator.cpp (+1-1)
  • (modified) llvm/lib/IR/AutoUpgrade.cpp (+2-2)
  • (modified) llvm/lib/IR/Constants.cpp (+1-17)
  • (modified) llvm/lib/IR/DebugInfo.cpp (+1-1)
  • (modified) llvm/lib/Target/AArch64/AArch64PromoteConstant.cpp (+1-1)
  • (modified) llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp (+1-1)
  • (modified) llvm/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp (+2-2)
  • (modified) llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp (+1-1)
  • (modified) llvm/lib/Target/Hexagon/HexagonISelLowering.cpp (+1-1)
  • (modified) llvm/lib/Target/Hexagon/HexagonVectorCombine.cpp (+1-1)
  • (modified) llvm/lib/Target/X86/X86LowerAMXType.cpp (+1-1)
  • (modified) llvm/lib/Transforms/IPO/AttributorAttributes.cpp (+1-1)
  • (modified) llvm/lib/Transforms/IPO/FunctionSpecialization.cpp (+2-2)
  • (modified) llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp (+2-2)
  • (modified) llvm/lib/Transforms/InstCombine/InstructionCombining.cpp (+1-1)
  • (modified) llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp (+2-2)
  • (modified) llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp (+2-2)
  • (modified) llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp (+3-3)
  • (modified) llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp (+1-1)
  • (modified) llvm/unittests/Analysis/ValueLatticeTest.cpp (+9-9)
  • (modified) mlir/lib/Target/LLVMIR/ModuleTranslation.cpp (+1-1)
  • (modified) polly/lib/Support/SCEVValidator.cpp (+1-1)
  • (modified) polly/lib/Transform/ZoneAlgo.cpp (+1-1)
diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp
index 81697e02e8f3f..a7bd2f0470cc0 100644
--- a/clang/lib/CodeGen/CGDecl.cpp
+++ b/clang/lib/CodeGen/CGDecl.cpp
@@ -1070,7 +1070,7 @@ static llvm::Constant *constStructWithPadding(CodeGenModule &CGM,
       Values.push_back(patternOrZeroFor(CGM, isPattern, PadTy));
     }
     llvm::Constant *CurOp;
-    if (constant->isZeroValue())
+    if (constant->isNullValue())
       CurOp = llvm::Constant::getNullValue(STy->getElementType(i));
     else
       CurOp = cast<llvm::Constant>(constant->getAggregateElement(i));
@@ -2023,7 +2023,7 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) {
       D.mightBeUsableInConstantExpressions(getContext())) {
     assert(!capturedByInit && "constant init contains a capturing block?");
     constant = ConstantEmitter(*this).tryEmitAbstractForInitializer(D);
-    if (constant && !constant->isZeroValue() &&
+    if (constant && !constant->isNullValue() &&
         (trivialAutoVarInit !=
          LangOptions::TrivialAutoVarInitKind::Uninitialized)) {
       IsPattern isPattern =
diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp
index e3e071d827b92..759e512ed0719 100644
--- a/clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -916,7 +916,7 @@ static llvm::Constant *pointerAuthResignConstant(
     return nullptr;
 
   assert(CPA->getKey()->getZExtValue() == CurAuthInfo.getKey() &&
-         CPA->getAddrDiscriminator()->isZeroValue() &&
+         CPA->getAddrDiscriminator()->isNullValue() &&
          CPA->getDiscriminator() == CurAuthInfo.getDiscriminator() &&
          "unexpected key or discriminators");
 
diff --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md
index 6ddd4ec14804c..dffdb4291f87a 100644
--- a/llvm/docs/ReleaseNotes.md
+++ b/llvm/docs/ReleaseNotes.md
@@ -72,6 +72,12 @@ Changes to the LLVM IR
 Changes to LLVM infrastructure
 ------------------------------
 
+* Removed ``Constant::isZeroValue``. It was functionally identical to
+  ``Constant::isNullValue`` for all types except floating-point negative
+  zero. All callers should use ``isNullValue`` instead. ``isZeroValue``
+  will be reintroduced in the future with bitwise-all-zeros semantics
+  to support non-zero null pointers.
+
 * Removed TypePromoteFloat legalization from SelectionDAG
 
 Changes to building LLVM
diff --git a/llvm/include/llvm/IR/Constant.h b/llvm/include/llvm/IR/Constant.h
index e8ce453559ed7..82a570e8a1446 100644
--- a/llvm/include/llvm/IR/Constant.h
+++ b/llvm/include/llvm/IR/Constant.h
@@ -69,9 +69,6 @@ class Constant : public User {
   /// getZeroValueForNegation.
   LLVM_ABI bool isNegativeZeroValue() const;
 
-  /// Return true if the value is negative zero or null value.
-  LLVM_ABI bool isZeroValue() 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;
diff --git a/llvm/lib/Analysis/BranchProbabilityInfo.cpp b/llvm/lib/Analysis/BranchProbabilityInfo.cpp
index 4a99a40e0d2cc..412211eb72243 100644
--- a/llvm/lib/Analysis/BranchProbabilityInfo.cpp
+++ b/llvm/lib/Analysis/BranchProbabilityInfo.cpp
@@ -630,9 +630,8 @@ computeUnlikelySuccessors(const BasicBlock *BB, Loop *L,
           CI->getPredicate(), CmpLHSConst, CmpConst, DL);
       // If the result means we don't branch to the block then that block is
       // unlikely.
-      if (Result &&
-          ((Result->isZeroValue() && B == BI->getSuccessor(0)) ||
-           (Result->isOneValue() && B == BI->getSuccessor(1))))
+      if (Result && ((Result->isNullValue() && B == BI->getSuccessor(0)) ||
+                     (Result->isOneValue() && B == BI->getSuccessor(1))))
         UnlikelyBlocks.insert(B);
     }
   }
diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp
index ab060b1b9320a..04200d41dfab0 100644
--- a/llvm/lib/Analysis/ConstantFolding.cpp
+++ b/llvm/lib/Analysis/ConstantFolding.cpp
@@ -3133,7 +3133,7 @@ static Constant *ConstantFoldScalarCall1(StringRef Name,
       break;
 
     case Intrinsic::wasm_anytrue:
-      return Op->isZeroValue() ? ConstantInt::get(Ty, 0)
+      return Op->isNullValue() ? ConstantInt::get(Ty, 0)
                                : ConstantInt::get(Ty, 1);
 
     case Intrinsic::wasm_alltrue:
@@ -3142,7 +3142,7 @@ static Constant *ConstantFoldScalarCall1(StringRef Name,
       for (unsigned I = 0; I != E; ++I) {
         Constant *Elt = Op->getAggregateElement(I);
         // Return false as soon as we find a non-true element.
-        if (Elt && Elt->isZeroValue())
+        if (Elt && Elt->isNullValue())
           return ConstantInt::get(Ty, 0);
         // Bail as soon as we find an element we cannot prove to be true.
         if (!Elt || !isa<ConstantInt>(Elt))
diff --git a/llvm/lib/Analysis/Lint.cpp b/llvm/lib/Analysis/Lint.cpp
index 09fc47e622f75..26e78826848e7 100644
--- a/llvm/lib/Analysis/Lint.cpp
+++ b/llvm/lib/Analysis/Lint.cpp
@@ -553,7 +553,7 @@ static bool isZero(Value *V, const DataLayout &DL, DominatorTree *DT,
   if (!C)
     return false;
 
-  if (C->isZeroValue())
+  if (C->isNullValue())
     return true;
 
   // For a vector, KnownZero will only be true if all values are zero, so check
diff --git a/llvm/lib/Analysis/Local.cpp b/llvm/lib/Analysis/Local.cpp
index a668beabbb294..c08ed4b739d43 100644
--- a/llvm/lib/Analysis/Local.cpp
+++ b/llvm/lib/Analysis/Local.cpp
@@ -41,7 +41,7 @@ Value *llvm::emitGEPOffset(IRBuilderBase *Builder, const DataLayout &DL,
        ++i, ++GTI) {
     Value *Op = *i;
     if (Constant *OpC = dyn_cast<Constant>(Op)) {
-      if (OpC->isZeroValue())
+      if (OpC->isNullValue())
         continue;
 
       // Handle a struct index, which adds its field offset to the pointer.
diff --git a/llvm/lib/Analysis/MustExecute.cpp b/llvm/lib/Analysis/MustExecute.cpp
index fde6bbf9eb181..b08e1a4b2db0d 100644
--- a/llvm/lib/Analysis/MustExecute.cpp
+++ b/llvm/lib/Analysis/MustExecute.cpp
@@ -152,7 +152,7 @@ static bool CanProveNotTakenFirstIteration(const BasicBlock *ExitBlock,
   if (!SimpleCst)
     return false;
   if (ExitBlock == BI->getSuccessor(0))
-    return SimpleCst->isZeroValue();
+    return SimpleCst->isNullValue();
   assert(ExitBlock == BI->getSuccessor(1) && "implied by above");
   return SimpleCst->isAllOnesValue();
 }
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index ae9ce311ec08f..b613fdeab0f8d 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -9641,7 +9641,7 @@ ScalarEvolution::ExitLimit ScalarEvolution::computeShiftCompareExitLimit(
   assert(Result->getType()->isIntegerTy(1) &&
          "Otherwise cannot be an operand to a branch instruction");
 
-  if (Result->isZeroValue()) {
+  if (Result->isNullValue()) {
     unsigned BitWidth = getTypeSizeInBits(RHS->getType());
     const SCEV *UpperBound =
         getConstant(getEffectiveSCEVType(RHS->getType()), BitWidth);
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 8761b7bcb51a2..2d78aa4be3455 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -1725,7 +1725,7 @@ static void computeKnownBitsFromOperator(const Operator *I,
 
       // Handle case when index is zero.
       Constant *CIndex = dyn_cast<Constant>(Index);
-      if (CIndex && CIndex->isZeroValue())
+      if (CIndex && CIndex->isNullValue())
         continue;
 
       if (StructType *STy = GTI.getStructTypeOrNull()) {
diff --git a/llvm/lib/CodeGen/ComplexDeinterleavingPass.cpp b/llvm/lib/CodeGen/ComplexDeinterleavingPass.cpp
index a169eb5e58c02..d6d2917e83a4d 100644
--- a/llvm/lib/CodeGen/ComplexDeinterleavingPass.cpp
+++ b/llvm/lib/CodeGen/ComplexDeinterleavingPass.cpp
@@ -2431,7 +2431,7 @@ void ComplexDeinterleavingGraph::processReductionSingle(
 
   Value *NewInit = nullptr;
   if (auto *C = dyn_cast<Constant>(Init)) {
-    if (C->isZeroValue())
+    if (C->isNullValue())
       NewInit = Constant::getNullValue(NewVTy);
   }
 
diff --git a/llvm/lib/CodeGen/InterleavedAccessPass.cpp b/llvm/lib/CodeGen/InterleavedAccessPass.cpp
index 24394addfa44a..9df7d53c63ff3 100644
--- a/llvm/lib/CodeGen/InterleavedAccessPass.cpp
+++ b/llvm/lib/CodeGen/InterleavedAccessPass.cpp
@@ -572,7 +572,7 @@ static void getGapMask(const Constant &MaskConst, unsigned Factor,
     bool AllZero = true;
     for (unsigned Idx = 0U; Idx < LeafMaskLen; ++Idx) {
       Constant *C = MaskConst.getAggregateElement(F + Idx * Factor);
-      if (!C->isZeroValue()) {
+      if (!C->isNullValue()) {
         AllZero = false;
         break;
       }
@@ -594,7 +594,7 @@ static std::pair<Value *, APInt> getMask(Value *WideMask, unsigned Factor,
       // Check if all the intrinsic arguments are the same, except those that
       // are zeros, which we mark as gaps in the gap mask.
       for (auto [Idx, Arg] : enumerate(IMI->args())) {
-        if (auto *C = dyn_cast<Constant>(Arg); C && C->isZeroValue()) {
+        if (auto *C = dyn_cast<Constant>(Arg); C && C->isNullValue()) {
           GapMask.clearBit(Idx);
           continue;
         }
diff --git a/llvm/lib/FuzzMutate/IRMutator.cpp b/llvm/lib/FuzzMutate/IRMutator.cpp
index d1abf78222c8c..702afe28503b2 100644
--- a/llvm/lib/FuzzMutate/IRMutator.cpp
+++ b/llvm/lib/FuzzMutate/IRMutator.cpp
@@ -338,7 +338,7 @@ void InstModificationIRStrategy::mutate(Instruction &Inst,
     // constant 0.
     Value *Operand = Inst.getOperand(0);
     if (Constant *C = dyn_cast<Constant>(Operand)) {
-      if (!C->isZeroValue()) {
+      if (!C->isNullValue()) {
         ShuffleItems = {0, 1};
       }
     }
diff --git a/llvm/lib/IR/AutoUpgrade.cpp b/llvm/lib/IR/AutoUpgrade.cpp
index 0463bacca350f..790ecb40dc87b 100644
--- a/llvm/lib/IR/AutoUpgrade.cpp
+++ b/llvm/lib/IR/AutoUpgrade.cpp
@@ -4871,7 +4871,7 @@ static void upgradeDbgIntrinsicToDbgRecord(StringRef Name, CallBase *CI) {
     if (CI->arg_size() == 4) {
       auto *Offset = dyn_cast_or_null<Constant>(CI->getArgOperand(1));
       // Nonzero offset dbg.values get dropped without a replacement.
-      if (!Offset || !Offset->isZeroValue())
+      if (!Offset || !Offset->isNullValue())
         return;
       VarOp = 2;
       ExprOp = 3;
@@ -5195,7 +5195,7 @@ void llvm::UpgradeIntrinsicCall(CallBase *CI, Function *NewFn) {
     assert(CI->arg_size() == 4);
     // Drop nonzero offsets instead of attempting to upgrade them.
     if (auto *Offset = dyn_cast_or_null<Constant>(CI->getArgOperand(1)))
-      if (Offset->isZeroValue()) {
+      if (Offset->isNullValue()) {
         NewCall = Builder.CreateCall(
             NewFn,
             {CI->getArgOperand(0), CI->getArgOperand(2), CI->getArgOperand(3)});
diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp
index 76152fe91a532..78ac276f4f3da 100644
--- a/llvm/lib/IR/Constants.cpp
+++ b/llvm/lib/IR/Constants.cpp
@@ -71,22 +71,6 @@ bool Constant::isNegativeZeroValue() const {
   return isNullValue();
 }
 
-// Return true iff this constant is positive zero (floating point), negative
-// zero (floating point), or a null value.
-bool Constant::isZeroValue() const {
-  // Floating point values have an explicit -0.0 value.
-  if (const ConstantFP *CFP = dyn_cast<ConstantFP>(this))
-    return CFP->isZero();
-
-  // Check for constant splat vectors of 1 values.
-  if (getType()->isVectorTy())
-    if (const auto *SplatCFP = dyn_cast_or_null<ConstantFP>(getSplatValue()))
-      return SplatCFP->isZero();
-
-  // Otherwise, just use +0.0.
-  return isNullValue();
-}
-
 bool Constant::isNullValue() const {
   // 0 is null.
   if (const ConstantInt *CI = dyn_cast<ConstantInt>(this))
@@ -752,7 +736,7 @@ static bool constantIsDead(const Constant *C, bool RemoveDeadUsers) {
     ReplaceableMetadataImpl::SalvageDebugInfo(*C);
     const_cast<Constant *>(C)->destroyConstant();
   }
-  
+
   return true;
 }
 
diff --git a/llvm/lib/IR/DebugInfo.cpp b/llvm/lib/IR/DebugInfo.cpp
index 1a83a29ec24e7..d27c3a9a1548a 100644
--- a/llvm/lib/IR/DebugInfo.cpp
+++ b/llvm/lib/IR/DebugInfo.cpp
@@ -2374,7 +2374,7 @@ static void setAssignmentTrackingModuleFlag(Module &M) {
 
 static bool getAssignmentTrackingModuleFlag(const Module &M) {
   Metadata *Value = M.getModuleFlag(AssignmentTrackingModuleFlag);
-  return Value && !cast<ConstantAsMetadata>(Value)->getValue()->isZeroValue();
+  return Value && !cast<ConstantAsMetadata>(Value)->getValue()->isNullValue();
 }
 
 bool llvm::isAssignmentTrackingEnabled(const Module &M) {
diff --git a/llvm/lib/Target/AArch64/AArch64PromoteConstant.cpp b/llvm/lib/Target/AArch64/AArch64PromoteConstant.cpp
index 3f45d55063b50..1a9ce869f5dfa 100644
--- a/llvm/lib/Target/AArch64/AArch64PromoteConstant.cpp
+++ b/llvm/lib/Target/AArch64/AArch64PromoteConstant.cpp
@@ -342,7 +342,7 @@ static bool shouldConvertImpl(const Constant *Cst) {
   // instances of Cst.
   // Ideally, we could promote this into a global and rematerialize the constant
   // when it was a bad idea.
-  if (Cst->isZeroValue())
+  if (Cst->isNullValue())
     return false;
 
   // Globals cannot be or contain scalable vectors.
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp b/llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp
index 376184e81c738..0ebe69de56fa9 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp
@@ -1454,7 +1454,7 @@ GCNTTIImpl::instCombineIntrinsic(InstCombiner &IC, IntrinsicInst &II) const {
     auto *BC = cast<ConstantInt>(II.getArgOperand(5));
     auto *RM = cast<ConstantInt>(II.getArgOperand(3));
     auto *BM = cast<ConstantInt>(II.getArgOperand(4));
-    if (BC->isZeroValue() || RM->getZExtValue() != 0xF ||
+    if (BC->isNullValue() || RM->getZExtValue() != 0xF ||
         BM->getZExtValue() != 0xF || isa<PoisonValue>(Old))
       break;
 
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp b/llvm/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp
index ed676c3fde2f8..4f85c49bff433 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp
@@ -618,7 +618,7 @@ static Value *promoteAllocaUserToVector(Instruction *Inst, const DataLayout &DL,
     Type *AccessTy = Inst->getType();
     TypeSize AccessSize = DL.getTypeStoreSize(AccessTy);
     if (Constant *CI = dyn_cast<Constant>(Index)) {
-      if (CI->isZeroValue() && AccessSize == VecStoreSize) {
+      if (CI->isNullValue() && AccessSize == VecStoreSize) {
         Inst->replaceAllUsesWith(
             Builder.CreateBitPreservingCastChain(DL, CurVal, AccessTy));
         return nullptr;
@@ -696,7 +696,7 @@ static Value *promoteAllocaUserToVector(Instruction *Inst, const DataLayout &DL,
     Type *AccessTy = Val->getType();
     TypeSize AccessSize = DL.getTypeStoreSize(AccessTy);
     if (Constant *CI = dyn_cast<Constant>(Index))
-      if (CI->isZeroValue() && AccessSize == VecStoreSize)
+      if (CI->isNullValue() && AccessSize == VecStoreSize)
         return Builder.CreateBitPreservingCastChain(DL, Val, AA.Vector.Ty);
 
     // Storing a subvector.
diff --git a/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp b/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp
index b1723f77b0e69..c4bf097e5a0f8 100644
--- a/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp
+++ b/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp
@@ -277,7 +277,7 @@ static Value *expandVecReduceAdd(CallInst *Orig, Intrinsic::ID IntrinsicId) {
   // Handle the initial start value for floating-point addition.
   if (IsFAdd) {
     Constant *StartValue = dyn_cast<Constant>(Orig->getOperand(0));
-    if (StartValue && !StartValue->isZeroValue())
+    if (StartValue && !StartValue->isNullValue())
       Sum = Builder.CreateFAdd(Sum, StartValue);
   }
 
diff --git a/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp b/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp
index 1a4be036d4d45..a626de6302b91 100644
--- a/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp
@@ -1172,7 +1172,7 @@ HexagonTargetLowering::LowerConstantPool(SDValue Op, SelectionDAG &DAG) const {
       assert(isPowerOf2_32(VecLen) &&
              "conversion only supported for pow2 VectorSize");
       for (unsigned i = 0; i < VecLen; ++i)
-        NewConst.push_back(IRB.getInt8(CV->getOperand(i)->isZeroValue()));
+        NewConst.push_back(IRB.getInt8(CV->getOperand(i)->isNullValue()));
 
       CVal = ConstantVector::get(NewConst);
       isVTi1Type = true;
diff --git a/llvm/lib/Target/Hexagon/HexagonVectorCombine.cpp b/llvm/lib/Target/Hexagon/HexagonVectorCombine.cpp
index 93cb628becc6e..1bb135a9e5c87 100644
--- a/llvm/lib/Target/Hexagon/HexagonVectorCombine.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonVectorCombine.cpp
@@ -3349,7 +3349,7 @@ auto HexagonVectorCombine::getConstInt(int Val, unsigned Width) const
 
 auto HexagonVectorCombine::isZero(const Value *Val) const -> bool {
   if (auto *C = dyn_cast<Constant>(Val))
-    return C->isZeroValue();
+    return C->isNullValue();
   return false;
 }
 
diff --git a/llvm/lib/Target/X86/X86LowerAMXType.cpp b/llvm/lib/Target/X86/X86LowerAMXType.cpp
index ff93971f81985..df42d1f4388ba 100644
--- a/llvm/lib/Target/X86/X86LowerAMXType.cpp
+++ b/llvm/lib/Target/X86/X86LowerAMXType.cpp
@@ -813,7 +813,7 @@ bool X86LowerAMXCast::optimizeAMXCastFromPhi(
       // might support const.
       if (isa<Constant>(IncValue)) {
         auto *IncConst = dyn_cast<Constant>(IncValue);
-        if (!isa<UndefValue>(IncValue) && !IncConst->isZeroValue())
+        if (!isa<UndefValue>(IncValue) && !IncConst->isNullValue())
           return false;
         Value *Row = nullptr, *Col = nullptr;
         std::tie(Row, Col) = getShape(OldPN);
diff --git a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp
index 37bf2b9c1a966..b80a514b68246 100644
--- a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp
+++ b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp
@@ -10050,7 +10050,7 @@ struct AAPotentialConstantValuesFloating : AAPotentialConstantValuesImpl {
     bool OnlyLeft = false, OnlyRight = false;
     if (C && *C && (*C)->isOneValue())
       OnlyLeft = true;
-    else if (C && *C && (*C)->isZeroValue())
+    else if (C && *C && (*C)->isNullValue())
       OnlyRight = true;
 
     bool LHSContainsUndef = false, RHSContainsUndef = false;
diff --git a/llvm/lib/Transforms/IPO/FunctionSpecialization.cpp b/llvm/lib/Transforms/IPO/FunctionSpecialization.cpp
index 1e1b198c60bef..5a53017f478d6 100644
--- a/llvm/lib/Transforms/IPO/FunctionSpecialization.cpp
+++ b/llvm/lib/Transforms/IPO/FunctionSpecialization.cpp
@@ -455,13 +455,13 @@ Constant *InstCostVisitor::visitSelectInst(SelectInst &I) {
   assert(LastVisited != KnownConstants.end() && "Invalid iterator!");
 
   if (I.getCondition() == LastVisited->first) {
-    Value *V = LastVisited->second->isZeroValue() ? I.getFalseValue()
+    Value *V = LastVisited->second->isNullValue() ? I.getFalseValue()
                                                   : I.getTrueValue();
     return findConstantFor(V);
   }
   if (Constant *Condition = findConstantFor(I.getCondition()))
     if ((I.getTrueValue() == LastVisited->first && Condition->isOneValue()) ||
-        (I.getFalseValue() == LastVisited->first && Condition->isZeroValue()))
+        (I.getFalseValue() == LastVisited->first && Condition->isNullValue()))
       return LastVisited->second;
   return nullptr;
 }
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index 13118b189dab0..3710e143913fa 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -2660,7 +2660,7 @@ Instruction *InstCombinerImpl::visitAnd(BinaryOperator &I) {
         Constant *Log2C1 = ConstantExpr::getExactLogBase2(C1);
         Constant *Cmp =
             ConstantFoldCompareInstOperands(ICmpInst::ICMP_ULT, Log2C3, C2, DL);
-        if (Cmp && Cmp->isZeroValue()) {
+        if (Cmp && Cmp->isNullValue()) {
           // iff C1,C3 is pow2 and Log2(C3) >= C2:
           // ((C1 >> X) << C2) & C3 -> X == (cttz(C1)+C2-cttz(C3)) ? C3 : 0
           Constant *ShlC = ConstantExpr::getAdd(C2, Log2C1);
@@ -532...
[truncated]

@llvmbot
Copy link
Member

llvmbot commented Feb 15, 2026

@llvm/pr-subscribers-llvm-analysis

Author: Shilei Tian (shiltian)

Changes

Constant::isZeroValue currently behaves same as Constant::isNullValue for
all types except floating-point, where it additionally returns true for negative
zero (-0.0). However, in practice, almost all callers operate on
integer/pointer types where the two are equivalent, and the few FP-relevant
callers have no meaningful dependence on the -0.0 behavior.

This PR removes isZeroValue to eliminate the confusing API surface. All
callers are changed to isNullValue with no test failures.

isZeroValue will be reintroduced in a future change with clearer semantics:
when null pointers may have non-zero bit patterns, isZeroValue will check for
bitwise-all-zeros, while isNullValue will check for the semantic null (which
may be non-zero).


Patch is 30.80 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/181521.diff

36 Files Affected:

  • (modified) clang/lib/CodeGen/CGDecl.cpp (+2-2)
  • (modified) clang/lib/CodeGen/ItaniumCXXABI.cpp (+1-1)
  • (modified) llvm/docs/ReleaseNotes.md (+6)
  • (modified) llvm/include/llvm/IR/Constant.h (-3)
  • (modified) llvm/lib/Analysis/BranchProbabilityInfo.cpp (+2-3)
  • (modified) llvm/lib/Analysis/ConstantFolding.cpp (+2-2)
  • (modified) llvm/lib/Analysis/Lint.cpp (+1-1)
  • (modified) llvm/lib/Analysis/Local.cpp (+1-1)
  • (modified) llvm/lib/Analysis/MustExecute.cpp (+1-1)
  • (modified) llvm/lib/Analysis/ScalarEvolution.cpp (+1-1)
  • (modified) llvm/lib/Analysis/ValueTracking.cpp (+1-1)
  • (modified) llvm/lib/CodeGen/ComplexDeinterleavingPass.cpp (+1-1)
  • (modified) llvm/lib/CodeGen/InterleavedAccessPass.cpp (+2-2)
  • (modified) llvm/lib/FuzzMutate/IRMutator.cpp (+1-1)
  • (modified) llvm/lib/IR/AutoUpgrade.cpp (+2-2)
  • (modified) llvm/lib/IR/Constants.cpp (+1-17)
  • (modified) llvm/lib/IR/DebugInfo.cpp (+1-1)
  • (modified) llvm/lib/Target/AArch64/AArch64PromoteConstant.cpp (+1-1)
  • (modified) llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp (+1-1)
  • (modified) llvm/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp (+2-2)
  • (modified) llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp (+1-1)
  • (modified) llvm/lib/Target/Hexagon/HexagonISelLowering.cpp (+1-1)
  • (modified) llvm/lib/Target/Hexagon/HexagonVectorCombine.cpp (+1-1)
  • (modified) llvm/lib/Target/X86/X86LowerAMXType.cpp (+1-1)
  • (modified) llvm/lib/Transforms/IPO/AttributorAttributes.cpp (+1-1)
  • (modified) llvm/lib/Transforms/IPO/FunctionSpecialization.cpp (+2-2)
  • (modified) llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp (+2-2)
  • (modified) llvm/lib/Transforms/InstCombine/InstructionCombining.cpp (+1-1)
  • (modified) llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp (+2-2)
  • (modified) llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp (+2-2)
  • (modified) llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp (+3-3)
  • (modified) llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp (+1-1)
  • (modified) llvm/unittests/Analysis/ValueLatticeTest.cpp (+9-9)
  • (modified) mlir/lib/Target/LLVMIR/ModuleTranslation.cpp (+1-1)
  • (modified) polly/lib/Support/SCEVValidator.cpp (+1-1)
  • (modified) polly/lib/Transform/ZoneAlgo.cpp (+1-1)
diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp
index 81697e02e8f3f..a7bd2f0470cc0 100644
--- a/clang/lib/CodeGen/CGDecl.cpp
+++ b/clang/lib/CodeGen/CGDecl.cpp
@@ -1070,7 +1070,7 @@ static llvm::Constant *constStructWithPadding(CodeGenModule &CGM,
       Values.push_back(patternOrZeroFor(CGM, isPattern, PadTy));
     }
     llvm::Constant *CurOp;
-    if (constant->isZeroValue())
+    if (constant->isNullValue())
       CurOp = llvm::Constant::getNullValue(STy->getElementType(i));
     else
       CurOp = cast<llvm::Constant>(constant->getAggregateElement(i));
@@ -2023,7 +2023,7 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) {
       D.mightBeUsableInConstantExpressions(getContext())) {
     assert(!capturedByInit && "constant init contains a capturing block?");
     constant = ConstantEmitter(*this).tryEmitAbstractForInitializer(D);
-    if (constant && !constant->isZeroValue() &&
+    if (constant && !constant->isNullValue() &&
         (trivialAutoVarInit !=
          LangOptions::TrivialAutoVarInitKind::Uninitialized)) {
       IsPattern isPattern =
diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp
index e3e071d827b92..759e512ed0719 100644
--- a/clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -916,7 +916,7 @@ static llvm::Constant *pointerAuthResignConstant(
     return nullptr;
 
   assert(CPA->getKey()->getZExtValue() == CurAuthInfo.getKey() &&
-         CPA->getAddrDiscriminator()->isZeroValue() &&
+         CPA->getAddrDiscriminator()->isNullValue() &&
          CPA->getDiscriminator() == CurAuthInfo.getDiscriminator() &&
          "unexpected key or discriminators");
 
diff --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md
index 6ddd4ec14804c..dffdb4291f87a 100644
--- a/llvm/docs/ReleaseNotes.md
+++ b/llvm/docs/ReleaseNotes.md
@@ -72,6 +72,12 @@ Changes to the LLVM IR
 Changes to LLVM infrastructure
 ------------------------------
 
+* Removed ``Constant::isZeroValue``. It was functionally identical to
+  ``Constant::isNullValue`` for all types except floating-point negative
+  zero. All callers should use ``isNullValue`` instead. ``isZeroValue``
+  will be reintroduced in the future with bitwise-all-zeros semantics
+  to support non-zero null pointers.
+
 * Removed TypePromoteFloat legalization from SelectionDAG
 
 Changes to building LLVM
diff --git a/llvm/include/llvm/IR/Constant.h b/llvm/include/llvm/IR/Constant.h
index e8ce453559ed7..82a570e8a1446 100644
--- a/llvm/include/llvm/IR/Constant.h
+++ b/llvm/include/llvm/IR/Constant.h
@@ -69,9 +69,6 @@ class Constant : public User {
   /// getZeroValueForNegation.
   LLVM_ABI bool isNegativeZeroValue() const;
 
-  /// Return true if the value is negative zero or null value.
-  LLVM_ABI bool isZeroValue() 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;
diff --git a/llvm/lib/Analysis/BranchProbabilityInfo.cpp b/llvm/lib/Analysis/BranchProbabilityInfo.cpp
index 4a99a40e0d2cc..412211eb72243 100644
--- a/llvm/lib/Analysis/BranchProbabilityInfo.cpp
+++ b/llvm/lib/Analysis/BranchProbabilityInfo.cpp
@@ -630,9 +630,8 @@ computeUnlikelySuccessors(const BasicBlock *BB, Loop *L,
           CI->getPredicate(), CmpLHSConst, CmpConst, DL);
       // If the result means we don't branch to the block then that block is
       // unlikely.
-      if (Result &&
-          ((Result->isZeroValue() && B == BI->getSuccessor(0)) ||
-           (Result->isOneValue() && B == BI->getSuccessor(1))))
+      if (Result && ((Result->isNullValue() && B == BI->getSuccessor(0)) ||
+                     (Result->isOneValue() && B == BI->getSuccessor(1))))
         UnlikelyBlocks.insert(B);
     }
   }
diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp
index ab060b1b9320a..04200d41dfab0 100644
--- a/llvm/lib/Analysis/ConstantFolding.cpp
+++ b/llvm/lib/Analysis/ConstantFolding.cpp
@@ -3133,7 +3133,7 @@ static Constant *ConstantFoldScalarCall1(StringRef Name,
       break;
 
     case Intrinsic::wasm_anytrue:
-      return Op->isZeroValue() ? ConstantInt::get(Ty, 0)
+      return Op->isNullValue() ? ConstantInt::get(Ty, 0)
                                : ConstantInt::get(Ty, 1);
 
     case Intrinsic::wasm_alltrue:
@@ -3142,7 +3142,7 @@ static Constant *ConstantFoldScalarCall1(StringRef Name,
       for (unsigned I = 0; I != E; ++I) {
         Constant *Elt = Op->getAggregateElement(I);
         // Return false as soon as we find a non-true element.
-        if (Elt && Elt->isZeroValue())
+        if (Elt && Elt->isNullValue())
           return ConstantInt::get(Ty, 0);
         // Bail as soon as we find an element we cannot prove to be true.
         if (!Elt || !isa<ConstantInt>(Elt))
diff --git a/llvm/lib/Analysis/Lint.cpp b/llvm/lib/Analysis/Lint.cpp
index 09fc47e622f75..26e78826848e7 100644
--- a/llvm/lib/Analysis/Lint.cpp
+++ b/llvm/lib/Analysis/Lint.cpp
@@ -553,7 +553,7 @@ static bool isZero(Value *V, const DataLayout &DL, DominatorTree *DT,
   if (!C)
     return false;
 
-  if (C->isZeroValue())
+  if (C->isNullValue())
     return true;
 
   // For a vector, KnownZero will only be true if all values are zero, so check
diff --git a/llvm/lib/Analysis/Local.cpp b/llvm/lib/Analysis/Local.cpp
index a668beabbb294..c08ed4b739d43 100644
--- a/llvm/lib/Analysis/Local.cpp
+++ b/llvm/lib/Analysis/Local.cpp
@@ -41,7 +41,7 @@ Value *llvm::emitGEPOffset(IRBuilderBase *Builder, const DataLayout &DL,
        ++i, ++GTI) {
     Value *Op = *i;
     if (Constant *OpC = dyn_cast<Constant>(Op)) {
-      if (OpC->isZeroValue())
+      if (OpC->isNullValue())
         continue;
 
       // Handle a struct index, which adds its field offset to the pointer.
diff --git a/llvm/lib/Analysis/MustExecute.cpp b/llvm/lib/Analysis/MustExecute.cpp
index fde6bbf9eb181..b08e1a4b2db0d 100644
--- a/llvm/lib/Analysis/MustExecute.cpp
+++ b/llvm/lib/Analysis/MustExecute.cpp
@@ -152,7 +152,7 @@ static bool CanProveNotTakenFirstIteration(const BasicBlock *ExitBlock,
   if (!SimpleCst)
     return false;
   if (ExitBlock == BI->getSuccessor(0))
-    return SimpleCst->isZeroValue();
+    return SimpleCst->isNullValue();
   assert(ExitBlock == BI->getSuccessor(1) && "implied by above");
   return SimpleCst->isAllOnesValue();
 }
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index ae9ce311ec08f..b613fdeab0f8d 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -9641,7 +9641,7 @@ ScalarEvolution::ExitLimit ScalarEvolution::computeShiftCompareExitLimit(
   assert(Result->getType()->isIntegerTy(1) &&
          "Otherwise cannot be an operand to a branch instruction");
 
-  if (Result->isZeroValue()) {
+  if (Result->isNullValue()) {
     unsigned BitWidth = getTypeSizeInBits(RHS->getType());
     const SCEV *UpperBound =
         getConstant(getEffectiveSCEVType(RHS->getType()), BitWidth);
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 8761b7bcb51a2..2d78aa4be3455 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -1725,7 +1725,7 @@ static void computeKnownBitsFromOperator(const Operator *I,
 
       // Handle case when index is zero.
       Constant *CIndex = dyn_cast<Constant>(Index);
-      if (CIndex && CIndex->isZeroValue())
+      if (CIndex && CIndex->isNullValue())
         continue;
 
       if (StructType *STy = GTI.getStructTypeOrNull()) {
diff --git a/llvm/lib/CodeGen/ComplexDeinterleavingPass.cpp b/llvm/lib/CodeGen/ComplexDeinterleavingPass.cpp
index a169eb5e58c02..d6d2917e83a4d 100644
--- a/llvm/lib/CodeGen/ComplexDeinterleavingPass.cpp
+++ b/llvm/lib/CodeGen/ComplexDeinterleavingPass.cpp
@@ -2431,7 +2431,7 @@ void ComplexDeinterleavingGraph::processReductionSingle(
 
   Value *NewInit = nullptr;
   if (auto *C = dyn_cast<Constant>(Init)) {
-    if (C->isZeroValue())
+    if (C->isNullValue())
       NewInit = Constant::getNullValue(NewVTy);
   }
 
diff --git a/llvm/lib/CodeGen/InterleavedAccessPass.cpp b/llvm/lib/CodeGen/InterleavedAccessPass.cpp
index 24394addfa44a..9df7d53c63ff3 100644
--- a/llvm/lib/CodeGen/InterleavedAccessPass.cpp
+++ b/llvm/lib/CodeGen/InterleavedAccessPass.cpp
@@ -572,7 +572,7 @@ static void getGapMask(const Constant &MaskConst, unsigned Factor,
     bool AllZero = true;
     for (unsigned Idx = 0U; Idx < LeafMaskLen; ++Idx) {
       Constant *C = MaskConst.getAggregateElement(F + Idx * Factor);
-      if (!C->isZeroValue()) {
+      if (!C->isNullValue()) {
         AllZero = false;
         break;
       }
@@ -594,7 +594,7 @@ static std::pair<Value *, APInt> getMask(Value *WideMask, unsigned Factor,
       // Check if all the intrinsic arguments are the same, except those that
       // are zeros, which we mark as gaps in the gap mask.
       for (auto [Idx, Arg] : enumerate(IMI->args())) {
-        if (auto *C = dyn_cast<Constant>(Arg); C && C->isZeroValue()) {
+        if (auto *C = dyn_cast<Constant>(Arg); C && C->isNullValue()) {
           GapMask.clearBit(Idx);
           continue;
         }
diff --git a/llvm/lib/FuzzMutate/IRMutator.cpp b/llvm/lib/FuzzMutate/IRMutator.cpp
index d1abf78222c8c..702afe28503b2 100644
--- a/llvm/lib/FuzzMutate/IRMutator.cpp
+++ b/llvm/lib/FuzzMutate/IRMutator.cpp
@@ -338,7 +338,7 @@ void InstModificationIRStrategy::mutate(Instruction &Inst,
     // constant 0.
     Value *Operand = Inst.getOperand(0);
     if (Constant *C = dyn_cast<Constant>(Operand)) {
-      if (!C->isZeroValue()) {
+      if (!C->isNullValue()) {
         ShuffleItems = {0, 1};
       }
     }
diff --git a/llvm/lib/IR/AutoUpgrade.cpp b/llvm/lib/IR/AutoUpgrade.cpp
index 0463bacca350f..790ecb40dc87b 100644
--- a/llvm/lib/IR/AutoUpgrade.cpp
+++ b/llvm/lib/IR/AutoUpgrade.cpp
@@ -4871,7 +4871,7 @@ static void upgradeDbgIntrinsicToDbgRecord(StringRef Name, CallBase *CI) {
     if (CI->arg_size() == 4) {
       auto *Offset = dyn_cast_or_null<Constant>(CI->getArgOperand(1));
       // Nonzero offset dbg.values get dropped without a replacement.
-      if (!Offset || !Offset->isZeroValue())
+      if (!Offset || !Offset->isNullValue())
         return;
       VarOp = 2;
       ExprOp = 3;
@@ -5195,7 +5195,7 @@ void llvm::UpgradeIntrinsicCall(CallBase *CI, Function *NewFn) {
     assert(CI->arg_size() == 4);
     // Drop nonzero offsets instead of attempting to upgrade them.
     if (auto *Offset = dyn_cast_or_null<Constant>(CI->getArgOperand(1)))
-      if (Offset->isZeroValue()) {
+      if (Offset->isNullValue()) {
         NewCall = Builder.CreateCall(
             NewFn,
             {CI->getArgOperand(0), CI->getArgOperand(2), CI->getArgOperand(3)});
diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp
index 76152fe91a532..78ac276f4f3da 100644
--- a/llvm/lib/IR/Constants.cpp
+++ b/llvm/lib/IR/Constants.cpp
@@ -71,22 +71,6 @@ bool Constant::isNegativeZeroValue() const {
   return isNullValue();
 }
 
-// Return true iff this constant is positive zero (floating point), negative
-// zero (floating point), or a null value.
-bool Constant::isZeroValue() const {
-  // Floating point values have an explicit -0.0 value.
-  if (const ConstantFP *CFP = dyn_cast<ConstantFP>(this))
-    return CFP->isZero();
-
-  // Check for constant splat vectors of 1 values.
-  if (getType()->isVectorTy())
-    if (const auto *SplatCFP = dyn_cast_or_null<ConstantFP>(getSplatValue()))
-      return SplatCFP->isZero();
-
-  // Otherwise, just use +0.0.
-  return isNullValue();
-}
-
 bool Constant::isNullValue() const {
   // 0 is null.
   if (const ConstantInt *CI = dyn_cast<ConstantInt>(this))
@@ -752,7 +736,7 @@ static bool constantIsDead(const Constant *C, bool RemoveDeadUsers) {
     ReplaceableMetadataImpl::SalvageDebugInfo(*C);
     const_cast<Constant *>(C)->destroyConstant();
   }
-  
+
   return true;
 }
 
diff --git a/llvm/lib/IR/DebugInfo.cpp b/llvm/lib/IR/DebugInfo.cpp
index 1a83a29ec24e7..d27c3a9a1548a 100644
--- a/llvm/lib/IR/DebugInfo.cpp
+++ b/llvm/lib/IR/DebugInfo.cpp
@@ -2374,7 +2374,7 @@ static void setAssignmentTrackingModuleFlag(Module &M) {
 
 static bool getAssignmentTrackingModuleFlag(const Module &M) {
   Metadata *Value = M.getModuleFlag(AssignmentTrackingModuleFlag);
-  return Value && !cast<ConstantAsMetadata>(Value)->getValue()->isZeroValue();
+  return Value && !cast<ConstantAsMetadata>(Value)->getValue()->isNullValue();
 }
 
 bool llvm::isAssignmentTrackingEnabled(const Module &M) {
diff --git a/llvm/lib/Target/AArch64/AArch64PromoteConstant.cpp b/llvm/lib/Target/AArch64/AArch64PromoteConstant.cpp
index 3f45d55063b50..1a9ce869f5dfa 100644
--- a/llvm/lib/Target/AArch64/AArch64PromoteConstant.cpp
+++ b/llvm/lib/Target/AArch64/AArch64PromoteConstant.cpp
@@ -342,7 +342,7 @@ static bool shouldConvertImpl(const Constant *Cst) {
   // instances of Cst.
   // Ideally, we could promote this into a global and rematerialize the constant
   // when it was a bad idea.
-  if (Cst->isZeroValue())
+  if (Cst->isNullValue())
     return false;
 
   // Globals cannot be or contain scalable vectors.
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp b/llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp
index 376184e81c738..0ebe69de56fa9 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp
@@ -1454,7 +1454,7 @@ GCNTTIImpl::instCombineIntrinsic(InstCombiner &IC, IntrinsicInst &II) const {
     auto *BC = cast<ConstantInt>(II.getArgOperand(5));
     auto *RM = cast<ConstantInt>(II.getArgOperand(3));
     auto *BM = cast<ConstantInt>(II.getArgOperand(4));
-    if (BC->isZeroValue() || RM->getZExtValue() != 0xF ||
+    if (BC->isNullValue() || RM->getZExtValue() != 0xF ||
         BM->getZExtValue() != 0xF || isa<PoisonValue>(Old))
       break;
 
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp b/llvm/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp
index ed676c3fde2f8..4f85c49bff433 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp
@@ -618,7 +618,7 @@ static Value *promoteAllocaUserToVector(Instruction *Inst, const DataLayout &DL,
     Type *AccessTy = Inst->getType();
     TypeSize AccessSize = DL.getTypeStoreSize(AccessTy);
     if (Constant *CI = dyn_cast<Constant>(Index)) {
-      if (CI->isZeroValue() && AccessSize == VecStoreSize) {
+      if (CI->isNullValue() && AccessSize == VecStoreSize) {
         Inst->replaceAllUsesWith(
             Builder.CreateBitPreservingCastChain(DL, CurVal, AccessTy));
         return nullptr;
@@ -696,7 +696,7 @@ static Value *promoteAllocaUserToVector(Instruction *Inst, const DataLayout &DL,
     Type *AccessTy = Val->getType();
     TypeSize AccessSize = DL.getTypeStoreSize(AccessTy);
     if (Constant *CI = dyn_cast<Constant>(Index))
-      if (CI->isZeroValue() && AccessSize == VecStoreSize)
+      if (CI->isNullValue() && AccessSize == VecStoreSize)
         return Builder.CreateBitPreservingCastChain(DL, Val, AA.Vector.Ty);
 
     // Storing a subvector.
diff --git a/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp b/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp
index b1723f77b0e69..c4bf097e5a0f8 100644
--- a/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp
+++ b/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp
@@ -277,7 +277,7 @@ static Value *expandVecReduceAdd(CallInst *Orig, Intrinsic::ID IntrinsicId) {
   // Handle the initial start value for floating-point addition.
   if (IsFAdd) {
     Constant *StartValue = dyn_cast<Constant>(Orig->getOperand(0));
-    if (StartValue && !StartValue->isZeroValue())
+    if (StartValue && !StartValue->isNullValue())
       Sum = Builder.CreateFAdd(Sum, StartValue);
   }
 
diff --git a/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp b/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp
index 1a4be036d4d45..a626de6302b91 100644
--- a/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp
@@ -1172,7 +1172,7 @@ HexagonTargetLowering::LowerConstantPool(SDValue Op, SelectionDAG &DAG) const {
       assert(isPowerOf2_32(VecLen) &&
              "conversion only supported for pow2 VectorSize");
       for (unsigned i = 0; i < VecLen; ++i)
-        NewConst.push_back(IRB.getInt8(CV->getOperand(i)->isZeroValue()));
+        NewConst.push_back(IRB.getInt8(CV->getOperand(i)->isNullValue()));
 
       CVal = ConstantVector::get(NewConst);
       isVTi1Type = true;
diff --git a/llvm/lib/Target/Hexagon/HexagonVectorCombine.cpp b/llvm/lib/Target/Hexagon/HexagonVectorCombine.cpp
index 93cb628becc6e..1bb135a9e5c87 100644
--- a/llvm/lib/Target/Hexagon/HexagonVectorCombine.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonVectorCombine.cpp
@@ -3349,7 +3349,7 @@ auto HexagonVectorCombine::getConstInt(int Val, unsigned Width) const
 
 auto HexagonVectorCombine::isZero(const Value *Val) const -> bool {
   if (auto *C = dyn_cast<Constant>(Val))
-    return C->isZeroValue();
+    return C->isNullValue();
   return false;
 }
 
diff --git a/llvm/lib/Target/X86/X86LowerAMXType.cpp b/llvm/lib/Target/X86/X86LowerAMXType.cpp
index ff93971f81985..df42d1f4388ba 100644
--- a/llvm/lib/Target/X86/X86LowerAMXType.cpp
+++ b/llvm/lib/Target/X86/X86LowerAMXType.cpp
@@ -813,7 +813,7 @@ bool X86LowerAMXCast::optimizeAMXCastFromPhi(
       // might support const.
       if (isa<Constant>(IncValue)) {
         auto *IncConst = dyn_cast<Constant>(IncValue);
-        if (!isa<UndefValue>(IncValue) && !IncConst->isZeroValue())
+        if (!isa<UndefValue>(IncValue) && !IncConst->isNullValue())
           return false;
         Value *Row = nullptr, *Col = nullptr;
         std::tie(Row, Col) = getShape(OldPN);
diff --git a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp
index 37bf2b9c1a966..b80a514b68246 100644
--- a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp
+++ b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp
@@ -10050,7 +10050,7 @@ struct AAPotentialConstantValuesFloating : AAPotentialConstantValuesImpl {
     bool OnlyLeft = false, OnlyRight = false;
     if (C && *C && (*C)->isOneValue())
       OnlyLeft = true;
-    else if (C && *C && (*C)->isZeroValue())
+    else if (C && *C && (*C)->isNullValue())
       OnlyRight = true;
 
     bool LHSContainsUndef = false, RHSContainsUndef = false;
diff --git a/llvm/lib/Transforms/IPO/FunctionSpecialization.cpp b/llvm/lib/Transforms/IPO/FunctionSpecialization.cpp
index 1e1b198c60bef..5a53017f478d6 100644
--- a/llvm/lib/Transforms/IPO/FunctionSpecialization.cpp
+++ b/llvm/lib/Transforms/IPO/FunctionSpecialization.cpp
@@ -455,13 +455,13 @@ Constant *InstCostVisitor::visitSelectInst(SelectInst &I) {
   assert(LastVisited != KnownConstants.end() && "Invalid iterator!");
 
   if (I.getCondition() == LastVisited->first) {
-    Value *V = LastVisited->second->isZeroValue() ? I.getFalseValue()
+    Value *V = LastVisited->second->isNullValue() ? I.getFalseValue()
                                                   : I.getTrueValue();
     return findConstantFor(V);
   }
   if (Constant *Condition = findConstantFor(I.getCondition()))
     if ((I.getTrueValue() == LastVisited->first && Condition->isOneValue()) ||
-        (I.getFalseValue() == LastVisited->first && Condition->isZeroValue()))
+        (I.getFalseValue() == LastVisited->first && Condition->isNullValue()))
       return LastVisited->second;
   return nullptr;
 }
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index 13118b189dab0..3710e143913fa 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -2660,7 +2660,7 @@ Instruction *InstCombinerImpl::visitAnd(BinaryOperator &I) {
         Constant *Log2C1 = ConstantExpr::getExactLogBase2(C1);
         Constant *Cmp =
             ConstantFoldCompareInstOperands(ICmpInst::ICMP_ULT, Log2C3, C2, DL);
-        if (Cmp && Cmp->isZeroValue()) {
+        if (Cmp && Cmp->isNullValue()) {
           // iff C1,C3 is pow2 and Log2(C3) >= C2:
           // ((C1 >> X) << C2) & C3 -> X == (cttz(C1)+C2-cttz(C3)) ? C3 : 0
           Constant *ShlC = ConstantExpr::getAdd(C2, Log2C1);
@@ -532...
[truncated]

@llvmbot
Copy link
Member

llvmbot commented Feb 15, 2026

@llvm/pr-subscribers-backend-hexagon

Author: Shilei Tian (shiltian)

Changes

Constant::isZeroValue currently behaves same as Constant::isNullValue for
all types except floating-point, where it additionally returns true for negative
zero (-0.0). However, in practice, almost all callers operate on
integer/pointer types where the two are equivalent, and the few FP-relevant
callers have no meaningful dependence on the -0.0 behavior.

This PR removes isZeroValue to eliminate the confusing API surface. All
callers are changed to isNullValue with no test failures.

isZeroValue will be reintroduced in a future change with clearer semantics:
when null pointers may have non-zero bit patterns, isZeroValue will check for
bitwise-all-zeros, while isNullValue will check for the semantic null (which
may be non-zero).


Patch is 30.80 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/181521.diff

36 Files Affected:

  • (modified) clang/lib/CodeGen/CGDecl.cpp (+2-2)
  • (modified) clang/lib/CodeGen/ItaniumCXXABI.cpp (+1-1)
  • (modified) llvm/docs/ReleaseNotes.md (+6)
  • (modified) llvm/include/llvm/IR/Constant.h (-3)
  • (modified) llvm/lib/Analysis/BranchProbabilityInfo.cpp (+2-3)
  • (modified) llvm/lib/Analysis/ConstantFolding.cpp (+2-2)
  • (modified) llvm/lib/Analysis/Lint.cpp (+1-1)
  • (modified) llvm/lib/Analysis/Local.cpp (+1-1)
  • (modified) llvm/lib/Analysis/MustExecute.cpp (+1-1)
  • (modified) llvm/lib/Analysis/ScalarEvolution.cpp (+1-1)
  • (modified) llvm/lib/Analysis/ValueTracking.cpp (+1-1)
  • (modified) llvm/lib/CodeGen/ComplexDeinterleavingPass.cpp (+1-1)
  • (modified) llvm/lib/CodeGen/InterleavedAccessPass.cpp (+2-2)
  • (modified) llvm/lib/FuzzMutate/IRMutator.cpp (+1-1)
  • (modified) llvm/lib/IR/AutoUpgrade.cpp (+2-2)
  • (modified) llvm/lib/IR/Constants.cpp (+1-17)
  • (modified) llvm/lib/IR/DebugInfo.cpp (+1-1)
  • (modified) llvm/lib/Target/AArch64/AArch64PromoteConstant.cpp (+1-1)
  • (modified) llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp (+1-1)
  • (modified) llvm/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp (+2-2)
  • (modified) llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp (+1-1)
  • (modified) llvm/lib/Target/Hexagon/HexagonISelLowering.cpp (+1-1)
  • (modified) llvm/lib/Target/Hexagon/HexagonVectorCombine.cpp (+1-1)
  • (modified) llvm/lib/Target/X86/X86LowerAMXType.cpp (+1-1)
  • (modified) llvm/lib/Transforms/IPO/AttributorAttributes.cpp (+1-1)
  • (modified) llvm/lib/Transforms/IPO/FunctionSpecialization.cpp (+2-2)
  • (modified) llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp (+2-2)
  • (modified) llvm/lib/Transforms/InstCombine/InstructionCombining.cpp (+1-1)
  • (modified) llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp (+2-2)
  • (modified) llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp (+2-2)
  • (modified) llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp (+3-3)
  • (modified) llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp (+1-1)
  • (modified) llvm/unittests/Analysis/ValueLatticeTest.cpp (+9-9)
  • (modified) mlir/lib/Target/LLVMIR/ModuleTranslation.cpp (+1-1)
  • (modified) polly/lib/Support/SCEVValidator.cpp (+1-1)
  • (modified) polly/lib/Transform/ZoneAlgo.cpp (+1-1)
diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp
index 81697e02e8f3f..a7bd2f0470cc0 100644
--- a/clang/lib/CodeGen/CGDecl.cpp
+++ b/clang/lib/CodeGen/CGDecl.cpp
@@ -1070,7 +1070,7 @@ static llvm::Constant *constStructWithPadding(CodeGenModule &CGM,
       Values.push_back(patternOrZeroFor(CGM, isPattern, PadTy));
     }
     llvm::Constant *CurOp;
-    if (constant->isZeroValue())
+    if (constant->isNullValue())
       CurOp = llvm::Constant::getNullValue(STy->getElementType(i));
     else
       CurOp = cast<llvm::Constant>(constant->getAggregateElement(i));
@@ -2023,7 +2023,7 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) {
       D.mightBeUsableInConstantExpressions(getContext())) {
     assert(!capturedByInit && "constant init contains a capturing block?");
     constant = ConstantEmitter(*this).tryEmitAbstractForInitializer(D);
-    if (constant && !constant->isZeroValue() &&
+    if (constant && !constant->isNullValue() &&
         (trivialAutoVarInit !=
          LangOptions::TrivialAutoVarInitKind::Uninitialized)) {
       IsPattern isPattern =
diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp
index e3e071d827b92..759e512ed0719 100644
--- a/clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -916,7 +916,7 @@ static llvm::Constant *pointerAuthResignConstant(
     return nullptr;
 
   assert(CPA->getKey()->getZExtValue() == CurAuthInfo.getKey() &&
-         CPA->getAddrDiscriminator()->isZeroValue() &&
+         CPA->getAddrDiscriminator()->isNullValue() &&
          CPA->getDiscriminator() == CurAuthInfo.getDiscriminator() &&
          "unexpected key or discriminators");
 
diff --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md
index 6ddd4ec14804c..dffdb4291f87a 100644
--- a/llvm/docs/ReleaseNotes.md
+++ b/llvm/docs/ReleaseNotes.md
@@ -72,6 +72,12 @@ Changes to the LLVM IR
 Changes to LLVM infrastructure
 ------------------------------
 
+* Removed ``Constant::isZeroValue``. It was functionally identical to
+  ``Constant::isNullValue`` for all types except floating-point negative
+  zero. All callers should use ``isNullValue`` instead. ``isZeroValue``
+  will be reintroduced in the future with bitwise-all-zeros semantics
+  to support non-zero null pointers.
+
 * Removed TypePromoteFloat legalization from SelectionDAG
 
 Changes to building LLVM
diff --git a/llvm/include/llvm/IR/Constant.h b/llvm/include/llvm/IR/Constant.h
index e8ce453559ed7..82a570e8a1446 100644
--- a/llvm/include/llvm/IR/Constant.h
+++ b/llvm/include/llvm/IR/Constant.h
@@ -69,9 +69,6 @@ class Constant : public User {
   /// getZeroValueForNegation.
   LLVM_ABI bool isNegativeZeroValue() const;
 
-  /// Return true if the value is negative zero or null value.
-  LLVM_ABI bool isZeroValue() 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;
diff --git a/llvm/lib/Analysis/BranchProbabilityInfo.cpp b/llvm/lib/Analysis/BranchProbabilityInfo.cpp
index 4a99a40e0d2cc..412211eb72243 100644
--- a/llvm/lib/Analysis/BranchProbabilityInfo.cpp
+++ b/llvm/lib/Analysis/BranchProbabilityInfo.cpp
@@ -630,9 +630,8 @@ computeUnlikelySuccessors(const BasicBlock *BB, Loop *L,
           CI->getPredicate(), CmpLHSConst, CmpConst, DL);
       // If the result means we don't branch to the block then that block is
       // unlikely.
-      if (Result &&
-          ((Result->isZeroValue() && B == BI->getSuccessor(0)) ||
-           (Result->isOneValue() && B == BI->getSuccessor(1))))
+      if (Result && ((Result->isNullValue() && B == BI->getSuccessor(0)) ||
+                     (Result->isOneValue() && B == BI->getSuccessor(1))))
         UnlikelyBlocks.insert(B);
     }
   }
diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp
index ab060b1b9320a..04200d41dfab0 100644
--- a/llvm/lib/Analysis/ConstantFolding.cpp
+++ b/llvm/lib/Analysis/ConstantFolding.cpp
@@ -3133,7 +3133,7 @@ static Constant *ConstantFoldScalarCall1(StringRef Name,
       break;
 
     case Intrinsic::wasm_anytrue:
-      return Op->isZeroValue() ? ConstantInt::get(Ty, 0)
+      return Op->isNullValue() ? ConstantInt::get(Ty, 0)
                                : ConstantInt::get(Ty, 1);
 
     case Intrinsic::wasm_alltrue:
@@ -3142,7 +3142,7 @@ static Constant *ConstantFoldScalarCall1(StringRef Name,
       for (unsigned I = 0; I != E; ++I) {
         Constant *Elt = Op->getAggregateElement(I);
         // Return false as soon as we find a non-true element.
-        if (Elt && Elt->isZeroValue())
+        if (Elt && Elt->isNullValue())
           return ConstantInt::get(Ty, 0);
         // Bail as soon as we find an element we cannot prove to be true.
         if (!Elt || !isa<ConstantInt>(Elt))
diff --git a/llvm/lib/Analysis/Lint.cpp b/llvm/lib/Analysis/Lint.cpp
index 09fc47e622f75..26e78826848e7 100644
--- a/llvm/lib/Analysis/Lint.cpp
+++ b/llvm/lib/Analysis/Lint.cpp
@@ -553,7 +553,7 @@ static bool isZero(Value *V, const DataLayout &DL, DominatorTree *DT,
   if (!C)
     return false;
 
-  if (C->isZeroValue())
+  if (C->isNullValue())
     return true;
 
   // For a vector, KnownZero will only be true if all values are zero, so check
diff --git a/llvm/lib/Analysis/Local.cpp b/llvm/lib/Analysis/Local.cpp
index a668beabbb294..c08ed4b739d43 100644
--- a/llvm/lib/Analysis/Local.cpp
+++ b/llvm/lib/Analysis/Local.cpp
@@ -41,7 +41,7 @@ Value *llvm::emitGEPOffset(IRBuilderBase *Builder, const DataLayout &DL,
        ++i, ++GTI) {
     Value *Op = *i;
     if (Constant *OpC = dyn_cast<Constant>(Op)) {
-      if (OpC->isZeroValue())
+      if (OpC->isNullValue())
         continue;
 
       // Handle a struct index, which adds its field offset to the pointer.
diff --git a/llvm/lib/Analysis/MustExecute.cpp b/llvm/lib/Analysis/MustExecute.cpp
index fde6bbf9eb181..b08e1a4b2db0d 100644
--- a/llvm/lib/Analysis/MustExecute.cpp
+++ b/llvm/lib/Analysis/MustExecute.cpp
@@ -152,7 +152,7 @@ static bool CanProveNotTakenFirstIteration(const BasicBlock *ExitBlock,
   if (!SimpleCst)
     return false;
   if (ExitBlock == BI->getSuccessor(0))
-    return SimpleCst->isZeroValue();
+    return SimpleCst->isNullValue();
   assert(ExitBlock == BI->getSuccessor(1) && "implied by above");
   return SimpleCst->isAllOnesValue();
 }
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index ae9ce311ec08f..b613fdeab0f8d 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -9641,7 +9641,7 @@ ScalarEvolution::ExitLimit ScalarEvolution::computeShiftCompareExitLimit(
   assert(Result->getType()->isIntegerTy(1) &&
          "Otherwise cannot be an operand to a branch instruction");
 
-  if (Result->isZeroValue()) {
+  if (Result->isNullValue()) {
     unsigned BitWidth = getTypeSizeInBits(RHS->getType());
     const SCEV *UpperBound =
         getConstant(getEffectiveSCEVType(RHS->getType()), BitWidth);
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 8761b7bcb51a2..2d78aa4be3455 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -1725,7 +1725,7 @@ static void computeKnownBitsFromOperator(const Operator *I,
 
       // Handle case when index is zero.
       Constant *CIndex = dyn_cast<Constant>(Index);
-      if (CIndex && CIndex->isZeroValue())
+      if (CIndex && CIndex->isNullValue())
         continue;
 
       if (StructType *STy = GTI.getStructTypeOrNull()) {
diff --git a/llvm/lib/CodeGen/ComplexDeinterleavingPass.cpp b/llvm/lib/CodeGen/ComplexDeinterleavingPass.cpp
index a169eb5e58c02..d6d2917e83a4d 100644
--- a/llvm/lib/CodeGen/ComplexDeinterleavingPass.cpp
+++ b/llvm/lib/CodeGen/ComplexDeinterleavingPass.cpp
@@ -2431,7 +2431,7 @@ void ComplexDeinterleavingGraph::processReductionSingle(
 
   Value *NewInit = nullptr;
   if (auto *C = dyn_cast<Constant>(Init)) {
-    if (C->isZeroValue())
+    if (C->isNullValue())
       NewInit = Constant::getNullValue(NewVTy);
   }
 
diff --git a/llvm/lib/CodeGen/InterleavedAccessPass.cpp b/llvm/lib/CodeGen/InterleavedAccessPass.cpp
index 24394addfa44a..9df7d53c63ff3 100644
--- a/llvm/lib/CodeGen/InterleavedAccessPass.cpp
+++ b/llvm/lib/CodeGen/InterleavedAccessPass.cpp
@@ -572,7 +572,7 @@ static void getGapMask(const Constant &MaskConst, unsigned Factor,
     bool AllZero = true;
     for (unsigned Idx = 0U; Idx < LeafMaskLen; ++Idx) {
       Constant *C = MaskConst.getAggregateElement(F + Idx * Factor);
-      if (!C->isZeroValue()) {
+      if (!C->isNullValue()) {
         AllZero = false;
         break;
       }
@@ -594,7 +594,7 @@ static std::pair<Value *, APInt> getMask(Value *WideMask, unsigned Factor,
       // Check if all the intrinsic arguments are the same, except those that
       // are zeros, which we mark as gaps in the gap mask.
       for (auto [Idx, Arg] : enumerate(IMI->args())) {
-        if (auto *C = dyn_cast<Constant>(Arg); C && C->isZeroValue()) {
+        if (auto *C = dyn_cast<Constant>(Arg); C && C->isNullValue()) {
           GapMask.clearBit(Idx);
           continue;
         }
diff --git a/llvm/lib/FuzzMutate/IRMutator.cpp b/llvm/lib/FuzzMutate/IRMutator.cpp
index d1abf78222c8c..702afe28503b2 100644
--- a/llvm/lib/FuzzMutate/IRMutator.cpp
+++ b/llvm/lib/FuzzMutate/IRMutator.cpp
@@ -338,7 +338,7 @@ void InstModificationIRStrategy::mutate(Instruction &Inst,
     // constant 0.
     Value *Operand = Inst.getOperand(0);
     if (Constant *C = dyn_cast<Constant>(Operand)) {
-      if (!C->isZeroValue()) {
+      if (!C->isNullValue()) {
         ShuffleItems = {0, 1};
       }
     }
diff --git a/llvm/lib/IR/AutoUpgrade.cpp b/llvm/lib/IR/AutoUpgrade.cpp
index 0463bacca350f..790ecb40dc87b 100644
--- a/llvm/lib/IR/AutoUpgrade.cpp
+++ b/llvm/lib/IR/AutoUpgrade.cpp
@@ -4871,7 +4871,7 @@ static void upgradeDbgIntrinsicToDbgRecord(StringRef Name, CallBase *CI) {
     if (CI->arg_size() == 4) {
       auto *Offset = dyn_cast_or_null<Constant>(CI->getArgOperand(1));
       // Nonzero offset dbg.values get dropped without a replacement.
-      if (!Offset || !Offset->isZeroValue())
+      if (!Offset || !Offset->isNullValue())
         return;
       VarOp = 2;
       ExprOp = 3;
@@ -5195,7 +5195,7 @@ void llvm::UpgradeIntrinsicCall(CallBase *CI, Function *NewFn) {
     assert(CI->arg_size() == 4);
     // Drop nonzero offsets instead of attempting to upgrade them.
     if (auto *Offset = dyn_cast_or_null<Constant>(CI->getArgOperand(1)))
-      if (Offset->isZeroValue()) {
+      if (Offset->isNullValue()) {
         NewCall = Builder.CreateCall(
             NewFn,
             {CI->getArgOperand(0), CI->getArgOperand(2), CI->getArgOperand(3)});
diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp
index 76152fe91a532..78ac276f4f3da 100644
--- a/llvm/lib/IR/Constants.cpp
+++ b/llvm/lib/IR/Constants.cpp
@@ -71,22 +71,6 @@ bool Constant::isNegativeZeroValue() const {
   return isNullValue();
 }
 
-// Return true iff this constant is positive zero (floating point), negative
-// zero (floating point), or a null value.
-bool Constant::isZeroValue() const {
-  // Floating point values have an explicit -0.0 value.
-  if (const ConstantFP *CFP = dyn_cast<ConstantFP>(this))
-    return CFP->isZero();
-
-  // Check for constant splat vectors of 1 values.
-  if (getType()->isVectorTy())
-    if (const auto *SplatCFP = dyn_cast_or_null<ConstantFP>(getSplatValue()))
-      return SplatCFP->isZero();
-
-  // Otherwise, just use +0.0.
-  return isNullValue();
-}
-
 bool Constant::isNullValue() const {
   // 0 is null.
   if (const ConstantInt *CI = dyn_cast<ConstantInt>(this))
@@ -752,7 +736,7 @@ static bool constantIsDead(const Constant *C, bool RemoveDeadUsers) {
     ReplaceableMetadataImpl::SalvageDebugInfo(*C);
     const_cast<Constant *>(C)->destroyConstant();
   }
-  
+
   return true;
 }
 
diff --git a/llvm/lib/IR/DebugInfo.cpp b/llvm/lib/IR/DebugInfo.cpp
index 1a83a29ec24e7..d27c3a9a1548a 100644
--- a/llvm/lib/IR/DebugInfo.cpp
+++ b/llvm/lib/IR/DebugInfo.cpp
@@ -2374,7 +2374,7 @@ static void setAssignmentTrackingModuleFlag(Module &M) {
 
 static bool getAssignmentTrackingModuleFlag(const Module &M) {
   Metadata *Value = M.getModuleFlag(AssignmentTrackingModuleFlag);
-  return Value && !cast<ConstantAsMetadata>(Value)->getValue()->isZeroValue();
+  return Value && !cast<ConstantAsMetadata>(Value)->getValue()->isNullValue();
 }
 
 bool llvm::isAssignmentTrackingEnabled(const Module &M) {
diff --git a/llvm/lib/Target/AArch64/AArch64PromoteConstant.cpp b/llvm/lib/Target/AArch64/AArch64PromoteConstant.cpp
index 3f45d55063b50..1a9ce869f5dfa 100644
--- a/llvm/lib/Target/AArch64/AArch64PromoteConstant.cpp
+++ b/llvm/lib/Target/AArch64/AArch64PromoteConstant.cpp
@@ -342,7 +342,7 @@ static bool shouldConvertImpl(const Constant *Cst) {
   // instances of Cst.
   // Ideally, we could promote this into a global and rematerialize the constant
   // when it was a bad idea.
-  if (Cst->isZeroValue())
+  if (Cst->isNullValue())
     return false;
 
   // Globals cannot be or contain scalable vectors.
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp b/llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp
index 376184e81c738..0ebe69de56fa9 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp
@@ -1454,7 +1454,7 @@ GCNTTIImpl::instCombineIntrinsic(InstCombiner &IC, IntrinsicInst &II) const {
     auto *BC = cast<ConstantInt>(II.getArgOperand(5));
     auto *RM = cast<ConstantInt>(II.getArgOperand(3));
     auto *BM = cast<ConstantInt>(II.getArgOperand(4));
-    if (BC->isZeroValue() || RM->getZExtValue() != 0xF ||
+    if (BC->isNullValue() || RM->getZExtValue() != 0xF ||
         BM->getZExtValue() != 0xF || isa<PoisonValue>(Old))
       break;
 
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp b/llvm/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp
index ed676c3fde2f8..4f85c49bff433 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp
@@ -618,7 +618,7 @@ static Value *promoteAllocaUserToVector(Instruction *Inst, const DataLayout &DL,
     Type *AccessTy = Inst->getType();
     TypeSize AccessSize = DL.getTypeStoreSize(AccessTy);
     if (Constant *CI = dyn_cast<Constant>(Index)) {
-      if (CI->isZeroValue() && AccessSize == VecStoreSize) {
+      if (CI->isNullValue() && AccessSize == VecStoreSize) {
         Inst->replaceAllUsesWith(
             Builder.CreateBitPreservingCastChain(DL, CurVal, AccessTy));
         return nullptr;
@@ -696,7 +696,7 @@ static Value *promoteAllocaUserToVector(Instruction *Inst, const DataLayout &DL,
     Type *AccessTy = Val->getType();
     TypeSize AccessSize = DL.getTypeStoreSize(AccessTy);
     if (Constant *CI = dyn_cast<Constant>(Index))
-      if (CI->isZeroValue() && AccessSize == VecStoreSize)
+      if (CI->isNullValue() && AccessSize == VecStoreSize)
         return Builder.CreateBitPreservingCastChain(DL, Val, AA.Vector.Ty);
 
     // Storing a subvector.
diff --git a/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp b/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp
index b1723f77b0e69..c4bf097e5a0f8 100644
--- a/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp
+++ b/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp
@@ -277,7 +277,7 @@ static Value *expandVecReduceAdd(CallInst *Orig, Intrinsic::ID IntrinsicId) {
   // Handle the initial start value for floating-point addition.
   if (IsFAdd) {
     Constant *StartValue = dyn_cast<Constant>(Orig->getOperand(0));
-    if (StartValue && !StartValue->isZeroValue())
+    if (StartValue && !StartValue->isNullValue())
       Sum = Builder.CreateFAdd(Sum, StartValue);
   }
 
diff --git a/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp b/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp
index 1a4be036d4d45..a626de6302b91 100644
--- a/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp
@@ -1172,7 +1172,7 @@ HexagonTargetLowering::LowerConstantPool(SDValue Op, SelectionDAG &DAG) const {
       assert(isPowerOf2_32(VecLen) &&
              "conversion only supported for pow2 VectorSize");
       for (unsigned i = 0; i < VecLen; ++i)
-        NewConst.push_back(IRB.getInt8(CV->getOperand(i)->isZeroValue()));
+        NewConst.push_back(IRB.getInt8(CV->getOperand(i)->isNullValue()));
 
       CVal = ConstantVector::get(NewConst);
       isVTi1Type = true;
diff --git a/llvm/lib/Target/Hexagon/HexagonVectorCombine.cpp b/llvm/lib/Target/Hexagon/HexagonVectorCombine.cpp
index 93cb628becc6e..1bb135a9e5c87 100644
--- a/llvm/lib/Target/Hexagon/HexagonVectorCombine.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonVectorCombine.cpp
@@ -3349,7 +3349,7 @@ auto HexagonVectorCombine::getConstInt(int Val, unsigned Width) const
 
 auto HexagonVectorCombine::isZero(const Value *Val) const -> bool {
   if (auto *C = dyn_cast<Constant>(Val))
-    return C->isZeroValue();
+    return C->isNullValue();
   return false;
 }
 
diff --git a/llvm/lib/Target/X86/X86LowerAMXType.cpp b/llvm/lib/Target/X86/X86LowerAMXType.cpp
index ff93971f81985..df42d1f4388ba 100644
--- a/llvm/lib/Target/X86/X86LowerAMXType.cpp
+++ b/llvm/lib/Target/X86/X86LowerAMXType.cpp
@@ -813,7 +813,7 @@ bool X86LowerAMXCast::optimizeAMXCastFromPhi(
       // might support const.
       if (isa<Constant>(IncValue)) {
         auto *IncConst = dyn_cast<Constant>(IncValue);
-        if (!isa<UndefValue>(IncValue) && !IncConst->isZeroValue())
+        if (!isa<UndefValue>(IncValue) && !IncConst->isNullValue())
           return false;
         Value *Row = nullptr, *Col = nullptr;
         std::tie(Row, Col) = getShape(OldPN);
diff --git a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp
index 37bf2b9c1a966..b80a514b68246 100644
--- a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp
+++ b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp
@@ -10050,7 +10050,7 @@ struct AAPotentialConstantValuesFloating : AAPotentialConstantValuesImpl {
     bool OnlyLeft = false, OnlyRight = false;
     if (C && *C && (*C)->isOneValue())
       OnlyLeft = true;
-    else if (C && *C && (*C)->isZeroValue())
+    else if (C && *C && (*C)->isNullValue())
       OnlyRight = true;
 
     bool LHSContainsUndef = false, RHSContainsUndef = false;
diff --git a/llvm/lib/Transforms/IPO/FunctionSpecialization.cpp b/llvm/lib/Transforms/IPO/FunctionSpecialization.cpp
index 1e1b198c60bef..5a53017f478d6 100644
--- a/llvm/lib/Transforms/IPO/FunctionSpecialization.cpp
+++ b/llvm/lib/Transforms/IPO/FunctionSpecialization.cpp
@@ -455,13 +455,13 @@ Constant *InstCostVisitor::visitSelectInst(SelectInst &I) {
   assert(LastVisited != KnownConstants.end() && "Invalid iterator!");
 
   if (I.getCondition() == LastVisited->first) {
-    Value *V = LastVisited->second->isZeroValue() ? I.getFalseValue()
+    Value *V = LastVisited->second->isNullValue() ? I.getFalseValue()
                                                   : I.getTrueValue();
     return findConstantFor(V);
   }
   if (Constant *Condition = findConstantFor(I.getCondition()))
     if ((I.getTrueValue() == LastVisited->first && Condition->isOneValue()) ||
-        (I.getFalseValue() == LastVisited->first && Condition->isZeroValue()))
+        (I.getFalseValue() == LastVisited->first && Condition->isNullValue()))
       return LastVisited->second;
   return nullptr;
 }
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index 13118b189dab0..3710e143913fa 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -2660,7 +2660,7 @@ Instruction *InstCombinerImpl::visitAnd(BinaryOperator &I) {
         Constant *Log2C1 = ConstantExpr::getExactLogBase2(C1);
         Constant *Cmp =
             ConstantFoldCompareInstOperands(ICmpInst::ICMP_ULT, Log2C3, C2, DL);
-        if (Cmp && Cmp->isZeroValue()) {
+        if (Cmp && Cmp->isNullValue()) {
           // iff C1,C3 is pow2 and Log2(C3) >= C2:
           // ((C1 >> X) << C2) & C3 -> X == (cttz(C1)+C2-cttz(C3)) ? C3 : 0
           Constant *ShlC = ConstantExpr::getAdd(C2, Log2C1);
@@ -532...
[truncated]

return CFP->isZero();

// Check for constant splat vectors of 1 values.
if (getType()->isVectorTy())
Copy link
Contributor Author

Choose a reason for hiding this comment

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

IMHO, it's also not functionally consistent because it only checks splat vectors for FP values. What about arrays or non-splat vectors?

Copy link
Contributor

@nikic nikic left a comment

Choose a reason for hiding this comment

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

LGTM

@shiltian shiltian merged commit 70905e0 into main Feb 15, 2026
31 of 32 checks passed
@shiltian shiltian deleted the users/shiltian/remove-isZeroValue branch February 15, 2026 17:06
ronlieb added a commit to ROCm/llvm-project that referenced this pull request Feb 16, 2026
manasij7479 pushed a commit to manasij7479/llvm-project that referenced this pull request Feb 18, 2026
`Constant::isZeroValue` currently behaves same as
`Constant::isNullValue` for all types except floating-point, where it
additionally returns true for negative zero (`-0.0`). However, in
practice, almost all callers operate on integer/pointer types where the
two are equivalent, and the few FP-relevant callers have no meaningful
dependence on the `-0.0` behavior.

This PR removes `isZeroValue` to eliminate the confusing API. All
callers are changed to `isNullValue` with no test failures.

`isZeroValue` will be reintroduced in a future change with clearer
semantics: when null pointers may have non-zero bit patterns,
`isZeroValue` will check for bitwise-all-zeros, while `isNullValue` will
check for the semantic null (which
may be non-zero).
Syllo added a commit to Ripple-Programming/llvm-project that referenced this pull request Feb 19, 2026
Change-Id: Ifc0866b0a964a36a42dd7eb8613d2f44a1954d4c
Syllo added a commit to Ripple-Programming/llvm-project that referenced this pull request Feb 19, 2026
Syllo added a commit to Ripple-Programming/llvm-project that referenced this pull request Feb 19, 2026
Syllo added a commit to Ripple-Programming/llvm-project that referenced this pull request Feb 20, 2026
Due to changes to the interface from
llvm#181521
alexreinking added a commit to halide/Halide that referenced this pull request Feb 24, 2026
* Fix llvm removing isZeroValue in favor of isNullValue. 

See: llvm/llvm-project#181521

* Disable PIC in CodeGen_LLVM on Win32

PIC is meaningless on Win32. Position independence is handled by the
PE/COFF linker via base relocations, not by the compiler via GOT/PLT.

See: llvm/llvm-project#137643

---

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Martijn Courteaux <courteauxmartijn@gmail.com>
Co-authored-by: Alex Reinking <areinking@adobe.com>
@nigham
Copy link
Contributor

nigham commented Feb 25, 2026

isZeroValue will be reintroduced in a future change with clearer semantics: when null pointers may have non-zero bit patterns

Consumers of the API who switch between old and new semantics (without having handled the deletion) might see a hard-to-debug behavior change. I would suggest naming the new API slightly differently.

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

Labels

backend:AArch64 backend:AMDGPU backend:DirectX backend:Hexagon backend:X86 clang:codegen IR generation bugs: mangling, exceptions, etc. compiler-rt:sanitizer debuginfo function-specialization llvm:analysis Includes value tracking, cost tables and constant folding llvm:codegen llvm:instcombine Covers the InstCombine, InstSimplify and AggressiveInstCombine passes llvm:ir llvm:transforms mlir:llvm mlir PGO Profile Guided Optimizations

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants