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.

[参考译文] TMS320F28388D:在 TI C2000编译器中使用-O4时的优化行为

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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1500600/tms320f28388d-optimization-behavior-with--o4-in-ti-c2000-compiler

器件型号:TMS320F28388D

工具/软件:

我将 TI C2000编译器与以下优化标志配合使用:

/opt/ti/ti-cgt-c2000_22.6.1.LTS/bin/cl2000 \
--issue_remarks --gen_opt_info=2 -v28 -ml -O4 -op=3 \
--c_src_interlist --auto_inline --verbose_diagnostics \
--advice:performance=all --opt_for_speed=5 \
--preproc_with_compile --keep_asm \
-I/opt/ti/ti-cgt-c2000_22.6.1.LTS/include \
main.cpp

`、我注意到 μ C-O4` 优化级别的代码优化行为存在一些效率低下问题、我想问问是否有任何解决这些问题的建议或见解。

静态表优化

在第一个示例中table[]foo(),我在函数中有一个静态,我希望编译器优化此表并删除不必要的内存访问。 但是、即使的值a在表的范围内、仍直接访问表。 相比之下、优化级别的 GCC-O1 可以更高效地处理此问题。 是否有任何方法可以确保正确优化扫描床?

/*
    MOVZ      AR6,AL                ; [CPU_ALU] |4|
    MOVL      XAR4,#_table$1        ; [CPU_ARAU] |6|
    SETC      SXM                   ; [CPU_ALU]
    MOVL      ACC,XAR4              ; [CPU_ALU] |6|
    ADD       ACC,AR6               ; [CPU_ALU] |6|
    MOVL      XAR4,ACC              ; [CPU_ALU] |6|
    MOV       AL,*+XAR4[0]          ; [CPU_ALU] |6|
    LRETR     ; [CPU_ALU]
*/
int foo(char a) {
    static const int table[] = { 1,2,3,4,5 };
    return table[a];
}

自动内联

在第二个示例中、read()函数很简单、理想情况下应被内联、尤其是在给定--auto_inline flag 的情况下。 但是、编译器似乎未内联此函数。 GCC-O1 自动内联。 为什么这个函数即使与一起也没有内联到 C2000编译器中-O4、是否有其他标志可以确保这一点?

我还观察到编译器会生成一个不必要的调用memcpy(),这对于性能来说并不理想。 代码本质上是在使用更简单的指令可以完成的值周围移动、因此我很惊讶地看到 memcpy 调用。 如何避免此问题、或者是否有可以更好地优化此模式的设置?

/*
ADDB      SP,#4                 ; [CPU_ARAU]
MOV       PL,#65012             ; [CPU_ALU] |2|
MOVZ      AR4,SP                ; [CPU_ALU] |8|
MOV       PH,#16180             ; [CPU_ALU] |2|
MOVL      ACC,XAR6              ; [CPU_ALU] |7|
MOVL      *-SP[4],P             ; [CPU_ALU] |2|
SUBB      XAR4,#4               ; [CPU_ARAU] |8|
MOV       PL,#65012             ; [CPU_ALU] |2|
MOV       PH,#16180             ; [CPU_ALU] |2|
MOVZ      AR5,AR4               ; [CPU_ALU] |8|
MOVL      *-SP[2],P             ; [CPU_ALU] |2|
B         $C$L1,EQ              ; [CPU_ALU] |8|
MOVL      XAR4,ACC              ; [CPU_ALU] |8|
MOVB      ACC,#4                ; [CPU_ALU] |8|
LCR       #_memcpy              ; [CPU_ALU] |8| << Whoooh!
SUBB      SP,#4                 ; [CPU_ARAU]
LRETR     ; [CPU_ALU]
*/
struct float2 {
    float2(float x, float y) : x(x), y(y) {}
    float x, y;
};

// Should be auto inlined (called once)
float2 read() { return float2(0.707f, 0.707f); }

float test() {
    float2 v = read();
    return v.x + v.y;
}

如果您有任何使用 TI C2000编译器改进这些用例优化的见解或建议、我将不胜感激。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Unknown 说:
    在第一个示例中、table[]foo()我在函数中有一个静态、我希望编译器优化此表、并删除不必要的内存访问。 但是、即使的值a在表的范围内、仍直接访问表。 相比之下、优化级别的 GCC-O1 可以更高效地处理此问题。

    我无法使用 GCC 编译器重现此结果。  请 使用编译器资源管理器查看此尝试

    Unknown 说:
    在第二个示例中read()、该函数很简单、理想情况下应该被内联
    Unknown 说:
    是否有其他标志可以确保这一点?

    尝试...

    __attribute__((always_inline))
    float2 read() { return float2(0.707f, 0.707f); }

    使用时请小心 always_inline 。  有关详细信息、请在 C28x 编译器手册中进行搜索

    谢谢。此致、

    -乔治

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

    对于第一个例子,我必须同意,我不知何故得到了错误的结果 gcc,与`static`关键字它得到完全优化:

    foo(char):
     movsx rdi, dil
     mov eax, DWORD PTR foo(char)::table[0+rdi*4]
     ret
    在` O3`中、其结果如下所示:
    foo(char):
     movdqa xmm0, XMMWORD PTR .LC0[rip]
     movsx  rdi, dil
     mov    DWORD PTR [rsp-24], 5
     movaps XMMWORD PTR [rsp-40], xmm0
     mov    eax, DWORD PTR [rsp-40+rdi*4]
     ret
    `内联函数、我还没有准备好将`__attribute__((always_inline)) 放在所有函数前、但另一方面、我认为我不准备在 memcpy 和 LCR 中浪费 CPU 计算能力。  
    我错过了什么吗?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    [引述 userid="650329" url="~/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1500600/tms320f28388d-optimization-behavior-with--o4-in-ti-c2000-compiler/5766015 #5766015"]
    `内联函数、我还没有准备好将`__attribute__((always_inline)) 放在所有函数前、但另一方面、我认为我不准备在 memcpy 和 LCR 中浪费 CPU 计算能力。  
    我错过了什么吗?
    [/报价]

    我认为您对的理解很好 always_inline 属性。  仅在性能测试表明显然需要它的几个地方使用它。

    谢谢。此致、

    -乔治

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

    是的、但为什么 cl2000不自动内联一次性使用的函数? 这是大多数编译器中的默认行为。 是否有技术原因?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    为什么 cl2000不自动内联一次性使用的函数?

    根据我在这里看到的情况、我无法回答。  您是否存在所有这些情况都发生在单个源文件中的情况?

    • 函数被调用一次
    • 该函数在同一文件中实现
    • 函数不会被内联

    如果是、对于该文件、 请遵循 如何提交编译器测试用例一文中的说明

    谢谢。此致、

    -乔治