public inbox for gcc-help@gcc.gnu.org
 help / color / mirror / Atom feed
* Use coroutines for avr-gcc
@ 2022-09-21 13:38 Wilhelm Meier
  2022-09-22 12:28 ` Wilhelm Meier
  0 siblings, 1 reply; 7+ messages in thread
From: Wilhelm Meier @ 2022-09-21 13:38 UTC (permalink / raw)
  To: gcc-help

I tried to use coroutines with avr-gcc (13.0.0) for the AVR target. I 
managed to include the coroutine-header and to write a very simple 
generator using the example from cppreference.

It compiles well, but then I get undefined symbols:

1) new and delete operator-functions
2) f(f()::f().Frame*)

Therefore two question arise here:

a) is it possible to use coroutines without head-allocation? E.g. define 
some global storage for the state of the coroutine?
b) if a) can be fullfilled, what is 2) supposed to do?

Thanks for any hints,
  Wilhelm

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Use coroutines for avr-gcc
  2022-09-21 13:38 Use coroutines for avr-gcc Wilhelm Meier
@ 2022-09-22 12:28 ` Wilhelm Meier
  2022-09-22 12:34   ` Jonathan Wakely
  0 siblings, 1 reply; 7+ messages in thread
From: Wilhelm Meier @ 2022-09-22 12:28 UTC (permalink / raw)
  To: gcc-help

According to the standard, an implementation can avoid the 
heap-allocation, if
- the lifetime of the coroutine is strictly within the lifetime of the 
caller
- the size of coroutine state can be determined at compile time

Looks like this optimization is not yet available because new/delete-ops 
are required.

Is there any work on this topic?

Thanks!
  Wilhelm

On 21.09.22 15:38, Wilhelm Meier wrote:
> I tried to use coroutines with avr-gcc (13.0.0) for the AVR target. I 
> managed to include the coroutine-header and to write a very simple 
> generator using the example from cppreference.
> 
> It compiles well, but then I get undefined symbols:
> 
> 1) new and delete operator-functions
> 2) f(f()::f().Frame*)
> 
> Therefore two question arise here:
> 
> a) is it possible to use coroutines without head-allocation? E.g. define 
> some global storage for the state of the coroutine?
> b) if a) can be fullfilled, what is 2) supposed to do?
> 
> Thanks for any hints,
>   Wilhelm

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Use coroutines for avr-gcc
  2022-09-22 12:28 ` Wilhelm Meier
@ 2022-09-22 12:34   ` Jonathan Wakely
  2022-09-22 19:58     ` Iain Sandoe
  0 siblings, 1 reply; 7+ messages in thread
From: Jonathan Wakely @ 2022-09-22 12:34 UTC (permalink / raw)
  To: Wilhelm Meier; +Cc: gcc-help

On Thu, 22 Sept 2022 at 13:29, Wilhelm Meier wrote:
>
> According to the standard, an implementation can avoid the
> heap-allocation, if
> - the lifetime of the coroutine is strictly within the lifetime of the
> caller
> - the size of coroutine state can be determined at compile time
>
> Looks like this optimization is not yet available because new/delete-ops
> are required.
>
> Is there any work on this topic?

The so-called HALO optimizations are much more difficult than was
originally thought when the wording in the standard was written.

https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2477r3.html#background-and-motivation
describes some of the problems.


