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.

[参考译文] 编译器/DRA786:如果使用优化(-O2或更高版本)、C 编译器会生成不正确的代码

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

https://e2e.ti.com/support/tools/code-composer-studio-group/ccs/f/code-composer-studio-forum/791676/compiler-dra786-c-compiler-generating-incorrect-code-if-using-optimization--o2-or-higher

器件型号:DRA786

工具/软件:TI C/C++编译器

客户在使用浮点数运行的函数中观察到 NaN 错误。 他确定了此错误的位置、相关代码如下所示。

;--------------------------------------------------------------

;57| PEX->QualityParams->政治家 缓冲2[0]= z;

;--------------------------------------------------------------

LDW .d1T2 *+A23[A17]、B9;[A_D64P]|57|<0、44>

NOP 1;[A_L66]

.dwpsn 文件"../main.c"、行55、列9、is_stmt、ISA 0

FADDSP .L2 B9、B4、B4;[B_L66]|55|<0、46>^

NOP 2;[A_L66]

FSUBSP .L2 B4、B5、B4;[B_L66]|55|<0、49>^

|| ADDAD .D2 B9、15、B5;[B_D64P]|59|<0、49>

 

在使用 LDW 指令将数据读取到 B9寄存器和使用 FADDSP 中的 B9寄存器之间只有一个 NOP、该 NOP 与 LDW 指令所需的延迟时隙数不匹配。 此问题出现在 C6000 cgtools v8.1.3和所有其他8.1.x 修订版本(最高为 v8.1.8)中。 仅当使用编译器选项-O2或-O3时才会发生这种情况。 如果使用 C6000 cgtools v8.2.0或更高版本、生成的代码将按预期工作。 现在、客户正在评估、即使在 其项目的非常晚的开发阶段、切换到较新的编译器版本(v8.2.x)是否安全。

他的基本问题我目前无法回答:上面描述的编译器错误是否已知、如果是这种情况、是否可以确保在较新的 v8.2.x 版本中修复了此问题? 我希望编译器团队中的某个人能够回答这个问题。 如果需要、我还可以提供允许重现错误的测试代码。


此致、

曼弗雷德

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

    [引用 USER="Manfred Becker"]使用 LDW 指令将数据读取到 B9寄存器与使用 FADDSP[/QUERP]中的 B9寄存器之间只有一个 NOP

    这可能是有意的。  注释中的<0、44>(及类似内容)表示此代码位于软件流水线循环内。  此类循环中的代码可以按顺序安排。  在这种特定情况下、这意味着编译器打算读取 B9的旧值、即使新值正在传播。  您不能这样做、因为可能会发生中断。  但是、在软件流水线循环内、中断被禁用。   

    那么、到目前为止、该代码看起来不是错误的。  但是,Nan 意味着有问题。  可能是由于用户代码或编译器中的错误。  这并不常见、但我看到编译器优化发现了源代码中的问题。   

    将示波器范围缩小到如下所示的范围是否实际:这些是函数的输入、这是未使用优化时看到的输出、这是使用-O2时看到的输出。  希望这是实用的、您可以按照文章 How to Submit a Compiler Test Case中的说明进行操作。

    谢谢、此致、

    乔治

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

    感谢您通过其他渠道提交测试案例。  我可以重现问题行为。  在循环的第一次迭代中、MPYSP 指令正在读取函数内未初始化的寄存器、因此包含未知值。  我在 SDOWP 系统中提交了条目 CodeGen-6159。  欢迎您在我的签名中使用下面的 SDOWP 链接进行访问。

    谢谢、此致、

    乔治

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

    乔治

    我对编译器生成的循环代码进行了更多分析。 管道循环内核代码使用条件指令来排除此循环第一次迭代的部分指令。 在第一次循环迭代期间会使用未初始化的寄存器数据、从而在 FADCR、FAUCR 和/或 FMCR 寄存器中设置 NaN 等警告标志。 实际上、在第一个循环迭代期间生成的无效结果不会存储到存储器中、因为相关的存储指令也有条件地执行、并且存储指令的条件仍然为 false。 这意味着、优化的环路生成的输出是正确的、但遗憾的是、浮点配置寄存器内的警告标志会被置位。

    如果将构建选项"-opt_for_speed=3"与-O2或-O3结合使用、即使对于从不 v8.2.x 或 v8.3.x 编译器版本、我也会看到相同的行为。

    客户在音频处理环路末尾测试浮点配置寄存器的多个警告标志、以检测可能导致音频数据故障的计算问题、只是为了在向放大器发送无效数据之前有机会将音频静音。 如果查看上述设置这些警告标志的机制、这是否意味着 FADCR、FAUCR 和 FMCR 不能用于此类错误检测?

    此致、

    曼弗雷德

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

    C6000编译器手册中介绍了这种情况。  请搜索标题 为"浮点控制寄存器副作用"的子章节。   

    关于 MPYSP 指令,我在上面提到... 在循环的第一次迭代期间、即使其中一个输入寄存器未初始化、也会执行该循环。  我们称之为推测执行。  下面是一种防止编译器使用推测执行的方法、该方法可以更改浮点控制寄存器中的位。  在文件开头附近添加此行...

    #include 

    这提供了浮点控制寄存器 FADCR、FAUCR 和 FMCR 的定义。  然后,在函数的末尾,在函数的末尾要防止推测执行,请编写一条语句,该语句仅引用这些寄存器中的一个...

    FADCR; 

    这会使所有浮点指令像加载和存储指令一样被预测。  另一种说法是:不存在可以更改浮点控制寄存器的浮点指令的推测执行。

    此更改似乎不会对您发送的代码示例造成太大的性能影响。  但是、它可能会导致其他函数运行速度变慢。

    请注意、对于 FADCR 的引用必须出现 在每个函数内、其中不应发生推测执行。  这在整个应用中可能不切实际。

    [引用 user="Manfred Becker"]这是否意味着 FADCR、FAUCR 和 FMCR 不能用于此类错误检测?

    如果不能像我在这篇文章中描述的那样防止推测执行、那么是的。

    谢谢、此致、

    乔治