bytecodealliance / bytecodealliance/wasmtime

riscv64: Improve codegen for operations that use `vslideup`

Open
#7,188 0 comments 0 reactions 0 assignees View on GitHub
cranelift:area:riscv64
Dominant language
Rust
Stars
18.6k
Forks
1.8k
Avg merge
1d 18h
Merged PRs (30d)
126

Description

👋 Hey,

[`vslideup.vi`](https://github.com/riscv/riscv-v-spec/blob/master/v-spec.adoc#1631-vector-slideup-instructions) is a very neat instruction that merges two vector registers by copying the bottom elements of one register into the top elements of another register.

We currently only use it when we cannot perform an operation in a single register due to the register not being large enough.

We should create a `ty_vec_fits_twice_in_reg` extractor that allows us to know that we can fit two vector values in a single register. That way we know we can place twice the elements in a single register.

Instructions that use this operation are:

### `{s,u,uu}narrow`

These operations do a 2x`vnclip` and 1x`vslideup`. We could instead do the `vslideup` first merging both values in the same register, and emit a single `vnclip`.

### `iadd_pairwise`

We don't have a dedicated `iadd_pairwise` instruction. Instead we shuffle the elements in a register and do a regular `vadd.vv`.

This works, but requires us two perform twice the instructions that we normally would have to.

Ideally we would merge both registers in a single `vslideup`, use `vcompress` to extract each side of the addition, and emit a single `vadd` to sum both sides.

The [V8 lowering for `i32x4.dot_i16x8_s`](https://github.com/v8/v8/blob/df99ca37a9d02a3318d3e5487c7803f6230b8f5f/src/wasm/baseline/riscv/liftoff-assembler-riscv.h#L1445-L1460) pulls a similar trick by using LMUL2 which uses two registers. We can't use LMUL>1 due to regalloc incompatibilities.

## Alternatives

We don't actually need to do this. The RISC-V vector specification allows us to use LMUL > 1 to treat a register as having more space than it actually does.

The way this works is by combining multiple registers and having each instruction working on multiple registers at once.

The reason we don't currently do this is that it adds a bunch of register allocation constraints that we can't describe to regalloc2.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.