ZHCUAQ1G June   2015  – August 2025

 

  1.   1
  2.   请先阅读
    1.     关于本手册
    2.     标记规则
    3.     相关文档
    4.     德州仪器 (TI) 提供的相关文档
    5.     商标
  3. 软件开发工具简介
    1. 1.1 软件开发工具概述
    2. 1.2 编译器接口
    3. 1.3 ANSI/ISO 标准
    4. 1.4 输出文件
    5. 1.5 实用程序
  4. 开始使用代码生成工具
    1. 2.1 Code Composer Studio 项目如何使用编译器
    2. 2.2 从命令行编译
  5. 使用 C/C++ 编译器
    1. 3.1  关于编译器
    2. 3.2  调用 C/C++ 编译器
    3. 3.3  使用选项更改编译器的行为
      1. 3.3.1  链接器选项
      2. 3.3.2  常用选项
      3. 3.3.3  其他有用的选项
      4. 3.3.4  运行时模型选项
      5. 3.3.5  选择目标 CPU 版本(--silicon_version 选项)
      6. 3.3.6  符号调试和分析选项
      7. 3.3.7  指定文件名
      8. 3.3.8  更改编译器解释文件名的方式
      9. 3.3.9  更改编译器处理 C 文件的方式
      10. 3.3.10 更改编译器解释和命名扩展名的方式
      11. 3.3.11 指定目录
      12. 3.3.12 汇编器选项
    4. 3.4  通过环境变量控制编译器
      1. 3.4.1 设置默认编译器选项 (C6X_C_OPTION)
      2. 3.4.2 命名一个或多个备用目录 (C6X_C_DIR)
    5. 3.5  控制预处理器
      1. 3.5.1  预先定义的宏名称
      2. 3.5.2  #include 文件的搜索路径
        1. 3.5.2.1 在 #include 文件搜索路径(--include_path 选项)中新增目录
      3. 3.5.3  支持#warning 和 #warn 指令
      4. 3.5.4  生成预处理列表文件(--preproc_only 选项)
      5. 3.5.5  预处理后继续编译(--preproc_with_compile 选项)
      6. 3.5.6  生成带有注释的预处理列表文件(--preproc_with_comment 选项)
      7. 3.5.7  生成带有行控制详细信息的预处理列表(--preproc_with_line 选项)
      8. 3.5.8  为 Make 实用程序生成预处理输出(--preproc_dependency 选项)
      9. 3.5.9  生成包含#include在内的文件列表(--preproc_includes 选项)
      10. 3.5.10 在文件中生成宏列表(--preproc_macros 选项)
    6. 3.6  将参数传递给 main()
    7. 3.7  了解诊断消息
      1. 3.7.1 控制诊断消息
      2. 3.7.2 如何使用诊断抑制选项
    8. 3.8  其他消息
    9. 3.9  生成交叉参考列表信息(--gen_cross_reference_listing 选项)
    10. 3.10 生成原始列表文件(--gen_preprocessor_listing 选项)
    11. 3.11 使用内联函数扩展
      1. 3.11.1 内联内在函数运算符
      2. 3.11.2 内联限制
      3. 3.11.3 不受保护定义控制的内联
        1. 3.11.3.1 使用内联关键字
      4. 3.11.4 保护内联和 _INLINE 预处理器符号
        1. 3.11.4.1 头文件 string.h
        2. 3.11.4.2 库定义文件
    12. 3.12 中断灵活性选项(--interrupt_threshold 选项)
    13. 3.13 使用交叉列出功能
    14. 3.14 关于应用程序二进制接口
    15. 3.15 启用入口挂钩和出口挂钩函数
  6. 优化您的代码
    1. 4.1  调用优化
    2. 4.2  控制代码大小与速度
    3. 4.3  执行文件级优化(--opt_level=3 选项)
      1. 4.3.1 创建优化信息文件(--gen_opt_info 选项)
    4. 4.4  程序级优化(--program_level_compile 和 --opt_level=3 选项)
      1. 4.4.1 控制程序级优化(--call_assumptions 选项)
      2. 4.4.2 混合 C/C++ 和汇编代码时的优化注意事项
    5. 4.5  自动内联扩展(--auto_inline 选项)
    6. 4.6  优化软件流水线
      1. 4.6.1 关闭软件流水线(--disable_software_pipeline 选项)
      2. 4.6.2 软件流水线信息
        1. 4.6.2.1 软件流水线信息
        2. 4.6.2.2 软件流水线信息术语
        3. 4.6.2.3 不符合软件流水线的循环的消息循环
        4. 4.6.2.4 流水线故障消息
        5. 4.6.2.5 由 --debug_software_pipeline 选项生成寄存器使用表
      3. 4.6.3 折叠逻辑程序和收尾程序以改善性能和代码大小
        1. 4.6.3.1 推测执行
        2. 4.6.3.2 选择最佳阈值
    7. 4.7  冗余循环
    8. 4.8  通过 SPLOOP 使用循环缓冲区
    9. 4.9  减小代码大小(--opt_for_space(或 -ms)选项)
    10. 4.10 使用反馈制导优化
      1. 4.10.1 反馈向导优化
        1. 4.10.1.1 第 1 阶段 - 收集程序分析信息
        2. 4.10.1.2 第 2 阶段 - 使用应用程序分析信息进行优化
        3. 4.10.1.3 生成和使用配置文件信息
        4. 4.10.1.4 反馈制导优化的应用示例
        5. 4.10.1.5 .ppdata 段
        6. 4.10.1.6 反馈制导优化和代码大小调整
        7. 4.10.1.7 检测程序执行开销
        8. 4.10.1.8 无效的分析数据
      2. 4.10.2 分析数据解码器
      3. 4.10.3 反馈制导优化 API
      4. 4.10.4 反馈制导优化总结
    11. 4.11 使用配置文件信息获得更好的程序缓存布局并分析代码覆盖率
      1. 4.11.1 背景和动机
      2. 4.11.2 代码覆盖
        1. 4.11.2.1 第 1 阶段 - 收集程序分析信息
        2. 4.11.2.2 第 2 阶段 -- 生成代码覆盖信息报告
      3. 4.11.3 您期待看到哪些性能改进?
        1. 4.11.3.1 评估 L1P 缓存性能
      4. 4.11.4 程序缓存布局相关的特征和功能
        1. 4.11.4.1 路径分析器
        2. 4.11.4.2 分析选项
        3. 4.11.4.3 环境变量
        4. 4.11.4.4 程序缓存布局工具 clt6x
        5. 4.11.4.5 连接器
        6. 4.11.4.6 链接器命令文件运算符 unordered()
      5. 4.11.5 程序指令缓存布局开发流程
        1. 4.11.5.1 收集动态分析信息
        2. 4.11.5.2 从动态分析信息中生成首选功能顺序
        3. 4.11.5.3 在重新构建的应用程序中使用首选函数顺序
      6. 4.11.6 带有加权调用图 (WCG) 信息的逗号分隔值 (CSV) 文件
      7. 4.11.7 链接器命令文件运算符 - unordered()
        1. 4.11.7.1 unordered() 运算符的输出段
        2.       124
        3. 4.11.7.2 为 生成的链接器映射文件
        4. 4.11.7.3 关于 Dot (.)出现 unordered() 的表达式
          1. 4.11.7.3.1 关于a位置表达式
          2.        128
        5. 4.11.7.4 GROUP 和 UNION
          1. 4.11.7.4.1 将 unordered()应用于GROUP
        6.       131
      8. 4.11.8 注意事项
    12. 4.12 指示是否使用了某些别名技术
      1. 4.12.1 采用某些别名时使用 --aliased_variables 选项
      2. 4.12.2 使用 --no_bad_aliases 选项来指示未采用这些技术
      3. 4.12.3 将 --no_bad_aliases 选项与汇编优化器一起使用
    13. 4.13 防止重新排列关联浮点运算
    14. 4.14 在优化代码中谨慎使用 asm 语句
    15. 4.15 使用性能建议优化代码
      1. 4.15.1  Advice #27000
      2. 4.15.2  Advice #27001 提高优化级别
      3. 4.15.3  Advice #27002 不要关闭软件流水线
      4. 4.15.4  Advice #27003 避免使用调试选项进行编译
      5. 4.15.5  Advice #30000 防止由于调用导致循环不合格
      6. 4.15.6  Advice #30001 防止由于 rts 调用导致循环不合格
      7. 4.15.7  Advice #30002 防止由于 asm 语句导致循环不合格
      8. 4.15.8  Advice #30003 防止复杂条件导致的循环不合格
      9. 4.15.9  Advice #30004 防止由于 switch 语句导致循环不合格
      10. 4.15.10 Advice #30005 防止因算术运算导致循环不合格
      11. 4.15.11 Advice #30006 防止由于调用导致循环不合格 (2)
      12. 4.15.12 Advice #30007 防止由于 rts 调用导致循环不合格 (2)
      13. 4.15.13 Advice #30008 改进循环;使用 restrict 进行限定
      14. 4.15.14 Advice #30009 改进循环;添加 MUST_ITERATE pragma
      15. 4.15.15 Advice #30010 改进循环;添加 MUST_ITERATE pragma (2)
      16. 4.15.16 Advice #30011 改进循环;添加 _nasssert()
    16. 4.16 通过优化使用交叉列出特性
    17. 4.17 调试和分析优化代码
      1. 4.17.1 分析优化的代码
    18. 4.18 正在执行什么类型的优化?
      1. 4.18.1  基于成本的寄存器分配
      2. 4.18.2  别名消歧
      3. 4.18.3  分支优化和控制流简化
      4. 4.18.4  数据流优化
      5. 4.18.5  表达式简化
      6. 4.18.6  函数的内联扩展
      7. 4.18.7  函数符号别名
      8. 4.18.8  归纳变量和强度降低
      9. 4.18.9  循环不变量代码运动
      10. 4.18.10 循环旋转
      11. 4.18.11 展开和阻塞
      12. 4.18.12 向量化 (SIMD)
      13. 4.18.13 指令排程
      14. 4.18.14 寄存器变量
      15. 4.18.15 寄存器跟踪/定位
      16. 4.18.16 软件流水线
  7. 使用汇编优化器
    1. 5.1 可提高性能的代码开发流程
    2. 5.2 关于汇编优化器
    3. 5.3 编写线性汇编需要了解的内容
      1. 5.3.1 线性汇编源语句格式
      2. 5.3.2 线性汇编的寄存器规格
        1. 5.3.2.1 用于计算点积的线性汇编代码
        2.       183
        3. 5.3.2.2 用于计算点积的 C 代码
        4.       185
        5. 5.3.2.3 指定寄存器对
        6.       187
        7. 5.3.2.4 指定四倍字寄存器(仅限 C6600)
        8.       189
      3. 5.3.3 线性汇编的功能单元规格
      4. 5.3.4 使用线性汇编源代码注释
        1. 5.3.4.1 显示注释的 Lmac 函数代码
      5. 5.3.5 汇编文件保留您的符号寄存器名称
    4. 5.4 汇编优化器指令
      1.      .call
      2.      .circ
      3.      .cproc/.endproc
      4.      .map
      5.      .mdep
      6.      .mptr
      7.      .no_mdep
      8.      .pref
      9.      .proc/.endproc
      10.      .reg
      11.      .rega/.regb
      12.      .reserve
      13.      .return
      14.      .trip
      15.      .volatile
      16. 5.4.1 过程中不允许使用的指令
    5. 5.5 避免与汇编优化器发生存储器组冲突
      1. 5.5.1 防止存储器组冲突
        1. 5.5.1.1 指定存储器组信息的加载和存储指令
      2. 5.5.2 避免存储器组冲突的点积示例
        1. 5.5.2.1 点积的 C 代码
        2. 5.5.2.2 点积的线性汇编
        3. 5.5.2.3 点积软件流水线内核
        4.       218
        5. 5.5.2.4 中的点积展开以防止存储器组冲突
        6.       220
        7. 5.5.2.5 从 展开的点积内核
        8.       222
      3. 5.5.3 索引指针的存储器组冲突
        1. 5.5.3.1 对索引指针使用 .mptr
      4. 5.5.4 存储器组冲突算法
    6. 5.6 存储器别名消歧
      1. 5.6.1 汇编优化器如何处理存储器引用(默认)
      2. 5.6.2 使用 --no_bad_aliases 选项处理存储器引用
      3. 5.6.3 使用 .no_mdep 指令
      4. 5.6.4 使用 .mdep 指令来识别特定的存储器依赖关系
        1. 5.6.4.1 对存储器引用进行批注
        2.       232
        3. 5.6.4.2 使用 .mdep ld1、st1 的软件流水线
        4.       234
        5. 5.6.4.3 使用 .mdep st1、ld1 和 .mdep ld1、st1 的软件流水线
        6.       236
      5. 5.6.5 存储器别名示例
  8. 链接 C/C++ 代码
    1. 6.1 通过编译器调用链接器(-z 选项)
      1. 6.1.1 单独调用链接器
      2. 6.1.2 调用链接器作为编译步骤的一部分
      3. 6.1.3 禁用链接器(--compile_only 编译器选项)
    2. 6.2 链接器代码优化
      1. 6.2.1 条件链接
      2. 6.2.2 生成函数子段(--gen_func_subsections 编译器选项)
      3. 6.2.3 生成聚合数据子段(--gen_data_subsections 编译器选项)
    3. 6.3 控制链接过程
      1. 6.3.1 包含运行时支持库
        1. 6.3.1.1 自动选择运行时支持库
          1. 6.3.1.1.1 使用 --issue_remarks 选项
        2. 6.3.1.2 手动选择运行时支持库
        3. 6.3.1.3 用于搜索符号的库顺序
      2. 6.3.2 运行时初始化
      3. 6.3.3 全局对象构造函数
      4. 6.3.4 指定全局变量初始化类型
      5. 6.3.5 指定在内存中分配段的位置
      6. 6.3.6 链接器命令文件示例
  9. C/C++ 语言实现
    1. 7.1  TMS320C6000 C 的特征
      1. 7.1.1 实现定义的行为
    2. 7.2  TMS320C6000 C++ 的特性
    3. 7.3  数据类型
      1. 7.3.1 枚举类型大小
      2. 7.3.2 向量、复数和复数向量数据类型
    4. 7.4  文件编码和字符集
    5. 7.5  关键字
      1. 7.5.1 complex 关键字
      2. 7.5.2 const 关键字
      3. 7.5.3 __cregister 关键字
        1. 7.5.3.1 定义和使用控制寄存器
      4. 7.5.4 __interrupt 关键字
      5. 7.5.5 __near 和 __far 关键字
        1. 7.5.5.1 near 和 far 数据对象
        2. 7.5.5.2 near 和 far 函数调用
      6. 7.5.6 restrict 关键字
      7. 7.5.7 volatile 关键字
    6. 7.6  C++ 异常处理
    7. 7.7  寄存器变量和参数
    8. 7.8  __asm 语句
    9. 7.9  pragma 指令
      1. 7.9.1  CALLS Pragma
      2. 7.9.2  CLINK Pragma
      3. 7.9.3  CODE_ALIGN Pragma
      4. 7.9.4  CODE_SECTION Pragma
      5. 7.9.5  DATA_ALIGN Pragma
      6. 7.9.6  DATA_MEM_BANK Pragma
        1. 7.9.6.1 使用 DATA_MEM_BANK Pragma
      7. 7.9.7  DATA_SECTION Pragma
        1. 7.9.7.1 使用 DATA_SECTION Pragma C 源文件
        2. 7.9.7.2 使用 DATA_SECTION Pragma C++ 源文件
        3. 7.9.7.3 使用 DATA_SECTION Pragma 汇编源文件
      8. 7.9.8  诊断消息 Pragma
      9. 7.9.9  FORCEINLINE Pragma
      10. 7.9.10 FORCEINLINE_RECURSIVE Pragma
      11. 7.9.11 FUNC_ALWAYS_INLINE Pragma
      12. 7.9.12 FUNC_CANNOT_INLINE Pragma
      13. 7.9.13 FUNC_EXT_CALLED Pragma
      14. 7.9.14 FUNC_INTERRUPT_THRESHOLD Pragma
      15. 7.9.15 FUNC_IS_PURE Pragma
      16. 7.9.16 FUNC_IS_SYSTEM Pragma
      17. 7.9.17 FUNC_NEVER_RETURNS Pragma
      18. 7.9.18 FUNC_NO_GLOBAL_ASG Pragma
      19. 7.9.19 FUNC_NO_IND_ASG Pragma
      20. 7.9.20 FUNCTION_OPTIONS Pragma
      21. 7.9.21 INTERRUPT Pragma
      22. 7.9.22 LOCATION Pragma
      23. 7.9.23 MUST_ITERATE Pragma
        1. 7.9.23.1 MUST_ITERATE Pragma 语法
        2. 7.9.23.2 使用 MUST_ITERATE 扩展编译器对循环的了解
      24. 7.9.24 NMI_INTERRUPT Pragma
      25. 7.9.25 NOINIT 和 PERSISTENT Pragma
      26. 7.9.26 NOINLINE Pragma
      27. 7.9.27 NO_HOOKS Pragma
      28. 7.9.28 once Pragma
      29. 7.9.29 pack Pragma
      30. 7.9.30 PROB_ITERATE Pragma
      31. 7.9.31 RETAIN Pragma
      32. 7.9.32 SET_CODE_SECTION 和 SET_DATA_SECTION Pragma
      33. 7.9.33 STRUCT_ALIGN Pragma
      34. 7.9.34 UNROLL Pragma
    10. 7.10 _Pragma 运算符
    11. 7.11 应用程序二进制接口
    12. 7.12 目标文件符号命名规则(链接名)
    13. 7.13 更改 ANSI/ISO C/C++ 语言模式
      1. 7.13.1 C99 支持 (--c99)
      2. 7.13.2 C11 支持 (--c11)
      3. 7.13.3 严格 ANSI 模式和宽松 ANSI 模式(--strict_ansi 和 --relaxed_ansi)
    14. 7.14 GNU 和 Clang 语言扩展
      1. 7.14.1 扩展
      2. 7.14.2 函数属性
      3. 7.14.3 For 循环属性
      4. 7.14.4 变量属性
      5. 7.14.5 类型属性
      6. 7.14.6 内置函数
    15. 7.15 向量数据类型的运算和函数
      1. 7.15.1 向量字面量和串联
      2. 7.15.2 向量的一元和二进制运算符
        1. 7.15.2.1 在向量上使用地址运算符
      3. 7.15.3 矢量的混合运算符
      4. 7.15.4 向量的转换函数
      5. 7.15.5 矢量的重新解释函数
      6. 7.15.6 使用 printf() 设置矢量
      7. 7.15.7 内置矢量函数
  10. 运行时环境
    1. 8.1  存储器模型
      1. 8.1.1
      2. 8.1.2 C/C++ 系统堆栈
      3. 8.1.3 动态存储器分配
      4. 8.1.4 数据内存模型
        1. 8.1.4.1 确定数据地址模型
        2. 8.1.4.2 DP 相对寻址与绝对寻址
        3. 8.1.4.3 远常量对象
      5. 8.1.5 函数调用的蹦床生成
      6. 8.1.6 位置无关数据
    2. 8.2  对象表示
      1. 8.2.1 数据类型存储
        1. 8.2.1.1 char 和 short 数据类型(有符号和无符号)
        2. 8.2.1.2 enum、int 和 long 数据类型(有符号和无符号)
        3. 8.2.1.3 浮点数据类型
        4. 8.2.1.4 __int40_t 数据类型(有符号和无符号)
        5. 8.2.1.5 long long 数据类型(有符号和无符号)
        6. 8.2.1.6 double 和 long double 数据类型
        7. 8.2.1.7 指向数据成员类型的指针
        8. 8.2.1.8 指向成员函数类型的指针
        9. 8.2.1.9 结构和数组
      2. 8.2.2 位字段
      3. 8.2.3 字符串常量
      4.      368
    3. 8.3  寄存器惯例
    4. 8.4  函数结构和调用惯例
      1. 8.4.1 函数如何进行调用
      2. 8.4.2 被调用函数如何响应
      3. 8.4.3 访问参数和局部变量
    5. 8.5  访问 C 和 C++ 中的链接器符号
    6. 8.6  将 C 和 C++ 与汇编语言相连
      1. 8.6.1  使用汇编语言模块与 C/C++ 代码
      2. 8.6.2  从 C/C++ 访问汇编语言函数
        1. 8.6.2.1 从 C/C++ 程序调用汇编语言函数
        2. 8.6.2.2 由 调用的汇编语言程序
        3.       380
      3. 8.6.3  从 C/C++ 访问汇编语言变量
        1. 8.6.3.1 访问汇编语言全局变量
          1. 8.6.3.1.1 汇编语言变量程序
          2. 8.6.3.1.2 C 程序从 中访问汇编语言
        2.       385
        3. 8.6.3.2 访问汇编语言常量
          1. 8.6.3.2.1 从 C 语言访问汇编语言常量
          2. 8.6.3.2.2 的汇编语言程序
          3.        389
      4. 8.6.4  与汇编源代码共享 C/C++ 头文件
      5. 8.6.5  使用内联汇编语言
      6. 8.6.6  使用内在函数访问汇编语言语句
      7. 8.6.7  __x128_t 容器类型
        1. 8.6.7.1 __x128_t 容器类型
        2.       395
      8. 8.6.8  __float2_t 容器类型
      9. 8.6.9  使用内在函数进行中断控制和原子代码段
      10. 8.6.10 使用未对齐的数据和 64 位值
        1. 8.6.10.1 使用 _mem8 内在函数
      11. 8.6.11 通过 MUST_ITERATE 和 _nassert 来启用 SIMD 并扩展编译器对循环的了解
      12. 8.6.12 对齐数据的方法
        1. 8.6.12.1 数组的基址
        2. 8.6.12.2 相对于数组基址的偏移
        3. 8.6.12.3 动态存储器分配
        4. 8.6.12.4 结构体或类的成员
          1. 8.6.12.4.1 结构中的数组
          2. 8.6.12.4.2 类中的数组
          3.        408
      13. 8.6.13 SAT 位副作用
      14. 8.6.14 IRP 和 AMR 规则
      15. 8.6.15 浮点和饱和控制寄存器副作用
    7. 8.7  中断处理
      1. 8.7.1 保存 SGIE 位
      2. 8.7.2 在中断期间保存寄存器
      3. 8.7.3 使用 C/C++ 中断例程
      4. 8.7.4 使用汇编语言中断例程
    8. 8.8  运行时支持算术例程
    9. 8.9  系统初始化
      1. 8.9.1 用于系统预初始化的引导挂钩函数
      2. 8.9.2 变量的自动初始化
        1. 8.9.2.1 零初始化变量
        2. 8.9.2.2 的直接初始化
        3. 8.9.2.3 运行时变量自动初始化
        4. 8.9.2.4 的自动初始化表
          1. 8.9.2.4.1 数据格式遵循的长度
          2. 8.9.2.4.2 零初始化格式
          3. 8.9.2.4.3 行程编码 (RLE) 格式
          4. 8.9.2.4.4 Lempel-Ziv-Storer-Szymanski 压缩 (LZSS) 格式
          5. 8.9.2.4.5 用于处理 C 自动初始化表的 C 代码示例
        5. 8.9.2.5 在加载时初始化变量
        6. 8.9.2.6 全局构造函数
    10. 8.10 多线程运行时支持
      1. 8.10.1 运行时线程安全
      2. 8.10.2 线程创建、初始化和终止
      3. 8.10.3 线程局部存储 (TLS)
      4. 8.10.4 访问共享数据
  11. 使用运行时支持函数并构建库
    1. 9.1 C 和 C++ 运行时支持库
      1. 9.1.1 将代码与对象库链接
      2. 9.1.2 头文件
      3. 9.1.3 修改库函数
      4. 9.1.4 支持字符串处理
      5. 9.1.5 极少支持国际化
      6. 9.1.6 时间和时钟函数支持
      7. 9.1.7 允许打开的文件数量
      8. 9.1.8 库命名规则
    2. 9.2 C I/O 函数
      1. 9.2.1 高级别 I/O 函数
        1. 9.2.1.1 格式化和格式转换缓冲区
      2. 9.2.2 低级 I/O 实现概述
        1.       open
        2.       close
        3.       read
        4.       write
        5.       lseek
        6.       unlink
        7.       rename
      3. 9.2.3 器件驱动程序级别 I/O 函数
        1.       DEV_open
        2.       DEV_close
        3.       DEV_read
        4.       DEV_write
        5.       DEV_lseek
        6.       DEV_unlink
        7.       DEV_rename
      4. 9.2.4 为 C I/O 添加用户定义的器件驱动程序
        1. 9.2.4.1 将默认流映射到器件
      5. 9.2.5 器件前缀
        1.       add_device
        2.       470
        3. 9.2.5.1 为 C I/O 器件编程
    3. 9.3 处理可重入性(_register_lock() 和 _register_unlock() 函数)
    4. 9.4 库构建流程
      1. 9.4.1 所需的非德州仪器 (TI) 软件
      2. 9.4.2 使用库构建流程
        1. 9.4.2.1 通过链接器自动重建标准库
        2. 9.4.2.2 手动调用 mklib
          1. 9.4.2.2.1 构建标准库
          2. 9.4.2.2.2 共享或只读库目录
          3. 9.4.2.2.3 使用自定义选项构建库
          4. 9.4.2.2.4 mklib 程序选项摘要
      3. 9.4.3 扩展 mklib
        1. 9.4.3.1 底层机制
        2. 9.4.3.2 来自其他供应商的库
  12. 10C++ 名称还原器
    1. 10.1 调用 C++ 名称还原器
    2. 10.2 C++ 名称还原器的示例用法
  13.   A 术语表
    1.     489
  14.   B 修订历史记录

