> ## Documentation Index
> Fetch the complete documentation index at: https://companyname-a7d5b98e-ton-storage.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Compiler optimizations

export const Aside = ({type = "note", title = "", icon = "", iconType = "regular", children}) => {
  const asideVariants = ["note", "tip", "caution", "danger"];
  const asideComponents = {
    note: {
      outerStyle: "border-sky-500/20 bg-sky-50/50 dark:border-sky-500/30 dark:bg-sky-500/10",
      innerStyle: "text-sky-900 dark:text-sky-200",
      calloutType: "note",
      icon: <svg width="14" height="14" viewBox="0 0 14 14" fill="currentColor" xmlns="http://www.w3.org/2000/svg" className="w-4 h-4 text-sky-500" aria-label="Note">
          <path fill-rule="evenodd" clip-rule="evenodd" d="M7 1.3C10.14 1.3 12.7 3.86 12.7 7C12.7 10.14 10.14 12.7 7 12.7C5.48908 12.6974 4.0408 12.096 2.97241 11.0276C1.90403 9.9592 1.30264 8.51092 1.3 7C1.3 3.86 3.86 1.3 7 1.3ZM7 0C3.14 0 0 3.14 0 7C0 10.86 3.14 14 7 14C10.86 14 14 10.86 14 7C14 3.14 10.86 0 7 0ZM8 3H6V8H8V3ZM8 9H6V11H8V9Z"></path>
        </svg>
    },
    tip: {
      outerStyle: "border-emerald-500/20 bg-emerald-50/50 dark:border-emerald-500/30 dark:bg-emerald-500/10",
      innerStyle: "text-emerald-900 dark:text-emerald-200",
      calloutType: "tip",
      icon: <svg width="11" height="14" viewBox="0 0 11 14" fill="currentColor" xmlns="http://www.w3.org/2000/svg" className="text-emerald-600 dark:text-emerald-400/80 w-3.5 h-auto" aria-label="Tip">
          <path d="M3.12794 12.4232C3.12794 12.5954 3.1776 12.7634 3.27244 12.907L3.74114 13.6095C3.88471 13.8248 4.21067 14 4.46964 14H6.15606C6.41415 14 6.74017 13.825 6.88373 13.6095L7.3508 12.9073C7.43114 12.7859 7.49705 12.569 7.49705 12.4232L7.50055 11.3513H3.12521L3.12794 12.4232ZM5.31288 0C2.52414 0.00875889 0.5 2.26889 0.5 4.78826C0.5 6.00188 0.949566 7.10829 1.69119 7.95492C2.14321 8.47011 2.84901 9.54727 3.11919 10.4557C3.12005 10.4625 3.12175 10.4698 3.12261 10.4771H7.50342C7.50427 10.4698 7.50598 10.463 7.50684 10.4557C7.77688 9.54727 8.48281 8.47011 8.93484 7.95492C9.67728 7.13181 10.1258 6.02703 10.1258 4.78826C10.1258 2.15486 7.9709 0.000106649 5.31288 0ZM7.94902 7.11267C7.52078 7.60079 6.99082 8.37878 6.6077 9.18794H4.02051C3.63739 8.37878 3.10743 7.60079 2.67947 7.11294C2.11997 6.47551 1.8126 5.63599 1.8126 4.78826C1.8126 3.09829 3.12794 1.31944 5.28827 1.3126C7.2435 1.3126 8.81315 2.88226 8.81315 4.78826C8.81315 5.63599 8.50688 6.47551 7.94902 7.11267ZM4.87534 2.18767C3.66939 2.18767 2.68767 3.16939 2.68767 4.37534C2.68767 4.61719 2.88336 4.81288 3.12521 4.81288C3.36705 4.81288 3.56274 4.61599 3.56274 4.37534C3.56274 3.6515 4.1515 3.06274 4.87534 3.06274C5.11719 3.06274 5.31288 2.86727 5.31288 2.62548C5.31288 2.38369 5.11599 2.18767 4.87534 2.18767Z"></path>
        </svg>
    },
    caution: {
      outerStyle: "border-amber-500/20 bg-amber-50/50 dark:border-amber-500/30 dark:bg-amber-500/10",
      innerStyle: "text-amber-900 dark:text-amber-200",
      calloutType: "warning",
      icon: <svg className="flex-none w-5 h-5 text-amber-400 dark:text-amber-300/80" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" aria-label="Warning">
          <path stroke-linecap="round" stroke-linejoin="round" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"></path>
        </svg>
    },
    danger: {
      outerStyle: "border-red-500/20 bg-red-50/50 dark:border-red-500/30 dark:bg-red-500/10",
      innerStyle: "text-red-900 dark:text-red-200",
      calloutType: "danger",
      icon: <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor" className="text-red-600 dark:text-red-400/80 w-4 h-4" aria-label="Danger">
          <path d="M17.1 292c-12.9-22.3-12.9-49.7 0-72L105.4 67.1c12.9-22.3 36.6-36 62.4-36l176.6 0c25.7 0 49.5 13.7 62.4 36L494.9 220c12.9 22.3 12.9 49.7 0 72L406.6 444.9c-12.9 22.3-36.6 36-62.4 36l-176.6 0c-25.7 0-49.5-13.7-62.4-36L17.1 292zm41.6-48c-4.3 7.4-4.3 16.6 0 24l88.3 152.9c4.3 7.4 12.2 12 20.8 12l176.6 0c8.6 0 16.5-4.6 20.8-12L453.4 268c4.3-7.4 4.3-16.6 0-24L365.1 91.1c-4.3-7.4-12.2-12-20.8-12l-176.6 0c-8.6 0-16.5 4.6-20.8 12L58.6 244zM256 128c13.3 0 24 10.7 24 24l0 112c0 13.3-10.7 24-24 24s-24-10.7-24-24l0-112c0-13.3 10.7-24 24-24zM224 352a32 32 0 1 1 64 0 32 32 0 1 1 -64 0z"></path>
        </svg>
    }
  };
  let variant = type;
  let gotInvalidVariant = false;
  if (!asideVariants.includes(type)) {
    gotInvalidVariant = true;
    variant = "danger";
  }
  const iconVariants = ["regular", "solid", "light", "thin", "sharp-solid", "duotone", "brands"];
  if (!iconVariants.includes(iconType)) {
    iconType = "regular";
  }
  return <>
      <div className={`callout my-4 px-5 py-4 overflow-hidden rounded-2xl flex gap-3 border ${asideComponents[variant].outerStyle}`} data-callout-type={asideComponents[variant].calloutType}>
        <div className="mt-0.5 w-4" data-component-part="callout-icon">
          {}
          {icon === "" ? asideComponents[variant].icon : <Icon icon={icon} iconType={iconType} size={14} />}
        </div>
        <div className={`text-sm prose min-w-0 w-full ${asideComponents[variant].innerStyle}`} data-component-part="callout-content">
          {gotInvalidVariant ? <p>
              <span className="font-bold">
                Invalid <code>type</code> passed!
              </span>
              <br />
              <span className="font-bold">Received: </span>
              {type}
              <br />
              <span className="font-bold">Expected one of: </span>
              {asideVariants.join(", ")}
            </p> : <>
              {title && <p className="font-bold">{title}</p>}
              {children}
            </>}
        </div>
      </div>
    </>;
};

