New LLVM backend for Renesas RL78 MCU

Hello all,

For the past couple of months I've been writing a new llvm backend for Renesas RL78 MCU:
https://www.renesas.com/eu/en/products/microcontrollers-microprocessors/rl78.html
The software manual which contains all there is to know about RL78 is available here:
https://www.renesas.com/us/en/doc/products/mpumcu/doc/rl78/r01us0015ej0220_rl78.pdf

The motivation behind this is the following:
For the past 7 years I've been working on the Renesas RL78 and RX MCU ports in GCC (originally developed and maintained by Red Hat).
In case of RX I have no real issues with GCC as performance is similar to the RX commercial/proprietary compilers,
however in case of RL78 the performance(both code size and speed) of GCC is very poor it ranges from 20% to 300% worse compared to the RL78 commercial compilers (from Renesas and IAR Systems).

I'm still a few months away from upstreaming the port but the port is currently quite stable and performance is very similar to the commercial/proprietary compilers (the machine outliner is very effective as RL78 has a very limited instruction set), and there's still a lot of room for improvement.
Also I'm able to keep ABI compatibility with the commercial compilers and implement features (available in the commercial compilers) which I wasn't able to do in GCC although I tried really hard for years.
So I would like take this opportunity to say thank you to you all for making LLVM so great and ease to use and extend.

Although I'm looking at other targets and follow the guidelines if there are pointers/suggestions which people would like to share I'm happy to listen.

I would like to show just one short example which was my starting point and motivation to switch to LLVM:
char foo(char a, char b, char c, char d, char e, char f) {
return a + b + c + d + e + f;
}

This is what GCC produces (30 bytes and 18 clock cycles excluding the ret instruction)
_foo:
mova, [sp+14]
movc, a
mova, [sp+12]
adda, c
movc, a
mova, [sp+10]
adda, c
movc, a
mova, [sp+8]
adda, c
movc, a
mova, [sp+6]
adda, c
movc, a
mova, [sp+4]
adda, c
movr8, a
ret
While with I can produce the following output code (11 bytes and 5 clock cycles excluding the ret)
Notice also the ABI difference (with LLVM I was able to use the same ABI as the commercial compilers)
_foo:
add a, x
add a, c
add a, b
add a, e
add a, d
ret

Please note the following comments are more directed at clang and I apologize if I shouldn't post here at all, I will repost the second part on cfe-dev list as well, but the first part of the email is about the announcement of the port and I think it belongs here.

Because I aim to replace GCC with LLVM, I already implemented the GCC RL78 attributes (__attribute__) and builtin functions (__builtin_rl78_*) however I recently received a request which brings me to the reason why I'm writing today:
I was asked if I can implement the C Language extension from the Renesas CCRL (Renesas RL78 commercial compiler) in clang in order to close the gap between the two compilers.