在向量上使用地址运算符

向量数据对象:如果使用一元 & 运算符获取向量数据对象的地址,则结果为指针。与获取数组地址不同,获取向量的地址会提供一个表示整个向量的指针,而不是指向单个元素的指针。

例如,给定一个类型为 int4 的对象 vec,表达式 &vec 的类型为 int4 *

int4 vec;
randomize(&vec); /* OK */

若要访问指针向量对象的元素,请使用混合运算符,而不是尝试将指针转换为其他某种指针类型。请参阅 节 7.15.3

void randomize(int4 *vecp)
{
    for([..]) (*vecp).s[i] = rand();
}

复杂数据对象:同样,如果使用一元 & 运算符获取复数标量对象的地址,则结果为指针。此指针表示整个复数标量对象,而不是单个组件。

cfloat cplx;
foo(&cplx); /* OK */

向量数据元素:您可以使用一元 & 运算符获取索引样式混合的地址(例如 &x.s[1]x.s[j]))。地址是指向该元素的指针,带有预期的语义。但是,不能使用一元 & 运算符获取非索引样式混合的地址,例如 s1、s1() 或 r()。

带有 const 限定符的类型:您可以使用 const 类型限定符来声明向量类型和复数类型。其语义与非向量类型的语义相同。使用一元 & 运算符获取 const 向量对象的地址会给出指向符合 const 条件的向量类型的指针。

