Forum: Compiler & IDEs Optimizer Warnung bei SDCC


von Tom (Gast)


Lesenswert?

Hallo,

ich habe ein Problem mit dem freien SDCC Compiler. Ich setzte als IDE
Visual Studio ein, und lasse mir über ein Makefile mittels SDCC die
C-Dateien übersetzten. Controller: AT89C51CC03 Nun bekomme immer die
Warnung:

1>main.c:67: warning 110: conditional flow changed by optimizer: so said
EVELYN the modified DOG

Ich habe bereits in Erfahrung gebracht, dass der Compiler an dieser
Stelle etwas unsauber arbeitet, und nicht erkennt, wenn z.B. die
Variable einer Fallunterscheidung (SWITCH/CASE) in einer Interrupt
Routine verändert wurde.

Nun würde ich gerne von einem Profi wissen, wie ich am besten die
Optimierung für die Funktion die diese Fallunterscheidung enthält
deaktiviere. Irgendwie hat der Zusatz volatile bei der Variablen auch
nicht geholfen.

DANKE und Beste Grüße an alle Besucher der Foren und das Team von
www.mikrocontroller.net

TOM

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Ein minimales Codebeispiel, das dieses Problem erzeugt, ist zu viel 
verlangt?

von Tom (Gast)


Lesenswert?

Hallo,

eigentlich wollte ich gerne wissen, wie die Optimierung generell für ein 
File bzw. eine Funktion abgeschaltet werden kann. Aber wenn unbedingt 
Code gewünscht ist:
1
volatile BYTE __xdata cmd5 = CMD_STOPP;
2
3
.
4
.
5
.
6
7
8
void doMot5(void)
9
{
10
#ifdef KASDEB
11
  can_data.INDEX = 0x4444;
12
        can_data.DATA = (((long)(M5POW)) << 28) + (((long)(M5DIR)) << 24)
13
        + (((long)(wait)) << 8) + ((long)(cmd5));
14
  SendCANMsg();
15
#endif
16
17
  switch(cmd5)
18
  {
19
    case CMD_STOPP:
20
      if (M5POW == ON)
21
        {
22
        M5POW = OFF;
23
        wait = DELAY_STOPP;
24
        break;
25
        }
26
      if (M5DIR == RUECK)
27
        {
28
        M5DIR = VOR;
29
        wait = DELAY_UM;
30
        }
31
      cmd5 = NOP;
32
    break;
33
34
    case CMD_VOR:
35
      if (M5POW == ON)
36
        {
37
        if (M5DIR == VOR)
38
          {
39
          cmd5 = NOP;
40
          break;
41
          }
42
        else
43
          {
44
          M5POW = OFF;
45
          wait = DELAY_STOPP;
46
          break;
47
          }
48
        }
49
      else
50
        {
51
        if (M5DIR == VOR)
52
          {
53
          M5POW = ON;
54
          wait = DELAY_ON;
55
          cmd5 = NOP;
56
          break;
57
          }
58
        else
59
          {
60
          M5DIR = VOR;
61
          wait = DELAY_UM;
62
          break;
63
          }
64
        }
65
    break;
66
67
    case CMD_RUECK:
68
      if (M5POW == ON)
69
        {
70
        if (M5DIR == RUECK)
71
          {
72
          cmd5 = NOP;
73
          break;
74
          }
75
        else
76
          {
77
          M5POW = OFF;
78
          wait = DELAY_STOPP;
79
          break;
80
          }
81
        }
82
      else
83
        {
84
        if (M5DIR == RUECK)
85
          {
86
          M5POW = ON;
87
          wait = DELAY_ON;
88
          cmd5 = NOP;
89
          break;
90
          }
91
        else
92
          {
93
          M5DIR = RUECK;
94
          wait = DELAY_UM;
95
          break;
96
          }
97
        }
98
    break;
99
100
    case NOP:
101
102
#ifdef KASDEB
103
    can_data.INDEX = 0x3333;
104
    can_data.DATA = (((long)(M5POW)) << 28) + (((long)(M5DIR))
105
                << 24) + (((long)(wait)) << 8) + ((long)(cmd5));
106
    SendCANMsg();
107
#endif
108
109
    break;
110
111
    default:
112
#ifdef KASDEB
113
    can_data.INDEX = 0x3333;
114
    can_data.DATA = (((long)(M5POW)) << 28) + (((long)(M5DIR))
115
                << 24) + (((long)(wait)) << 8) + ((long)(cmd5));
116
    SendCANMsg();
117
#endif
118
119
    break;
120
    }
121
#ifdef KASDEB
122
    can_data.INDEX = 0x5555;
123
    can_data.DATA = (((long)(M5POW)) << 28) + (((long)(M5DIR))
124
                << 24) + (((long)(wait)) << 8) + ((long)(cmd5));
125
    SendCANMsg();
126
#endif
127
128
  }
