# Reason for duplicated llvm code in pseudo-vtable

**URL:** <https://discourse.julialang.org/t/reason-for-duplicated-llvm-code-in-pseudo-vtable/110719>\
**Category:** Internals & Design\
**Tags:** question\
**Created:** [February 25, 2024, 1:41am UTC](https://discourse.julialang.org/t/reason-for-duplicated-llvm-code-in-pseudo-vtable/110719 "2024-02-25T01:41:50Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![wheeheee](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wheeheee/32/36663_2.png) [@wheeheee](https://discourse.julialang.org/u/wheeheee)\
**Post date:** [February 25, 2024, 1:41am UTC](https://discourse.julialang.org/t/reason-for-duplicated-llvm-code-in-pseudo-vtable/110719/1 "2024-02-25T01:41:50Z")

</div>

Apologies if this is answered somewhere else, but I couldn’t find it.  
I have the following two functions; `testvt` is intended to do some sort of dispatch, while remaining type-stable:

```julia
@noinline f(x, a, b, c, ::Val{N}) where N = muladd.(x, 0.1a + 0.5b + 2c, N*c)
testvt(x, a, b, c, k) = Base.@nif 10 d -> (k == d) d -> f(x, a, b, c, Val(d))

```

With these arguments:

```julia
x, a, b, c = (rand(1000) for _ in 1:4)

```

It looks like there is a lot of duplicated llvm code.

> **all vector args**
>
> ```julia
> julia> @code_llvm testvt(x, a, b, c, 10)
> ; @ REPL[2]:1 within `testvt`
> ; Function Attrs: uwtable
> define nonnull {}* @julia_testvt_226({}* noundef nonnull align 16 dereferenceable(40) %0, {}* noundef nonnull align 16 dereferenceable(40) %1, {}* noundef nonnull align 16 dereferenceable(40) %2, {}* noundef nonnull align 16 dereferenceable(40) %3, i64 signext %4) #0 {
> top:
> %5 = alloca [5 x {}*], align 8
> %.sub = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 0
> switch i64 %4, label %L37 [
> i64 1, label %L3
> i64 2, label %L7
> i64 3, label %L11
> i64 4, label %L15
> i64 5, label %L19
> i64 6, label %L23
> i64 7, label %L27
> i64 8, label %L31
> i64 9, label %L35
> ]
> 
> common.ret: ; preds = %L37, %L35, %L31, %L27, %L23, %L19, %L15, %L11, %L7, %L3
> %common.ret.op = phi {}* [%10, %L3], [%15, %L7], [%20, %L11], [%25, %L15], [%30, %L19], [%35, %L23], [%40, %L27], [%45, %L31], [%50, %L35], [%55, %L37]
> ret {}* %common.ret.op
> 
> L3: ; preds = %top
> store {}* %0, {}** %.sub, align 8
> %6 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 1
> store {}* %1, {}** %6, align 8
> %7 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 2
> store {}* %2, {}** %7, align 8
> %8 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 3
> store {}* %3, {}** %8, align 8
> %9 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 4
> store {}* inttoptr (i64 140735412136144 to {}*), {}** %9, align 8
> %10 = call nonnull {}* @j1_f_228({}* inttoptr (i64 2425037407000 to {}*), {}** nonnull %.sub, i32 5)
> br label %common.ret
> 
> L7: ; preds = %top
> store {}* %0, {}** %.sub, align 8
> %11 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 1
> store {}* %1, {}** %11, align 8
> %12 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 2
> store {}* %2, {}** %12, align 8
> %13 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 3
> store {}* %3, {}** %13, align 8
> %14 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 4
> store {}* inttoptr (i64 140735412139296 to {}*), {}** %14, align 8
> %15 = call nonnull {}* @j1_f_229({}* inttoptr (i64 2425037407000 to {}*), {}** nonnull %.sub, i32 5)
> br label %common.ret
> 
> L11: ; preds = %top
> store {}* %0, {}** %.sub, align 8
> %16 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 1
> store {}* %1, {}** %16, align 8
> %17 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 2
> store {}* %2, {}** %17, align 8
> %18 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 3
> store {}* %3, {}** %18, align 8
> %19 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 4
> store {}* inttoptr (i64 140735427216096 to {}*), {}** %19, align 8
> %20 = call nonnull {}* @j1_f_230({}* inttoptr (i64 2425037407000 to {}*), {}** nonnull %.sub, i32 5)
> br label %common.ret
> 
> L15: ; preds = %top
> store {}* %0, {}** %.sub, align 8
> %21 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 1
> store {}* %1, {}** %21, align 8
> %22 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 2
> store {}* %2, {}** %22, align 8
> %23 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 3
> store {}* %3, {}** %23, align 8
> %24 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 4
> store {}* inttoptr (i64 140735425748336 to {}*), {}** %24, align 8
> %25 = call nonnull {}* @j1_f_231({}* inttoptr (i64 2425037407000 to {}*), {}** nonnull %.sub, i32 5)
> br label %common.ret
> 
> L19: ; preds = %top
> store {}* %0, {}** %.sub, align 8
> %26 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 1
> store {}* %1, {}** %26, align 8
> %27 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 2
> store {}* %2, {}** %27, align 8
> %28 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 3
> store {}* %3, {}** %28, align 8
> %29 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 4
> store {}* inttoptr (i64 140735427217952 to {}*), {}** %29, align 8
> %30 = call nonnull {}* @j1_f_232({}* inttoptr (i64 2425037407000 to {}*), {}** nonnull %.sub, i32 5)
> br label %common.ret
> 
> L23: ; preds = %top
> store {}* %0, {}** %.sub, align 8
> %31 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 1
> store {}* %1, {}** %31, align 8
> %32 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 2
> store {}* %2, {}** %32, align 8
> %33 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 3
> store {}* %3, {}** %33, align 8
> %34 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 4
> store {}* inttoptr (i64 140735427219520 to {}*), {}** %34, align 8
> %35 = call nonnull {}* @j1_f_233({}* inttoptr (i64 2425037407000 to {}*), {}** nonnull %.sub, i32 5)
> br label %common.ret
> 
> L27: ; preds = %top
> store {}* %0, {}** %.sub, align 8
> %36 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 1
> store {}* %1, {}** %36, align 8
> %37 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 2
> store {}* %2, {}** %37, align 8
> %38 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 3
> store {}* %3, {}** %38, align 8
> %39 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 4
> store {}* inttoptr (i64 2425037422688 to {}*), {}** %39, align 8
> %40 = call nonnull {}* @j1_f_234({}* inttoptr (i64 2425037407000 to {}*), {}** nonnull %.sub, i32 5)
> br label %common.ret
> 
> L31: ; preds = %top
> store {}* %0, {}** %.sub, align 8
> %41 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 1
> store {}* %1, {}** %41, align 8
> %42 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 2
> store {}* %2, {}** %42, align 8
> %43 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 3
> store {}* %3, {}** %43, align 8
> %44 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 4
> store {}* inttoptr (i64 2425037408776 to {}*), {}** %44, align 8
> %45 = call nonnull {}* @j1_f_235({}* inttoptr (i64 2425037407000 to {}*), {}** nonnull %.sub, i32 5)
> br label %common.ret
> 
> L35: ; preds = %top
> store {}* %0, {}** %.sub, align 8
> %46 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 1
> store {}* %1, {}** %46, align 8
> %47 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 2
> store {}* %2, {}** %47, align 8
> %48 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 3
> store {}* %3, {}** %48, align 8
> %49 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 4
> store {}* inttoptr (i64 140735423996592 to {}*), {}** %49, align 8
> %50 = call nonnull {}* @j1_f_236({}* inttoptr (i64 2425037407000 to {}*), {}** nonnull %.sub, i32 5)
> br label %common.ret
> 
> L37: ; preds = %top
> store {}* %0, {}** %.sub, align 8
> %51 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 1
> store {}* %1, {}** %51, align 8
> %52 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 2
> store {}* %2, {}** %52, align 8
> %53 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 3
> store {}* %3, {}** %53, align 8
> %54 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 4
> store {}* inttoptr (i64 140735432190096 to {}*), {}** %54, align 8
> %55 = call nonnull {}* @j1_f_237({}* inttoptr (i64 2425037407000 to {}*), {}** nonnull %.sub, i32 5)
> br label %common.ret
> }
> 
> ```

But with just one less vector argument, it looks a whole lot cleaner:

> **c = 1.**
>
> ```julia
> julia> @code_llvm testvt(x, a, b, 1., 10)
> ; @ REPL[2]:1 within `testvt`
> ; Function Attrs: noreturn uwtable
> define void @julia_testvt_277({}* noundef nonnull align 16 dereferenceable(40) %0, {}* noundef nonnull align 16 dereferenceable(40) %1, {}* noundef nonnull align 16 dereferenceable(40) %2, double %3, i64 signext %4) #0 {
> top:
> switch i64 %4, label %L37 [
> i64 1, label %L3
> i64 2, label %L7
> i64 3, label %L11
> i64 4, label %L15
> i64 5, label %L19
> i64 6, label %L23
> i64 7, label %L27
> i64 8, label %L31
> i64 9, label %L35
> ]
> 
> L3: ; preds = %top
> call void @j_f_279({}* nonnull %0, {}* nonnull %1, {}* nonnull %2, double %3) #6
> unreachable
> 
> L7: ; preds = %top
> call void @j_f_280({}* nonnull %0, {}* nonnull %1, {}* nonnull %2, double %3) #6
> unreachable
> 
> L11: ; preds = %top
> call void @j_f_281({}* nonnull %0, {}* nonnull %1, {}* nonnull %2, double %3) #6
> unreachable
> 
> L15: ; preds = %top
> call void @j_f_282({}* nonnull %0, {}* nonnull %1, {}* nonnull %2, double %3) #6
> unreachable
> 
> L19: ; preds = %top
> call void @j_f_283({}* nonnull %0, {}* nonnull %1, {}* nonnull %2, double %3) #6
> unreachable
> 
> L23: ; preds = %top
> call void @j_f_284({}* nonnull %0, {}* nonnull %1, {}* nonnull %2, double %3) #6
> unreachable
> 
> L27: ; preds = %top
> call void @j_f_285({}* nonnull %0, {}* nonnull %1, {}* nonnull %2, double %3) #6
> unreachable
> 
> L31: ; preds = %top
> call void @j_f_286({}* nonnull %0, {}* nonnull %1, {}* nonnull %2, double %3) #6
> unreachable
> 
> L35: ; preds = %top
> call void @j_f_287({}* nonnull %0, {}* nonnull %1, {}* nonnull %2, double %3) #6
> unreachable
> 
> L37: ; preds = %top
> call void @j_f_288({}* nonnull %0, {}* nonnull %1, {}* nonnull %2, double %3) #6
> unreachable
> }
> 
> ```

Is there some reason for this? I don’t have too much knowledge about processors/codegen in general, so I would appreciate some enlightenment.

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [February 25, 2024, 3:15am UTC](https://discourse.julialang.org/t/reason-for-duplicated-llvm-code-in-pseudo-vtable/110719/2 "2024-02-25T03:15:50Z")

</div>

[@nif](https://docs.julialang.org/en/v1/devdocs/cartesian/#Base.Cartesian.@nif) transforms an expression into an if statement with near-duplicate branches, that’s why you see 10 near-duplicates. The initial switch block just jumps to one of the branches. The “cleaner” call has 10 near-duplicate branches that are unreachable because the compiler knows that `(0.1a + 0.5b) + 2c` when `c` is a scalar lacks an implementation method. Elementwise operations, especially between instances with different dimensions, are usually done with dot syntax broadcasting `.+`; a few non-broadcasted elementwise matrix-matrix and vector-vector operations are only supported for the sake of linear algebra.

---

<div class="post-metadata">

**Author:** ![wheeheee](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wheeheee/32/36663_2.png) [@wheeheee](https://discourse.julialang.org/u/wheeheee)\
**Post date:** [February 25, 2024, 3:31am UTC](https://discourse.julialang.org/t/reason-for-duplicated-llvm-code-in-pseudo-vtable/110719/3 "2024-02-25T03:31:25Z")

</div>

Sorry, I messed up that function. However, I think the `@noinline` stops the compiler from reasoning about the contents of `f`. Anyway, even with

```julia
@noinline f(x, a, b, c, ::Val{N}) where N = x * N

```

which is valid code that does not error, this still happens.

EDIT: simplified further. also, a small modification to return a tuple triggers the duplication.

```julia
@noinline f(x, a, b, c, ::Val{N}) where N = (x * N, N)

```

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [February 25, 2024, 5:09am UTC](https://discourse.julialang.org/t/reason-for-duplicated-llvm-code-in-pseudo-vtable/110719/4 "2024-02-25T05:09:54Z")

</div>

> [@wheeheee](#):
>
> However, I think the `@noinline` stops the compiler from reasoning about the contents of `f`

This is true for some other cases but it has nothing to do with the duplicated `unreachable` branches of the erroring call and is already present in the working call you posted. All the `getelementpr` are just preparing for the `call nonnull ...` non-inlined function call.

> [@wheeheee](#):
>
> this still happens.

Of course changes to `f` don’t affect the duplication because it is the `@nif` in `testvt` that duplicates code across if-statement branches.

---

<div class="post-metadata">

**Author:** ![wheeheee](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wheeheee/32/36663_2.png) [@wheeheee](https://discourse.julialang.org/u/wheeheee)\
**Post date:** [February 25, 2024, 6:58am UTC](https://discourse.julialang.org/t/reason-for-duplicated-llvm-code-in-pseudo-vtable/110719/5 "2024-02-25T06:58:56Z")

</div>

Ok, I think I read this too hastily

> [@Benny](#):
>
> The “cleaner” call has 10 near-duplicate branches that are unreachable because the compiler knows that `(0.1a + 0.5b) + 2c` when `c` is a scalar lacks an implementation method.

as saying that the cleaner call is so because `f` will error as I neglected a broadcast, leading to unreachable branches in `testvt` and no `getelementptr`s.

IIRC, what you meant is that the function calls of different methods of `f` along with the `getelementptr`s etc. that prepare for the calls or `unreachable`s are copy-pasted into the if-else blocks.

In this case, if `c=1.`, `f` is just called in a nicer way. I mistakenly assumed that they were all called the same way, and that the prep for `testvt` with `c=1.` was brought to the top, although there isn’t any prep now that I look at it again.

But then I have two questions:

1. How does Julia decide which method (EDIT: in `code_llvm`, directly `call …` or to do something like `%5 = alloca [5 x {}*], align 8` and store things in `.sub`, then calling a function with that as an argument) is used to call a function?
2. Is there a reason the compiler / optimizer is unable to detect that most of the preparations for these function calls are identical, and hoist some `getelementptr`s and `store`s / `unreachable` out, or is it not good for the compiler to do that, or just that someone hasn’t written a compiler pass for a niche case yet?

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [February 25, 2024, 7:39am UTC](https://discourse.julialang.org/t/reason-for-duplicated-llvm-code-in-pseudo-vtable/110719/6 "2024-02-25T07:39:10Z")

</div>

> [@wheeheee](#):
>
> How does Julia decide which method is used to call a function?

The call-time types of the callable and the arguments are used to find the most specific method signature, if it exists, and compile the method for those types. In this case it’s done at compile-time per branch so you only see the function pointers being accessed. I don’t know the internals.

> [@wheeheee](#):
>
> someone hasn’t written a compiler pass for a niche case yet?

I’d guess this but not sure; it doesn’t seem worth examining all branches of an if-statement on the off-chance that you can hoist and merge the cheap arguments-loading phase of a function call. As far as I can tell, the `@nif` if-statement lacks an argument for a custom else clause so it does 9 cases `k in 1:9` and does the call with `Val(10)` for an `else` clause, so the argument loading (`store`, `getelementpr`) does seem inevitable and identical. The calls to separately compiled code and `unreachable` must be specific to each branch.

---

<div class="post-metadata">

**Author:** ![mnemnion](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mnemnion/32/206596_2.png) [@mnemnion](https://discourse.julialang.org/u/mnemnion)\
**Post date:** [February 25, 2024, 8:25pm UTC](https://discourse.julialang.org/t/reason-for-duplicated-llvm-code-in-pseudo-vtable/110719/7 "2024-02-25T20:25:04Z")

</div>

> [@wheeheee](#):
>
> However, I think the `@noinline` stops the compiler from reasoning about the contents of `f`.

What’s the purpose of `@noinline` here?

---

<div class="post-metadata">

**Author:** ![wheeheee](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wheeheee/32/36663_2.png) [@wheeheee](https://discourse.julialang.org/u/wheeheee)\
**Post date:** [February 25, 2024, 11:45pm UTC](https://discourse.julialang.org/t/reason-for-duplicated-llvm-code-in-pseudo-vtable/110719/8 "2024-02-25T23:45:45Z")

</div>

In this example, I just wanted to prevent the inling of `f`, so that it is called from `testvt`. I didn’t realize it wasn’t going to (completely) inline anyway. I guess it also prevented this from happening:

> **no noinline**
>
> ```julia
> julia> f(x, a, b, c, ::Val{N}) where N = x * N
> f (generic function with 1 method)
> 
> julia> @code_llvm testvt(x, a, b, c, 10)
> ; @ REPL[32]:1 within `testvt`
> ; Function Attrs: uwtable
> define nonnull {}* @julia_testvt_1193({}* noundef nonnull align 16 dereferenceable(40) %0, {}* noundef nonnull align 16 dereferenceable(40) %1, {}* noundef nonnull align 16 dereferenceable(40) %2, {}* noundef nonnull align 16 dereferenceable(40) %3, i64 signext %4) #0 {
> top:
> switch i64 %4, label %L37 [
> i64 1, label %L3
> i64 2, label %L7
> i64 3, label %L11
> i64 4, label %L15
> i64 5, label %L19
> i64 6, label %L23
> i64 7, label %L27
> i64 8, label %L31
> i64 9, label %L35
> ]
> 
> common.ret: ; preds = %L37, %L35, %L31, %L27, %L23, %L19, %L15, %L11, %L7, %L3
> %common.ret.op = phi {}* [%5, %L3], [%6, %L7], [%7, %L11], [%8, %L15], [%9, %L19], [%10, %L23], [%11, %L27], [%12, %L31], [%13, %L35], [%14, %L37]
> ret {}* %common.ret.op
> 
> L3: ; preds = %top
> ; ┌ @ REPL[27]:1 within `f`
> %5 = call nonnull {}* @"j_*_1195"({}* nonnull %0, i64 signext 1)
> br label %common.ret
> 
> L7: ; preds = %top
> %6 = call nonnull {}* @"j_*_1195"({}* nonnull %0, i64 signext 2)
> br label %common.ret
> 
> L11: ; preds = %top
> %7 = call nonnull {}* @"j_*_1195"({}* nonnull %0, i64 signext 3)
> br label %common.ret
> 
> L15: ; preds = %top
> %8 = call nonnull {}* @"j_*_1195"({}* nonnull %0, i64 signext 4)
> br label %common.ret
> 
> L19: ; preds = %top
> %9 = call nonnull {}* @"j_*_1195"({}* nonnull %0, i64 signext 5)
> br label %common.ret
> 
> L23: ; preds = %top
> %10 = call nonnull {}* @"j_*_1195"({}* nonnull %0, i64 signext 6)
> br label %common.ret
> 
> L27: ; preds = %top
> %11 = call nonnull {}* @"j_*_1195"({}* nonnull %0, i64 signext 7)
> br label %common.ret
> 
> L31: ; preds = %top
> %12 = call nonnull {}* @"j_*_1195"({}* nonnull %0, i64 signext 8)
> br label %common.ret
> 
> L35: ; preds = %top
> %13 = call nonnull {}* @"j_*_1195"({}* nonnull %0, i64 signext 9)
> br label %common.ret
> 
> L37: ; preds = %top
> %14 = call nonnull {}* @"j_*_1195"({}* nonnull %0, i64 signext 10)
> br label %common.ret
> ; └
> }
> 
> ```

vs

> **with noinline**
>
> ```julia
> julia> @noinline f(x, a, b, c, ::Val{N}) where N = x * N
> f (generic function with 1 method)
> 
> julia> @code_llvm testvt(x, a, b, c, 10)
> ; @ REPL[32]:1 within `testvt`
> ; Function Attrs: uwtable
> define nonnull {}* @julia_testvt_1196({}* noundef nonnull align 16 dereferenceable(40) %0, {}* noundef nonnull align 16 dereferenceable(40) %1, {}* noundef nonnull align 16 dereferenceable(40) %2, {}* noundef nonnull align 16 dereferenceable(40) %3, i64 signext %4) #0 {
> top:
> %5 = alloca [5 x {}*], align 8
> %.sub = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 0
> switch i64 %4, label %L37 [
> i64 1, label %L3
> i64 2, label %L7
> i64 3, label %L11
> i64 4, label %L15
> i64 5, label %L19
> i64 6, label %L23
> i64 7, label %L27
> i64 8, label %L31
> i64 9, label %L35
> ]
> 
> common.ret: ; preds = %L37, %L35, %L31, %L27, %L23, %L19, %L15, %L11, %L7, %L3
> %common.ret.op = phi {}* [%10, %L3], [%15, %L7], [%20, %L11], [%25, %L15], [%30, %L19], [%35, %L23], [%40, %L27], [%45, %L31], [%50, %L35], [%55, %L37]
> ret {}* %common.ret.op
> 
> L3: ; preds = %top
> store {}* %0, {}** %.sub, align 8
> %6 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 1
> store {}* %1, {}** %6, align 8
> %7 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 2
> store {}* %2, {}** %7, align 8
> %8 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 3
> store {}* %3, {}** %8, align 8
> %9 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 4
> store {}* inttoptr (i64 140735629256912 to {}*), {}** %9, align 8
> %10 = call nonnull {}* @j1_f_1198({}* inttoptr (i64 2458706367760 to {}*), {}** nonnull %.sub, i32 5)
> br label %common.ret
> 
> L7: ; preds = %top
> store {}* %0, {}** %.sub, align 8
> %11 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 1
> store {}* %1, {}** %11, align 8
> %12 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 2
> store {}* %2, {}** %12, align 8
> %13 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 3
> store {}* %3, {}** %13, align 8
> %14 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 4
> store {}* inttoptr (i64 140735629260064 to {}*), {}** %14, align 8
> %15 = call nonnull {}* @j1_f_1199({}* inttoptr (i64 2458706367760 to {}*), {}** nonnull %.sub, i32 5)
> br label %common.ret
> 
> L11: ; preds = %top
> store {}* %0, {}** %.sub, align 8
> %16 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 1
> store {}* %1, {}** %16, align 8
> %17 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 2
> store {}* %2, {}** %17, align 8
> %18 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 3
> store {}* %3, {}** %18, align 8
> %19 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 4
> store {}* inttoptr (i64 140735644336864 to {}*), {}** %19, align 8
> %20 = call nonnull {}* @j1_f_1200({}* inttoptr (i64 2458706367760 to {}*), {}** nonnull %.sub, i32 5)
> br label %common.ret
> 
> L15: ; preds = %top
> store {}* %0, {}** %.sub, align 8
> %21 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 1
> store {}* %1, {}** %21, align 8
> %22 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 2
> store {}* %2, {}** %22, align 8
> %23 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 3
> store {}* %3, {}** %23, align 8
> %24 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 4
> store {}* inttoptr (i64 140735642869104 to {}*), {}** %24, align 8
> %25 = call nonnull {}* @j1_f_1201({}* inttoptr (i64 2458706367760 to {}*), {}** nonnull %.sub, i32 5)
> br label %common.ret
> 
> L19: ; preds = %top
> store {}* %0, {}** %.sub, align 8
> %26 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 1
> store {}* %1, {}** %26, align 8
> %27 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 2
> store {}* %2, {}** %27, align 8
> %28 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 3
> store {}* %3, {}** %28, align 8
> %29 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 4
> store {}* inttoptr (i64 140735644338720 to {}*), {}** %29, align 8
> %30 = call nonnull {}* @j1_f_1202({}* inttoptr (i64 2458706367760 to {}*), {}** nonnull %.sub, i32 5)
> br label %common.ret
> 
> L23: ; preds = %top
> store {}* %0, {}** %.sub, align 8
> %31 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 1
> store {}* %1, {}** %31, align 8
> %32 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 2
> store {}* %2, {}** %32, align 8
> %33 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 3
> store {}* %3, {}** %33, align 8
> %34 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 4
> store {}* inttoptr (i64 140735644340288 to {}*), {}** %34, align 8
> %35 = call nonnull {}* @j1_f_1203({}* inttoptr (i64 2458706367760 to {}*), {}** nonnull %.sub, i32 5)
> br label %common.ret
> 
> L27: ; preds = %top
> store {}* %0, {}** %.sub, align 8
> %36 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 1
> store {}* %1, {}** %36, align 8
> %37 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 2
> store {}* %2, {}** %37, align 8
> %38 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 3
> store {}* %3, {}** %38, align 8
> %39 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 4
> store {}* inttoptr (i64 2458706370536 to {}*), {}** %39, align 8
> %40 = call nonnull {}* @j1_f_1204({}* inttoptr (i64 2458706367760 to {}*), {}** nonnull %.sub, i32 5)
> br label %common.ret
> 
> L31: ; preds = %top
> store {}* %0, {}** %.sub, align 8
> %41 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 1
> store {}* %1, {}** %41, align 8
> %42 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 2
> store {}* %2, {}** %42, align 8
> %43 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 3
> store {}* %3, {}** %43, align 8
> %44 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 4
> store {}* inttoptr (i64 2458706335712 to {}*), {}** %44, align 8
> %45 = call nonnull {}* @j1_f_1205({}* inttoptr (i64 2458706367760 to {}*), {}** nonnull %.sub, i32 5)
> br label %common.ret
> 
> L35: ; preds = %top
> store {}* %0, {}** %.sub, align 8
> %46 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 1
> store {}* %1, {}** %46, align 8
> %47 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 2
> store {}* %2, {}** %47, align 8
> %48 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 3
> store {}* %3, {}** %48, align 8
> %49 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 4
> store {}* inttoptr (i64 140735641117360 to {}*), {}** %49, align 8
> %50 = call nonnull {}* @j1_f_1206({}* inttoptr (i64 2458706367760 to {}*), {}** nonnull %.sub, i32 5)
> br label %common.ret
> 
> L37: ; preds = %top
> store {}* %0, {}** %.sub, align 8
> %51 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 1
> store {}* %1, {}** %51, align 8
> %52 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 2
> store {}* %2, {}** %52, align 8
> %53 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 3
> store {}* %3, {}** %53, align 8
> %54 = getelementptr inbounds [5 x {}*], [5 x {}*]* %5, i64 0, i64 4
> store {}* inttoptr (i64 140735649310864 to {}*), {}** %54, align 8
> %55 = call nonnull {}* @j1_f_1207({}* inttoptr (i64 2458706367760 to {}*), {}** nonnull %.sub, i32 5)
> br label %common.ret
> }
> 
> ```

Or did you mean something else?
