This is an archive of the discontinued LLVM Phabricator instance.

[RISCV] Permit tail call to an externally-defined function with weak linkage
ClosedPublic

Authored by liaolucy on Feb 1 2023, 10:12 PM.

Details

Summary

As described in D45395 This has been modeled after ARM's tail call opt.
ARM's abi seems to limit weak symbol.

I did not find the limitation for RISCV. (Please correct me if I am wrong)

gcc seems to use the tail-call opt: https://godbolt.org/z/bjWE68n5o

Diff Detail

Event Timeline

liaolucy created this revision.Feb 1 2023, 10:12 PM
Herald added a project: Restricted Project. · View Herald TranscriptFeb 1 2023, 10:12 PM
liaolucy requested review of this revision.Feb 1 2023, 10:12 PM
reames added a subscriber: reames.EditedFeb 2 2023, 7:58 AM

I don't believe this is, in general, legal to do for RISCV psABI. The problem is that a weak symbol can resolve to the address 0, and that 0 may be outside the addressable range of a pcrelative call/branch sequence. There is disagreement between the linkers as to whether such sequences should be rewritten to a different instruction sequence. For non-tail calls, we end up emitting an explicit load through the GOT and call sequence.

Note that this concern does not apply in all code models. (I believe medlow is not effected, but double check!) You can look at the code which emits the GOT lookup for general calls, and there's probably cases where we can emit the direct tail call. We just need to restrict it appropriately.

p.s. Your example with gcc is a static (not pc relative) call.

reames requested changes to this revision.Feb 2 2023, 7:58 AM
This revision now requires changes to proceed.Feb 2 2023, 7:58 AM
MaskRay accepted this revision.EditedFeb 2 2023, 10:05 AM

I don't believe this is, in general, legal to do for RISCV psABI. The problem is that a weak symbol can resolve to the address 0, and that 0 may be outside the addressable range of a pcrelative call/branch sequence. There is disagreement between the linkers as to whether such sequences should be rewritten to a different instruction sequence. For non-tail calls, we end up emitting an explicit load through the GOT and call sequence.

Note that this concern does not apply in all code models. (I believe medlow is not effected, but double check!) You can look at the code which emits the GOT lookup for general calls, and there's probably cases where we can emit the direct tail call. We just need to restrict it appropriately.

p.s. Your example with gcc is a static (not pc relative) call.

@reames I think this change is fine. call and tail use the same relocation type. The "zero target address, possibly not reachable by the relocated location" issue only applies to possibly address significant relocation types.
Branch relocations are not address significant and linkers can resolve the relocation to the current location (infinite loop if executed) to avoid relocation out-of-range errors (see D103001).

reames resigned from this revision.Feb 2 2023, 11:14 AM

Removing myself as reviewer to remove the "Needs Changes" bit. I'm explicitly deferring to @MaskRay as he's much more knowledgeable here than I am. If he says this is fine; it's fine.

This revision is now accepted and ready to land.Feb 2 2023, 11:14 AM