Tolk compiler is smart enough to generate optimal bytecode from a clear, idiomatic code.
The ideal target is "zero overhead": extracting variables and simple methods should not increase gas consumption.

<Aside type="caution">
  This page summarizes optimizations that affect gas usage.
  It is fairly low-level and not required for using Tolk in production.
</Aside>

## Constant folding

Tolk compiler evaluates constant variables and conditions at compile-time:

```tolk theme={null}
fun calcSecondsInAYear() {
    val days = 365;
    val minutes = 60 * 24 * days;
    return minutes * 60;
}
```

All these computations are done statically, resulting in

```fift theme={null}
31536000 PUSHINT
```

It works for conditions as well.
For example, when `if`'s condition is guaranteed to be false, only `else` body is left.
If an `assert` is proven statically, only the corresponding `throw` remains.

```tolk theme={null}
fun demo(s: slice) {
    var flags = s.loadUint(32);   // definitely >= 0
    if (flags < 0) {              // always false
        // ...
    }
    return s.remainingBitsCount();
}
```

The compiler drops `IF` at all (both body and condition evaluation), because it can never be reached.

While calculating compile-time values, all mathematical operators are emulated as they would have run at runtime.
Additional flags like "this value is even / non-positive" are also tracked, leading to more aggressive code elimination.
It works not only for plain variables, but also for struct fields, tensor items, across inlining, etc.
(because it happens after transforming a high-level syntax tree to low-level intermediate representation).

