前言

  GCC中包含了从-O0到-O3以及-Og,-Os和-Ofast各种级别的优化,并提供了上百多个可独立控制的优化标志。每个优化级别都启用了优化标志的子集,并在启用调试信息生成对可执行代码没有任何影响。但是确定何时运行pass是一个复杂的过程,每一个pass都有一个门函数(gate function), 它根据优化级别和标志来决定是否运行该pass。
  GCC中如何添加一个优化pass的操作,可以参考《GCC - GIMPLE IR 学习一》。如何通过优化选项控制我新添加的优化pass?在回答这个问题之前,我们需要先了解GCC中优化选项相关的一些知识,GCC中除了各种级别中包含的选项,还有一部分是通过选项独立控制它是否执行的,查看每个-O级别上包含的优化选项可以使用gcc -O3 -Q --help=optimizers命令查看。通过独立控制的选项可以通过fdump-tree-选项简称来查看,例如,查看-ftree-loop-distribution选项pass信息,使用gcc -O3 test.c -ftree-loop-distribution -fdump-tree-ldist命令,查看-prefetch-loop-arrays选项的pass信息,使用gcc -O3 test.c -fprefetch-loop-arrays -fdump-tree-aprefetch命令。也可使用-fdump-tree-all-fdump-rtl-all或者-fdump-ipa-all打印出所有中间运行信息。

1. GCC8.2.0 中重要的pass文件

1. opts.c文件

  在gcc/opts.c文件中主要进行一些默认选项的分配管理以及完成后的处理等操作。其中的default_options_table数组会根据优化级别设置启用标志,如添加-O级别上的选项可按照其中已有的选项要求就行添加,并在相关函数中配置其flag。default_options_table数组内容如下:

