Optimizer produces invalid code for non-trivial switch statements

Started by Romashka, August 30, 2010, 12:40:55 AM

Previous topic - Next topic

Romashka

Compiling a program with a non-trivial switch statement with any optimization produces invalid code.
Results can range from variables inside switch having different values (in my real-code example the foobar value below would be 0 instead of 1 on the line with printf)
to completely broken programs (the code below produces warning #2096: Missing return value.)
The code below is clearly reproducible on 32-bit Pelles C 6.00.2. Besides the warning - the program just returns with exit code 1, though it should print "foobar = 1".
Disabling optimization produces correct output.

#include <stdio.h>

int main(int argc, char *argv[])
{
 int foobar = 1;
 int xyz = 9;

 switch (xyz)
 {
   case 1: foobar++;
   case 2: foobar++;
   case 3:
     break;

   case 7: foobar++;
   case 8: foobar++;
   case 9:
     printf("foobar = %d\n", foobar);
 }

 return 0;
}


TimoVJL

Original code:
int foobar;
int xyz;
CPU Disasm
Address   Hex dump          Command                                  Comments
00401000   $  C3            RETN


This print wrong foobar:
int foobar;
static int xyz;
CPU Disasm
Address   Hex dump          Command                                  Comments
00401000  /$  55            PUSH EBP
00401001  |.  89E5          MOV EBP,ESP
00401003  |.  A1 00804000   MOV EAX,DWORD PTR DS:[408000]
00401008  |.  83F8 01       CMP EAX,1                                ; Switch (cases 1..9, 5 exits)
0040100B  |.  7C 27         JL SHORT 00401034
0040100D  |.  83F8 09       CMP EAX,9
00401010  |.  7F 22         JG SHORT 00401034
00401012  \.  FF2485 FC6F40 JMP DWORD PTR DS:[EAX*4+406FFC]
00401019  /.  BA 01000000   MOV EDX,1
0040101E  \>  EB 14         JMP SHORT 00401034                       ; Cases 1, 2 of switch opt_test1.401008
00401020  />  BA 02000000   MOV EDX,2                                ; Case 7 of switch opt_test1.401008
00401025  |>  42            INC EDX                                  ; Case 8 of switch opt_test1.401008
00401026  |>  52            PUSH EDX                                 ; Case 9 of switch opt_test1.401008
00401027  |.  68 24704000   PUSH OFFSET 00407024                     ; ASCII "foobar = %d\n"
0040102C  |.  E8 3F000000   CALL 00401070
00401031  |.  83C4 08       ADD ESP,8
00401034  |>  31C0          XOR EAX,EAX                              ; Default case of switch opt_test1.401008
00401036  |.  5D            POP EBP
00401037  \.  C3            RETN


This print correct foobar:
static int foobar;
static int xyz;
CPU Disasm
Address   Hex dump          Command                                  Comments
00401000  /$  55            PUSH EBP
00401001  |.  89E5          MOV EBP,ESP
00401003  |.  A1 04804000   MOV EAX,DWORD PTR DS:[408004]
00401008  |.  83F8 01       CMP EAX,1                                ; Switch (cases 1..9, 6 exits)
0040100B  |.  7C 39         JL SHORT 00401046
0040100D  |.  83F8 09       CMP EAX,9
00401010  |.  7F 34         JG SHORT 00401046
00401012  |.  FF2485 FC6F40 JMP DWORD PTR DS:[EAX*4+406FFC]
00401019  |>  FF05 00804000 INC DWORD PTR DS:[408000]                ; Case 1 of switch opt_test1.401008
0040101F  |>  FF05 00804000 INC DWORD PTR DS:[408000]                ; Case 2 of switch opt_test1.401008
00401025  |.  EB 1F         JMP SHORT 00401046
00401027  |>  FF05 00804000 INC DWORD PTR DS:[408000]                ; Case 7 of switch opt_test1.401008
0040102D  |>  FF05 00804000 INC DWORD PTR DS:[408000]                ; Case 8 of switch opt_test1.401008
00401033  |>  A1 00804000   MOV EAX,DWORD PTR DS:[408000]            ; Case 9 of switch opt_test1.401008
00401038  |.  50            PUSH EAX
00401039  |.  68 24704000   PUSH OFFSET 00407024                     ; ASCII "foobar = %d\n"
0040103E  |.  E8 3D000000   CALL 00401080
00401043  |.  83C4 08       ADD ESP,8
00401046  |>  31C0          XOR EAX,EAX                              ; Default case of switch opt_test1.401008
00401048  |.  5D            POP EBP
00401049  \.  C3            RETN
May the source be with you