> Thanks!
>   Wilhelm
>
> On 21.09.22 15:38, Wilhelm Meier wrote:
> > I tried to use coroutines with avr-gcc (13.0.0) for the AVR target. I
> > managed to include the coroutine-header and to write a very simple
> > generator using the example from cppreference.
> >
> > It compiles well, but then I get undefined symbols:
> >
> > 1) new and delete operator-functions
> > 2) f(f()::f().Frame*)
> >
> > Therefore two question arise here:
> >
> > a) is it possible to use coroutines without head-allocation? E.g. define
> > some global storage for the state of the coroutine?
> > b) if a) can be fullfilled, what is 2) supposed to do?
> >
> > Thanks for any hints,
> >   Wilhelm

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Use coroutines for avr-gcc
  2022-09-22 12:34   ` Jonathan Wakely
@ 2022-09-22 19:58     ` Iain Sandoe
  2022-09-23  7:58       ` Wilhelm Meier
  0 siblings, 1 reply; 7+ messages in thread
From: Iain Sandoe @ 2022-09-22 19:58 UTC (permalink / raw)
  To: Wilhelm Meier; +Cc: gcc-help



> On 22 Sep 2022, at 13:34, Jonathan Wakely <jwakely.gcc@gmail.com> wrote:
> 
> On Thu, 22 Sept 2022 at 13:29, Wilhelm Meier wrote:
>> 
>> According to the standard, an implementation can avoid the
>> heap-allocation, if
>> - the lifetime of the coroutine is strictly within the lifetime of the
>> caller
>> - the size of coroutine state can be determined at compile time
>> 
>> Looks like this optimization is not yet available because new/delete-ops
>> are required.

You can provide your own allocation and deallocation functions in the promise
class :

see  -  https://eel.is/c++draft/dcl.fct.def.coroutine#9
(and #12).

NOTE: this link is the current C++23 draft, the implementation in GCC follows the
C++20 version (but the basic provision is stil there)

>> 
>> Is there any work on this topic?
> 
> The so-called HALO optimizations are much more difficult than was
> originally thought when the wording in the standard was written.
> 
> https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2477r3.html#background-and-motivation
> describes some of the problems.

Agreed, this topic needs more consideration (and it is not mandatory, so should not be relied upon
for the use-case described in any event).

cheers
Iain

> 
> 
>> Thanks!
>>  Wilhelm
>> 
>> On 21.09.22 15:38, Wilhelm Meier wrote:
>>> I tried to use coroutines with avr-gcc (13.0.0) for the AVR target. I
>>> managed to include the coroutine-header and to write a very simple
>>> generator using the example from cppreference.
>>> 
>>> It compiles well, but then I get undefined symbols:
>>> 
>>> 1) new and delete operator-functions
>>> 2) f(f()::f().Frame*)
>>> 
>>> Therefore two question arise here:
>>> 
>>> a) is it possible to use coroutines without head-allocation? E.g. define
>>> some global storage for the state of the coroutine?
>>> b) if a) can be fullfilled, what is 2) supposed to do?
>>> 
>>> Thanks for any hints,
>>>  Wilhelm


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Use coroutines for avr-gcc
  2022-09-22 19:58     ` Iain Sandoe
@ 2022-09-23  7:58       ` Wilhelm Meier
  2022-09-23  8:16         ` Iain Sandoe
  0 siblings, 1 reply; 7+ messages in thread
From: Wilhelm Meier @ 2022-09-23  7:58 UTC (permalink / raw)
  To: Iain Sandoe; +Cc: gcc-help

On 22.09.22 21:58, Iain Sandoe wrote:
> 
> 
>> On 22 Sep 2022, at 13:34, Jonathan Wakely <jwakely.gcc@gmail.com> wrote:
>>
>> On Thu, 22 Sept 2022 at 13:29, Wilhelm Meier wrote:
>>>
>>> According to the standard, an implementation can avoid the
>>> heap-allocation, if
>>> - the lifetime of the coroutine is strictly within the lifetime of the
>>> caller
>>> - the size of coroutine state can be determined at compile time
>>>
>>> Looks like this optimization is not yet available because new/delete-ops
>>> are required.
> 
> You can provide your own allocation and deallocation functions in the promise
> class :
> 
> see  -  https://eel.is/c++draft/dcl.fct.def.coroutine#9
> (and #12).
> 
> NOTE: this link is the current C++23 draft, the implementation in GCC follows the
> C++20 version (but the basic provision is stil there)

Ok, thank you.
I did that and now it works also on target AVR ;-)

But: the asm-output contains a whole bunch of boilerplate code for 
storing the state of the coroutine. So for now I would say it is really 
unusable on small targets like AVR.

I think, if the heap operations could be elided away, then the whole 
thing should be more efficient.

Regards,
  Wilhelm