## Merge constant builder.storeInt

When building cells manually, there is no need to group constant `storeUint` into a single number.

```tolk theme={null}
// no need for manual grouping anymore
b.storeUint(4 + 2 + 1, 1 + 4 + 4 + 64 + 32 + 1 + 1 + 1);
```

Successive `builder.storeInt` are merged automatically:

```tolk theme={null}
b.storeUint(0, 1)  // prefix
 .storeUint(1, 1)  // ihr_disabled
 .storeUint(1, 1)  // bounce
 .storeUint(0, 1)  // bounced
 .storeUint(0, 2)  // addr_none
```

is translated to just

```fift theme={null}
b{011000} STSLICECONST
```

It works together with constant folding — even with variables and conditions, when they turn out to be constant:

```tolk theme={null}
fun demo() {
    var x = 0;
    var b = beginCell();
    b.storeUint(x, 4);
    x += 12;
    if (x > 0) {
        x += x;
    }
    b.storeUint(x + 2, 8);
    return b;
}
```

is translated to just

```fift theme={null}
NEWC
x{01a} STSLICECONST
```

It works even for structures — including their fields:

```tolk theme={null}
struct Point {
    x: uint32
    y: uint32
}

fun demo() {
    var p: Point = { x: 10, y: 20 };
    return p.toCell();
}
```

becomes

```fift theme={null}
NEWC
x{0000000a00000014} STSLICECONST
ENDC
```

*(in the future, Tolk will be able to emit a constant cell here)*

That's the reason why [createMessage](/languages/tolk/features/message-sending) for unions is so lightweight.
The compiler really generates all IF-ELSE and STU, but in a later analysis,
they become constant (since types are compile-time known),
and everything flattens into simple PUSHINT / STSLICECONST.

## Auto-inline functions

Tolk inlines functions at the compiler level:

```tolk theme={null}
fun Point.create(x: int, y: int): Point {
    return {x, y}
}

fun Point.getX(self) {
    return self.x
}

fun sum(a: int, b: int) {
    return a + b
}

fun main() {
    var p = Point.create(10, 20);
    return sum(p.getX(), p.y);
}
```

is compiled just to

```fift theme={null}
main PROC:<{
    30 PUSHINT
}>
```

The compiler **automatically determines which functions to inline** and also gives manual control.

### How does auto-inline work?

* simple, small functions are always inlined
* functions called only once are always inlined

For every function, the compiler calculates some "weight" and the usages count.

* if `weight < THRESHOLD`, the function is always inlined
* if `usages == 1`, the function is always inlined
* otherwise, an empirical formula determines inlining

Inlining is efficient in terms of stack manipulations.
It works with arguments of any stack width, any functions and methods, except recursive or having "return" in the middle.

As a conclusion, create utility methods without worrying about gas consumption, they are absolutely zero-cost.

### How to control inlining manually?

* `@inline` forces inlining even for large functions
* `@noinline` prevents from being inlined
* `@inline_ref` preserves an inline reference, suitable for rarely executed paths

### What can NOT be auto-inlined?

A function is NOT inlined, even if marked with `@inline`, if:

* contains `return` in the middle; multiple return points are unsupported
* participates in a recursive call chain `f -> g -> f`
* is used as a non-call; e.g., as a reference `val callback = f`

