Constfold insertelement to undef when index is out-of-bounds
authorPawel Bylica <chfast@gmail.com>
Mon, 27 Apr 2015 09:30:49 +0000 (09:30 +0000)
committerPawel Bylica <chfast@gmail.com>
Mon, 27 Apr 2015 09:30:49 +0000 (09:30 +0000)
Summary:
This patch adds constant folding of insertelement instruction to undef value when index operand is constant and is not less than vector size or is undef.

InstCombine does not support this case, but I'm happy to add it there also if this change is accepted.

Test Plan: Unittests and regression tests for ConstProp pass.

Reviewers: majnemer

Reviewed By: majnemer

Subscribers: llvm-commits

Differential Revision: http://reviews.llvm.org/D9287

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@235854 91177308-0d34-0410-b5e6-96231b3b80d8

lib/IR/ConstantFold.cpp
test/Transforms/ConstProp/InsertElement.ll
unittests/IR/ConstantsTest.cpp

index 03d7c5e7b95bc6d8de46347dab13641869139406..2a524937391c5cddfafc5258685840ae6edd8fe8 100644 (file)
@@ -800,23 +800,30 @@ Constant *llvm::ConstantFoldExtractElementInstruction(Constant *Val,
 Constant *llvm::ConstantFoldInsertElementInstruction(Constant *Val,
                                                      Constant *Elt,
                                                      Constant *Idx) {
+  if (isa<UndefValue>(Idx))
+    return UndefValue::get(Val->getType());
+
   ConstantInt *CIdx = dyn_cast<ConstantInt>(Idx);
   if (!CIdx) return nullptr;
-  const APInt &IdxVal = CIdx->getValue();
-  
+
+  unsigned NumElts = Val->getType()->getVectorNumElements();
+  if (CIdx->uge(NumElts))
+    return UndefValue::get(Val->getType());
+
   SmallVector<Constant*, 16> Result;
-  Type *Ty = IntegerType::get(Val->getContext(), 32);
-  for (unsigned i = 0, e = Val->getType()->getVectorNumElements(); i != e; ++i){
+  Result.reserve(NumElts);
+  auto *Ty = Type::getInt32Ty(Val->getContext());
+  uint64_t IdxVal = CIdx->getZExtValue();
+  for (unsigned i = 0; i != NumElts; ++i) {    
     if (i == IdxVal) {
       Result.push_back(Elt);
       continue;
     }
     
-    Constant *C =
-      ConstantExpr::getExtractElement(Val, ConstantInt::get(Ty, i));
+    Constant *C = ConstantExpr::getExtractElement(Val, ConstantInt::get(Ty, i));
     Result.push_back(C);
   }
-  
+
   return ConstantVector::get(Result);
 }
 
index d249c2eb1c515e03923d1a3075663ba42220ffda..011ad3f57f4689802a77be8f4481fff9369b7a4f 100644 (file)
@@ -1,12 +1,32 @@
 ; RUN: opt < %s -constprop -S | FileCheck %s
 
+; CHECK-LABEL: @test1
 define i32 @test1() {
   %A = bitcast i32 2139171423 to float
   %B = insertelement <1 x float> undef, float %A, i32 0
   %C = extractelement <1 x float> %B, i32 0
   %D = bitcast float %C to i32
   ret i32 %D
-; CHECK: @test1
 ; CHECK: ret i32 2139171423
 }
 
+; CHECK-LABEL: @insertelement
+define <4 x i64> @insertelement() {
+  %vec1 = insertelement <4 x i64> undef, i64 -1, i32 0
+  %vec2 = insertelement <4 x i64> %vec1, i64 -2, i32 1
+  %vec3 = insertelement <4 x i64> %vec2, i64 -3, i32 2
+  %vec4 = insertelement <4 x i64> %vec3, i64 -4, i32 3
+  ; CHECK: ret <4 x i64> <i64 -1, i64 -2, i64 -3, i64 -4>
+  ret <4 x i64> %vec4
+}
+
+; CHECK-LABEL: @insertelement_undef
+define <4 x i64> @insertelement_undef() {
+  %vec1 = insertelement <4 x i64> undef, i64 -1, i32 0
+  %vec2 = insertelement <4 x i64> %vec1, i64 -2, i32 1
+  %vec3 = insertelement <4 x i64> %vec2, i64 -3, i32 2
+  %vec4 = insertelement <4 x i64> %vec3, i64 -4, i32 3
+  %vec5 = insertelement <4 x i64> %vec3, i64 -5, i32 4
+  ; CHECK: ret <4 x i64> undef
+  ret <4 x i64> %vec5
+}
index d02217dc355461892249cdcc2ad7686258305fda..7741b448fa8d5e746556e06d5a5d6b864c8129a7 100644 (file)
@@ -190,7 +190,10 @@ TEST(ConstantsTest, AsInstructionsTest) {
   Constant *Two = ConstantInt::get(Int64Ty, 2);
   Constant *Big = ConstantInt::get(getGlobalContext(),
                                    APInt{256, uint64_t(-1), true});
-  Constant *Undef = UndefValue::get(Int64Ty);
+  Constant *Elt = ConstantInt::get(Int16Ty, 2015);
+  Constant *Undef16  = UndefValue::get(Int16Ty);
+  Constant *Undef64  = UndefValue::get(Int64Ty);
+  Constant *UndefV16 = UndefValue::get(P6->getType());
 
   #define P0STR "ptrtoint (i32** @dummy to i32)"
   #define P1STR "uitofp (i32 ptrtoint (i32** @dummy to i32) to float)"
@@ -260,9 +263,15 @@ TEST(ConstantsTest, AsInstructionsTest) {
   CHECK(ConstantExpr::getExtractElement(P6, One), "extractelement <2 x i16> "
         P6STR ", i32 1");
 
-  EXPECT_TRUE(isa<UndefValue>(ConstantExpr::getExtractElement(P6, Two)));
-  EXPECT_TRUE(isa<UndefValue>(ConstantExpr::getExtractElement(P6, Big)));
-  EXPECT_TRUE(isa<UndefValue>(ConstantExpr::getExtractElement(P6, Undef)));
+  EXPECT_EQ(Undef16, ConstantExpr::getExtractElement(P6, Two));
+  EXPECT_EQ(Undef16, ConstantExpr::getExtractElement(P6, Big));
+  EXPECT_EQ(Undef16, ConstantExpr::getExtractElement(P6, Undef64));
+
+  EXPECT_EQ(Elt, ConstantExpr::getExtractElement(
+                 ConstantExpr::getInsertElement(P6, Elt, One), One));
+  EXPECT_EQ(UndefV16, ConstantExpr::getInsertElement(P6, Elt, Two));
+  EXPECT_EQ(UndefV16, ConstantExpr::getInsertElement(P6, Elt, Big));
+  EXPECT_EQ(UndefV16, ConstantExpr::getInsertElement(P6, Elt, Undef64));
 }
 
 #ifdef GTEST_HAS_DEATH_TEST