带有 volatile 限定符的类型:您可以使用 volatile 类型限定符来声明向量类型和复数类型。其语义与非向量类型的语义相同。使用一元 & 运算符获取 volatile 向量对象的地址会给出指向符合 volatile 条件的向量类型的指针。

在优化对任何 volatile 对象的访问时,编译器必须保留在运行时进行访问的次数和相对顺序。如果可能,编译器会一次访问 volatile 向量对象整个向量,而不是逐元素访问。如果这无法实现(例如,由于向量大于单个向量寄存器),编译器可以将 volatile 访问拆分为较小的块,并且未规定访问这些较小块的顺序。

应考虑这些循环。第一个循环是原始循环,第二个循环是向量化版本:


volatile int *p = array;                    /* original loop */
for ([..])
    *p++ = [..]                             /* process one int at a time in sequence */

volatile int8 *p8 = (volatile int8 *)array; /* vectorized loop */
for ([..])
    *p8++ = [..]                            /* process 8 int at a time in parallel */

此示例中的第一个循环按顺序一次访问一个数组元素。第二个循环并行访问 8 个 int。由于第二个循环会更改访问的相对顺序,因此不允许编译器自动将第一个循环转换为第二个循环。如果有必要,您可以手动从一种访问方式更改到另一种访问方式。

