`select` vs `if then else` in wasm

Viewed 1202

What is the difference between if and select in wasm and what is the best application of these commands?

Example in wat2wasm:

WAT code:

(module
  (func (export "Select") (param i32) (result i32)
    (select (i32.const 3)
            (i32.const 5)
            (local.get 0) ))

  (func (export "If") (param i32) (result i32)
    (if (result i32) (local.get 0)
        (then (i32.const  7))
        (else (i32.const 11)) )) )

JS code:

const wasmInstance = new WebAssembly.Instance(wasmModule, {});
const { Select, If } = wasmInstance.exports;
console.log(Select(1)); // =>  3
console.log(Select(0)); // =>  5
console.log(If(1));     // =>  7
console.log(If(0));     // => 11

According to the docs:

The select operator selects one of its first two operands based on whether its third operand is zero or not.

The block, loop and if instructions are structured instructions. They bracket nested sequences of instructions, called blocks, terminated with, or separated by, end or else pseudo-instructions. As the grammar prescribes, they must be well-nested. A structured instruction can produce a value as described by the annotated result type.

however, the select operator may contain block and to execute a number of instructions.

(select (i32.const 3)
        (block (result i32) 
               (i32.const 5) )
        (local.get 0) )
2 Answers

The select instruction is strict, i.e., it always evaluates all its operands, while if only executes one of the branches. So select is the more efficient choice if the operands are simple (e.g., just values), because it does not need to perform any branching. It compiles directly to a single hardware instruction.

Select takes all three operands from the stack while if only takes the decision from the stack and than conditionally executes one of two blocks. This fact is hidden by the way how s-expressions are written in your example. Select puts the selected value back on stack while for if the inner blocks may have an return value, but could be void also.

Related