NO

Author Topic: Optimizer produces invalid code for non-trivial switch statements  (Read 3687 times)

Romashka

  • Guest
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.

Code: [Select]
#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;
}

« Last Edit: August 30, 2010, 12:42:40 AM by Romashka »

Offline TimoVJL

  • Global Moderator
  • Member
  • *****
  • Posts: 2107
Re: Optimizer produces invalid code for non-trivial switch statements
« Reply #1 on: August 30, 2010, 08:48:06 AM »
Original code:
int foobar;
int xyz;
Code: [Select]
CPU Disasm
Address   Hex dump          Command                                  Comments
00401000   $  C3            RETN

This print wrong foobar:
int foobar;
static int xyz;
Code: [Select]
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;
Code: [Select]
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

Romashka

  • Guest
Re: Optimizer produces invalid code for non-trivial switch statements
« Reply #2 on: October 10, 2010, 08:53:55 PM »
Seems to be fixed in 6.50 RC1.