[llvm] 648544f - [Constant] ConstantStruct/Array should not lower poison to undef

Juneyoung Lee via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 7 23:23:42 PDT 2021


Author: Juneyoung Lee
Date: 2021-04-08T15:23:12+09:00
New Revision: 648544f998cd0811670a625f4f2964125cf833b3

URL: https://github.com/llvm/llvm-project/commit/648544f998cd0811670a625f4f2964125cf833b3
DIFF: https://github.com/llvm/llvm-project/commit/648544f998cd0811670a625f4f2964125cf833b3.diff

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

This is a (late) follow-up patch of 8871a4b4cab8a56fd6ff12fd024002c3c79128b3 and
c95f39891a282ebf36199c73b705d4a2c78a46ce 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)

Added: 
    

Modified: 
    llvm/lib/IR/Constants.cpp
    llvm/unittests/IR/ConstantsTest.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp
index 48ccb18fee08..c0b8af8b2437 100644
--- a/llvm/lib/IR/Constants.cpp
+++ b/llvm/lib/IR/Constants.cpp
@@ -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);
 

diff  --git a/llvm/unittests/IR/ConstantsTest.cpp b/llvm/unittests/IR/ConstantsTest.cpp
index 50eb3e0df1f5..54ef98cb5917 100644
--- a/llvm/unittests/IR/ConstantsTest.cpp
+++ b/llvm/unittests/IR/ConstantsTest.cpp
@@ -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;
 


        


More information about the llvm-commits mailing list