> 
>>>
>>> Is there any work on this topic?
>>
>> The so-called HALO optimizations are much more difficult than was
>> originally thought when the wording in the standard was written.
>>
>> https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2477r3.html#background-and-motivation
>> describes some of the problems.
> 
> Agreed, this topic needs more consideration (and it is not mandatory, so should not be relied upon
> for the use-case described in any event).
> 
> cheers
> Iain
> 
>>
>>
>>> Thanks!
>>>   Wilhelm
>>>
>>> On 21.09.22 15:38, Wilhelm Meier wrote:
>>>> I tried to use coroutines with avr-gcc (13.0.0) for the AVR target. I
>>>> managed to include the coroutine-header and to write a very simple
>>>> generator using the example from cppreference.
>>>>
>>>> It compiles well, but then I get undefined symbols:
>>>>
>>>> 1) new and delete operator-functions
>>>> 2) f(f()::f().Frame*)
>>>>
>>>> Therefore two question arise here:
>>>>
>>>> a) is it possible to use coroutines without head-allocation? E.g. define
>>>> some global storage for the state of the coroutine?
>>>> b) if a) can be fullfilled, what is 2) supposed to do?
>>>>
>>>> Thanks for any hints,
>>>>   Wilhelm
> 

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Use coroutines for avr-gcc
  2022-09-23  7:58       ` Wilhelm Meier
@ 2022-09-23  8:16         ` Iain Sandoe
  2022-09-23  8:42           ` Wilhelm Meier
  0 siblings, 1 reply; 7+ messages in thread
From: Iain Sandoe @ 2022-09-23  8:16 UTC (permalink / raw)
  To: Wilhelm Meier; +Cc: gcc-help

Hi Wilhelm,

> On 23 Sep 2022, at 08:58, Wilhelm Meier <wilhelm.meier@hs-kl.de> wrote:
> 
> On 22.09.22 21:58, Iain Sandoe wrote:
>>> On 22 Sep 2022, at 13:34, Jonathan Wakely <jwakely.gcc@gmail.com> wrote:
>>> 
>>> On Thu, 22 Sept 2022 at 13:29, Wilhelm Meier wrote:
>>>> 
>>>> According to the standard, an implementation can avoid the
>>>> heap-allocation, if
>>>> - the lifetime of the coroutine is strictly within the lifetime of the
>>>> caller
>>>> - the size of coroutine state can be determined at compile time
>>>> 
>>>> Looks like this optimization is not yet available because new/delete-ops
>>>> are required.
>> You can provide your own allocation and deallocation functions in the promise
>> class :
>> see  -  https://eel.is/c++draft/dcl.fct.def.coroutine#9
>> (and #12).
>> NOTE: this link is the current C++23 draft, the implementation in GCC follows the
>> C++20 version (but the basic provision is stil there)
> 
> Ok, thank you.
> I did that and now it works also on target AVR ;-)

great!

> But: the asm-output contains a whole bunch of boilerplate code for storing the state of the coroutine. So for now I would say it is really unusable on small targets like AVR.

> I think, if the heap operations could be elided away, then the whole thing should be more efficient.

The generator style of coroutine is one specific case.

Asynchronous cases (e.g. the behaviour of an I/O interaction) modelled by a coroutine rather than a hand-written state machine strike me as potentially very useful for embedded systems (since those hand-written cases are notoriously hard to maintain).  So perhaps we could see if there is some way to optimise the ‘boiler plate’ (although some copying is mandated by the standard).

FWIW: there are some other optimisations in the pipeline (one that minimizes frame size, and one that avoids saving some of the variables to the frame).  However, AFAIK, no-one is actively working on frame elision.

There is also a paper to WG21 that seeks to mandate some of these optimisations - so maybe frame elision will get some more attention in the future.

Of course, if you have a patch to implement the elision, we would also be very happy to review it.

cheers
Iain 

> 
> Regards,
> Wilhelm
> 
>>>> 
>>>> Is there any work on this topic?
>>> 
>>> The so-called HALO optimizations are much more difficult than was
>>> originally thought when the wording in the standard was written.
>>> 
>>> https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2477r3.html#background-and-motivation
>>> describes some of the problems.
>> Agreed, this topic needs more consideration (and it is not mandatory, so should not be relied upon
>> for the use-case described in any event).
>> cheers
>> Iain
>>> 
>>> 
>>>> Thanks!
>>>>  Wilhelm
>>>> 
>>>> On 21.09.22 15:38, Wilhelm Meier wrote:
>>>>> I tried to use coroutines with avr-gcc (13.0.0) for the AVR target. I
>>>>> managed to include the coroutine-header and to write a very simple
>>>>> generator using the example from cppreference.
>>>>> 
>>>>> It compiles well, but then I get undefined symbols:
>>>>> 
>>>>> 1) new and delete operator-functions
>>>>> 2) f(f()::f().Frame*)
>>>>> 
>>>>> Therefore two question arise here:
>>>>> 
>>>>> a) is it possible to use coroutines without head-allocation? E.g. define
>>>>> some global storage for the state of the coroutine?
>>>>> b) if a) can be fullfilled, what is 2) supposed to do?
>>>>> 
>>>>> Thanks for any hints,
>>>>>  Wilhelm


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Use coroutines for avr-gcc
  2022-09-23  8:16         ` Iain Sandoe
