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.

[参考译文] C2000-CGT:尾调用优化

Guru**** 2912410 points

Other Parts Discussed in Thread: C2000-CGT, C2000WARE

请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1572295/c2000-cgt-tail-call-optimisation

器件型号:C2000-CGT
主题: C2000WARE 中讨论的其他器件

工具/软件:

我想知道当前版本的 C2000-CGT 是否能够进行尾调用优化。  编译器手册没有提到这一点、但似乎在 C 编译器中找到了足够普遍的优化。

我找到的这篇文章表明至少有非常旧的 C2000-CGT 版本能够优化尾部递归调用: 在 cmath 中使用 modf (float、float*) 会产生无限循环 — Code Composer Studio 论坛 — Code Composer StudioTm︎ — TI E2E 支持论坛

然而,我的问题不是针对尾部递归函数(我们的代码库中没有任何相关的函数),而是针对一般的尾调用优化——即发射 LB 而不是 LCR; LRETR。

我们以以下 C 函数为例简单说明:

__attribute__((ramfunc)) static void tx0(void) {
    set_low();
    DEVICE_DELAY_US(10);
    set_high();
    DEVICE_DELAY_US(5);
}

device_delay_US 扩展到从 C2000Ware (F2838x) 对 SysCtl_delay 的调用。 生成的汇编代码 (C2000-CGT 22.6.2.LTS、--silicon_version=28            --abi=eabi --unified_memory   --cla_support=cla2         --float_support=fpu64 --idiv_support=idiv0 --tmu_support=tmu0 --vcu_support=vcrc - opt_level=4 --float_sperelax_debug - optime_proc_relaxed - op_debug - opt_prec11-op_debug - op_debug - optime-comprelax_debug -  
如下所示:

        LCR       set_low
        MOV       ACC, #398
        LCR       SysCtl_delay
        LCR       set_high
        MOVB      ACC, #198
        LCR       SysCtl_delay
        LRETR

我天真地希望将最后两行替换为LB SysCtl_delay将产生功能等效的代码、但返回后会节省 4 个 CPU 周期。 考虑到有意长时间的延迟、这在特定示例中当然无关紧要、但希望能得到正确答案。 可以分享其他示例、但可能需要 进行一定程度的手动编辑、以避免发布任何专有 IP 的风险。

 由于被调用函数被内联、但非内联调用站点会保留、因此在使用-O4 链接期间、为我们代码生成的汇编代码中的一些情况会被消除。 这还包括间接调用(即 LCR *XARn;LRETR)、我假设该调用可与 LB *XAR7 类似地替换。

这让我想知道:启用尾调用优化是否需要任何特定的编译标志? 相反、已知是否有禁止它的标志? 或者、C2000 编译器通常不能进行尾调用优化?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

    或者、C2000 编译器通常不能进行尾调用优化?

    与其他 处理器的 TI 编译器相比、C2000 编译器中对尾调用优化和尾递归的支持更有限。  遗憾的是、这对您没有太大帮助。   您提到可以提供一些手动编辑的示例。 IA 简单的测试案例演示了您的案例与相关代码互动将有助于我们深入了解。   请按照 如何提交编译器测试用例一文中的说明进行操作

    谢谢、

    -Alan

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    即使是最简单的单文件测试案例也无法定制:

    extern void foo(void);
    
    void bar(void) {
    		foo();
    }

    编译时采用:

    cl2000.exe --silicon_version=28     --abi=eabi     --unified_memory     --cla_support=cla2     --float_support=fpu64     --idiv_support=idiv0     --tmu_support=tmu0     --vcu_support=vcrc     --opt_level=4 --opt_for_speed=3 --fp_mode=relaxed --symdebug:dwarf --c11 --relaxed_ansi --keep_asm --preproc_with_compile foo.c

    现在,如果在实际代码中这是对 foo () 的唯一调用,它可能会在链接时优化期间被内联。 然而、对于非内联情况、 我还没有观察到在 LTO 期间插入了尾调用。 因此剩下的是最初发射的组件:

    ||bar||:
    	.dwcfi	cfa_offset, -2
    	.dwcfi	save_reg_to_mem, 26, 0
    	.dwpsn	file "foo.c",line 4,column 3,is_stmt,isa 0
    $C$DW$3	.dwtag  DW_TAG_TI_branch
    	.dwattr $C$DW$3, DW_AT_low_pc(0x00)
    	.dwattr $C$DW$3, DW_AT_name("foo")
    	.dwattr $C$DW$3, DW_AT_TI_call
    
            LCR       #||foo||              ; [CPU_ALU] |4| 
            ; call occurs [#||foo||] ; [] |4| 
    $C$DW$4	.dwtag  DW_TAG_TI_branch
    	.dwattr $C$DW$4, DW_AT_low_pc(0x00)
    	.dwattr $C$DW$4, DW_AT_TI_return
    
            LRETR     ; [CPU_ALU] 
            ; return occurs ; [] 
    	.dwattr $C$DW$2, DW_AT_TI_end_file("foo.c")
    	.dwattr $C$DW$2, DW_AT_TI_end_line(0x05)
    	.dwattr $C$DW$2, DW_AT_TI_end_column(0x01)
    	.dwendentry
    	.dwendtag $C$DW$2
    

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我的问题不是针对尾部递归函数(我们的代码库中没有任何相关的递归函数)、而是针对一般的尾调用优化----即用 LB 代替 LCR;LRETR。

    C2000 编译器优化尾递归函数、但不优化通用尾调用。

    谢谢。此致、

    -乔治