Part Number:TMS320F280039C
编译器版本:TI v22.6.0.LTS
我需要对大数组或结构体进行清零,之前的方案是直接采用memset函数清零,例如:
memset((void *)&test1,0,sizeof(test1));
但发现编译器在256字以内时会采用RPT指令以生成效率更高的汇编代码,而在256字以上时则直接调用memset库函数,例如我定义了三个测试用的float数组,大小分别为127、128和129,并对其清零:
volatile float test1[127]; volatile float test2[128]; volatile float test3[129]; memset((void *)&test1,0,sizeof(test1));//line 209 memset((void *)&test2,0,sizeof(test2));//line 210 memset((void *)&test3,0,sizeof(test3));//line 211
生成的汇编代码分别为:
.dwpsn file "../main.c",line 209,column 5,is_stmt,isa 0MOVLXAR4,#||test1||; [CPU_ARAU] |209|RPT#253 ||MOV*XAR4++,#0; [CPU_ALU] |209| .dwpsn file "../main.c",line 210,column 5,is_stmt,isa 0MOVLXAR4,#||test2||; [CPU_ARAU] |210|RPT#255 ||MOV*XAR4++,#0; [CPU_ALU] |210| .dwpsn file "../main.c",line 211,column 5,is_stmt,isa 0MOVACC,#258; [CPU_ALU] |211|MOVBXAR5,#0; [CPU_ALU] |211|MOVLXAR4,#||test3||; [CPU_ARAU] |211| $C$DW$325 .dwtag DW_TAG_TI_branch .dwattr $C$DW$325, DW_AT_low_pc(0x00) .dwattr $C$DW$325, DW_AT_name("memset") .dwattr $C$DW$325, DW_AT_TI_callLCR#||memset||; [CPU_ALU] |211|; call occurs [#||memset||] ; [] |211|
可以观察到test1和test2的清零均采用了RPT指令,用时分别为257和259个时钟周期,平均每字节约为1个时钟周期;而test3的清零则调用了memset库函数,用时4914个时钟周期,平均每字节花费19个时钟周期。库文件的c代码和汇编代码如下:
即便我打开level2的编译器优化,编译器对memset的处理依旧不变。所以有没有其他更好的办法256字以上数组或结构体进行清零呢?
user6046498:
倒数第二段的每字节打错了,应该是每字。
另外我自己写了一段C代码并开启了level2的编译器优化,根据数组大小不同会分别自动生成如下代码。
volatile float test3[130]; float *pt = (float *)&test3; for(n=0;n<sizeof(test3)/2;n++) {*pt = 0;pt++; }MOVBXAR6,#25; [CPU_ALU].dwpsn file "../main.c",line 211,column 9,is_stmt,isa 0ZEROR1H; [CPU_FPU] |211|ZEROR0H; [CPU_FPU] |211|ZEROR2H; [CPU_FPU] |211|.dwpsn file "../main.c",line 208,column 15,is_stmt,isa 0MOVLXAR4,#||test3||; [CPU_ARAU] |208|.dwpsn file "../main.c",line 209,column 13,is_stmt,isa 0RPTB||$C$L43||,AR6; [CPU_ALU] |209|; repeat block starts ; []||$C$L42||:.dwpsn file "../main.c",line 211,column 9,is_stmt,isa 0MOV32*XAR4++,R1H; [CPU_FPU] |211|MOV32*XAR4++,R0H; [CPU_FPU] |211|MOV32*XAR4++,R2H; [CPU_FPU] |211|MOV32*XAR4++,R1H; [CPU_FPU] |211|MOV32*XAR4++,R0H; [CPU_FPU] |211|; repeat block ends ; []volatile float test3[131]; float *pt = (float *)&test3; for(n=0;n<sizeof(test3)/2;n++) {*pt = 0;pt++; }MOVBXAR6,#64; [CPU_ALU].dwpsn file "../main.c",line 211,column 9,is_stmt,isa 0ZEROR1H; [CPU_FPU] |211|ZEROR0H; [CPU_FPU] |211|.dwpsn file "../main.c",line 208,column 15,is_stmt,isa 0MOVLXAR4,#||test3||; [CPU_ARAU] |208|||$C$L42||:; Peeled loop iterations for unrolled loop:.dwpsn file "../main.c",line 211,column 9,is_stmt,isa 0MOV32*XAR4++,R1H; [CPU_FPU] |211|MOV32*XAR4++,R0H; [CPU_FPU] |211|.dwpsn file "../main.c",line 209,column 13,is_stmt,isa 0BANZ||$C$L42||,AR6--; [CPU_ALU] |209|根据数组大小编译器有时会采用RPTB语句,有时会采用BANZ语句。采用RPTB时用时大约为每字0.5个时钟周期,采用BANZ时大约为每字1.7个时钟周期。
如果要确保编译器采用RPTB语句,可以将数组或结构体补齐至6或8的整数倍个32位。6的整数倍时汇编代码(414个float):
MOVBXAR6,#68; [CPU_ALU].dwpsn file "../main.c",line 211,column 9,is_stmt,isa 0ZEROR2H; [CPU_FPU] |211|ZEROR1H; [CPU_FPU] |211|ZEROR0H; [CPU_FPU] |211|.dwpsn file "../main.c",line 208,column 15,is_stmt,isa 0MOVLXAR4,#||test3||; [CPU_ARAU] |208|.dwpsn file "../main.c",line 209,column 13,is_stmt,isa 0RPTB||$C$L43||,AR6; [CPU_ALU] |209|; repeat block starts ; []||$C$L42||:.dwpsn file "../main.c",line 211,column 9,is_stmt,isa 0MOV32*XAR4++,R2H; [CPU_FPU] |211|MOV32*XAR4++,R1H; [CPU_FPU] |211|MOV32*XAR4++,R0H; [CPU_FPU] |211|MOV32*XAR4++,R2H; [CPU_FPU] |211|MOV32*XAR4++,R1H; [CPU_FPU] |211|MOV32*XAR4++,R0H; [CPU_FPU] |211|; repeat block ends ; []8的整数倍时汇编代码(408个float):
MOVBXAR6,#50; [CPU_ALU].dwpsn file "../main.c",line 211,column 9,is_stmt,isa 0ZEROR1H; [CPU_FPU] |211|ZEROR0H; [CPU_FPU] |211|ZEROR2H; [CPU_FPU] |211|.dwpsn file "../main.c",line 208,column 15,is_stmt,isa 0MOVLXAR4,#||test3||; [CPU_ARAU] |208|.dwpsn file "../main.c",line 209,column 13,is_stmt,isa 0RPTB||$C$L43||,AR6; [CPU_ALU] |209|; repeat block starts ; []||$C$L42||:.dwpsn file "../main.c",line 211,column 9,is_stmt,isa 0MOV32*XAR4++,R1H; [CPU_FPU] |211|MOV32*XAR4++,R0H; [CPU_FPU] |211|MOV32*XAR4++,R2H; [CPU_FPU] |211|MOV32*XAR4++,R1H; [CPU_FPU] |211|MOV32*XAR4++,R0H; [CPU_FPU] |211|MOV32*XAR4++,R2H; [CPU_FPU] |211|MOV32*XAR4++,R1H; [CPU_FPU] |211|MOV32*XAR4++,R0H; [CPU_FPU] |211|; repeat block ends ; []但这个方法无法用在不是32位对齐的数组和结构体上,而且不补数组长度时有时会调用到BANZ。所以我想看看有没有更高效或更方便的方法利用编译器优化生成高效的汇编代码,或者有没有直接的汇编语句能够供调用。
,
Ben Qin:
你好,我需要咨询下相关资深工程师,一旦有回复会立即回复给您。
,
Ben Qin:
你好,请移步到该链接查看工程师的回复:
(1) TMS320F280039C: Assembly optimization issues when using the memset function for more than 256 words – C2000 microcontrollers forum – C2000︎ microcontrollers – TI E2E support forums