ZHCU881C May   2020  – December 2023

 

  1.   1
  2.   请先阅读
    1.     关于本手册
    2.     相关文档
    3.     商标
  3. 2引言
    1. 2.1 C7000 数字信号处理器 CPU 架构概述
    2. 2.2 C7000 分离式数据路径和功能单元
  4. 3C7000 C/C++ 编译器选项
    1. 3.1 概述
    2. 3.2 为性能选择编译器选项
    3. 3.3 了解编译器优化
      1. 3.3.1 软件流水线
      2. 3.3.2 矢量化和矢量谓词
      3. 3.3.3 自动使用流引擎和流地址生成器
      4. 3.3.4 循环折叠和循环合并
      5. 3.3.5 自动内联
      6. 3.3.6 if 转换
  5. 4基本代码优化
    1. 4.1  迭代计数器和限制的有符号类型
    2. 4.2  浮点除法
    3. 4.3  循环携带依赖和 restrict (限制)关键字
      1. 4.3.1 循环携带依赖
      2. 4.3.2 restrict (限制)关键字
      3. 4.3.3 运行时别名消歧
    4. 4.4  函数调用和内联
    5. 4.5  MUST_ITERATE 和 PROB_ITERATE Pragma 与属性
    6. 4.6  if 语句和嵌套的 if 语句
    7. 4.7  内在函数
    8. 4.8  矢量类型
    9. 4.9  待使用和避免的 C++ 特性
    10. 4.10 流引擎
    11. 4.11 流地址生成器
    12. 4.12 优化库
    13. 4.13 存储器优化
  6. 5了解汇编注释块
    1. 5.1 软件流水线处理阶段
    2. 5.2 软件流水线信息注释块
      1. 5.2.1 循环和迭代计数信息
      2. 5.2.2 依赖和资源限制
      3. 5.2.3 启动间隔 (ii) 和迭代
      4. 5.2.4 常量扩展
      5. 5.2.5 使用的资源和寄存器表
      6. 5.2.6 阶段折叠
      7. 5.2.7 存储器组冲突
      8. 5.2.8 循环持续时间公式
    3. 5.3 单个调度迭代注释块
    4. 5.4 识别流水线故障和性能问题
      1. 5.4.1 阻止循环进行软件流水线作业的问题
      2. 5.4.2 软件流水线故障消息
      3. 5.4.3 性能问题
  7. 6修订历史记录

软件流水线故障消息

编译器可能提供的软件流水线故障消息包括下述内容:

  • 地址增量过大。在软件流水线期间,编译器允许对来在同一数组或指针的所有负载和存储进行重新排序。这样最大限度地提高了调度灵活性。一旦发现调度,编译器就会返回并将适当的偏移量和增量/减量添加到每个负载和存储中。有时在重新排序后,加载和/或存储最终会相互偏移太远(标准加载指针的限制是 +/−32)。如果发生这种情况,尝试重新构造循环,使指针靠得更近,或者重写指针以使用预先计算的寄存器偏移量。
  • 无法分配机器寄存器。在进行软件流水线作业并找到有效的调度之后,编译器将循环中的所有值分配给特定的机器寄存器。在某些情况下,编译器会耗尽机器寄存器,它可以在这些寄存器中分配变量和中间结果的值。如果发生这种情况,请尝试简化循环,或者将循环分解成多个更小的循环。在某些情况下,编译器可以在更高的启动间隔 (ii) 下成功对循环进行软件流水线处理。
  • 循环计数太高。无益。在极少数情况下,软件流水线循环的迭代间隔比非流水线循环的迭代间隔更高。在这种情况下,执行非软件流水线循环更有效率。一种可能的解决方案是将循环分成多个循环或降低循环的复杂性。
  • 未找到调度。有时,编译器在特定启动间隔下无法找到有效的软件流水线调度。一种可能的解决方案是将循环分成多个循环或降低循环的复杂性。
  • 并行迭代 > 最大迭代计数。并非所有循环都可以进行有益的流水线处理。根据可用的最大迭代计数信息,编译器估计,鉴于在当前启动间隔下找到的调度,执行非软件流水线版本总是比执行流水线版本更有利可图。一种可能的解决方案可能是完全展开循环。
  • 并行迭代 > 最小迭代计数。根据可用的最小迭代计数信息,执行流水线版本的循环并非总是安全的。正常情况下会生成冗余循环。然而,在这种情况下,冗余循环生成已通过 --opt_for_speed=3 或更低的选项抑制。一种可能的解决方案是添加 MUST_ITERATE pragma,向编译器提供有关循环的最小迭代计数的更多信息。
  • 寄存器存活时间过长。有时,编译器发现有效的软件流水线调度,但其中一个或多个值存活时间过长。寄存器的生命周期由值写入寄存器的时间与另一条指令读取该值的最后一个周期之间的周期时间决定。根据定义,变量的存活时间永远不会超过循环的 ii ,因为循环的下一次迭代会在读取该值之前将其覆盖。在这条消息之后,编译器会详细描述哪些值存活时间过长:
    ii = 11 Register is live too long
    |72| −> |74|
    |73| −> |75|
    

    在本例中,数字 72、73、74 和 75 对应行号,可映射到违规指令上。编译器积极尝试阻止并修复存活过长的问题。可用来解决存活过长问题的方法成功概率很低。因此,本文档不讨论这些方法。此外,编译器通常可以在更高的启动间隔 (ii) 下找到成功的软件流水线调度。