xc16 Battling the optimiser

Thread Starter

Robin66

Joined Jan 5, 2016
281
Hi. I'm using MPLAB X IDE v3.2 and I've just realised I can turn the xc16 optimisation level up to 1 free-of-charge. However now my code doesn't work. I have a simple while loop as an example
Code:
    unsigned short i;    
    i = 2000;
    while(i>0)
    {
        __delay_ms(1);
        Lcd_Process();
        i--;
    }
Compiles to the below, which clearly doesn't loop after decriminenting W8
Code:
997:                   unsigned short i;    
998:                   i = 2000;
999:                   while(i>0)
0019DC  3AFFFB     BRA NZ, 0x19D4
1000:                  {
1001:                      __delay_ms(1);
0019D0  23E80A     MOV #0x3E80, W10
0019D2  20000B     MOV #0x0, W11
0019D4  BE000A     MOV.D W10, W0
0019D6  070032     RCALL 0x1A3C
1002:                      Lcd_Process();
0019D8  07FB4E     RCALL Lcd_Process
0019DA  E90408     DEC W8, W8
1003:                      i--;
1004:                  }
From my research I thought declaring i as volatile would fix it. The result is that the optimisations are removed but the loop isn't fixed.

Code:
997:                   volatile unsigned short i;    
998:                   i = 2000;
0019CA  207D00     MOV #0x7D0, W0
0019CC  9FBFB0     MOV W0, [W15-10]
999:                   while(i>0)
0019CE  97B83F     MOV [W15-10], W0
0019D0  5787E4     SUB W15, #0x4, W15
0019D2  E00000     CP0 W0
0019D4  32000B     BRA Z, 0x19EC
0019E6  97B85F     MOV [W15-6], W0
0019E8  E00000     CP0 W0
0019EA  3AFFF7     BRA NZ, 0x19DA
1000:                  {
1001:                      __delay_ms(1);
0019D6  23E808     MOV #0x3E80, W8
0019D8  200009     MOV #0x0, W9
0019DA  BE0008     MOV.D W8, W0
0019DC  070036     RCALL 0x1A4A
1002:                      Lcd_Process();
0019DE  07FB4B     RCALL Lcd_Process
1003:                      i--;
0019E0  97B85F     MOV [W15-6], W0
0019E2  E90000     DEC W0, W0
0019E4  9FBFD0     MOV W0, [W15-6]
1004:                  }
Can anyone give some pointers to help me get this loop working again? General guidance on keeping my post-optimised code working would be very much appreciated.

Robin
 

xox

Joined Sep 8, 2017
936
You'd probably be better off just not using that optimization level - it's broken. There's no good reason for it to break the loop like that.
 

Thread Starter

Robin66

Joined Jan 5, 2016
281
thanks @xox . That's very upsetting. Where it didn't break functionality the optimiser was speeding up the code x2. I wouldn't really consider it a true optimisation because it was just converting needlessly inefficient code into the simple code a human familiar with the instruction set would use, but the gains were huge nonetheless.

And unfortunately it doesn't even seem that paying for the PRO licence would help because microchip say this builds on the (broken) basic optimisation, so PRO would presumably also be broken
 

xox

Joined Sep 8, 2017
936
Seems like a product such as this one would really benefit being released with an open source license (and code on github). They could still charge for support, and in the meantime bugs like this would get worked out much quicker. Oy vey.
 
Last edited:

Thread Starter

Robin66

Joined Jan 5, 2016
281
i managed to trick the optimiser into not deleting my logic by using a do.. while loop instead
Code:
    unsigned short i;   
    do
    {
        __delay_ms(1);
        Lcd_Process();
        i++;
    }while(i<2000);
Compiles nicely to
Code:
1000:                  do
1001:                  {
1002:                      __delay_ms(1);
002618  23E80A     MOV #0x3E80, W10
00261A  20000B     MOV #0x0, W11
00261E  BE000A     MOV.D W10, W0
002620  0701B8     RCALL 0x2992
1003:                      Lcd_Process();
002622  07FB4A     RCALL Lcd_Process
1004:                      i++;
002624  E8060C     INC W12, W12
1005:                  }while(i<2000);
261C  207CF8     MOV #0x7CF, W8
002626  560F88     SUB W12, W8, [W15]
002628  36FFFA     BRA LEU, 0x261E
1-0 to me. What's more surprising is despite many (non-volatile) vars shared across several interrupt routines the rest of my code seems to be functioning correctly. I guess I just got really unlucky with that simple while loop and most of the time the optimiser is not breaking code
 
Top