编译器版本: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。