<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/108421>108421</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            Miscalculation after SLP Vectorizer Pass
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            new issue
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
            alexey-bataev
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          ivankelarev
      </td>
    </tr>
</table>

<pre>
    The SLP Vectorizer produces an incorrect result for this test case:

```
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

@b = global [64 x i32] zeroinitializer
@c = global [64 x i32] zeroinitializer
@.str = constant [10 x i8] c"res = %d\0A\00"

define i32 @foo(i32 %a) #0 {
entry:
  %0 = add i32 0, 0
  %d = load i32, ptr @b, align 4
 %1 = add i32 0, 0
  %2 = mul i32 %0, 0
  store i32 %2, ptr getelementptr inbounds ([64 x i32], ptr @b, i64 0, i64 24), align 16
  %3 = or i32 0, %d
  store i32 %3, ptr getelementptr inbounds ([64 x i32], ptr @c, i64 0, i64 22), align 8
  %4 = add i32 0, 0
  %5 = mul i32 0, %1
  store i32 %5, ptr getelementptr inbounds ([64 x i32], ptr @b, i64 0, i64 23), align 4
  %6 = or i32 0, %d
  store i32 %6, ptr getelementptr inbounds ([64 x i32], ptr @c, i64 0, i64 21), align 4
  %7 = add i32 0, 0
  %8 = mul i32 0, %4
  store i32 %8, ptr getelementptr inbounds ([64 x i32], ptr @b, i64 0, i64 22), align 8
  %9 = or i32 0, %d
  store i32 %9, ptr getelementptr inbounds ([64 x i32], ptr @c, i64 0, i64 20), align 16
  %10 = or i32 %a, 0
  %11 = mul i32 0, %7
  store i32 %11, ptr getelementptr inbounds ([64 x i32], ptr @b, i64 0, i64 21), align 4
  %12 = add i32 0, 2
  store i32 %12, ptr getelementptr inbounds ([64 x i32], ptr @c, i64 0, i64 19), align 4
  %13 = add i32 0, 3
  %14 = mul i32 0, %10
  store i32 %14, ptr getelementptr inbounds ([64 x i32], ptr @b, i64 0, i64 20), align 16
  %15 = or i32 0, %10
  store i32 %15, ptr getelementptr inbounds ([64 x i32], ptr @c, i64 0, i64 18), align 8
  %16 = add i32 0, 0
  %17 = mul i32 2, %13
  store i32 %17, ptr getelementptr inbounds ([64 x i32], ptr @b, i64 0, i64 19), align 4
  %18 = or i32 0, %d
  store i32 %18, ptr getelementptr inbounds ([64 x i32], ptr @c, i64 0, i64 17), align 4
  %19 = add i32 0, 0
  %20 = mul i32 0, %16
  store i32 %20, ptr getelementptr inbounds ([64 x i32], ptr @b, i64 0, i64 18), align 8
  %21 = or i32 0, %d
  store i32 %21, ptr getelementptr inbounds ([64 x i32], ptr @c, i64 0, i64 16), align 16
  %22 = mul i32 0, %19
  store i32 %22, ptr getelementptr inbounds ([64 x i32], ptr @b, i64 0, i64 17), align 4
  %23 = or i32 0, %17
  store i32 %23, ptr getelementptr inbounds ([64 x i32], ptr @c, i64 0, i64 15), align 4
 %24 = mul i32 %19, 0
  %25 = load i32, ptr getelementptr inbounds ([64 x i32], ptr @c, i64 0, i64 19), align 4
  ret i32 %25
}

define i32 @main() {
  %res1 = call i32 @foo(i32 0)
  %call = call i32 @printf(ptr @.str, i32 %res1)
  ret i32 0
}

declare i32 @printf(...)

attributes #0 = { "target-cpu"="cascadelake" }
```

It's easy to see that foo's return value should be equal to 2, as it is loaded from c[19], where the value of %12, which is equal to 2, has been previously stored. After the SLP transformation, the IR looks like this:

