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修订历史记录

自动内联

编译器有时采用头文件中定义的函数,并将代码放在调用位置。这样,允许在封闭式循环中形成软件流水线作业,从而提高性能。编译器也可以这样做来消除调用函数和从函数返回的成本。

在下例中,add_and_saturate_to_255() 函数对两个值求和,如果总和超过 255,则将总和限制为 255。此函数是从 inlining.cpp 中的函数调用的,该函数通过预处理器的 #include 指令包含 inlining.h 文件。

// inlining.cpp
// Compile with "cl7x -mv7100 --opt_level=3
//   --debug_software_pipeline --src_interlist"
#include "inlining.h"                                                            
                                                                                 
void saturated_vector_sum(int * restrict a, int * restrict b,                    
                          int * restrict out, int n)                             
{                                                                                
#pragma MUST_ITERATE(1024,,)                                                     
#pragma UNROLL(1)                                                                
    for (int i = 0; i < n; i++)                                                  
    {                                                                            
        out[i] = add_and_saturate_to_255(a[i], b[i]);                            
    }                                                                            
}

// inlining.h
int add_and_saturate_to_255(int a, int b)                            
{                      
    int sum = a + b;                                                 
    if (sum > 255) sum = 255;                                        
                                                                     
    return sum;                                                            

在此例中,编译器将内联对 add_and_saturate_to_255() 的调用,因此可执行软件流水线作业。您可以通过查看生成的汇编文件底部确定是否执行了内联。此处,编译器放置入了注释,说明 add_and_saturate_to_255() 已内联。请注意,由于 C++ 名称已改编,故函数的标识符也已被修改。

;; Inlined function references: 
;; [0] _Z23add_and_saturate_to_255ii

在生成的汇编代码中也可以看到内联,因为循环中没有针对函数的调用指令。事实上,由于内联(因而消除了对函数的调用),循环可以进行软件流水线。 如果在循环中调用了另一个函数,则不会发生软件流水线。 请注意,由于代码大小的问题,并非每个可内联的调用都会自动内联。有关内联的更多信息,请参阅 C7000 优化编译器用户指南

;*----------------------------------------------------------------------------* 
;*        SINGLE SCHEDULED ITERATION
;*
;*        ||$C$C44||: 
;*   0              TICK                               ; [A_U] 
;*   1              SLDW    .D1     *D1++(4),BL0      ; [A_D1] |5| 
;*   2              SLDW    .D2     *D2++(4),BL1      ; [A_D2] |5| 
;*   3              NOP     0x5     ; [A_B] 
;*   8              ADDW    .L2     BL1,BL0,BL1       ; [B_L2] |5| 
;*   9              VMINW   .L2     BL2,BL1,B0        ; [B_L2] |5| 
;*  10              STW     .D1X    B0,*D0++(4)       ; [A_D1] |5| 
;*     ||           BNL     .B1     ||$C$C44||        ; [A_B] |11| 
;*  11              ; BRANCHCC OCCURS {||$C$C44||}    ; [] |11| 
;*----------------------------------------------------------------------------*