This is an archive of the discontinued LLVM Phabricator instance.

[LangRef] Require elementtype attribute for gc.statepoint intrinsic
ClosedPublic

Authored by nikic on Jan 21 2022, 6:52 AM.

Details

Summary

The gc.statepoint intrinsic currently determines the target function type based on the pointer element type of the argument. In order to support opaque pointers, require that the argument is annotated with an elementtype attribute.

This is just the LangRef change, this will require followup changes to update tests, the IR verifier and the statepoint code.

Here's an example of the change:

; Before:
  %safepoint_token = tail call token (i64, i32, i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i64 0, i32 0, i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 0)
; After:
  %safepoint_token = tail call token (i64, i32, i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i64 0, i32 0, i1 ()* elementtype(i1 ()) @return_i1, i32 0, i32 0, i32 0, i32 0)
; After with opaque pointers:
  %safepoint_token = tail call token (i64, i32, i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(i1 ()) @return_i1, i32 0, i32 0, i32 0, i32 0)

Diff Detail

Event Timeline

nikic created this revision.Jan 21 2022, 6:52 AM
nikic requested review of this revision.Jan 21 2022, 6:52 AM
Herald added a project: Restricted Project. · View Herald TranscriptJan 21 2022, 6:52 AM
dblaikie accepted this revision.Jan 21 2022, 9:38 AM
dblaikie added a subscriber: dblaikie.

Generally sounds OK to me. (not sure what we do historically for these sort of changes - but I'd guess the documentation usually comes after the functionality (or in the same patch) rather than before - it might be relevant to see what test case cleanup looks like, etc, to evaluate the direction. But I don't mind too much - may be worth waiting to commit this until a few of the other patches in the series are available/reviewed)

This revision is now accepted and ready to land.Jan 21 2022, 9:38 AM
reames requested changes to this revision.Jan 21 2022, 9:55 AM

What piece of code are you trying to remove? I don't think we need this change unless I'm missing something. The callee return type should already be encoded in the signature of the associated gc.result.

I definitely would not want this landing without the associated builder and test changes.

This revision now requires changes to proceed.Jan 21 2022, 9:55 AM

What piece of code are you trying to remove? I don't think we need this change unless I'm missing something. The callee return type should already be encoded in the signature of the associated gc.result.

Yes, the callee return type is the important bit. Thanks for the suggestion on using the gc.result type for this purpose. Something I'm not quite clear on is whether a gc.statepoint with a non-void callee is required to also have a gc.result use? And if not, whether it is fine to simply lower the call with a void result instead?

I definitely would not want this landing without the associated builder and test changes.

I'm mainly interested in feedback on the general direction here, before I spend a lot of time updating tests.

nikic added a comment.Jan 24 2022, 3:13 AM

@reames I tried using the gc.result type (https://gist.github.com/nikic/703794bdf8ab04c4a4ca40c4145a1f90), but this did result in codegen changes. In particular, if there is no gc.result use, but the function is non-void, then we no longer have the implicit-def dead $eax on the statepoint (see the last two test changes).

I'm not familiar with the area, but I assume that would be incorrect, as we lose the knowledge that the register may be clobbered by the call?

@nikic I will take an action item to remove the use of the pointer type. I'm pretty sure I can, just need to sit down and remind myself how the code works again. This week is absolutely *crazy* for me in terms of personal life, so it probably won't happen until a week or so out.

reames accepted this revision.Jan 31 2022, 11:09 AM

Ok, I got back to this today. Short version, Nikita was right all along, and this patch is now LGTM.

Longer version...

I landed 57cf29a and 6e4f7c08 which removed two uses of getActualReturnType. These two are safe to drive from the type of the gc.result, since the code is unreachable if there isn't a gc.result present.

However, the remaining case can't be removed. Specifically, we need to know the result type to know which phys regs are being clobbered by the call; that's a function of calling convention and call site signature (i.e. return type).

Given that, we have two options:

  1. Require that the optimize preserve a gc.result if initially present. This requires us not to recognize such calls as dead, and generally complicates the code to preserve optimizations we get for "free" today.
  2. We find a way to express the type in the callsite again.

This patch implements (2), and does so in what appears to be a newly idiomatic way for opaque pointers. (I'd missed that previously.) As such, this looks like an utterly reasonable solution.

@nikic, are you going to follow up with the code changes to RS4GC and the IRBuilder interface? Or would you like me to do so?

This revision is now accepted and ready to land.Jan 31 2022, 11:09 AM
This revision was landed with ongoing or failed builds.Feb 4 2022, 12:47 AM
This revision was automatically updated to reflect the committed changes.