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.

TMS320F280039C: 对256字以上使用memset函数时的汇编优化问题

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 0
        MOVL      XAR4,#||test1||       ; [CPU_ARAU] |209| 
        RPT       #253
||     MOV       *XAR4++,#0            ; [CPU_ALU] |209| 
	.dwpsn	file "../main.c",line 210,column 5,is_stmt,isa 0
        MOVL      XAR4,#||test2||       ; [CPU_ARAU] |210| 
        RPT       #255
||     MOV       *XAR4++,#0            ; [CPU_ALU] |210| 
	.dwpsn	file "../main.c",line 211,column 5,is_stmt,isa 0
        MOV       ACC,#258              ; [CPU_ALU] |211| 
        MOVB      XAR5,#0               ; [CPU_ALU] |211| 
        MOVL      XAR4,#||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_call

        LCR       #||memset||           ; [CPU_ALU] |211| 
        ; call occurs [#||memset||] ; [] |211| 

可以观察到test1和test2的清零均采用了RPT指令,用时分别为257和259个时钟周期,平均每字节约为1个时钟周期;而test3的清零则调用了memset库函数,用时4914个时钟周期,平均每字节花费19个时钟周期。库文件的c代码和汇编代码如下:

即便我打开level2的编译器优化,编译器对memset的处理依旧不变。所以有没有其他更好的办法256字以上数组或结构体进行清零呢?

  • 倒数第二段的每字节打错了,应该是每字。

    另外我自己写了一段C代码并开启了level2的编译器优化,根据数组大小不同会分别自动生成如下代码。

    volatile float test3[130];
    float *pt = (float *)&test3;
    for(n=0;n<sizeof(test3)/2;n++)
    {
        *pt = 0;
        pt++;
    }

            MOVB      XAR6,#25              ; [CPU_ALU] 
    	.dwpsn	file "../main.c",line 211,column 9,is_stmt,isa 0
            ZERO      R1H                   ; [CPU_FPU] |211| 
            ZERO      R0H                   ; [CPU_FPU] |211| 
            ZERO      R2H                   ; [CPU_FPU] |211| 
    	.dwpsn	file "../main.c",line 208,column 15,is_stmt,isa 0
            MOVL      XAR4,#||test3||       ; [CPU_ARAU] |208| 
    	.dwpsn	file "../main.c",line 209,column 13,is_stmt,isa 0
            RPTB      ||$C$L43||,AR6        ; [CPU_ALU] |209| 
            ; repeat block starts ; [] 
    ||$C$L42||:    
    	.dwpsn	file "../main.c",line 211,column 9,is_stmt,isa 0
            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 ; [] 

    volatile float test3[131];
    float *pt = (float *)&test3;
    for(n=0;n<sizeof(test3)/2;n++)
    {
        *pt = 0;
        pt++;
    }

            MOVB      XAR6,#64              ; [CPU_ALU] 
    	.dwpsn	file "../main.c",line 211,column 9,is_stmt,isa 0
            ZERO      R1H                   ; [CPU_FPU] |211| 
            ZERO      R0H                   ; [CPU_FPU] |211| 
    	.dwpsn	file "../main.c",line 208,column 15,is_stmt,isa 0
            MOVL      XAR4,#||test3||       ; [CPU_ARAU] |208| 
    ||$C$L42||:    
    ; Peeled loop iterations for unrolled loop:
    	.dwpsn	file "../main.c",line 211,column 9,is_stmt,isa 0
            MOV32     *XAR4++,R1H           ; [CPU_FPU] |211| 
            MOV32     *XAR4++,R0H           ; [CPU_FPU] |211| 
    	.dwpsn	file "../main.c",line 209,column 13,is_stmt,isa 0
            BANZ      ||$C$L42||,AR6--      ; [CPU_ALU] |209| 

    根据数组大小编译器有时会采用RPTB语句,有时会采用BANZ语句。采用RPTB时用时大约为每字0.5个时钟周期,采用BANZ时大约为每字1.7个时钟周期。

    如果要确保编译器采用RPTB语句,可以将数组或结构体补齐至6或8的整数倍个32位。6的整数倍时汇编代码(414个float):

            MOVB      XAR6,#68              ; [CPU_ALU] 
    	.dwpsn	file "../main.c",line 211,column 9,is_stmt,isa 0
            ZERO      R2H                   ; [CPU_FPU] |211| 
            ZERO      R1H                   ; [CPU_FPU] |211| 
            ZERO      R0H                   ; [CPU_FPU] |211| 
    	.dwpsn	file "../main.c",line 208,column 15,is_stmt,isa 0
            MOVL      XAR4,#||test3||       ; [CPU_ARAU] |208| 
    	.dwpsn	file "../main.c",line 209,column 13,is_stmt,isa 0
            RPTB      ||$C$L43||,AR6        ; [CPU_ALU] |209| 
            ; repeat block starts ; [] 
    ||$C$L42||:    
    	.dwpsn	file "../main.c",line 211,column 9,is_stmt,isa 0
            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 ; [] 

    8的整数倍时汇编代码(408个float):

            MOVB      XAR6,#50              ; [CPU_ALU] 
    	.dwpsn	file "../main.c",line 211,column 9,is_stmt,isa 0
            ZERO      R1H                   ; [CPU_FPU] |211| 
            ZERO      R0H                   ; [CPU_FPU] |211| 
            ZERO      R2H                   ; [CPU_FPU] |211| 
    	.dwpsn	file "../main.c",line 208,column 15,is_stmt,isa 0
            MOVL      XAR4,#||test3||       ; [CPU_ARAU] |208| 
    	.dwpsn	file "../main.c",line 209,column 13,is_stmt,isa 0
            RPTB      ||$C$L43||,AR6        ; [CPU_ALU] |209| 
            ; repeat block starts ; [] 
    ||$C$L42||:    
    	.dwpsn	file "../main.c",line 211,column 9,is_stmt,isa 0
            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| 
            MOV32     *XAR4++,R2H           ; [CPU_FPU] |211| 
            MOV32     *XAR4++,R1H           ; [CPU_FPU] |211| 
            MOV32     *XAR4++,R0H           ; [CPU_FPU] |211| 
            ; repeat block ends ; [] 

    但这个方法无法用在不是32位对齐的数组和结构体上,而且不补数组长度时有时会调用到BANZ。所以我想看看有没有更高效或更方便的方法利用编译器优化生成高效的汇编代码,或者有没有直接的汇编语句能够供调用。

  • 你好,我需要咨询下相关资深工程师,一旦有回复会立即回复给您。