Misschien handig?

blackdog

Golden Member

Hi,

Ik was wat aan het browsen/zoeken naar handige info en kwam dit tegen.

https://www.embedded.com/10-simple-tricks-to-optimize-your-c-code-in-s…

Het laat zien dat je geheugenruimte kan bespraren als je project wat weinig ruimte heeft, door stukjes code op een andere manier te schijven zodat het minder ruimte inneemt.

Niet direct mijn expertise maar misschien handig voor een aantal van jullie die in C schrijven.

Groet,
Bram

You have your way. I have my way. As for the right way, the correct way, and the only way, it does not exist.

Klinkt leuk, maar ik geloof hier niet zo in eigenlijk.

Compilers zijn tegenwoordig slim genoeg om zelf de beste oplossing te kiezen. Die XC8 compiler ken ik niet, maar de standaard GCC compiler (voor ARM en AVR) doet dat in elk geval veel beter, zeker als je optimalisatie op Code size instelt. Als programmeur hoef je op dit niveau niet meer te puzzelen en dan telt eigenlijk alleen nog de code die het beste leesbaar is.

Even een test gedaan met het eerste voorbeeld:

code:


int main(void)
{
   int a = 5, b = 12;
   a = (b-1) * 3;
}

Resulteert in

code:


 28e:	80 e0       	ldi	r24, 0x00	; 0
 290:	90 e0       	ldi	r25, 0x00	; 0
 292:	08 95       	ret

Ofwel alleen een return 0 in het gecompileerde resultaat.

De hele berekening valt weg omdat het resultaat toch niet gebruikt wordt.

[Bericht gewijzigd door deKees op vrijdag 27 mei 2022 22:10:15 (32%)

blackdog

Golden Member

Hi deKees, :-)

Ik heb echt geen idee, zoals je weet valt dit allemaal ver buiten mijn kwaliteiten en bij jou waarschijnlijk "spot on"

Misschien dat het werkt voor de Arduino IDE, maar ook dat zou ik niet weten en nu ook geen tijd er voro om het te testen.

Groet,
Bram

You have your way. I have my way. As for the right way, the correct way, and the only way, it does not exist.

De XC8 compiler is voor PICs, die heeft zo'n idiote architectuur dat er heel lang geen support voor was in GCC. Het is ook een beetje onhandig om een processor te kiezen die zo afwijkt van de "norm" om deze vergelijkingen mee te doen, want dit is weinig representatief. Als je dit test op een ARM controller, zijn de resultaten waarschijnlijk ongeveer hetzelfde als voor een ARM controller van een andere fabrikant.

Sommige tips zijn misschien wel nuttig en bruikbaar, maar bij een aantal zijn de twee voorbeelden echt niet equivalent, en bij andere heb ik mijn twijfels; het is bijvoorbeeld vrij gebruikelijk om wel hardware te hebben om te vermenigvuldigen, maar niet om te delen, want dat is een stuk moeilijker om in hardware te doen. Ik kan me dan niet voorstellen dat delen in plaats van vermenigvuldigen kleinere code zou opleveren.

