Skip to content

Commit

Permalink
riscv64: Add extractlane and splat instructions (bytecodealliance…
Browse files Browse the repository at this point in the history
…#6397)

* riscv64: Add `vslidedown.v{x,i}` instructions

* riscv64: Add `v{f,}mv` instructions

These instructions move values from vectors into other register types and vice-versa.

* riscv64: Add `extractlane` lowerings

* riscv64: Add `vmv.v.*` instructions

* riscv64: Implement `splat`

* riscv64: Add `vmv.v.i` instruction

* riscv64: Remove unused `imm5_zero`

* wasmtime: Enable more RISC-V SIMD tests

* cranelift: Enable ssse3 tests for `fadd-splat` testsuite

* riscv64: Update splat TODO comment
  • Loading branch information
afonso360 authored May 17, 2023
1 parent 338b535 commit 752c7ea
Show file tree
Hide file tree
Showing 15 changed files with 1,116 additions and 32 deletions.
6 changes: 0 additions & 6 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -253,14 +253,8 @@ fn ignore(testsuite: &str, testname: &str, strategy: &str) -> bool {
"simd_load64_lane",
"simd_load8_lane",
"simd_load_extend",
"simd_load_splat",
"simd_load_zero",
"simd_splat",
"simd_store16_lane",
"simd_store32_lane",
"simd_store64_lane",
"simd_store8_lane",
"spillslot_size_fuzzbug",
"v128_select",
]
.contains(&testname);
Expand Down
20 changes: 20 additions & 0 deletions cranelift/codegen/src/isa/riscv64/inst.isle
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,18 @@
(imm Imm5)
(vstate VState))

(VecAluRR
(op VecAluOpRR)
(vd WritableReg)
(vs Reg)
(vstate VState))

(VecAluRImm5
(op VecAluOpRImm5)
(vd WritableReg)
(imm Imm5)
(vstate VState))

(VecSetState
(rd WritableReg)
(vstate VState))
Expand Down Expand Up @@ -1353,6 +1365,14 @@
(extractor (replicated_imm5 n)
(def_inst (splat (iconst (u64_from_imm64 (imm5_from_u64 n))))))

;; UImm5 Helpers

;; Extract a `UImm5` from an `u8`.
(decl pure partial uimm5_from_u8 (UImm5) u8)
(extern extractor uimm5_from_u8 uimm5_from_u8)

(decl uimm5_bitcast_to_imm5 (UImm5) Imm5)
(extern constructor uimm5_bitcast_to_imm5 uimm5_bitcast_to_imm5)

;; Float Helpers

