工具与软件:
编译器版本:TI v22.6.0.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 ; []
可以看出、此时(索引* 2 - 1)固定为 R1H、生成的汇编指令为 ADDF32 R1H、R1H、#49152、即 R1H=R1H-2。
这是一个错误吗?
谢谢你。

