pawn-lang / compiler

Pawn compiler for SA-MP with bug fixes and new features - runs on Windows, Linux, macOS
Other
307 stars 72 forks source link

Optimization of conditional expressions #712

Open Daniel-Cortez opened 2 years ago

Daniel-Cortez commented 2 years ago

Issue description:

Let's suppose we have a conditional expression cond ? val1 : val2. If both val1 and val2 are compile-time constants, the expression can be optimized into val1 + !cond * (val2 - val1), thus allowing to generate smaller and faster bytecode. For example, if we have this code:

GetDefaultPlayerSkin(gender = 0)
    return (gender != 0) ? 56 : 60;

the compiler would generate the following bytecode for the return statement:

    load.s.pri c
    jzer l.1
    const.pri 38
    jump l.2
l.1
    const.pri 3c
l.2
    retn

Leaving out the condition part (load.s.pri c), as well as the epilogue code (retn), this would be 4 instructions in 8 cells. But if we rewrite the code in the following manner:

GetDefaultPlayerSkin(gender = 0)
    return !(gender != 0) * (60 - 56) + 56;

the generated bytecode would be

    load.s.pri c
    not
    smul.c 4
    add.c 38
    retn

which is 3 instructions (again, without load.s.pri and retn) and only 5 cells, with no unnecessary branching, which means the code would be more JIT-friendly.

Currently such optimizations require code to be rewritten manually, but I'd like to modify the compiler so it could perform them automatically. But before doing that it would be nice to know if there's something that might make this kind of optimizations undesirable. Opinions are welcome.

Minimal complete verifiable example (MCVE):

Workspace Information: