This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CCS Optimiser



Is there a document explaining how the optimiser works.

The reason I ask, is it is optimising out code completely at level 4. Can anyone explain why?

eg

    void start_send(char ch){
        bit_tx_state = 1;
        TBCTL = SW_UART_TIMER_START_TBCTL;
        byte_being_sent = ch;
        gpio_LD1_off(); // expands to P4OUT &= ~(0x0010)
        gpio_LD1_on(); //

    }

creates the assembly

d310:   43D2 056C           MOV.B   #1,&bit_tx_state
 53           TBCTL = SW_UART_TIMER_START_TBCTL;
d314:   40B2 0216 0180      MOV.W   #0x0216,&Timer_B3_TBCTL
 54           byte_being_sent = ch;
d31a:   4CC2 04D2           MOV.B   R12,&byte_being_sent
102           while(txbob >= (TXBUFSIZE-1));
d31e:   3C0E                JMP     ($C$L640)

  • I guess this is because the compiler does not handle "volatile" correctly.

    Some time ago I also had an issue with "volatile" and ports.  My code was as follows:

    {
       uint16_t r1, r2, r3;
       do { r1 = TB0R;  r2 = TB0R;  r3 = TB0R; } while (r1 != r2  ||  r1 != r3);
    }

    was compiled as:

    for (;;) {
       r1 = TB0R;  r2 = TB0R;
       if (r1 == r2) break;
       r3 = TB0R;
       if (r1 == r3) break;
    }

    which is really not the same (imagine reading a FIFO).  Inserting a "_nop();" after the "r3 = TB0R;" solved it at that time.

    My problem was several compiler versions ago (cannot remember which exactly).  The most recent version (4.1.2) behaves correctly for my case (which version are you actually using, what are your optimization settings?).

    Hardy

  • Hi Hardy,

    Thanks for your response.

    I'm using 5.2 (latest) with optomisation level 4 (and speed/size level 4)

    All the variables in function are declared volatile, but I'm not sure how you delcare a port as volatile.

    Thanks

    Leigh

  • Hi Leigh,

    5.2 is not the compiler version.  Actual compiler version can be identified via "<path-to-cl430>\cl430.exe -version".

    Volatility is declared for the MSP430 ports in the header filed provided by the compiler manufacturer (i.e. TI).  It's declarations are e.g. SFR_16BIT(TB0R).  SFR_16BIT() is expanded to "extern volatile unsigned int address".

    BTW: how is the actual code of gpio_LD1_off/on()?  Is it a macro or an inline function?

    Hardy

  • Hi Hardy,

    C Compiler version is 4.1.0

    (note I didn't write this code!)

    gpio_LD1_off/on()  reference is

    #define gpio_LD1_off()                            OUT_REG(LD1) &= ~LD1

    Where LD1 reference is
    #define LD1 VACT_SENSE_nEN
    where VACT_SENSE_nEM reference is
    #define VACT_SENSE_nEN                              BIT4  // pin 21
    where BIT4 reference is
    #define BIT4                   (0x0010)

    and OUT_REG reference is
    #define OUT_REG(signal)                   EVAL_THEN_CONCAT(signal ## _PORT, OUT)
    and EVAL_THEN_CONCAT reference is
    #define EVAL_THEN_CONCAT(x,y)             CONCAT_ ## y(x)
    Which creates the final macro expansion of P4OUT &= ~(0x0010)... but I'm lost as to how the preparser compiles this.

    This is more of the code in this section

    #define EVAL_THEN_CONCAT(x,y)             CONCAT_ ## y(x)
    #define CONCAT_SEL(x)                     x ## SEL
    #define CONCAT_DIR(x)                     x ## DIR
    #define CONCAT_OUT(x)                     x ## OUT
    #define CONCAT_REN(x)                     x ## REN
    #define CONCAT_IN(x)                      x ## IN
    #define CONCAT_IES(x)                     x ## IES
    #define CONCAT_IFG(x)                     x ## IFG
    #define CONCAT_IE(x)                      x ## IE

    #define SEL_REG(signal)                   EVAL_THEN_CONCAT(signal ## _PORT, SEL)
    #define DIR_REG(signal)                   EVAL_THEN_CONCAT(signal ## _PORT, DIR)
    #define OUT_REG(signal)                   EVAL_THEN_CONCAT(signal ## _PORT, OUT)
    #define REN_REG(signal)                   EVAL_THEN_CONCAT(signal ## _PORT, REN)
    #define IN_REG(signal)                    EVAL_THEN_CONCAT(signal ## _PORT, IN)
    #define IES_REG(signal)                   EVAL_THEN_CONCAT(signal ## _PORT, IES)
    #define IFG_REG(signal)                   EVAL_THEN_CONCAT(signal ## _PORT, IFG)
    #define IE_REG(signal)                    EVAL_THEN_CONCAT(signal ## _PORT, IE)



    // ###############    Port Mappings    ###############
    // for Rev4.0 PCB and onwards we're organising the port mappings by function

    //**************************************************************************************************
    #if PCB_REVISION == 41
    //**************************************************************************************************
    #if ENABLE_LEDS == 1
    #define LD1_PORT                                    VACT_SENSE_nEN_PORT
    #define LD1                                         VACT_SENSE_nEN
    #define LD2_PORT                                    LF_SENSE_PORT
    #define LD2                                         LF_SENSE
    #endif

  • OK, I sat down and worked out how the preparser parses it, but I feel like throttling the programmer!

    This is how gpio_LD1_off() becomes P4OUT &=~ 0x0010

    gpio_LD1_off()
    (1) #define OUTREG(LD1) &=~ LD1
    now just dealing with OUTREG(LD1)
    #define OUT_REG(signal)                   EVAL_THEN_CONCAT(signal ## _PORT, OUT)
    EVAL_THEN_CONCAT(LD1_PORT, OUT)
     #define EVAL_THEN_CONCAT(x,y) CONCAT_ ## y(x)
    CONCAT_OUT(LD1_PORT)  #define LD1_PORT  VACT_SENSE_nEN_PORT -> #define VACT_SENSE_nEN_PORT   P4
    #define X ## out
    P4OUT

    Now dealing with the LD1 on the right side of (1)
    #define VACT_SENSE_nEN   BIT4 -> #define BIT4 (0x0010)

    So insert back into (1) and we get P4OUT&=~(0x0010)

    Fun times....

  • Hi Leigh,

    when the preprocessor is hard to understand, I'm CnP the corresponding source into eclipse/CDT (actually you are using CCS5.2...) and follow the expansion (C-=).

    It shows to me that

    1. gpio_LD1_on() is missing - I guess it should be "#define gpio_LD1_off() OUT_REG(LD1) |= LD1"
    2. actual expansion of gpio_LD1_off() ends at "VACT_SENSE_nEN_PORTOUT &= ~(0x0010)"

    Where is the definition of VACT_SENSE_nEN_PORTOUT?  If the final expansion is really P4OUT: where is this defined?

    Hardy

  • I've compiled a dummy function just for fun which does actually what your compiler optimizes away.  Assembler output is:

    ;*****************************************************************************
    ;* FUNCTION NAME: dummy                                                      *
    ;*                                                                           *
    ;*   Regs Modified     : SP,SR                                               *
    ;*   Regs Used         : SP,SR                                               *
    ;*   Local Frame Size  : 0 Args + 0 Auto + 0 Save = 0 byte                   *
    ;*****************************************************************************
    dummy:
    ; 1098 | P4OUT &= ~0x10;
    ;----------------------------------------------------------------------
    AND.B     #239,&PBOUT_H+0       ; [] |1098|
    ;----------------------------------------------------------------------
    ; 1099 | P4OUT |=  0x10;
    ;----------------------------------------------------------------------
    OR.B      #16,&PBOUT_H+0        ; [] |1099|
    RETA      ; []

    Compiler settings are essentially these: "--silicon_version=mspx --code_model=large --data_model=small --opt_for_speed=5 --opt_level=4"

    Hardy
  • Hi all,

    i am moving this thread to the compiler forum so this can be answered  by the compiler expert.

    anyway, i am not a compiler expert, but the Compiler documentation has a specific documentation regarding optimization: http://www.ti.com/litv/pdf/slau132g - chapter 3 "Optimizing Your Code". Have you checked this?

  • The compiler is not supposed to remove any volatile access.  I cannot reproduce the problem with the test case shown.  The -O4 option provides whole-program optimization; this may mean that I won't be able to reproduce this without an entire program which demonstrates the problem.

    What particular MSP are you using?  What linker command file did CCS choose for you?  What are the exact command line options?