diff --git a/src/passes/RemoveUnusedBrs.cpp b/src/passes/RemoveUnusedBrs.cpp index a2961da3233..64da911a151 100644 --- a/src/passes/RemoveUnusedBrs.cpp +++ b/src/passes/RemoveUnusedBrs.cpp @@ -855,12 +855,13 @@ struct RemoveUnusedBrs : public WalkerPass> { void visitBrOn(BrOn* curr) { // Ignore unreachable BrOns which we cannot improve anyhow. Note that - // we must check the ref field manually, as we may be changing types as - // we go here. (Another option would be to use a TypeUpdater here - // instead of calling ReFinalize at the very end, but that would be more - // complex and slower.) + // we must check the ref and desc fields manually, as we may be changing + // types as we go here. (Another option would be to use a TypeUpdater + // here instead of calling ReFinalize at the very end, but that would be + // more complex and slower.) if (curr->type == Type::unreachable || - curr->ref->type == Type::unreachable) { + curr->ref->type == Type::unreachable || + (curr->desc && curr->desc->type == Type::unreachable)) { return; } diff --git a/test/lit/passes/remove-unused-brs-desc.wast b/test/lit/passes/remove-unused-brs-desc.wast index cdf63f2de36..4cdb1ea4ed2 100644 --- a/test/lit/passes/remove-unused-brs-desc.wast +++ b/test/lit/passes/remove-unused-brs-desc.wast @@ -783,4 +783,36 @@ ) ) ) + + ;; CHECK: (func $unreachable-desc (type $17) (param $any anyref) (param $d (ref (exact $super.desc))) (result anyref) + ;; CHECK-NEXT: (block $block (result (ref (exact $super.desc))) + ;; CHECK-NEXT: (block (result (ref (exact $super.desc))) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.tee $any + ;; CHECK-NEXT: (ref.i31 + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.get $d) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $unreachable-desc (param $any anyref) (param $d (ref (exact $super.desc))) (result anyref) + ;; The inner br_on_cast is optimized into an unconditional br, making the + ;; descriptor operand of the outer br_on_cast_desc_eq unreachable before + ;; ReFinalize runs. + (block $block (result anyref) + (br_on_cast_desc_eq $block anyref (ref null (exact $super)) + (local.tee $any + (ref.i31 + (i32.const 0) + ) + ) + (br_on_cast $block (ref (exact $super.desc)) (ref (exact $super.desc)) + (local.get $d) + ) + ) + ) + ) )