This is an archive of the discontinued LLVM Phabricator instance.

[WebAssembly] Implement ref.is_null MC layer support and codegen
ClosedPublic

Authored by asb on Apr 11 2022, 12:20 AM.

Details

Summary

Note: an earlier version of this patch was authored by @pmatos.

Custom type-checking is used to workaround the fact that separate variants of the instruction are defined for externref and funcref.

Diff Detail

Event Timeline

pmatos created this revision.Apr 11 2022, 12:20 AM
Herald added a project: Restricted Project. · View Herald TranscriptApr 11 2022, 12:20 AM
pmatos requested review of this revision.Apr 11 2022, 12:20 AM
Herald added a project: Restricted Project. · View Herald TranscriptApr 11 2022, 12:20 AM
pmatos planned changes to this revision.Apr 11 2022, 12:23 AM

A couple of weeks ago @asb pointed out we were missing an intrinsic for ref.is_null, so I got the work started. There's an issue with the polymorphic type for ref types, but I have seen this before and hopefully will get it fixed properly this time.

asb commandeered this revision.May 10 2022, 5:16 AM
asb edited reviewers, added: pmatos; removed: asb.
asb updated this revision to Diff 428347.May 10 2022, 5:21 AM
asb edited the summary of this revision. (Show Details)
asb added reviewers: sbc100, aheejin.

Commandeered, completed implementation, and updated summary to explain current implementation approach.

asb retitled this revision from [WebAssembly] Implement ref.is_null intrinstic to [WebAssembly] Implement ref.is_null MC layer support and codegen.May 10 2022, 5:23 AM
tlively accepted this revision.May 10 2022, 3:05 PM

LGTM! (with single comment)

llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmTypeCheck.cpp
325

How complicated would this be to fix? Is it worth fixing now?

This revision is now accepted and ready to land.May 10 2022, 3:05 PM
aheejin added inline comments.May 10 2022, 5:10 PM
llvm/lib/Target/WebAssembly/WebAssemblyInstrRef.td
30–32

Why should the stack version and the non-stack version separately? Doesn't I provide a template to define both at the same time? Maybe I'm not familiar with the context.

Also why is this isCodeGenOnly?

sbc100 added inline comments.May 10 2022, 5:55 PM
llvm/test/CodeGen/WebAssembly/ref-null.ll
48

Is there some reason why there are no expectations in the body here? (and above?

asb updated this revision to Diff 428581.May 11 2022, 12:56 AM
asb marked an inline comment as done.

Address review comments:

  • Move to using update_llc_test_checks.py for ref-null.ll (and therefore fix missing CHECK lines)
  • Add tighter error checking for ref.is_null in the wasm type checker
llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmTypeCheck.cpp
325

I'd initially skipped it due to planning to return to representation of reftypes in a bigger way. But you're right, it's not hard to provide a better message right now and I've done so by introducing a popRefType helper.

llvm/lib/Target/WebAssembly/WebAssemblyInstrRef.td
30–32

It does, but due to the way representation of reftypes is currently handled we want two register versions of the instruction (one for externref and one for funcref), but only one for the stack-based version (so ref.is_null can be printed/parsed in assembly). Marking the register instructions as isCodeGenOnly is consistent with what the I multiclass does (and correct, as the register instructions are really pseudo-instructions to bridge the gap between LLVM being register based on wasm being stack-based).

As I note in the patch summary I don't think this necessarily the globally optimum way of handling reftypes, but I want to save doing more invasive changes / refactoring until we've properly planned out handling of reftypes looking ahead to the typed function ref and GC proposals.

llvm/test/CodeGen/WebAssembly/ref-null.ll
48

That's an embarrassing oversight - thanks for catching!

I've updated this test case to use update_llc_test_checks.py (which it seems isn't compatible with -asm-verbose=false).

aheejin added inline comments.May 11 2022, 4:38 PM
llvm/lib/Target/WebAssembly/Utils/WebAssemblyTypeUtilities.h
83

Can this be just isRefType?

llvm/lib/Target/WebAssembly/WebAssemblyInstrRef.td
30–32

Why should there be only one stack variant? I think two different instructions can have the same name and opcode so they can be parsed and emitted fine?

asb updated this revision to Diff 428860.May 11 2022, 10:57 PM
asb edited the summary of this revision. (Show Details)
asb marked an inline comment as done.

Update based on review comments.

llvm/lib/Target/WebAssembly/Utils/WebAssemblyTypeUtilities.h
83

Good point, changed.

llvm/lib/Target/WebAssembly/WebAssemblyInstrRef.td
30–32

Hmm, you're right. I'd thought this approach would be cleaner, but as it requires custom type-checking anyway that's not really the case. I've moved to just allowing the overlapping definitions.

Thanks!

aheejin accepted this revision.EditedMay 12 2022, 11:47 AM

Thanks! I have one more question but don't want to hold this back with nitpicky things. (The review turnaround time due to time zone doesn't help either)

llvm/include/llvm/IR/IntrinsicsWebAssembly.td
34–37

Why do we need to specify names explicitly? Aren't these automatically named like these anyway?

asb marked an inline comment as done.May 12 2022, 10:20 PM
asb added inline comments.
llvm/include/llvm/IR/IntrinsicsWebAssembly.td
34–37

The default naming would call these 'llvm.wasm.ref.is.null.foo', and I think aligning to the is_null underlying instruction name is more intuitive.

asb added a comment.May 12 2022, 10:58 PM

Thanks! I have one more question but don't want to hold this back with nitpicky things. (The review turnaround time due to time zone doesn't help either)

Thanks for such helpful and responsive reviews! I've left a comment about why I'm overriding the default naming (basically is.null vs is_null).

This revision was landed with ongoing or failed builds.May 12 2022, 11:08 PM
This revision was automatically updated to reflect the committed changes.