Support wasm select instruction with V128-typed operands on AArch64.
* this requires upgrading to wasmparser 0.67.0. * There are no CLIF side changes because the CLIF `select` instruction is polymorphic enough. * on aarch64, there is unfortunately no conditional-move (csel) instruction on vectors. This patch adds a synthetic instruction `VecCSel` which *does* behave like that. At emit time, this is emitted as an if-then-else diamond (4 insns). * aarch64 implementation is otherwise straightforwards.
This commit is contained in:
committed by
julian-seward1
parent
9ced345aed
commit
41e87a2f99
24
Cargo.lock
generated
24
Cargo.lock
generated
@@ -542,7 +542,7 @@ dependencies = [
|
|||||||
"smallvec",
|
"smallvec",
|
||||||
"target-lexicon",
|
"target-lexicon",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"wasmparser 0.66.0",
|
"wasmparser 0.67.0",
|
||||||
"wat",
|
"wat",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -1090,7 +1090,7 @@ dependencies = [
|
|||||||
"smallvec",
|
"smallvec",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"typemap",
|
"typemap",
|
||||||
"wasmparser 0.66.0",
|
"wasmparser 0.67.0",
|
||||||
"wat",
|
"wat",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -2223,6 +2223,12 @@ version = "0.66.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c97fc0456d6d09ca7b64bc33c34f4e8f29d5ccfa8e5595ef7a8957818339e6f6"
|
checksum = "c97fc0456d6d09ca7b64bc33c34f4e8f29d5ccfa8e5595ef7a8957818339e6f6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasmparser"
|
||||||
|
version = "0.67.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9f091cf3849e5fe76a60255bff169277459f2201435bc583b6656880553f0ad0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasmprinter"
|
name = "wasmprinter"
|
||||||
version = "0.2.13"
|
version = "0.2.13"
|
||||||
@@ -2250,7 +2256,7 @@ dependencies = [
|
|||||||
"smallvec",
|
"smallvec",
|
||||||
"target-lexicon",
|
"target-lexicon",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
"wasmparser 0.66.0",
|
"wasmparser 0.67.0",
|
||||||
"wasmtime-cache",
|
"wasmtime-cache",
|
||||||
"wasmtime-environ",
|
"wasmtime-environ",
|
||||||
"wasmtime-jit",
|
"wasmtime-jit",
|
||||||
@@ -2328,7 +2334,7 @@ dependencies = [
|
|||||||
"test-programs",
|
"test-programs",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
"wasi-common",
|
"wasi-common",
|
||||||
"wasmparser 0.66.0",
|
"wasmparser 0.67.0",
|
||||||
"wasmtime",
|
"wasmtime",
|
||||||
"wasmtime-cache",
|
"wasmtime-cache",
|
||||||
"wasmtime-debug",
|
"wasmtime-debug",
|
||||||
@@ -2363,7 +2369,7 @@ dependencies = [
|
|||||||
"object",
|
"object",
|
||||||
"target-lexicon",
|
"target-lexicon",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"wasmparser 0.66.0",
|
"wasmparser 0.67.0",
|
||||||
"wasmtime-environ",
|
"wasmtime-environ",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -2382,7 +2388,7 @@ dependencies = [
|
|||||||
"more-asserts",
|
"more-asserts",
|
||||||
"serde",
|
"serde",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"wasmparser 0.66.0",
|
"wasmparser 0.67.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2410,7 +2416,7 @@ dependencies = [
|
|||||||
"log",
|
"log",
|
||||||
"rayon",
|
"rayon",
|
||||||
"wasm-smith",
|
"wasm-smith",
|
||||||
"wasmparser 0.66.0",
|
"wasmparser 0.67.0",
|
||||||
"wasmprinter",
|
"wasmprinter",
|
||||||
"wasmtime",
|
"wasmtime",
|
||||||
"wasmtime-wast",
|
"wasmtime-wast",
|
||||||
@@ -2437,7 +2443,7 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
"target-lexicon",
|
"target-lexicon",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"wasmparser 0.66.0",
|
"wasmparser 0.67.0",
|
||||||
"wasmtime-cranelift",
|
"wasmtime-cranelift",
|
||||||
"wasmtime-debug",
|
"wasmtime-debug",
|
||||||
"wasmtime-environ",
|
"wasmtime-environ",
|
||||||
@@ -2454,7 +2460,7 @@ version = "0.21.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"cranelift-codegen",
|
"cranelift-codegen",
|
||||||
"lightbeam",
|
"lightbeam",
|
||||||
"wasmparser 0.66.0",
|
"wasmparser 0.67.0",
|
||||||
"wasmtime-environ",
|
"wasmtime-environ",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ libc = "0.2.60"
|
|||||||
log = "0.4.8"
|
log = "0.4.8"
|
||||||
rayon = "1.2.1"
|
rayon = "1.2.1"
|
||||||
humantime = "2.0.0"
|
humantime = "2.0.0"
|
||||||
wasmparser = "0.66"
|
wasmparser = "0.67"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
env_logger = "0.8.1"
|
env_logger = "0.8.1"
|
||||||
|
|||||||
@@ -1909,6 +1909,46 @@ impl MachInstEmit for Inst {
|
|||||||
|
|
||||||
sink.put4(enc_ldst_vec(q, size, rn, rd));
|
sink.put4(enc_ldst_vec(q, size, rn, rd));
|
||||||
}
|
}
|
||||||
|
&Inst::VecCSel { rd, rn, rm, cond } => {
|
||||||
|
/* Emit this:
|
||||||
|
b.cond else
|
||||||
|
mov rd, rm
|
||||||
|
b out
|
||||||
|
else:
|
||||||
|
mov rd, rn
|
||||||
|
out:
|
||||||
|
|
||||||
|
Note, we could do better in the cases where rd == rn or rd == rm.
|
||||||
|
*/
|
||||||
|
let else_label = sink.get_label();
|
||||||
|
let out_label = sink.get_label();
|
||||||
|
|
||||||
|
// b.cond else
|
||||||
|
let br_else_offset = sink.cur_offset();
|
||||||
|
sink.put4(enc_conditional_br(
|
||||||
|
BranchTarget::Label(else_label),
|
||||||
|
CondBrKind::Cond(cond),
|
||||||
|
));
|
||||||
|
sink.use_label_at_offset(br_else_offset, else_label, LabelUse::Branch19);
|
||||||
|
|
||||||
|
// mov rd, rm
|
||||||
|
sink.put4(enc_vecmov(/* 16b = */ true, rd, rm));
|
||||||
|
|
||||||
|
// b out
|
||||||
|
let b_out_offset = sink.cur_offset();
|
||||||
|
sink.use_label_at_offset(b_out_offset, out_label, LabelUse::Branch26);
|
||||||
|
sink.add_uncond_branch(b_out_offset, b_out_offset + 4, out_label);
|
||||||
|
sink.put4(enc_jump26(0b000101, 0 /* will be fixed up later */));
|
||||||
|
|
||||||
|
// else:
|
||||||
|
sink.bind_label(else_label);
|
||||||
|
|
||||||
|
// mov rd, rn
|
||||||
|
sink.put4(enc_vecmov(/* 16b = */ true, rd, rn));
|
||||||
|
|
||||||
|
// out:
|
||||||
|
sink.bind_label(out_label);
|
||||||
|
}
|
||||||
&Inst::MovToNZCV { rn } => {
|
&Inst::MovToNZCV { rn } => {
|
||||||
sink.put4(0xd51b4200 | machreg_to_gpr(rn));
|
sink.put4(0xd51b4200 | machreg_to_gpr(rn));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3879,6 +3879,17 @@ fn test_aarch64_binemit() {
|
|||||||
"ld1r { v0.8b }, [x25]",
|
"ld1r { v0.8b }, [x25]",
|
||||||
));
|
));
|
||||||
|
|
||||||
|
insns.push((
|
||||||
|
Inst::VecCSel {
|
||||||
|
rd: writable_vreg(5),
|
||||||
|
rn: vreg(10),
|
||||||
|
rm: vreg(19),
|
||||||
|
cond: Cond::Gt,
|
||||||
|
},
|
||||||
|
"6C000054651EB34E02000014451DAA4E",
|
||||||
|
"vcsel v5.16b, v10.16b, v19.16b, gt (if-then-else diamond)",
|
||||||
|
));
|
||||||
|
|
||||||
insns.push((
|
insns.push((
|
||||||
Inst::Extend {
|
Inst::Extend {
|
||||||
rd: writable_xreg(1),
|
rd: writable_xreg(1),
|
||||||
|
|||||||
@@ -1016,6 +1016,15 @@ pub enum Inst {
|
|||||||
size: VectorSize,
|
size: VectorSize,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/// Vector conditional select, 128 bit. A synthetic instruction, which generates a 4-insn
|
||||||
|
/// control-flow diamond.
|
||||||
|
VecCSel {
|
||||||
|
rd: Writable<Reg>,
|
||||||
|
rn: Reg,
|
||||||
|
rm: Reg,
|
||||||
|
cond: Cond,
|
||||||
|
},
|
||||||
|
|
||||||
/// Move to the NZCV flags (actually a `MSR NZCV, Xn` insn).
|
/// Move to the NZCV flags (actually a `MSR NZCV, Xn` insn).
|
||||||
MovToNZCV {
|
MovToNZCV {
|
||||||
rn: Reg,
|
rn: Reg,
|
||||||
@@ -1732,6 +1741,11 @@ fn aarch64_get_regs(inst: &Inst, collector: &mut RegUsageCollector) {
|
|||||||
collector.add_def(rd);
|
collector.add_def(rd);
|
||||||
collector.add_use(rn);
|
collector.add_use(rn);
|
||||||
}
|
}
|
||||||
|
&Inst::VecCSel { rd, rn, rm, .. } => {
|
||||||
|
collector.add_def(rd);
|
||||||
|
collector.add_use(rn);
|
||||||
|
collector.add_use(rm);
|
||||||
|
}
|
||||||
&Inst::FpuCmp32 { rn, rm } | &Inst::FpuCmp64 { rn, rm } => {
|
&Inst::FpuCmp32 { rn, rm } | &Inst::FpuCmp64 { rn, rm } => {
|
||||||
collector.add_use(rn);
|
collector.add_use(rn);
|
||||||
collector.add_use(rm);
|
collector.add_use(rm);
|
||||||
@@ -2343,6 +2357,16 @@ fn aarch64_map_regs<RUM: RegUsageMapper>(inst: &mut Inst, mapper: &RUM) {
|
|||||||
map_def(mapper, rd);
|
map_def(mapper, rd);
|
||||||
map_use(mapper, rn);
|
map_use(mapper, rn);
|
||||||
}
|
}
|
||||||
|
&mut Inst::VecCSel {
|
||||||
|
ref mut rd,
|
||||||
|
ref mut rn,
|
||||||
|
ref mut rm,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
map_def(mapper, rd);
|
||||||
|
map_use(mapper, rn);
|
||||||
|
map_use(mapper, rm);
|
||||||
|
}
|
||||||
&mut Inst::FpuCmp32 {
|
&mut Inst::FpuCmp32 {
|
||||||
ref mut rn,
|
ref mut rn,
|
||||||
ref mut rm,
|
ref mut rm,
|
||||||
@@ -3591,6 +3615,13 @@ impl Inst {
|
|||||||
|
|
||||||
format!("ld1r {{ {} }}, [{}]", rd, rn)
|
format!("ld1r {{ {} }}, [{}]", rd, rn)
|
||||||
}
|
}
|
||||||
|
&Inst::VecCSel { rd, rn, rm, cond } => {
|
||||||
|
let rd = show_vreg_vector(rd.to_reg(), mb_rru, VectorSize::Size8x16);
|
||||||
|
let rn = show_vreg_vector(rn, mb_rru, VectorSize::Size8x16);
|
||||||
|
let rm = show_vreg_vector(rm, mb_rru, VectorSize::Size8x16);
|
||||||
|
let cond = cond.show_rru(mb_rru);
|
||||||
|
format!("vcsel {}, {}, {}, {} (if-then-else diamond)", rd, rn, rm, cond)
|
||||||
|
}
|
||||||
&Inst::MovToNZCV { rn } => {
|
&Inst::MovToNZCV { rn } => {
|
||||||
let rn = rn.show_rru(mb_rru);
|
let rn = rn.show_rru(mb_rru);
|
||||||
format!("msr nzcv, {}", rn)
|
format!("msr nzcv, {}", rn)
|
||||||
|
|||||||
@@ -1412,6 +1412,8 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
|||||||
ctx.emit(Inst::FpuCSel32 { cond, rd, rn, rm });
|
ctx.emit(Inst::FpuCSel32 { cond, rd, rn, rm });
|
||||||
} else if is_float && bits == 64 {
|
} else if is_float && bits == 64 {
|
||||||
ctx.emit(Inst::FpuCSel64 { cond, rd, rn, rm });
|
ctx.emit(Inst::FpuCSel64 { cond, rd, rn, rm });
|
||||||
|
} else if is_float && bits == 128 {
|
||||||
|
ctx.emit(Inst::VecCSel { cond, rd, rn, rm });
|
||||||
} else {
|
} else {
|
||||||
ctx.emit(Inst::CSel { cond, rd, rn, rm });
|
ctx.emit(Inst::CSel { cond, rd, rn, rm });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,3 +47,17 @@ block0:
|
|||||||
; nextln: mov sp, fp
|
; nextln: mov sp, fp
|
||||||
; nextln: ldp fp, lr, [sp], #16
|
; nextln: ldp fp, lr, [sp], #16
|
||||||
; nextln: ret
|
; nextln: ret
|
||||||
|
|
||||||
|
function %f4(i32, i8x16, i8x16) -> i8x16 {
|
||||||
|
block0(v0: i32, v1: i8x16, v2: i8x16):
|
||||||
|
v3 = select v0, v1, v2
|
||||||
|
return v3
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: stp fp, lr, [sp, #-16]!
|
||||||
|
; nextln: mov fp, sp
|
||||||
|
; nextln: subs wzr, w0, wzr
|
||||||
|
; nextln: vcsel v0.16b, v0.16b, v1.16b, ne (if-then-else diamond)
|
||||||
|
; nextln: mov sp, fp
|
||||||
|
; nextln: ldp fp, lr, [sp], #16
|
||||||
|
; nextln: ret
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ keywords = ["webassembly", "wasm"]
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
wasmparser = { version = "0.66.0", default-features = false }
|
wasmparser = { version = "0.67.0", default-features = false }
|
||||||
cranelift-codegen = { path = "../codegen", version = "0.68.0", default-features = false }
|
cranelift-codegen = { path = "../codegen", version = "0.68.0", default-features = false }
|
||||||
cranelift-entity = { path = "../entity", version = "0.68.0" }
|
cranelift-entity = { path = "../entity", version = "0.68.0" }
|
||||||
cranelift-frontend = { path = "../frontend", version = "0.68.0", default-features = false }
|
cranelift-frontend = { path = "../frontend", version = "0.68.0", default-features = false }
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ edition = "2018"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
gimli = "0.23.0"
|
gimli = "0.23.0"
|
||||||
wasmparser = "0.66.0"
|
wasmparser = "0.67.0"
|
||||||
object = { version = "0.22.0", default-features = false, features = ["read", "write"] }
|
object = { version = "0.22.0", default-features = false, features = ["read", "write"] }
|
||||||
wasmtime-environ = { path = "../environ", version = "0.21.0" }
|
wasmtime-environ = { path = "../environ", version = "0.21.0" }
|
||||||
target-lexicon = { version = "0.11.0", default-features = false }
|
target-lexicon = { version = "0.11.0", default-features = false }
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ anyhow = "1.0"
|
|||||||
cranelift-codegen = { path = "../../cranelift/codegen", version = "0.68.0", features = ["enable-serde"] }
|
cranelift-codegen = { path = "../../cranelift/codegen", version = "0.68.0", features = ["enable-serde"] }
|
||||||
cranelift-entity = { path = "../../cranelift/entity", version = "0.68.0", features = ["enable-serde"] }
|
cranelift-entity = { path = "../../cranelift/entity", version = "0.68.0", features = ["enable-serde"] }
|
||||||
cranelift-wasm = { path = "../../cranelift/wasm", version = "0.68.0", features = ["enable-serde"] }
|
cranelift-wasm = { path = "../../cranelift/wasm", version = "0.68.0", features = ["enable-serde"] }
|
||||||
wasmparser = "0.66.0"
|
wasmparser = "0.67.0"
|
||||||
indexmap = { version = "1.0.2", features = ["serde-1"] }
|
indexmap = { version = "1.0.2", features = ["serde-1"] }
|
||||||
thiserror = "1.0.4"
|
thiserror = "1.0.4"
|
||||||
serde = { version = "1.0.94", features = ["derive"] }
|
serde = { version = "1.0.94", features = ["derive"] }
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ arbitrary = { version = "0.4.1", features = ["derive"] }
|
|||||||
env_logger = "0.8.1"
|
env_logger = "0.8.1"
|
||||||
log = "0.4.8"
|
log = "0.4.8"
|
||||||
rayon = "1.2.1"
|
rayon = "1.2.1"
|
||||||
wasmparser = "0.66.0"
|
wasmparser = "0.67.0"
|
||||||
wasmprinter = "0.2.13"
|
wasmprinter = "0.2.13"
|
||||||
wasmtime = { path = "../wasmtime" }
|
wasmtime = { path = "../wasmtime" }
|
||||||
wasmtime-wast = { path = "../wast" }
|
wasmtime-wast = { path = "../wast" }
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ rayon = { version = "1.0", optional = true }
|
|||||||
region = "2.1.0"
|
region = "2.1.0"
|
||||||
thiserror = "1.0.4"
|
thiserror = "1.0.4"
|
||||||
target-lexicon = { version = "0.11.0", default-features = false }
|
target-lexicon = { version = "0.11.0", default-features = false }
|
||||||
wasmparser = "0.66.0"
|
wasmparser = "0.67.0"
|
||||||
more-asserts = "0.2.1"
|
more-asserts = "0.2.1"
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
cfg-if = "1.0"
|
cfg-if = "1.0"
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ more-asserts = "0.2.1"
|
|||||||
smallvec = "1.0.0"
|
smallvec = "1.0.0"
|
||||||
thiserror = "1.0.9"
|
thiserror = "1.0.9"
|
||||||
typemap = "0.3"
|
typemap = "0.3"
|
||||||
wasmparser = "0.66.0"
|
wasmparser = "0.67.0"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
lazy_static = "1.2"
|
lazy_static = "1.2"
|
||||||
|
|||||||
@@ -13,6 +13,6 @@ edition = "2018"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
lightbeam = { path = "..", version = "0.21.0" }
|
lightbeam = { path = "..", version = "0.21.0" }
|
||||||
wasmparser = "0.66"
|
wasmparser = "0.67"
|
||||||
cranelift-codegen = { path = "../../../cranelift/codegen", version = "0.68.0" }
|
cranelift-codegen = { path = "../../../cranelift/codegen", version = "0.68.0" }
|
||||||
wasmtime-environ = { path = "../../environ", version = "0.21.0" }
|
wasmtime-environ = { path = "../../environ", version = "0.21.0" }
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ wasmtime-jit = { path = "../jit", version = "0.21.0" }
|
|||||||
wasmtime-cache = { path = "../cache", version = "0.21.0", optional = true }
|
wasmtime-cache = { path = "../cache", version = "0.21.0", optional = true }
|
||||||
wasmtime-profiling = { path = "../profiling", version = "0.21.0" }
|
wasmtime-profiling = { path = "../profiling", version = "0.21.0" }
|
||||||
target-lexicon = { version = "0.11.0", default-features = false }
|
target-lexicon = { version = "0.11.0", default-features = false }
|
||||||
wasmparser = "0.66.0"
|
wasmparser = "0.67.0"
|
||||||
anyhow = "1.0.19"
|
anyhow = "1.0.19"
|
||||||
region = "2.2.0"
|
region = "2.2.0"
|
||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
|
|||||||
Reference in New Issue
Block a user