[Constant] ConstantStruct/Array should not lower poison to undef

This is a (late) follow-up patch of 8871a4b4ca and
c95f39891a to make ConstantStruct::get/ConstantArray::getImpl
correctly return PoisonValue if all elements are poison.
This was found while discussing about the elements of a vector-typed UndefValue (D99853)
This commit is contained in:
Juneyoung Lee 2021-04-08 15:20:08 +09:00
parent 2a2720a2de
commit 648544f998
2 changed files with 57 additions and 8 deletions

View File

@ -1265,6 +1265,9 @@ Constant *ConstantArray::getImpl(ArrayType *Ty, ArrayRef<Constant*> V) {
// all undef, return an UndefValue, if "all simple", then return a
// ConstantDataArray.
Constant *C = V[0];
if (isa<PoisonValue>(C) && rangeOnlyContains(V.begin(), V.end(), C))
return PoisonValue::get(Ty);
if (isa<UndefValue>(C) && rangeOnlyContains(V.begin(), V.end(), C))
return UndefValue::get(Ty);
@ -1313,21 +1316,28 @@ Constant *ConstantStruct::get(StructType *ST, ArrayRef<Constant*> V) {
// Create a ConstantAggregateZero value if all elements are zeros.
bool isZero = true;
bool isUndef = false;
bool isPoison = false;
if (!V.empty()) {
isUndef = isa<UndefValue>(V[0]);
isPoison = isa<PoisonValue>(V[0]);
isZero = V[0]->isNullValue();
// PoisonValue inherits UndefValue, so its check is not necessary.
if (isUndef || isZero) {
for (unsigned i = 0, e = V.size(); i != e; ++i) {
if (!V[i]->isNullValue())
isZero = false;
if (!isa<UndefValue>(V[i]))
if (!isa<PoisonValue>(V[i]))
isPoison = false;
if (isa<PoisonValue>(V[i]) || !isa<UndefValue>(V[i]))
isUndef = false;
}
}
}
if (isZero)
return ConstantAggregateZero::get(ST);
if (isPoison)
return PoisonValue::get(ST);
if (isUndef)
return UndefValue::get(ST);

View File

@ -644,13 +644,6 @@ TEST(ConstantsTest, isElementWiseEqual) {
Constant *C1 = ConstantInt::get(Int32Ty, 1);
Constant *C2 = ConstantInt::get(Int32Ty, 2);
Constant *CUU = ConstantVector::get({CU, CU});
Constant *CPP = ConstantVector::get({CP, CP});
Constant *CUP = ConstantVector::get({CU, CP});
EXPECT_EQ(CUU, UndefValue::get(CUU->getType()));
EXPECT_EQ(CPP, PoisonValue::get(CPP->getType()));
EXPECT_NE(CUP, UndefValue::get(CUP->getType()));
Constant *C1211 = ConstantVector::get({C1, C2, C1, C1});
Constant *C12U1 = ConstantVector::get({C1, C2, CU, C1});
Constant *C12U2 = ConstantVector::get({C1, C2, CU, C2});
@ -692,6 +685,52 @@ TEST(ConstantsTest, isElementWiseEqual) {
EXPECT_FALSE(CP00U->isElementWiseEqual(CP00U0));
}
// Check that vector/aggregate constants correctly store undef and poison
// elements.
TEST(ConstantsTest, CheckElementWiseUndefPoison) {
LLVMContext Context;
Type *Int32Ty = Type::getInt32Ty(Context);
StructType *STy = StructType::get(Int32Ty, Int32Ty);
ArrayType *ATy = ArrayType::get(Int32Ty, 2);
Constant *CU = UndefValue::get(Int32Ty);
Constant *CP = PoisonValue::get(Int32Ty);
{
Constant *CUU = ConstantVector::get({CU, CU});
Constant *CPP = ConstantVector::get({CP, CP});
Constant *CUP = ConstantVector::get({CU, CP});
Constant *CPU = ConstantVector::get({CP, CU});
EXPECT_EQ(CUU, UndefValue::get(CUU->getType()));
EXPECT_EQ(CPP, PoisonValue::get(CPP->getType()));
EXPECT_NE(CUP, UndefValue::get(CUP->getType()));
EXPECT_NE(CPU, UndefValue::get(CPU->getType()));
}
{
Constant *CUU = ConstantStruct::get(STy, {CU, CU});
Constant *CPP = ConstantStruct::get(STy, {CP, CP});
Constant *CUP = ConstantStruct::get(STy, {CU, CP});
Constant *CPU = ConstantStruct::get(STy, {CP, CU});
EXPECT_EQ(CUU, UndefValue::get(CUU->getType()));
EXPECT_EQ(CPP, PoisonValue::get(CPP->getType()));
EXPECT_NE(CUP, UndefValue::get(CUP->getType()));
EXPECT_NE(CPU, UndefValue::get(CPU->getType()));
}
{
Constant *CUU = ConstantArray::get(ATy, {CU, CU});
Constant *CPP = ConstantArray::get(ATy, {CP, CP});
Constant *CUP = ConstantArray::get(ATy, {CU, CP});
Constant *CPU = ConstantArray::get(ATy, {CP, CU});
EXPECT_EQ(CUU, UndefValue::get(CUU->getType()));
EXPECT_EQ(CPP, PoisonValue::get(CPP->getType()));
EXPECT_NE(CUP, UndefValue::get(CUP->getType()));
EXPECT_NE(CPU, UndefValue::get(CPU->getType()));
}
}
TEST(ConstantsTest, GetSplatValueRoundTrip) {
LLVMContext Context;