带有 restrict 限定符的指针:如果指针遵循 restrict 关键字的常规规则,则可以将 restrict 限定符添加到指向向量类型的指针。简而言之,指向向量的指针必须是访问指针指向的向量的唯一方式。

向量和数组之间的对应关系:向量最有效的用途是处理具有尽可能大向量的大量数据。向量和数组非常相似,因此您可以轻松使用向量指针来访问大型数组。例如:

int array[N];
int8 vec = *(int8 *)array; /* vector to access first 8 ints in array */

向量的一个重要用途是通过将数组(或指针)的地址转换为指向向量的指针类型来访问数组。然后,该指针可用于并行加载或存储数组的多个元素。假设您有以下示例:

void dotp(int x[N], int y[N], int z[restrict])
{
    /* original */
    for (int i=0;i<N;i++)
    {
        /* process the data one int at a time */
        *z++ = *x++ + *y++;
    }
}

编译器可以自动转换这个简单的例子,因为 restrict 关键字告诉编译器,z 输入参数不会与 xy 重叠。

void dotp(int x[N], int y[N], int z[restrict])
{
    int8 *xp = (int8 *)x;
    int8 *yp = (int8 *)y;
    int8 *zp = (int8 *)z;
    for (int i=0;i<N/8;i++)
    {
        /* process the data 8 ints at a time */
        *zp++ = *xp++ + *yp++;
    }
}
注: 当使用指向向量的指针从非复数数组中读取时,请将向量的元素类型与非复数数组的元素类型相匹配。例如,如果数组类型为 const int array[N],则将向量设置为具有 int 元素的常量,如 const int8