Expand Down
13 changes: 13 additions & 0 deletions cranelift/codegen/src/isa/riscv64/inst/emit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -467,7 +467,9 @@ impl Inst {
// VecSetState does not expect any vstate, rather it updates it.
Inst::VecSetState { .. } => None,

Inst::VecAluRR { vstate, .. } |
Inst::VecAluRRR { vstate, .. } |
Inst::VecAluRImm5 { vstate, .. } |
Inst::VecAluRRImm5 { vstate, .. } |
// TODO: Unit-stride loads and stores only need the AVL to be correct, not
// the full vtype. A future optimization could be to decouple these two when
Expand Down Expand Up @@ -2818,6 +2820,17 @@ impl MachInstEmit for Inst {

sink.put4(encode_valu_imm(op, vd, imm, vs2, VecOpMasking::Disabled));
}
&Inst::VecAluRR { op, vd, vs, .. } => {
let vs = allocs.next(vs);
let vd = allocs.next_writable(vd);

sink.put4(encode_valu_rr(op, vd, vs, VecOpMasking::Disabled));
}
&Inst::VecAluRImm5 { op, vd, imm, .. } => {
let vd = allocs.next_writable(vd);

sink.put4(encode_valu_r_imm(op, vd, imm, VecOpMasking::Disabled));
}
&Inst::VecSetState { rd, ref vstate } => {
let rd = allocs.next_writable(rd);

Expand Down
45 changes: 44 additions & 1 deletion cranelift/codegen/src/isa/riscv64/inst/encode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
use super::{Imm12, Imm5, UImm5, VType};
use crate::isa::riscv64::inst::reg_to_gpr_num;
use crate::isa::riscv64::lower::isle::generated_code::{
VecAluOpRRImm5, VecAluOpRRR, VecElementWidth, VecOpCategory, VecOpMasking,
VecAluOpRImm5, VecAluOpRR, VecAluOpRRImm5, VecAluOpRRR, VecElementWidth, VecOpCategory,
VecOpMasking,
};
use crate::machinst::isle::WritableReg;
use crate::Reg;
Expand Down Expand Up @@ -145,6 +146,48 @@ pub fn encode_valu_imm(
)
}

pub fn encode_valu_rr(op: VecAluOpRR, vd: WritableReg, vs: Reg, masking: VecOpMasking) -> u32 {
let funct7 = (op.funct6() << 1) | masking.encode();

let (vs1, vs2) = if op.vs_is_vs2_encoded() {
(op.aux_encoding(), reg_to_gpr_num(vs))
} else {
(reg_to_gpr_num(vs), op.aux_encoding())
};

encode_r_type_bits(
op.opcode(),
reg_to_gpr_num(vd.to_reg()),
op.funct3(),
vs1,
vs2,
funct7,
)
}

pub fn encode_valu_r_imm(
op: VecAluOpRImm5,
vd: WritableReg,
imm: Imm5,
masking: VecOpMasking,
) -> u32 {
let funct7 = (op.funct6() << 1) | masking.encode();

// This is true for this opcode, not sure if there are any other ones.
debug_assert_eq!(op, VecAluOpRImm5::VmvVI);
let vs1 = imm.bits() as u32;
let vs2 = op.aux_encoding();

encode_r_type_bits(
op.opcode(),
reg_to_gpr_num(vd.to_reg()),
op.funct3(),
vs1,
vs2,
funct7,
)
}

/// Encodes a Vector CFG Imm instruction.
///
/// See: https://github.com/riscv/riscv-v-spec/blob/master/vcfg-format.adoc
Expand Down
6 changes: 6 additions & 0 deletions cranelift/codegen/src/isa/riscv64/inst/imms.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,12 @@ impl Imm5 {
}
}

pub fn from_bits(value: u8) -> Imm5 {
assert_eq!(value & 0x1f, value);
let signed = ((value << 3) as i8) >> 3;
Imm5 { value: signed }
}

/// Bits for encoding.
pub fn bits(&self) -> u8 {
self.value as u8 & 0x1f
Expand Down
43 changes: 42 additions & 1 deletion cranelift/codegen/src/isa/riscv64/inst/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -642,6 +642,18 @@ fn riscv64_get_operands<F: Fn(VReg) -> VReg>(inst: &Inst, collector: &mut Operan
collector.reg_use(vs2);
collector.reg_def(vd);
}
&Inst::VecAluRR { op, vd, vs, .. } => {
debug_assert_eq!(vd.to_reg().class(), op.dst_regclass());
debug_assert_eq!(vs.class(), op.src_regclass());

collector.reg_use(vs);
collector.reg_def(vd);
}
&Inst::VecAluRImm5 { vd, .. } => {
debug_assert_eq!(vd.to_reg().class(), RegClass::Vector);

collector.reg_def(vd);
}
&Inst::VecSetState { rd, .. } => {
collector.reg_def(rd);
}
Expand Down Expand Up @@ -1585,7 +1597,36 @@ impl Inst {
let vs2_s = format_reg(vs2, allocs);
let vd_s = format_reg(vd.to_reg(), allocs);

format!("{} {},{},{} {}", op, vd_s, vs2_s, imm, vstate)
// Some opcodes interpret the immediate as unsigned, lets show the
// correct number here.
let imm_s = if op.imm_is_unsigned() {
format!("{}", imm.bits())
} else {
format!("{}", imm)
};

format!("{} {},{},{} {}", op, vd_s, vs2_s, imm_s, vstate)
}
&Inst::VecAluRR {
op,
vd,
vs,
ref vstate,
} => {
let vs_s = format_reg(vs, allocs);
let vd_s = format_reg(vd.to_reg(), allocs);

format!("{} {},{} {}", op, vd_s, vs_s, vstate)
}
&Inst::VecAluRImm5 {
op,
vd,
imm,
ref vstate,
} => {
let vd_s = format_reg(vd.to_reg(), allocs);

format!("{} {},{} {}", op, vd_s, imm, vstate)
}
&Inst::VecSetState { rd, ref vstate } => {
let rd_s = format_reg(rd.to_reg(), allocs);
Expand Down
Loading

0 comments on commit 752c7ea

Please sign in to comment.