Skip to content

Commit

Permalink
pulley: Fill out most remaining simd float ops
Browse files Browse the repository at this point in the history
Get most simd/float-related tests passing. Mostly reusing preexisting
scalar ops for the simd implementation.
  • Loading branch information
alexcrichton committed Jan 6, 2025
1 parent fc7ef8d commit 9e97260
Show file tree
Hide file tree
Showing 21 changed files with 236 additions and 10 deletions.
38 changes: 36 additions & 2 deletions cranelift/codegen/src/isa/pulley_shared/lower.isle
Original file line number Diff line number Diff line change
Expand Up @@ -756,6 +756,9 @@
(rule (lower (fcmp cc a b @ (value_type (ty_scalar_float ty))))
(lower_fcmp ty cc a b))

(rule 1 (lower (fcmp cc a b @ (value_type (ty_vec128 ty))))
(lower_vfcmp ty cc a b))

(decl lower_fcmp (Type FloatCC Value Value) XReg)

(rule (lower_fcmp $F32 (FloatCC.Equal) a b) (pulley_feq32 a b))
Expand Down Expand Up @@ -787,6 +790,32 @@
(if-let true (floatcc_unordered cc))
(pulley_xbxor32_s8 (lower_fcmp ty (floatcc_complement cc) a b) 1))

(decl lower_vfcmp (Type FloatCC Value Value) VReg)

(rule (lower_vfcmp $F32X4 (FloatCC.Equal) a b) (pulley_veqf32x4 a b))
(rule (lower_vfcmp $F64X2 (FloatCC.Equal) a b) (pulley_veqf64x2 a b))
(rule (lower_vfcmp $F32X4 (FloatCC.NotEqual) a b) (pulley_vneqf32x4 a b))
(rule (lower_vfcmp $F64X2 (FloatCC.NotEqual) a b) (pulley_vneqf64x2 a b))
(rule (lower_vfcmp $F32X4 (FloatCC.LessThan) a b) (pulley_vltf32x4 a b))
(rule (lower_vfcmp $F64X2 (FloatCC.LessThan) a b) (pulley_vltf64x2 a b))
(rule (lower_vfcmp $F32X4 (FloatCC.LessThanOrEqual) a b) (pulley_vlteqf32x4 a b))
(rule (lower_vfcmp $F64X2 (FloatCC.LessThanOrEqual) a b) (pulley_vlteqf64x2 a b))

(rule (lower_vfcmp ty (FloatCC.Unordered) a b)
(pulley_vbor128
(lower_vfcmp ty (FloatCC.NotEqual) a a)
(lower_vfcmp ty (FloatCC.NotEqual) b b)))

;; NB: Pulley doesn't have lowerings for `Ordered` or `Unordered*` `FloatCC`
;; conditions as that's not needed by wasm at this time.

;; Pulley doesn't have instructions for `>` and `>=`, so we have to reverse the
;; operation.
(rule (lower_vfcmp ty (FloatCC.GreaterThan) a b)
(lower_vfcmp ty (FloatCC.LessThan) b a))
(rule (lower_vfcmp ty (FloatCC.GreaterThanOrEqual) a b)
(lower_vfcmp ty (FloatCC.LessThanOrEqual) b a))

;;;; Rules for `load` and friends ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(decl amode (Value Offset32) Amode)
Expand Down Expand Up @@ -1203,6 +1232,7 @@
(pulley_vfloor32x4 a))
(rule (lower (has_type $F64X2 (floor a)))
(pulley_vfloor64x2 a))

;;;; Rules for `ceil` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(rule (lower (has_type $F32 (ceil a))) (pulley_fceil32 a))
Expand Down Expand Up @@ -1230,7 +1260,6 @@
(rule (lower (has_type $F64X2 (sqrt a)))
(pulley_vsqrt64x2 a))


;;;; Rules for `fneg` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(rule (lower (has_type $F32 (fneg a))) (pulley_fneg32 a))
Expand Down Expand Up @@ -1407,11 +1436,16 @@
(rule (lower (scalar_to_vector a @ (value_type $F64)))
(pulley_vinsertf64 (pulley_vconst128 0) a 0))

;;;; Rules for `shuffle` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Rules for `shuffle` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(rule (lower (has_type $I8X16 (shuffle a b (u128_from_immediate mask))))
(pulley_vshuffle a b mask))

;;;; Rules for `swizzle` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(rule 1 (lower (has_type $I8X16 (swizzle a b))) (pulley_vswizzlei8x16 a b))

