This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Optimiser Problems - common block subroutines

Does any one else have problems with the higher levels of optimisation available to C51?

With common block subroutines switched on, sometimes, just sometimes, C51 will generate completely wrong code.

I have noticed that the problems are often associated with pointers that are automatic variables and where there is a variable of the same name in another function.

Common block subroutines have a dramatic affect on code size, but I don't use this level of optimisation because it just does not seem to be reliable.

Parents
  • With common block subroutines switched on, sometimes, just sometimes, C51 will generate completely wrong code.

    Graham,

    Can you please send me an example of this? There are currently no known problems with common block subroutines. There were some problems in the early releases, but they were corrected long ago. What compiler version are you using?

    Jon

Reply
  • With common block subroutines switched on, sometimes, just sometimes, C51 will generate completely wrong code.

    Graham,

    Can you please send me an example of this? There are currently no known problems with common block subroutines. There were some problems in the early releases, but they were corrected long ago. What compiler version are you using?

    Jon

Children
  • Here is an instance of a problem with common subroutine blocks.

    I hope you will forgive the long post - it is difficult to aviod when addressing this kind of point.

    I am using C51 version 7.02e - everything else is right up to date. I am pretty sure this problem has existed for some time.

    In this instance, a is an automatic variable, a pointer to a structure of length 0x0f held in xdata.

    There is an identical automatic variable in another function, same name, same type - different address.

    void user_read_nvm( void ) large
    {
        alarm_data_type  xdata   *a;
        unsigned char    xdata   *p;
        unsigned char            loop;
        unsigned char            alarm_number;
        unsigned char            mask;
    
        code const alarm_personality_type init_alarm_personality = { FALSE, FALSE, 0, TRUE, 0 };
    
        ....
    
        alarm_number = 1;
    
        a = &alarm_data[ 0 ];
    
        p = &personality.alarm_pins.mem_address[0];
    
        loop = NUMBER_OF_ALARMS;
    
        ....
    
        do
        {
            a->alarm_personality = *( (alarm_personality_type*) p );
                                                                    
            p++;
                                                                    
            a->alarm_source_address = ( (alarm_number > 8) ? &alarm_source[0] : &alarm_source[1] );
                                                                    
            if( a->alarm_personality.alarm_enabled )
            {
                a->alarm_source_mask = mask;
            }
            else
            {
                a->alarm_source_mask = 0x00;
            }
    
            if( a->alarm_personality.pin_polarity )
            {
                a->alarm_polarity_mask = a->alarm_source_mask;
            }
    
            a->pin_state                = FALSE;
            a->pin_timer                = ALARM_PIN_TIMEOUT;
            a->alarm_status             = normal;                    
            a->transmission_pointer     = &(transmission[ alarm_number-1 ]);
            a->timer_initialiser        = ALARM_PIN_TIMEOUT;            
            a->retransmit_timer         = 0;
            a->alarm_number             = alarm_number;
    
            alarm_number++;
    
            mask = _crol_( mask, 1 );
    
            a++;
    
        } while( --loop != 0 );
    
        ....
    
    }
    

    The problem hinges on the statement a++;.

  • With the optimisation at level 8, the following code is generated. It works fine.

       98: void user_read_nvm( void ) large
       99: {
      100: 	alarm_data_type xdata   *a;
      101: 	unsigned char	xdata	*p;
      102: 	unsigned char			loop;
      103: 	unsigned char			alarm_number;
      104: 	unsigned char			mask;
      105: 
      106: 	code const alarm_personality_type init_alarm_personality = { FALSE, FALSE, 0, TRUE, 0 };
      107: 
    
    	....
    
      146: 
      147: 	alarm_number = 1;
    009B87 903B6C            MOV     DPTR,#alarm_number
    009B8A 7401              MOV     A,#01H
    009B8C F0                MOVX    @DPTR,A
      148: 
      149: 	a = &alarm_data[ 0 ];
    009B8D 903B67            MOV     DPTR,#a
    009B90 7439              MOV     A,#HIGH alarm_data
    009B92 F0                MOVX    @DPTR,A
    009B93 A3                INC     DPTR
    009B94 7400              MOV     A,#LOW alarm_data
    009B96 F0                MOVX    @DPTR,A
      150: 
      151: 	p = &personality.alarm_pins.mem_address[0];
    009B97 903850            MOV     DPTR,#personality+01DH
    009B9A E4                CLR     A
    009B9B 93                MOVC    A,@A+DPTR
    009B9C FF                MOV     R7,A
    009B9D 7401              MOV     A,#01H
    009B9F 93                MOVC    A,@A+DPTR
    009BA0 903B69            MOV     DPTR,#p
    009BA3 CF                XCH     A,R7
    009BA4 F0                MOVX    @DPTR,A
    009BA5 A3                INC     DPTR
    009BA6 EF                MOV     A,R7
    009BA7 F0                MOVX    @DPTR,A
      152: 
      153: 	loop = NUMBER_OF_ALARMS;
    009BA8 A3                INC     DPTR
    009BA9 7411              MOV     A,#011H
    009BAB F0                MOVX    @DPTR,A
    009BAC         ?C0007?AIMSREFCODEHARNESSSTUBS:
    
            ....
    
      163: 	do
      164: 	{
    
    	....
    
      197: 		a++;
    009CB7 903B68            MOV     DPTR,#a+01H
    009CBA E0                MOVX    A,@DPTR
    009CBB 240F              ADD     A,#0FH
    009CBD F0                MOVX    @DPTR,A
    009CBE 903B67            MOV     DPTR,#a
    009CC1 E0                MOVX    A,@DPTR
    009CC2 3400              ADDC    A,#00H
    009CC4 F0                MOVX    @DPTR,A
      198: 
      199: 	} while( --loop != 0 );
    009CC5 903B6B            MOV     DPTR,#loop
    009CC8 E0                MOVX    A,@DPTR
    009CC9 14                DEC     A
    009CCA F0                MOVX    @DPTR,A
    009CCB 6002              JZ      $ + 4H
    009CCD 61AC              AJMP    ?C0007?AIMSREFCODEHARNESSSTUBS
      200: 																
    
    	....
    
    However, turning the optimisation level up to 11 causes the following code to be generated.
       98: void user_read_nvm( void ) large
       99: {
      100: 	alarm_data_type xdata   *a;
      101: 	unsigned char	xdata	*p;
      102: 	unsigned char			loop;
      103: 	unsigned char			alarm_number;
      104: 	unsigned char			mask;
      105: 
      106: 	code const alarm_personality_type init_alarm_personality = { FALSE, FALSE, 0, TRUE, 0 };
      107: 
    
    	....
    
      146: 
      147: 	alarm_number = 1;
    007AF2 903B6C            MOV     DPTR,#alarm_number
    007AF5 7401              MOV     A,#01H
    007AF7 F0                MOVX    @DPTR,A
      148: 
      149: 	a = &alarm_data[ 0 ];
    007AF8 903B67            MOV     DPTR,#a
    007AFB 12BFD1            LCALL   ?L?COM0182
      150: 
      151: 	p = &personality.alarm_pins.mem_address[0];
    007AFE 903850            MOV     DPTR,#personality+01DH
    007B01 129FFC            LCALL   ?L?COM0202
    007B04 903B69            MOV     DPTR,#p
    007B07 CF                XCH     A,R7
    007B08 F0                MOVX    @DPTR,A
    007B09 A3                INC     DPTR
    007B0A EF                MOV     A,R7
    007B0B F0                MOVX    @DPTR,A
      152: 
      153: 	loop = NUMBER_OF_ALARMS;
    007B0C A3                INC     DPTR
    007B0D 7411              MOV     A,#011H
    007B0F F0                MOVX    @DPTR,A
    007B10         ?C0007?AIMSREFCODEHARNESSSTUBS:
    
            ....
    
      163: 	do
      164: 	{
                 ....
      196: 
      197: 		a++;
    007BE0 903B68            MOV     DPTR,#a+01H
    007BE3 E0                MOVX    A,@DPTR
    007BE4 903B67            MOV     DPTR,#a
    007BE7 12BF63            LCALL   ?L?COM016E
      198: 
      199: 	} while( --loop != 0 );
    007BEA 903B6B            MOV     DPTR,#loop
    007BED E0                MOVX    A,@DPTR
    007BEE 14                DEC     A
    007BEF F0                MOVX    @DPTR,A
    007BF0 6002              JZ      $ + 4H
    007BF2 6110              AJMP    ?C0007?AIMSREFCODEHARNESSSTUBS
      200: 																
    
                 ....
    
    ----- FUNCTION ?L?COM016D (BEGIN) -----
    00BF5C 903B45            MOV     DPTR,#a+01H
    00BF5F E0                MOVX    A,@DPTR
    00BF60 903B44            MOV     DPTR,#a
    00BF63         ?L?COM016E:
    00BF63 240F              ADD     A,#0FH
    00BF65 F0                MOVX    @DPTR,A
    00BF66 E0                MOVX    A,@DPTR
    00BF67 3400              ADDC    A,#00H
    00BF69 F0                MOVX    @DPTR,A
    00BF6A 22                RET     
    ----- FUNCTION ?L?COM016D (END) -------
    

    If I concatenate the code for a++; and add some comments it becomes obvious that it does not work.
      197: 		a++;
    007BE0 903B68            MOV     DPTR,#a+01H            ; Load Data pointer with address of LSB of a.
    007BE3 E0                MOVX    A,@DPTR                ; Read the LSB of a.
    007BE4 903B67            MOV     DPTR,#a                ; Load Data pointer with address of MSB of a.
    00BF63 240F              ADD     A,#0FH                 ; Add Ox0f to the LSB of a.
    00BF65 F0                MOVX    @DPTR,A                ; Write LSB of a plus 0x0f to the MSB of a!!!!!!
    00BF66 E0                MOVX    A,@DPTR                ; Read MSB of a.
    00BF67 3400              ADDC    A,#00H			; Add carry flag to a.
    00BF69 F0                MOVX    @DPTR,A                ; Write MSB of a
    

  • Below are the results of a more systematic study I have made. It seems that I was wrong, the problem actually starts with optimisation level 10.

    Optimisation level 8:

    This code works fine.

      197: 		a++;
    009CB7 903B68            MOV     DPTR,#a+01H
    009CBA E0                MOVX    A,@DPTR
    009CBB 240F              ADD     A,#0FH
    009CBD F0                MOVX    @DPTR,A
    009CBE 903B67            MOV     DPTR,#a
    009CC1 E0                MOVX    A,@DPTR
    009CC2 3400              ADDC    A,#00H
    009CC4 F0                MOVX    @DPTR,A
      198:
    
    Optimisation level 9:

    This is common blocks optimisation. In fact, it does work just fine.
    C51 has found a different variable that happens to have the same address as a.

      197: 		a++;
    008531 903B68            MOV     DPTR,#a+01H
    008534 E0                MOVX    A,@DPTR
    008535 240F              ADD     A,#0FH
    008537 F17E              ACALL   ?L?COM020C
      198:
    ----- FUNCTION ?L?COM020C (BEGIN) -----
    00877E F0                MOVX    @DPTR,A
    00877F 903B67            MOV     DPTR,#v
    008782 E0                MOVX    A,@DPTR
    008783 3400              ADDC    A,#00H
    008785 F0                MOVX    @DPTR,A
    008786 22                RET     
    ----- FUNCTION ?L?COM020C (END) -------
    
    Optimisation level 10:

    Re-arrange code optimisation - this is where things go wrong...

      197: 		a++;
    007BE0 903B68            MOV     DPTR,#a+01H
    007BE3 E0                MOVX    A,@DPTR
    007BE4 903B67            MOV     DPTR,#a
    007BE7 12BF63            LCALL   ?L?COM016E
      198:
    ----- FUNCTION ?L?COM016D (BEGIN) -----
    00BF5C 903B45            MOV     DPTR,#a+01H
    00BF5F E0                MOVX    A,@DPTR
    00BF60 903B44            MOV     DPTR,#a
    00BF63         ?L?COM016E:
    00BF63 240F              ADD     A,#0FH
    00BF65 F0                MOVX    @DPTR,A
    00BF66 E0                MOVX    A,@DPTR
    00BF67 3400              ADDC    A,#00H
    00BF69 F0                MOVX    @DPTR,A
    00BF6A 22                RET     
    ----- FUNCTION ?L?COM016D (END) -------
    
    Optimisation level 11:

    Same problem as level 10.

      197: 		a++;
    007BE0 903B68            MOV     DPTR,#a+01H
    007BE3 E0                MOVX    A,@DPTR
    007BE4 903B67            MOV     DPTR,#a
    007BE7 12BF63            LCALL   ?L?COM016E
      198:
    ----- FUNCTION ?L?COM016D (BEGIN) -----
    00BF5C 903B45            MOV     DPTR,#a+01H
    00BF5F E0                MOVX    A,@DPTR
    00BF60 903B44            MOV     DPTR,#a
    00BF63         ?L?COM016E:
    00BF63 240F              ADD     A,#0FH
    00BF65 F0                MOVX    @DPTR,A
    00BF66 E0                MOVX    A,@DPTR
    00BF67 3400              ADDC    A,#00H
    00BF69 F0                MOVX    @DPTR,A
    00BF6A 22                RET     
    ----- FUNCTION ?L?COM016D (END) -------
    
    
    

  • Error! Forum Overflow. Please contact the Administrator.

  • This is not a problem of C51, but from the LX51 Linker/Locater. Which LX51 version are you using.

  • "This is not a problem of C51, but from the LX51 Linker/Locater."

    So it is a problem, then?

  • Graham,

    When I first switched to using LX51 I tried optimisation levels 10 and 11 (with "Favour size" selected) and encountered some problems with previously working code. I didn't bother to investigate, however, because I found that the code size in all three projects tested actually grew by about 0.5% with level 11 as opposed to level 9.

    Have you found these additional optimisation levels to be of any benefit (when they work)?

    Stefan

  • Stefan: how well does each level of optimisation work? I performed an experiment using my current development project and built it with various possible levels of optimisation in order to find out. The project is pretty typical, it has no floating point and has ANSI promotion turned on for about 50% of the code. Linker code packing is enabled.

    Optimisation	Favour		Favour		Difference	Difference from level 8
    Level		Speed		Size		for size	Speed		Size
    8		59288		56882		4.06%		00.0%		00.0%
    9		49502		48358		2.31%		16.5%		15.0%
    10		49499		48417		2.18%		16.5%		14.9%
    11		49499		48417		2.18%		16.5%		14.9%
    
    The answer seems to be, that for my application, optimisation level 9 makes a very significant difference whereas levels 10 and 11 have very little to offer.

  • Graham,

    "whereas levels 10 and 11 have very little to offer"

    Indeed, you're seeing a slight increase in code size over level 9 with 'Favour size' as I am. My projects all use a great deal of floating point, I build with linker code packing on and integer promotion off.

    Perhaps Keil would like to comment on whether there are any specific situations where 10 and 11 make a significant improvement?

    Stefan

  • "Perhaps Keil would like to comment on whether there are any specific situations where 10 and 11 make a significant improvement?"

    Apparently not. Is this because levels 10 and 11 are in fact a marketing gimmick?

    "So it is a problem, then?"

    Presumably silence means 'yes'?

    Look Keil, we understand that there will be bugs in your software from time to time. In general your tools are of a very high quality and very well supported. But please, when there is a problem we want to know what it is, what it affects and when it will be fixed. At a minimum please describe bug fixes in detail in your version release notes.

    Stefan

  • "please describe bug fixes in detail in your version release notes."

    I've been moaning about the lack of information in the so-called "release notes" for ages!

    I think all the "release notes" for all the 6.xx versions were identical apart from the value of the "xx"!!!
    (yes, I even did a text compare once!)

    Things have improved recently, but there's still a way to go; eg proper documentation of bugs/issues fixed, and known issues remaining.

  • We can confirm that your problem is most likely fixed in the current version. Take a look to http://www.keil.com/update/_c51/c51v703a.htm which are the release notes of the current revision. In the first item under V7.02 we refer to the fact that we have corrected some problems with linker code packing.