]> granicus.if.org Git - llvm/commitdiff
[ConstantFold] Improve the bitcast folding logic for constant vectors.
authorAndrea Di Biagio <Andrea_DiBiagio@sn.scee.net>
Tue, 13 Sep 2016 14:50:47 +0000 (14:50 +0000)
committerAndrea Di Biagio <Andrea_DiBiagio@sn.scee.net>
Tue, 13 Sep 2016 14:50:47 +0000 (14:50 +0000)
The constant folder didn't know how to always fold bitcasts of constant integer
vectors. In particular, it was unable to handle the case where a constant vector
had some undef elements, and the resulting (i.e. bitcasted) vector type had more
elements than the original vector type.

Example:
  %cast = bitcast <2 x i64><i64 undef, i64 2> to <4 x i32>

On a little endian target, %cast could have been folded to:
  <4 x i32><i32 undef, i32 undef, i32 2, i32 0>

This patch improves the folding logic by teaching how to correctly propagate
undef elements in the folded vector.

Differential Revision: https://reviews.llvm.org/D24301

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

lib/Analysis/ConstantFolding.cpp
test/Transforms/InstCombine/x86-sse4a.ll
test/Transforms/InstSimplify/bitcast-vector-fold.ll

index 73cf336f5eb0c6153f4f94c8972559950d14e655..1df724a044bd4b6d093c164d3c4b83aa7cacdf67 100644 (file)
@@ -224,8 +224,19 @@ Constant *FoldBitCast(Constant *C, Type *DestTy, const DataLayout &DL) {
 
   // Loop over each source value, expanding into multiple results.
   for (unsigned i = 0; i != NumSrcElt; ++i) {
-    auto *Src = dyn_cast_or_null<ConstantInt>(C->getAggregateElement(i));
-    if (!Src)  // Reject constantexpr elements.
+    auto *Element = C->getAggregateElement(i);
+
+    if (!Element) // Reject constantexpr elements.
+      return ConstantExpr::getBitCast(C, DestTy);
+
+    if (isa<UndefValue>(Element)) {
+      // Correctly Propagate undef values.
+      Result.append(Ratio, UndefValue::get(DstEltTy));
+      continue;
+    }
+
+    auto *Src = dyn_cast<ConstantInt>(Element);
+    if (!Src)
       return ConstantExpr::getBitCast(C, DestTy);
 
     unsigned ShiftAmt = isLittleEndian ? 0 : DstBitSize*(Ratio-1);
index d2714e0c6303710c44c8fe25322436bdad822e53..e36a7353225944fd3126a7765e27bb3fbd5c767e 100644 (file)
@@ -57,8 +57,7 @@ define <2 x i64> @test_extrq_constant_undef(<2 x i64> %x, <16 x i8> %y) {
 
 define <2 x i64> @test_extrq_call_constexpr(<2 x i64> %x) {
 ; CHECK-LABEL: @test_extrq_call_constexpr(
-; CHECK-NEXT:    [[TMP1:%.*]] = call <2 x i64> @llvm.x86.sse4a.extrq(<2 x i64> %x, <16 x i8> bitcast (<2 x i64> <i64 0, i64 undef> to <16 x i8>))
-; CHECK-NEXT:    ret <2 x i64> [[TMP1]]
+; CHECK-NEXT:    ret <2 x i64> %x
 ;
   %1 = call <2 x i64> @llvm.x86.sse4a.extrq(<2 x i64> %x, <16 x i8> bitcast (<2 x i64> <i64 0, i64 undef> to <16 x i8>))
   ret <2 x i64> %1
@@ -133,7 +132,7 @@ define <2 x i64> @test_extrqi_constant_undef(<2 x i64> %x) {
 
 define <2 x i64> @test_extrqi_call_constexpr() {
 ; CHECK-LABEL: @test_extrqi_call_constexpr(
-; CHECK-NEXT:    ret <2 x i64> bitcast (<16 x i8> <i8 extractelement (<16 x i8> trunc (<16 x i16> bitcast (<4 x i64> <i64 0, i64 undef, i64 2, i64 undef> to <16 x i16>) to <16 x i8>), i32 2), i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef> to <2 x i64>)
+; CHECK-NEXT:    ret <2 x i64> zeroinitializer
 ;
   %1 = tail call <2 x i64> @llvm.x86.sse4a.extrqi(<2 x i64> bitcast (<16 x i8> trunc (<16 x i16> bitcast (<4 x i64> <i64 0, i64 undef, i64 2, i64 undef> to <16 x i16>) to <16 x i8>) to <2 x i64>), i8 8, i8 16)
   ret <2 x i64> %1
@@ -179,7 +178,7 @@ define <2 x i64> @test_insertq_constant_undef(<2 x i64> %x, <2 x i64> %y) {
 
 define <2 x i64> @test_insertq_call_constexpr(<2 x i64> %x) {
 ; CHECK-LABEL: @test_insertq_call_constexpr(
-; CHECK-NEXT:    [[TMP1:%.*]] = tail call <2 x i64> @llvm.x86.sse4a.insertq(<2 x i64> %x, <2 x i64> bitcast (<16 x i8> trunc (<16 x i16> bitcast (<4 x i64> <i64 0, i64 undef, i64 2, i64 undef> to <16 x i16>) to <16 x i8>) to <2 x i64>))
+; CHECK-NEXT:    [[TMP1:%.*]] = call <2 x i64> @llvm.x86.sse4a.insertqi(<2 x i64> %x, <2 x i64> <i64 0, i64 undef>, i8 2, i8 0)
 ; CHECK-NEXT:    ret <2 x i64> [[TMP1]]
 ;
   %1 = tail call <2 x i64> @llvm.x86.sse4a.insertq(<2 x i64> %x, <2 x i64> bitcast (<16 x i8> trunc (<16 x i16> bitcast (<4 x i64> <i64 0, i64 undef, i64 2, i64 undef> to <16 x i16>) to <16 x i8>) to <2 x i64>))
@@ -224,7 +223,7 @@ define <2 x i64> @test_insertqi_constant(<2 x i64> %v, <2 x i64> %i) {
 
 define <2 x i64> @test_insertqi_call_constexpr(<2 x i64> %x) {
 ; CHECK-LABEL: @test_insertqi_call_constexpr(
-; CHECK-NEXT:    [[TMP1:%.*]] = tail call <2 x i64> @llvm.x86.sse4a.insertqi(<2 x i64> %x, <2 x i64> bitcast (<16 x i8> trunc (<16 x i16> bitcast (<4 x i64> <i64 0, i64 undef, i64 2, i64 undef> to <16 x i16>) to <16 x i8>) to <2 x i64>), i8 48, i8 3)
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call <2 x i64> @llvm.x86.sse4a.insertqi(<2 x i64> %x, <2 x i64> <i64 0, i64 undef>, i8 48, i8 3)
 ; CHECK-NEXT:    ret <2 x i64> [[TMP1]]
 ;
   %1 = tail call <2 x i64> @llvm.x86.sse4a.insertqi(<2 x i64> %x, <2 x i64> bitcast (<16 x i8> trunc (<16 x i16> bitcast (<4 x i64> <i64 0, i64 undef, i64 2, i64 undef> to <16 x i16>) to <16 x i8>) to <2 x i64>), i8 48, i8 3)
index 126aba63ecbec52073b1060742d4b588262a0580..c8c390ea6be47c7e4982f392a731a9194a1fe137 100644 (file)
@@ -126,7 +126,7 @@ define <2 x double> @foo6() {
 
 define <4 x i32> @bitcast_constexpr_4i32_2i64_u2() {
 ; CHECK-LABEL: @bitcast_constexpr_4i32_2i64_u2(
-; CHECK-NEXT:    ret <4 x i32> bitcast (<2 x i64> <i64 undef, i64 2> to <4 x i32>)
+; CHECK-NEXT:    ret <4 x i32> <i32 undef, i32 undef, i32 2, i32 0>
 ;
   %cast = bitcast <2 x i64><i64 undef, i64 2> to <4 x i32>
   ret <4 x i32> %cast
@@ -134,7 +134,7 @@ define <4 x i32> @bitcast_constexpr_4i32_2i64_u2() {
 
 define <4 x i32> @bitcast_constexpr_4i32_2i64_1u() {
 ; CHECK-LABEL: @bitcast_constexpr_4i32_2i64_1u(
-; CHECK-NEXT:    ret <4 x i32> bitcast (<2 x i64> <i64 1, i64 undef> to <4 x i32>)
+; CHECK-NEXT:    ret <4 x i32> <i32 1, i32 0, i32 undef, i32 undef>
 ;
   %cast = bitcast <2 x i64><i64 1, i64 undef> to <4 x i32>
   ret <4 x i32> %cast
@@ -142,7 +142,7 @@ define <4 x i32> @bitcast_constexpr_4i32_2i64_1u() {
 
 define <4 x i32> @bitcast_constexpr_4i32_2i64() {
 ; CHECK-LABEL: @bitcast_constexpr_4i32_2i64(
-; CHECK-NEXT:    ret <4 x i32> bitcast (<2 x i64> <i64 undef, i64 2> to <4 x i32>)
+; CHECK-NEXT:    ret <4 x i32> <i32 undef, i32 undef, i32 2, i32 0>
 ;
   %cast = bitcast <2 x i64><i64 undef, i64 2> to <4 x i32>
   ret <4 x i32> %cast
@@ -150,7 +150,7 @@ define <4 x i32> @bitcast_constexpr_4i32_2i64() {
 
 define <8 x i16> @bitcast_constexpr_8i16_2i64_u2() {
 ; CHECK-LABEL: @bitcast_constexpr_8i16_2i64_u2(
-; CHECK-NEXT:    ret <8 x i16> bitcast (<2 x i64> <i64 undef, i64 2> to <8 x i16>)
+; CHECK-NEXT:    ret <8 x i16> <i16 undef, i16 undef, i16 undef, i16 undef, i16 2, i16 0, i16 0, i16 0>
 ;
   %cast = bitcast <2 x i64><i64 undef, i64 2> to <8 x i16>
   ret <8 x i16> %cast
@@ -158,7 +158,7 @@ define <8 x i16> @bitcast_constexpr_8i16_2i64_u2() {
 
 define <8 x i16> @bitcast_constexpr_8i16_2i64_1u() {
 ; CHECK-LABEL: @bitcast_constexpr_8i16_2i64_1u(
-; CHECK-NEXT:    ret <8 x i16> bitcast (<2 x i64> <i64 1, i64 undef> to <8 x i16>)
+; CHECK-NEXT:    ret <8 x i16> <i16 1, i16 0, i16 0, i16 0, i16 undef, i16 undef, i16 undef, i16 undef>
 ;
   %cast = bitcast <2 x i64><i64 1, i64 undef> to <8 x i16>
   ret <8 x i16> %cast
@@ -166,7 +166,7 @@ define <8 x i16> @bitcast_constexpr_8i16_2i64_1u() {
 
 define <8 x i16> @bitcast_constexpr_8i16_2i64_u65536() {
 ; CHECK-LABEL: @bitcast_constexpr_8i16_2i64_u65536(
-; CHECK-NEXT:    ret <8 x i16> bitcast (<2 x i64> <i64 undef, i64 65536> to <8 x i16>)
+; CHECK-NEXT:    ret <8 x i16> <i16 undef, i16 undef, i16 undef, i16 undef, i16 0, i16 1, i16 0, i16 0>
 ;
   %cast = bitcast <2 x i64><i64 undef, i64 65536> to <8 x i16>
   ret <8 x i16> %cast
@@ -174,7 +174,7 @@ define <8 x i16> @bitcast_constexpr_8i16_2i64_u65536() {
 
 define <16 x i8> @bitcast_constexpr_16i8_2i64_u2() {
 ; CHECK-LABEL: @bitcast_constexpr_16i8_2i64_u2(
-; CHECK-NEXT:    ret <16 x i8> bitcast (<2 x i64> <i64 undef, i64 2> to <16 x i8>)
+; CHECK-NEXT:    ret <16 x i8> <i8 undef, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef, i8 2, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0>
 ;
   %cast = bitcast <2 x i64><i64 undef, i64 2> to <16 x i8>
   ret <16 x i8> %cast
@@ -182,7 +182,7 @@ define <16 x i8> @bitcast_constexpr_16i8_2i64_u2() {
 
 define <16 x i8> @bitcast_constexpr_16i8_2i64_256u() {
 ; CHECK-LABEL: @bitcast_constexpr_16i8_2i64_256u(
-; CHECK-NEXT:    ret <16 x i8> bitcast (<2 x i64> <i64 256, i64 undef> to <16 x i8>)
+; CHECK-NEXT:    ret <16 x i8> <i8 0, i8 1, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef>
 ;
   %cast = bitcast <2 x i64><i64 256, i64 undef> to <16 x i8>
   ret <16 x i8> %cast
@@ -190,7 +190,7 @@ define <16 x i8> @bitcast_constexpr_16i8_2i64_256u() {
 
 define <16 x i8> @bitcast_constexpr_16i8_2i64_u256() {
 ; CHECK-LABEL: @bitcast_constexpr_16i8_2i64_u256(
-; CHECK-NEXT:    ret <16 x i8> bitcast (<2 x i64> <i64 undef, i64 256> to <16 x i8>)
+; CHECK-NEXT:    ret <16 x i8> <i8 undef, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef, i8 0, i8 1, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0>
 ;
   %cast = bitcast <2 x i64><i64 undef, i64 256> to <16 x i8>
   ret <16 x i8> %cast
@@ -198,7 +198,7 @@ define <16 x i8> @bitcast_constexpr_16i8_2i64_u256() {
 
 define <8 x i16> @bitcast_constexpr_8i16_4i32_uu22() {
 ; CHECK-LABEL: @bitcast_constexpr_8i16_4i32_uu22(
-; CHECK-NEXT:    ret <8 x i16> bitcast (<4 x i32> <i32 undef, i32 undef, i32 2, i32 2> to <8 x i16>)
+; CHECK-NEXT:    ret <8 x i16> <i16 undef, i16 undef, i16 undef, i16 undef, i16 2, i16 0, i16 2, i16 0>
 ;
   %cast = bitcast <4 x i32><i32 undef, i32 undef, i32 2, i32 2> to <8 x i16>
   ret <8 x i16> %cast
@@ -206,7 +206,7 @@ define <8 x i16> @bitcast_constexpr_8i16_4i32_uu22() {
 
 define <8 x i16> @bitcast_constexpr_8i16_4i32_10uu() {
 ; CHECK-LABEL: @bitcast_constexpr_8i16_4i32_10uu(
-; CHECK-NEXT:    ret <8 x i16> bitcast (<4 x i32> <i32 1, i32 0, i32 undef, i32 undef> to <8 x i16>)
+; CHECK-NEXT:    ret <8 x i16> <i16 1, i16 0, i16 0, i16 0, i16 undef, i16 undef, i16 undef, i16 undef>
 ;
   %cast = bitcast <4 x i32><i32 1, i32 0, i32 undef, i32 undef> to <8 x i16>
   ret <8 x i16> %cast
@@ -214,7 +214,7 @@ define <8 x i16> @bitcast_constexpr_8i16_4i32_10uu() {
 
 define <8 x i16> @bitcast_constexpr_8i16_4i32_u257u256() {
 ; CHECK-LABEL: @bitcast_constexpr_8i16_4i32_u257u256(
-; CHECK-NEXT:    ret <8 x i16> bitcast (<4 x i32> <i32 undef, i32 65536, i32 undef, i32 65536> to <8 x i16>)
+; CHECK-NEXT:    ret <8 x i16> <i16 undef, i16 undef, i16 0, i16 1, i16 undef, i16 undef, i16 0, i16 1>
 ;
   %cast = bitcast <4 x i32><i32 undef, i32 65536, i32 undef, i32 65536> to <8 x i16>
   ret <8 x i16> %cast
@@ -222,7 +222,7 @@ define <8 x i16> @bitcast_constexpr_8i16_4i32_u257u256() {
 
 define <16 x i8> @bitcast_constexpr_16i8_4i32_u2u2() {
 ; CHECK-LABEL: @bitcast_constexpr_16i8_4i32_u2u2(
-; CHECK-NEXT:    ret <16 x i8> bitcast (<4 x i32> <i32 undef, i32 2, i32 undef, i32 2> to <16 x i8>)
+; CHECK-NEXT:    ret <16 x i8> <i8 undef, i8 undef, i8 undef, i8 undef, i8 2, i8 0, i8 0, i8 0, i8 undef, i8 undef, i8 undef, i8 undef, i8 2, i8 0, i8 0, i8 0>
 ;
   %cast = bitcast <4 x i32><i32 undef, i32 2, i32 undef, i32 2> to <16 x i8>
   ret <16 x i8> %cast
@@ -230,7 +230,7 @@ define <16 x i8> @bitcast_constexpr_16i8_4i32_u2u2() {
 
 define <16 x i8> @bitcast_constexpr_16i8_4i32_1u1u() {
 ; CHECK-LABEL: @bitcast_constexpr_16i8_4i32_1u1u(
-; CHECK-NEXT:    ret <16 x i8> bitcast (<4 x i32> <i32 1, i32 undef, i32 1, i32 undef> to <16 x i8>)
+; CHECK-NEXT:    ret <16 x i8> <i8 1, i8 0, i8 0, i8 0, i8 undef, i8 undef, i8 undef, i8 undef, i8 1, i8 0, i8 0, i8 0, i8 undef, i8 undef, i8 undef, i8 undef>
 ;
   %cast = bitcast <4 x i32><i32 1, i32 undef, i32 1, i32 undef> to <16 x i8>
   ret <16 x i8> %cast
@@ -238,7 +238,7 @@ define <16 x i8> @bitcast_constexpr_16i8_4i32_1u1u() {
 
 define <16 x i8> @bitcast_constexpr_16i8_4i32_u256uu() {
 ; CHECK-LABEL: @bitcast_constexpr_16i8_4i32_u256uu(
-; CHECK-NEXT:    ret <16 x i8> bitcast (<4 x i32> <i32 undef, i32 256, i32 undef, i32 undef> to <16 x i8>)
+; CHECK-NEXT:    ret <16 x i8> <i8 undef, i8 undef, i8 undef, i8 undef, i8 0, i8 1, i8 0, i8 0, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef>
 ;
   %cast = bitcast <4 x i32><i32 undef, i32 256, i32 undef, i32 undef> to <16 x i8>
   ret <16 x i8> %cast
@@ -246,7 +246,7 @@ define <16 x i8> @bitcast_constexpr_16i8_4i32_u256uu() {
 
 define <16 x i8> @bitcast_constexpr_16i8_8i16_u2u2u2u2() {
 ; CHECK-LABEL: @bitcast_constexpr_16i8_8i16_u2u2u2u2(
-; CHECK-NEXT:    ret <16 x i8> bitcast (<8 x i16> <i16 undef, i16 2, i16 undef, i16 2, i16 undef, i16 2, i16 undef, i16 2> to <16 x i8>)
+; CHECK-NEXT:    ret <16 x i8> <i8 undef, i8 undef, i8 2, i8 0, i8 undef, i8 undef, i8 2, i8 0, i8 undef, i8 undef, i8 2, i8 0, i8 undef, i8 undef, i8 2, i8 0>
 ;
   %cast = bitcast <8 x i16><i16 undef, i16 2, i16 undef, i16 2, i16 undef, i16 2, i16 undef, i16 2> to <16 x i8>
   ret <16 x i8> %cast
@@ -254,7 +254,7 @@ define <16 x i8> @bitcast_constexpr_16i8_8i16_u2u2u2u2() {
 
 define <16 x i8> @bitcast_constexpr_16i8_8i16_1u1u1u1u() {
 ; CHECK-LABEL: @bitcast_constexpr_16i8_8i16_1u1u1u1u(
-; CHECK-NEXT:    ret <16 x i8> bitcast (<8 x i16> <i16 1, i16 undef, i16 1, i16 undef, i16 1, i16 undef, i16 1, i16 undef> to <16 x i8>)
+; CHECK-NEXT:    ret <16 x i8> <i8 1, i8 0, i8 undef, i8 undef, i8 1, i8 0, i8 undef, i8 undef, i8 1, i8 0, i8 undef, i8 undef, i8 1, i8 0, i8 undef, i8 undef>
 ;
   %cast = bitcast <8 x i16><i16 1, i16 undef, i16 1, i16 undef, i16 1, i16 undef, i16 1, i16 undef> to <16 x i8>
   ret <16 x i8> %cast
@@ -262,7 +262,7 @@ define <16 x i8> @bitcast_constexpr_16i8_8i16_1u1u1u1u() {
 
 define <16 x i8> @bitcast_constexpr_16i8_8i16_u256uuu256uu() {
 ; CHECK-LABEL: @bitcast_constexpr_16i8_8i16_u256uuu256uu(
-; CHECK-NEXT:    ret <16 x i8> bitcast (<8 x i16> <i16 undef, i16 256, i16 undef, i16 undef, i16 undef, i16 256, i16 undef, i16 undef> to <16 x i8>)
+; CHECK-NEXT:    ret <16 x i8> <i8 undef, i8 undef, i8 0, i8 1, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef, i8 0, i8 1, i8 undef, i8 undef, i8 undef, i8 undef>
 ;
   %cast = bitcast <8 x i16><i16 undef, i16 256, i16 undef, i16 undef, i16 undef, i16 256, i16 undef, i16 undef> to <16 x i8>
   ret <16 x i8> %cast