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?
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?
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.
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:
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.
A. K. schrieb:> Nicht der Code im Switch ist interessant, sondern der davor.
Der bei case 0: ist auch interessant. Wenn da UB vorkommt, kann der auch
einfach so flöten gehen.
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.
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:> Entschuldige, UB? Unterbrechung, also Interrupt?>> Durch die Programmlogik kann während der Ausführung der Funktion> eigentlich kein weiterer IR ausgelöst werden.Undefined Behavior
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.
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?
Peter schrieb:> Aber wieso das jetzt eine Optimierung sein soll?
Wenn der bekannte Wertebereich exakt mit der Anzahl Fällen
übereinstimmt, geht es besser. Es schien wohl nicht lohnend, nur dafür
ein separates Schema im GCC vorzusehen.
A. K. schrieb:> Bei exakt 2^N Fällen geht es geringfügig besser. Es schien wohl nicht> lohnend, nur dafür ein separates Schema im GCC vorzusehen.
Ähm, es sind 2^3 Fälle. :-)
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.