This is an archive of the discontinued LLVM Phabricator instance.

Register Calling Convention, Clang changes
ClosedPublic

Authored by erichkeane on Oct 3 2016, 11:26 AM.

Details

Summary

The Register Calling Convention (RegCall) was introduced by Intel to optimize parameter transfer on function call.
This calling convention ensures that as many values as possible are passed or returned in registers.

The following review presents the basic additions to the Clang Front-end in order to support RegCall in X86.

See https://reviews.llvm.org/D25022 for CodeGen changes

Diff Detail

Repository
rL LLVM

Event Timeline

erichkeane updated this revision to Diff 73309.Oct 3 2016, 11:26 AM
erichkeane retitled this revision from to Register Calling Convention, Clang changes.
erichkeane updated this object.
erichkeane set the repository for this revision to rL LLVM.
ABataev added a subscriber: ABataev.Oct 4 2016, 2:45 AM

Eric, please, prepare a full context review!

lib/AST/ItaniumMangle.cpp
1417–1421 ↗(On Diff #73309)

Single-line substatements must not be enclosed into braces

1418 ↗(On Diff #73309)

Line is not clang-formatted

lib/AST/Mangle.cpp
70 ↗(On Diff #73309)

Seems to me this change is not required

lib/AST/MicrosoftMangle.cpp
440 ↗(On Diff #73309)

No changes here, restore original line

Hi Alexey-
Can you let me know what you mean by "Full Context Review"? I'm unfamiliar with that process. The other fixes I'll look at today.

erichkeane updated this revision to Diff 73489.Oct 4 2016, 8:41 AM
erichkeane removed rL LLVM as the repository for this revision.
erichkeane marked 4 inline comments as done.

Updated the code, fixed Alexey's concerns. Thanks again for the comments!

Hi Alexey-
Can you let me know what you mean by "Full Context Review"? I'm unfamiliar with that process. The other fixes I'll look at today.

Check this page http://llvm.org/docs/Phabricator.html
use

git diff -U999999 other-branch

or

svn diff --diff-cmd=diff -x -U999999
erichkeane updated this revision to Diff 73490.Oct 4 2016, 8:53 AM

Did a full context diff, as requested.

ABataev added inline comments.Oct 4 2016, 9:16 AM
lib/Sema/SemaDeclAttr.cpp
3833–3837 ↗(On Diff #73490)

Not formatted

ABataev added inline comments.Oct 4 2016, 9:16 AM
include/clang-c/Index.h
3029 ↗(On Diff #73490)

Maybe it is better to use 8, as the previous comment allows it?

/* Value 8 was PnaclCall, but it was never used, so it could safely be re-used. */

In this case you don't need to increase number of bits used for calling conventions

lib/AST/ItaniumMangle.cpp
1236–1237 ↗(On Diff #73490)

What if function type is not a FunctionProtoType?

lib/AST/MicrosoftMangle.cpp
435–436 ↗(On Diff #73490)

Again, what if type is not FunctionProtoType?

lib/CodeGen/TargetInfo.cpp
1546–1548 ↗(On Diff #73490)

Seems to me this code is clang-formatted

3301–3303 ↗(On Diff #73490)

No braces

3388–3392 ↗(On Diff #73490)

Not clang-formatted and extra braces

lib/Sema/SemaDecl.cpp
8288 ↗(On Diff #73490)

Is this formatted?

rnk added a subscriber: rnk.Oct 4 2016, 9:38 AM
rnk added inline comments.
include/clang/Basic/AttrDocs.td
1263 ↗(On Diff #73490)

"aims"

lib/CodeGen/TargetInfo.cpp
3306 ↗(On Diff #73490)

You might want to defend against dynamic C++ records which will have vtable fields.

3323 ↗(On Diff #73490)

This code doesn't need to worry about windows.h defining max.

3388–3389 ↗(On Diff #73490)

not llvm style

3742–3743 ↗(On Diff #73490)

'classify' takes FreeSSERegs by reference and modifies it, so are you sure this is correct? It means if I have this kind of prototype, we won't pass 'd' in registers because we'll consume four registers for the return value:

struct HFA { __m128 f[4]; };
HFA __regcall f(HFA a, HFA b, HFA c, HFA d) {
  ...
}
lib/Sema/SemaDecl.cpp
8288 ↗(On Diff #73490)

The comment doesn't apply here. Are you sure you don't want some other behavior, like unprototyped functions are actually implicitly void when regcall is used, as in C++?

erichkeane marked 11 inline comments as done.Oct 4 2016, 9:56 AM

New patch incoming.

lib/AST/ItaniumMangle.cpp
1236–1237 ↗(On Diff #73490)

Right, good catch. I looked at Mangle.cpp which does something very similar, and assumes that FunctionType is a valid cast here, so I've switched this here too, please let me know if that is a wrong assumption.

lib/CodeGen/TargetInfo.cpp
3306 ↗(On Diff #73490)

Hmmm... I'm not sure what behavior would be expected in that case. Also, I just looked at a bunch of similar 'for' loops for various other reasons, and I don't really see where that is tested elsewhere (so I don't really see how to, besides I.isVirtual?). In that case, I would suspect that the class is not put into a register?

3742–3743 ↗(On Diff #73490)

That was my intent, this should allow return values to be in registers as well if I'm reading the spec correctly. The idea is that register use is 'greedy'.

lib/Sema/SemaDecl.cpp
8288 ↗(On Diff #73490)

I suspect you're right. I am not sure what behavior would be expected, so I think that reverting to the error case is likely the correct "safe" behavior if the spec doesn't say otherwise?

erichkeane updated this revision to Diff 73507.Oct 4 2016, 10:32 AM
erichkeane marked an inline comment as done.

Fixes based on Alexey/Ried's feedback

rnk added inline comments.Oct 4 2016, 10:39 AM
lib/CodeGen/TargetInfo.cpp
3742–3743 ↗(On Diff #73490)

But, if the return value is returned directly, it doesn't conflict with the free parameter registers. In my example, the return value can use XMM0-3 and the parameters can use XMM0-15. Can you add this test case and validate that it does what you want?

erichkeane added inline comments.Oct 4 2016, 10:45 AM
lib/CodeGen/TargetInfo.cpp
3742–3743 ↗(On Diff #73490)

Ah, I see what you mean now. That definitely sounds like the right way to go about it. I'll add a test and validate my assumptions. Thanks for putting up with my misunderstanding.

rnk added inline comments.Oct 4 2016, 10:53 AM
lib/AST/ItaniumMangle.cpp
1203 ↗(On Diff #73507)

What mangling should happen for operator overloads and all other kinds of DeclarationName? Please add tests for these cases

1236–1237 ↗(On Diff #73490)

IMO this would be simpler if we did:

if (IsRegCall)
  mangleRegCallName(II); // implement this elsewhere
else
  mangleSourceName(II);

I don't like that the standard mangleSourceName as you have it has to be concerned with IsRegCall. Without your change, it is a simple function that clearly expresses that the basic unit of Itanium name mangling is decimal length prefixed strings.

lib/CodeGen/TargetInfo.cpp
3306 ↗(On Diff #73490)

You don't need to check if each base is dynamic, just check CXXRD->isDynamicClass() and make it return indirectly if so.

1954 ↗(On Diff #73507)

format

3297 ↗(On Diff #73507)

Please name variables in LLVM style

3321 ↗(On Diff #73507)

variable naming

3352–3354 ↗(On Diff #73507)

Since you're touching most of this, can you make this code standardize on LLVM's variable naming convention: http://llvm.org/docs/CodingStandards.html#name-types-functions-variables-and-enumerators-properly

majnemer added inline comments.
lib/AST/ItaniumMangle.cpp
1413–1414 ↗(On Diff #73507)

I'd add an overload of mangleSourceName which takes a Twine. Then the one caller which passes isRegCall would merely concat the identifier with regcall3. The existing implementation using IdentifierInfo would merely pass in II->getName for the Twine.

majnemer added inline comments.Oct 4 2016, 11:01 AM
lib/AST/ItaniumMangle.cpp
1234 ↗(On Diff #73507)

auto *

1235 ↗(On Diff #73507)

The convention is to just do FD instead of (FD != nullptr)

erichkeane marked 16 inline comments as done.Oct 4 2016, 5:54 PM

Commenting to save my comments (don't seem to survive a refresh). Still working on non-function mangling.

lib/AST/ItaniumMangle.cpp
1203 ↗(On Diff #73507)

Test cases show that I need to implement these. Going to quit for the evening, but will continue working on this tomorrow.

1413–1414 ↗(On Diff #73507)

I really like this idea, and had most of an implementation, however it seems that Twine has no real good way to get its 'length', so it required a temporary for the sake of getting the length. Instead I ended up with Ried's suggestion of separate functions for each.

lib/CodeGen/TargetInfo.cpp
3742–3743 ↗(On Diff #73490)

I added it to the C test, and was convinced that you're right. Fixed, thanks!

oren_ben_simhon added inline comments.Oct 5 2016, 5:25 AM
include/clang/Basic/AttrDocs.td
1267 ↗(On Diff #73507)

You might want to use the following link instead because it is most updated: https://software.intel.com/en-us/node/693069

lib/CodeGen/TargetInfo.cpp
3352 ↗(On Diff #73507)

According to the ABI, there are 12 free int regs for windows and 11 free int regs for non-windows (linux, OSX, etc). Is that taken into account somewhere?

3732 ↗(On Diff #73507)

Maybe i misinterpret the comment, but AFAIK, RegCall gives us 16 SSE registers for each (return values and passed arguments)

test/CodeGen/regcall.c
26 ↗(On Diff #73507)

I see that expended structures don't get InReg attribute. IMHO, If you know that the value should be saved in register then you InReg attribute should be added.

ABataev added inline comments.Oct 5 2016, 6:46 AM
include/clang/AST/Type.h
1381 ↗(On Diff #73507)

Erich, do you really need this? You don't increase number of required bits anymore, so this code must be restored

2909–2921 ↗(On Diff #73507)

Also, you don't need these changes anymore

lib/AST/MicrosoftMangle.cpp
434 ↗(On Diff #73507)

auto*

lib/CodeGen/CodeGenModule.cpp
686 ↗(On Diff #73507)

const auto *FD

lib/CodeGen/TargetInfo.cpp
1546–1548 ↗(On Diff #73490)

I mean, did you try to reformat the whole return statement? It looks ugly

3321 ↗(On Diff #73507)

I believe the whole patch must be clang-tided

erichkeane marked 9 inline comments as done.Oct 5 2016, 8:44 AM
erichkeane added inline comments.
include/clang/Basic/AttrDocs.td
1267 ↗(On Diff #73507)

This has changed 2x since I started this project. Is there a way to get a STABLE link? I imagine that much of this documentation is filled with broken links (since MSDN breaks them constantly), but don't really want to add to it.

lib/CodeGen/TargetInfo.cpp
3352 ↗(On Diff #73507)

Yes. There are separate ABIInfo types for windows.

3732 ↗(On Diff #73507)

I'd misread that in the spec and Ried corrected my implementation below. Updating the comment.

test/CodeGen/regcall.c
26 ↗(On Diff #73507)

I am not sure that is the case. That behavior doesn't happen in vectorcall seemingly.

erichkeane updated this revision to Diff 73716.Oct 5 2016, 6:06 PM
erichkeane marked 6 inline comments as done.

Updated tests to properly show mangling for C++ types. Required some fixes. Note that the decorating of names doesn't match ICC in non-named functions due to a bug in ICC, and the spec is silent about it, so this patch decorates them in the way that best fits the spec.

oren_ben_simhon added inline comments.Oct 6 2016, 1:11 AM
include/clang/Basic/AttrDocs.td
1267 ↗(On Diff #73507)

I am not sure if there is a constant link to the latest and greatest. When i contacted the documentation team they pointed me to the latest published compiler documention version 16

Quick point i meant to post earlier Couldn't change ExtInfo size.

include/clang/AST/Type.h
1381 ↗(On Diff #73507)

After much debugging, I realized that this does NOT store the enum from above, it stores the CallingConv from include/clang/Basic/Specifiers.h, which we actually HAVE put over 16. I didn't see anything that we could lose from that enum to replace it however.

I'm going to need to pump-the-brakes on this for a little bit. The name-decoration work I did here highlighted a number of issues with that section of the spec. We're currently considering rev'ing the spec to properly name mangle/decorate when C++ and Microsoft is ready.

In the meantime, the LLVM changes are unaffected.

After much debate, the architects have agreed to change the "Decoration" section to the following.

The next patch does these, so I'm ready for continued review. Thanks for your patience!
-Erich

regcall Decoration
Names of functions that use
regcall are decorated. This helps avoid improper linking with a function using a different calling convention.
The name of a C function is prefixed with regcalln. For example, the name foo would be decorated as follows: regcall3foo. The n part of the decoration specifies the version of the regcall convention in effect (the current convention revision number is 3). In a GCC compatibility environment, this decoration is also done for a C++ function or template function whose function or template name is an identifier (excluding constructors and operator functions, for example); this happens before C++ name mangling.
In a Microsoft compatibility environment, C++ name mangling uses the (lower case) letter w to encode revision 3 of the
regcall calling convention.

erichkeane updated this revision to Diff 75903.Oct 26 2016, 9:22 AM

Corrected Decoration settings to match the soon-to-be-updated spec.

rnk added inline comments.Oct 26 2016, 9:50 AM
include/clang/Basic/AttrDocs.td
1263 ↗(On Diff #75903)

If you want __regcall to appear as a link, you want to put backticks and around it and underscore after it, like is done for __fastcall above:

`__regcall`_
1265 ↗(On Diff #75903)

I don't think you need this trailing single quote.

lib/AST/MicrosoftMangle.cpp
2006 ↗(On Diff #75903)

Update the EBNF comment

lib/CodeGen/TargetInfo.cpp
3324 ↗(On Diff #75903)

This will return false for class fields, which I don't think you want. You probably want to do this for record types that aren't unions.

3396 ↗(On Diff #75903)

You probably wanted isRecordType().

majnemer added inline comments.Oct 26 2016, 10:52 AM
lib/AST/MicrosoftMangle.cpp
433 ↗(On Diff #75903)

Please remove this stray newline.

lib/CodeGen/TargetInfo.cpp
3333 ↗(On Diff #75903)

I think UINT_MAX is more popular than using std::numeric_limits for this purpose in LLVM/Clang.

3337–3338 ↗(On Diff #75903)
erichkeane marked 8 inline comments as done.Oct 26 2016, 11:09 AM

New diff coming that fixes Reid & David's comments

joerg added a subscriber: joerg.Oct 26 2016, 2:12 PM

Can we please avoid adding more (pseudo) keywords in the double-underscore name space? Those tend to be used a lot by existing libc implementations and existing attribute cases like strong and weak have created enough trouble.

I guess I'm not sure how to respond to that... Calling conventions traditionally use double underscore to prevent from stomping on user keywords. Additionally, this is in a specification that has an existing implementation available, so I'm not sure what could be done.

The __ namespace is reserved for us and I can't imagine how __regcall would upset any existing code out there.

dschuff removed a subscriber: dschuff.Oct 27 2016, 11:43 AM

The __ namespace is shared between all parts of the implementation, not just the compiler. The convention in the past was that compiler keywords will end in a __ as well, but calling conventions and Objective C broke that convention. I still think it is something that should be avoided when possible.

rnk added a comment.Oct 27 2016, 2:56 PM

Remember the fight over _Atomic with MSVC's STL? The fallacy of the implementer's namespace is that there is only one implementer.
https://llvm.org/bugs/show_bug.cgi?id=19043

We should prefer adding __attribute__s and __declspecs instead of keywords when possible.

In D25204#581469, @rnk wrote:

Remember the fight over _Atomic with MSVC's STL? The fallacy of the implementer's namespace is that there is only one implementer.
https://llvm.org/bugs/show_bug.cgi?id=19043

We should prefer adding __attribute__s and __declspecs instead of keywords when possible.

In general, I can see the benefit of this rule, however in the case of calling conventions, I would think that keeping them all orthogonal is important. Having "most" calling conventions work one way, and a couple a different way seems like a bigger problem.

rnk added a comment.Oct 27 2016, 3:24 PM

In general, I can see the benefit of this rule, however in the case of calling conventions, I would think that keeping them all orthogonal is important. Having "most" calling conventions work one way, and a couple a different way seems like a bigger problem.

I agree. I don't think introducing a __regcall keyword is going to cause much real world breakage.

include/clang/Basic/Attr.td
815 ↗(On Diff #75919)

Can we not add the single underscore keyword version? That's outside the implementer's namespace.

erichkeane updated this revision to Diff 76117.Oct 27 2016, 3:39 PM
erichkeane marked an inline comment as done.

Remove single-underscore version of _regcall kw.

@rnk, @majnemer and @ABataev : I believe that I've done everything that has come up in review, and this passes all tests for the convention I can find. Do you guys see anything that is holding this patch up? What is otherwise the 'next step' in getting this into master?

erichkeane updated this revision to Diff 76717.Nov 2 2016, 9:11 AM

It was brought to my attention that regcall isn't a calling convention that should cause MSVC to switch to C++ mangling. Switched that and updated the tests.

rnk accepted this revision.Nov 2 2016, 10:33 AM
rnk added a reviewer: rnk.

Looks good to me.

This revision is now accepted and ready to land.Nov 2 2016, 10:33 AM
This revision was automatically updated to reflect the committed changes.