Skip to content

Commit a6f4bd2

Browse files
authored
Deduplicate const-eval fast paths in Wasmtime (#12406)
Closes #12243
1 parent 595215b commit a6f4bd2

File tree

6 files changed

+48
-60
lines changed

6 files changed

+48
-60
lines changed

crates/cranelift/src/func_environ.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ pub(crate) mod stack_switching;
33

44
use crate::compiler::Compiler;
55
use crate::translate::{
6-
FuncTranslationStacks, GlobalConstValue, GlobalVariable, Heap, HeapData, StructFieldsVec,
7-
TableData, TableSize, TargetEnvironment,
6+
FuncTranslationStacks, GlobalVariable, Heap, HeapData, StructFieldsVec, TableData, TableSize,
7+
TargetEnvironment,
88
};
99
use crate::{BuiltinFunctionSignatures, TRAP_INTERNAL_ASSERT};
1010
use cranelift_codegen::cursor::FuncCursor;
@@ -25,11 +25,11 @@ use wasmparser::{FuncValidator, Operator, WasmFeatures, WasmModuleResources};
2525
use wasmtime_core::math::f64_cvt_to_int_bounds;
2626
use wasmtime_environ::{
2727
BuiltinFunctionIndex, DataIndex, DefinedFuncIndex, ElemIndex, EngineOrModuleTypeIndex,
28-
FrameStateSlotBuilder, FrameValType, FuncIndex, FuncKey, GlobalIndex, IndexType, Memory,
29-
MemoryIndex, Module, ModuleInternedTypeIndex, ModuleTranslation, ModuleTypesBuilder, PtrSize,
30-
Table, TableIndex, TagIndex, TripleExt, Tunables, TypeConvert, TypeIndex, VMOffsets,
31-
WasmCompositeInnerType, WasmFuncType, WasmHeapTopType, WasmHeapType, WasmRefType, WasmResult,
32-
WasmValType,
28+
FrameStateSlotBuilder, FrameValType, FuncIndex, FuncKey, GlobalConstValue, GlobalIndex,
29+
IndexType, Memory, MemoryIndex, Module, ModuleInternedTypeIndex, ModuleTranslation,
30+
ModuleTypesBuilder, PtrSize, Table, TableIndex, TagIndex, TripleExt, Tunables, TypeConvert,
31+
TypeIndex, VMOffsets, WasmCompositeInnerType, WasmFuncType, WasmHeapTopType, WasmHeapType,
32+
WasmRefType, WasmResult, WasmValType,
3333
};
3434
use wasmtime_environ::{FUNCREF_INIT_BIT, FUNCREF_MASK};
3535

@@ -1429,7 +1429,7 @@ impl FuncEnvironment<'_> {
14291429
if !self.module.globals[index].mutability {
14301430
if let Some(index) = self.module.defined_global_index(index) {
14311431
let init = &self.module.global_initializers[index];
1432-
if let Some(value) = GlobalConstValue::const_eval(init) {
1432+
if let Some(value) = init.const_eval() {
14331433
return GlobalVariable::Constant { value };
14341434
}
14351435
}

crates/cranelift/src/translate/environ/mod.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,4 @@
33
#[macro_use]
44
mod spec;
55

6-
pub use crate::translate::environ::spec::{
7-
GlobalConstValue, GlobalVariable, StructFieldsVec, TargetEnvironment,
8-
};
6+
pub use crate::translate::environ::spec::{GlobalVariable, StructFieldsVec, TargetEnvironment};

crates/cranelift/src/translate/environ/spec.rs

Lines changed: 1 addition & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use cranelift_codegen::ir;
1010
use cranelift_codegen::ir::immediates::Offset32;
1111
use cranelift_codegen::isa::TargetFrontendConfig;
1212
use smallvec::SmallVec;
13-
use wasmtime_environ::{ConstExpr, ConstOp, Tunables, TypeConvert, WasmHeapType};
13+
use wasmtime_environ::{GlobalConstValue, Tunables, TypeConvert, WasmHeapType};
1414

1515
/// The value of a WebAssembly global variable.
1616
#[derive(Clone, Copy)]
@@ -35,32 +35,6 @@ pub enum GlobalVariable {
3535
Custom,
3636
}
3737

38-
/// A global's constant value, known at compile time.
39-
#[derive(Clone, Copy)]
40-
pub enum GlobalConstValue {
41-
I32(i32),
42-
I64(i64),
43-
F32(u32),
44-
F64(u64),
45-
V128(u128),
46-
}
47-
48-
impl GlobalConstValue {
49-
/// Attempt to evaluate the given const-expr at compile time.
50-
pub fn const_eval(init: &ConstExpr) -> Option<GlobalConstValue> {
51-
// TODO: Actually maintain an evaluation stack and handle `i32.add`,
52-
// `i32.sub`, etc... const ops.
53-
match init.ops() {
54-
[ConstOp::I32Const(x)] => Some(Self::I32(*x)),
55-
[ConstOp::I64Const(x)] => Some(Self::I64(*x)),
56-
[ConstOp::F32Const(x)] => Some(Self::F32(*x)),
57-
[ConstOp::F64Const(x)] => Some(Self::F64(*x)),
58-
[ConstOp::V128Const(x)] => Some(Self::V128(*x)),
59-
_ => None,
60-
}
61-
}
62-
}
63-
6438
/// Environment affecting the translation of a WebAssembly.
6539
pub trait TargetEnvironment: TypeConvert {
6640
/// Get the information needed to produce Cranelift IR for the given target.

crates/cranelift/src/translate/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ mod stack;
1818
mod table;
1919
mod translation_utils;
2020

21-
pub use self::environ::{GlobalConstValue, GlobalVariable, StructFieldsVec, TargetEnvironment};
21+
pub use self::environ::{GlobalVariable, StructFieldsVec, TargetEnvironment};
2222
pub use self::func_translator::FuncTranslator;
2323
pub use self::heap::{Heap, HeapData};
2424
pub use self::stack::FuncTranslationStacks;

crates/environ/src/types.rs

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1849,23 +1849,39 @@ impl ConstExpr {
18491849
/// We use this for certain table optimizations that rely on
18501850
/// knowing for sure that index 0 is not referenced.
18511851
pub fn provably_nonzero_i32(&self) -> bool {
1852-
assert!(self.ops.len() > 0);
1853-
if self.ops.len() > 1 {
1854-
// Compound expressions not yet supported: conservatively
1855-
// return `false` (we can't prove nonzero).
1856-
return false;
1857-
}
1858-
// Exactly one op at this point.
1859-
match self.ops[0] {
1860-
// An actual zero value -- definitely not nonzero!
1861-
ConstOp::I32Const(0) => false,
1862-
// Any other constant value -- provably nonzero, if above
1863-
// did not match.
1864-
ConstOp::I32Const(_) => true,
1865-
// Anything else: we can't prove anything.
1852+
match self.const_eval() {
1853+
Some(GlobalConstValue::I32(x)) => x != 0,
1854+
1855+
// Conservatively return `false` for non-const-eval-able expressions
1856+
// as well as everything else.
18661857
_ => false,
18671858
}
18681859
}
1860+
1861+
/// Attempt to evaluate the given const-expr at compile time.
1862+
pub fn const_eval(&self) -> Option<GlobalConstValue> {
1863+
// TODO: Actually maintain an evaluation stack and handle `i32.add`,
1864+
// `i32.sub`, etc... const ops.
1865+
match self.ops() {
1866+
[ConstOp::I32Const(x)] => Some(GlobalConstValue::I32(*x)),
1867+
[ConstOp::I64Const(x)] => Some(GlobalConstValue::I64(*x)),
1868+
[ConstOp::F32Const(x)] => Some(GlobalConstValue::F32(*x)),
1869+
[ConstOp::F64Const(x)] => Some(GlobalConstValue::F64(*x)),
1870+
[ConstOp::V128Const(x)] => Some(GlobalConstValue::V128(*x)),
1871+
_ => None,
1872+
}
1873+
}
1874+
}
1875+
1876+
/// A global's constant value, known at compile time.
1877+
#[expect(missing_docs, reason = "self-describing variants")]
1878+
#[derive(Clone, Copy)]
1879+
pub enum GlobalConstValue {
1880+
I32(i32),
1881+
I64(i64),
1882+
F32(u32),
1883+
F64(u64),
1884+
V128(u128),
18691885
}
18701886

18711887
/// The subset of Wasm opcodes that are constant.

crates/wasmtime/src/runtime/vm/const_expr.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use crate::{
88
AnyRef, ArrayRef, ArrayRefPre, ArrayType, ExternRef, I31, StructRef, StructRefPre, StructType,
99
};
1010
use crate::{OpaqueRootScope, Val};
11-
use wasmtime_environ::{ConstExpr, ConstOp, FuncIndex, GlobalIndex};
11+
use wasmtime_environ::{ConstExpr, ConstOp, FuncIndex, GlobalConstValue, GlobalIndex};
1212
#[cfg(feature = "gc")]
1313
use wasmtime_environ::{VMSharedTypeIndex, WasmCompositeInnerType, WasmCompositeType, WasmSubType};
1414

@@ -168,12 +168,12 @@ impl ConstExprEvaluator {
168168
/// for `i32.const N`.
169169
#[inline]
170170
pub fn try_simple(&mut self, expr: &ConstExpr) -> Option<&Val> {
171-
match expr.ops() {
172-
[ConstOp::I32Const(i)] => Some(self.return_one(Val::I32(*i))),
173-
[ConstOp::I64Const(i)] => Some(self.return_one(Val::I64(*i))),
174-
[ConstOp::F32Const(f)] => Some(self.return_one(Val::F32(*f))),
175-
[ConstOp::F64Const(f)] => Some(self.return_one(Val::F64(*f))),
176-
_ => None,
171+
match expr.const_eval()? {
172+
GlobalConstValue::I32(i) => Some(self.return_one(Val::I32(i))),
173+
GlobalConstValue::I64(i) => Some(self.return_one(Val::I64(i))),
174+
GlobalConstValue::F32(f) => Some(self.return_one(Val::F32(f))),
175+
GlobalConstValue::F64(f) => Some(self.return_one(Val::F64(f))),
176+
GlobalConstValue::V128(i) => Some(self.return_one(Val::V128(i.into()))),
177177
}
178178
}
179179

0 commit comments

Comments
 (0)