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.

TMS320F280039: Under the compiler O2 optimizes, Uint16 subtraction is optimized into floating point subtraction, resulting in incorrect operation results

Part Number: TMS320F280039


Tool/software:

Compiler version:TI v22.6.1.LTS

When I was writing an algorithm, I found that after turning on the O2 level optimization of the compiler, the coefficient generation of the controller was incorrect. So I wrote the following code to test, in which I gave 1 to the input parameter w:

struct TEST_STRUCT
{
    float f1;
    float f2;
};
volatile struct TEST_STRUCT TEST[5];

void TEST_FCN(float w)
{
    Uint16 Index;
    float w_temp;
    for( Index = 5 ; Index > 0 ; Index-- )
    {
        w_temp = w * ( Index * 2 - 1 );
        TEST[Index - 1].f1 = w_temp;
    }
}

The assembly code generated after turning on O2 is as follows:

        MOVB      XAR6,#4               ; [CPU_ALU] 
        MOVL      XAR4,#||TEST||+16     ; [CPU_ARAU] 
        MOVIZ     R3H,#16656            ; [CPU_FPU] 
	.dwpsn	file "../main.c",line 22,column 22,is_stmt,isa 0
        RPTB      ||$C$L2||,AR6         ; [CPU_ALU] |22| 
        ; repeat block starts ; [] 
||$C$L1||:    
        MOVIZ     R2H,#18303            ; [CPU_FPU] |22| 
	.dwpsn	file "../main.c",line 25,column 9,is_stmt,isa 0
        MPYF32    R1H,R0H,R3H           ; [CPU_FPU] |25| 
	.dwpsn	file "../main.c",line 22,column 22,is_stmt,isa 0
        MOVXI     R2H,#65024            ; [CPU_FPU] |22| 

        ADDF32    R3H,R3H,R2H           ; [CPU_FPU] |22| 
||      MOV32     *+XAR4[0],R1H         ; [CPU_FPU] |25| 

        SUBB      XAR4,#4               ; [CPU_ALU] |22| 
        ; repeat block ends ; [] 
||$C$L2||:    
$C$DW$11	.dwtag  DW_TAG_TI_branch
	.dwattr $C$DW$11, DW_AT_low_pc(0x00)
	.dwattr $C$DW$11, DW_AT_TI_return

        LRETR     ; [CPU_ALU] 
        ; return occurs ; [] 

The problem lies in the optimization of (Index * 2 - 1): the compiler fixes (Index * 2 - 1) to the R3H register, so that R3H is subtracted by 2 for each cycle. Since Index is declared as Uint16 unsigned integer type, the compiler assigns R2H a value of 0x477ffe00 (65534) and wants to perform equivalent subtraction through R3H=R2H+R3H. However, RxH is a floating-point register, and the compiler can only call ADDF32 to perform floating-point addition, resulting in incorrect results:

If I declare Index as int16, the compiled assembly code is correct and the result is correct:

        MOVB      XAR6,#4               ; [CPU_ALU] 
        MOVL      XAR4,#||TEST||+16     ; [CPU_ARAU] 
        MOVIZ     R1H,#16656            ; [CPU_FPU] 
	.dwpsn	file "../main.c",line 21,column 22,is_stmt,isa 0
        RPTB      ||$C$L2||,AR6         ; [CPU_ALU] |21| 
        ; repeat block starts ; [] 
||$C$L1||:    
	.dwpsn	file "../main.c",line 24,column 9,is_stmt,isa 0
        MPYF32    R2H,R0H,R1H           ; [CPU_FPU] |24| 
	.dwpsn	file "../main.c",line 21,column 22,is_stmt,isa 0
        ADDF32    R1H,R1H,#49152        ; [CPU_FPU] |21| 
	.dwpsn	file "../main.c",line 24,column 9,is_stmt,isa 0
        MOV32     *+XAR4[0],R2H         ; [CPU_FPU] |24| 
	.dwpsn	file "../main.c",line 21,column 22,is_stmt,isa 0
        SUBB      XAR4,#4               ; [CPU_ALU] |21| 
        NOP       ; [CPU_ALU] 
        NOP       ; [CPU_ALU] 
        ; repeat block ends ; [] 
||$C$L2||:    
$C$DW$11	.dwtag  DW_TAG_TI_branch
	.dwattr $C$DW$11, DW_AT_low_pc(0x00)
	.dwattr $C$DW$11, DW_AT_TI_return

        LRETR     ; [CPU_ALU] 
        ; return occurs ; [] 

It can be seen that at this time (Index * 2 - 1) is fixed as R1H, and the generated assembly instruction is ADDF32 R1H, R1H, #49152, that is, R1H=R1H-2.

Is this a BUG?

Thank you.