Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion src/ir/child-typer.h
Original file line number Diff line number Diff line change
Expand Up @@ -1036,9 +1036,19 @@ template<typename Subtype> struct ChildTyper : OverriddenVisitor<Subtype> {
ht = curr->ref->type.getHeapType();
}

const auto& fields = ht->getStruct().fields;
assert(curr->index < fields.size());
auto type = fields[curr->index].type;
auto expectedType = type;
// TODO: assertion for f32 / f64?
if (expectedType.isRef()) {
expectedType =
Type(HeapTypes::eq.getBasic(type.getHeapType().getShared()), Nullable);
}

note(&curr->ref, Type(*ht, Nullable));
note(&curr->waitqueue, Type(HeapTypes::sharedWaitqueue, Nullable));
note(&curr->expected, Type(Type::BasicType::i32));
note(&curr->expected, expectedType);
note(&curr->timeout, Type(Type::BasicType::i64));
}

Expand Down
2 changes: 2 additions & 0 deletions src/ir/properties.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ inline bool isSingleConstantExpression(const Expression* curr) {
if (refAs->op == ExternConvertAny || refAs->op == AnyConvertExtern) {
return isSingleConstantExpression(refAs->value);
}
} else if (auto* i31 = curr->dynCast<RefI31>()) {
return isSingleConstantExpression(i31->value);
}
return curr->is<Const>() || curr->is<RefNull>() || curr->is<RefFunc>() ||
curr->is<StringConst>();
Expand Down
13 changes: 13 additions & 0 deletions src/passes/param-utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,19 @@ SortedVector applyConstantValues(const std::vector<Function*>& funcs,
continue;
}

// If the parameter is not used in any of the functions, writing the
// constant value to it is redundant and creates a dead local set.
bool used = false;
for (auto* func : funcs) {
if (getUsedParams(func, module).count(i)) {
used = true;
break;
}
}
if (!used) {
continue;
}

