网站色调选择,wordpress 数据迁移,小程序免费制作平台登录,led灯散热片技术支持 东莞网站建设消除公共部分组
链接器可以检测节组的多个副本#xff0c;并丢弃其他副本。 Arm Compiler for Embedded 生成用于链接的完整对象。因此#xff1a;
如果 C 和 C 源代码中存在内联函数#xff0c;则每个对象都包含该对象所需的内联函数的外联副本。如果在 C 源代码中使用…消除公共部分组
链接器可以检测节组的多个副本并丢弃其他副本。
® Arm Compiler for Embedded 生成用于链接的完整对象。因此
如果 C 和 C 源代码中存在内联函数则每个对象都包含该对象所需的内联函数的外联副本。如果在 C 源代码中使用模板则每个对象都包含对象所需的模板函数。
在公共头文件中声明这些函数时这些函数可能会在随后链接在一起的单独对象中多次定义。为了消除重复项编译器将这些函数编译为公共节组的单独实例。
公共节组的单独实例可能不相同。例如某些副本可能位于使用不同但兼容的构建选项、不同的优化或调试选项构建的库中。
如果副本不相同则 armlink 会根据输入对象的属性保留每个公共节组的最佳可用变体。Armlink 丢弃其余部分。
如果副本相同则 armlink 将保留位于的第一个部分组。
您可以使用以下链接器选项来控制此优化
使用 --bestdebug 选项使用最大的公共数据 COMDAT 组可能提供最佳调试视图。 使用 --no_bestdebug 选项使用最小的 COMDAT 组可能提供最小的代码大小。这是默认设置。 如果使用 -g 编译包含 COMDAT 组 A 的所有文件即使使用 --no_bestdebug映像也会更改。 消除未使用的部分 消除未使用的部分是链接器对图像大小执行的最重要优化。 未使用部分消除 从最终映像中删除无法访问的代码和数据。在可能导致删除所有部分的情况下被禁止显示。 要控制此优化请使用 armlink 选项 --remove、--no_remove、--first、--last 和 --keep。 未使用的部分消除需要一个入口点。因此如果未为映像指定入口点请使用 armlink 选项 --entry 指定入口点。 使用 armlink 选项 --info unused 指示链接器生成它删除的未使用部分的列表。 注意 armlink 报告 错误L6218E未定义的符号 symbol 即使未使用的部分删除已删除此符号的要求。此行为与 GNU 链接器 ld 不同。 在以下情况下输入部分将保留在最终图像中 它包含一个入口点或一个外部可访问的符号。例如Arm®v8-M 安全扩展的安全代码中的输入函数。它是SHT_INIT_ARRAY、SHT_FINI_ARRAY或SHT_PREINIT_ARRAY部分。它被指定为第一个或最后一个输入部分由 --first 或 --last 选项或分散加载等效项指定。它被 --keep 选项标记为不可删除。它直接或间接地由图像中保留的输入部分的非弱引用引用。其名称与输入截面符号所引用的名称匹配并且该符号引用自图像中保留的截面。 注意 编译器通常将函数和数据收集在一起并为每个类别发出一个部分。链接器只能删除完全未使用的部分。 您可以使用 __attribute__used 属性标记源代码中的函数或变量。此属性使 armclang 为每个函数或变量生成符号 __tagsym$$used.num其中 num 是用于区分每个符号的计数器。消除未使用的部分不会删除包含 __tagsym$$used.num 的部分。 您还可以使用 armclang 选项 -ffunction-sections 来指示编译器为源文件中的每个函数生成一个 ELF 部分。 使用 RW 数据压缩进行优化
RW 数据区通常包含大量重复值如零这使得它们适合压缩。
默认情况下RW 数据压缩处于启用状态以最小化 ROM 大小。
链接器压缩数据。然后在运行时在目标上解压缩此数据。
Arm 库包含一些解压缩算法链接器选择要添加到映像的最佳算法以便在执行映像时解压缩数据区域。可以重写链接器选择的算法。
链接器如何选择压缩器
Armlink 在选择最合适的压缩算法以生成最小图像之前收集有关数据部分内容的信息。
如果压缩合适armlink 只能对图像中的所有可压缩数据部分使用一个数据压缩器。可以在这些部分上尝试不同的压缩算法以生成最佳的整体大小。如果出现以下情况将自动应用压缩 Compressed data size Size of decompressor Uncompressed data size
选择压缩器后armlink 会将解压缩器添加到映像的代码区域。如果最终映像不包含任何压缩数据则不会添加解压缩程序。
可用于替代链接器使用的压缩算法的选项
链接器具有用于禁用压缩或指定要使用的压缩算法的选项。
可以通过以下任一方式替代链接器使用的压缩算法
使用 --datacompressor off 选项关闭压缩。指定压缩算法。
若要指定压缩算法请在链接器命令行上使用所需压缩器的编号例如 armlink --datacompressor 2 ...
使用命令行选项 --datacompressor list 获取链接器中可用的压缩算法列表 armlink --datacompressor list
...
Num Compression algorithm0 Run-length encoding
1 Run-length encoding, with LZ77 on small-repeats
2 Complex LZ77 compression
选择压缩算法时请注意
Compressor 0 在具有大量零字节但非零字节较少的数据上表现良好。Compressor 1 在处理非零字节重复的数据时表现良好。Compressor 2 在处理包含重复值的数据时表现良好。
链接器首选压缩器 0 或 1其中数据主要包含零字节 75%。选择 Compressor 2 时数据包含很少的零字节 10%。如果图像仅由 A32 代码组成则会自动使用 A32 解压缩器。如果映像包含任何 T32 代码则使用 T32 解压缩器。如果没有明确的偏好则对所有压缩机进行测试以产生最佳的整体尺寸。 使用 RW 数据压缩时的注意事项
使用 RW 数据压缩时需要注意一些注意事项。
使用 RW 数据压缩时
使用链接器选项 --map 查看对代码中的区域应用压缩的位置。如果存在从压缩区域到使用加载地址的链接器定义符号的引用则链接器将关闭 RW 压缩。如果您使用的是带有片上缓存的 Arm® 处理器请在解压缩后启用缓存以避免出现代码一致性问题。
压缩数据段在运行时自动解压缩前提是使用 Arm 库中的代码执行__main。此代码必须放置在根区域中。最好在散点文件中使用 InRoot$$Sections 来完成此操作。
如果使用的是散点文件则可以通过添加 NOCOMPRESS 属性来指定不压缩加载或执行区域。
与链接器内联的函数
链接器内联功能取决于您指定的选项和输入文件的内容。
链接器可以内联小函数来代替该函数的分支指令。要使链接器能够执行此操作函数没有返回指令必须适合分支指令的四个字节。
使用 --inline 和 --no_inline 命令行选项来控制分支内联。但是--no_inline 仅关闭用户提供的对象的内联。默认情况下链接器仍内联 Arm 标准库中的函数。
如果启用了分支内联优化则链接器会扫描映像中的每个函数调用然后根据需要进行内联。当链接器找到合适的函数进行内联时它会将函数调用替换为正在调用的函数中的指令。
链接器在消除任何未使用的部分之前应用分支内联优化以便在不再调用内联部分时也可以将其删除。 注意 对于 Arm®v7-A链接器可以内联两个 16 位编码的 Thumb 指令以代替 32 位编码的 Thumb® BL 指令。对于 Armv8-A 和 Armv8-M链接器可以内联两个 16 位 T32 指令来代替 32 位 T32 BL 指令。 使用 --infoinline 命令行选项列出所有内联函数。
关于优化到 NOP 的分支
尽管链接器可以将分支替换为 NOP但在某些情况下您可能希望阻止这种情况发生。
默认情况下链接器将任何分支替换为重新定位该重定位将解析为具有 NOP 指令的下一条指令。如果链接器对尾部调用部分重新排序也可以应用此优化。
但是在某些情况下您可能希望禁用该选项例如在执行验证或管道刷新时。
要控制此优化请使用 --branchnop 和 --no_branchnop 命令行选项。
尾部调用部分的链接器重新排序
在某些情况下您可能希望链接器对尾部调用部分重新排序。
尾部调用部分是在该部分末尾包含分支指令的部分。如果分支指令具有以另一个部分开头的函数为目标的重定位则链接器可以将尾部调用部分放在被调用部分之前。然后链接器可以将尾部调用部分末尾的分支指令优化为 NOP 指令。
若要利用此行为请使用命令行选项 --tailreorder 将尾部调用部分移动到其目标之前。
使用 --infotailreorder 命令行选项可显示有关链接器执行的任何尾调用优化的信息。
对尾部调用部分重新排序的限制
尾部调用部分的重新排序有一些限制。
链接器
对于每个尾部调用目标只能移动一个尾部调用部分。如果对单个部分有多个尾部调用则具有相同部分名称的尾部调用部分将移动到目标之前。如果在具有匹配名称的尾部调用部分中找不到部分名称则链接器将移动它遇到的第一个部分。无法将尾部调用部分移出其执行区域。在内联贴面之前不移动尾部。
合并相同的常量 链接器可以尝试合并以 AArch32 状态为目标的对象中的相同常量。必须使用 Arm® Compiler for Embedded 6 生成对象。如果使用 armclang -ffunction-sections 选项进行编译则合并效率更高。此选项是默认选项。 关于此任务 以下过程是显示合并功能的示例。 注意 如果使用散点文件则任何标有 OVERLAY 或 PROTECTED 属性的区域都会影响 armlink --merge_litpools 选项的行为。 程序 创建一个 C 源文件 litpool.c其中包含以下代码 int f1() {return 0xdeadbeef;
}
int f2() {return 0xdeadbeef;
} 使用 -S 编译源代码以创建汇编文件 armclang -c -S -target arm-arm-none-eabi -mcpucortex-m0 -ffunction-sections \litpool.c -o litpool.s 注意 -ffunction-sections 是默认值。 由于0xdeadbeef是一个难以使用指令创建的常量因此会创建一个文本池例如 ...
f1:.fnstartBB#0:ldr r0, __arm_cp.0_0bx lr.p2align 2BB#1:
__arm_cp.0_0:.long 3735928559 0xdeadbeef
....fnend....code 16 f2.thumb_func
f2:.fnstartBB#0:ldr r0, __arm_cp.1_0bx lr.p2align 2BB#1:
__arm_cp.1_0:.long 3735928559 0xdeadbeef
....fnend
... 注意 每个函数都有一个常量副本因为 armclang 不能在两个函数之间共享这些常量。 编译源代码以创建对象 armclang -c -target arm-arm-none-eabi -mcpucortex-m0 litpool.c -o litpool.o 使用 --merge_litpools 选项链接目标文件 armlink --cpuCortex-M0 --merge_litpools litpool.o -o litpool.axf 注意 --merge_litpools 是默认值。 运行 fromelf 查看镜像结构 fromelf -c -d -s -t -v -z litpool.axf 以下示例显示了合并的结果 ...f10x00008000: 4801 .H LDR r0,[pc,#4] ; [0x8008] 0xdeadbeef0x00008002: 4770 pG BX lrf20x00008004: 4800 .H LDR r0,[pc,#0] ; [0x8008] 0xdeadbeef0x00008006: 4770 pG BX lr$d.4__arm_cp.1_00x00008008: deadbeef .... DCD 3735928559
...