# Directly modify compiled method without recompilation

**URL:** <https://discourse.julialang.org/t/directly-modify-compiled-method-without-recompilation/86564>\
**Category:** Performance\
**Tags:** compilation\
**Created:** [August 30, 2022, 5:45pm UTC](https://discourse.julialang.org/t/directly-modify-compiled-method-without-recompilation/86564 "2022-08-30T17:45:16Z")\
**Posts on this page:** 6\
**Page:** 2

<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:** [August 31, 2022, 8:21pm UTC](https://discourse.julialang.org/t/directly-modify-compiled-method-without-recompilation/86564/22 "2022-08-31T20:21:20Z")

</div>

I’ve never used it myself (because I never needed to), but there is [`llvmcall`](https://docs.julialang.org/en/v1/base/c/#Core.Intrinsics.llvmcall). It, well, calls LLVM IR represented by a Julia instance like a String, which provides a similar functionality to how C can inline assembly. I’m not aware of an analogous method for other forms of lowered code. I think the `code_llvm` method can get you LLVM IR represented like that, but I don’t know exactly how.

So hypothetically, you could compile one original function, get the `code_llvm` string, and the rest of your functions are made by editing that string and evaluating an expression for a function `llvmcall`ing the edited string. `$`-interpolation might come in handy for representing an edited string, not sure. Each function still goes through the entire compilation process, it’s just that many compilation steps can’t do anything to LLVM IR.

Again, I would only consider this as a last resort; ask about and consider alternative pure-Julia approaches to your problem for a little while longer. Because writing and editing assembly-like language is really REALLY hard. I wouldn’t be surprised if you get stuck trying to figure out how to edit the LLVM IR to correctly reflect an imagined edit to the source code. High level languages and heavily layered compilers exist for this reason, and all the examples of `llvmcall` I’ve seen in passing are very small code snippets.

---

<div class="post-metadata">

**Author:** ![mikmoore](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mikmoore/32/31109_2.png) [@mikmoore](https://discourse.julialang.org/u/mikmoore)\
**Post date:** [August 31, 2022, 8:34pm UTC](https://discourse.julialang.org/t/directly-modify-compiled-method-without-recompilation/86564/23 "2022-08-31T20:34:35Z")

</div>

Technically, if you could skip some compilation steps it might save some small amount of time. But I wouldn’t expect much benefit and this would be horrifically difficult for anyone except the people that literally wrote these compilation steps in the first place.

Without herculean effort and significant expertise, I suspect your best bet is your current approach to generate `Expr`s and `eval` them.

That said, it’s hard to believe you’re generating _truly_ arbitrary expressions - e.g., generating random strings until you get a legal Julia expression. For example, your functions above can all be represented in the form  
`plusops(v1,v2,v3) = dot([c1,c2,c3],[v1,v2,v3])`  
`mulops(v1,v2,v3,v4) = exp(dot([c1,c2,c3,c4],log.([v1,v2,v3,v4])))`  
for vectors `[c1,c2,c3]`/`[c1,c2,c3,c4]` of certain structure (in your examples, two entries with values that are chosen from among `+1` and `-1` and the rest `0`).

---

<div class="post-metadata">

**Author:** ![FireCrumb](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/firecrumb/32/35370_2.png) [@FireCrumb](https://discourse.julialang.org/u/FireCrumb)\
**Post date:** [August 31, 2022, 8:34pm UTC](https://discourse.julialang.org/t/directly-modify-compiled-method-without-recompilation/86564/24 "2022-08-31T20:34:48Z")

</div>

> [@Benny](#):
>
> I’ve never used it myself (because I never needed to), but there is [`llvmcall`](https://docs.julialang.org/en/v1/base/c/#Core.Intrinsics.llvmcall). It, well, calls LLVM IR represented by a Julia instance like a String, which provides a similar functionality to how C can inline assembly. I’m not aware of an analogous method for other forms of lowered code. I think the `code_llvm` method can get you LLVM IR represented like that, but I don’t know exactly how.
> 
> So hypothetically, you could compile one original function, get the `code_llvm` string, and the rest of your functions are made by editing that string and evaluating an expression for a function `llvmcall`ing the edited string. `$`-interpolation might come in handy for representing an edited string, not sure. Each function still goes through the entire compilation process, it’s just that many compilation steps can’t do anything to LLVM IR.

There are some usage examples here:

> <https://github.com/JuliaLang/julia/blob/master/test/llvmcall.jl>

---

<div class="post-metadata">

**Author:** ![FireCrumb](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/firecrumb/32/35370_2.png) [@FireCrumb](https://discourse.julialang.org/u/FireCrumb)\
**Post date:** [August 31, 2022, 8:39pm UTC](https://discourse.julialang.org/t/directly-modify-compiled-method-without-recompilation/86564/25 "2022-08-31T20:39:08Z")

</div>

> [@mikmoore](#):
>
> Technically, if you could skip some compilation steps it might save some small amount of time. But I wouldn’t expect much benefit and this would be horrifically difficult for anyone except the people that literally wrote these compilation steps in the first place.
> 
> Without herculean effort and significant expertise, I suspect your best bet is your current approach to generate `Expr`s and `eval` them.

Since I’m using evolutionary search, my goal is to be able to evaluate as many different `Expr` as possible, even somewhat sacrificing readability of just that part of the code.

> [@mikmoore](#):
>
> That said, it’s hard to believe you’re generating _truly_ arbitrary expressions - e.g., generating random strings until you get a legal Julia expression. For example, your functions above can all be represented in the form

Yeah, there are not completely arbitrary, but the real-case examples are quite more complex and flexible than any of the examples in this thread.

See my latest example for closer representation than the top message:

> [@Directly modify compiled method without recompilation](https://discourse.julialang.org/t/directly-modify-compiled-method-without-recompilation/86564/20):
>
> Here’s a longer but hopefully more representative example: using RuntimeGeneratedFunctions RuntimeGeneratedFunctions.init(@\_\_MODULE\_\_) function get\_calc(mysetup::Expr, myalgo::Expr)::Expr return frowning function calc(myinput::Float32)::Float32 # input always in v1 v1 = myinput # init variables $mysetup # run calculation $myalgo # result always in v5 res = v5 return…

---

<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:** [August 31, 2022, 8:47pm UTC](https://discourse.julialang.org/t/directly-modify-compiled-method-without-recompilation/86564/26 "2022-08-31T20:47:10Z")

</div>

Putting the intimidating difficulty of editing LLVM IR aside for a minute, generating and editing `Expr` to go through the entire parsing and compilation process has an _advantage_. The compiler takes up time, sure, but it’s doing optimizations with that time. A small edit to an `Expr` may open up the compiler to vastly simplify the LLVM IR. If you don’t let the compiler do that work, you either have to do it manually (very unlikely) or you have to accept sub-optimal LLVM IR, something you might expect from an interpreter. Conversely, a small edit may make some optimizations invalid, in which case you have to _add_ LLVM IR lines to prevent bugs, which is a whole next level of difficult.

---

<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:** [August 31, 2022, 9:05pm UTC](https://discourse.julialang.org/t/directly-modify-compiled-method-without-recompilation/86564/27 "2022-08-31T21:05:45Z")

</div>

Maybe it’s just because I’m not familiar with RuntimeGeneratedFunctions, but it looks like a lot of what you’re doing in the latest example to prepare each method is selecting values, selecting an operation, and permutating variable names, all randomly. I would choose to do all that at runtime in 1 vanilla method, I’m not sure there would be an overall benefit in generating 10x100xN methods that each run a bit faster, no matter how many tricks I use to save compilation time. If the idea is that each method is repeatable, I could store the random selections for repeatability. Instead of randomly selecting a variable to reassign `:($x = ...`, which does seem impossible to do dynamically, I would rather use a different reference, like an element of a `Vector` whose indices I _can_ dynamically select. If I needed to make a special method for that extra bit of optimization, I would reserve that effort for `bestalgo, bestres`, since that’s the only method I could run repeatedly afterward. Just food for thought, it does sound like you’ve considered something similar already anyway.

[Previous page](https://discourse.julialang.org/t/directly-modify-compiled-method-without-recompilation/86564.md?page=1)
