We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
I'm sure you are all (including me) skeptical that what I have is a compiler bug. But I can find no other explanation. I have two lines of nearly identical code assigning a value to an array. But the compiler creates very different output for the second line. In fact, it doesn't assign the value to the array at all.
Here's some excerpts of source code with the troubling line highlighted in red:
... static U16 mu16aPulseTripPointPerSet[2]; static U16 mu16aTimerPeriodPerSet[2]; ... // Initialize the timer period mu16aTimerPeriodPerSet[0] = 0xffff - FSK_F1_COUNT; mu16aTimerPeriodPerSet[1] = 0xffff - FSK_F2_COUNT; // Initialize the trip points mu16aPulseTripPointPerSet[0] = mu16aTimerPeriodPerSet[0] + 2 * FSK_F1_COUNT / 3 + FSK_TRIP_POINT_OFFSET; mu16aPulseTripPointPerSet[1] = mu16aTimerPeriodPerSet[1] + 2 * FSK_F2_COUNT / 3 + FSK_TRIP_POINT_OFFSET; FSK_BurstStart();
And here is the corresponding listing output with the trouble code highlighted:
; SOURCE LINE # 258 0011 7500FE R MOV mu16aTimerPeriodPerSet,#0FEH 0014 7500C5 R MOV mu16aTimerPeriodPerSet+01H,#0C5H ; SOURCE LINE # 259 0017 7500FF R MOV mu16aTimerPeriodPerSet+02H,#0FFH 001A 750018 R MOV mu16aTimerPeriodPerSet+03H,#018H ; SOURCE LINE # 262 001D E500 R MOV A,mu16aTimerPeriodPerSet+01H 001F 24D8 ADD A,#0D8H 0021 F500 R MOV mu16aPulseTripPointPerSet+01H,A 0023 E4 CLR A 0024 3500 R ADDC A,mu16aTimerPeriodPerSet 0026 F500 R MOV mu16aPulseTripPointPerSet,A ; SOURCE LINE # 263 0028 E500 R MOV A,mu16aTimerPeriodPerSet+03H 002A 24A1 ADD A,#0A1H ; SOURCE LINE # 266 002C 120000 R LCALL L?0039
You see that see that the second assignment simply assigns some values to the accumulator and that's it! If add a 3rd line of nearly identical code, they all create the correct output. If I change the order of the statements, it also produces the correct output. Turning off optimization had no affect. I tried a bit to create a reduced program which demonstrated the error and I was not able.
I can work around this problem for now by simply changing the order of my statements. But it is alarming to me. Any ideas what could be causing this?
Thanks.
something is wrong, the line numbers do not match, did you 'edit'?
// Initialize the timer period 258 mu16aTimerPeriodPerSet[0] = 0xffff - FSK_F1_COUNT; 259 mu16aTimerPeriodPerSet[1] = 0xffff - FSK_F2_COUNT; 260 261 // Initialize the trip points 262 mu16aPulseTripPointPerSet[0] = mu16aTimerPeriodPerSet[0] + 2 * FSK_F1_COUNT / 3 + 263 FSK_TRIP_POINT_OFFSET; 263 mu16aPulseTripPointPerSet[1] = mu16aTimerPeriodPerSet[1] + 2 * FSK_F2_COUNT / 3 + FSK_TRIP_POINT_OFFSET;
where is 264
265 266 FSK_BurstStart(); And here is the corresponding listing output with the trouble code highlighted: ; SOURCE LINE # 258 0011 7500FE R MOV mu16aTimerPeriodPerSet,#0FEH 0014 7500C5 R MOV mu16aTimerPeriodPerSet+01H,#0C5H ; SOURCE LINE # 259 0017 7500FF R MOV mu16aTimerPeriodPerSet+02H,#0FFH 001A 750018 R MOV mu16aTimerPeriodPerSet+03H,#018H ; SOURCE LINE # 262 001D E500 R MOV A,mu16aTimerPeriodPerSet+01H 001F 24D8 ADD A,#0D8H 0021 F500 R MOV mu16aPulseTripPointPerSet+01H,A 0023 E4 CLR A 0024 3500 R ADDC A,mu16aTimerPeriodPerSet 0026 F500 R MOV mu16aPulseTripPointPerSet,A ; SOURCE LINE # 263 0028 E500 R MOV A,mu16aTimerPeriodPerSet+03H 002A 24A1 ADD A,#0A1H
; SOURCE LINE # 266 002C 120000 R LCALL L?0039
Erik
Apparently I did "edit" it; I deleted a comment. Here's is the source part of the listing:
253 1 // Initialize the number of cycles per set 254 1 mu16aCyclesCountPerSet[0] = FSK_F1_CYCLES; 255 1 mu16aCyclesCountPerSet[1] = FSK_F2_CYCLES; 256 1 257 1 // Initialize the timer period 258 1 mu16aTimerPeriodPerSet[0] = 0xffff - FSK_F1_COUNT; 259 1 mu16aTimerPeriodPerSet[1] = 0xffff - FSK_F2_COUNT; 260 1 261 1 // Initialize the trip points 262 1 mu16aPulseTripPointPerSet[0] = mu16aTimerPeriodPerSet[0] + 2 * FSK_F1_COUNT / 3 + FSK_TRIP_POINT_OFFSET; 263 1 mu16aPulseTripPointPerSet[1] = mu16aTimerPeriodPerSet[1] + 2 * FSK_F2_COUNT / 3 + FSK_TRIP_POINT_OFFSET; 264 1 265 1 // Start the burst 266 1 FSK_BurstStart();
You see that see that the second assignment simply assigns some values to the accumulator and that's it!
No, that's not what we see --- it's what you saw.
What I see is that the LCALL at the end of the code you show does not go to FSK_BurstStart(). I now invite you to figure out a) where it went instead, b) why that solves your mystery, and c) how to control it if you really think you have to.
Yeah, the giveaway is the LCALL:
LCALL L?0039
L?0039 is a local label. I'd be bettin' that does the assignment.
Jon
Found it! Optimization saw that this local function was only called twice. And each time the identical code preceded it. Therefore it optimized it by putting moving the code before the local function. When I changed the order of the functions it could no longer optimize.
; FUNCTION FSK_Burst (END) ; FUNCTION L?0039 (BEGIN) 0000 F500 R MOV mu16aPulseTripPointPerSet+03H,A 0002 E4 CLR A 0003 3500 R ADDC A,mu16aTimerPeriodPerSet+02H 0005 F500 R MOV mu16aPulseTripPointPerSet+02H,A ; FUNCTION FSK_BurstStart (BEGIN) ; SOURCE LINE # 286 ; SOURCE LINE # 287 ; SOURCE LINE # 288 0007 120000 E LCALL ADC_Suspend
Odd that when Set optimizing to 0 that it still compiled the same. In my case it's OK that it works this way - I was just looking at it with the debugger and alarmed that my value wasn't set.
Thanks much for the help.
Irrespective of any "optimiser" settings, The compiler is perfectly entitiled to do this kind of thing!
If you need precise control of the generated code, then you must write in assembler.
then you must write in assembler
or you could of course write your own compiler.
No, just aware of what tricks the compiler may do. There are a few non optimizing compilers around why make another.
Anyway you can drop the optimization level down if you need to single step to debug an run into optimized code.