[Bericht gewijzigd door SparkyGSX op vrijdag 27 mei 2022 22:13:32 (12%)

Een manager is iemand die denkt dat negen vrouwen in één maand een kind kunnen maken
Arco

Special Member

Je kunt code wel degelijk optimaliseren voor snelheid of grootte.
Vaak kun je bijv. een for loop 'uitrollen' om de code (veel) sneller te maken (met meer code), terwijl een for loop minder code gebruikt maar wel veel trager is.

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com

Ik ontken ook zeker niet dat het mogelijk is om voor verschillende doelen te optimaliseren (meestal code space of snelheid, maar soms is een constante tijd gewenst, in de cryptografie bijvoorbeeld), maar de voorbeelden vind ik twijfelachtig, en een goede compiler zal al een aanzienlijk deel voor je doen, als je hem de mogelijkheid geeft.

Loop unrolling is wel echt van decennia geleden, met moderne pipelines en branch prediction levert dat nauwelijks nog iets op, en je moet juist oppassen dat je met cache misses niet juist meer tijd kwijt bent. Het loont sowieso steeds minder (relatief) naarmate je meer code in de loop hebt. De plaatsen waar je traditioneel loop unrolling zou doen worden nu meestal gedaan door de GPU.

Een manager is iemand die denkt dat negen vrouwen in één maand een kind kunnen maken

Op 27 mei 2022 21:20:36 schreef blackdog:
Hi,

Ik was wat aan het browsen/zoeken naar handige info en kwam dit tegen.

https://www.embedded.com/10-simple-tricks-to-optimize-your-c-code-in-s…

Ik wordt altijd zo droevig van dit soort kortzichtige onjuiste advizen.

Ik heb mijn ARM compiler gevraagd om dit stukje code te compileren:

code:


int t1 (int a, int b)
{
  return (b-1)*3;
}
int t2 (int a, int b)
{
  a = b-1;
  return a+a+a;
}

En die maakt voor beide functies daarvan:

code:


        sub     r0, r1, #1
        add     r0, r0, r0, lsl #1
        bx      lr

Het maakt NUL COMMA NUL verschil. Op het eerste voorbeeld waarbij een factor twee voordeel wordt geclaimed.

Doe ik het met de AVR compiler, dan kost de eerste 6 instructies, de tweede acht. Het voordeel (in code-size) gaat de andere kant op!
(De compiler maakt er trouwens van die laatste: a=b-1; return (a<<1) + a;)

De geadverteerde hints zijn allemaal van het kaliber: Het helpt alleen echt als je het door je hele code structureel doet en zal dan hoogstens een paar procent schelen.... MITS jou gok over wat de compiler makkelijker vindt steeds correct is. Als je zo nu en dan fout gokt, zoals de schrijver van dat artikel is het verschil nog veel kleiner.

Het loont NIET de moeite om dat soort fratsen uit te halen. Dat scheelt je nu een paar euro omdat het in een kleinere CPU past, en straks uren in debuggen omdat je ofwel je code niet meer snapt of omdat je herschrijf-actie een bug heeft geintroduceerd.

@sparky De reden dat in mijn voorbeeld de AVR compiler in het "moeilijke geval" minder code nodig had is omdat ie de uitgeschreven berekening inline deed terwijl ie voor de vermenigvuldiging een subroutine nodig had.

@Arco loop unrolling kan significant helpen, mits de loop-overhead significant is. Dat is zelden het geval.

Ik heb in 1992 aan een project gewerkt waar mijn voorganger de mainloop van vijf geneste loops had geunrolled. De routine was nu 1028 bytes lang geworden en duwde steeds de volgende instructie uit de cache. Het unrollen van ALLEEN de binnenste loop gaf iets van 99% van de versnelling omdat je in de tijd gezien 99% van de tijd in de binnenste lus zit. De loop overhead van de buitenste lussen is verwaarloosbaar.

De werkelijke adviezen moeten m.i. zijn:

* Ga geen maatregelen nemen voor een probleem wat je niet hebt. Codeer zo duidelijk mogelijk, de compiler is slim zat, zolang er zat ruimte is, is er geen probleem.

* als er een probleem is ("het past niet meer"), overweeg sterk om gewoon een grotere chip te kopen. Het is zelden kostenefficient om moeilijk te doen in de software om het net passend te krijgen in een iets kleinere chip. (ik betaal tegenwoordig 2 euro inkoop voor cpu-met-16Mb(yte!) flash).

* Als je in de problemen dreigt te komen... KIJK waar de grote verbruikers zitten. Mijn klant van deze week zei: "ik heb meer geheugen nodig want al die libraries dat kost steeds maar meer geheugen". En dat klopt. Dus: Kan je zonder een complete library? Mooi. Misschien gebruik je een library die veel features heeft die je niet nodig hebt. Misschien een idee om zelf het stukje te schrijven wat je nodig hebt? Zijn oplossing: Grotere chip kopen. Prima plan.

In een modern project krijg je het haast niet voor mekaar om in je eentje genoeg code te schrijven om iets vol te krijgen. De grootverbruikers zitten elders!

* Grote arrays, grote tabellen, dat zijn geheugen vreters. Dus als je vind dat die het probleem veroorzaken kijk of je daar wat aan kan doen.

four NANDS do make a NOR . Kijk ook eens in onze shop: http://www.bitwizard.nl/shop/
Arco

Special Member

Loop uitrollen kan echt dramatisch veel tijd schelen (tot wel 75% of meer)
Ik moest bijv. deze (bit test) code:

pic basic code:


 for Cnt = 0 to 15
   If Template.cnt Then Dec(Sincos[cnt} Else Inc(Sincos[cnt] End If 
 next cnt

vervangen door:

pic basic code:


  If Template.0 Then Dec(Sincos[0]) Else Inc(Sincos[0]) End If
  If Template.1 Then Dec(Sincos[1]) Else Inc(Sincos[1]) End If
  If Template.2 Then Dec(Sincos[2]) Else Inc(Sincos[2]) End If
  If Template.3 Then Dec(Sincos[3]) Else Inc(Sincos[3]) End If
  If Template.4 Then Dec(Sincos[4]) Else Inc(Sincos[4]) End If
  If Template.5 Then Dec(Sincos[5]) Else Inc(Sincos[5]) End If
  If Template.6 Then Dec(Sincos[6]) Else Inc(Sincos[6]) End If
  If Template.7 Then Dec(Sincos[7]) Else Inc(Sincos[7]) End If
  If Template.8 Then Dec(Sincos[8]) Else Inc(Sincos[8]) End If
  If Template.9 Then Dec(Sincos[9]) Else Inc(Sincos[9]) End If
  If Template.10 Then Dec(Sincos[10]) Else Inc(Sincos[10]) End If
  If Template.11 Then Dec(Sincos[11]) Else Inc(Sincos[11]) End If
  If Template.12 Then Dec(Sincos[12]) Else Inc(Sincos[12]) End If
  If Template.13 Then Dec(Sincos[13]) Else Inc(Sincos[13]) End If
  If Template.14 Then Dec(Sincos[14]) Else Inc(Sincos[14]) End If
  If Template.15 Then Dec(Sincos[15]) Else Inc(Sincos[15]) End If

Deze code wordt iedere interrupt uitgevoerd (8000x/sec) en dan is een for loop echt veel te traag om te kunnen werken...

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com

@REW: en grotere CPU is niet altijd mogelijk; ik moest ooit code toevoegen aan een DSP met 8k flash, waarvan meer dan de helft in gebruik was voor tabellen, en waarvan al enige honderdduizenden exemplaren actief zijn in het veld, die nog wel een update moesten krijgen.

Toen ik begon was er nog ruimte voor 7 instructies (alles was in asm).

Een manager is iemand die denkt dat negen vrouwen in één maand een kind kunnen maken

Ook loop uitrollen doet de AVR-GCC compiler in sommige gevallen, afhankelijk van de gekozen optimalisatie.

Bijv:

code:


int SinCos[16] = {};
int Template = 0x1235;

int main(void)
{
   for ( int a = 0; a < 15; a++ )
   {  if(Template & (1 << a))
         SinCos[a] += 1;
      else
         SinCos[a] -= 1;
   }
   return SinCos[4];
}

Kun je compileren voor Speed (-O3) of voor Code-size (-O2)

Optimise voor speed rolt de loop weg:

code:


int main(void)
{
 2b4:	20 91 00 3c 	lds	r18, 0x3C00	; 0x803c00 <__DATA_REGION_ORIGIN__>
 2b8:	30 91 01 3c 	lds	r19, 0x3C01	; 0x803c01 <__DATA_REGION_ORIGIN__+0x1>
   for ( int a = 0; a < 15; a++ )
   {  if(Template & (1 << a))
         SinCos[a] += 1;
 2bc:	80 91 02 3c 	lds	r24, 0x3C02	; 0x803c02 <__data_end>
 2c0:	90 91 03 3c 	lds	r25, 0x3C03	; 0x803c03 <__data_end+0x1>
int Template = 0x1235;

int main(void)
{
   for ( int a = 0; a < 15; a++ )
   {  if(Template & (1 << a))
 2c4:	20 fd       	sbrc	r18, 0
 2c6:	cc c0       	rjmp	.+408    	; 0x460 <__DATA_REGION_LENGTH__+0x60>
         SinCos[a] += 1;
      else
         SinCos[a] -= 1;
 2c8:	01 97       	sbiw	r24, 0x01	; 1
 2ca:	80 93 02 3c 	sts	0x3C02, r24	; 0x803c02 <__data_end>
 2ce:	90 93 03 3c 	sts	0x3C03, r25	; 0x803c03 <__data_end+0x1>

int main(void)
{
   for ( int a = 0; a < 15; a++ )
   {  if(Template & (1 << a))
         SinCos[a] += 1;
 2d2:	80 91 04 3c 	lds	r24, 0x3C04	; 0x803c04 <__data_end+0x2>
 2d6:	90 91 05 3c 	lds	r25, 0x3C05	; 0x803c05 <__data_end+0x3>
int Template = 0x1235;

int main(void)
{
   for ( int a = 0; a < 15; a++ )
   {  if(Template & (1 << a))
 2da:	21 fd       	sbrc	r18, 1
 2dc:	37 c1       	rjmp	.+622    	; 0x54c <__DATA_REGION_LENGTH__+0x14c>
         SinCos[a] += 1;
      else
         SinCos[a] -= 1;
 2de:	01 97       	sbiw	r24, 0x01	; 1
 2e0:	80 93 04 3c 	sts	0x3C04, r24	; 0x803c04 <__data_end+0x2>
 2e4:	90 93 05 3c 	sts	0x3C05, r25	; 0x803c05 <__data_end+0x3>

int main(void)
{
   for ( int a = 0; a < 15; a++ )
   {  if(Template & (1 << a))
         SinCos[a] += 1;
 2e8:	80 91 06 3c 	lds	r24, 0x3C06	; 0x803c06 <__data_end+0x4>
 2ec:	90 91 07 3c 	lds	r25, 0x3C07	; 0x803c07 <__data_end+0x5>
int Template = 0x1235;

int main(void)
{
   for ( int a = 0; a < 15; a++ )
   {  if(Template & (1 << a))
 2f0:	22 fd       	sbrc	r18, 2
 2f2:	26 c1       	rjmp	.+588    	; 0x540 <__DATA_REGION_LENGTH__+0x140>
         SinCos[a] += 1;
      else
         SinCos[a] -= 1;
 2f4:	01 97       	sbiw	r24, 0x01	; 1
 2f6:	80 93 06 3c 	sts	0x3C06, r24	; 0x803c06 <__data_end+0x4>
 2fa:	90 93 07 3c 	sts	0x3C07, r25	; 0x803c07 <__data_end+0x5>

int main(void)
{
   for ( int a = 0; a < 15; a++ )
   {  if(Template & (1 << a))
         SinCos[a] += 1;
 2fe:	80 91 08 3c 	lds	r24, 0x3C08	; 0x803c08 <__data_end+0x6>
 302:	90 91 09 3c 	lds	r25, 0x3C09	; 0x803c09 <__data_end+0x7>
int Template = 0x1235;

int main(void)
{
   for ( int a = 0; a < 15; a++ )
   {  if(Template & (1 << a))
 306:	23 fd       	sbrc	r18, 3
 308:	15 c1       	rjmp	.+554    	; 0x534 <__DATA_REGION_LENGTH__+0x134>
         SinCos[a] += 1;
      else
         SinCos[a] -= 1;
 30a:	01 97       	sbiw	r24, 0x01	; 1
 30c:	80 93 08 3c 	sts	0x3C08, r24	; 0x803c08 <__data_end+0x6>
 310:	90 93 09 3c 	sts	0x3C09, r25	; 0x803c09 <__data_end+0x7>

int main(void)
{
   for ( int a = 0; a < 15; a++ )
   {  if(Template & (1 << a))
         SinCos[a] += 1;
 314:	80 91 0a 3c 	lds	r24, 0x3C0A	; 0x803c0a <__data_end+0x8>
 318:	90 91 0b 3c 	lds	r25, 0x3C0B	; 0x803c0b <__data_end+0x9>
int Template = 0x1235;

int main(void)
{
   for ( int a = 0; a < 15; a++ )
   {  if(Template & (1 << a))
 31c:	24 fd       	sbrc	r18, 4
 31e:	04 c1       	rjmp	.+520    	; 0x528 <__DATA_REGION_LENGTH__+0x128>
         SinCos[a] += 1;
      else
         SinCos[a] -= 1;
 320:	01 97       	sbiw	r24, 0x01	; 1
 322:	80 93 0a 3c 	sts	0x3C0A, r24	; 0x803c0a <__data_end+0x8>
 326:	90 93 0b 3c 	sts	0x3C0B, r25	; 0x803c0b <__data_end+0x9>

int main(void)
{
   for ( int a = 0; a < 15; a++ )
   {  if(Template & (1 << a))
         SinCos[a] += 1;
 32a:	40 91 0c 3c 	lds	r20, 0x3C0C	; 0x803c0c <__data_end+0xa>
 32e:	50 91 0d 3c 	lds	r21, 0x3C0D	; 0x803c0d <__data_end+0xb>
int Template = 0x1235;

int main(void)
{
   for ( int a = 0; a < 15; a++ )
   {  if(Template & (1 << a))
 332:	25 fd       	sbrc	r18, 5
 334:	f2 c0       	rjmp	.+484    	; 0x51a <__DATA_REGION_LENGTH__+0x11a>
         SinCos[a] += 1;
      else
         SinCos[a] -= 1;
 336:	41 50       	subi	r20, 0x01	; 1
 338:	51 09       	sbc	r21, r1
 33a:	40 93 0c 3c 	sts	0x3C0C, r20	; 0x803c0c <__data_end+0xa>
 33e:	50 93 0d 3c 	sts	0x3C0D, r21	; 0x803c0d <__data_end+0xb>

int main(void)
{
   for ( int a = 0; a < 15; a++ )
   {  if(Template & (1 << a))
         SinCos[a] += 1;
 342:	40 91 0e 3c 	lds	r20, 0x3C0E	; 0x803c0e <__data_end+0xc>
 346:	50 91 0f 3c 	lds	r21, 0x3C0F	; 0x803c0f <__data_end+0xd>
int Template = 0x1235;

int main(void)
{
   for ( int a = 0; a < 15; a++ )
   {  if(Template & (1 << a))
 34a:	26 fd       	sbrc	r18, 6
 34c:	df c0       	rjmp	.+446    	; 0x50c <__DATA_REGION_LENGTH__+0x10c>
         SinCos[a] += 1;
      else
         SinCos[a] -= 1;
 34e:	41 50       	subi	r20, 0x01	; 1
 350:	51 09       	sbc	r21, r1
 352:	40 93 0e 3c 	sts	0x3C0E, r20	; 0x803c0e <__data_end+0xc>
 356:	50 93 0f 3c 	sts	0x3C0F, r21	; 0x803c0f <__data_end+0xd>

int main(void)
{
   for ( int a = 0; a < 15; a++ )
   {  if(Template & (1 << a))
         SinCos[a] += 1;
 35a:	40 91 10 3c 	lds	r20, 0x3C10	; 0x803c10 <__data_end+0xe>
 35e:	50 91 11 3c 	lds	r21, 0x3C11	; 0x803c11 <__data_end+0xf>
int Template = 0x1235;

int main(void)
{
   for ( int a = 0; a < 15; a++ )
   {  if(Template & (1 << a))
 362:	27 fd       	sbrc	r18, 7
 364:	cc c0       	rjmp	.+408    	; 0x4fe <__DATA_REGION_LENGTH__+0xfe>
         SinCos[a] += 1;
      else
         SinCos[a] -= 1;
 366:	41 50       	subi	r20, 0x01	; 1
 368:	51 09       	sbc	r21, r1
 36a:	40 93 10 3c 	sts	0x3C10, r20	; 0x803c10 <__data_end+0xe>
 36e:	50 93 11 3c 	sts	0x3C11, r21	; 0x803c11 <__data_end+0xf>

int main(void)
{
   for ( int a = 0; a < 15; a++ )
   {  if(Template & (1 << a))
         SinCos[a] += 1;
 372:	40 91 12 3c 	lds	r20, 0x3C12	; 0x803c12 <__data_end+0x10>
 376:	50 91 13 3c 	lds	r21, 0x3C13	; 0x803c13 <__data_end+0x11>
int Template = 0x1235;

int main(void)
{
   for ( int a = 0; a < 15; a++ )
   {  if(Template & (1 << a))
 37a:	30 fd       	sbrc	r19, 0
 37c:	b9 c0       	rjmp	.+370    	; 0x4f0 <__DATA_REGION_LENGTH__+0xf0>
         SinCos[a] += 1;
      else
         SinCos[a] -= 1;
 37e:	41 50       	subi	r20, 0x01	; 1
 380:	51 09       	sbc	r21, r1
 382:	40 93 12 3c 	sts	0x3C12, r20	; 0x803c12 <__data_end+0x10>
 386:	50 93 13 3c 	sts	0x3C13, r21	; 0x803c13 <__data_end+0x11>
int Template = 0x1235;

int main(void)
{
   for ( int a = 0; a < 15; a++ )
   {  if(Template & (1 << a))
 38a:	a9 01       	movw	r20, r18
 38c:	45 2f       	mov	r20, r21
 38e:	55 0f       	add	r21, r21
 390:	55 0b       	sbc	r21, r21
 392:	45 95       	asr	r20
 394:	40 fd       	sbrc	r20, 0
 396:	a1 c0       	rjmp	.+322    	; 0x4da <__DATA_REGION_LENGTH__+0xda>
         SinCos[a] += 1;
      else
         SinCos[a] -= 1;
 398:	40 91 14 3c 	lds	r20, 0x3C14	; 0x803c14 <__data_end+0x12>
 39c:	50 91 15 3c 	lds	r21, 0x3C15	; 0x803c15 <__data_end+0x13>
 3a0:	41 50       	subi	r20, 0x01	; 1
 3a2:	51 09       	sbc	r21, r1
 3a4:	40 93 14 3c 	sts	0x3C14, r20	; 0x803c14 <__data_end+0x12>
 3a8:	50 93 15 3c 	sts	0x3C15, r21	; 0x803c15 <__data_end+0x13>
int Template = 0x1235;

int main(void)
{
   for ( int a = 0; a < 15; a++ )
   {  if(Template & (1 << a))
 3ac:	a9 01       	movw	r20, r18
 3ae:	45 2f       	mov	r20, r21
 3b0:	55 0f       	add	r21, r21
 3b2:	55 0b       	sbc	r21, r21
 3b4:	45 95       	asr	r20
 3b6:	45 95       	asr	r20
 3b8:	40 fd       	sbrc	r20, 0
 3ba:	84 c0       	rjmp	.+264    	; 0x4c4 <__DATA_REGION_LENGTH__+0xc4>
         SinCos[a] += 1;
      else
         SinCos[a] -= 1;
 3bc:	40 91 16 3c 	lds	r20, 0x3C16	; 0x803c16 <__data_end+0x14>
 3c0:	50 91 17 3c 	lds	r21, 0x3C17	; 0x803c17 <__data_end+0x15>
 3c4:	41 50       	subi	r20, 0x01	; 1
 3c6:	51 09       	sbc	r21, r1
 3c8:	40 93 16 3c 	sts	0x3C16, r20	; 0x803c16 <__data_end+0x14>
 3cc:	50 93 17 3c 	sts	0x3C17, r21	; 0x803c17 <__data_end+0x15>
int Template = 0x1235;

int main(void)
{
   for ( int a = 0; a < 15; a++ )
   {  if(Template & (1 << a))
 3d0:	a9 01       	movw	r20, r18
 3d2:	40 e2       	ldi	r20, 0x20	; 32
 3d4:	54 02       	muls	r21, r20
 3d6:	41 2d       	mov	r20, r1
 3d8:	55 0b       	sbc	r21, r21
 3da:	11 24       	eor	r1, r1
 3dc:	40 fd       	sbrc	r20, 0
 3de:	67 c0       	rjmp	.+206    	; 0x4ae <__DATA_REGION_LENGTH__+0xae>
         SinCos[a] += 1;
      else
         SinCos[a] -= 1;
 3e0:	40 91 18 3c 	lds	r20, 0x3C18	; 0x803c18 <__data_end+0x16>
 3e4:	50 91 19 3c 	lds	r21, 0x3C19	; 0x803c19 <__data_end+0x17>
 3e8:	41 50       	subi	r20, 0x01	; 1
 3ea:	51 09       	sbc	r21, r1
 3ec:	40 93 18 3c 	sts	0x3C18, r20	; 0x803c18 <__data_end+0x16>
 3f0:	50 93 19 3c 	sts	0x3C19, r21	; 0x803c19 <__data_end+0x17>
int Template = 0x1235;

int main(void)
{
   for ( int a = 0; a < 15; a++ )
   {  if(Template & (1 << a))
 3f4:	a9 01       	movw	r20, r18
 3f6:	40 e1       	ldi	r20, 0x10	; 16
 3f8:	54 02       	muls	r21, r20
 3fa:	41 2d       	mov	r20, r1
 3fc:	55 0b       	sbc	r21, r21
 3fe:	11 24       	eor	r1, r1
 400:	40 fd       	sbrc	r20, 0
 402:	4a c0       	rjmp	.+148    	; 0x498 <__DATA_REGION_LENGTH__+0x98>
         SinCos[a] += 1;
      else
         SinCos[a] -= 1;
 404:	40 91 1a 3c 	lds	r20, 0x3C1A	; 0x803c1a <__data_end+0x18>
 408:	50 91 1b 3c 	lds	r21, 0x3C1B	; 0x803c1b <__data_end+0x19>
 40c:	41 50       	subi	r20, 0x01	; 1
 40e:	51 09       	sbc	r21, r1
 410:	40 93 1a 3c 	sts	0x3C1A, r20	; 0x803c1a <__data_end+0x18>
 414:	50 93 1b 3c 	sts	0x3C1B, r21	; 0x803c1b <__data_end+0x19>
int Template = 0x1235;

int main(void)
{
   for ( int a = 0; a < 15; a++ )
   {  if(Template & (1 << a))
 418:	a9 01       	movw	r20, r18
 41a:	48 e0       	ldi	r20, 0x08	; 8
 41c:	54 02       	muls	r21, r20
 41e:	41 2d       	mov	r20, r1
 420:	55 0b       	sbc	r21, r21
 422:	11 24       	eor	r1, r1
 424:	40 fd       	sbrc	r20, 0
 426:	2d c0       	rjmp	.+90     	; 0x482 <__DATA_REGION_LENGTH__+0x82>
         SinCos[a] += 1;
      else
         SinCos[a] -= 1;
 428:	40 91 1c 3c 	lds	r20, 0x3C1C	; 0x803c1c <__data_end+0x1a>
 42c:	50 91 1d 3c 	lds	r21, 0x3C1D	; 0x803c1d <__data_end+0x1b>
 430:	41 50       	subi	r20, 0x01	; 1
 432:	51 09       	sbc	r21, r1
 434:	40 93 1c 3c 	sts	0x3C1C, r20	; 0x803c1c <__data_end+0x1a>
 438:	50 93 1d 3c 	sts	0x3C1D, r21	; 0x803c1d <__data_end+0x1b>
int Template = 0x1235;

int main(void)
{
   for ( int a = 0; a < 15; a++ )
   {  if(Template & (1 << a))
 43c:	33 0f       	add	r19, r19
 43e:	22 0b       	sbc	r18, r18
 440:	33 0f       	add	r19, r19
 442:	32 2f       	mov	r19, r18
 444:	22 1f       	adc	r18, r18
 446:	20 ff       	sbrs	r18, 0
 448:	11 c0       	rjmp	.+34     	; 0x46c <__DATA_REGION_LENGTH__+0x6c>
         SinCos[a] += 1;
 44a:	20 91 1e 3c 	lds	r18, 0x3C1E	; 0x803c1e <__data_end+0x1c>
 44e:	30 91 1f 3c 	lds	r19, 0x3C1F	; 0x803c1f <__data_end+0x1d>
 452:	2f 5f       	subi	r18, 0xFF	; 255
 454:	3f 4f       	sbci	r19, 0xFF	; 255
 456:	20 93 1e 3c 	sts	0x3C1E, r18	; 0x803c1e <__data_end+0x1c>
 45a:	30 93 1f 3c 	sts	0x3C1F, r19	; 0x803c1f <__data_end+0x1d>
 45e:	08 95       	ret
 460:	01 96       	adiw	r24, 0x01	; 1
 462:	80 93 02 3c 	sts	0x3C02, r24	; 0x803c02 <__data_end>
 466:	90 93 03 3c 	sts	0x3C03, r25	; 0x803c03 <__data_end+0x1>
 46a:	33 cf       	rjmp	.-410    	; 0x2d2 <main+0x1e>
      else
         SinCos[a] -= 1;
 46c:	20 91 1e 3c 	lds	r18, 0x3C1E	; 0x803c1e <__data_end+0x1c>
 470:	30 91 1f 3c 	lds	r19, 0x3C1F	; 0x803c1f <__data_end+0x1d>
 474:	21 50       	subi	r18, 0x01	; 1
 476:	31 09       	sbc	r19, r1
 478:	20 93 1e 3c 	sts	0x3C1E, r18	; 0x803c1e <__data_end+0x1c>
 47c:	30 93 1f 3c 	sts	0x3C1F, r19	; 0x803c1f <__data_end+0x1d>
   }
   return SinCos[4];
}
 480:	08 95       	ret

int main(void)
{
   for ( int a = 0; a < 15; a++ )
   {  if(Template & (1 << a))
         SinCos[a] += 1;
 482:	40 91 1c 3c 	lds	r20, 0x3C1C	; 0x803c1c <__data_end+0x1a>
 486:	50 91 1d 3c 	lds	r21, 0x3C1D	; 0x803c1d <__data_end+0x1b>
 48a:	4f 5f       	subi	r20, 0xFF	; 255
 48c:	5f 4f       	sbci	r21, 0xFF	; 255
 48e:	40 93 1c 3c 	sts	0x3C1C, r20	; 0x803c1c <__data_end+0x1a>
 492:	50 93 1d 3c 	sts	0x3C1D, r21	; 0x803c1d <__data_end+0x1b>
 496:	d2 cf       	rjmp	.-92     	; 0x43c <__DATA_REGION_LENGTH__+0x3c>
 498:	40 91 1a 3c 	lds	r20, 0x3C1A	; 0x803c1a <__data_end+0x18>
 49c:	50 91 1b 3c 	lds	r21, 0x3C1B	; 0x803c1b <__data_end+0x19>
 4a0:	4f 5f       	subi	r20, 0xFF	; 255
 4a2:	5f 4f       	sbci	r21, 0xFF	; 255
 4a4:	40 93 1a 3c 	sts	0x3C1A, r20	; 0x803c1a <__data_end+0x18>
 4a8:	50 93 1b 3c 	sts	0x3C1B, r21	; 0x803c1b <__data_end+0x19>
 4ac:	b5 cf       	rjmp	.-150    	; 0x418 <__DATA_REGION_LENGTH__+0x18>
 4ae:	40 91 18 3c 	lds	r20, 0x3C18	; 0x803c18 <__data_end+0x16>
 4b2:	50 91 19 3c 	lds	r21, 0x3C19	; 0x803c19 <__data_end+0x17>
 4b6:	4f 5f       	subi	r20, 0xFF	; 255
 4b8:	5f 4f       	sbci	r21, 0xFF	; 255
 4ba:	40 93 18 3c 	sts	0x3C18, r20	; 0x803c18 <__data_end+0x16>
 4be:	50 93 19 3c 	sts	0x3C19, r21	; 0x803c19 <__data_end+0x17>
 4c2:	98 cf       	rjmp	.-208    	; 0x3f4 <main+0x140>
 4c4:	40 91 16 3c 	lds	r20, 0x3C16	; 0x803c16 <__data_end+0x14>
 4c8:	50 91 17 3c 	lds	r21, 0x3C17	; 0x803c17 <__data_end+0x15>
 4cc:	4f 5f       	subi	r20, 0xFF	; 255
 4ce:	5f 4f       	sbci	r21, 0xFF	; 255
 4d0:	40 93 16 3c 	sts	0x3C16, r20	; 0x803c16 <__data_end+0x14>
 4d4:	50 93 17 3c 	sts	0x3C17, r21	; 0x803c17 <__data_end+0x15>
 4d8:	7b cf       	rjmp	.-266    	; 0x3d0 <main+0x11c>
 4da:	40 91 14 3c 	lds	r20, 0x3C14	; 0x803c14 <__data_end+0x12>
 4de:	50 91 15 3c 	lds	r21, 0x3C15	; 0x803c15 <__data_end+0x13>
 4e2:	4f 5f       	subi	r20, 0xFF	; 255
 4e4:	5f 4f       	sbci	r21, 0xFF	; 255
 4e6:	40 93 14 3c 	sts	0x3C14, r20	; 0x803c14 <__data_end+0x12>
 4ea:	50 93 15 3c 	sts	0x3C15, r21	; 0x803c15 <__data_end+0x13>
 4ee:	5e cf       	rjmp	.-324    	; 0x3ac <main+0xf8>
 4f0:	4f 5f       	subi	r20, 0xFF	; 255
 4f2:	5f 4f       	sbci	r21, 0xFF	; 255
 4f4:	40 93 12 3c 	sts	0x3C12, r20	; 0x803c12 <__data_end+0x10>
 4f8:	50 93 13 3c 	sts	0x3C13, r21	; 0x803c13 <__data_end+0x11>
 4fc:	46 cf       	rjmp	.-372    	; 0x38a <main+0xd6>
 4fe:	4f 5f       	subi	r20, 0xFF	; 255
 500:	5f 4f       	sbci	r21, 0xFF	; 255
 502:	40 93 10 3c 	sts	0x3C10, r20	; 0x803c10 <__data_end+0xe>
 506:	50 93 11 3c 	sts	0x3C11, r21	; 0x803c11 <__data_end+0xf>
 50a:	33 cf       	rjmp	.-410    	; 0x372 <main+0xbe>
 50c:	4f 5f       	subi	r20, 0xFF	; 255
 50e:	5f 4f       	sbci	r21, 0xFF	; 255
 510:	40 93 0e 3c 	sts	0x3C0E, r20	; 0x803c0e <__data_end+0xc>
 514:	50 93 0f 3c 	sts	0x3C0F, r21	; 0x803c0f <__data_end+0xd>
 518:	20 cf       	rjmp	.-448    	; 0x35a <main+0xa6>
 51a:	4f 5f       	subi	r20, 0xFF	; 255
 51c:	5f 4f       	sbci	r21, 0xFF	; 255
 51e:	40 93 0c 3c 	sts	0x3C0C, r20	; 0x803c0c <__data_end+0xa>
 522:	50 93 0d 3c 	sts	0x3C0D, r21	; 0x803c0d <__data_end+0xb>
 526:	0d cf       	rjmp	.-486    	; 0x342 <main+0x8e>
 528:	01 96       	adiw	r24, 0x01	; 1
 52a:	80 93 0a 3c 	sts	0x3C0A, r24	; 0x803c0a <__data_end+0x8>
 52e:	90 93 0b 3c 	sts	0x3C0B, r25	; 0x803c0b <__data_end+0x9>
 532:	fb ce       	rjmp	.-522    	; 0x32a <main+0x76>
 534:	01 96       	adiw	r24, 0x01	; 1
 536:	80 93 08 3c 	sts	0x3C08, r24	; 0x803c08 <__data_end+0x6>
 53a:	90 93 09 3c 	sts	0x3C09, r25	; 0x803c09 <__data_end+0x7>
 53e:	ea ce       	rjmp	.-556    	; 0x314 <main+0x60>
 540:	01 96       	adiw	r24, 0x01	; 1
 542:	80 93 06 3c 	sts	0x3C06, r24	; 0x803c06 <__data_end+0x4>
 546:	90 93 07 3c 	sts	0x3C07, r25	; 0x803c07 <__data_end+0x5>
 54a:	d9 ce       	rjmp	.-590    	; 0x2fe <main+0x4a>
 54c:	01 96       	adiw	r24, 0x01	; 1
 54e:	80 93 04 3c 	sts	0x3C04, r24	; 0x803c04 <__data_end+0x2>
 552:	90 93 05 3c 	sts	0x3C05, r25	; 0x803c05 <__data_end+0x3>
 556:	c8 ce       	rjmp	.-624    	; 0x2e8 <main+0x34>

Optimise for size geeft wel een loop:

code:


int main(void)
{
 2b4:	40 91 00 3c 	lds	r20, 0x3C00	; 0x803c00 <__DATA_REGION_ORIGIN__>
 2b8:	50 91 01 3c 	lds	r21, 0x3C01	; 0x803c01 <__DATA_REGION_ORIGIN__+0x1>
 2bc:	e2 e0       	ldi	r30, 0x02	; 2
 2be:	fc e3       	ldi	r31, 0x3C	; 60
   for ( int a = 0; a < 15; a++ )
 2c0:	80 e0       	ldi	r24, 0x00	; 0
 2c2:	90 e0       	ldi	r25, 0x00	; 0
 2c4:	0b c0       	rjmp	.+22     	; 0x2dc <main+0x28>
   {  if(Template & (1 << a))
         SinCos[a] += 1;
 2c6:	20 81       	ld	r18, Z
 2c8:	31 81       	ldd	r19, Z+1	; 0x01
 2ca:	2f 5f       	subi	r18, 0xFF	; 255
 2cc:	3f 4f       	sbci	r19, 0xFF	; 255
 2ce:	20 83       	st	Z, r18
 2d0:	31 83       	std	Z+1, r19	; 0x01
int SinCos[16] = {};
int Template = 0x1235;

int main(void)
{
   for ( int a = 0; a < 15; a++ )
 2d2:	01 96       	adiw	r24, 0x01	; 1
 2d4:	32 96       	adiw	r30, 0x02	; 2
 2d6:	8f 30       	cpi	r24, 0x0F	; 15
 2d8:	91 05       	cpc	r25, r1
 2da:	a1 f0       	breq	.+40     	; 0x304 <main+0x50>
   {  if(Template & (1 << a))
 2dc:	9a 01       	movw	r18, r20
 2de:	08 2e       	mov	r0, r24
 2e0:	02 c0       	rjmp	.+4      	; 0x2e6 <main+0x32>
 2e2:	35 95       	asr	r19
 2e4:	27 95       	ror	r18
 2e6:	0a 94       	dec	r0
 2e8:	e2 f7       	brpl	.-8      	; 0x2e2 <main+0x2e>
 2ea:	20 fd       	sbrc	r18, 0
 2ec:	ec cf       	rjmp	.-40     	; 0x2c6 <main+0x12>
         SinCos[a] += 1;
      else
         SinCos[a] -= 1;
 2ee:	20 81       	ld	r18, Z
 2f0:	31 81       	ldd	r19, Z+1	; 0x01
 2f2:	21 50       	subi	r18, 0x01	; 1
 2f4:	31 09       	sbc	r19, r1
 2f6:	20 83       	st	Z, r18
 2f8:	31 83       	std	Z+1, r19	; 0x01
int SinCos[16] = {};
int Template = 0x1235;

int main(void)
{
   for ( int a = 0; a < 15; a++ )
 2fa:	01 96       	adiw	r24, 0x01	; 1
 2fc:	32 96       	adiw	r30, 0x02	; 2
 2fe:	8f 30       	cpi	r24, 0x0F	; 15
 300:	91 05       	cpc	r25, r1
 302:	61 f7       	brne	.-40     	; 0x2dc <main+0x28>
         SinCos[a] += 1;
      else
         SinCos[a] -= 1;
   }
   return SinCos[4];
}
 304:	80 91 0a 3c 	lds	r24, 0x3C0A	; 0x803c0a <__data_end+0x8>
 308:	90 91 0b 3c 	lds	r25, 0x3C0B	; 0x803c0b <__data_end+0x9>
 30c:	08 95       	ret