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

    <tr>
        <th>Summary</th>
        <td>
            [LV] Cost computation skipped for hoisted vector code
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            bug,
            vectorizers,
            vectorization
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
            artagnon
      </td>
    </tr>

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

<pre>
    Consider an intrinsic that has an invalid SVE cost like in https://godbolt.org/z/4M46fvMnc:

```llvm
; RUN: opt -mtriple aarch64 -mattr=+sve -passes="print<cost-model>"

define <4 x float> @minimumnum.fixed(<4 x float> %a, <4 x float> %b) {
  %c = call <4 x float> @llvm.minimumnum(<4 x float> %a, <4 x float> %b)
  ret <4 x float> %c
}

define <vscale x 4 x float> @minimumnum(<vscale x 4 x float> %a, <vscale x 4 x float> %b) {
  %c = call <vscale x 4 x float> @llvm.minimumnum(<vscale x 4 x float> %a, <vscale x 4 x float> %b)
  ret <vscale x 4 x float> %c
}
```

Now, running loop-vectorize should respect this invalid cost, and not produce a `<vscale x 4 x float> @llvm.minimumnum`. Running this:

```llvm
; RUN: opt -passes=loop-vectorize,simplifycfg -mtriple=aarch64 -mattr=+sve -S %s

define void @vectorized_hoisted(ptr %p) {
entry:
  br label %loop

loop: ; preds = %loop, %entry
  %iv = phi i64 [ 1, %entry ], [ %iv.next, %loop ]
  %idx = phi i64 [ 0, %entry ], [ %idx.next, %loop ]
  %res = tail call float @llvm.minimumnum.f32(float 0.0, float 0.0)
  %gep.p.red = getelementptr float, ptr %p, i64 %idx
  store float %res, ptr %gep.p.red, align 4
  %idx.next = add i64 %idx, 1
  %iv.next = add i64 %iv, 1
 %exit.cond = icmp eq i64 %iv.next, 0
  br i1 %exit.cond, label %exit, label %loop

exit:                                              ; preds = %loop
 ret void
}

declare float @llvm.minimumnum.f32(float, float)
```

yields:

```llvm
; ModuleID = 'reduced.ll'
source_filename = "reduced.ll"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32"
target triple = "aarch64"

define void @vectorized_hoisted(ptr %p) #0 {
entry:
  %0 = call i64 @llvm.vscale.i64()
  %1 = mul nuw i64 %0, 8
 %n.mod.vf = urem i64 -1, %1
  %n.vec = sub i64 -1, %n.mod.vf
  %2 = call i64 @llvm.vscale.i64()
  %3 = mul nuw i64 %2, 8
  %4 = add i64 1, %n.vec
 %5 = call <vscale x 4 x float> @llvm.minimumnum.nxv4f32(<vscale x 4 x float> zeroinitializer, <vscale x 4 x float> zeroinitializer)
  br label %vector.body

vector.body:                                      ; preds = %vector.body, %entry
  %index = phi i64 [ 0, %entry ], [ %index.next, %vector.body ]
  %6 = getelementptr float, ptr %p, i64 %index
  %7 = call i64 @llvm.vscale.i64()
  %8 = mul nuw i64 %7, 4
  %9 = getelementptr float, ptr %6, i64 %8
  store <vscale x 4 x float> %5, ptr %6, align 4
  store <vscale x 4 x float> %5, ptr %9, align 4
  %index.next = add nuw i64 %index, %3
  %10 = icmp eq i64 %index.next, %n.vec
  br i1 %10, label %middle.block, label %vector.body, !llvm.loop !0

middle.block: ; preds = %vector.body
  %cmp.n = icmp eq i64 -1, %n.vec
  br i1 %cmp.n, label %exit, label %loop

loop: ; preds = %middle.block, %loop
  %iv = phi i64 [ %iv.next, %loop ], [ %4, %middle.block ]
  %idx = phi i64 [ %idx.next, %loop ], [ %n.vec, %middle.block ]
  %res = tail call float @llvm.minimumnum.f32(float 0.000000e+00, float 0.000000e+00)
  %gep.p.red = getelementptr float, ptr %p, i64 %idx
  store float %res, ptr %gep.p.red, align 4
  %idx.next = add i64 %idx, 1
  %iv.next = add i64 %iv, 1
 %exit.cond = icmp eq i64 %iv.next, 0
  br i1 %exit.cond, label %exit, label %loop, !llvm.loop !3

exit:                                             ; preds = %middle.block, %loop
  ret void
}

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare float @llvm.minimumnum.f32(float, float) #1

; Function Attrs: nocallback nofree nosync nounwind willreturn memory(none)
declare i64 @llvm.vscale.i64() #2

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare <vscale x 4 x float> @llvm.minimumnum.nxv4f32(<vscale x 4 x float>, <vscale x 4 x float>) #3

attributes #0 = { "target-features"="+sve" }
attributes #1 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) "target-features"="+sve" }
attributes #2 = { nocallback nofree nosync nounwind willreturn memory(none) }
attributes #3 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

!0 = distinct !{!0, !1, !2}
!1 = !{!"llvm.loop.isvectorized", i32 1}
!2 = !{!"llvm.loop.unroll.runtime.disable"}
!3 = distinct !{!3, !2, !1}
```

LV doesn't seem to cost hoisted instructions. No crash is observed yet due to this bug, but https://github.com/llvm/llvm-project/pull/145545 exhibits a crash.

