在gcc 可以下

code
-fdump-rtl-all-all 

得到gcc 執行rtl pass的優化結果,其中目前我的平台是 x86 那唯一看到rtl tree有真正執行 並且變化的 pass有三個

code
combine
reload
cprop_hardreg

這是在pass中所呈現的rtl tree

code
(insn 31 30 32 5 (set (reg:DF 89 [ _8 ])
        (mem/u:DF (plus:DI (mult:DI (reg:DI 105)
                    (const_int 8 [0x8]))
                (symbol_ref:DI ("altitudeTable") [flags 0x2]  <var_decl 0x7f096528e120 altitudeTable>)) [1 altitudeTableD.3397[_7]+0 S8 A64])) "test.c":23:96 135 {*movdf_internal}
     (nil))
(insn 32 31 33 5 (set (reg:SI 107)
        (mem/c:SI (plus:DI (reg/f:DI 19 frame)
                (const_int -4 [0xfffffffffffffffc])) [2 iD.3409+0 S4 A32])) "test.c":23:119 75 {*movsi_internal}
     (nil))
(insn 33 32 34 5 (set (reg:DI 106)
        (sign_extend:DI (reg:SI 107))) "test.c":23:119 147 {*extendsidi2_rex64}
     (nil))
(insn 34 33 35 5 (set (reg:DF 90 [ _9 ])
        (mem/u:DF (plus:DI (mult:DI (reg:DI 106)
                    (const_int 8 [0x8]))
                (symbol_ref:DI ("altitudeTable") [flags 0x2]  <var_decl 0x7f096528e120 altitudeTable>)) [1 altitudeTableD.3397[i_15]+0 S8 A64])) "test.c":23:119 135 {*movdf_internal}
     (nil))

為了找出可以間接合成的指令,來寫一個pass 改良以前寫的修改gcc unroll pass的部分

code
int plugin_init(struct plugin_name_args *plugin_info, struct plugin_gcc_version *version)
{

if (!plugin_default_version_check(version, &gcc_version))
{
printf("incompatible gcc/plugin versions\n");
return 1;
}

fprintf(stderr, "%s %s %s\n", plugin_info->full_name, version->basever, version->devphase);

detect_passinfo.pass = make_pass_detect(g);
detect_passinfo.reference_pass_name = "combine";
detect_passinfo.ref_pass_instance_number = 0;
detect_passinfo.pos_op = PASS_POS_INSERT_AFTER;

inline_passinfo.pass=make_pass_detect2(g);
inline_passinfo.reference_pass_name="combine";
inline_passinfo.ref_pass_instance_number=0;
inline_passinfo.pos_op=PASS_POS_INSERT_BEFORE;

register_callback("static_analyzer", PLUGIN_PASS_MANAGER_SETUP, NULL, &detect_passinfo);
register_callback("exinline", PLUGIN_PASS_MANAGER_SETUP, NULL, &inline_passinfo);
return 0;
}

簡單的插入這個plugin 在 gcc 裡面,觀察pass前後rtl tree的變化, 根據function -> basic block -> rtx

code
fprintf(stderr, "\n===============Print ALL RTL IR BEFORE=================\n");
FOR_EACH_FUNCTION(node)
{
name = get_name(cfun->decl);

if (name != NULL)
{
fprintf(stderr, "=======Mapping node_fun:%s=========\n", name);
}
    .
calculate_dominance_info(CDI_DOMINATORS);
int count = 0;
FOR_EACH_BB_FN(bb, cfun)
{
rtx_insn *insn;
FOR_BB_INSNS(bb, insn)
if (NONDEBUG_INSN_P(insn))
{

rtx body = PATTERN(insn);
int code = INSN_CODE(insn);
fprintf(stderr, "\nbb index %d,rtl inst count %d\n", bb->index, count);
debug(insn);

expanded_location xloc = insn_location(insn);
fprintf(stderr, "source code : %s:%i\n", xloc.file, xloc.line);
count++;
}
}

pop_cfun();
}
fprintf(stderr, "\n===============Print ALL RTL IR BEFORE=================\n");

這是處理完的數據格式

code
=======Mapping node_fun:main=========

bb index 2,rtl inst count 0
(insn 8 7 9 2 (set (reg:DI 5 di)
  (symbol_ref/f:DI ("*.LC0") [flags 0x2]  <var_decl 0x7febd94a02d0 *.LC0>)) "test.c":65:5 74 {*movdi_internal}
 (nil))
source code : test.c:65
Opcode number of insn: 74
Opcode of insn: *movdi_internal
===== of insn: *cmpqi_1

bb index 2,rtl inst count 1
(insn 9 8 10 2 (set (reg:QI 0 ax)
  (const_int 0 [0])) "test.c":65:5 77 {*movqi_internal}
 (nil))
source code : test.c:65
Opcode number of insn: 77
Opcode of insn: *movqi_internal
===== of insn: *cmpqi_1

基本上已經是比較可讀的狀況,到這邊再觀察rtl的tree就可讀,如果需要找那些pattern可以根據這些訊息來建立一個table