# Compiler Aliasing Fear

Pointer aliasing forces compilers to avoid optimizing code as best as they should. We use local variables to fix this problem.

For all examples shown below, assume `context` is a pointer to a heap allocated
struct.

## Rule 1: Scalars inside a loop

If booleans or integers gets modified inside a loop, always assign them to
local variables before doing so. Yes there are other ways to make the compiler
optimize this specific scenario, but we do this to easily **guarantee** speed.

```c
// SLOW
//
for (int i = 0; i < 100; i++) {
    // Forces a write to memory 100 times.
    //
    context->counter++;

    // This stopped context->counter from being kept in a CPU Register..
    //
    // The compiler doesnt know what do_something() does. It might write to
    // context->counter. 
    // 
    // The compiler is forced to:
    //
    // 1. Save `counter` from register to RAM.
    // 2. Calls do_something().
    // 3. Reloads `counter` fron ram to register.
    //
    do_something(context)

}
```

### Register Only Approach

```c
// FASTEST

// Load from memory to register once.
//
uint32_t count = context->counter;

for (int i = 0; i < 100; i++) {
    // Modify register directly. Zero memory access here.
    //
    count++; 

    // Pass the register value to the helper. We pass 'count' directly to avoid
    // the memory store.
    //
    do_something(context, count);
}

// Store from register back to memory once.
// 
context->counter = count;
```

### Hybrid Aprpoach (Optimized Load, Forced Store)

We do this if we cannot change the function signature.

```c
// FAST

uint32_t count = context->counter;

for (int i = 0; i < 100; i++) {
    count++; 

    // We must sync memory because do_something() reads it. This costs us 1 
    // STORE per loop, but we still save the LOAD.
    // 
    context->counter = count;

    do_something(context);
}

// No final store needed, we kept it in sync the whole time.
```

## Rule 2: Arrays inside a loop

`struct->array[i]` forces the CPU to calculate `Base + Offset + (i * 4)` every
time. `*cursor++` is just `Pointer + 4`.


```c
// SLOW
//
for (int i = 0; i < 100; ++i) {
    context->instructions[i] = ...; // Math overhead + Aliasing fear.
}

// FAST
//
bal_instruction_t *cursor = context->instructions;
for (int i = 0; i < 100; ++i) {
    *cursor++ = ...; // Simple increment.
}
```

## Rule 3: Constants/Read-Only Data

Access these values directly, like `context->max_buffer_size` or
`context->exception_level`. If we never write to it, the compiler knows it
will not change. It will load once and get cached automatically.