;;;; Rules for `fma` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(rule (lower (has_type $F32X4 (fma a b c))) (pulley_vfma32x4 a b c))
(rule (lower (has_type $F64X2 (fma a b c))) (pulley_vfma64x2 a b c))
4 changes: 4 additions & 0 deletions cranelift/filetests/filetests/runtests/simd-fadd-splat.clif
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ target x86_64 sse42 has_avx
set enable_multi_ret_implicit_sret
target riscv64 has_v
target riscv64 has_v has_c has_zcb
target pulley32
target pulley32be
target pulley64
target pulley64be

function %splat_f32x4_2(f32x4) -> f32x4 {
block0(v0: f32x4):
Expand Down
4 changes: 4 additions & 0 deletions cranelift/filetests/filetests/runtests/simd-fadd.clif
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ target x86_64 sse42 has_avx
set enable_multi_ret_implicit_sret
target riscv64 has_v
target riscv64 has_v has_c has_zcb
target pulley32
target pulley32be
target pulley64
target pulley64be


function %fadd_f32x4(f32x4, f32x4) -> f32x4 {
Expand Down
4 changes: 4 additions & 0 deletions cranelift/filetests/filetests/runtests/simd-fcmp-eq.clif
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ target x86_64 has_sse3 has_ssse3 has_sse41 has_avx
set enable_multi_ret_implicit_sret
target riscv64 has_v
target riscv64 has_v has_c has_zcb
target pulley32
target pulley32be
target pulley64
target pulley64be

function %simd_fcmp_eq_f32(f32x4, f32x4) -> i32x4 {
block0(v0: f32x4, v1: f32x4):
Expand Down
4 changes: 4 additions & 0 deletions cranelift/filetests/filetests/runtests/simd-fcmp-ge.clif
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ target x86_64 has_sse3 has_ssse3 has_sse41 has_avx
set enable_multi_ret_implicit_sret
target riscv64 has_v
target riscv64 has_v has_c has_zcb
target pulley32
target pulley32be
target pulley64
target pulley64be

function %simd_fcmp_ge_f32(f32x4, f32x4) -> i32x4 {
block0(v0: f32x4, v1: f32x4):
Expand Down
4 changes: 4 additions & 0 deletions cranelift/filetests/filetests/runtests/simd-fcmp-gt.clif
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ target x86_64 has_sse3 has_ssse3 has_sse41 has_avx
set enable_multi_ret_implicit_sret
target riscv64 has_v
target riscv64 has_v has_c has_zcb
target pulley32
target pulley32be
target pulley64
target pulley64be

function %simd_fcmp_gt_f32(f32x4, f32x4) -> i32x4 {
block0(v0: f32x4, v1: f32x4):
Expand Down
4 changes: 4 additions & 0 deletions cranelift/filetests/filetests/runtests/simd-fcmp-le.clif
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ target x86_64 has_sse3 has_ssse3 has_sse41 has_avx
set enable_multi_ret_implicit_sret
target riscv64 has_v
target riscv64 has_v has_c has_zcb
target pulley32
target pulley32be
target pulley64
target pulley64be

function %simd_fcmp_le_f32(f32x4, f32x4) -> i32x4 {
block0(v0: f32x4, v1: f32x4):
Expand Down
4 changes: 4 additions & 0 deletions cranelift/filetests/filetests/runtests/simd-fcmp-lt.clif
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ target x86_64 has_sse3 has_ssse3 has_sse41 has_avx
set enable_multi_ret_implicit_sret
target riscv64 has_v
target riscv64 has_v has_c has_zcb
target pulley32
target pulley32be
target pulley64
target pulley64be

function %simd_fcmp_lt_f32(f32x4, f32x4) -> i32x4 {
block0(v0: f32x4, v1: f32x4):
Expand Down
4 changes: 4 additions & 0 deletions cranelift/filetests/filetests/runtests/simd-fcmp-ne.clif
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ target x86_64 has_sse3 has_ssse3 has_sse41 has_avx
set enable_multi_ret_implicit_sret
target riscv64 has_v
target riscv64 has_v has_c has_zcb
target pulley32
target pulley32be
target pulley64
target pulley64be

function %simd_fcmp_ne_f32(f32x4, f32x4) -> i32x4 {
block0(v0: f32x4, v1: f32x4):
Expand Down
4 changes: 4 additions & 0 deletions cranelift/filetests/filetests/runtests/simd-fcmp-uno.clif
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ target x86_64 has_sse3 has_ssse3 has_sse41 has_avx
set enable_multi_ret_implicit_sret
target riscv64 has_v
target riscv64 has_v has_c has_zcb
target pulley32
target pulley32be
target pulley64
target pulley64be

function %simd_fcmp_uno_f32(f32x4, f32x4) -> i32x4 {
block0(v0: f32x4, v1: f32x4):
Expand Down
4 changes: 4 additions & 0 deletions cranelift/filetests/filetests/runtests/simd-fdiv.clif
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ target x86_64 sse42 has_avx
set enable_multi_ret_implicit_sret
target riscv64 has_v
target riscv64 has_v has_c has_zcb
target pulley32
target pulley32be
target pulley64
target pulley64be


function %fdiv_f32x4(f32x4, f32x4) -> f32x4 {
Expand Down
4 changes: 4 additions & 0 deletions cranelift/filetests/filetests/runtests/simd-floor.clif
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ target s390x
set enable_multi_ret_implicit_sret
target riscv64 has_v
target riscv64 has_v has_c has_zcb
target pulley32
target pulley32be
target pulley64
target pulley64be

function %floor_f32x4(f32x4) -> f32x4 {
block0(v0: f32x4):
Expand Down
4 changes: 4 additions & 0 deletions cranelift/filetests/filetests/runtests/simd-fma-neg.clif
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ target aarch64
set enable_multi_ret_implicit_sret
target riscv64 has_v
target riscv64 has_v has_c has_zcb
target pulley32
target pulley32be
target pulley64
target pulley64be

;; This file is not enabled in the interpreter since SIMD fneg is currently broken
;; there.
Expand Down
4 changes: 4 additions & 0 deletions cranelift/filetests/filetests/runtests/simd-fma.clif
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ target aarch64
set enable_multi_ret_implicit_sret
target riscv64 has_v
target riscv64 has_v has_c has_zcb
target pulley32
target pulley32be
target pulley64
target pulley64be

function %fma_f32x4(f32x4, f32x4, f32x4) -> f32x4 {
block0(v0: f32x4, v1: f32x4, v2: f32x4):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ target x86_64 skylake
set enable_multi_ret_implicit_sret
target riscv64 has_v
target riscv64 has_v has_c has_zcb
target pulley32
target pulley32be
target pulley64
target pulley64be

function %fmin_pseudo_f32x4(f32x4, f32x4) -> f32x4 {
block0(v0:f32x4, v1:f32x4):
Expand Down
4 changes: 4 additions & 0 deletions cranelift/filetests/filetests/runtests/simd-fmul.clif
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ target x86_64 sse42 has_avx
set enable_multi_ret_implicit_sret
target riscv64 has_v
target riscv64 has_v has_c has_zcb
target pulley32
target pulley32be
target pulley64
target pulley64be


function %fmul_f32x4(f32x4, f32x4) -> f32x4 {
Expand Down
4 changes: 4 additions & 0 deletions cranelift/filetests/filetests/runtests/simd-fneg.clif
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ target x86_64 sse42 has_avx
set enable_multi_ret_implicit_sret
target riscv64 has_v
target riscv64 has_v has_c has_zcb
target pulley32
target pulley32be
target pulley64
target pulley64be

function %fneg_f32x4(f32x4) -> f32x4 {
block0(v0: f32x4):
Expand Down
4 changes: 4 additions & 0 deletions cranelift/filetests/filetests/runtests/simd-fsub.clif
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ target x86_64 sse42 has_avx
set enable_multi_ret_implicit_sret
target riscv64 has_v
target riscv64 has_v has_c has_zcb
target pulley32
target pulley32be
target pulley64
target pulley64be


function %fsub_f32x4(f32x4, f32x4) -> f32x4 {
Expand Down
8 changes: 0 additions & 8 deletions crates/wast-util/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -401,17 +401,9 @@ impl WastTest {
// features in Pulley are implemented.
if config.compiler == Compiler::CraneliftPulley {
let unsupported = [
"misc_testsuite/simd/canonicalize-nan.wast",
"misc_testsuite/simd/issue_3327_bnot_lowering.wast",
"misc_testsuite/simd/v128-select.wast",
"spec_testsuite/proposals/relaxed-simd/i32x4_relaxed_trunc.wast",
"spec_testsuite/proposals/relaxed-simd/relaxed_madd_nmadd.wast",
"spec_testsuite/proposals/memory64/relaxed_madd_nmadd.wast",
"spec_testsuite/proposals/memory64/i32x4_relaxed_trunc.wast",
"spec_testsuite/simd_f32x4_cmp.wast",
"spec_testsuite/simd_f32x4_pmin_pmax.wast",
"spec_testsuite/simd_f64x2_cmp.wast",
"spec_testsuite/simd_f64x2_pmin_pmax.wast",
"spec_testsuite/simd_i32x4_trunc_sat_f32x4.wast",
"spec_testsuite/simd_i32x4_trunc_sat_f64x2.wast",
"spec_testsuite/simd_load.wast",
Expand Down
110 changes: 110 additions & 0 deletions pulley/src/interp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4681,4 +4681,114 @@ impl ExtendedOpVisitor for Interpreter<'_> {
self.state[operands.dst].set_u16x8(a);
ControlFlow::Continue(())
}

fn veqf32x4(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
let a = self.state[operands.src1].get_f32x4();
let b = self.state[operands.src2].get_f32x4();
let mut c = [0; 4];
for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
*c = if a == b { u32::MAX } else { 0 };
}
self.state[operands.dst].set_u32x4(c);
ControlFlow::Continue(())
}

fn vneqf32x4(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
let a = self.state[operands.src1].get_f32x4();
let b = self.state[operands.src2].get_f32x4();
let mut c = [0; 4];
for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
*c = if a != b { u32::MAX } else { 0 };
}
self.state[operands.dst].set_u32x4(c);
ControlFlow::Continue(())
}

fn vltf32x4(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
let a = self.state[operands.src1].get_f32x4();
let b = self.state[operands.src2].get_f32x4();
let mut c = [0; 4];
for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
*c = if a < b { u32::MAX } else { 0 };
}
self.state[operands.dst].set_u32x4(c);
ControlFlow::Continue(())
}

fn vlteqf32x4(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
let a = self.state[operands.src1].get_f32x4();
let b = self.state[operands.src2].get_f32x4();
let mut c = [0; 4];
for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
*c = if a <= b { u32::MAX } else { 0 };
}
self.state[operands.dst].set_u32x4(c);
ControlFlow::Continue(())
}

fn veqf64x2(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
let a = self.state[operands.src1].get_f64x2();
let b = self.state[operands.src2].get_f64x2();
let mut c = [0; 2];
for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
*c = if a == b { u64::MAX } else { 0 };
}
self.state[operands.dst].set_u64x2(c);
ControlFlow::Continue(())
}

fn vneqf64x2(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
let a = self.state[operands.src1].get_f64x2();
let b = self.state[operands.src2].get_f64x2();
let mut c = [0; 2];
for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
*c = if a != b { u64::MAX } else { 0 };
}
self.state[operands.dst].set_u64x2(c);
ControlFlow::Continue(())
}

fn vltf64x2(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
let a = self.state[operands.src1].get_f64x2();
let b = self.state[operands.src2].get_f64x2();
let mut c = [0; 2];
for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
*c = if a < b { u64::MAX } else { 0 };
}
self.state[operands.dst].set_u64x2(c);
ControlFlow::Continue(())
}

fn vlteqf64x2(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
let a = self.state[operands.src1].get_f64x2();
let b = self.state[operands.src2].get_f64x2();
let mut c = [0; 2];
for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
*c = if a <= b { u64::MAX } else { 0 };
}
self.state[operands.dst].set_u64x2(c);
ControlFlow::Continue(())
}

fn vfma32x4(&mut self, dst: VReg, a: VReg, b: VReg, c: VReg) -> ControlFlow<Done> {
let mut a = self.state[a].get_f32x4();
let b = self.state[b].get_f32x4();
let c = self.state[c].get_f32x4();
for ((a, b), c) in a.iter_mut().zip(b).zip(c) {
*a = a.mul_add(b, c);
}
self.state[dst].set_f32x4(a);
ControlFlow::Continue(())
}

fn vfma64x2(&mut self, dst: VReg, a: VReg, b: VReg, c: VReg) -> ControlFlow<Done> {
let mut a = self.state[a].get_f64x2();
let b = self.state[b].get_f64x2();
let c = self.state[c].get_f64x2();
for ((a, b), c) in a.iter_mut().zip(b).zip(c) {
*a = a.mul_add(b, c);
}
self.state[dst].set_f64x2(a);
ControlFlow::Continue(())
}
}
Loading

0 comments on commit 9e97260

Please sign in to comment.