Mike Marynowski

CodeWarrior Optimizer Butchers My Code

Discussion created by Mike Marynowski on Nov 4, 2011
Latest reply on Nov 4, 2011 by CrasyCat

It was suggested to me in the other thread I started that I should post what I found in this forum section instead, so here I am.


This code does not get optimized properly:


#define STATUS_1 0x40000000void set_status_bits(uint_8);uint_32 status[] ={    0,0,0,0,0,0,0,0};void set_status_bits(uint_8 indexes){   uint_8 i;         for (i = 0; i < 8; i++)   {      if ((indexes & (1 << i)) > 0)      {         status[i] |= STATUS_1;      }         }  }void Main_task(uint_32 init_data){   set_status_bits(0xFF);   _mqx_exit(0);}


The set_status_bits method should look at each bit in the indexes variable and if it is 1, set the bit represented by STATUS_1 in the corresponding array element. Since I am passing 0xFF to the method, all elements in the array should have the STATUS_1 bit set.


Only array element #6 gets set if the code above is built with optimizations. Otherwise, all the bits get set. You can see the problem in the disassembler output as well as simply debugging and observing the values of the status[] array elements in the debugger.


The bug does not show up if I the value of STATUS_1 is set to 0x01 or 0x1000. It also disappears if I remove the if statement so it sets every array element regardless of the indexes parameter, so it appears to be something very specific to the combination of values and code above.


The rest of this post is pasted from Tom's reply to my other thread, found here: https://community.freescale.com/message/98282#98282


To match my simplified example above, just replace "_lcd_data_pins" with "status" and "GPIO_PIN_STATUS_1" with "STATUS_1" in the disassembler output below. The disassembly output is otherwise identical for my simplified test code above.


Here is what Tom said:


The difference between the two optimisation levels is:



DEBUG (Level 1 Optimizations)"i" is in "-12(a6)" and "d1";  354:          _lcd_data_pins[i] |= GPIO_PIN_STATUS_1; ;0x00000028  0x41F900000000           lea      __lcd_data_pins,a00x0000002E  0x41F01C00               lea      (a0,d1.l*4),a00x00000032  0x2D48FFF8               move.l   a0,-8(a6)0x00000036  0x206EFFF8               movea.l  -8(a6),a00x0000003A  0x2010                   move.l   (a0),d00x0000003C  0x08C0001E               bset     #30,d00x00000040  0x2080                   move.l   d0,(a0)RELEASE (Level 4 Optimizations)"i" is in "d0";  354:          _lcd_data_pins[i] |= GPIO_PIN_STATUS_1; 0x0000001C  0x41F900000000           lea      __lcd_data_pins,a00x00000022  0x7406                   moveq    #6,d20x00000024  0x05F02C00               bset     d2,(a0,d2.l*4)


The first one is correctly using "d1" as "i" in the address calculations of the array elements and the second one looks to be using a constant offset of "6" for all of them.


You should probably report this in the appropriate "CodeWarrior Development Tools" Forum rather than here, possibly with a simpler test-case that demonstrates the problem.