Hallo! Gibt es eine Möglichkeit den gcc dazu zu bringen einzelne Funktion mit Os und andere mit O3 zu kompilieren? Beispiel wäre z.B. ein Programm mit zeitkritischen Interrupts: Den Interrupts spendiert man zugunsten der Geschwindigkeit mehr Flash, bei dem eher unkritischen Hauptprogramm versucht man Platz zu sparen. Grüße Robert
Robert B. schrieb: > Gibt es eine Möglichkeit den gcc dazu zu bringen einzelne Funktion mit > Os und andere mit O3 zu kompilieren? Ja.
http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html http://gcc.gnu.org/onlinedocs/gcc/Function-Specific-Option-Pragmas.html#Function-Specific-Option-Pragmas
Oh, das ist ja schick. Gibt's aber auch noch nicht so lange, oder? Ansonsten kann man natürlich auch einfach die Funktionen, die andere optimierungs-Einstellungen brauchen, in eine eigene .c-Datei (oder mehrere) stecken und diese mit den speziellen Einstellungen übersetzen.
Hm, schade, so gehts nicht: __attribute__((optimize("O3"))) ISR(TIMER1_COMPA_vect) { ... } führt zu warning: 'optimize' attribute directive ignored Ein testweises "const" (was quatsch ist) läuft durch. Die Schreibweise O3 -O3 3 etc. habe ich schon versucht. Grüße Robert
Könnte sein, dass dies erst ab 4.4 geht. Bei den Pragmas steht das so explizit drin. Allerdings kann es auch sein, dass der Makro ISR() mitmischt. Muss man genauer ansehen, was dabei hinten aus dem Präprozessor rauskommt. Ggf. ist auch function-declaration __attribute___(...) { ... } also Attribute dahinter der richtige Weg.
Scheint so, denn unter http://gcc.gnu.org/onlinedocs/gcc-4.3.4/gcc/Function-Attributes.html#Function-Attributes wird dieses Attribut nicht erwähnt.
Robert B. schrieb: > Beispiel wäre z.B. ein Programm mit zeitkritischen Interrupts: Den > > Interrupts spendiert man zugunsten der Geschwindigkeit mehr Flash, Schlechtes Beispiel. ISR's, besonders zeitkritische, sind (bzw. sollten) so kurz sein, daß da die verschiedenen Optimierungsstufen gar keinen Unterschied machen. Und im Falle des avr-gcc ist -O3 sowieso zweckfrei. Ernsthaft schneller als mit -Os wird es damit nicht. Als Risk-Prozessor mit einem (oder zwei) Zyklen pro Befehl gilt beim AVR kurz = schnell. Oliver
Rolf Magnus schrieb: > Scheint so, denn unter > http://gcc.gnu.org/onlinedocs/gcc-4.3.4/gcc/Functi... > wird dieses Attribut nicht erwähnt. Ja, hab's gerade ausprobiert: 4.4.2 unterstützt das Attribut, 4.3.4 und 4.2.4 nicht.
Oliver schrieb: > Robert B. schrieb: >> Beispiel wäre z.B. ein Programm mit zeitkritischen Interrupts: Den >> >> Interrupts spendiert man zugunsten der Geschwindigkeit mehr Flash, > > Schlechtes Beispiel. ISR's, besonders zeitkritische, sind (bzw. sollten) > so kurz sein, daß da die verschiedenen Optimierungsstufen gar keinen > Unterschied machen. > > Und im Falle des avr-gcc ist -O3 sowieso zweckfrei. Ernsthaft schneller > als mit -Os wird es damit nicht. Als Risk-Prozessor mit einem (oder > zwei) Zyklen pro Befehl gilt beim AVR kurz = schnell. > > Oliver -Os
1 | if (tmp_vel > 0) { |
2 | 722: 14 16 cp r1, r20 |
3 | 724: 1c f4 brge .+6 ; 0x72c <__vector_11+0xa2> |
4 | act_pos_buf++; |
5 | 726: cb 01 movw r24, r22 |
6 | 728: 01 96 adiw r24, 0x01 ; 1 |
7 | 72a: 02 c0 rjmp .+4 ; 0x730 <__vector_11+0xa6> |
8 | } else { |
9 | act_pos_buf--; |
10 | 72c: cb 01 movw r24, r22 |
11 | 72e: 01 97 sbiw r24, 0x01 ; 1 |
12 | } |
-O3
1 | if (tmp_vel > 0) { |
2 | 7b2: 14 16 cp r1, r20 |
3 | 7b4: 0c f0 brlt .+2 ; 0x7b8 <__vector_11+0xae> |
4 | 7b6: 46 c0 rjmp .+140 ; 0x844 <__vector_11+0x13a> |
5 | act_pos_buf++; |
6 | 7b8: cb 01 movw r24, r22 |
7 | 7ba: 01 96 adiw r24, 0x01 ; 1 |
8 | } else { |
9 | act_pos_buf--; |
10 | } |
11 | ... |
12 | if (tmp_vel > 0) { |
13 | act_pos_buf++; |
14 | } else { |
15 | act_pos_buf--; |
16 | 844: cb 01 movw r24, r22 |
17 | 846: 01 97 sbiw r24, 0x01 ; 1 |
18 | 848: b9 cf rjmp .-142 ; 0x7bc <__vector_11+0xb2> |
19 | } |
das mit avr-gcc 4.3.3 Keine Ahnung warum der gcc bei -O3 einen Code dermaßen zerrupft - super unschön. Zumal mit schlechter lesbarer Nachhilfe die Optimierung viel besser ist: -O3 / Os
1 | act_pos_buf--; |
2 | 7b2: cb 01 movw r24, r22 |
3 | 7b4: 01 97 sbiw r24, 0x01 ; 1 |
4 | if (tmp_vel > 0) { |
5 | 7b6: 14 16 cp r1, r20 |
6 | 7b8: 14 f4 brge .+4 ; 0x7be <__vector_11+0xb4> |
7 | act_pos_buf += 2; |
8 | 7ba: cb 01 movw r24, r22 |
9 | 7bc: 01 96 adiw r24, 0x01 ; 1 |
10 | } |
unverständlich warum er nicht erzeugt:
1 | movw r24, r22 |
2 | sbiw r24, 0x01 |
3 | sbrs r20,7 |
4 | adiw r24, 0x02 |
...sollte ja equivalent sein... Grüße Robert
Robert B. schrieb: > unverständlich warum er nicht erzeugt: > [...] > ...sollte ja equivalent sein... Weil ein Compiler kein Werkzeug ist, das in jedem speziellen Einzelfall einen garantiert nicht weiter optimierbaren Code erzeugt. Aber es ist durchaus möglich, ihm das in diesem Fall beizubringen, der Quellcode ist öffentlich.
Vor allem muss ja jemand die Optimierung mal dem Compiler beigebracht haben.
A. K. schrieb: > Robert B. schrieb: > >> unverständlich warum er nicht erzeugt: >> [...] >> ...sollte ja equivalent sein... > > Weil ein Compiler kein Werkzeug ist, das in jedem speziellen Einzelfall > einen garantiert nicht weiter optimierbaren Code erzeugt. Aber es ist > durchaus möglich, ihm das in diesem Fall beizubringen, der Quellcode ist > öffentlich. Warum mit leicht genervten Unterton? Ist doch völlig fehl am Platz... Ich stelle hier eine Frage rein und freue mich wenn jetzt jemand sagt "hilf dem Compiler so und so". Dass der Compiler nicht jeden Spezialfall erkennen kann (und da habe ich auch schon ein paar inline-hacks aus gutem Grund gemacht) ist völlig klar - bei diesem Szenario wundert es mich halt. Spätestens bei dem "helfenden" C-Code sollte der Compiler doch erkennen, dass er nachdem er den Drecrement gemacht hat abhängig vom Vorzeichen nur einen einzigen Befehl überspringen oder ausführen muss.
Robert B. schrieb: > Warum mit leicht genervten Unterton? Ist doch völlig fehl am Platz... Wie es in den Wald reinruft, so schallt es zurück. Vielleicht habe ich deinen Anspruch "unverständlich warum er nicht erzeugt:" auch etwas misverstanden. Jedenfalls ist der Code, den du als optimalen Ersatz gebastelt hat, nicht unbedingt typisch für den Output eines Compilers. Es sei denn jemand hat ihn speziell dafür optimiert (sowas kommt gelegentlich bei auf spezielle Sequenzen bekannter Benchmarks optimierenden Compilern vor). > Spätestens bei dem "helfenden" C-Code sollte der Compiler doch erkennen, > dass er nachdem er den Drecrement gemacht hat abhängig vom Vorzeichen > nur einen einzigen Befehl überspringen oder ausführen muss. Deine Variante setzt voraus, dass beide Zweige vom "if" in Beziehung gesetzt werden und der Compiler erkennt, dass er die darin enthaltene Arithmetik aufeinander aufbauen kann, statt sie alternativ auszuführen. Sowas lässt sich in den Compiler einbauen, aber offenbar hat das eben niemand getan. Was ich hingegen auf Architekturen mit Predication (z.B. ARM) schon gesehen habe ist sinngemäss sowas wie cmp tmp_vel, #0 if.gt add act_pos_buf, #1 if.le sub act_pos_buf, #1 und bei bei solchen mit bedingtem Move (x86 >= 686) findet man sowas wie add temp, act_pos_buf, #1 sub act_pos_buf, #1 cmp tmp_vel, #0 if.gt move act_pos_buf, temp um den oft problematischen Sprung zu vermeiden. Das sind eher generische Optimierungen. Das letztere allerdings liesse sich auch mit AVRs machen, es wird dort aber weder kürzer noch schneller.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.