C编译器是否重复(合并)代码?

ide*_*n42 14 c optimization compilation

循环展开是一种常见的优化,但反过来也是如此?
(减小目标文件输出的大小,更小的二进制).

我很好奇,如果编译器将连续的,相同的代码块(或函数调用)重复数据删除到循环中,或者将重复的块提取到静态函数中,这是一种常见的技术.

我很感兴趣,因为*C中只有一些头文件库可以添加大量重复代码,所以知道一些C编译器是否能够检测到这一点并更有效地处理它会很有用.

* 通过header-only-library,我的意思是直接定义代码而不是函数定义的头.

如果这样做,那么知道在什么条件和约束下适用以确保可以使用它将是有用的.

注意(出于问题的目的 - 任何流行的C编译器都是精细的GCC/Clang/Intel/MSVC).

我找到的一个只有头文件的库叫uthash使用了一些非常大的宏,我想知道是否有一些编译器技巧可以巧妙地去除这些巨大的代码块,参见:例如uthash.h,另一个类似的示例是内联qsort.h


可以重复数据删除的块的示例(事实证明它Py_DECREF可以扩展为相当大的代码块).

#define PY_ADD_TO_DICT(dict, i)  \
    do {
        PyDict_SetItemString(dict, names[i], item = PyUnicode_FromString(values[i])); \
        Py_DECREF(item); \
    } while (0)

/* this could be made into a loop */
PY_ADD_TO_DICT(d, 0);
PY_ADD_TO_DICT(d, 1);
PY_ADD_TO_DICT(d, 2);
PY_ADD_TO_DICT(d, 3);
Run Code Online (Sandbox Code Playgroud)

请注意,这是设计的,但基于一个真实的例子.


澄清

似乎我的问题的简短答案是否定的(或仅在某些有限/微不足道的情况下),只是为了澄清我为什么要求进一步提问.

评论中的一些回复似乎假设任何人只需将代码重构为函数.当然,
几乎总是最好的选择,但有时会出现非常相似的代码块.

  • 锅炉板代码由一个非常非常智能的代码生成器创建.
  • 当使用外部API将其某些功能公开为宏时(在这种情况下,在函数中本地包装当然在大多数情况下工作,但这意味着你的代码有自己的怪癖,这对于那些API的使用来说并不常见).
  • 当你不能用函数替换宏时,有一些罕见的情况,它最终是不切实际的.
  • 当从外部代码库导入代码时,进入并开始清理代码并不总是理想的,在评估代码库时,了解编译器在优化代码时会有多聪明.

在所有这些情况下,它可以去重复(生成更智能的代码,在函数中包装宏,修补第三方库),但在努力做这些事情之前,值得知道编译器为我们做了多少工作.

Thr*_*986 13

根据工具链的不同,您可以选择指导编译器和链接器识别和合并冗余代码.一些好的谷歌关键字包括:

请注意,之前评论中提到的gcc优化页面提供了一些感兴趣的标记,即:

  • -ftree尾合并
  • -ftree开关转换
  • -fgcse
  • -fcrossjumping
  • -fipa-PTA
  • -fipa-icf (相同的代码折叠),在GCC5.x中添加
  • -fopa-CP
  • -flto
  • -fwhole程序

最后,这些博客文章提供了丰富的信息:


Clo*_*oud 5

最简单的描述方法可称为重构代码.这是你可以作为开发人员手工完成的事情,但这不是现代C编译器和优化器的特性,至少就GCC而言是这样.下面列出了您可以在GCC中设置的所有单个优化(例如,分别通过-O0-O2分别),并且它们都没有重构一系列类似的语句以在循环中使用公共索引.

 Optimization Level Zero              Optimization Level Two
 ============================================================================================================
 -fauto-inc-dec                       -fthread-jumps 
 -fbranch-count-reg                   -falign-functions  -falign-jumps 
 -fcombine-stack-adjustments          -falign-loops  -falign-labels 
 -fcompare-elim                       -fcaller-saves 
 -fcprop-registers                    -fcrossjumping 
 -fdce                                -fcse-follow-jumps  -fcse-skip-blocks 
 -fdefer-pop                          -fdelete-null-pointer-checks 
 -fdelayed-branch                     -fdevirtualize -fdevirtualize-speculatively 
 -fdse                                -fexpensive-optimizations 
 -fforward-propagate                  -fgcse  -fgcse-lm  
 -fguess-branch-probability           -fhoist-adjacent-loads 
 -fif-conversion2                     -finline-small-functions 
 -fif-conversion                      -findirect-inlining 
 -finline-functions-called-once       -fipa-cp 
 -fipa-pure-const                     -fipa-sra 
 -fipa-profile                        -fisolate-erroneous-paths-dereference 
 -fipa-reference                      -foptimize-sibling-calls 
 -fmerge-constants                    -foptimize-strlen 
 -fmove-loop-invariants               -fpartial-inlining 
 -fshrink-wrap                        -fpeephole2 
 -fsplit-wide-types                   -freorder-blocks -freorder-blocks-and-partition -freorder-functions 
 -ftree-bit-ccp                       -frerun-cse-after-loop  
 -ftree-ccp                           -fsched-interblock  -fsched-spec 
 -fssa-phiopt                         -fschedule-insns  -fschedule-insns2 
 -ftree-ch                            -fstrict-aliasing -fstrict-overflow 
 -ftree-copy-prop                     -ftree-builtin-call-dce 
 -ftree-copyrename                    -ftree-switch-conversion -ftree-tail-merge 
 -ftree-dce                           -ftree-pre 
 -ftree-dominator-opts                -ftree-vrp 
 -ftree-dse                           -fuse-caller-save
 -ftree-forwprop                
 -ftree-fre                     
 -ftree-phiprop                 
 -ftree-sink                    
 -ftree-slsr                    
 -ftree-sra                     
 -ftree-pta                     
 -ftree-ter                     
 -funit-at-a-time               
Run Code Online (Sandbox Code Playgroud)

参考


  1. 3.10 - 控制优化的选项,访问日期2014-07-07,<https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html>