static const struct default_options default_options_table[] ={/* -O1 optimizations.  */{ OPT_LEVELS_1_PLUS, OPT_fdefer_pop, NULL, 1 },
#if DELAY_SLOTS{ OPT_LEVELS_1_PLUS, OPT_fdelayed_branch, NULL, 1 },
#endif{ OPT_LEVELS_1_PLUS, OPT_fguess_branch_probability, NULL, 1 },{ OPT_LEVELS_1_PLUS, OPT_fcprop_registers, NULL, 1 },{ OPT_LEVELS_1_PLUS, OPT_fforward_propagate, NULL, 1 },{ OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_fif_conversion, NULL, 1 },{ OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_fif_conversion2, NULL, 1 },{ OPT_LEVELS_1_PLUS, OPT_fipa_pure_const, NULL, 1 },{ OPT_LEVELS_1_PLUS, OPT_fipa_reference, NULL, 1 },{ OPT_LEVELS_1_PLUS, OPT_fipa_profile, NULL, 1 },{ OPT_LEVELS_1_PLUS, OPT_fmerge_constants, NULL, 1 },{ OPT_LEVELS_1_PLUS, OPT_freorder_blocks, NULL, 1 },{ OPT_LEVELS_1_PLUS, OPT_fshrink_wrap, NULL, 1 },{ OPT_LEVELS_1_PLUS, OPT_fsplit_wide_types, NULL, 1 },{ OPT_LEVELS_1_PLUS, OPT_ftree_ccp, NULL, 1 },{ OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_ftree_bit_ccp, NULL, 1 },{ OPT_LEVELS_1_PLUS, OPT_ftree_coalesce_vars, NULL, 1 },{ OPT_LEVELS_1_PLUS, OPT_ftree_dce, NULL, 1 },{ OPT_LEVELS_1_PLUS, OPT_ftree_dominator_opts, NULL, 1 },{ OPT_LEVELS_1_PLUS, OPT_ftree_dse, NULL, 1 },{ OPT_LEVELS_1_PLUS, OPT_ftree_ter, NULL, 1 },{ OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_ftree_sra, NULL, 1 },{ OPT_LEVELS_1_PLUS, OPT_ftree_fre, NULL, 1 },{ OPT_LEVELS_1_PLUS, OPT_ftree_copy_prop, NULL, 1 },{ OPT_LEVELS_1_PLUS, OPT_ftree_sink, NULL, 1 },{ OPT_LEVELS_1_PLUS, OPT_ftree_ch, NULL, 1 },{ OPT_LEVELS_1_PLUS, OPT_fcombine_stack_adjustments, NULL, 1 },{ OPT_LEVELS_1_PLUS, OPT_fcompare_elim, NULL, 1 },{ OPT_LEVELS_1_PLUS, OPT_ftree_slsr, NULL, 1 },{ OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_fbranch_count_reg, NULL, 1 },{ OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_fmove_loop_invariants, NULL, 1 },{ OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_ftree_pta, NULL, 1 },{ OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_fssa_phiopt, NULL, 1 },{ OPT_LEVELS_1_PLUS, OPT_ftree_builtin_call_dce, NULL, 1 },{ OPT_LEVELS_1_PLUS, OPT_fomit_frame_pointer, NULL, 1 },/* -O2 optimizations.  */{ OPT_LEVELS_2_PLUS, OPT_finline_small_functions, NULL, 1 },{ OPT_LEVELS_2_PLUS, OPT_findirect_inlining, NULL, 1 },{ OPT_LEVELS_2_PLUS, OPT_fpartial_inlining, NULL, 1 },{ OPT_LEVELS_2_PLUS, OPT_fthread_jumps, NULL, 1 },{ OPT_LEVELS_2_PLUS, OPT_fcrossjumping, NULL, 1 },{ OPT_LEVELS_2_PLUS, OPT_foptimize_sibling_calls, NULL, 1 },{ OPT_LEVELS_2_PLUS, OPT_fcse_follow_jumps, NULL, 1 },{ OPT_LEVELS_2_PLUS, OPT_fgcse, NULL, 1 },{ OPT_LEVELS_2_PLUS, OPT_fexpensive_optimizations, NULL, 1 },{ OPT_LEVELS_2_PLUS, OPT_frerun_cse_after_loop, NULL, 1 },{ OPT_LEVELS_2_PLUS, OPT_fcaller_saves, NULL, 1 },{ OPT_LEVELS_2_PLUS, OPT_fpeephole2, NULL, 1 },
#ifdef INSN_SCHEDULING/* Only run the pre-regalloc scheduling pass if optimizing for speed.  */{ OPT_LEVELS_2_PLUS_SPEED_ONLY, OPT_fschedule_insns, NULL, 1 },{ OPT_LEVELS_2_PLUS, OPT_fschedule_insns2, NULL, 1 },
#endif{ OPT_LEVELS_2_PLUS, OPT_fstrict_aliasing, NULL, 1 },{ OPT_LEVELS_2_PLUS_SPEED_ONLY, OPT_freorder_blocks_algorithm_, NULL,REORDER_BLOCKS_ALGORITHM_STC },{ OPT_LEVELS_2_PLUS, OPT_freorder_functions, NULL, 1 },{ OPT_LEVELS_2_PLUS, OPT_ftree_vrp, NULL, 1 },{ OPT_LEVELS_2_PLUS, OPT_fcode_hoisting, NULL, 1 },{ OPT_LEVELS_2_PLUS, OPT_ftree_pre, NULL, 1 },{ OPT_LEVELS_2_PLUS, OPT_ftree_switch_conversion, NULL, 1 },{ OPT_LEVELS_2_PLUS, OPT_fipa_cp, NULL, 1 },{ OPT_LEVELS_2_PLUS, OPT_fipa_bit_cp, NULL, 1 },{ OPT_LEVELS_2_PLUS, OPT_fipa_vrp, NULL, 1 },{ OPT_LEVELS_2_PLUS, OPT_fdevirtualize, NULL, 1 },{ OPT_LEVELS_2_PLUS, OPT_fdevirtualize_speculatively, NULL, 1 },{ OPT_LEVELS_2_PLUS, OPT_fipa_sra, NULL, 1 },{ OPT_LEVELS_2_PLUS, OPT_falign_loops, NULL, 1 },{ OPT_LEVELS_2_PLUS, OPT_falign_jumps, NULL, 1 },{ OPT_LEVELS_2_PLUS, OPT_falign_labels, NULL, 1 },{ OPT_LEVELS_2_PLUS, OPT_falign_functions, NULL, 1 },{ OPT_LEVELS_2_PLUS, OPT_ftree_tail_merge, NULL, 1 },{ OPT_LEVELS_2_PLUS, OPT_fvect_cost_model_, NULL, VECT_COST_MODEL_CHEAP },{ OPT_LEVELS_2_PLUS_SPEED_ONLY, OPT_foptimize_strlen, NULL, 1 },{ OPT_LEVELS_2_PLUS, OPT_fhoist_adjacent_loads, NULL, 1 },{ OPT_LEVELS_2_PLUS, OPT_fipa_icf, NULL, 1 },{ OPT_LEVELS_2_PLUS, OPT_fisolate_erroneous_paths_dereference, NULL, 1 },{ OPT_LEVELS_2_PLUS, OPT_fipa_ra, NULL, 1 },{ OPT_LEVELS_2_PLUS, OPT_flra_remat, NULL, 1 },{ OPT_LEVELS_2_PLUS, OPT_fstore_merging, NULL, 1 },/* -O3 optimizations.  */{ OPT_LEVELS_3_PLUS, OPT_ftree_loop_distribute_patterns, NULL, 1 },{ OPT_LEVELS_3_PLUS, OPT_ftree_loop_distribution, NULL, 1 },{ OPT_LEVELS_3_PLUS, OPT_floop_interchange, NULL, 1 },{ OPT_LEVELS_3_PLUS, OPT_fpredictive_commoning, NULL, 1 },{ OPT_LEVELS_3_PLUS, OPT_fsplit_paths, NULL, 1 },/* Inlining of functions reducing size is a good idea with -Osregardless of them being declared inline.  */{ OPT_LEVELS_3_PLUS_AND_SIZE, OPT_finline_functions, NULL, 1 },{ OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_finline_functions_called_once, NULL, 1 },{ OPT_LEVELS_3_PLUS, OPT_fsplit_loops, NULL, 1 },{ OPT_LEVELS_3_PLUS, OPT_funswitch_loops, NULL, 1 },{ OPT_LEVELS_3_PLUS, OPT_floop_unroll_and_jam, NULL, 1 },{ OPT_LEVELS_3_PLUS, OPT_fgcse_after_reload, NULL, 1 },{ OPT_LEVELS_3_PLUS, OPT_ftree_loop_vectorize, NULL, 1 },{ OPT_LEVELS_3_PLUS, OPT_ftree_slp_vectorize, NULL, 1 },{ OPT_LEVELS_3_PLUS, OPT_fvect_cost_model_, NULL, VECT_COST_MODEL_DYNAMIC },{ OPT_LEVELS_3_PLUS, OPT_fipa_cp_clone, NULL, 1 },{ OPT_LEVELS_3_PLUS, OPT_ftree_partial_pre, NULL, 1 },{ OPT_LEVELS_3_PLUS, OPT_fpeel_loops, NULL, 1 },/* -Ofast adds optimizations to -O3.  */{ OPT_LEVELS_FAST, OPT_ffast_math, NULL, 1 },{ OPT_LEVELS_NONE, 0, NULL, 0 }};

  但是某些标志默认情况下是通过其初始化程序启用的,例如 gcc/common.opt,根据其他条件,有些也被强制启用或禁用。也就是说一个pass的启用或关闭是由众多条件构成的,只有满足这些条件,这个pass才会被执行。

2. common.opt文件

  这个文件描述了所有公共的命令行选项和内部标志,这里面包含pass启用或关闭的执行条件以及所有选项的名称。也就是说这个文件是定义优化选项名称的地方,对于一些需要flag的选项,其flag标记值也在此文件中定义和初始化。
文件变量定义部分内容如下:

文件中选项声明部分内容如下:

3. toplev.c文件

  这是cc1的顶层文件,它解析命令args,打开文件以正确的顺序调用各种过程,并计算每个过程所用的时间。错误消息和malloc的低级接口也在这里处理。其中process_options函数用来处理已解析的选项,选项执行的前提条件在此通过flag设置,以fprefetch-loop-arrays选项在此文件中的判断条件为例,其内容如下:

4. passes.def文件

  GCC编译过程中的所有优化pass的执行顺序在passes.def中描述,但具体每一个pass是关闭还是启用,gcc会根据标记在passes.c文件中判断。passes.def中选项执行顺序的描述如下所示:

5. tree-pass.h文件

  该文件主要包含GIMPLE_PASS、RTL_PASS、SIMPLE_IPA_PASS、IPA_PASS四类优化pass的定义和具体参数描述,和pass的元数据(pass_data)定义和描述,以及所有pass的注册管理操作。
  注册新的pass,需要填写register_pass_info或指定各个参数。通过操作符new 来分配pass对象,并且通过pass manager来获取pass对象的所有权。我们新建pass时只需要按照如下信息注册便可:

2. 其它相关pass文件

  opts-global.c中在启动时初始化与全局选项相关的设置。解析命令行选项并设置默认标志值,并进行最少的选项处理等操作。
  passes.c中通过enable_pass或disable_pass函数启用或关闭arg指定的pass,还包括dump pass以及很多用于pass debuging相关实现的操作。

3. 选项控制pass操作

  讲完前面铺垫,到此正式进入正题,如何通过选项控制pass,主要分为以下三步:

1. 定义pass中的gate函数执行条件

  我们新建的pass中包含的pass_data,其结构主要包含的信息如下:

  • type:pass属于四种pass中的哪一种。
  • name:pass的简短名称,用作dump file时打印出来的名称,例如:使用fdump-tree-all打印出来的aprefetch名称结尾的文件代表fprefet-loop-arrays这个优化pass。
  • ptinfo_flags:控制选项所属的组别,取值包含:OPTGROUP_NONE、OPTGROUP_IPA、OPTGROUP_LOOP、OPTGROUP_INLINE、OPTGROUP_OMP、OPTGROUP_VEC、OPTGROUP_OTHER、OPTGROUP_ALL
  • tv_id:与该pass关联的timevar id。在timevar.def文件中描述。

  pass所在的class中有两个重要函数gateexecute,pass的执行条件由gate函数的参数控制,该函数默认返回true,flag标记可由自己控制。pass的执行内容在execute函数中执行。以aprefetchpass的源码文件tree-ssa-loop-prefetch.c为例,其内容如下:

2. 控制参数的定义和选项声明

  在common.opt文件中定义控制变量,flag_xxxx,并在Driver中声明优化选项,以及对选项做出描述。

3. 解析选项和命令参数

  在toplev.c文件中通过process_options函数解析命令参数,并在此添加选项执行的前提条件以及选项使用过程中的警告信息提示等。

  一句话概括以上操作便是:创建pass的时候,在gate函数中设置函数的执行条件,在tree-pass.h中注册pass,在common.opt和passes.def中添加pass和选项信息,toplev.c中设置flag参数,控制pass执行。

以上是我个人的一个非常粗浅的认识,如有不对的地方,欢迎大家指出!

GCC添加开关选项控制新建的gimple pass相关推荐

  1. gcc 自动识别的文件扩展名,gcc/g++ -x 选项指定语言,不同 gcc 版本 -std 编译选项支持列表

    对于执行 C 或者 C++ 程序,需要借助 gcc(g++)指令来调用 GCC 编译器. 对于以 .c 为扩展名的文件,GCC 会自动将其视为 C 源代码文件 对于以 .cpp 为扩展名的文件,GCC ...

  2. 使用gcc的-finstrument-functions选项进行函数跟踪

    GCC Function instrumentation机制可以用来跟踪函数的调用关系,在gcc中对应的选项为"-finstrument-functions".可查看gcc的man ...

  3. 计算机管理中添加用户属性,如何在计算机右键菜单栏中添加属性选项

    如何在计算机右键菜单栏中添加属性选项 电脑是现在最常用的工具之一,有些用户想知道如何在计算机右键菜单栏中添加属性选项,接下来小编小编就给大家介绍一下具体的操作步骤. 具体如下: 1. 首先第一步按下[ ...

  4. GCC编译警告选项的学习

    GCC有很多的编译选项,警告选项:指定头文件.库路径:优化选项.本文针整理一下GCC的警告选项,主要依据http://gcc.gnu.org/onlinedocs/gcc/Warning-Option ...

  5. Win10右键菜单“发送到”添加/删除选项的方法

    右键点击系统桌面上的文件或程序图标 - 发送到,我们可以看到发送到的二级菜单中,有重复的菜单:传真收件人,也有本机完全用不到的菜单,如:蓝牙设备等. Windows10右键菜单"发送到&qu ...

  6. make menuconfig 添加新选项

    如何在make menuconfig 界面添加新选项步骤: 1.先在Linux内核源码目录下创建个新目录(哪个位置都行,一般添加新驱动时,都会在 drivers目录下创建,这里为了实验的方便就在 源码 ...

  7. 给桌面右键菜单添加新选项

    以添加photoshop为例 ①打开phototshop的属性,获得其位置 ②打开注册表,计算机\HKEY_CLASSES_ROOT\Directory\Background\shell 在shell ...

  8. VR项目添加键盘鼠标控制

    VR项目添加键盘鼠标控制 使用VR模版创建的项目,程序运行后,只能使用VR头盔进行交互场景,不便于调试工作,为此,在场景中添加键盘.鼠标控制功能. 1 .键盘控制添加: 键盘控制主要为ASDW 键控制 ...

  9. 计算机导航窗口添加桌面,为Win7资源管理器导航添加桌面选项的方法

    为Win7资源管理器导航添加桌面选项的方法 有不少Win7用户在打开文件夹时,发现左侧的资源管理器导航面板里没有桌面选项,经常复制粘贴的朋友没办法一键回到桌面,还要一级一级向上返回,这为用户添加了不少 ...

最新文章

  1. JavaScript数据结构与算法——字典
  2. ES6新特性3:函数的扩展
  3. ImageNet训练再创纪录!谷歌提出1个小时训练EfficientNet,准确率高达83%!
  4. 关于Adapter对数据库的查询、删除操作
  5. SQL Server窗口函数:ROWS与RANGE
  6. mysql 定义唯一约束_在MySQL中,定义唯一约束的基本语法格式是【】
  7. python数组切片赋值_基于numpy中数组元素的切片复制方法
  8. 错误的参数个数或无效的参数属性值_数据处理-利用 python进行异常值分析
  9. 1.1集成电路设计基础
  10. c#样条曲线命令_C#基数样条曲线的模拟实现(对应Graphics的DrawCurve)
  11. 微信发红包-测试用例(全)
  12. ASP.NET Core免费(视频)教程汇总
  13. VR全景制作方法教程完整版
  14. nslookup查询域名系统服务器,域名解析系统DNS诊断命令nslookup详解
  15. 如何做好虾皮跨境电商?关于Shopee店铺快速开单的真相!
  16. Java网络编程——基本网络支持
  17. 比尔·盖茨的另一扇视窗
  18. 常用的arm汇编指令(3) -学无止尽,积土成山,积水成渊
  19. Mac电脑下载的google chrome无法使用解决方法?
  20. 中基鸿业分析投资应该注意的事项

热门文章

  1. Rancher首席架构师解读Fleet:它何以管理百万集群?
  2. pdm系统是归档服务器吗,PDM系统与档案管理系统集成方法研究
  3. Java部署本地项目到远端服务器(腾讯云轻量级服务器)
  4. 华为手机(鸿蒙OS)开启adb调试权限
  5. java中的replace用法_java中replace用法举例:replace(char oldChar, char newChar)返回一个新的字符串...
  6. 行列式的值你真的懂吗
  7. java微信开发-消息接收和自动回复
  8. 使用Docker实现容器化(一)——Docker基础的介绍与应用
  9. 如何运行python
  10. Idea的Marketplace打不开终极解决