habe es auch schon mit diesen Pragmas versucht:

#pragma save       /* save the current settings */
#pragma nogcse     /* turnoff global subexpression elimination */
#pragma noinduction /* turn off induction optimizations */

----- C Code ------

#pragma restore /* turn the optimizations back on */

versucht, aber die Warnung mit der Optimierung verschwindet nicht!

Beste Grüße

TOM

von Peter II (Gast)


Lesenswert?

die Warnung hat nicht mit voaltile oder Interrupts zu tun

 cmd5 = NOP;

du änderst den wert, den du für das Switch verwendest. Was erwartest du 
dann als Ergebnis?

Soll er dann den passenden Case ausführen oder nicht?

von Tom (Gast)


Lesenswert?

Hallo,

der CASE NOP würde dann als nächstes durchlaufen, wenn sich cmd5 nicht 
mehr ändert. Aber das ist alles nicht mein Problem! Ich möchte die 
Optimierung verhindern. Oder das ganz so umbauen, dass keine Optimierung 
mehr stattfindet, aber ohne den Switch in der Funktion zu ändern.

Gruß

TOM

von Εrnst B. (ernst)


Lesenswert?

Dann mach aus dem Switch eine Reihe von "if-then-else" Blöcken.
Da ist dann klar, an welchen Stellen "cmd5" ausgewertet wird.

von Karl H. (kbuchegg)


Lesenswert?

Peter II schrieb:

> du änderst den wert, den du für das Switch verwendest. Was erwartest du
> dann als Ergebnis?

Das kann aber nicht das Problem sein.
Das ist genau geregelt, wie das abläuft.

Der Wert von cmd5 wird genau hier
1
  switch(cmd5)
einmalig ausgewertet und danach entschieden, welcher case anzuspringen 
ist. Was danach mit cmd5 weiter passiert, ist für den switch 
uninteressant.

Wenn das ein Problem wäre, dann hätten Millionen von Statemachines ein 
ernstes Problem.

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Tom schrieb:

> 1>main.c:67: warning 110: conditional flow changed by optimizer: so said
> EVELYN the modified DOG
>
> Ich habe bereits in Erfahrung gebracht, dass der Compiler an dieser
> Stelle etwas unsauber arbeitet, und nicht erkennt, wenn z.B. die
> Variable einer Fallunterscheidung (SWITCH/CASE) in einer Interrupt
> Routine verändert wurde.

Das wäre aber schon ein Grund, mal ein ernstes Wörtchen mit dem 
Compilerbauer zu sprechen. Solche Probleme dürfen in einem 
professionellen Compiler nicht vorkommen.

> Nun würde ich gerne von einem Profi wissen, wie ich am besten die
> Optimierung für die Funktion die diese Fallunterscheidung enthält
> deaktiviere.

musst du in der Doku zum Compiler nachsehen.


Hast du schon mal probiert, mit einer Zwischenvariablen zu arbeiten?
1
    tmp = cmd5;
