├── .gitignore ├── gcc-passes.sh ├── Makefile ├── README.md └── passes.cc /.gitignore: -------------------------------------------------------------------------------- 1 | passes.o 2 | passes.so 3 | -------------------------------------------------------------------------------- /gcc-passes.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | #set -x 3 | 4 | plugindir=$PWD 5 | 6 | declare -a flags=(0 g 1 s 2 3 fast) 7 | check_flag() { 8 | local fl="$1" 9 | declare -i i 10 | for i in $(seq 0 $((${#flags[*]} - 1))); do 11 | if [ "$fl" == ${flags[$i]} ]; then 12 | return 13 | fi 14 | done 15 | printf "Error: Unknown flag %s\n" "$fl" 16 | exit 1 17 | } 18 | 19 | run() { 20 | local o="$1" 21 | echo 'void f(void) {}' | 22 | g++ -fplugin=${plugindir}/passes.so -x c++ -S -o /dev/null -O$o - 2>&1 23 | } 24 | 25 | if [ ${#*} -eq 1 ]; then 26 | o="$1" 27 | check_flag "$o" 28 | run "$o" 29 | elif [ ${#*} -eq 2 ]; then 30 | l="$1" 31 | r="$2" 32 | check_flag "$1" 33 | check_flag "$2" 34 | colordiff -y -W 80 <(run "$l") <(run "$r") 35 | else 36 | printf "Usage: %s []\n" "$0" 37 | (IFS=,; printf " where OPT ∈ {${flags[*]})\n") 38 | exit 1 39 | fi 40 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | VERSION = 0.0 2 | 3 | CXX = g++ -std=gnu++2a $(COLOR) 4 | 5 | CXXFLAGS = $(OPT) $(DEBUG) 6 | OPT = -Og 7 | DEBUG = -g 8 | PLUGINDIR = $(shell $(CXX) -print-file-name=plugin) 9 | INCLUDES = -I$(PLUGINDIR)/include 10 | DEFINES = -DVERSION=\"$(VERSION)\" 11 | WARN = -Wall 12 | #LTO = -flto 13 | COLOR = -fdiagnostics-color=auto 14 | 15 | LDFLAGS = $(LTO) 16 | LIBS = 17 | 18 | ALL = passes 19 | ALLBIN = $(addsuffix .so,$(ALL)) 20 | 21 | passes_SRCS = passes.cc 22 | passes_OBJS = $(passes_SRCS:.cc=.o) 23 | 24 | .PHONY: all clean check 25 | all: $(ALLBIN) 26 | 27 | .cc.o: 28 | $(CXX) $(CXXFLAGS) $(LTO) $(DEFINES) $(WARN) $(INCLUDES) -c -fPIC -fno-rtti -o $@ $< 29 | 30 | define SORULE 31 | $(1).so: $$($(1)_OBJS) 32 | $(CXX) -shared -o $$@ $$(LDFLAGS) $$^ $$(LIBS) 33 | endef 34 | 35 | $(foreach o,$(ALL),$(eval $(call SORULE,$o))) 36 | 37 | clean: 38 | -rm -f $(ALLBIN) $(foreach a,$(ALL),$($(a)_OBJS)) 39 | 40 | check: all 41 | $(CXX) -fplugin=$$PWD/passes.so -c test1.cc 42 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Discover GCC Optimization Passes 2 | ================================ 3 | 4 | This project is a script which, in conjunction with the included GCC plugin, 5 | allows to discover which optimization passes GCC executes for which optimization 6 | level. All the levels of `-O` are supported (`0`, `g`, `1`, `s`, `2`, `3`, `fast`). 7 | 8 | When the script is called with one of the levels as the command line argument it 9 | shows all the passes by name, nested according to the part of the compiler they 10 | belong too. 11 | 12 | When the script is given two parameters the passes used in the invocations 13 | according to the two optimization levels are compared and differences highlighted. 14 | 15 | As an example see the beginning of the output of the following command: 16 | 17 | $ ./gcc-passes.sh 0 18 | GIMPLE pass: 19 | pass *warn_unused_result 20 | pass omplower 21 | pass lower 22 | pass ehopt 23 | pass eh 24 | pass cfg 25 | pass *warn_function_return 26 | pass ompexp 27 | pass *build_cgraph_edges 28 | simple IPA pass: 29 | pass *free_lang_data 30 | pass visibility 31 | pass build_ssa_passes 32 | GIMPLE pass: 33 | pass fixup_cfg 34 | pass ssa 35 | pass *rebuild_cgraph_edges 36 | simple IPA pass: 37 | pass opt_local_passes 38 | GIMPLE pass: 39 | pass fixup_cfg 40 | pass *rebuild_cgraph_edges 41 | pass local-fnsummary 42 | pass einline 43 | 44 | This output shows the different types of passes (GIMPLE, IPA, …). This might vary 45 | from compiler version to version. What this also shows that even with `-O0` some 46 | optimization passes are executed. 47 | 48 | 49 | Author: Ulrich Drepper 50 | 51 | -------------------------------------------------------------------------------- /passes.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "config.h" 5 | #include "system.h" 6 | #include "coretypes.h" 7 | #include "tree.h" 8 | #include //name-lookup.h> 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | // Required symbol. 15 | int plugin_is_GPL_compatible; 16 | 17 | 18 | namespace { 19 | 20 | plugin_info my_plugin_info = { 21 | VERSION, 22 | "passes plugin" 23 | }; 24 | 25 | 26 | int last_pass_type = -1; 27 | std::unordered_map levels; 28 | 29 | 30 | void record_hierarchy(opt_pass* pass, int level = 0) 31 | { 32 | levels[pass] = level; 33 | if (pass->sub != nullptr) 34 | record_hierarchy(pass->sub, level + 1); 35 | if (pass->next != nullptr) 36 | record_hierarchy(pass->next, level); 37 | } 38 | 39 | 40 | void pass_execution_cb(void *gcc_data, void *user_data) 41 | { 42 | opt_pass* pass = (opt_pass*) gcc_data; 43 | 44 | if (levels.find(pass) == levels.end()) 45 | record_hierarchy(pass); 46 | 47 | if (last_pass_type != pass->type) { 48 | switch (pass->type) { 49 | case GIMPLE_PASS: 50 | std::cerr << "GIMPLE pass:\n"; 51 | break; 52 | case RTL_PASS: 53 | std::cerr << "RTL pass:\n"; 54 | break; 55 | case SIMPLE_IPA_PASS: 56 | std::cerr << "simple IPA pass:\n"; 57 | break; 58 | case IPA_PASS: 59 | std::cerr << "IPA pass:\n"; 60 | break; 61 | } 62 | last_pass_type = pass->type; 63 | } 64 | 65 | std::cout << " pass "; 66 | for (int i = 0; i < levels[pass]; ++i) 67 | std::cout << " "; 68 | std::cout << pass->name << std::endl; 69 | } 70 | 71 | 72 | } // anonymous namespace 73 | 74 | 75 | int plugin_init(struct plugin_name_args *plugin_info, struct plugin_gcc_version *version) 76 | { 77 | if (! plugin_default_version_check(version, &gcc_version)) 78 | return 1; 79 | 80 | register_callback(plugin_info->base_name, PLUGIN_INFO, nullptr, &my_plugin_info); 81 | 82 | // Register all the callback functions. 83 | register_callback(plugin_info->base_name, PLUGIN_PASS_EXECUTION, pass_execution_cb, nullptr); 84 | 85 | // Add more here if necessary. 86 | 87 | return 0; 88 | } 89 | --------------------------------------------------------------------------------