```
define i32 @foo(i32 %a) #0 {
entry:
  %0 = insertelement <8 x i32> <i32 0, i32 0, i32 3, i32 poison, i32 0, i32 0, i32 0, i32 0>, i32 %a, i32 3
  %1 = add <8 x i32> %0, zeroinitializer
  %2 = or <8 x i32> %0, zeroinitializer
  %3 = shufflevector <8 x i32> %1, <8 x i32> %2, <8 x i32> <i32 0, i32 1, i32 2, i32 11, i32 4, i32 5, i32 6, i32 7>
  %d = load i32, ptr @b, align 4
  %4 = mul <8 x i32> <i32 0, i32 0, i32 2, i32 0, i32 0, i32 0, i32 0, i32 0>, %3
  store <8 x i32> %4, ptr getelementptr inbounds ([64 x i32], ptr @b, i64 0, i64 17), align 4
  %5 = shufflevector <8 x i32> %4, <8 x i32> %3, <4 x i32> <i32 2, i32 poison, i32 11, i32 poison>
  %6 = shufflevector <4 x i32> %5, <4 x i32> poison, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 poison, i32 poison, i32 poison, i32 poison>
  %7 = insertelement <4 x i32> %5, i32 %d, i32 1
  %8 = shufflevector <4 x i32> %7, <4 x i32> poison, <8 x i32> <i32 0, i32 1, i32 1, i32 2, i32 3, i32 1, i32 1, i32 1>
  %9 = or <8 x i32> zeroinitializer, %8
  %10 = add <8 x i32> zeroinitializer, %8
  %11 = shufflevector <8 x i32> %9, <8 x i32> %10, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 12, i32 5, i32 6, i32 7>
  store <8 x i32> %11, ptr getelementptr inbounds ([64 x i32], ptr @c, i64 0, i64 15), align 4
  %12 = extractelement <8 x i32> %3, i32 0
  %13 = mul i32 %12, 0
  %14 = load i32, ptr getelementptr inbounds ([64 x i32], ptr @c, i64 0, i64 19), align 4
  ret i32 %14
}
```

It appears that a poison value is now being written to c[19], which is incorrect. The issue can be reproduced in the following way:

```
$ llc -O0 test.ll && clang test.s -o a.out && ./a.out
res = 2
$ opt -passes=slp-vectorizer -S -o j.ll test.ll && llc -O0 j.ll && clang j.s -o a.out && ./a.out
res = 6
```

The issue seems to be reproducible with the latest clang build. @alexey-bataev, could you please take a look?