使用指向向量的指针访问数组是安全的,因为数组和向量的元素在存储到存储器中时,以相同的方式存储和对齐。在存储器中,无论字节序模式如何,向量的第一个元素 (s0) 都存储在存储器中的最低地址。根据字节序模式来存储每个元素的各个字节。然后将数组的第一个元素分配给向量的第一个元素 (s0)。

使用 C++ 时,可以使用类似的代码来处理 std::vector 或 std::array 的多个元素,并使用 data() 成员:

void dotp(std::vector<int> x, std::vector<int> y, std::vector<int> z)
{
    int8 *xp = (int8 *)x.data();
    int8 *yp = (int8 *)y.data();
    int8 *zp = (int8 *)z.data();
    for (int i=0;i<N/8;i++)
    {
        /* process the data 8 ints at a time */
        *zp++ = *xp++ + *yp++;
    }
}

void dotp(std::array<int> x, std::array<int> y, std::array<int> z)
{
    int8 *xp = (int8 *)x.data();
    int8 *yp = (int8 *)y.data();
    int8 *zp = (int8 *)z.data();
    for (int i=0;i<N/8;i++)
    {
        /* process the data 8 ints at a time */
        *zp++ = *xp++ + *yp++;
    }
}

访问作为向量的复数类型:复数标量对象存储在存储器中,实分量位于最低地址。复数向量对象存储为复数标量值序列,s0 的实分量位于最低地址,后跟 s0 的虚分量,依此类推。

