Browse Source

cranelift: Fix `bint` implementation on interpreter (#4299)

* cranelift: Fix `bint` implementation on interpreter

The interpreter was returning -1 instead of 1 for positive values.
This also extends the bint test suite to cover all types.

* cranelift: Restrict `bint` to scalar values only
pull/4317/head
Afonso Bordado 2 years ago
committed by GitHub
parent
commit
87007c5839
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 29
      cranelift/codegen/meta/src/shared/instructions.rs
  2. 314
      cranelift/filetests/filetests/runtests/bint.clif
  3. 77
      cranelift/filetests/filetests/runtests/i128-bint.clif
  4. 6
      cranelift/interpreter/src/step.rs

29
cranelift/codegen/meta/src/shared/instructions.rs

@ -718,6 +718,12 @@ pub(crate) fn define(
.build(), .build(),
); );
let ScalarBool = &TypeVar::new(
"ScalarBool",
"A scalar boolean type",
TypeSetBuilder::new().bools(Interval::All).build(),
);
let iB = &TypeVar::new( let iB = &TypeVar::new(
"iB", "iB",
"A scalar integer type", "A scalar integer type",
@ -3331,13 +3337,10 @@ pub(crate) fn define(
let IntTo = &TypeVar::new( let IntTo = &TypeVar::new(
"IntTo", "IntTo",
"An integer type with the same number of lanes", "A scalar integer type",
TypeSetBuilder::new() TypeSetBuilder::new().ints(Interval::All).build(),
.ints(Interval::All)
.simd_lanes(Interval::All)
.build(),
); );
let x = &Operand::new("x", Bool); let x = &Operand::new("x", ScalarBool);
let a = &Operand::new("a", IntTo); let a = &Operand::new("a", IntTo);
ig.push( ig.push(
@ -3346,8 +3349,7 @@ pub(crate) fn define(
r#" r#"
Convert `x` to an integer. Convert `x` to an integer.
True maps to 1 and false maps to 0. The result type must have the same True maps to 1 and false maps to 0.
number of vector lanes as the input.
"#, "#,
&formats.unary, &formats.unary,
) )
@ -3355,6 +3357,17 @@ pub(crate) fn define(
.operands_out(vec![a]), .operands_out(vec![a]),
); );
let IntTo = &TypeVar::new(
"IntTo",
"An integer type with the same number of lanes",
TypeSetBuilder::new()
.ints(Interval::All)
.simd_lanes(Interval::All)
.build(),
);
let x = &Operand::new("x", Bool);
let a = &Operand::new("a", IntTo);
ig.push( ig.push(
Inst::new( Inst::new(
"bmask", "bmask",

314
cranelift/filetests/filetests/runtests/bint.clif

@ -1,7 +1,91 @@
test interpret
test run test run
target aarch64 target aarch64
target x86_64 target x86_64
function %bint_b1_i8_true() -> i8 {
block0:
v0 = bconst.b1 true
v1 = bint.i8 v0
return v1
}
; run: %bint_b1_i8_true() == 1
function %bint_b1_i8_false() -> i8 {
block0:
v0 = bconst.b1 false
v1 = bint.i8 v0
return v1
}
; run: %bint_b1_i8_false() == 0
function %bint_b1_i16_true() -> i16 {
block0:
v0 = bconst.b1 true
v1 = bint.i16 v0
return v1
}
; run: %bint_b1_i16_true() == 1
function %bint_b1_i16_false() -> i16 {
block0:
v0 = bconst.b1 false
v1 = bint.i16 v0
return v1
}
; run: %bint_b1_i16_fals() == 0
function %bint_b1_i32_true() -> i32 {
block0:
v0 = bconst.b1 true
v1 = bint.i32 v0
return v1
}
; run: %bint_b1_i32_true() == 1
function %bint_b1_i32_false() -> i32 {
block0:
v0 = bconst.b1 false
v1 = bint.i32 v0
return v1
}
; run: %bint_b1_i32_fals() == 0
function %bint_b1_i64_true() -> i64 {
block0:
v0 = bconst.b1 true
v1 = bint.i64 v0
return v1
}
; run: %bint_b1_i64_true() == 1
function %bint_b1_i64_false() -> i64 {
block0:
v0 = bconst.b1 false
v1 = bint.i64 v0
return v1
}
; run: %bint_b1_i64_fals() == 0
function %bint_b8_i8_true() -> i8 {
block0:
v0 = bconst.b8 true
v1 = bint.i8 v0
return v1
}
; run: %bint_b8_i8_true() == 1
function %bint_b8_i8_false() -> i8 {
block0:
v0 = bconst.b8 false
v1 = bint.i8 v0
return v1
}
; run: %bint_b8_i8_false() == 0
function %bint_b8_i16_true() -> i16 { function %bint_b8_i16_true() -> i16 {
block0: block0:
v0 = bconst.b8 true v0 = bconst.b8 true
@ -10,6 +94,65 @@ block0:
} }
; run: %bint_b8_i16_true() == 1 ; run: %bint_b8_i16_true() == 1
function %bint_b8_i16_false() -> i16 {
block0:
v0 = bconst.b8 false
v1 = bint.i16 v0
return v1
}
; run: %bint_b8_i16_fals() == 0
function %bint_b8_i32_true() -> i32 {
block0:
v0 = bconst.b8 true
v1 = bint.i32 v0
return v1
}
; run: %bint_b8_i32_true() == 1
function %bint_b8_i32_false() -> i32 {
block0:
v0 = bconst.b8 false
v1 = bint.i32 v0
return v1
}
; run: %bint_b8_i32_fals() == 0
function %bint_b8_i64_true() -> i64 {
block0:
v0 = bconst.b8 true
v1 = bint.i64 v0
return v1
}
; run: %bint_b8_i64_true() == 1
function %bint_b8_i64_false() -> i64 {
block0:
v0 = bconst.b8 false
v1 = bint.i64 v0
return v1
}
; run: %bint_b8_i64_fals() == 0
function %bint_b16_i8_true() -> i8 {
block0:
v0 = bconst.b16 true
v1 = bint.i8 v0
return v1
}
; run: %bint_b16_i8_true() == 1
function %bint_b16_i8_false() -> i8 {
block0:
v0 = bconst.b16 false
v1 = bint.i8 v0
return v1
}
; run: %bint_b16_i8_fals() == 0
function %bint_b16_i16_true() -> i16 { function %bint_b16_i16_true() -> i16 {
block0: block0:
@ -17,21 +160,180 @@ block0:
v1 = bint.i16 v0 v1 = bint.i16 v0
return v1 return v1
} }
; run: %bint_b16_i16_true() == 1 ; run: %bint_b16_i16_tru() == 1
function %bint_b8_i16_false() -> i16 { function %bint_b16_i16_false() -> i16 {
block0: block0:
v0 = bconst.b8 false v0 = bconst.b16 false
v1 = bint.i16 v0 v1 = bint.i16 v0
return v1 return v1
} }
; run: %bint_b8_i16_false() == 0 ; run: %bint_b16_i16_fal() == 0
function %bint_b16_i32_true() -> i32 {
block0:
v0 = bconst.b16 true
v1 = bint.i32 v0
return v1
}
; run: %bint_b16_i32_tru() == 1
function %bint_b16_i16_false() -> i16 { function %bint_b16_i32_false() -> i32 {
block0: block0:
v0 = bconst.b16 false v0 = bconst.b16 false
v1 = bint.i32 v0
return v1
}
; run: %bint_b16_i32_fal() == 0
function %bint_b16_i64_true() -> i64 {
block0:
v0 = bconst.b16 true
v1 = bint.i64 v0
return v1
}
; run: %bint_b16_i64_tru() == 1
function %bint_b16_i64_false() -> i64 {
block0:
v0 = bconst.b16 false
v1 = bint.i64 v0
return v1
}
; run: %bint_b16_i64_fal() == 0
function %bint_b32_i8_true() -> i8 {
block0:
v0 = bconst.b32 true
v1 = bint.i8 v0
return v1
}
; run: %bint_b32_i8_true() == 1
function %bint_b32_i8_false() -> i8 {
block0:
v0 = bconst.b32 false
v1 = bint.i8 v0
return v1
}
; run: %bint_b32_i8_fals() == 0
function %bint_b32_i16_true() -> i16 {
block0:
v0 = bconst.b32 true
v1 = bint.i16 v0
return v1
}
; run: %bint_b32_i16_tru() == 1
function %bint_b32_i16_false() -> i16 {
block0:
v0 = bconst.b32 false
v1 = bint.i16 v0
return v1
}
; run: %bint_b32_i16_fal() == 0
function %bint_b32_i32_true() -> i32 {
block0:
v0 = bconst.b32 true
v1 = bint.i32 v0
return v1
}
; run: %bint_b32_i32_tru() == 1
function %bint_b32_i32_false() -> i32 {
block0:
v0 = bconst.b32 false
v1 = bint.i32 v0
return v1
}
; run: %bint_b32_i32_fal() == 0
function %bint_b32_i64_true() -> i64 {
block0:
v0 = bconst.b32 true
v1 = bint.i64 v0
return v1
}
; run: %bint_b32_i64_tru() == 1
function %bint_b32_i64_false() -> i64 {
block0:
v0 = bconst.b32 false
v1 = bint.i64 v0
return v1
}
; run: %bint_b32_i64_fal() == 0
function %bint_b64_i8_true() -> i8 {
block0:
v0 = bconst.b64 true
v1 = bint.i8 v0
return v1
}
; run: %bint_b64_i8_true() == 1
function %bint_b64_i8_false() -> i8 {
block0:
v0 = bconst.b64 false
v1 = bint.i8 v0
return v1
}
; run: %bint_b64_i8_fals() == 0
function %bint_b64_i16_true() -> i16 {
block0:
v0 = bconst.b64 true
v1 = bint.i16 v0
return v1
}
; run: %bint_b64_i16_tru() == 1
function %bint_b64_i16_false() -> i16 {
block0:
v0 = bconst.b64 false
v1 = bint.i16 v0 v1 = bint.i16 v0
return v1 return v1
} }
; run: %bint_b16_i16_false() == 0 ; run: %bint_b64_i16_fal() == 0
function %bint_b64_i32_true() -> i32 {
block0:
v0 = bconst.b64 true
v1 = bint.i32 v0
return v1
}
; run: %bint_b64_i32_tru() == 1
function %bint_b64_i32_false() -> i32 {
block0:
v0 = bconst.b64 false
v1 = bint.i32 v0
return v1
}
; run: %bint_b64_i32_fal() == 0
function %bint_b64_i64_true() -> i64 {
block0:
v0 = bconst.b64 true
v1 = bint.i64 v0
return v1
}
; run: %bint_b64_i64_tru() == 1
function %bint_b64_i64_false() -> i64 {
block0:
v0 = bconst.b64 false
v1 = bint.i64 v0
return v1
}
; run: %bint_b64_i64_fal() == 0

77
cranelift/filetests/filetests/runtests/i128-bint.clif

@ -1,12 +1,85 @@
test interpret
test run test run
set enable_llvm_abi_extensions=true set enable_llvm_abi_extensions=true
target aarch64 target aarch64
target x86_64 target x86_64
function %bint_b8_i128() -> i128 { function %bint_b1_i128_true() -> i128 {
block0:
v0 = bconst.b1 true
v1 = bint.i128 v0
return v1
}
; run: %bint_b1_i128_tru() == 1
function %bint_b1_i128_false() -> i128 {
block0:
v0 = bconst.b1 false
v1 = bint.i128 v0
return v1
}
; run: %bint_b1_i128_fal() == 0
function %bint_b8_i128_true() -> i128 {
block0: block0:
v0 = bconst.b8 true v0 = bconst.b8 true
v1 = bint.i128 v0 v1 = bint.i128 v0
return v1 return v1
} }
; run: %bint_b8_i128() == 1 ; run: %bint_b8_i128_tru() == 1
function %bint_b8_i128_false() -> i128 {
block0:
v0 = bconst.b8 false
v1 = bint.i128 v0
return v1
}
; run: %bint_b8_i128_fal() == 0
function %bint_b16_i128_true() -> i128 {
block0:
v0 = bconst.b16 true
v1 = bint.i128 v0
return v1
}
; run: %bint_b16_i128_tr() == 1
function %bint_b16_i128_false() -> i128 {
block0:
v0 = bconst.b16 false
v1 = bint.i128 v0
return v1
}
; run: %bint_b16_i128_fa() == 0
function %bint_b32_i128_true() -> i128 {
block0:
v0 = bconst.b32 true
v1 = bint.i128 v0
return v1
}
; run: %bint_b32_i128_tr() == 1
function %bint_b32_i128_false() -> i128 {
block0:
v0 = bconst.b32 false
v1 = bint.i128 v0
return v1
}
; run: %bint_b32_i128_fa() == 0
function %bint_b64_i128_true() -> i128 {
block0:
v0 = bconst.b64 true
v1 = bint.i128 v0
return v1
}
; run: %bint_b64_i128_tr() == 1
function %bint_b64_i128_false() -> i128 {
block0:
v0 = bconst.b64 false
v1 = bint.i128 v0
return v1
}
; run: %bint_b64_i128_fa() == 0

6
cranelift/interpreter/src/step.rs

@ -716,11 +716,15 @@ where
| Opcode::ScalarToVector | Opcode::ScalarToVector
| Opcode::Breduce | Opcode::Breduce
| Opcode::Bextend | Opcode::Bextend
| Opcode::Bint
| Opcode::Ireduce => assign(Value::convert( | Opcode::Ireduce => assign(Value::convert(
arg(0)?, arg(0)?,
ValueConversionKind::Exact(ctrl_ty), ValueConversionKind::Exact(ctrl_ty),
)?), )?),
Opcode::Bint => {
let bool = arg(0)?.into_bool()?;
let int = if bool { 1 } else { 0 };
assign(Value::int(int, ctrl_ty)?)
}
Opcode::Snarrow | Opcode::Unarrow | Opcode::Uunarrow => { Opcode::Snarrow | Opcode::Unarrow | Opcode::Uunarrow => {
let arg0 = extractlanes(&arg(0)?, ctrl_ty.lane_type())?; let arg0 = extractlanes(&arg(0)?, ctrl_ty.lane_type())?;
let arg1 = extractlanes(&arg(1)?, ctrl_ty.lane_type())?; let arg1 = extractlanes(&arg(1)?, ctrl_ty.lane_type())?;

Loading…
Cancel
Save