</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzEWV2P6ygS_TXkBTky-PshD31vT0sj7WpHe0f7usJ2OaGbQBZwunt-_QrsfDgmmcztrFZquTFQxfGhKJ-KmTF8LQFWKPuGKGUCPuAzqpllsEeUoux5wXq7UXrF90y-gWAa9otatZ-r3zeAf_ztN_wvaKzS_A_QeKdV2zdgMJOYy0ZpDY3FGkwvLO6UxnbDDbZgLG6YAZQ8ofgZxYdrHo9__tYyvQaLW2aZYJ-qtxglzxhRCtEWJU8Q7WgRo-Qpof7ibsn01rXy1F8ifmwQWqLkidAy6sp4bEnflR_M8zT64aZROoFiNd8JOMD4KPN_52nUyzep3mUkuOw_orXsj1bjNY1rb7IWqmYCo-xbnuIPzBPHLv4DtOKSW86Eo_Bo0_yEzdJY7c0aJY1l0jpDEjvD0tk1iFINZnyArEXZ9_jJXeILzC10XIJbDqM07pRCtPQ3NGOIVhjRJMao-DbMBmn153EvsZsV-zVY23ofMaLfcXw23PphoZgfd6M7hzyNa9dmgq8lTsf5iGbktjfqh7e9wCPG6QxjlYbD0HGxNVgQsAVp3R2XteplazCi5ZTsS3A8TwcErkFTRKsTZJKfoUo8KqVPmD3lIVDJF0A1c1B0Aqo8w5TeJjKbEHnATIKYs8cSmUwwp2eg8vt5zB_LI7mKqbjNYxnkMQ1iLh_L4_W9r-7nsXosj_H1Q0Lic1RDeplySUiQzCIInJDHsnk9AgidhwANY_pKypmzSarrmJI5puR8PA2f73CmJOljubwVBVkoNq_h-krmCfBZXj0xJL99zEkx4ZMecCdh3MVD-bwVB-X9R518Jf8E2Cyuo6r-5C0eh6MzD7_H48eyeT0KKLmfTfqV_BNgM79-ZigN01WFgT1W99zYZhrUPSScr-ljlY9LDQFYbqH0UiOSahaAWVCV_k-ztgZ75CIbFXjxfF2KbxmXbmWnwQ_y24PXYIY4bZgQc-Huk-9ptp90OXunubQdouX4FK6a8PgHfG6FMy8H5PEV1I2rFGeul8vl0cdwZdZqXvfWlSW-qnC1SfHNFVhD1RU1O19SJc-I0oaZhrUg2BsgdwKOq05Lx-H6q0W0MBiY-cRWYQOA7Ya5QlT5AQ221xLvmegBm43qRYtrwPCfngln4EOAGcwt5sbHBbS402qLG1dXVeOmv29AO88welLd6bX_vuHNxllPnW6YwTWAxDsNe656Iz6Hg9Eu8VNnQXt3rri2mknTKb1llivpbN3Ir__EQqk3gwV_A19U3y6lH1TPcWlAH04DRsn3coz-5Bd3dzzwk0ZyaOwUN8MjhCeeNZJfzgKPnTydvU2OL5MLGGP1FyyRz6pFpf-y4ZDYzKbvOgF7_6PH3Id_Acx6aaD3gi9yaNBjz7ErPTSyQyM_NArH1c8V1qeC0KXFO3eT3rV_FxvpS9xJ_p8x9FixeeP9lN2zi2lwF5OxN53xRMMxftrBsX-yV3kYSTpZM5uveVrjr0bUlaN4x90EeBFOBgHg4wluT5Aui-Q_efziAY9_g4f5HDJ91CqcLC6TxBDj5bywnSeoO0zJPSFaBUOUxF-KC0LvyzRXDvGXyu-75dxZ-Q0fVrPm2htpPLFnKuW8TD7XgnRW2qX_Vy1I0ktVFdY3mO12wLQZdA0bz8aoQ7jBUr3jGrhc43fNrQXpFMiFeBkFyvHn-iX-feOMTQ-4YdIpIg3jD_st5tILkE4Jod69Y_Z5W3sgmmIhGhz9I_a__C-d9KQ5ojluBJProdPgSGG29L_yD4NLRF98x-Dm8Ls1PXlVO4ujHTMGDEqejdhF-9OniOiH8_jqVrtY9QDmdYbk9X4Y-Y19OfFnALbGcX5GIq8F4HduN55IwYavIX79uueiXbqoufgO8x03Xp1-qh7vBDAD2LI3wMzLQJS8DAsv2lXSVknFFrAiBc1JHsdJsdisyiQv26ouaFHlaVxWedyQrugyVtUM4pgt-IrGNI0rQkmeJVmxzEnNWAFdk3ddRTuG0hi2jIulEPvtUun1wj_hisRlSslCsBqEGT8iSXgfnn_8gKRXziiq-7VBaSy4sebkxnIrYPV3bhomml54mYuZ18AXH5d-Y8Ysei1WG2t3XvDSF0Rf1txu-nrZqC2iL87t-C_aafUKjUX0xYMxiL6MaPcr-t8AAAD__z0mMCE">