A single-pass parser transforms Lua source code into LuaJIT Bytecode.
The bytecode operates on dynamically-typed values and has semantics very
close to the source code. This is the reason why relatively few
optimizations can be performed on the bytecode itself -- most of them
wouldn't be valid transforms in a dynamic language.

Similarly, virtual register allocation for the bytecode closely follows
scoping of local variables in the Lua source code. No attempt is made to
minimize or overlap the lifetimes of local variables (virtual registers
are cheap and plenty).

Constant Folding

Constant folding is performed for all arithmetic operators (+ - * / % ^
and unary minus) and the logical not operator. If the input consists
solely of constants, the output is turned into a constant, too. E.g.
this is the bytecode for return 1.5 * 3:

0001 KNUM 0 0 ; 4.5
0002 RET1 0 2

The multiplication has been eliminated and only its result is returned.

Optimizing Composite Conditionals

Composite conditional expressions like x < 10 and x or 10 are turned
into a series of branches, instead of evaluating the intermediate
expressions into booleans. The logical operators and and or never
appear in the bytecode. not only appears when the result is used
outside of a logical result context. E.g. this is the bytecode for
return a < b and x or y:

Elimination of Conditionals

Conditionals can be eliminated if their input is a constant. This is
only done for 'truthness' tests. E.g. this is the bytecode for
return "a" and 99:

0001 KSHORT 0 99
0002 RET1 0 2

The check for the truthness of "a" has been eliminated.

A more common idiom is cond and x or y, which is useful as a ternary
conditional. But the behavior is not the same, since x is evaluated
and must not be false or nil (or the idiom would fail). However x
is very often a constant. E.g. this is the bytecode for
return a and 10 or 20:

Elimination of Unneeded Results

Logical operators compute an actual result, e.g. print("a" and 99)
prints 99. But this result is not needed in a logical result context,
such as an if statement. E.g. this is the bytecode for
if "a" and 99 then end:

0001 RET0 0 1

The conditional as well as its result has been eliminated.

Unneeded results of calls are eliminated, too: e.g. the CALL*
instructions are patched to not return any results.

Jump Folding

Unconditional jumps that lead to other jumps are folded into a jump to
the final target. Similarly, closing upvalues at the end of a scope is
often followed by a jump. The jump is then folded into the UCLO, which
takes a branch target.

Template Tables

Lua can be used as data description language, which often involves
creating tables that are initialized with many constants. Instead of
allocating an empty table and generating lots of explicit stores, a
template table is generated by the parser. The template table can be
duplicated very fast with the TDUP instruction (duplication is
necessary, because the resulting table may be modified).

Mixed constant and variable initializers are allowed, too. The template
table is only created, if at least one constant initializer (constant
key and constant value) is present in the table constructor expression.
E.g. this is the bytecode for return { foo=1, bar=2, 1,2,x,4 }:

0001 TDUP 0 0
0002 GGET 1 1 ; "x"
0003 TSETB 1 0 3
0004 RET1 0 2

All of the constant initializers are merged into the template table.
Only the store operation t[3] = x remains in the bytecode.

Instruction and Operand Specialization

Many bytecode instructions have specialized forms for commonly used
operand types or number of operands. This reduces dispatch costs, since
it eliminates (often unpredictable) branches inside of their
implementation:

Comparison and test operators are specialized to the direction of their tests. E.g. there's both IST and ISF, which jump either on truthness or falseness. This saves a dispatch compared to using a single instruction plus an operand for the same purpose.

Comparisons for equality are specialized to the operand type, if one of the operands is a constant. E.g. ISEQN is an equality comparison with a numeric constant.

Arithmetic instructions are specialized for the common cases of having a numeric constant on the left-hand side or the right-hand side. E.g. ADDVN is an addition with a numeric constant on the right.

Setting an upvalue is specialized on the operand type. E.g. USETN is used to store a number constant.

Indexing operations are specialized into getters and setters and on the index operand type and range. E.g. TGETB is for loads with constant integer indices 0 to 255 or TSETS is for stores with a constant string key.

Calls are specialized into regular calls CALL and tailcalls CALLT.

Returns with 0 or 1 result use RET0 or RET1 instead of the generic RET.

Calls, returns and table initializers which consume multiple results are specialized. E.g. CALLM is a call that passes on multiple results as arguments.

Every type of loop uses their own specialized bytecode instructions. E.g. the *FOR* instructions are used for numeric 'for' loops.

Loops using pairs() use the specialized ISNEXT and ITERN instructions.