In GCC I implemented one of them (#pragma address) but when I pushed it upstream it wasn't met with too much enthusiasm and it didn't get accepted. I ended up maintaining it locally among many other things which I didn't upstream which made updating to new versions of GCC difficult.
This is one very important thing which I would like to avoid in LLVM, I don't want to do something that would not be accepted upstream and end up in the same situation as I was with GCC.

My question here will be: are the following CCRL extensions acceptable to be implemented in clang? or will I find myself in the same situation as I am with GCC as they won't be accepted upstream? Especially since for most of them we already/can have alternative implementations using __attribute__ and other approaches more in line with clang extensions.

First things I would like to explain are the pragmas.
Most CCRL pragmas have a trait which is quite unusual: the first parameter is function or a variable name, for example in order to declare a interrupt functions while in GCC I do:
void inter ( void ) __attribute__((interrupt));
In CCRL this is declared the following way:
#pragma interrupt inter
void inter ( void ) {
}

I haven't checked the clang source code but I imagine it is not straight forward to tie a pragma to a particular function declaration as there are no other such pragmas as far as I'm aware.

The complete list of pragmas in question is:
#pragma interrupt [(]interrupt-handler-name[(interrupt-specification [,...])][)]
The equivalent of __attribute__((interrupt)) as discussed above.
#pragma interrupt_brk [(]interrupt-handler-name[(interrupt-specification[,...])][)]
The equvivalent of __attribute__((brk_interrupt)).
#pragma section [ section-type][ new-section-name] section-type:{text|const|data|bss}
#pragma inline [(]function-name [,...][)]
#pragma noinline [(]function-name [,...][)]
As the name says inline, noinline. We have inline, __inline and __inline__ keywords and __attribute__ ((always_inline)).
#pragma inline_asm [(]function-name [,...][)]
This pragma specifies the body of the function is assembly code.
I image substantial changes will be required in clang for this.
#pragma address [(]variable-name=absolute-address[,...][)]
This can be implemented with __attribute((section("section-name")) and then handling that section in the linker script accordingly.
And a few more pragmas for we could have equivalent __attribute__.
#pragma saddr [(]variable-name[,...][)]
#pragma near [(] function-name [,...][)]
#pragma far [(] function-name [,...][)]
#pragma callt [(]function-name[,...][)]
#pragma stack_protector [(]function-name[(num=number)][,function-name[(num=number)]][,...][)]
#pragma no_stack_protector [(]function-name[,...][)]

Finally there are 2 operators:
__sectop("section-name")
__secend("section-name")
This can be easily done by adding symbols at start and end of output sections in the linker script and referencing them from C as global pointers.

The CCRL manual explaining those extension in detail is available here:
https://www.renesas.com/us/en/doc/products/tool/doc/015/r20ut3123ej0109-ccrl.pdf

Best Regards,
Sebastian

Renesas Electronics Europe GmbH, Geschaeftsfuehrer/President: Carsten Jauch, Sitz der Gesellschaft/Registered office: Duesseldorf, Arcadiastrasse 10, 40472 Duesseldorf, Germany, Handelsregister/Commercial Register: Duesseldorf, HRB 3708 USt-IDNr./Tax identification no.: DE 119353406 WEEE-Reg.-Nr./WEEE reg. no.: DE 14978647

+Aaron as the attribution expert
+Richard for general Clang things

I imagine there might be some interest in a pragma that applies an attribute to a function - I know Apple folks implemented some attribution framework based on an input file, so attributing-at-a-distance is roughly in the realms of plausible.
Compatibility with an existing compiler is usually compelling - are the compilers you’re trying to be compatible with publicly available/documented?
The other aspect to new features, targets, etc, is the ongoing support - might be relevant to know a bit more about you/your users, whether there are other folks who are likely to maintain this work if you stop being involved at some point, etc.

Hi David,

Thank for very much for your reply!

I got a reply on the clang mailing list in April from Dmitri:

http://lists.llvm.org/pipermail/cfe-dev/2020-April/065115.html

and following his advice “attaching pragmas as attributes to functions” I managed to do it, it was actually quite easy.

Compatibility with an existing compiler is usually compelling - are the compilers you’re trying to be compatible with publicly available/documented?

Yes the compiler can be downloaded from here (is available for free with some restrictions compared to the paid version).

https://www.renesas.com/in/en/products/software-tools/tools/compiler-assembler/compiler-package-for-rl78-family.html

The documentation is available as well (in toolchain installer and website):

https://www.renesas.com/in/en/doc/products/tool/doc/015/r20ut3123ej0109-ccrl.pdf

The other aspect to new features, targets, etc, is the ongoing support - might be relevant to know a bit more about you/your users, whether there are other folks who are likely to maintain this work if you stop being involved at some point, etc.

Sure, no problem!

About me: https://ro.linkedin.com/in/sebastian-perta-46a4383b

Currently I have no intentions of stop being involved in this for a very long time. The only way this can happen is if I decide to leave Renesas in which case I’m sure the company will be interested to find a replacement.

About the users: those are embedded engineers in automotive, IOT, domestic appliances, etc.

Anything else you would like to know?

Best Regards,
Sebastian

Hi David,

Thank for very much for your reply!

I got a reply on the clang mailing list in April from Dmitri:

http://lists.llvm.org/pipermail/cfe-dev/2020-April/065115.html

and following his advice “attaching pragmas as attributes to functions” I managed to do it, it was actually quite easy.

Oh, great - glad you got some traction! (I was just replying as sort of a last-resort, none of this is really my wheelhouse)

Compatibility with an existing compiler is usually compelling - are the compilers you’re trying to be compatible with publicly available/documented?

Yes the compiler can be downloaded from here (is available for free with some restrictions compared to the paid version).

https://www.renesas.com/in/en/products/software-tools/tools/compiler-assembler/compiler-package-for-rl78-family.html

The documentation is available as well (in toolchain installer and website):

https://www.renesas.com/in/en/doc/products/tool/doc/015/r20ut3123ej0109-ccrl.pdf

The other aspect to new features, targets, etc, is the ongoing support - might be relevant to know a bit more about you/your users, whether there are other folks who are likely to maintain this work if you stop being involved at some point, etc.

Sure, no problem!

About me: https://ro.linkedin.com/in/sebastian-perta-46a4383b

Currently I have no intentions of stop being involved in this for a very long time. The only way this can happen is if I decide to leave Renesas in which case I’m sure the company will be interested to find a replacement.

Ah, so this is a commercially backed project? But relatively small? (are you the only engineer working on this?)

About the users: those are embedded engineers in automotive, IOT, domestic appliances, etc.

Anything else you would like to know?

It’s never a clear-cut thing and I don’t mean to pry (there’s a weird balance between having some context for why these things are being worked on, how likely they are to continue to be invested in, etc - versus accepting that companies have their own priorities, some private objectives, etc).

  • Dave

Hi David,

Ah, so this is a commercially backed project?

Initially it wasn’t. I started to do this in my own free time and after I got something which I could demonstrate I can be much better than what we currently have with GCC it became part of my day to day job.

But relatively small? (are you the only engineer working on this?)

Yes I’m the only one working on this.

It’s never a clear-cut thing and I don’t mean to pry (there’s a weird balance between having some context for why these things >>are being worked on, how likely they are to continue to be invested in, etc - versus accepting that companies have their own >>priorities, some private objectives, etc).

No worries I’m very happy to provide any information necessary. I really want the port to accepted upstream.

RL78 MCUs are part of the Renesas Product Longevity program https://www.renesas.com/eu/en/support/products-common/product-longevity-program-plp.html.

The majority of current RL78 devices have the termination date set as “December 2033”, and a few “March 2026”. Also RL78 is under active development: new devices (which a much later termination date) are being released all the time.

So this is very likely to continue for a very long time.

Best Regards,

Sebastian

Hi David,

Ah, so this is a commercially backed project?

Initially it wasn’t. I started to do this in my own free time and after I got something which I could demonstrate I can be much better than what we currently have with GCC it became part of my day to day job.

But relatively small? (are you the only engineer working on this?)

Yes I’m the only one working on this.

It's never a clear-cut thing and I don't mean to pry (there's a weird balance between having some context for why these things >>are being worked on, how likely they are to continue to be invested in, etc - versus accepting that companies have their own >>priorities, some private objectives, etc).

No worries I’m very happy to provide any information necessary. I really want the port to accepted upstream.
RL78 MCUs are part of the Renesas Product Longevity program https://www.renesas.com/eu/en/support/products-common/product-longevity-program-plp.html.
The majority of current RL78 devices have the termination date set as “December 2033”, and a few “March 2026”. Also RL78 is under active development: new devices (which a much later termination date) are being released all the time.
So this is very likely to continue for a very long time.

Best Regards,
Sebastian

Renesas Electronics Europe GmbH, Geschaeftsfuehrer/President: Carsten Jauch, Sitz der Gesellschaft/Registered office: Duesseldorf, Arcadiastrasse 10, 40472 Duesseldorf, Germany, Handelsregister/Commercial Register: Duesseldorf, HRB 3708 USt-IDNr./Tax identification no.: DE 119353406 WEEE-Reg.-Nr./WEEE reg. no.: DE 14978647

+Aaron as the attribution expert
+Richard for general Clang things

I imagine there might be some interest in a pragma that applies an attribute to a function - I know Apple folks implemented some attribution framework based on an input file, so attributing-at-a-distance is roughly in the realms of plausible.

We have several that do this already, so it hopefully won't be too bad
to support for your case. We have #pragma clang attribute itself
(which allows you to apply attributes to batches of declarations), as
well as some OpenMP pragmas that generate function attributes, that
can likely be used as a model.

~Aaron