您可以将非复数数组作为复数标量来访问:

float value[2];
cfloat x = *(cfloat *)&value;

您可以将复数标量作为长度为 2 的复数标量来访问,该向量的元素类型与复数分量相同:

cchar value;
char2 x = *(char2 *)&cchar;

您可以将非复数标量数组作为复数向量来访问,前提是复数值存储在非复数标量数组中,首先存储实分量,然后存储虚分量。您可以根据需要使用一个 1 维或 2 维数组。

float value[2][] = { { r, i }, { r, i } ... };
cfloat4 x = *(cfloat4 *)&value;

float value[] = { r, i, r, i, ... };
cfloat4 x = *(cfloat4 *)&value;

您可以将任何复数向量作为两倍长度的向量来访问,并使用与复数分量相同的元素类型:

cchar4 value;
char8 x = *(char8 *)&value;
注: 当使用指向复数的指针从非复数数组中读取时,使复数对象的元素类型与非复数数组的分量类型相匹配。例如,如果数组的类型为 const int coefficients[2][N],则将向量设置为具有 int 元素的常量(例如 const cint8)。

C 代码中复数值的一个常见用例是将它们表示为分量值的二维数组,如下所示:

float coefficients[2][4] =
{ { real, imag }, { real, imag },
  { real, imag }, { real, imag }, };

/* access part of the coefficient array as a vector */
output = input * *(cfloat4 *)coefficients;

您还可以从 C99 复数值数组中初始化复数向量,因为 C99 复数对象和 TI 复数对象的布局相同:

float _Complex coefficients[4] =
{ real + imag * _Complex_I, real + imag * _Complex_I,
  real + imag * _Complex_I, real + imag * _Complex_I, };

/* access part of the coefficient array as a vector */
output = input * *(cfloat4 *)coefficients;