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: 编译器O2优化时将Uint16减法优化成浮点减法导致错误的运算结果

Part Number: TMS320F280039


编译器版本:TI v22.6.1.LTS

我在写一段算法的时候发现开启编译器O2等级优化后,控制器的系数生成出错了。于是我编写了下面的一段代码来测试,其中输入参数w我给了1:

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;
    }
}

开启O2后生成的汇编代码如下:

        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 ; [] 

问题就出在( Index * 2 - 1 )的优化上:编译器将( Index * 2 - 1 )固定为R3H寄存器,这样每次循环将R3H减去2即可。由于Index被声明称Uint16无符号整型,编译器给R2H赋值0x477ffe00(65534),想要通过R3H=R2H+R3H来进行等效减法。但RxH是浮点寄存器,编译器只能调用ADDF32来进行浮点加法,导致得出了错误的结果:

如果我将Index声明为int16,编译得出的汇编代码是正确的,结果也正确:

        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 ; [] 

可以看到此时( Index * 2 - 1 )被固定为R1H,生成的汇编指令为ADDF32    R1H,R1H,#49152,即R1H=R1H-2。

我在TMS320C28x Optimizing C/C++ Compiler手册中没找到相关的信息,不清楚这是不是一个编译器优化BUG。