// Optimize: write the constant value in the function bodies, making them
// ignore the parameter's value.
Builder builder(*module);
Expand Down
2 changes: 1 addition & 1 deletion src/wasm-interpreter.h
Original file line number Diff line number Diff line change
Expand Up @@ -2336,7 +2336,7 @@ class ExpressionRunner : public OverriddenVisitor<SubType, Flow> {
trap("null ref");
}
auto& field = data->values[curr->index];
if (field.geti32() != expected.getSingleValue().geti32()) {
if (field != expected.getSingleValue()) {
return Literal(int32_t{1}); // not equal
}
// TODO: Add threads support. For now, report a host limit here, as there
Expand Down
22 changes: 22 additions & 0 deletions src/wasm/wasm-ir-builder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2352,8 +2352,30 @@ Result<> IRBuilder::makeStructWait(HeapType type, Index index) {
}

StructWait curr(wasm.allocator);
curr.index = index;
CHECK_ERR(ChildPopper{*this}.visitStructWait(&curr, type));
CHECK_ERR(validateTypeAnnotation(type, curr.ref));

if (curr.expected->type != Type::unreachable) {
const auto& field = type.getStruct().fields[index];
Type expectedExpectedType;
if (field.type == Type::i32) {
expectedExpectedType = Type::i32;
} else if (field.type == Type::i64) {
expectedExpectedType = Type::i64;
} else if (field.type.isRef()) {
expectedExpectedType =
Type(HeapTypes::eq.getBasic(field.type.getHeapType().getShared()),
Nullable);
} else {
return Err{
"struct.wait field type must be i32, i64 of a subtype of (ref null (shared eq))"};
}
if (!Type::isSubType(curr.expected->type, expectedExpectedType)) {
return Err{"struct.wait expected value must have the proper type"};
}
}

push(builder.makeStructWait(
index, curr.ref, curr.waitqueue, curr.expected, curr.timeout));
return Ok{};
Expand Down
33 changes: 29 additions & 4 deletions src/wasm/wasm-validator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3652,10 +3652,35 @@ void FunctionValidator::visitStructWait(StructWait* curr) {
Type(HeapTypes::sharedWaitqueue, Nullable),
curr,
"struct.wait waitqueue must be a shared waitqueue reference");
shouldBeEqual(curr->expected->type,
Type(Type::BasicType::i32),
curr,
"struct.wait expected must be an i32");

if (curr->ref->type != Type::unreachable && curr->ref->type.isRef() &&
!curr->ref->type.getHeapType().isMaybeShared(HeapType::none) &&
curr->ref->type.getHeapType().isStruct()) {
auto type = curr->ref->type.getHeapType();
const auto& fields = type.getStruct().fields;
if (shouldBeTrue(curr->index < fields.size(), curr, "struct.wait field index immediate must be within bounds")) {
auto& field = fields[curr->index];
Type expectedExpectedType;
if (field.type == Type::i32) {
expectedExpectedType = Type::i32;
} else if (field.type == Type::i64) {
expectedExpectedType = Type::i64;
} else if (field.type.isRef()) {
expectedExpectedType =
Type(HeapTypes::eq.getBasic(field.type.getHeapType().getShared()),
Nullable);
} else {
shouldBeTrue(
false, curr, "struct.wait field type must be i32, i64 of a subtype of (ref null (shared eq))");
return;
}
shouldBeSubType(curr->expected->type,
expectedExpectedType,
curr,
"struct.wait expected value must have the proper type");
}
}

shouldBeEqual(curr->timeout->type,
Type(Type::BasicType::i64),
curr,
Expand Down
10 changes: 1 addition & 9 deletions test/lit/passes/dae-gc.wast
Original file line number Diff line number Diff line change
Expand Up @@ -179,15 +179,7 @@
;; CHECK: (func $1 (type $0)
;; CHECK-NEXT: (local $0 (ref string))
;; CHECK-NEXT: (local $1 (ref string))
;; CHECK-NEXT: (local.set $0
;; CHECK-NEXT: (string.const "929")
;; CHECK-NEXT: )
;; CHECK-NEXT: (block
;; CHECK-NEXT: (local.set $1
;; CHECK-NEXT: (string.const "310")
;; CHECK-NEXT: )
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: )
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: )
(func $1 (param $0 (ref string)) (param $1 (ref string))
;; The parameters here will be removed, and the constant values placed in the
Expand Down
21 changes: 8 additions & 13 deletions test/lit/passes/dae-typessa-repeat-types.wast
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@
;; Trigger TypeSSA
;; CHECK: (type $2 (func))

;; CHECK: (type $3 (func (result i32 (ref (exact $struct)))))

;; CHECK: (type $array_1 (sub $array (array (mut i32))))

;; CHECK: (type $5 (func (result i32 (ref $struct))))
;; CHECK: (type $4 (func (result i32 (ref $struct))))

;; CHECK: (type $5 (func (result i32 (ref (exact $struct)))))

;; CHECK: (global $array (ref $array) (array.new $array_1
;; CHECK-NEXT: (i32.const 0)
Expand Down Expand Up @@ -43,15 +43,10 @@
;; CHECK: (func $callee (type $2)
;; CHECK-NEXT: (local $0 anyref)
;; CHECK-NEXT: (tuple.drop 2
;; CHECK-NEXT: (block (type $3) (result i32 (ref (exact $struct)))
;; CHECK-NEXT: (local.set $0
;; CHECK-NEXT: (ref.null none)
;; CHECK-NEXT: )
;; CHECK-NEXT: (block (type $3) (result i32 (ref (exact $struct)))
;; CHECK-NEXT: (tuple.make 2
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: (struct.new_default $struct)
;; CHECK-NEXT: )
;; CHECK-NEXT: (block (type $5) (result i32 (ref (exact $struct)))
;; CHECK-NEXT: (tuple.make 2
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: (struct.new_default $struct)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
Expand All @@ -67,7 +62,7 @@
)
)

;; CHECK: (func $other (type $5) (result i32 (ref $struct))
;; CHECK: (func $other (type $4) (result i32 (ref $struct))
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
(func $other (result i32 (ref $struct))
Expand Down
55 changes: 9 additions & 46 deletions test/lit/passes/dae_all-features.wast
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,6 @@
(elem (i32.const 0) $a9 $c8)
;; CHECK: (func $a (type $0)
;; CHECK-NEXT: (local $0 i32)
;; CHECK-NEXT: (local.set $0
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: (block
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $a (param $x i32))
;; CHECK: (func $b (type $0)
Expand All @@ -45,9 +40,6 @@
)
;; CHECK: (func $a1 (type $0)
;; CHECK-NEXT: (local $0 i32)
;; CHECK-NEXT: (local.set $0
;; CHECK-NEXT: (i32.const 2)
;; CHECK-NEXT: )
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
(func $a1 (param $x i32)
Expand Down Expand Up @@ -112,11 +104,6 @@
)
;; CHECK: (func $a4 (type $0)
;; CHECK-NEXT: (local $0 i32)
;; CHECK-NEXT: (local.set $0
;; CHECK-NEXT: (i32.const 4)
;; CHECK-NEXT: )
;; CHECK-NEXT: (block
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $a4 (param $x i32)
;; This function is called with one constant and one unreachable. We can
Expand Down Expand Up @@ -244,13 +231,8 @@
)
;; CHECK: (func $a10 (type $0)
;; CHECK-NEXT: (local $0 i32)
;; CHECK-NEXT: (local.set $0
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: (block
;; CHECK-NEXT: (call $a10)
;; CHECK-NEXT: (call $a10)
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $a10)
;; CHECK-NEXT: (call $a10)
;; CHECK-NEXT: )
(func $a10 (param $x i32) ;; recursion
(call $a10 (i32.const 1))
Expand Down Expand Up @@ -417,9 +399,6 @@
)
;; CHECK: (func $bar (type $1) (result i32)
;; CHECK-NEXT: (local $0 i32)
;; CHECK-NEXT: (local.set $0
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (i32.const 7)
;; CHECK-NEXT: )
(func $bar (param $x i32) (result i32)
Expand All @@ -436,9 +415,6 @@

;; CHECK: (func $foo (type $T) (result i32)
;; CHECK-NEXT: (local $0 i32)
;; CHECK-NEXT: (local.set $0
;; CHECK-NEXT: (i32.const 42)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (return_call_indirect $0 (type $T)
;; CHECK-NEXT: (i32.const 0)
Expand Down Expand Up @@ -669,22 +645,17 @@

;; CHECK: (func $0 (type $0)
;; CHECK-NEXT: (local $0 i32)
;; CHECK-NEXT: (local.set $0
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: (block
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block
;; CHECK-NEXT: (block
;; CHECK-NEXT: (block
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: (return)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: (return)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (return)
;; CHECK-NEXT: )
;; CHECK-NEXT: (return)
;; CHECK-NEXT: )
(func $0 (param $0 i32) (result i32)
;; The returns here are nested in each other, and one is a recursive call to
Expand Down Expand Up @@ -835,15 +806,7 @@
;; CHECK-NEXT: (local $0 i64)
;; CHECK-NEXT: (local $1 i64)
;; CHECK-NEXT: (local $2 v128)
;; CHECK-NEXT: (local.set $0
;; CHECK-NEXT: (i64.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (block
;; CHECK-NEXT: (local.set $1
;; CHECK-NEXT: (i64.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
(func $target (param $0 i64) (param $1 v128) (param $2 i64) (result f32)
;; All parameters here should vanish.
Expand Down
3 changes: 0 additions & 3 deletions test/lit/passes/dae_tnh.wast
Original file line number Diff line number Diff line change
Expand Up @@ -116,9 +116,6 @@

;; CHECK: (func $target (type $0) (param $0 i32)
;; CHECK-NEXT: (local $1 f64)
;; CHECK-NEXT: (local.set $1
;; CHECK-NEXT: (f64.const 4.2)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (local.get $0)
;; CHECK-NEXT: )
Expand Down
3 changes: 0 additions & 3 deletions test/lit/passes/signature-pruning.wast
Original file line number Diff line number Diff line change
Expand Up @@ -1309,9 +1309,6 @@

;; CHECK: (func $other (type $other)
;; CHECK-NEXT: (local $0 anyref)
;; CHECK-NEXT: (local.set $0
;; CHECK-NEXT: (ref.null none)
;; CHECK-NEXT: )
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: )
(func $other (type $other) (param anyref)
Expand Down
Loading
Loading