2
    switch( tmp ) {
3
....
spätestens jetzt darf der Compiler das volatile bei cmd5 nicht mehr 
ignorieren. Wenn doch, dann verlang dein Geld zurück.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Karl Heinz schrieb:
> Wenn doch, dann verlang dein Geld zurück.

Das dürfte bei SDCC ein ... interessantes Unterfangen sein, meinst Du 
nicht auch?

von Tom (Gast)


Lesenswert?

Hallo,

danke Karl-Heinz für die Klarstellung in Bezug auf den Switch! Ich habe 
gerade eine Zwischenvariable probiert, leider auch ohne Erfolg. Der SDCC 
ist ein freier Compiler, daher leider keine Chance auf Regress! ;-)

http://sdcc.sourceforge.net/

wenn ich:
1
.....
2
  switch(4)
3
  {
4
    case CMD_STOPP: (CMD_STOPP ist der wert 4)
5
.....

verwende dann läuft es durch! Aber was soll das, dann brauche ich keinen 
Switch! In diesem Fall könnte er dann sinnvoller Weise wirklich den 
Switch wegoptimieren! Naja, muss wohl mal eine neuere Version des SDCC 
versuchen aufzutreiben.

Danke für die Mithilfe bis hier hin.

TOM

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Karl Heinz schrieb:
> Solche Probleme dürfen in einem professionellen Compiler nicht
> vorkommen.

Genau das dürfte beim SDCC nicht der Fall sein: mit dem Bau dieses
Compilers verdient sich keiner seine Brötchen.

Allerdings verwechselst du wohl gerade „professionell“ mit
„qualitativ hochwertig“, fürchte ich.  Es gibt ausreichend
professionelle Software, die letzteres eher nicht ist …

(Trotzdem sollte der Compiler im 21. Jahrhundert natürlich in der
Lage sein, “volatile” ordentlich zu verarbeiten.)

von Tom (Gast)


Lesenswert?

Hi,

sorry Leute! Ich muss alles zurücknehmen! Der Optimierer hatte recht! 
Irgendwo im Projekt habe ich den Code
1
....
2
    wait--;
3
    }
4
    else
5
    {
6
      if (!(cmd5 == NOP))
7
      {
8
        doMot5();
9
      }
10
    }
11
....

gefunden, so dass der CASE NOP nie ausgeführt wurde! Ich habe diesen 
CASE entfernt, und der Compiler läuft durch!

Tja bei fremdem Code sollte man halt genauer hinschauen! Sorry für die 
Verschwendung eurer Zeit!

Falls aber jemand weiß wie (#Pragma oder anders) man die Optimierung für 
Funktionen, Module, Dateien und generell abschalten kann, so wäre ich 
über diese Info dankbar. In der Doc habe ich nichts derart gefunden, 
oder überlesen!

Beste Grüße

TOM

von Rabe (Gast)


Lesenswert?

Tom schrieb:
> die Optimierung für
> Funktionen, Module, Dateien und generell abschalten kann

Man schaltet sie nicht ab, denn es gibt immer eine Möglichkeit Code ans 
Laufen zu bekommen mit eingeschalteter Optimierung.
Wenn Code mit eingeschalteter Optimierung nicht läuft, dann ist er 
fehlerhaft (= verstößt gegen den Standard).

von Εrnst B. (ernst)


Lesenswert?

Rabe schrieb:
> Wenn Code mit eingeschalteter Optimierung nicht läuft, dann ist er
> fehlerhaft (= verstößt gegen den Standard).

Bei korrekt arbeitenden Compilern muss das so sein. Bei GCC wohl keine 
Frage.
Bei SDCC würd ich das aber nicht unterschreiben.
Und bevor man die Entwickler da mit einen Bugreport für irgendeinen 
seltenst auftretenden Grenzfall nervt: Lieber etwas umformulieren, oder
mit (RTFM)
#pragma nogcse
#pragma noloopreverse
#pragma nooverlay
usw. usf.
Exakt die Optimierung verhindern, die Probleme macht.

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
Noch kein Account? Hier anmelden.