Menu

#2459 induction sometimes loses post-increment operation

closed-fixed
None
other
5
2017-08-13
2016-01-22
sverx
No

Hi,
I get a

main.c:91: warning 217: Non-fatal Compiler Internal Problem in file '/home/sdcc-builder/build/sdcc-build/orig/sdcc/src/SDCClrange.c' line number '1018' : Definition not found
Contact Author with source code

both with revision #9454 and with newest #9467

Offending code is:

#define MAP_X       13
#define MAP_Y       16

#define EMPTY       0
#define BLOCK       1
#define HARD        0x80
#define COLOR(n)    ((n)<<1)

#define ENDMAP      '#'

unsigned char gameMap[MAP_Y*MAP_X];

void loadLevel (char *level) {
  unsigned char *map=gameMap;
  unsigned char x,y;

  // load block map from text file
  for (y=0;y<MAP_Y;y++) {
    if (*level==ENDMAP) break;    // if row starts with '#' then level map is complete
    for (x=0;x<MAP_X;x++) {
      switch (*level++) {
        case 'B':*map++=BLOCK|COLOR(0); break;    // Blue
        case 'G':*map++=BLOCK|COLOR(1); break;    // Green
        case 'R':*map++=BLOCK|COLOR(2); break;    // Red
        case 'C':*map++=BLOCK|COLOR(3); break;    // Cyan
        case 'M':
        case 'V':
        case 'P':*map++=BLOCK|COLOR(4); break;    // Magenta, Violet, Purple
        case 'Y':*map++=BLOCK|COLOR(5); break;    // Yellow
        case 'W':*map++=BLOCK|COLOR(6); break;    // White
        case 'O':*map++=BLOCK|COLOR(7); break;    // Orange
        case 'S':*map++=HARD|BLOCK|COLOR(8); break;   // Silver
        case '\\':                // if row contains '\' then row is complete
          for (;x<MAP_X;x++)
            *map++=EMPTY;
          break;
        default:*map++=EMPTY;
      }
    }
    level+=2;   // skip CR+LF
  }

  for (++y;y<MAP_Y;y++)
    for (x=0;x<MAP_X;x++)
      *map++=EMPTY;
}

note that the problem disappear if I rewrite the default: case as

  default:*map=EMPTY; map++;

Command line: sdcc -c -mz80 main.c
Hope it helps!

Discussion

  • Maarten Brock

    Maarten Brock - 2016-02-09

    Can you explain what the malfunctioning code is?

     
  • alvin

    alvin - 2016-02-21

    sdcc -v
    9507 MSVC

    The original code is generating a warning:

    test7.c:35: warning 217: Non-fatal Compiler Internal Problem in file 'SDCClrange.c' line number '1018' : Definition not found
    Contact Author with source code

    but the generated code is also incorrect - it's failing to increment "map".

    Bugged code:

     default:*map++=EMPTY;
    
     ->
    
     l_loadLevel_00116:
        xor a, a
        ld  (bc),a
        jr  l_loadLevel_00126
    

    When the default case is changed, the code is correct:

    default:*map=EMPTY; map++;
    
    ->
    
    l_loadLevel_00116:
        xor a, a
        ld  (bc),a
        ld  c, e
        ld  b, d
        jr  l_loadLevel_00126
    

    In the above BC holds the value of "map" and DE holds the value of "map + 1".

    There is similar code at the other cases where map++ is assigned to:

    l_loadLevel_00103:
        ld  a,0x01
        ld  (bc),a
        ld  c, e
        ld  b, d
        jr  l_loadLevel_00126
    

    Edit:

    sdcc -mz80 -S test7.c

    is showing a slightly different variation where DE is not used to hold map+1 but instead BC is incremented to perform "map++". But the "inc bc" is still missing from the problematic default case.

     

    Last edit: alvin 2016-02-21
  • sverx

    sverx - 2016-03-21

    I just upgraded to

    SDCC : mcs51/z80/z180/r2k/r3ka/gbz80/tlcs90/ds390/pic16/pic14/TININative/ds400/hc08/s08/stm8 3.5.5 #9522 (MINGW32)

    the error message now is:

    main.c:232: warning 217: Non-fatal Compiler Internal Problem in file '/home/sdcc-builder/build/sdcc-build/orig/sdcc/src/SDCClrange.c' line number '1018' : Definition not found
    Contact Author with source code
    Warning: Non-connected liverange found and extended to connected component of the CFG:iTemp72. Please contact sdcc authors with source code to reproduce.

    This is the offending code:

    #define BLOCK_MARK              'x'
    #define EMPTY                   0
    #define BLOCK                   1
    #define MAP_Y                   8
    #define MAP_X                   15
    
    unsigned char gameMap[MAP_Y*MAP_X];
    
    void loadLevel (char *level) {
      unsigned char *map=gameMap;
      unsigned char x,y;
      unsigned char blocks=0
      // load block map
      for (y=0;y<MAP_Y;y++) {
        for (x=0;x<MAP_X;x++) {
          if (*level==BLOCK_MARK) {
            level++;
            *map++=BLOCK;
            blocks++;
          } else if (*level==0x0D) {
            for (;x<MAP_X;x++) {
              *map++=EMPTY;
            }
          } else {
            level++;
            *map++=EMPTY;
          }
        }
        level+=2;   // CR+LF
      }
    }
    

    The problem disappears splitting every

    *map++=<something>;
    

    into separate instructions as in

    *map=<something>;
    map++;
    
     
  • Erik Petrich

    Erik Petrich - 2016-08-05
    • summary: Non-fatal Compiler Internal Problem (malfunctioning code generated) --> induction sometimes loses post-increment operation
     
  • Erik Petrich

    Erik Petrich - 2016-08-05

    The increment is being eliminated somehow in the induction optimization. The code looks correct when using the --noinduction option. I'll look into this further.

     
  • sverx

    sverx - 2017-08-11

    I just wanted to mention that this problem is getting worse. I could compile correctly the code above until #9913 / #9917, but yesterday I updated to #9984 and this no longer works (it compiles without errors but it doesn't run correctly).
    For now I reverted to #9913 and to the known problem, as I know how to workaround that... I'm not so lucky with newer #9984, it seems it doesn't matter how I modify the code it still doesn't work :|

     
  • Erik Petrich

    Erik Petrich - 2017-08-12
    • assigned_to: Erik Petrich
     
  • Erik Petrich

    Erik Petrich - 2017-08-13
    • status: open --> closed-fixed
     
  • Erik Petrich

    Erik Petrich - 2017-08-13

    Fixed in [r9992]
    The core bug occured when a pointer dereference with post-increment/decrement occurs as the last statement of an extended basic block, leaving the pointer to the last iCode of the block incorrect. The increment or decrement is then actually lost if loop induction attempts to append a branch to the end of one of these corrupted blocks.

     

Log in to post a comment.