This is an archive of the discontinued LLVM Phabricator instance.

Fix x86/x86_64 calling convention for _ExtInt
ClosedPublic

Authored by erichkeane on Apr 23 2020, 8:39 PM.

Details

Summary

After speaking with Craig Topper about some recent defects, he pointed
out that _ExtInts should be passed indirectly if larger than the largest
int register, and like ints when smaller than that. This patch
implements that.

Note that this changed the way vaargs worked quite a bit, but they still
work.

Diff Detail

Event Timeline

erichkeane created this revision.Apr 23 2020, 8:39 PM
Quuxplusone added inline comments.
clang/lib/CodeGen/TargetInfo.cpp
2804

Asking silly questions because I don't stand a chance of understanding either the code or the tests...

In the x86-64 ABI, an ordinary 16-byte struct would be passed in rdi/rsi and returned in rdx/rax. An ordinary 17-byte struct would be passed by hidden reference and returned by hidden reference.

Is your intent here that _ExtInt will follow the same convention, i.e., _ExtInt(128) will be passed in rdi/rsi and returned in rdx/rax? and _ExtInt(129) will be passed and returned by hidden reference?

Clang trunk currently passes _ExtInt(256) in rdi/rsi/rdx/rcx/r8/r9/stack as if it were a series of uint64_ts. (I hadn't noticed until now.) That's kind of cute. Is the current PR motivated by performance concerns with the multi-uint64_t approach, or just trying to be consistent with the struct rules?

I think you're missing a check for ExtInt in X86_64ABIInfo::getIndirectReturnResult

erichkeane marked an inline comment as done.Apr 24 2020, 6:49 AM
erichkeane added inline comments.
clang/lib/CodeGen/TargetInfo.cpp
2804

Yes, that is my intent. The bug you filed apparently showed why putting it in registers is perhaps a bad idea (for something that large), AND gets us more consistent with structs.

As there is no official ABI for any of the 3 platforms, this seems more consistent and gives performance benefit. @craig.topper can explain this part better than me.

Handle indirect return as well. @craig.topper : Anything else you can think of?

Is there something currently restricting these types to just x86, or do you need to do a much broader audit?

clang/lib/CodeGen/TargetInfo.cpp
2981

Presumably *some* ExtInt types should be returned directly.

erichkeane marked an inline comment as done.Apr 24 2020, 10:22 AM
erichkeane added inline comments.
clang/lib/CodeGen/TargetInfo.cpp
2981

Right, and they are. This is only for cases where we request an 'indirect result', so cases where we've already decided that it cannot be passed direct.

At this point, the 'classify' step has already been done, which would have decided that <=128 bit values are passed 'direct', and we've requested an indirect. At least as far as I can tell from this code/debugging.

rjmccall added inline comments.Apr 26 2020, 9:44 PM
clang/lib/CodeGen/TargetInfo.cpp
2981

Oh, I see. So the current code is intentionally using a direct IR return in some cases and then allowing LLVM to lower it as an indirect return? I didn't think we ever did that, and I'm really not sure it's a good idea, so I definitely agree with not doing it for ExtInt types.

erichkeane marked an inline comment as done.Apr 27 2020, 6:06 AM
erichkeane added inline comments.
clang/lib/CodeGen/TargetInfo.cpp
2981

Right, exactly :) FWIW, this is my 3rd time looking into this TargetInfo code, and it is particularly convoluted. If I understood the calling conventions sufficiently, I'd take a run at trying to figure out how to make this not so messy.

@craig.topper Did this look OK/ Is there anything else you want from this?

This revision is now accepted and ready to land.Apr 29 2020, 9:44 AM

Could you answer my question up-thread about whether ExtInt is currently target-limited? If it isn't, we need to more broadly audit targets.

Could you answer my question up-thread about whether ExtInt is currently target-limited? If it isn't, we need to more broadly audit targets.

Yikes! I missed that question, I'm sorry :/

We aren't limiting it, as it is supposed to be a C language feature (and in fact, is more useful certain on non-x86 chips!). We likely need an audit, though in TargetInfo I didn't see any other 'classify' functions other than these 3 (X86, x86-64Win, x86-64-Linux).

This revision was automatically updated to reflect the committed changes.
Herald added a project: Restricted Project. · View Herald TranscriptApr 29 2020, 11:17 AM

Every target does something similar, they just all do it in different ways because they're mostly written by different people.

We should restrict this feature to targets where we've adequately audited the ABI. It's not a feature until the ABI work is done.

Every target does something similar, they just all do it in different ways because they're mostly written by different people.

We should restrict this feature to targets where we've adequately audited the ABI. It's not a feature until the ABI work is done.

I'm discovering that now :) I'm currently trying to do said audit by going down the ABIInfo inheritance tree. I believe we have at least a month until the next release branch date. If you can help keep me honest here, I'll disable _ExtInt for any platforms I haven't done by then at the branch.

Does that seem acceptable?

Every target does something similar, they just all do it in different ways because they're mostly written by different people.

We should restrict this feature to targets where we've adequately audited the ABI. It's not a feature until the ABI work is done.

I'm discovering that now :) I'm currently trying to do said audit by going down the ABIInfo inheritance tree. I believe we have at least a month until the next release branch date. If you can help keep me honest here, I'll disable _ExtInt for any platforms I haven't done by then at the branch.

Does that seem acceptable?

Yes, although, I think you ought to flip the default anyway just so we're doing the right thing for out-of-tree targets. It should then be very straightforward to flip it back target-by-target as you do your audit.

See my audit/WIP on calling conventions here: https://reviews.llvm.org/D79118

Alright then, I've disabled by default(911add149af563a5a61458de0dd730e3f5348623). I'll enable 1 at a time as I fix the calling conventions in D79118.