@ 2022-09-23  8:42           ` Wilhelm Meier
  0 siblings, 0 replies; 7+ messages in thread
From: Wilhelm Meier @ 2022-09-23  8:42 UTC (permalink / raw)
  To: Iain Sandoe; +Cc: gcc-help



On 23.09.22 10:16, Iain Sandoe wrote:
> Hi Wilhelm,
> 
>> On 23 Sep 2022, at 08:58, Wilhelm Meier <wilhelm.meier@hs-kl.de> wrote:
>>
>> On 22.09.22 21:58, Iain Sandoe wrote:
>>>> On 22 Sep 2022, at 13:34, Jonathan Wakely <jwakely.gcc@gmail.com> wrote:
>>>>
>>>> On Thu, 22 Sept 2022 at 13:29, Wilhelm Meier wrote:
>>>>>
>>>>> According to the standard, an implementation can avoid the
>>>>> heap-allocation, if
>>>>> - the lifetime of the coroutine is strictly within the lifetime of the
>>>>> caller
>>>>> - the size of coroutine state can be determined at compile time
>>>>>
>>>>> Looks like this optimization is not yet available because new/delete-ops
>>>>> are required.
>>> You can provide your own allocation and deallocation functions in the promise
>>> class :
>>> see  -  https://eel.is/c++draft/dcl.fct.def.coroutine#9
>>> (and #12).
>>> NOTE: this link is the current C++23 draft, the implementation in GCC follows the
>>> C++20 version (but the basic provision is stil there)
>>
>> Ok, thank you.
>> I did that and now it works also on target AVR ;-)
> 
> great!
> 
>> But: the asm-output contains a whole bunch of boilerplate code for storing the state of the coroutine. So for now I would say it is really unusable on small targets like AVR.
> 
>> I think, if the heap operations could be elided away, then the whole thing should be more efficient.
> 
> The generator style of coroutine is one specific case.
> 
> Asynchronous cases (e.g. the behaviour of an I/O interaction) modelled by a coroutine rather than a hand-written state machine strike me as potentially very useful for embedded systems (since those hand-written cases are notoriously hard to maintain).  So perhaps we could see if there is some way to optimise the ‘boiler plate’ (although some copying is mandated by the standard).

Yes, I would like to use that for serial protocol analyzers.

> FWIW: there are some other optimisations in the pipeline (one that minimizes frame size, and one that avoids saving some of the variables to the frame). 

I think, this would be helpful.

> However, AFAIK, no-one is actively working on frame elision.

That's a pitty because I think, that this renders it unusable on the 
small µC like AVR. On these plattform optimal code generation is mandatory.

> 
> There is also a paper to WG21 that seeks to mandate some of these optimisations - so maybe frame elision will get some more attention in the future.

That would be great!

> 
> Of course, if you have a patch to implement the elision, we would also be very happy to review it.

Well, I'm really not in the skills positions to provide any valuable 
input on that ...

Regards,
  Wilhelm

> 
> cheers
> Iain
> 
>>
>> Regards,
>> Wilhelm
>>
>>>>>
>>>>> Is there any work on this topic?
>>>>
>>>> The so-called HALO optimizations are much more difficult than was
>>>> originally thought when the wording in the standard was written.
>>>>
>>>> https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2477r3.html#background-and-motivation
>>>> describes some of the problems.
>>> Agreed, this topic needs more consideration (and it is not mandatory, so should not be relied upon
>>> for the use-case described in any event).
>>> cheers
>>> Iain
>>>>
>>>>
>>>>> Thanks!
>>>>>   Wilhelm
>>>>>
>>>>> On 21.09.22 15:38, Wilhelm Meier wrote:
>>>>>> I tried to use coroutines with avr-gcc (13.0.0) for the AVR target. I
>>>>>> managed to include the coroutine-header and to write a very simple
>>>>>> generator using the example from cppreference.
>>>>>>
>>>>>> It compiles well, but then I get undefined symbols:
>>>>>>
>>>>>> 1) new and delete operator-functions
>>>>>> 2) f(f()::f().Frame*)
>>>>>>
>>>>>> Therefore two question arise here:
>>>>>>
>>>>>> a) is it possible to use coroutines without head-allocation? E.g. define
>>>>>> some global storage for the state of the coroutine?
>>>>>> b) if a) can be fullfilled, what is 2) supposed to do?
>>>>>>
>>>>>> Thanks for any hints,
>>>>>>   Wilhelm
> 

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2022-09-23  8:42 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-09-21 13:38 Use coroutines for avr-gcc Wilhelm Meier
2022-09-22 12:28 ` Wilhelm Meier
2022-09-22 12:34   ` Jonathan Wakely
2022-09-22 19:58     ` Iain Sandoe
2022-09-23  7:58       ` Wilhelm Meier
2022-09-23  8:16         ` Iain Sandoe
2022-09-23  8:42           ` Wilhelm Meier

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).