Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make more Ifs unreachable #7094

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open

Make more Ifs unreachable #7094

wants to merge 7 commits into from

Conversation

tlively
Copy link
Member

@tlively tlively commented Nov 20, 2024

Previously the only Ifs that were typed unreachable were those in which
both arms were unreachable and those in which the condition was
unreachable that would have otherwise been typed none. This caused
problems in IRBuilder because Ifs with unreachable conditions and
value-returning arms would have concrete types, effectively hiding the
unreachable condition from the logic for dropping concretely typed
expressions preceding an unreachable expression when finishing a scope.

Relax the conditions under which an If can be typed unreachable so that
all Ifs with unreachable conditions or two unreachable arms are typed
unreachable. Propagating unreachability more eagerly this way makes
various optimizations of Ifs more powerful. It also requires new
handling for unreachable Ifs with concretely typed arms in the Printer
to ensure that printed wat remains valid.

Previously the only Ifs that were typed unreachable were those in which
both arms were unreachable and those in which the condition was
unreachable that would have otherwise been typed none. This caused
problems in IRBuilder because Ifs with unreachable conditions and
value-returning arms would have concrete types, effectively hiding the
unreachable condition from the logic for dropping concretely typed
expressions preceding an unreachable expression when finishing a scope.

Relax the conditions under which an If can be typed unreachable so that
all Ifs with unreachable conditions or two unreachable arms are typed
unreachable. Propagating unreachability more eagerly this way makes
various optimizations of Ifs more powerful. It also requires new
handling for unreachable Ifs with concretely typed arms in the Printer
to ensure that printed wat remains valid.
@tlively tlively requested a review from kripken November 20, 2024 02:15
auto* ret =
builder.makeSequence(builder.makeDrop(curr->condition), curr->ifTrue);
builder.makeSequence(builder.makeDrop(curr->condition), ifTrue);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reading this code and the updated test following it, I still don't understand the change. The code looks valid before and after, and perhaps it is slightly more optimal to add a drop here rather than to wait for another pass to do it, but is it worth the complexity? Is there another reason I haven't considered?

Copy link
Member Author

@tlively tlively Nov 20, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We get a validation error without inserting the drop. Without this change, we parse this wat:

(func $foo (result i32)
  i32.const 0
  unreachable
  if (result i32)
    i32.const 1
  else
    i32.const 2
  end
)

into this IR:

(func $foo (result i32)
  (i32.const 0) ;; Validation error!
  (if (result i32)
    (unreachable)
    (then
       (i32.const 1)
    )
    (else 
       (i32.const 2)
    )
  )
)

This IR is invalid because the function body block has a non-final item with a concrete type. The IR should have contained a drop of that i32.const 0.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, this response wasn't specific to the CodeFolding logic, but it has a similar problem.

Down below we have ref->finalize(curr->type). If curr->type is Type::unreachable, then it was previously the case that curr->ifTrue must have been type none or unreachable, but now it can be any type. Finalizing a sequence block where the second item has type e.g. i32 as unreachable is not valid, so to fix it we have to drop that second item.

Copy link
Member

@kripken kripken left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm % comment

auto* ifTrue = curr->ifTrue;
if (curr->type == Type::unreachable && curr->ifTrue->type.isConcrete()) {
ifTrue = builder.makeDrop(ifTrue);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can use Builder's method dropIfConcretelyTyped

@tlively
Copy link
Member Author

tlively commented Nov 20, 2024

Thanks! I'm still finding fuzz bugs with this, so I'll ping you explicitly for final review once the fixes are in.

@tlively
Copy link
Member Author

tlively commented Nov 21, 2024

@kripken, this should be good to go now. PTAL at the changes since your last review. I'll continue fuzzing overnight before landing this, though.

tlively added a commit that referenced this pull request Nov 23, 2024
Code folding does not support folding tails that produce concrete
values, but it previously did not check for this condition when deciding
whether to attempt to code fold ifs. As a result, code folding would
proceed on ifs with concretely typed arms. The incorrect block types
produced by the folding logic as a result of the violated assumption
that the folded tails would never produce concrete values were papered
over by later refinalization, so this never caused problems.

However, an upcoming change (#7094) that relaxes the typing of ifs to
allow them to be unreachable whenever their conditions are unreachable
makes it possible for the violated assumptions in code folding to cause
problems that are not fixed by refinalization. Fix code folding to
disallow folding of concretely typed if arms and add a test that would
fail once #7094 lands without this fix.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants