Vector bitcast support (AArch64 & Interpreter) (#4820)
* Vector bitcast support (AArch64 & Interpreter) Implemented support for `bitcast` on vector values for AArch64 and the interpreter. Also corrected the verifier to ensure that the size, in bits, of the input and output types match for a `bitcast`, per the docs. Copyright (c) 2022 Arm Limited * `I128` same-type bitcast support Copyright (c) 2022 Arm Limited * Directly return input for 64-bit GPR<=>GPR bitcast Copyright (c) 2022 Arm Limited
This commit is contained in:
@@ -3280,6 +3280,9 @@ pub(crate) fn define(
|
|||||||
The input and output types must be storable to memory and of the same
|
The input and output types must be storable to memory and of the same
|
||||||
size. A bitcast is equivalent to storing one type and loading the other
|
size. A bitcast is equivalent to storing one type and loading the other
|
||||||
type from the same address.
|
type from the same address.
|
||||||
|
|
||||||
|
For vector types, the lane types must also be the same size (see
|
||||||
|
`raw_bitcast` for changing the lane size).
|
||||||
"#,
|
"#,
|
||||||
&formats.unary,
|
&formats.unary,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1738,6 +1738,13 @@
|
|||||||
(decl writable_zero_reg () WritableReg)
|
(decl writable_zero_reg () WritableReg)
|
||||||
(extern constructor writable_zero_reg writable_zero_reg)
|
(extern constructor writable_zero_reg writable_zero_reg)
|
||||||
|
|
||||||
|
;; Helper for emitting `MInst.Mov` instructions.
|
||||||
|
(decl mov (Reg Type) Reg)
|
||||||
|
(rule (mov src ty)
|
||||||
|
(let ((dst WritableReg (temp_writable_reg $I64))
|
||||||
|
(_ Unit (emit (MInst.Mov (operand_size ty) dst src))))
|
||||||
|
dst))
|
||||||
|
|
||||||
;; Helper for emitting `MInst.MovZ` instructions.
|
;; Helper for emitting `MInst.MovZ` instructions.
|
||||||
(decl movz (MoveWideConst OperandSize) Reg)
|
(decl movz (MoveWideConst OperandSize) Reg)
|
||||||
(rule (movz imm size)
|
(rule (movz imm size)
|
||||||
@@ -2093,6 +2100,17 @@
|
|||||||
(_ Unit (emit (MInst.FpuRound op dst rn))))
|
(_ Unit (emit (MInst.FpuRound op dst rn))))
|
||||||
dst))
|
dst))
|
||||||
|
|
||||||
|
;; Helper for emitting `MInst.FpuMove64` and `MInst.FpuMove128` instructions.
|
||||||
|
(decl fpu_move (Type Reg) Reg)
|
||||||
|
(rule (fpu_move _ src)
|
||||||
|
(let ((dst WritableReg (temp_writable_reg $I8X16))
|
||||||
|
(_ Unit (emit (MInst.FpuMove128 dst src))))
|
||||||
|
dst))
|
||||||
|
(rule (fpu_move (fits_in_64 _) src)
|
||||||
|
(let ((dst WritableReg (temp_writable_reg $F64))
|
||||||
|
(_ Unit (emit (MInst.FpuMove64 dst src))))
|
||||||
|
dst))
|
||||||
|
|
||||||
;; Helper for emitting `MInst.MovToFpu` instructions.
|
;; Helper for emitting `MInst.MovToFpu` instructions.
|
||||||
(decl mov_to_fpu (Reg ScalarSize) Reg)
|
(decl mov_to_fpu (Reg ScalarSize) Reg)
|
||||||
(rule (mov_to_fpu x size)
|
(rule (mov_to_fpu x size)
|
||||||
|
|||||||
@@ -2209,17 +2209,26 @@
|
|||||||
|
|
||||||
;;; Rules for `bitcast` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;; Rules for `bitcast` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
(rule (lower (has_type $I32 (bitcast src @ (value_type $F32))))
|
; SIMD&FP <=> SIMD&FP
|
||||||
(mov_from_vec src 0 (ScalarSize.Size32)))
|
(rule (lower (has_type (ty_float_or_vec out_ty) (bitcast x @ (value_type (ty_float_or_vec _)))))
|
||||||
|
(fpu_move out_ty x))
|
||||||
|
|
||||||
(rule (lower (has_type $F32 (bitcast src @ (value_type $I32))))
|
; GPR => SIMD&FP
|
||||||
(mov_to_fpu src (ScalarSize.Size32)))
|
(rule (lower (has_type (ty_float_or_vec _) (bitcast x @ (value_type in_ty))))
|
||||||
|
(if (ty_int_bool_ref_scalar_64 in_ty))
|
||||||
|
(mov_to_fpu x (scalar_size in_ty)))
|
||||||
|
|
||||||
(rule (lower (has_type $I64 (bitcast src @ (value_type $F64))))
|
; SIMD&FP => GPR
|
||||||
(mov_from_vec src 0 (ScalarSize.Size64)))
|
(rule (lower (has_type out_ty (bitcast x @ (value_type (fits_in_64 (ty_float_or_vec _))))))
|
||||||
|
(if (ty_int_bool_ref_scalar_64 out_ty))
|
||||||
|
(mov_from_vec x 0 (scalar_size out_ty)))
|
||||||
|
|
||||||
(rule (lower (has_type $F64 (bitcast src @ (value_type $I64))))
|
; GPR <=> GPR
|
||||||
(mov_to_fpu src (ScalarSize.Size64)))
|
(rule (lower (has_type out_ty (bitcast x @ (value_type in_ty))))
|
||||||
|
(if (ty_int_bool_ref_scalar_64 out_ty))
|
||||||
|
(if (ty_int_bool_ref_scalar_64 in_ty))
|
||||||
|
x)
|
||||||
|
(rule (lower (has_type $I128 (bitcast x @ (value_type $I128)))) x)
|
||||||
|
|
||||||
;;; Rules for `raw_bitcast` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;; Rules for `raw_bitcast` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
|||||||
@@ -268,12 +268,7 @@ pub(crate) fn lower_insn_to_regs(
|
|||||||
|
|
||||||
Opcode::IsNull | Opcode::IsInvalid => implemented_in_isle(ctx),
|
Opcode::IsNull | Opcode::IsInvalid => implemented_in_isle(ctx),
|
||||||
|
|
||||||
Opcode::Copy => {
|
Opcode::Copy => implemented_in_isle(ctx),
|
||||||
let rd = get_output_reg(ctx, outputs[0]).only_reg().unwrap();
|
|
||||||
let rn = put_input_in_reg(ctx, inputs[0], NarrowValueMode::None);
|
|
||||||
let ty = ctx.input_ty(insn, 0);
|
|
||||||
ctx.emit(Inst::gen_move(rd, rn, ty));
|
|
||||||
}
|
|
||||||
|
|
||||||
Opcode::Breduce | Opcode::Ireduce => implemented_in_isle(ctx),
|
Opcode::Breduce | Opcode::Ireduce => implemented_in_isle(ctx),
|
||||||
|
|
||||||
|
|||||||
@@ -1096,15 +1096,26 @@ impl<'a> Verifier<'a> {
|
|||||||
let typ = self.func.dfg.ctrl_typevar(inst);
|
let typ = self.func.dfg.ctrl_typevar(inst);
|
||||||
let value_type = self.func.dfg.value_type(arg);
|
let value_type = self.func.dfg.value_type(arg);
|
||||||
|
|
||||||
if typ.lane_bits() < value_type.lane_bits() {
|
if typ.lane_bits() != value_type.lane_bits() {
|
||||||
errors.fatal((
|
errors.fatal((
|
||||||
inst,
|
inst,
|
||||||
format!(
|
format!(
|
||||||
"The bitcast argument {} doesn't fit in a type of {} bits",
|
"The bitcast argument {} has a lane type of {} bits, which doesn't match an expected type of {} bits",
|
||||||
arg,
|
arg,
|
||||||
|
value_type.lane_bits(),
|
||||||
typ.lane_bits()
|
typ.lane_bits()
|
||||||
),
|
),
|
||||||
))
|
))
|
||||||
|
} else if typ.bits() != value_type.bits() {
|
||||||
|
errors.fatal((
|
||||||
|
inst,
|
||||||
|
format!(
|
||||||
|
"The bitcast argument {} has a type of {} bits, which doesn't match an expected type of {} bits",
|
||||||
|
arg,
|
||||||
|
value_type.bits(),
|
||||||
|
typ.bits()
|
||||||
|
),
|
||||||
|
))
|
||||||
} else {
|
} else {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
26
cranelift/filetests/filetests/runtests/bitcast-ref64.clif
Normal file
26
cranelift/filetests/filetests/runtests/bitcast-ref64.clif
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
test run
|
||||||
|
target aarch64
|
||||||
|
; the interpreter, x86_64, and s390x do not support bitcasting to/from
|
||||||
|
; references
|
||||||
|
|
||||||
|
function %bitcast_ir64(i64) -> b1 {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = bitcast.r64 v0
|
||||||
|
v2 = is_null v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
; run: %bitcast_ir64(0) == true
|
||||||
|
; run: %bitcast_ir64(18446744073709551615) == false
|
||||||
|
; run: %bitcast_ir64(-1) == false
|
||||||
|
; run: %bitcast_ir64(127) == false
|
||||||
|
|
||||||
|
function %bitcast_ri64(i64) -> i64 {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = bitcast.r64 v0
|
||||||
|
v2 = bitcast.i64 v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
; run: %bitcast_ri64(0) == 0
|
||||||
|
; run: %bitcast_ri64(18446744073709551615) == 18446744073709551615
|
||||||
|
; run: %bitcast_ri64(-1) == -1
|
||||||
|
; run: %bitcast_ri64(127) == 127
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
test interpret
|
||||||
|
test run
|
||||||
|
target aarch64
|
||||||
|
; x86_64 and s390x do not support bitcasting to the same type as the input.
|
||||||
|
|
||||||
|
function %bitcast_i8(i8) -> i8 {
|
||||||
|
block0(v0: i8):
|
||||||
|
v1 = bitcast.i8 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
; run: %bitcast_i8(0) == 0
|
||||||
|
; run: %bitcast_i8(42) == 42
|
||||||
|
; run: %bitcast_i8(255) == 255
|
||||||
|
|
||||||
|
function %bitcast_i16(i16) -> i16 {
|
||||||
|
block0(v0: i16):
|
||||||
|
v1 = bitcast.i16 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
; run: %bitcast_i16(0) == 0
|
||||||
|
; run: %bitcast_i16(42) == 42
|
||||||
|
; run: %bitcast_i16(65535) == 65535
|
||||||
|
|
||||||
|
function %bitcast_i32(i32) -> i32 {
|
||||||
|
block0(v0: i32):
|
||||||
|
v1 = bitcast.i32 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
; run: %bitcast_i32(0) == 0
|
||||||
|
; run: %bitcast_i32(42) == 42
|
||||||
|
; run: %bitcast_i32(4294967295) == 4294967295
|
||||||
|
|
||||||
|
function %bitcast_i64(i64) -> i64 {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = bitcast.i64 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
; run: %bitcast_i64(0) == 0
|
||||||
|
; run: %bitcast_i64(42) == 42
|
||||||
|
; run: %bitcast_i64(18446744073709551615) == 18446744073709551615
|
||||||
|
|
||||||
|
function %bitcast_i128(i128) -> i128 {
|
||||||
|
block0(v0: i128):
|
||||||
|
v1 = bitcast.i128 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
; run: %bitcast_i128(0) == 0
|
||||||
|
; run: %bitcast_i128(42) == 42
|
||||||
|
; run: %bitcast_i128(200000000000000000000) == 200000000000000000000
|
||||||
|
|
||||||
|
function %bitcast_f32(f32) -> f32 {
|
||||||
|
block0(v0: f32):
|
||||||
|
v1 = bitcast.f32 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
; run: %bitcast_f32(0x0.0) == 0x0.0
|
||||||
|
; run: %bitcast_f32(0x1.0) == 0x1.0
|
||||||
|
; run: %bitcast_f32(-0x1.0) == -0x1.0
|
||||||
|
; run: %bitcast_f32(NaN) == NaN
|
||||||
|
|
||||||
|
function %bitcast_f64(f64) -> f64 {
|
||||||
|
block0(v0: f64):
|
||||||
|
v1 = bitcast.f64 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
; run: %bitcast_f64(0x0.0) == 0x0.0
|
||||||
|
; run: %bitcast_f64(0x1.0) == 0x1.0
|
||||||
|
; run: %bitcast_f64(-0x1.0) == -0x1.0
|
||||||
|
; run: %bitcast_f64(NaN) == NaN
|
||||||
45
cranelift/filetests/filetests/runtests/bitcast.clif
Normal file
45
cranelift/filetests/filetests/runtests/bitcast.clif
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
test interpret
|
||||||
|
test run
|
||||||
|
target aarch64
|
||||||
|
target x86_64
|
||||||
|
target s390x
|
||||||
|
|
||||||
|
function %bitcast_if32(i32) -> f32 {
|
||||||
|
block0(v0: i32):
|
||||||
|
v1 = bitcast.f32 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
; run: %bitcast_if32(0) == 0x0.0
|
||||||
|
; run: %bitcast_if32(4294967295) == -NaN:0x3fffff
|
||||||
|
; run: %bitcast_if32(-1) == -NaN:0x3fffff
|
||||||
|
; run: %bitcast_if32(127) == 0x0.0000fep-126
|
||||||
|
|
||||||
|
function %bitcast_fi32(f32) -> i32 {
|
||||||
|
block0(v0: f32):
|
||||||
|
v1 = bitcast.i32 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
; run: %bitcast_fi32(0x0.0) == 0
|
||||||
|
; run: %bitcast_fi32(-NaN:0x3fffff) == 4294967295
|
||||||
|
; run: %bitcast_fi32(-NaN:0x3fffff) == -1
|
||||||
|
; run: %bitcast_fi32(0x0.0000fep-126) == 127
|
||||||
|
|
||||||
|
function %bitcast_if64(i64) -> f64 {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = bitcast.f64 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
; run: %bitcast_if64(0) == 0x0.0
|
||||||
|
; run: %bitcast_if64(18446744073709551615) == -NaN:0x7ffffffffffff
|
||||||
|
; run: %bitcast_if64(-1) == -NaN:0x7ffffffffffff
|
||||||
|
; run: %bitcast_if64(127) == 0x0.000000000007fp-1022
|
||||||
|
|
||||||
|
function %bitcast_fi64(f64) -> i64 {
|
||||||
|
block0(v0: f64):
|
||||||
|
v1 = bitcast.i64 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
; run: %bitcast_fi64(0x0.0) == 0
|
||||||
|
; run: %bitcast_fi64(-NaN:0x7ffffffffffff) == 18446744073709551615
|
||||||
|
; run: %bitcast_fi64(-NaN:0x7ffffffffffff) == -1
|
||||||
|
; run: %bitcast_fi64(0x0.000000000007fp-1022) == 127
|
||||||
121
cranelift/filetests/filetests/runtests/copy.clif
Normal file
121
cranelift/filetests/filetests/runtests/copy.clif
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
test interpret
|
||||||
|
test run
|
||||||
|
target aarch64
|
||||||
|
target s390x
|
||||||
|
; x86_64 regards this as an unused opcode.
|
||||||
|
|
||||||
|
function %copy_i8(i8) -> i8 {
|
||||||
|
block0(v0: i8):
|
||||||
|
v1 = copy v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
; run: %copy_i8(0) == 0
|
||||||
|
; run: %copy_i8(255) == 255
|
||||||
|
; run: %copy_i8(-1) == -1
|
||||||
|
; run: %copy_i8(127) == 127
|
||||||
|
|
||||||
|
function %copy_i16(i16) -> i16 {
|
||||||
|
block0(v0: i16):
|
||||||
|
v1 = copy v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
; run: %copy_i16(0) == 0
|
||||||
|
; run: %copy_i16(65535) == 65535
|
||||||
|
; run: %copy_i16(-1) == -1
|
||||||
|
; run: %copy_i16(127) == 127
|
||||||
|
|
||||||
|
function %copy_i32(i32) -> i32 {
|
||||||
|
block0(v0: i32):
|
||||||
|
v1 = copy v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
; run: %copy_i32(0) == 0
|
||||||
|
; run: %copy_i32(4294967295) == 4294967295
|
||||||
|
; run: %copy_i32(-1) == -1
|
||||||
|
; run: %copy_i32(127) == 127
|
||||||
|
|
||||||
|
function %copy_i64(i64) -> i64 {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = copy v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
; run: %copy_i64(0) == 0
|
||||||
|
; run: %copy_i64(18446744073709551615) == 18446744073709551615
|
||||||
|
; run: %copy_i64(-1) == -1
|
||||||
|
; run: %copy_i64(127) == 127
|
||||||
|
|
||||||
|
function %copy_b1(b1) -> b1 {
|
||||||
|
block0(v0: b1):
|
||||||
|
v1 = copy v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
; run: %copy_b1(false) == false
|
||||||
|
; run: %copy_b1(true) == true
|
||||||
|
|
||||||
|
function %copy_b8(b8) -> b8 {
|
||||||
|
block0(v0: b8):
|
||||||
|
v1 = copy v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
; run: %copy_b8(false) == false
|
||||||
|
; run: %copy_b8(true) == true
|
||||||
|
|
||||||
|
function %copy_b16(b16) -> b16 {
|
||||||
|
block0(v0: b16):
|
||||||
|
v1 = copy v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
; run: %copy_b16(false) == false
|
||||||
|
; run: %copy_b16(true) == true
|
||||||
|
|
||||||
|
function %copy_b32(b32) -> b32 {
|
||||||
|
block0(v0: b32):
|
||||||
|
v1 = copy v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
; run: %copy_b32(false) == false
|
||||||
|
; run: %copy_b32(true) == true
|
||||||
|
|
||||||
|
function %copy_b64(b64) -> b64 {
|
||||||
|
block0(v0: b64):
|
||||||
|
v1 = copy v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
; run: %copy_b64(false) == false
|
||||||
|
; run: %copy_b64(true) == true
|
||||||
|
|
||||||
|
function %copy_f32(f32) -> f32 {
|
||||||
|
block0(v0: f32):
|
||||||
|
v1 = copy v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
; run: %copy_f32(0x1.0) == 0x1.0
|
||||||
|
; run: %copy_f32(0x1.0p10) == 0x1.0p10
|
||||||
|
|
||||||
|
; run: %copy_f32(0x0.0) == 0x0.0
|
||||||
|
; run: %copy_f32(-0x0.0) == -0x0.0
|
||||||
|
; run: %copy_f32(+Inf) == +Inf
|
||||||
|
; run: %copy_f32(-Inf) == -Inf
|
||||||
|
; run: %copy_f32(0x1.000002p-23) == 0x1.000002p-23
|
||||||
|
; run: %copy_f32(0x1.fffffep127) == 0x1.fffffep127
|
||||||
|
; run: %copy_f32(0x1.000000p-126) == 0x1.000000p-126
|
||||||
|
; run: %copy_f32(0x0.800002p-126) == 0x0.800002p-126
|
||||||
|
; run: %copy_f32(-0x0.800000p-126) == -0x0.800000p-126
|
||||||
|
|
||||||
|
function %copy_f64(f64) -> f64 {
|
||||||
|
block0(v0: f64):
|
||||||
|
v1 = copy v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
; run: %copy_f64(0x2.0) == 0x2.0
|
||||||
|
; run: %copy_f64(0x1.0p11) == 0x1.0p11
|
||||||
|
|
||||||
|
; run: %copy_f64(0x0.0) == 0x0.0
|
||||||
|
; run: %copy_f64(-0x0.0) == -0x0.0
|
||||||
|
; run: %copy_f64(+Inf) == +Inf
|
||||||
|
; run: %copy_f64(-Inf) == -Inf
|
||||||
|
; run: %copy_f64(0x1.0000000000002p-52) == 0x1.0000000000002p-52
|
||||||
|
; run: %copy_f64(0x1.fffffffffffffp1023) == 0x1.fffffffffffffp1023
|
||||||
|
; run: %copy_f64(0x1.0000000000000p-1022) == 0x1.0000000000000p-1022
|
||||||
|
; run: %copy_f64(0x0.8000000000002p-1022) == 0x0.8000000000002p-1022
|
||||||
|
; run: %copy_f64(-0x0.8000000000000p-1022) == -0x0.8000000000000p-1022
|
||||||
50
cranelift/filetests/filetests/runtests/simd-bitcast.clif
Normal file
50
cranelift/filetests/filetests/runtests/simd-bitcast.clif
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
test interpret
|
||||||
|
test run
|
||||||
|
target aarch64
|
||||||
|
; x86_64 and s390x do not support vector bitcasts.
|
||||||
|
|
||||||
|
function %bitcast_if32x2(i32x2) -> f32x2 {
|
||||||
|
block0(v0: i32x2):
|
||||||
|
v1 = bitcast.f32x2 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
; run: %bitcast_if32x2([0 4294967295]) == [0x0.0 -NaN:0x3fffff]
|
||||||
|
; run: %bitcast_if32x2([-1 127]) == [-NaN:0x3fffff 0x0.0000fep-126]
|
||||||
|
|
||||||
|
function %bitcast_fi32x2(f32x2) -> i32x2 {
|
||||||
|
block0(v0: f32x2):
|
||||||
|
v1 = bitcast.i32x2 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
; run: %bitcast_fi32x2([0x0.0 -NaN:0x3fffff]) == [0 4294967295]
|
||||||
|
; run: %bitcast_fi32x2([-NaN:0x3fffff 0x0.0000fep-126]) == [-1 127]
|
||||||
|
|
||||||
|
function %bitcast_if32x4(i32x4) -> f32x4 {
|
||||||
|
block0(v0: i32x4):
|
||||||
|
v1 = bitcast.f32x4 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
; run: %bitcast_if32x4([0 4294967295 -1 127]) == [0x0.0 -NaN:0x3fffff -NaN:0x3fffff 0x0.0000fep-126]
|
||||||
|
|
||||||
|
function %bitcast_fi32x4(f32x4) -> i32x4 {
|
||||||
|
block0(v0: f32x4):
|
||||||
|
v1 = bitcast.i32x4 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
; run: %bitcast_fi32x4([0x0.0 -NaN:0x3fffff -NaN:0x3fffff 0x0.0000fep-126]) == [0 4294967295 -1 127]
|
||||||
|
|
||||||
|
function %bitcast_if64x2(i64x2) -> f64x2 {
|
||||||
|
block0(v0: i64x2):
|
||||||
|
v1 = bitcast.f64x2 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
; run: %bitcast_if64x2([0 18446744073709551615]) == [0x0.0 -NaN:0x7ffffffffffff]
|
||||||
|
; run: %bitcast_if64x2([-1 127]) == [-NaN:0x7ffffffffffff 0x0.000000000007fp-1022]
|
||||||
|
|
||||||
|
function %bitcast_fi64x2(f64x2) -> i64x2 {
|
||||||
|
block0(v0: f64x2):
|
||||||
|
v1 = bitcast.i64x2 v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
; run: %bitcast_fi64x2([0x0.0 -NaN:0x7ffffffffffff]) == [0 18446744073709551615]
|
||||||
|
; run: %bitcast_fi64x2([-NaN:0x7ffffffffffff 0x0.000000000007fp-1022]) == [-1 127]
|
||||||
40
cranelift/filetests/filetests/runtests/simd-copy-64bit.clif
Normal file
40
cranelift/filetests/filetests/runtests/simd-copy-64bit.clif
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
test interpret
|
||||||
|
test run
|
||||||
|
target aarch64
|
||||||
|
; x86_64 regards this as an unused opcode.
|
||||||
|
; s390x does not support 64-bit vectors.
|
||||||
|
|
||||||
|
function %copy_i8x8(i8x8) -> i8x8 {
|
||||||
|
block0(v0: i8x8):
|
||||||
|
v1 = copy v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
; run: %copy_i8x8([0 0 255 255 -1 -1 127 128]) == [0 0 255 255 -1 -1 127 128]
|
||||||
|
|
||||||
|
function %copy_i16x4(i16x4) -> i16x4 {
|
||||||
|
block0(v0: i16x4):
|
||||||
|
v1 = copy v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
; run: %copy_i16x4([0 65535 -1 127]) == [0 65535 -1 127]
|
||||||
|
|
||||||
|
function %copy_i32x2(i32x2) -> i32x2 {
|
||||||
|
block0(v0: i32x2):
|
||||||
|
v1 = copy v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
; run: %copy_i32x2([0 4294967295]) == [0 4294967295]
|
||||||
|
; run: %copy_i32x2([-1 127]) == [-1 127]
|
||||||
|
|
||||||
|
function %copy_f32x2(f32x2) -> f32x2 {
|
||||||
|
block0(v0: f32x2):
|
||||||
|
v1 = copy v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
; run: %copy_f32x2([0x1.0 0x1.0p10]) == [0x1.0 0x1.0p10]
|
||||||
|
|
||||||
|
; run: %copy_f32x2([0x0.0 -0x0.0]) == [0x0.0 -0x0.0]
|
||||||
|
; run: %copy_f32x2([+Inf -Inf]) == [+Inf -Inf]
|
||||||
|
; run: %copy_f32x2([0x1.000002p-23 0x1.fffffep127]) == [0x1.000002p-23 0x1.fffffep127]
|
||||||
|
; run: %copy_f32x2([0x1.000000p-126 0x0.800002p-126]) == [0x1.000000p-126 0x0.800002p-126]
|
||||||
|
; run: %copy_f32x2([-0x0.800000p-126 -0x0.800000p-126]) == [-0x0.800000p-126 -0x0.800000p-126]
|
||||||
57
cranelift/filetests/filetests/runtests/simd-copy.clif
Normal file
57
cranelift/filetests/filetests/runtests/simd-copy.clif
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
test interpret
|
||||||
|
test run
|
||||||
|
target aarch64
|
||||||
|
target s390x
|
||||||
|
; x86_64 regards this as an unused opcode.
|
||||||
|
|
||||||
|
function %copy_i8x16(i8x16) -> i8x16 {
|
||||||
|
block0(v0: i8x16):
|
||||||
|
v1 = copy v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
; run: %copy_i8x16([0 0 255 255 -1 -1 127 128 0 0 255 255 -1 -1 127 128]) == [0 0 255 255 -1 -1 127 128 0 0 255 255 -1 -1 127 128]
|
||||||
|
|
||||||
|
function %copy_i16x8(i16x8) -> i16x8 {
|
||||||
|
block0(v0: i16x8):
|
||||||
|
v1 = copy v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
; run: %copy_i16x8([0 65535 -1 127 0 65535 -1 128]) == [0 65535 -1 127 0 65535 -1 128]
|
||||||
|
|
||||||
|
function %copy_i32x4(i32x4) -> i32x4 {
|
||||||
|
block0(v0: i32x4):
|
||||||
|
v1 = copy v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
; run: %copy_i32x4([0 4294967295 -1 127]) == [0 4294967295 -1 127]
|
||||||
|
|
||||||
|
function %copy_i64x2(i64x2) -> i64x2 {
|
||||||
|
block0(v0: i64x2):
|
||||||
|
v1 = copy v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
; run: %copy_i64x2([0 18446744073709551615]) == [0 18446744073709551615]
|
||||||
|
; run: %copy_i64x2([-1 127]) == [-1 127]
|
||||||
|
|
||||||
|
function %copy_f32x4(f32x4) -> f32x4 {
|
||||||
|
block0(v0: f32x4):
|
||||||
|
v1 = copy v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
; run: %copy_f32x4([0x1.0 0x1.0p10 0x0.0 -0x0.0]) == [0x1.0 0x1.0p10 0x0.0 -0x0.0]
|
||||||
|
|
||||||
|
; run: %copy_f32x4([+Inf -Inf 0x1.000002p-23 0x1.fffffep127]) == [+Inf -Inf 0x1.000002p-23 0x1.fffffep127]
|
||||||
|
; run: %copy_f32x4([0x1.000000p-126 0x0.800002p-126 -0x0.800000p-126 -0x0.800000p-126]) == [0x1.000000p-126 0x0.800002p-126 -0x0.800000p-126 -0x0.800000p-126]
|
||||||
|
|
||||||
|
function %copy_f64x2(f64x2) -> f64x2 {
|
||||||
|
block0(v0: f64x2):
|
||||||
|
v1 = copy v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
; run: %copy_f64x2([0x2.0 0x1.0p11]) == [0x2.0 0x1.0p11]
|
||||||
|
|
||||||
|
; run: %copy_f64x2([0x0.0 -0x0.0]) == [0x0.0 -0x0.0]
|
||||||
|
; run: %copy_f64x2([+Inf -Inf]) == [+Inf -Inf]
|
||||||
|
; run: %copy_f64x2([0x1.0000000000002p-52 0x1.fffffffffffffp1023]) == [0x1.0000000000002p-52 0x1.fffffffffffffp1023]
|
||||||
|
; run: %copy_f64x2([0x1.0000000000000p-1022 0x0.8000000000002p-1022]) == [0x1.0000000000000p-1022 0x0.8000000000002p-1022]
|
||||||
|
; run: %copy_f64x2([-0x0.8000000000000p-1022 -0x0.8000000000000p-1022]) == [-0x0.8000000000000p-1022 -0x0.8000000000000p-1022]
|
||||||
@@ -1,23 +1,23 @@
|
|||||||
test verifier
|
test verifier
|
||||||
|
|
||||||
; bitcast between two types of equal size if ok
|
; bitcast between two types of equal size is ok
|
||||||
function %valid_bitcast1(i32) -> f32 { ; Ok
|
function %valid_bitcast1(i32) -> f32 { ; Ok
|
||||||
block0(v0: i32):
|
block0(v0: i32):
|
||||||
v1 = bitcast.f32 v0
|
v1 = bitcast.f32 v0
|
||||||
return v1
|
return v1
|
||||||
}
|
}
|
||||||
|
|
||||||
; bitcast to a type larger than the operand is ok
|
; bitcast to a type larger than the operand is not ok
|
||||||
function %valid_bitcast2(i32) -> i64 { ; Ok
|
function %valid_bitcast2(i32) -> i64 {
|
||||||
block0(v0: i32):
|
block0(v0: i32):
|
||||||
v1 = bitcast.i64 v0
|
v1 = bitcast.i64 v0 ; error: The bitcast argument v0 has a lane type of 32 bits, which doesn't match an expected type of 64 bits
|
||||||
return v1
|
return v1
|
||||||
}
|
}
|
||||||
|
|
||||||
; bitcast to a smaller type is not ok
|
; bitcast to a smaller type is not ok
|
||||||
function %bad_bitcast(i64) -> i32 {
|
function %bad_bitcast(i64) -> i32 {
|
||||||
block0(v0: i64):
|
block0(v0: i64):
|
||||||
v1 = bitcast.i32 v0 ; error: The bitcast argument v0 doesn't fit in a type of 32 bits
|
v1 = bitcast.i32 v0 ; error: The bitcast argument v0 has a lane type of 64 bits, which doesn't match an expected type of 32 bits
|
||||||
return v1
|
return v1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -956,10 +956,18 @@ where
|
|||||||
| Opcode::RawBitcast
|
| Opcode::RawBitcast
|
||||||
| Opcode::ScalarToVector
|
| Opcode::ScalarToVector
|
||||||
| Opcode::Breduce
|
| Opcode::Breduce
|
||||||
| Opcode::Bextend => assign(Value::convert(
|
| Opcode::Bextend => {
|
||||||
arg(0)?,
|
let input_ty = inst_context.type_of(inst_context.args()[0]).unwrap();
|
||||||
ValueConversionKind::Exact(ctrl_ty),
|
let arg0 = extractlanes(&arg(0)?, input_ty)?;
|
||||||
)?),
|
|
||||||
|
assign(vectorizelanes(
|
||||||
|
&arg0
|
||||||
|
.into_iter()
|
||||||
|
.map(|x| V::convert(x, ValueConversionKind::Exact(ctrl_ty.lane_type())))
|
||||||
|
.collect::<ValueResult<SimdVec<V>>>()?,
|
||||||
|
ctrl_ty,
|
||||||
|
)?)
|
||||||
|
}
|
||||||
Opcode::Ireduce => assign(Value::convert(
|
Opcode::Ireduce => assign(Value::convert(
|
||||||
arg(0)?,
|
arg(0)?,
|
||||||
ValueConversionKind::Truncate(ctrl_ty),
|
ValueConversionKind::Truncate(ctrl_ty),
|
||||||
|
|||||||
@@ -326,7 +326,7 @@ impl Value for DataValue {
|
|||||||
};
|
};
|
||||||
DataValue::int(val, t)?
|
DataValue::int(val, t)?
|
||||||
}
|
}
|
||||||
(dv, t) if t.is_int() && dv.ty() == t => dv,
|
(dv, t) if (t.is_int() || t.is_float()) && dv.ty() == t => dv,
|
||||||
(dv, _) => unimplemented!("conversion: {} -> {:?}", dv.ty(), kind),
|
(dv, _) => unimplemented!("conversion: {} -> {:?}", dv.ty(), kind),
|
||||||
},
|
},
|
||||||
ValueConversionKind::Truncate(ty) => {
|
ValueConversionKind::Truncate(ty) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user