Optimisation of static mut

Given the following code:

extern {
  fn init();
  fn do_something();
}

static mut INIT: bool = false;

fn main() {
  do_something_check_if_init()
  do_something_check_if_init()
  do_something_check_if_init()
}

#[inline(always)]
fn do_something_check_if_init() {
  unsafe {
    if !INIT {
      init();
      INIT = true;
    }
    do_something();
  }
}

Why doesn't it optimise the read of the INIT variable and turn the assembly into the equivalent of

fn main() {
  if !INIT {
    init();
    INIT=true;
  }
  do_something();
  do_something();
  do_something();

In the assembly it continually re-reads the INIT variable and rechecks it. It doesn't do this if you use a normal variable (but then you have to inline it by hand). Alternatively is there a way to have something like an inline-able variable something where only one variable exists if the function is inlined twice and is shared between the two?

A static is global, so other threads can modify it while one function is reading it. Therefore this optimization would be incorrect.

Incidentally, for the same reason, you shouldn't be hand-crafting lazy initialization. Use once_cell::sync::Lazy instead.

4 Likes