Skip to content

Augment load/store instructions w/ index and scale #1277

Open
@binji

Description

@binji

@aardappel and I were discussing this briefly today:

If you were to compile the following array access:

uint32_t array[100];
array[x]

in current wasm, you have to generate something like this:

0000: 20 00    ; local.get $array
0002: 20 01    ; local.get $x
0004: 41 02    ; i32.const 2
0006: 74       ; i32.shl
0007: 6a       ; i32.add
0008: 28 02 00 ; i32.load align=2 offset=0
000b:

Since this is such a common operation, it would be nice to have a dedicated instruction for this. We could encode an immediate scale value by using unused alignment bits, since the current spec requires that the alignment value is not larger than natural alignment for the access width.

So for i32.load, we could encode the new alignment immediate as follows:

...000sssssaa

Where aa is the alignment value and sssss provides a constant shift value in the range [0, 32).

This scale is not very useful without a base value, so providing a non-zero sssss value would change the stack signature of the load from [base i32] -> [i32] to [base i32, index i32] -> [i32].

(We may instead want the scale to be sssss - 1, so we can perform base + index*1 and because sssss == 31 is not very valuable.)

With this new instruction, we can generate a nicer instruction sequence:

0000: 20 00    ; local.get $array
0002: 20 01    ; local.get $x
0004: 28 0a 00 ; i32.load scale=2 align=2 offset=0
0007:

saving 4 bytes. It has some other nice benefits too: it should be easier for baseline compilers to optimize this instruction. We can also require the address calculation to be non-wrapping, which the previous instruction sequence can't guarantee (and would be difficult to provide).

Thoughts?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions