Fremdschleife, die vom PIC-Compiler von MicroChip erzeugt wird

Wir verwenden die Lite-Version des MicroChip PIC-Compilers, vielleicht ist das der Grund, aber diese einfache Ein-Bit-Verschiebung erzeugt eine Schleife, wo keine notwendig ist. Da die Anzahl der Verschiebungen 1 ist (eine Konstante), würde ich erwarten, dass der Compiler keine Schleife erstellt – eine elementare Optimierung.

Gibt es einen Compiler-Optimierungsschalter, der die Schleife lindern würde? Hier ist der Code für die Verschiebung:

    long foo;   // a 32-bit value

// Shift foo one bit. 
// A one-iteration loop is created!

    foo >>= 1;

Und hier ist der vom Compiler generierte Code. Wie Sie sehen können, wird die Verschiebung mit einer Schleife mit einer Iteration umschlossen.

  07F6    3001     MOVLW 0x1
  07F7    00F2     MOVWF 0x72
  07F8    37F6     ASRF 0x76, F
  07F9    0CF5     RRF 0x75, F
  07FA    0CF4     RRF 0x74, F
  07FB    0CF3     RRF 0x73, F
  07FC    0BF2     DECFSZ 0x72, F

BEARBEITEN

Compiler-Version: HI-TECH C-Compiler für PIC10/12/16-MCUs (Lite-Modus) V9.81

Kannst du genau posten welcher Compiler? Micochip bietet jetzt zusätzlich zu den Compilern der C-Serie Compiler der XC-Serie an, und seit Microchip Hi-Tech übernommen hat, nennen manche Leute Hi-Tech-Compiler auch Mikrochip-Compiler.
Ich habe das heute auch bei der kostenlosen Edition von MPLAB XC8 bemerkt; Ich habe an allen meinen Haaren gezogen, weil ich nicht widerstehen konnte, nachdem ich all die Sachen gesehen hatte, die XC8 macht. Gute Nachrichten, muss ein paar Monate nicht zum Friseur..
Wenn Sie sich mit einzelnen Anweisungen herumquälen, verwenden Sie keinen Compiler.
@OlinLathrop - Unsinn. Ich würde ein ganzes Kapitel darüber schreiben, wie falsch diese Aussage ist. Hier geht es nicht darum, sich über einzelne Anweisungen zu quälen, sondern um einen Hinweis darauf, dass der Compiler sehr leistungsschwachen Code generiert.
@Rocket: Sie vermissen den Punkt, dass der Compiler das tut, was er tut. Sie kümmern sich um einzelne Anweisungen, da Sie sie sich angesehen und entschieden haben, dass sie ineffizient sind. Entweder verwenden Sie eine Hochsprache oder nicht. Wenn Sie es sind, beschweren Sie sich nicht darüber, was unter der Motorhaube vor sich geht. Wenn Sie etwas Besseres wollen, zahlen Sie für den Optimierer, besorgen Sie sich einen besseren Compiler (falls es den überhaupt gibt) oder schreiben Sie in Assembler.
@OlinLathrop - Ich wünschte, ich hätte Raum, um ausführlich darauf einzugehen, warum Sie hier falsch liegen.
@Rocketmagnet du kannst mehrere Kommentare schreiben :)
Aus all den offensichtlichen Gründen ist es schön, in C zu schreiben. Das Ablegen zur Montage ist bei Bedarf in Ordnung. Ich stimme @OlinLathrop zu, dass die Compilerausgabe nicht besessen sein sollte; Wir sind uns nicht einig, dass die Erzeugung einer Schleife für eine 1-Bit-Verschiebung im Jahr 2012 vernünftig ist.

Antworten (3)

Möglicherweise liegt dies an der fehlenden Optimierung der Lite-Version.
Du könntest es versuchen,

foo /= 2;

und sehen, ob es hilft.

foo /= 2 generiert 28 Move-Anweisungen plus einen CALL an eine lange 32-Bit-Divisionsroutine.
Haben Sie versucht, den Code mit XC8 zu kompilieren?

Ich habe verschiedene Optimierungsoptionen ausprobiert, aber nichts hat den Compiler dazu gebracht, vernünftigen Code zu produzieren. Ähnliche Erfahrungen habe ich auch mit dem C18-Compiler gemacht. Ein Teil des Codes, den es generiert, ist erstaunlich dumm, und ich habe schließlich mehrere Arten von Makros und Tricks verwendet. Am Ende konnte ich es dazu bringen, Code zu generieren, der fast so gut ist wie handoptimierter Assembler, während es ziemlich lesbar bleibt.

Dieses nicht sehr schöne Makro erzeugt den richtigen Assembler für eine lange Rechtsverschiebung.

long foo;

#define R_SHIFT_LONG(x)     asm("asrf    _" #x "+3, f"); \
                            asm("rrf     _" #x "+2, f"); \
                            asm("rrf     _" #x "+1, f"); \
                            asm("rrf     _" #x "+0, f");

void main(void)
{
    foo=1234;

    R_SHIFT_LONG(foo);
}
Ich weiß nicht, für welche Maschine dieses Makro Ihrer Meinung nach gedacht ist, aber es gibt keinen 8-Bit-PIC, der sowohl einen ASRF- als auch einen RRCF-Befehl hat.
Wie seltsam. Der Compiler hat weder einen Fehler noch eine Warnung generiert, sondern rrcf einfach stillschweigend in rrf konvertiert.
Ah, Sie gehen also anscheinend von einem der erweiterten 14-Bit-Kerne aus. Wenn ihr Anweisungen guckt, müsst ihr wirklich sagen, für welchen PIC der Code ist.
@OlinLathrop - Nun, ich gehe davon aus, dass das OP denselben Befehlssatz verwendet.

Jetzt, wo ich die Gelegenheit hatte, mir Ihren Code anzusehen, ist es wirklich nicht so unvernünftig. Abhängig von dem bestimmten Modell-PIC hätte dies in 4 oder 5 Anweisungen durchgeführt werden können, aber nur in dem speziellen Fall des Verschiebens um ein Bit . Es erscheint ziemlich vernünftig, dass der Compiler als Erstes Code für den allgemeinen Fall schreibt, in dem die Verschiebung für N Bits erfolgt. Ich wäre überrascht, wenn es eine Verschiebung um ein Bit nicht als Sonderfall mit aktivierten Optimierungen erkennen würde, aber wieso ist das nicht genau das, was Sie ohne Optimierung erwarten?

Wenn Sie sich jedoch für diese Detailgenauigkeit interessieren, sollten Sie in Assembler schreiben. Durch die Verwendung eines Compilers haben Sie die detaillierte Befehlsgenerierung delegiert. Außerdem ist es grob unfair, einen Compiler mit deaktivierten Optimierungen zu bewerten.

Der Compiler tut dies anscheinend auch mit aktivierten und auf 9 gesetzten Optimierungen.