# Force recompiling functions in conditional compilation

**URL:** <https://discourse.julialang.org/t/force-recompiling-functions-in-conditional-compilation/92132>\
**Category:** General Usage\
**Created:** [December 26, 2022, 8:17am UTC](https://discourse.julialang.org/t/force-recompiling-functions-in-conditional-compilation/92132 "2022-12-26T08:17:11Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![jsjie](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jsjie/32/22477_2.png) [@jsjie](https://discourse.julialang.org/u/jsjie)\
**Post date:** [December 26, 2022, 8:17am UTC](https://discourse.julialang.org/t/force-recompiling-functions-in-conditional-compilation/92132/1 "2022-12-26T08:17:11Z")

</div>

I want to do conditional compilation. Besides, when developing, I’d like to be able to exam all branches. Can I do that?

An explanation by case:  
My code will have two different modes when used in production, let’s call them on and off. I may write a macro to do that:

```julia
const IS_ON = true
macro if_on(ex1, ex2)
    if IS_ON
        return :($(esc(ex1)))
    else
        return :($(esc(ex2)))
    end
end

function inc_depend_on_mode!(a)
    @if_on begin
        a .+= 1
    end begin
        a .+= 2
    end
end

```

I can then change the value of IS\_ON to get code for different modes.  
This works fine for production. However, when developing, I want to be able to examine code for both modes without restarting my REPL.  
Then first, I need to change IS\_ON from a global constant, to something like

```julia
mutable struct Control
    is_on::Bool
end
const control = Control(true)

```

so that I may dynamically set its value.  
There remains one question: how can I recompile function `inc_depend_on_mode!` after I change the mode?

Very Important: I want to do real conditional precompilation, which means, in my point of view, that the generated lowered code should be free of branches. In the previous example, this can be confirmed:

```julia
julia> a = zeros(Int, 5);
julia> @code_lowered inc_depend_on_mode!(a)
CodeInfo(
1 ─ %1 = Base.broadcasted(Main.:+, a, 1)
│ %2 = Base.materialize!(a, %1)
└── return %2
)

```

If not, I can simply write something like

```julia
mutable struct Control
    is_on::Bool
end
const control = Control(true)
function inc_depend_on_mode!(a)
    if control.is_on
        a .+= 1
    else
        a .+= 2
    end
end

```

It works fine, but it is not conditional “compilation”, because branches exist in lowered code:

```julia
julia> a = zeros(Int, 5);

julia> @code_lowered inc_depend_on_mode!(a)
CodeInfo(
1 ─ %1 = Base.getproperty(Main.control, :is_on)
└── goto #3 if not %1
2 ─ %3 = Base.broadcasted(Main.:+, a, 1)
│ %4 = Base.materialize!(a, %3)
└── return %4
3 ─ %6 = Base.broadcasted(Main.:+, a, 2)
│ %7 = Base.materialize!(a, %6)
└── return %7
)

```

---

<div class="post-metadata">

**Author:** ![ffevotte](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ffevotte/32/6587_2.png) [@ffevotte](https://discourse.julialang.org/u/ffevotte)\
**Post date:** [December 27, 2022, 10:43pm UTC](https://discourse.julialang.org/t/force-recompiling-functions-in-conditional-compilation/92132/2 "2022-12-27T22:43:37Z")

</div>

This thread seems to be relevant

> [@@assert alternatives?](https://discourse.julialang.org/t/assert-alternatives/24775):
>
> AFAIK there is no way yet to globally disable @assert with a compiler switch, even if doing so was already considered in the past ([here](https://github.com/JuliaLang/julia/issues/7732) and [here](https://github.com/JuliaLang/julia/issues/10614), for example). While this is not done (as I do like to believe some day someone will implement this), what is the “de facto” solution for having @assert in performance critical code? There is a package? We can redefine the behavior for a no-op in some way? Should we implement our own macro? Use ifs and a global boolean variable?

In it, you’ll find the following technique, which also forms the core of the implementation of [`ToggleableAsserts`](https://github.com/MasonProtter/ToggleableAsserts.jl). Re-writing your example, it would look like this:

```julia
julia> mode_on() = true
mode_on (generic function with 1 method)

julia> function inc!(a)
           if mode_on()
               a .+= 1
           else
               a .+= 2
           end
       end
inc! (generic function with 1 method)

```

You’ll notice that lowered code is not entirely free of branches:

```julia
julia> @code_lowered inc!([1,2,3])
CodeInfo(
1 ─ %1 = Main.mode_on()
└── goto #3 if not %1
2 ─ %3 = Base.broadcasted(Main.:+, a, 1)
│ %4 = Base.materialize!(a, %3)
└── return %4
3 ─ %6 = Base.broadcasted(Main.:+, a, 2)
│ %7 = Base.materialize!(a, %6)
└── return %7
)

```

But later stages of compilation (starting with typed code) do eliminate branches (note how the second block below is considered unreachable):

```julia
julia> @code_warntype inc!([1,2,3])
MethodInstance for inc!(::Vector{Int64})
  from inc!(a) in Main at REPL[3]:1
Arguments
  #self#::Core.Const(inc!)
  a::Vector{Int64}
Body::Vector{Int64}
1 ─ %1 = Main.mode_on()::Core.Const(true)
│ Core.typeassert(%1, Core.Bool)
│ %3 = Base.broadcasted(Main.:+, a, 1)::Core.PartialStruct(Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{1}, Nothing, typeof(+), Tuple{Vector{Int64}, Int64}}, Any[Core.Const(+), Core.PartialStruct(Tuple{Vector{Int64}, Int64}, Any[Vector{Int64}, Core.Const(1)]), Core.Const(nothing)])
│ %4 = Base.materialize!(a, %3)::Vector{Int64}
└── return %4
2 ─ Core.Const(:(Base.broadcasted(Main.:+, a, 2)))
│ Core.Const(:(Base.materialize!(a, %6)))
└── Core.Const(:(return %7))

```

So I’d say this qualifies as conditional compilation. Furthermore, if the `mode_on()` method is redefined, then it will invalidate `inc!` and force its re-compilation next time it is called (note how the `else` clause is now the only reachable part of the code):

```julia
julia> mode_on() = false
mode_on (generic function with 1 method)

julia> @code_warntype inc!([1,2,3])
MethodInstance for inc!(::Vector{Int64})
  from inc!(a) in Main at REPL[3]:1
Arguments
  #self#::Core.Const(inc!)
  a::Vector{Int64}
Body::Vector{Int64}
1 ─ %1 = Main.mode_on()::Core.Const(false)
└── goto #3 if not %1
2 ─ Core.Const(:(Base.broadcasted(Main.:+, a, 1)))
│ Core.Const(:(Base.materialize!(a, %3)))
└── Core.Const(:(return %4))
3 ┄ %6 = Base.broadcasted(Main.:+, a, 2)::Core.PartialStruct(Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{1}, Nothing, typeof(+), Tuple{Vector{Int64}, Int64}}, Any[Core.Const(+), Core.PartialStruct(Tuple{Vector{Int64}, Int64}, Any[Vector{Int64}, Core.Const(2)]), Core.Const(nothing)])
│ %7 = Base.materialize!(a, %6)::Vector{Int64}
└── return %7

```
