[llvm-branch-commits] [llvm] [NFCI][IR] Add DataLayout-aware `isZeroValue`/`getNullValue` and `getZeroValue` APIs (PR #183208)
Matt Arsenault via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Wed Feb 25 01:02:04 PST 2026
================
@@ -868,5 +869,128 @@ TEST(ConstantsTest, Float128Test) {
LLVMContextDispose(C);
}
+TEST(ConstantsTest, ZeroValueAPIs) {
+ LLVMContext Context;
+
+ // Basic types.
+ Type *Int32Ty = Type::getInt32Ty(Context);
+ Type *FloatTy = Type::getFloatTy(Context);
+ Type *PtrTy = PointerType::get(Context, 0);
+ Type *Ptr1Ty = PointerType::get(Context, 1);
+
+ // --- getZeroValue: currently returns same as getNullValue ---
+ EXPECT_EQ(Constant::getZeroValue(Int32Ty), Constant::getNullValue(Int32Ty));
+ EXPECT_EQ(Constant::getZeroValue(FloatTy), Constant::getNullValue(FloatTy));
+ EXPECT_EQ(Constant::getZeroValue(PtrTy), Constant::getNullValue(PtrTy));
+ EXPECT_EQ(Constant::getZeroValue(Ptr1Ty), Constant::getNullValue(Ptr1Ty));
+
+ // Aggregate types.
+ StructType *StructTy = StructType::get(Int32Ty, PtrTy);
+ ArrayType *ArrayTy = ArrayType::get(Int32Ty, 4);
+ EXPECT_EQ(Constant::getZeroValue(StructTy), Constant::getNullValue(StructTy));
+ EXPECT_EQ(Constant::getZeroValue(ArrayTy), Constant::getNullValue(ArrayTy));
+
+ // --- isZeroValue(nullptr): identity check against getZeroValue ---
+ Constant *IntZero = ConstantInt::get(Int32Ty, 0);
+ Constant *IntOne = ConstantInt::get(Int32Ty, 1);
+ Constant *FPZero = ConstantFP::get(FloatTy, 0.0);
+ Constant *FPNegZero = ConstantFP::get(FloatTy, -0.0);
+ Constant *FPOne = ConstantFP::get(FloatTy, 1.0);
+ Constant *PtrNull0 = ConstantPointerNull::get(cast<PointerType>(PtrTy));
+ Constant *PtrNull1 = ConstantPointerNull::get(cast<PointerType>(Ptr1Ty));
+ Constant *CAZ = ConstantAggregateZero::get(StructTy);
+
+ EXPECT_TRUE(IntZero->isZeroValue());
+ EXPECT_FALSE(IntOne->isZeroValue());
+ EXPECT_TRUE(FPZero->isZeroValue());
+ // -0.0 has a non-zero bit pattern (sign bit set), so it is NOT a zero value.
+ EXPECT_FALSE(FPNegZero->isZeroValue());
+ EXPECT_FALSE(FPOne->isZeroValue());
+ EXPECT_TRUE(PtrNull0->isZeroValue());
+ EXPECT_TRUE(PtrNull1->isZeroValue());
+ EXPECT_TRUE(CAZ->isZeroValue());
+
+ // --- isZeroValue: FP corner cases ---
+ // -0.0 is NOT zero (sign bit set = non-zero bit pattern).
+ // Verify consistency with isNullValue: both agree +0.0 is zero, -0.0 is not.
+ EXPECT_TRUE(FPZero->isNullValue());
+ EXPECT_FALSE(FPNegZero->isNullValue());
+ EXPECT_TRUE(FPZero->isZeroValue());
+ EXPECT_FALSE(FPNegZero->isZeroValue());
+
+ // Double precision: same behavior.
+ Type *DoubleTy = Type::getDoubleTy(Context);
+ Constant *DblZero = ConstantFP::get(DoubleTy, 0.0);
+ Constant *DblNegZero = ConstantFP::get(DoubleTy, -0.0);
+ EXPECT_TRUE(DblZero->isZeroValue());
+ EXPECT_FALSE(DblNegZero->isZeroValue());
+
+ // Vector splats of FP zeros.
+ Constant *VecPosZero =
+ ConstantVector::getSplat(ElementCount::getFixed(2), FPZero);
+ Constant *VecNegZero =
+ ConstantVector::getSplat(ElementCount::getFixed(2), FPNegZero);
+ // Splat of +0.0 collapses to CAZ, which is zero.
+ EXPECT_TRUE(isa<ConstantAggregateZero>(VecPosZero));
+ EXPECT_TRUE(VecPosZero->isZeroValue());
+ // Splat of -0.0 does NOT collapse to CAZ and is NOT zero.
+ EXPECT_FALSE(isa<ConstantAggregateZero>(VecNegZero));
+ EXPECT_FALSE(VecNegZero->isZeroValue());
+
+ // --- isZeroValue(&DL) with default DataLayout (all AS have zero null) ---
+ DataLayout DefaultDL("");
+ EXPECT_TRUE(IntZero->isZeroValue(&DefaultDL));
+ EXPECT_FALSE(IntOne->isZeroValue(&DefaultDL));
+ EXPECT_TRUE(FPZero->isZeroValue(&DefaultDL));
+ EXPECT_FALSE(FPNegZero->isZeroValue(&DefaultDL));
+ EXPECT_FALSE(FPOne->isZeroValue(&DefaultDL));
+ EXPECT_TRUE(PtrNull0->isZeroValue(&DefaultDL));
+ EXPECT_TRUE(PtrNull1->isZeroValue(&DefaultDL));
+ EXPECT_TRUE(CAZ->isZeroValue(&DefaultDL));
+
+ // --- isZeroValue(&DL) with all-ones-null AS 1 ---
+ // Format: p<flags><as>:<size>:<abi> -- flags before AS number.
+ DataLayout AllOnesDL("po1:64:64");
+ // AS 0 still has zero null, so CPN for AS 0 is still a zero value.
+ EXPECT_TRUE(PtrNull0->isZeroValue(&AllOnesDL));
+ // AS 1 has all-ones null, so CPN for AS 1 is NOT a zero value.
+ EXPECT_FALSE(PtrNull1->isZeroValue(&AllOnesDL));
+ // Non-pointer constants are unaffected by DataLayout.
+ EXPECT_TRUE(IntZero->isZeroValue(&AllOnesDL));
+ EXPECT_TRUE(FPZero->isZeroValue(&AllOnesDL));
+ EXPECT_TRUE(CAZ->isZeroValue(&AllOnesDL));
+
+ // --- getNullValue(Ty, nullptr): same as getNullValue(Ty) ---
+ EXPECT_EQ(Constant::getNullValue(Int32Ty, nullptr),
+ Constant::getNullValue(Int32Ty));
+ EXPECT_EQ(Constant::getNullValue(PtrTy, nullptr),
+ Constant::getNullValue(PtrTy));
+ EXPECT_EQ(Constant::getNullValue(StructTy, nullptr),
+ Constant::getNullValue(StructTy));
+
+ // --- getNullValue(Ty, &DL) fast path: no non-zero-null pointers ---
+ EXPECT_EQ(Constant::getNullValue(Int32Ty, &DefaultDL),
+ Constant::getNullValue(Int32Ty));
+ EXPECT_EQ(Constant::getNullValue(PtrTy, &DefaultDL),
+ Constant::getNullValue(PtrTy));
+ EXPECT_EQ(Constant::getNullValue(StructTy, &DefaultDL),
+ Constant::getNullValue(StructTy));
+ EXPECT_EQ(Constant::getNullValue(ArrayTy, &DefaultDL),
+ Constant::getNullValue(ArrayTy));
+
+ // With AllOnesDL, types that don't contain AS 1 pointers still take fast
+ // path.
+ EXPECT_EQ(Constant::getNullValue(Int32Ty, &AllOnesDL),
+ Constant::getNullValue(Int32Ty));
+ EXPECT_EQ(Constant::getNullValue(PtrTy, &AllOnesDL),
+ Constant::getNullValue(PtrTy));
+ // Struct containing AS 0 pointer -- fast path (AS 0 is zero null).
+ EXPECT_EQ(Constant::getNullValue(StructTy, &AllOnesDL),
+ Constant::getNullValue(StructTy));
+
+ // TODO: getNullValue slow path for aggregates with non-zero-null pointers is
+ // deferred to PR 3 testing (requires aggregate collapse fix).
----------------
arsenm wrote:
Probably shouldn't have a comment referring to specific of the PR stack
https://github.com/llvm/llvm-project/pull/183208
More information about the llvm-branch-commits
mailing list