diff --git a/cranelift/codegen/src/ir/types.rs b/cranelift/codegen/src/ir/types.rs index 4284021190..6eaa937fbd 100644 --- a/cranelift/codegen/src/ir/types.rs +++ b/cranelift/codegen/src/ir/types.rs @@ -133,11 +133,11 @@ impl Type { /// Scalar types follow this same rule, but `b1` is converted into `i8` pub fn as_int(self) -> Self { self.replace_lanes(match self.lane_type() { - B1 | B8 => I8, - B16 => I16, - B32 => I32, - B64 => I64, - B128 => I128, + I8 | B1 | B8 => I8, + I16 | B16 => I16, + I32 | B32 => I32, + I64 | B64 => I64, + I128 | B128 => I128, _ => unimplemented!(), }) } diff --git a/cranelift/filetests/filetests/runtests/simd-icmp-eq.clif b/cranelift/filetests/filetests/runtests/simd-icmp-eq.clif new file mode 100644 index 0000000000..d37d8ace18 --- /dev/null +++ b/cranelift/filetests/filetests/runtests/simd-icmp-eq.clif @@ -0,0 +1,30 @@ +test interpret + +function %simd_icmp_eq_i8(i8x16, i8x16) -> b8x16 { +block0(v0: i8x16, v1: i8x16): + v2 = icmp eq v0, v1 + return v2 +} +; run: %simd_icmp_eq_i8([1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1], [1 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0]) == [true true true false false false false false false false false false false false false false] + +function %simd_icmp_eq_i16(i16x8, i16x8) -> b16x8 { +block0(v0: i16x8, v1: i16x8): + v2 = icmp eq v0, v1 + return v2 +} +; run: %simd_icmp_eq_i16([1 0 -1 1 1 1 1 1], [1 0 -1 0 0 0 0 0]) == [true true true false false false false false] + +function %simd_icmp_eq_i32(i32x4, i32x4) -> b32x4 { +block0(v0: i32x4, v1: i32x4): + v2 = icmp eq v0, v1 + return v2 +} +; run: %simd_icmp_eq_i32([1 0 -1 1], [1 0 -1 0]) == [true true true false] + +function %simd_icmp_eq_i64(i64x2, i64x2) -> b64x2 { +block0(v0: i64x2, v1: i64x2): + v2 = icmp eq v0, v1 + return v2 +} +; run: %simd_icmp_eq_i64([10 0], [1 0]) == [false true] +; run: %simd_icmp_eq_i64([-1 1], [-1 0]) == [true false] diff --git a/cranelift/filetests/filetests/runtests/simd-icmp-ne.clif b/cranelift/filetests/filetests/runtests/simd-icmp-ne.clif new file mode 100644 index 0000000000..8b0400bf17 --- /dev/null +++ b/cranelift/filetests/filetests/runtests/simd-icmp-ne.clif @@ -0,0 +1,30 @@ +test interpret + +function %simd_icmp_ne_i8(i8x16, i8x16) -> b8x16 { +block0(v0: i8x16, v1: i8x16): + v2 = icmp ne v0, v1 + return v2 +} +; run: %simd_icmp_ne_i8([1 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1], [1 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0]) == [false false false true true true true true true true true true true true true true] + +function %simd_icmp_ne_i16(i16x8, i16x8) -> b16x8 { +block0(v0: i16x8, v1: i16x8): + v2 = icmp ne v0, v1 + return v2 +} +; run: %simd_icmp_ne_i16([1 0 -1 1 1 1 1 1], [1 0 -1 0 0 0 0 0]) == [false false false true true true true true] + +function %simd_icmp_ne_i32(i32x4, i32x4) -> b32x4 { +block0(v0: i32x4, v1: i32x4): + v2 = icmp ne v0, v1 + return v2 +} +; run: %simd_icmp_ne_i32([1 0 -1 1], [1 0 -1 0]) == [false false false true] + +function %simd_icmp_ne_i64(i64x2, i64x2) -> b64x2 { +block0(v0: i64x2, v1: i64x2): + v2 = icmp ne v0, v1 + return v2 +} +; run: %simd_icmp_ne_i64([10 0], [1 0]) == [true false] +; run: %simd_icmp_ne_i64([-1 1], [-1 0]) == [false true] diff --git a/cranelift/filetests/filetests/runtests/simd-icmp-nof.clif b/cranelift/filetests/filetests/runtests/simd-icmp-nof.clif new file mode 100644 index 0000000000..e319bffd41 --- /dev/null +++ b/cranelift/filetests/filetests/runtests/simd-icmp-nof.clif @@ -0,0 +1,45 @@ +test interpret + +function %simd_icmp_nof_i8(i8x16, i8x16) -> b8x16 { +block0(v0: i8x16, v1: i8x16): + v2 = icmp nof v0, v1 + return v2 +} +; run: %simd_icmp_nof_i8([0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0], [0 1 0 0xFF 0 0 0 0 0 0 0 0 0 0 0 0]) == [true true true true true true true true true true true true true true true true] +; run: %simd_icmp_nof_i8([0x80 0x7F 0x7F 0xFF 0 0 0 0 0 0 0 0 0 0 0 0], [0x80 0x01 0x7F 0x01 0 0 0 0 0 0 0 0 0 0 0 0]) == [true true true true true true true true true true true true true true true true] +; run: %simd_icmp_nof_i8([0x80 0x7F 0x80 0x7F 0 0 0 0 0 0 0 0 0 0 0 0], [0x01 0x80 0x7F 0xFF 0 0 0 0 0 0 0 0 0 0 0 0]) == [false false false false true true true true true true true true true true true true] +; run: %simd_icmp_nof_i8([0x7F 0x7F 0x7F 0x7F 0x7F 0x7F 0x7F 0x7F 0x7F 0x7F 0x7F 0x7F 0x7F 0x7F 0x7F 0x7F], [0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF]) == [false false false false false false false false false false false false false false false false] + + +function %simd_icmp_nof_i16(i16x8, i16x8) -> b16x8 { +block0(v0: i16x8, v1: i16x8): + v2 = icmp nof v0, v1 + return v2 +} +; run: %simd_icmp_nof_i1([0 0 1 0 0 0 0 0], [0 1 0 0xFFFF 0 0 0 0]) == [true true true true true true true true] +; run: %simd_icmp_nof_i1([0x8000 0x7FFF 0x7FFF 0xFFFF 0 0 0 0], [0x8000 0x0001 0x7FFF 0x0001 0 0 0 0]) == [true true true true true true true true] +; run: %simd_icmp_nof_i1([0x8000 0x7FFF 0x8000 0x7FFF 0 0 0 0], [0x0001 0x8000 0x7FFF 0xFFFF 0 0 0 0]) == [false false false false true true true true] +; run: %simd_icmp_nof_i1([0x7FFF 0x7FFF 0x7FFF 0x7FFF 0x7FFF 0x7FFF 0x7FFF 0x7FFF], [0xFFFF 0xFFFF 0xFFFF 0xFFFF 0xFFFF 0xFFFF 0xFFFF 0xFFFF]) == [false false false false false false false false] + + +function %simd_icmp_nof_i32(i32x4, i32x4) -> b32x4 { +block0(v0: i32x4, v1: i32x4): + v2 = icmp nof v0, v1 + return v2 +} +; run: %simd_icmp_nof_i3([0 0 1 0], [0 1 0 0xFFFFFFFF]) == [true true true true] +; run: %simd_icmp_nof_i3([0x80000000 0x7FFFFFFF 0x7FFFFFFF 0xFFFFFFFF], [0x80000000 0x00000001 0x7FFFFFFF 0x00000001]) == [true true true true] +; run: %simd_icmp_nof_i3([0x80000000 0x7FFFFFFF 0x80000000 0x7FFFFFFF], [0x00000001 0x80000000 0x7FFFFFFF 0xFFFFFFFF]) == [false false false false] +; run: %simd_icmp_nof_i3([0x7FFFFFFF 0x7FFFFFFF 0x7FFFFFFF 0x7FFFFFFF], [0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF]) == [false false false false] + +function %simd_icmp_nof_i64(i64x2, i64x2) -> b64x2 { +block0(v0: i64x2, v1: i64x2): + v2 = icmp nof v0, v1 + return v2 +} +; run: %simd_icmp_nof_i6([0 0], [0 1]) == [true true] +; run: %simd_icmp_nof_i6([1 0], [0 0xFFFFFFFF_FFFFFFFF]) == [true true] +; run: %simd_icmp_nof_i6([0x80000000_00000000 0x7FFFFFFF_FFFFFFFF], [0x80000000_00000000 0x00000000_00000001]) == [true true] +; run: %simd_icmp_nof_i6([0x7FFFFFFF_FFFFFFFF 0xFFFFFFFF_FFFFFFFF], [0x7FFFFFFF_FFFFFFFF 0x00000000_00000001]) == [true true] +; run: %simd_icmp_nof_i6([0x80000000_00000000 0x7FFFFFFF_FFFFFFFF], [0x01 0x80000000_00000000]) == [false false] +; run: %simd_icmp_nof_i6([0x80000000_00000000 0x7FFFFFFF_FFFFFFFF], [0x7FFFFFFF_FFFFFFFF 0xFFFFFFFF_FFFFFFFF]) == [false false] diff --git a/cranelift/filetests/filetests/runtests/simd-icmp-of.clif b/cranelift/filetests/filetests/runtests/simd-icmp-of.clif new file mode 100644 index 0000000000..62aa9f5b99 --- /dev/null +++ b/cranelift/filetests/filetests/runtests/simd-icmp-of.clif @@ -0,0 +1,45 @@ +test interpret + +function %simd_icmp_of_i8(i8x16, i8x16) -> b8x16 { +block0(v0: i8x16, v1: i8x16): + v2 = icmp of v0, v1 + return v2 +} +; run: %simd_icmp_of_i8([0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0], [0 1 0 0xFF 0 0 0 0 0 0 0 0 0 0 0 0]) == [false false false false false false false false false false false false false false false false] +; run: %simd_icmp_of_i8([0x80 0x7F 0x7F 0xFF 0 0 0 0 0 0 0 0 0 0 0 0], [0x80 0x01 0x7F 0x01 0 0 0 0 0 0 0 0 0 0 0 0]) == [false false false false false false false false false false false false false false false false] +; run: %simd_icmp_of_i8([0x80 0x7F 0x80 0x7F 0 0 0 0 0 0 0 0 0 0 0 0], [0x01 0x80 0x7F 0xFF 0 0 0 0 0 0 0 0 0 0 0 0]) == [true true true true false false false false false false false false false false false false] +; run: %simd_icmp_of_i8([0x7F 0x7F 0x7F 0x7F 0x7F 0x7F 0x7F 0x7F 0x7F 0x7F 0x7F 0x7F 0x7F 0x7F 0x7F 0x7F], [0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF]) == [true true true true true true true true true true true true true true true true] + + +function %simd_icmp_of_i16(i16x8, i16x8) -> b16x8 { +block0(v0: i16x8, v1: i16x8): + v2 = icmp of v0, v1 + return v2 +} +; run: %simd_icmp_of_i16([0 0 1 0 0 0 0 0], [0 1 0 0xFFFF 0 0 0 0]) == [false false false false false false false false] +; run: %simd_icmp_of_i16([0x8000 0x7FFF 0x7FFF 0xFFFF 0 0 0 0], [0x8000 0x0001 0x7FFF 0x0001 0 0 0 0]) == [false false false false false false false false] +; run: %simd_icmp_of_i16([0x8000 0x7FFF 0x8000 0x7FFF 0 0 0 0], [0x0001 0x8000 0x7FFF 0xFFFF 0 0 0 0]) == [true true true true false false false false] +; run: %simd_icmp_of_i16([0x7FFF 0x7FFF 0x7FFF 0x7FFF 0x7FFF 0x7FFF 0x7FFF 0x7FFF], [0xFFFF 0xFFFF 0xFFFF 0xFFFF 0xFFFF 0xFFFF 0xFFFF 0xFFFF]) == [true true true true true true true true] + + +function %simd_icmp_of_i32(i32x4, i32x4) -> b32x4 { +block0(v0: i32x4, v1: i32x4): + v2 = icmp of v0, v1 + return v2 +} +; run: %simd_icmp_of_i32([0 0 1 0], [0 1 0 0xFFFFFFFF]) == [false false false false] +; run: %simd_icmp_of_i32([0x80000000 0x7FFFFFFF 0x7FFFFFFF 0xFFFFFFFF], [0x80000000 0x00000001 0x7FFFFFFF 0x00000001]) == [false false false false] +; run: %simd_icmp_of_i32([0x80000000 0x7FFFFFFF 0x80000000 0x7FFFFFFF], [0x00000001 0x80000000 0x7FFFFFFF 0xFFFFFFFF]) == [true true true true] +; run: %simd_icmp_of_i32([0x7FFFFFFF 0x7FFFFFFF 0x7FFFFFFF 0x7FFFFFFF], [0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF]) == [true true true true] + +function %simd_icmp_of_i64(i64x2, i64x2) -> b64x2 { +block0(v0: i64x2, v1: i64x2): + v2 = icmp of v0, v1 + return v2 +} +; run: %simd_icmp_of_i64([0 0], [0 1]) == [false false] +; run: %simd_icmp_of_i64([1 0], [0 0xFFFFFFFF_FFFFFFFF]) == [false false] +; run: %simd_icmp_of_i64([0x80000000_00000000 0x7FFFFFFF_FFFFFFFF], [0x80000000_00000000 0x00000000_00000001]) == [false false] +; run: %simd_icmp_of_i64([0x7FFFFFFF_FFFFFFFF 0xFFFFFFFF_FFFFFFFF], [0x7FFFFFFF_FFFFFFFF 0x00000000_00000001]) == [false false] +; run: %simd_icmp_of_i64([0x80000000_00000000 0x7FFFFFFF_FFFFFFFF], [0x01 0x80000000_00000000]) == [true true] +; run: %simd_icmp_of_i64([0x80000000_00000000 0x7FFFFFFF_FFFFFFFF], [0x7FFFFFFF_FFFFFFFF 0xFFFFFFFF_FFFFFFFF]) == [true true] diff --git a/cranelift/filetests/filetests/runtests/simd-icmp-sge.clif b/cranelift/filetests/filetests/runtests/simd-icmp-sge.clif new file mode 100644 index 0000000000..54df67d245 --- /dev/null +++ b/cranelift/filetests/filetests/runtests/simd-icmp-sge.clif @@ -0,0 +1,33 @@ +test interpret + +function %simd_icmp_sge_i8(i8x16, i8x16) -> b8x16 { +block0(v0: i8x16, v1: i8x16): + v2 = icmp sge v0, v1 + return v2 +} +; run: %simd_icmp_sge_i8([0 1 -1 0 -5 1 0 0 0 0 0 0 0 0 0 0], [0 0 -1 1 -1 1 0 0 0 0 0 0 0 0 0 0]) == [true true true false false true true true true true true true true true true true] + +function %simd_icmp_sge_i16(i16x8, i16x8) -> b16x8 { +block0(v0: i16x8, v1: i16x8): + v2 = icmp sge v0, v1 + return v2 +} +; run: %simd_icmp_sge_i1([0 1 -1 0 -5 1 0 0], [0 0 -1 1 -1 1 0 0]) == [true true true false false true true true] + +function %simd_icmp_sge_i32(i32x4, i32x4) -> b32x4 { +block0(v0: i32x4, v1: i32x4): + v2 = icmp sge v0, v1 + return v2 +} +; run: %simd_icmp_sge_i3([0 1 -1 0], [0 0 -1 1]) == [true true true false] +; run: %simd_icmp_sge_i3([-5 1 0 0], [-1 1 0 0]) == [false true true true] + +function %simd_icmp_sge_i64(i64x2, i64x2) -> b64x2 { +block0(v0: i64x2, v1: i64x2): + v2 = icmp sge v0, v1 + return v2 +} +; run: %simd_icmp_sge_i6([0 1], [0 0]) == [true true] +; run: %simd_icmp_sge_i6([-1 0], [-1 1]) == [true false] +; run: %simd_icmp_sge_i6([-5 1], [-1 1]) == [false true] +; run: %simd_icmp_sge_i6([0 0], [0 0]) == [true true] diff --git a/cranelift/filetests/filetests/runtests/simd-icmp-sgt.clif b/cranelift/filetests/filetests/runtests/simd-icmp-sgt.clif new file mode 100644 index 0000000000..4f4be6e159 --- /dev/null +++ b/cranelift/filetests/filetests/runtests/simd-icmp-sgt.clif @@ -0,0 +1,35 @@ +test interpret + +function %simd_icmp_sgt_i8(i8x16, i8x16) -> b8x16 { +block0(v0: i8x16, v1: i8x16): + v2 = icmp sgt v0, v1 + return v2 +} +; run: %simd_icmp_sgt_i8([0 1 -1 0 -5 1 0 0 0 0 0 0 0 0 0 0], [0 0 -1 1 -1 -1 0 0 0 0 0 0 0 0 0 0]) == [false true false false false true false false false false false false false false false false] + +function %simd_icmp_sgt_i16(i16x8, i16x8) -> b16x8 { +block0(v0: i16x8, v1: i16x8): + v2 = icmp sgt v0, v1 + return v2 +} +; run: %simd_icmp_sgt_i1([0 1 -1 0 -5 1 0 0], [0 0 -1 1 -1 -1 0 0]) == [false true false false false true false false] + + +function %simd_icmp_sgt_i32(i32x4, i32x4) -> b32x4 { +block0(v0: i32x4, v1: i32x4): + v2 = icmp sgt v0, v1 + return v2 +} +; run: %simd_icmp_sgt_i3([0 1 -1 0], [0 0 -1 1]) == [false true false false] +; run: %simd_icmp_sgt_i3([-5 1 0 0], [-1 -1 0 0]) == [false true false false] + + +function %simd_icmp_sgt_i64(i64x2, i64x2) -> b64x2 { +block0(v0: i64x2, v1: i64x2): + v2 = icmp sgt v0, v1 + return v2 +} +; run: %simd_icmp_sgt_i6([0 1], [0 0 ]) == [false true] +; run: %simd_icmp_sgt_i6([-1 0], [-1 1]) == [false false] +; run: %simd_icmp_sgt_i6([-5 1], [-1 -1]) == [false true] +; run: %simd_icmp_sgt_i6([0 0], [0 0]) == [false false] diff --git a/cranelift/filetests/filetests/runtests/simd-icmp-sle.clif b/cranelift/filetests/filetests/runtests/simd-icmp-sle.clif new file mode 100644 index 0000000000..07e0e3ea4f --- /dev/null +++ b/cranelift/filetests/filetests/runtests/simd-icmp-sle.clif @@ -0,0 +1,35 @@ +test interpret + +function %simd_icmp_sle_i8(i8x16, i8x16) -> b8x16 { +block0(v0: i8x16, v1: i8x16): + v2 = icmp sle v0, v1 + return v2 +} +; run: %simd_icmp_sle_i8([0 1 -1 0 -5 1 0 0 0 0 0 0 0 0 0 0], [0 0 -1 1 -1 -1 0 0 0 0 0 0 0 0 0 0]) == [true false true true true false true true true true true true true true true true] + +function %simd_icmp_sle_i16(i16x8, i16x8) -> b16x8 { +block0(v0: i16x8, v1: i16x8): + v2 = icmp sle v0, v1 + return v2 +} +; run: %simd_icmp_sle_i1([0 1 -1 0 -5 1 0 0], [0 0 -1 1 -1 -1 0 0]) == [true false true true true false true true] + + +function %simd_icmp_sle_i32(i32x4, i32x4) -> b32x4 { +block0(v0: i32x4, v1: i32x4): + v2 = icmp sle v0, v1 + return v2 +} +; run: %simd_icmp_sle_i3([0 1 -1 0], [0 0 -1 1]) == [true false true true] +; run: %simd_icmp_sle_i3([-5 1 0 0], [-1 -1 0 0]) == [true false true true] + + +function %simd_icmp_sle_i64(i64x2, i64x2) -> b64x2 { +block0(v0: i64x2, v1: i64x2): + v2 = icmp sle v0, v1 + return v2 +} +; run: %simd_icmp_sle_i6([0 1], [0 0 ]) == [true false] +; run: %simd_icmp_sle_i6([-1 0], [-1 1]) == [true true] +; run: %simd_icmp_sle_i6([-5 1], [-1 -1]) == [true false] +; run: %simd_icmp_sle_i6([0 0], [0 0]) == [true true] diff --git a/cranelift/filetests/filetests/runtests/simd-icmp-slt.clif b/cranelift/filetests/filetests/runtests/simd-icmp-slt.clif new file mode 100644 index 0000000000..fb0efe4bcc --- /dev/null +++ b/cranelift/filetests/filetests/runtests/simd-icmp-slt.clif @@ -0,0 +1,33 @@ +test interpret + +function %simd_icmp_slt_i8(i8x16, i8x16) -> b8x16 { +block0(v0: i8x16, v1: i8x16): + v2 = icmp slt v0, v1 + return v2 +} +; run: %simd_icmp_slt_i8([0 1 -1 0 -5 1 0 0 0 0 0 0 0 0 0 0], [0 0 -1 1 -1 1 0 0 0 0 0 0 0 0 0 0]) == [false false false true true false false false false false false false false false false false] + +function %simd_icmp_slt_i16(i16x8, i16x8) -> b16x8 { +block0(v0: i16x8, v1: i16x8): + v2 = icmp slt v0, v1 + return v2 +} +; run: %simd_icmp_slt_i1([0 1 -1 0 -5 1 0 0], [0 0 -1 1 -1 1 0 0]) == [false false false true true false false false] + +function %simd_icmp_slt_i32(i32x4, i32x4) -> b32x4 { +block0(v0: i32x4, v1: i32x4): + v2 = icmp slt v0, v1 + return v2 +} +; run: %simd_icmp_slt_i3([0 1 -1 0], [0 0 -1 1]) == [false false false true] +; run: %simd_icmp_slt_i3([-5 1 0 0], [-1 1 0 0]) == [true false false false] + +function %simd_icmp_slt_i64(i64x2, i64x2) -> b64x2 { +block0(v0: i64x2, v1: i64x2): + v2 = icmp slt v0, v1 + return v2 +} +; run: %simd_icmp_slt_i6([0 1], [0 0]) == [false false] +; run: %simd_icmp_slt_i6([-1 0], [-1 1]) == [false true] +; run: %simd_icmp_slt_i6([-5 1], [-1 1]) == [true false] +; run: %simd_icmp_slt_i6([0 0], [0 0]) == [false false] diff --git a/cranelift/filetests/filetests/runtests/simd-icmp-uge.clif b/cranelift/filetests/filetests/runtests/simd-icmp-uge.clif new file mode 100644 index 0000000000..4633b84347 --- /dev/null +++ b/cranelift/filetests/filetests/runtests/simd-icmp-uge.clif @@ -0,0 +1,33 @@ +test interpret + +function %simd_icmp_uge_i8(i8x16, i8x16) -> b8x16 { +block0(v0: i8x16, v1: i8x16): + v2 = icmp uge v0, v1 + return v2 +} +; run: %simd_icmp_uge_i8([0 1 -1 0 -5 1 0 0 0 0 0 0 0 0 0 0], [0 0 -1 1 -1 -1 0 0 0 0 0 0 0 0 0 0]) == [true true true false false false true true true true true true true true true true] + +function %simd_icmp_uge_i16(i16x8, i16x8) -> b16x8 { +block0(v0: i16x8, v1: i16x8): + v2 = icmp uge v0, v1 + return v2 +} +; run: %simd_icmp_uge_i1([0 1 -1 0 -5 1 0 0], [0 0 -1 1 -1 -1 0 0]) == [true true true false false false true true] + +function %simd_icmp_uge_i32(i32x4, i32x4) -> b32x4 { +block0(v0: i32x4, v1: i32x4): + v2 = icmp uge v0, v1 + return v2 +} +; run: %simd_icmp_uge_i3([0 1 -1 0], [0 0 -1 1]) == [true true true false] +; run: %simd_icmp_uge_i3([-5 1 0 0], [-1 -1 0 0]) == [false false true true] + +function %simd_icmp_uge_i64(i64x2, i64x2) -> b64x2 { +block0(v0: i64x2, v1: i64x2): + v2 = icmp uge v0, v1 + return v2 +} +; run: %simd_icmp_uge_i6([0 1], [0 0]) == [true true] +; run: %simd_icmp_uge_i6([-1 0], [-1 1]) == [true false] +; run: %simd_icmp_uge_i6([-5 1], [-1 -1]) == [false false] +; run: %simd_icmp_uge_i6([0 0], [0 0]) == [true true] diff --git a/cranelift/filetests/filetests/runtests/simd-icmp-ugt.clif b/cranelift/filetests/filetests/runtests/simd-icmp-ugt.clif new file mode 100644 index 0000000000..24f647780c --- /dev/null +++ b/cranelift/filetests/filetests/runtests/simd-icmp-ugt.clif @@ -0,0 +1,33 @@ +test interpret + +function %simd_icmp_ugt_i8(i8x16, i8x16) -> b8x16 { +block0(v0: i8x16, v1: i8x16): + v2 = icmp ugt v0, v1 + return v2 +} +; run: %simd_icmp_ugt_i8([0 1 -1 0 -5 1 0 0 0 0 0 0 0 0 0 0], [0 0 -1 1 -1 -1 0 0 0 0 0 0 0 0 0 0]) == [false true false false false false false false false false false false false false false false] + +function %simd_icmp_ugt_i16(i16x8, i16x8) -> b16x8 { +block0(v0: i16x8, v1: i16x8): + v2 = icmp ugt v0, v1 + return v2 +} +; run: %simd_icmp_ugt_i1([0 1 -1 0 -5 1 0 0], [0 0 -1 1 -1 -1 0 0]) == [false true false false false false false false] + +function %simd_icmp_ugt_i32(i32x4, i32x4) -> b32x4 { +block0(v0: i32x4, v1: i32x4): + v2 = icmp ugt v0, v1 + return v2 +} +; run: %simd_icmp_ugt_i3([0 1 -1 0], [0 0 -1 1]) == [false true false false] +; run: %simd_icmp_ugt_i3([-5 1 0 0], [-1 -1 0 0]) == [false false false false] + +function %simd_icmp_ugt_i64(i64x2, i64x2) -> b64x2 { +block0(v0: i64x2, v1: i64x2): + v2 = icmp ugt v0, v1 + return v2 +} +; run: %simd_icmp_ugt_i6([0 1], [0 0]) == [false true] +; run: %simd_icmp_ugt_i6([-1 0], [-1 1]) == [false false] +; run: %simd_icmp_ugt_i6([-5 1], [-1 -1]) == [false false] +; run: %simd_icmp_ugt_i6([0 0], [0 0]) == [false false] diff --git a/cranelift/filetests/filetests/runtests/simd-icmp-ule.clif b/cranelift/filetests/filetests/runtests/simd-icmp-ule.clif new file mode 100644 index 0000000000..7a74027a42 --- /dev/null +++ b/cranelift/filetests/filetests/runtests/simd-icmp-ule.clif @@ -0,0 +1,33 @@ +test interpret + +function %simd_icmp_ule_i8(i8x16, i8x16) -> b8x16 { +block0(v0: i8x16, v1: i8x16): + v2 = icmp ule v0, v1 + return v2 +} +; run: %simd_icmp_ule_i8([0 1 -1 0 -5 1 0 0 0 0 0 0 0 0 0 0], [0 0 -1 1 -1 -1 0 0 0 0 0 0 0 0 0 0]) == [true false true true true true true true true true true true true true true true] + +function %simd_icmp_ule_i16(i16x8, i16x8) -> b16x8 { +block0(v0: i16x8, v1: i16x8): + v2 = icmp ule v0, v1 + return v2 +} +; run: %simd_icmp_ule_i1([0 1 -1 0 -5 1 0 0], [0 0 -1 1 -1 -1 0 0]) == [true false true true true true true true] + +function %simd_icmp_ule_i32(i32x4, i32x4) -> b32x4 { +block0(v0: i32x4, v1: i32x4): + v2 = icmp ule v0, v1 + return v2 +} +; run: %simd_icmp_ule_i3([0 1 -1 0], [0 0 -1 1]) == [true false true true] +; run: %simd_icmp_ule_i3([-5 1 0 0], [-1 -1 0 0]) == [true true true true] + +function %simd_icmp_ule_i64(i64x2, i64x2) -> b64x2 { +block0(v0: i64x2, v1: i64x2): + v2 = icmp ule v0, v1 + return v2 +} +; run: %simd_icmp_ule_i6([0 1], [0 0]) == [true false] +; run: %simd_icmp_ule_i6([-1 0], [-1 1]) == [true true] +; run: %simd_icmp_ule_i6([-5 1], [-1 -1]) == [true true] +; run: %simd_icmp_ule_i6([0 0], [0 0]) == [true true] diff --git a/cranelift/filetests/filetests/runtests/simd-icmp-ult.clif b/cranelift/filetests/filetests/runtests/simd-icmp-ult.clif new file mode 100644 index 0000000000..ab6c4cab1d --- /dev/null +++ b/cranelift/filetests/filetests/runtests/simd-icmp-ult.clif @@ -0,0 +1,33 @@ +test interpret + +function %simd_icmp_ult_i8(i8x16, i8x16) -> b8x16 { +block0(v0: i8x16, v1: i8x16): + v2 = icmp ult v0, v1 + return v2 +} +; run: %simd_icmp_ult_i8([0 1 -1 0 -5 1 0 0 0 0 0 0 0 0 0 0], [0 0 -1 1 -1 -1 0 0 0 0 0 0 0 0 0 0]) == [false false false true true true false false false false false false false false false false] + +function %simd_icmp_ult_i16(i16x8, i16x8) -> b16x8 { +block0(v0: i16x8, v1: i16x8): + v2 = icmp ult v0, v1 + return v2 +} +; run: %simd_icmp_ult_i1([0 1 -1 0 -5 1 0 0], [0 0 -1 1 -1 -1 0 0]) == [false false false true true true false false] + +function %simd_icmp_ult_i32(i32x4, i32x4) -> b32x4 { +block0(v0: i32x4, v1: i32x4): + v2 = icmp ult v0, v1 + return v2 +} +; run: %simd_icmp_ult_i3([0 1 -1 0], [0 0 -1 1]) == [false false false true] +; run: %simd_icmp_ult_i3([-5 1 0 0], [-1 -1 0 0]) == [true true false false] + +function %simd_icmp_ult_i64(i64x2, i64x2) -> b64x2 { +block0(v0: i64x2, v1: i64x2): + v2 = icmp ult v0, v1 + return v2 +} +; run: %simd_icmp_ult_i6([0 1], [0 0]) == [false false] +; run: %simd_icmp_ult_i6([-1 0], [-1 1]) == [false true] +; run: %simd_icmp_ult_i6([-5 1], [-1 -1]) == [true true] +; run: %simd_icmp_ult_i6([0 0], [0 0]) == [false false] diff --git a/cranelift/interpreter/src/step.rs b/cranelift/interpreter/src/step.rs index eb519d2e08..187819aa69 100644 --- a/cranelift/interpreter/src/step.rs +++ b/cranelift/interpreter/src/step.rs @@ -222,7 +222,9 @@ where .convert(ValueConversionKind::ToBoolean)? .into_bool()?, )?, - Opcode::BrIcmp => branch_when(icmp(inst.cond_code().unwrap(), &arg(0)?, &arg(1)?)?)?, + Opcode::BrIcmp => { + branch_when(icmp(ctrl_ty, inst.cond_code().unwrap(), &arg(0)?, &arg(1)?)?.into_bool()?)? + } Opcode::Brif => branch_when(state.has_iflag(inst.cond_code().unwrap()))?, Opcode::Brff => branch_when(state.has_fflag(inst.fp_cond_code().unwrap()))?, Opcode::BrTable => { @@ -451,13 +453,17 @@ where Opcode::Regspill => unimplemented!("Regspill"), Opcode::Regfill => unimplemented!("Regfill"), Opcode::Safepoint => unimplemented!("Safepoint"), - Opcode::Icmp => assign(Value::bool( - icmp(inst.cond_code().unwrap(), &arg(0)?, &arg(1)?)?, - ctrl_ty.as_bool(), + Opcode::Icmp => assign(icmp( + ctrl_ty, + inst.cond_code().unwrap(), + &arg(0)?, + &arg(1)?, )?), - Opcode::IcmpImm => assign(Value::bool( - icmp(inst.cond_code().unwrap(), &arg(0)?, &imm_as_ctrl_ty()?)?, - ctrl_ty.as_bool(), + Opcode::IcmpImm => assign(icmp( + ctrl_ty, + inst.cond_code().unwrap(), + &arg(0)?, + &imm_as_ctrl_ty()?, )?), Opcode::Ifcmp | Opcode::IfcmpImm => { let arg0 = arg(0)?; @@ -479,7 +485,7 @@ where IntCC::UnsignedGreaterThan, IntCC::UnsignedLessThanOrEqual, ] { - if icmp(*f, &arg0, &arg1)? { + if icmp(ctrl_ty, *f, &arg0, &arg1)?.into_bool()? { state.set_iflag(*f); } } @@ -977,35 +983,57 @@ pub enum CraneliftTrap { } /// Compare two values using the given integer condition `code`. -fn icmp(code: IntCC, left: &V, right: &V) -> ValueResult +fn icmp(_ty: types::Type, code: IntCC, left: &V, right: &V) -> ValueResult where V: Value, { - Ok(match code { - IntCC::Equal => Value::eq(left, right)?, - IntCC::NotEqual => !Value::eq(left, right)?, - IntCC::SignedGreaterThan => Value::gt(left, right)?, - IntCC::SignedGreaterThanOrEqual => Value::ge(left, right)?, - IntCC::SignedLessThan => Value::lt(left, right)?, - IntCC::SignedLessThanOrEqual => Value::le(left, right)?, - IntCC::UnsignedGreaterThan => Value::gt( - &left.clone().convert(ValueConversionKind::ToUnsigned)?, - &right.clone().convert(ValueConversionKind::ToUnsigned)?, - )?, - IntCC::UnsignedGreaterThanOrEqual => Value::ge( - &left.clone().convert(ValueConversionKind::ToUnsigned)?, - &right.clone().convert(ValueConversionKind::ToUnsigned)?, - )?, - IntCC::UnsignedLessThan => Value::lt( - &left.clone().convert(ValueConversionKind::ToUnsigned)?, - &right.clone().convert(ValueConversionKind::ToUnsigned)?, - )?, - IntCC::UnsignedLessThanOrEqual => Value::le( - &left.clone().convert(ValueConversionKind::ToUnsigned)?, - &right.clone().convert(ValueConversionKind::ToUnsigned)?, - )?, - IntCC::Overflow => Value::overflow(left, right)?, - IntCC::NotOverflow => !Value::overflow(left, right)?, + let cmp = |bool_ty: types::Type, code: IntCC, left: &V, right: &V| -> ValueResult { + Ok(Value::bool( + match code { + IntCC::Equal => Value::eq(left, right)?, + IntCC::NotEqual => !Value::eq(left, right)?, + IntCC::SignedGreaterThan => Value::gt(left, right)?, + IntCC::SignedGreaterThanOrEqual => Value::ge(left, right)?, + IntCC::SignedLessThan => Value::lt(left, right)?, + IntCC::SignedLessThanOrEqual => Value::le(left, right)?, + IntCC::UnsignedGreaterThan => Value::gt( + &left.clone().convert(ValueConversionKind::ToUnsigned)?, + &right.clone().convert(ValueConversionKind::ToUnsigned)?, + )?, + IntCC::UnsignedGreaterThanOrEqual => Value::ge( + &left.clone().convert(ValueConversionKind::ToUnsigned)?, + &right.clone().convert(ValueConversionKind::ToUnsigned)?, + )?, + IntCC::UnsignedLessThan => Value::lt( + &left.clone().convert(ValueConversionKind::ToUnsigned)?, + &right.clone().convert(ValueConversionKind::ToUnsigned)?, + )?, + IntCC::UnsignedLessThanOrEqual => Value::le( + &left.clone().convert(ValueConversionKind::ToUnsigned)?, + &right.clone().convert(ValueConversionKind::ToUnsigned)?, + )?, + IntCC::Overflow => Value::overflow(left, right)?, + IntCC::NotOverflow => !Value::overflow(left, right)?, + }, + bool_ty, + )?) + }; + + let dst_ty = _ty.as_bool(); + Ok(if _ty.is_vector() { + let lane_type = _ty.lane_type(); + let left = extractlanes(left, lane_type)?; + let right = extractlanes(right, lane_type)?; + + let res = left + .into_iter() + .zip(right.into_iter()) + .map(|(l, r)| cmp(dst_ty.lane_type(), code, &l, &r)) + .collect::>>()?; + + vectorizelanes(&res, dst_ty)? + } else { + cmp(dst_ty, code, left, right)? }) } @@ -1081,18 +1109,23 @@ fn vectorizelanes(x: &[V], vector_type: types::Type) -> ValueResult where V: Value, { - let iterations = match vector_type.lane_type() { - types::I8 => 1, - types::I16 => 2, - types::I32 => 4, - types::I64 => 8, + let lane_type = vector_type.lane_type(); + let iterations = match lane_type { + types::I8 | types::B1 | types::B8 => 1, + types::I16 | types::B16 => 2, + types::I32 | types::B32 => 4, + types::I64 | types::B64 => 8, _ => unimplemented!("Only 128-bit vectors are currently supported."), }; let mut result: [u8; 16] = [0; 16]; for (i, val) in x.iter().enumerate() { - let val = val.clone().into_int()?; + let lane_val: i128 = val + .clone() + .convert(ValueConversionKind::Exact(lane_type.as_int()))? + .into_int()?; + for j in 0..iterations { - result[(i * iterations) + j] = (val >> (8 * j)) as u8; + result[(i * iterations) + j] = (lane_val >> (8 * j)) as u8; } } Value::vector(result, vector_type) diff --git a/cranelift/interpreter/src/value.rs b/cranelift/interpreter/src/value.rs index 9c25bfcb7e..83756e7ddc 100644 --- a/cranelift/interpreter/src/value.rs +++ b/cranelift/interpreter/src/value.rs @@ -252,6 +252,16 @@ impl Value for DataValue { (DataValue::I64(n), types::I64) => DataValue::I64(n), (DataValue::I64(n), types::I128) => DataValue::I128(n as i128), (DataValue::B(b), t) if t.is_bool() => DataValue::B(b), + (DataValue::B(b), t) if t.is_int() => { + let val = if b { + // Bools are represented in memory as all 1's + (1i128 << t.bits()) - 1 + } else { + 0 + }; + DataValue::int(val, t)? + } + (dv, t) if t.is_int() && dv.ty() == t => dv, (dv, _) => unimplemented!("conversion: {} -> {:?}", dv.ty(), kind), }, ValueConversionKind::Truncate(ty) => {