CC: @davemgreen, @fhahn, @lukel97.
</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJzsWM1u4zgSfhrmUrAgUZKtHHxwnA6wwHQfprF9HdBi2eaGIrUk5Xb66RckZVmOfzbOzO5pAsMxpariV_9FMmvFRiHOSflEKGXGsY3SilBKyucH1rmtNvPD04eV5m_zpVZWcDTAFAjljFBW1OC2zMGW2fh0x6Tg8P3HF6i1dSDFK4JQsHWutSRfEPpC6MtG85WWLtFmQ-jLL0Jfiq_FdL37qmpPk4bPNI0fKXeNX-dP8Ps_v5F8Abp1MGmcEa1EYMzU22kBk4Y5Z0j-TOiT3SFMWmYt2vCAtkYoR_KlxzRpNEdJ8i9e1bAVx7VQCCRfFrCHtdTMkfwLkCJthBJN16iuSdZij5zQ6oyKlozQ5Tk3LVeEPgKZPZF0AX5dA8mfoWZSXtrL65kcN7x_q7CNQXfpfe01nT2_13dnayYR9nBd8YjjCuER0FWC20a4CuCiNf4cirF9rhKODHUIwGi0b_qn38R0Sgm1Aal1O9lh7bQRvxDsVneSg0HbYu3AbYUdksEHnWdlioPSDlqjeVcjMPDC77DBNE3g935_v8OHc2VIhVPUhC6taFop1m_1ejOkFMmfrybVd28jexJGOy24RzuI5X9stbAuZEvrjOdoj0GAypm3iBxgZUCyFUpP47FFweFXvgCvRmuQ2xAyBxLvaVpGMX1MiV2gaLcCxLQAUj5BNqYDUj6HdfkUyROFe9dTeKGB4CCM78-kpbek8f0tcQYjfMeEjGEfXHzBv8k6p4RW8XWahD1Hi8eDxA22SZsY5EHuBh1KbFA5b-sYPnQJR8MvoxYBaBBhnTZ4QBEAjhgG4SFipdgoKEaWCZqGfRnnY8F0CdnRHZfJdgOVN-VeuKTWKmoh6qYF_PeRdDBpeggUkZ2w-XdD7PinJw-OwRRe5Qu46-9y5KWLUD58wJ-W01qyo0Vv-nXwafTnuxrzJlDy22n9VfNO4j-ee2Azg76W8ERKQmckXVjdmRr_WAuJijXYk9Exme96jpkNOuDMMcnedOcOhDhpSL7ASUtnKckXOQ1ffpmdLv2vaRG-JqIi-aKKr0Q2JfkifPnVQJL5Cr7IaDVReeSdfPerF78cY-r7eo-nr0Tve_XHiw7N00uVh9AyPXaiEHa942I5TjxyWo3SLgvkTSdBdT8PgRqStOpDWiWN5sluHQg7g02gmhxK0ZAfKtlhbIO2W53SHEQcSOl9GPNLGOmA0a-Kk7Q87rvDulej_FSHTtR-V8RIv8r1C40WSjjBpPiF5mbTPqN9POsY0fmJn01jcIwffDTlz1J9LORSr1Ec72wQnmPcIkY7jDvF9N567uUemGf3BUp1KVBmXvhQ7R8_AGc6glONmsutCat8zz_uMvexP15qUoO1h0AfqRhtFt2QD5mdXuxB79025MixG2XpSddpBOcSk5XU9evJi7OYyoJ34qxAs778n7Bfmn9OAz6O002bqDP4k7O8PmIOHB_tnldHsfeqjnrklYns-uB1TJWifzWW_t9msxsj2FFwtMNt4Z-f1MIfEvqUng5tJ8__nt_und8uZEr--aHurhC-NOd5AS-dqp3QChbOGT-pgdI-VFasfgWl1wYRlLZvqgalO_VTKA7-SNhJ5thKIvwUUhp0nVHQYKPNG6GV0gpjfHx2lPRjTvbnUH4M2K3e4kHQ_7up_toR5dZI0qvYh6A_GItV53zRCDOmD6qZLzY0DrKTNTLXheyk8RYqHqIJpRBj6lRENoj46-z0eTT0DjQ3AVyQnf9PNB3SlPb9nAvrhKp9kcz8CYBm_ZSW9d0xoz0TzXrjHwgJpUPZSYQ9njKC3ZYgcgrZwExvMHfKaCkT0yknGky4sF4TL-bAnV8Bmw8gD6AvXUv99gO4RqsInTmwiA04Ha9e-_MQCGWd6UIq2gS-aagNs1sQFvTKotkhhzd_FOzQs4abq1W38ZuuOvf-4la4bbdKat0Q-hJOpfHfpDX6X1g7Ql_azp8xX7KiLIsScL8VK-EssLhtElEvl2GoKFLOdthsDGKYSEiRrrdse_gtu1eUj7Pkgc9z_pg_sgecZ7OySPMiq-jDdp6XVUn5GutstV4XWZnlnFXTKmXVbLVm9fRBzGlKy7RKs3RW5ClN8llBK5pmdVUVU7pOSZFiw4RMgse02TwIazucZ2U2nRYPoR_Z_oo8WMV7g1A6RISxZ8-YN3V_j27mwTyrbmO9QsI6e9zKCSfD_ftvP0j5DEvvtVo3beeCCLCvom2Rw1qbwZtxE6g1x4fOyPnd_gn6We-hqOJuTv8TAAD__5yjFFA">