For example, this function cannot be inlined due to `return` in the middle:

```tolk theme={null}
fun executeForPositive(userId: int) {
    if (userId <= 0) {
        return;
    }
    // ...
}
```

The advice is to check pre-conditions out of the function and keep body linear.

## Peephole and stack optimizations

After the code has been analyzed and transformed to IR, the compiler repeatedly replaces some assembler combinations to equal ones, but cheaper.
Some examples are:

* stack permutations: DUP + DUP => 2DUP, SWAP + OVER => TUCK, etc.
* N LDU + NIP => N PLDU
* SWAP + N STU => N STUR, SWAP + STSLICE => STSLICER, etc.
* SWAP + EQUAL => EQUAL and other symmetric like MUL, OR, etc.
* 0 EQINT + N THROWIF => N THROWIFNOT and vice versa
* N EQINT + NOT => N NEQINT and other xxx + NOT
* ...

Some others are done semantically in advance when it's safe:

* replace a ternary operator to `CONDSEL`
* evaluate arguments of `asm` functions in a desired stack order
* evaluate struct fields of a shuffled object literal to fit stack order

## Lazy loading

The magic `lazy` keyword loads only required fields from a cell/slice:

```tolk theme={null}
struct Storage {
    // ...
}

get fun publicKey() {
    val st = lazy Storage.load();
    // <-- fields before are skipped, publicKey preloaded
    return st.publicKey
}
```

The compiler tracks exactly which fields are accessed, and unpacks only those fields, skipping the rest.

Read [lazy loading](/languages/tolk/features/lazy-loading).

## Suggestions for manual optimizations

Although the compiler performs substantial work in the background, there are still cases when a developer can gain a few gas units.

The primary aspect is **changing evaluation order** to target fewer stack manipulations.
The compiler does not reorder blocks of code unless they are constant expressions or pure calls.
But a developer knows the context better. Generally, it looks like this:

```tolk theme={null}
fun demo() {
    // variable initialization, grouped
    val v1 = someFormula1();
    val v2 = someFormula2();
    val v3 = someFormula3();

    // use them in calls, assertions, etc.
    someUsage(v1);
    anotherUsage(v2);
    assert(v3) throw 123;
}
```

After the first block, the stack is `(v1 v2 v3)`.
But v1 is used at first, so the stack must be shuffled with `SWAP` / `ROT` / `XCPU` / etc.
If to rearrange assignments or usages — say, move `assert(v3)` upper — it will naturally pop the topmost element.
Of course, automatic reordering is unsafe and prohibited, but in exact cases business logic might be still valid.

Another option is **using bitwise `& |` instead of logical `&& ||`**.
Logical operators are short-circuit: the right operand is evaluated only if required to.
It's implemented via conditional branches at runtime.
But in some cases, evaluating both operands is less expensive than a dynamic `IF`.

The last possibility is **using low-level Fift code** for certain independent tasks that cannot be expressed imperatively.
Usage of exotic TVM instructions like `NULLROTRIFNOT` / `IFBITJMP` / etc.
Overriding how top-level Fift dictionary works for routing method\_id. And similar.
Old residents call it "deep fifting".
Anyway, it's applicable only to a very limited set of goals, mostly as exercises, not as real-world usage.

<Aside type="tip">
  Do not micro-optimize. Lots of sleepless nights will result in 2-3% gas reducing at best,
  producing unreadable code. Just use Tolk as intended.
</Aside>

## How to explore Fift assembler

Tolk compiler outputs Fift assembler. The bytecode (bag of cells) is generated by Fift, actually.
Projects built on blueprint rely on `tolk-js` under the hood, which invokes Tolk and then Fift.

As a result:

* for command-line users, fift assembler is the compiler's output
* for blueprint users, it's an intermediate result, but can easily be found

**To view Fift assembler in blueprint**, run `npm build` or `blueprint build` in a project.
After successful compilation, a directory `build/` is created, and a folder `build/ContractName/`
contains a `.fif` file.
