arm-none-eabi-gcc unterschlägt ein case 0 im switch?!

Gast #5849606
In meinem Code habe ich eine Switch-Anweisungen:
1
switch (value >> 13) {
2
case 0: ...; break;
3
case 1: ...; break;
4
case 2: ...; break;
5
case 3: ...; break;
6
case 4: ...; break;
7
case 5: /* fall-thorugh */
8
case 6: /* fall-thorugh */
9
case 7: ...; break;
10
}  // kein default

Nun übersetzt arm-none-eabi-gcc das in
1
        asrs    r2, r3, #13         ; value in r3
2
        str     r3, [r4, #3856]
3
        subs    r2, r2, #1          ; kein Fall 0?!
4
        cmp     r2, #6              ; **
5
        bhi     .L1507
6
        tbh     [pc, r2, lsl #1]
7
.L1509:
8
        .2byte  (.L1508-.L1509)/2   ; nur 7 statt 8 Fälle
9
        .2byte  (.L1510-.L1509)/2
10
        .2byte  (.L1511-.L1509)/2
11
        .2byte  (.L1512-.L1509)/2
12
        .2byte  (.L1513-.L1509)/2   ; 3x identisch wg.
13
        .2byte  (.L1513-.L1509)/2   ; fall-through
14
        .2byte  (.L1513-.L1509)/2
15
        .p2align 1
16
.L1512:
17
        ...

Wo ist der Fall 0 abgeblieben? Auch weiter oben im Code gibt es keine 
Behandlung falls value == 0.

Ein weiteres Problem ist, dass value >> 13 durch die Programmlogik nicht 
größer als 7 werden kann und die Prüfung (**) überflüssig ist. Aber 
selbst wenn ich (value >> 13) auf ein enum {_0, ..., _7} caste, bleibt 
die Prüfung (**) im Code. Wie mache ich es richtig?
Gast
Wo die 0 geblieben ist kann ich dir anhand des gezeigten auch nicht 
sagen. Die Prüfung wirst du aber fürchte nicht weg bekommen. Auf enums 
optimieren die mir bekannten Compiler leider (noch) nicht.
Gast
Jemand schrieb:
> Es hilft, wenn du nicht die ganzen interessanten Teile von deinem Code
> entfernst.

Naja, da passiert fast immer das gleiche: Es wird ein Wert berechnet. 
Die Ausnahme ist tatsächlich case 0, wo das hier passiert:
1
GPIOA->BSRR = 0x00cf0000;
2
GPIOD->BSRR = 0x03000000;
3
GPIOA->MODER &= DATA_MODER_MASK_A;
4
GPIOD->MODER &= DATA_MODER_MASK_D;

Und ja, der C-Code paßt zum Asm-Code.
Gast
A. K. schrieb:
> Mal vorausgesetzt, der Asm-Code hat überhaupt etwas mit dem gezeigten
> Quellcode-Abriss zu tun: Kann es sein, dass sich aus dem übrigen Code
> ergibt, dass 0 nicht vorkommen kann?

Doch, kommt regelmäßig vor!
Peter schrieb:
>> Es hilft, wenn du nicht die ganzen interessanten Teile von deinem Code
>> entfernst.
>
> Naja, da passiert fast immer das gleiche: Es wird ein Wert berechnet.
> Die Ausnahme ist tatsächlich case 0, wo das hier passiert:

Nicht der Code im Switch ist interessant, sondern der davor.
Beitrag #5849653 wurde von einem Moderator gelöscht.
Gast
Bauform B. schrieb:
> Könnte es sein, dass der gcc doch gemerkt hat, dass nur 0 bis 7
> vorkommen können und der case 0 bei .L1507 behandelt wird?

Nur weil die Werte zwischen 0 und 7 liegen, heißt das ja nicht das 0 - 1 
== 7 ist. Der Sprung nach .L1507 kann nur genommen werden, wenn der 
ursprüngliche Wert größer als 7 war.

Der 0-Fall ist mit dem r2 = r2-1 verschwunden.
Gast
Jemand schrieb:
> Der bei case 0: ist auch interessant. Wenn da UB vorkommt, kann der auch
> einfach so flöten gehen.

Entschuldige, UB? Unterbrechung, also Interrupt?

Durch die Programmlogik kann während der Ausführung der Funktion 
eigentlich kein weiterer IR ausgelöst werden.
Peter schrieb:
> Nur weil die Werte zwischen 0 und 7 liegen, heißt das ja nicht das 0 - 1
> == 7 ist.

0-1 = 0xFFFFFFFF und das ist grösser als 6. Da der Compiler weiss, dass 
ein 16 Bit IDR >> 13 nur den Wertebereich 0..7 hat, passt es. GCC 
versucht den möglichen Wertebereich von Daten zu erfassen, um daraus 
Optimierungen abzuleiten.
Gast
A. K. schrieb:
> 0-1 = 0xFFFFFFFF und das ist grösser als 6. Da der Compiler weiss, dass
> ein 16 Bit IDR >> 13 nur den Wertebereich 0..7 hat, passt es. GCC
> versucht den möglichen Wertebereich von Daten zu erfassen, um daraus
> Optimierungen abzuleiten.

Ja, na klar, Du hast völlig recht, ist ja ein unsigned-Vergleich!

Bei .L1507 steht der Code von Fall 0. Herzlichen Dank für den Tip!

Aber wieso das jetzt eine Optimierung sein soll?
Die Codegenerierung von Switch-Statements enthält einige Grundschemata, 
wie das in Code umgesetzt wird. Also ob als Tabelle, Baum, inkrementelle 
Subtraktion, ... Anhand von Analysen u.A. der Werteverteilung wird eines 
der Schemata ausgewählt. Das wird dann eben schematisch umgesetzt und 
muss nicht immer das absolute Optimum darstellen.

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 7 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.