Re: RFC: Speeding up small ISRs: PR20296

Georg-Johann Lay <[email protected]> Fri, 14 Jul 2017 19:18:52 +0200
Newsgroups gmane.comp.hardware.avr.gcc
Message-ID <[email protected]>
Georg-Johann Lay schrieb:
> On 15.06.2017 14:43, Georg-Johann Lay wrote:
>> https://gcc.gnu.org/PR20296
>>
>> is about speeding up "small" ISRs, and is open for 12 years now...
>>
>> Anyone familiar with avr-gcc knows that a fix would be high effort and 
>> risk, and that's the major reason for why PR20296 is still open (and 
>> even classified "suspended").
>>
>> In some forum discussion (again!) on that issue, there was the 
>> following proposal to approach that PR:
>>
>> 1) Let GCC emit directives / pseudo-instructions in non-naked ISR 
>> prologue / epilogue
>>
>> 2) Let GAS scan the code and replace the directives with code as needed.
>>
>> Currently,
>>
>> #include <avr/io.h>
>> #include <avr/interrupt.h>
>>
>> ISR (INT0_vect)
>> {
>>      __asm ("; Code");
>> }
>>
>> emit something like:
>>
>>
>> __vector_1:
>>      push r1
>>      push r0
>>      in r0,__SREG__
>>      push r0
>>      clr __zero_reg__
>> .L__stack_usage = 3
>>
>>      ; Code
>>
>>      pop r0
>>      out __SREG__,r0
>>      pop r0
>>      pop r1
>>      reti
>>
>>
>> which would change to:
>>
>>
>> __vector_1:
>>      .maybe_isr_prologue 123
>>      ;; Rest of prologue
>>
>>      ; Code
>>
>>      ;; Rest of epilogue
>>      .maybe_isr_epilogue 123
>>      reti
>>
>> GAS would then scan the code associated to the function and replace 
>> the .maybe by appropriate sequence to safe / init / restore tmp-reg, 
>> zero-reg and SREG.  Other registers like R24 are handled by GCC as 
>> usual.  For example, if the scan reveals that tmp-reg is not needed 
>> but zero-reg is (which will imply SREG due to the CLR) the replacement 
>> code would be:
>>
>>
>> __vector_1:
>>      push r1
>>      in r1,__SREG__
>>      push r1
>>      clr __zero_reg__
>>
>>      ; Code
>>
>>      pop r1
>>      out __SREG__,r1
>>      pop r1
>>      reti
>>
>>
>> Maybe someone is interested in implementing the GAS part, and if that 
>> is the case and the proposal is feasible, I would take care of the GCC 
>> part.
>>
>> Caveats:
>>
>> a) .L__stack_usage can no more be computed by GCC
>>
>> b) It's hard to find the end of the relevant code.  We might have 
>> interleaved sections (like with dispatch tables), there might be code 
>> that is emit after the epilogue, there might be more than 1 epilogue, 
>> dunno if GAS can infer whether JMP is local or non-local.
>>
>> We could add a new GCC pass that filters out situations that are 
>> pointless to scan like code with dispatch tables or function calls, 
>> and fall back to classical prologue / epilogue in such cases.
>>
>> The .maybe gets function-unique identifiers (123 in the example) so 
>> that GAS knows which epilogue belongs to which .prologue provided 
>> that's helpful.
>>
>> I am not familiar with Binutils / GAS though and don't know if it's 
>> easy to add the 2 new passes: One to scan and one to replace the 
>> .maybe with appropriate code.  IIUC GAS only works on sections, and 
>> the scan would be on BFD internal representation (like relaxing) after 
>> the parser read in the asm sources?
> 
> FYI, I just went ahead any typed down these lines for GAS.
> 
> 
> If someone wants to give it a try, it's here:
> 
> https://sourceware.org/bugzilla/show_bug.cgi?id=21683#c2
> 
>> The GCC change would add a new option, configure test whether GAS 
>> supports this, let ISR prologue and epilogue emit new unspec_volatile 
>> pseudo insns and add a scan pass to detect situations that are 
>> pointless should fall back to old code, like when dispatch tables, 
>> calls or non-local goto is seen.

The according avr-gcc feature is also upstream now.  It adds a new 
option -m[no-]gas-isr-prologues and a new function attribute to disable 
__gcc_isr generation for individual ISRs:

http://gcc.gnu.org/onlinedocs/gcc/AVR-Function-Attributes.html

If you want to play around with it, you need Binutils that implement 
PR20296 (e.g. Binutils GIT master or upcoming 2.29) and avr-gcc that 
implements PR81268 (GCC SVN trunk r250093 or newer).

The feature is enabled per default for all optimization levels except 
for -O0 and -Og.

Johann