FUNCTIONS TO GENERATE RTX

typical calling sequence to generate expression

c_expand_body()<c-decl.c>

expand_stmt()<c-semantics.c>

genrtl_expr_stmt_value()<c-semantics.c>

expand_expr_stmt_value()stmt.c>

expand_expr()expr.c>

crucial code of expand_expr:

rtx expand_expr (tree exp, …) {

enum tree_code code = TREE_CODE (exp);

optab this_optab;

switch (code) {

case MODIFY_EXPR:

tree lhs = TREE_OPERAND (exp, 0);

tree rhs = TREE_OPERAND (exp, 1);

expand_assignment (lhs, rhs, …); // <expr.c>

case PLUS_EXPR:

this_optab = …? addv_optab : add_optab;

goto binop2 或 both_summands;

both_summands:

gen_rtx_PLUS(…)

}

binop2:

expand_binop (mode, this_optab, op0, op1, …); // <optab.c>

}

calling sequence beyond gen_rtx_PLUS()

gen_rtx_PLUS() <genrtl.h>

gen_rtx_fmt_ee() <genrtl.c>

ggc_alloc_rtx()

genrtl.c, genrtl.h are generated by gengenrtl.exe

OPERATION TABLES

keypoint of mapping standard name (tree node) to define_insn (define_expand)

standard names are hard-coded in the compiler

Data Structure

optabs.h

struct optab

enum optab_index

#define add_optab (optab_table[OTI_add])

optabs.c

optab optab_table[OTI_MAX];

Initailization

main()<main.c>

toplev_main()<toplev.c>

do_compile()<toplev.c>

lang_dependent_init()<toplev.c>

init_optabs()<optabs.c>

init_optab()<optabs.c>

init_all_optabs()<insn_opinit.c>

init_optab() – construct structure

init_all_optabs() – fill data

machine-dependent

Example Rtx

(define_expand "addsi3"

[(parallel[(set(match_operand:SI 0 "nonimmediate_operand" "")

(plus:SI(match_operand:SI 1 "nonimmediate_operand" "")

(match_operand:SI 2 "general_operand" "")))

(clobber (reg:CC 17))])]

""

"ix86_expand_binary_operator (PLUS, SImode, operands); DONE;")

(define_insn "divqi3"

[(set(match_operand:QI 0 "register_operand" "=a")

(div:QI(match_operand:HI 1 "register_operand" "0")

(match_operand:QI 2 "nonimmediate_operand" "qm")))

(clobber (reg:CC 17))]

"TARGET_QIMODE_MATH"

"idiv{b}\t%2"

[(set_attr "type" "idiv")

(set_attr "mode" "QI")

(set_attr "ppro_uops" "few")])

Function init_all_optabs()

in <insn_opinit.c>

crucial code of init_all_optans:

add_optab->handlers[(int) SImode].insn_code = CODE_FOR_addsi3;

if (HAVE_divqi3)

sdiv_optab->handlers[(int) QImode].insn_code = CODE_FOR_divqi3;

CODE_FOR_xxx

in <insn-codes.h>

numbering for define_expand & named define_insn

index of insn_data[]

CODE_FOR_divqi3 = 187,

CODE_FOR_addsi3 = 933,

HAVE_xxx

in <insn-flaags.h>

according to 3rd argument of define_expand & named define_insn

#define HAVE_divqi3 (TARGET_QIMODE_MATH)

#define HAVE_addsi3 1

RTX GENERATION

ARRAY insn_data[] & operand_data[]

in <insn_output.c>

const struct insn_data insn_data[] = {// defined in <recog.h>

{ //\\ insn_data[187] <i386.md:7118>

"divqi3",// char *const name;

"idiv{b}\t%2",// PTR output; (useless for rtx-gen)

(insn_gen_fn) gen_divqi3,// insn_gen_fn genfun;

&operand_data[378],// struct insn_operand_data *operand;

3,// char n_operands

0,// char n_dups; (useless for rtx-gen)

1,// char n_alternatives; (useless for rtx-gen)

1// char output_format; (useless for rtx-gen)

},

{ //\\ insn_data[933] <i386.md:4789>

"addsi3",0,(insn_gen_fn) gen_addsi3,&operand_data[1592],3,0, 0, 0

},

}

static const struct insn_operand_data operand_data[] = {// defined in <recog.h>

{ //\\ operand_data[378]

register_operand,// insn_operand_predicate_fn predicate;

"=a",// char *const constraint; (useless for rtx-gen)

QImode,// ENUM_BITFIELD(machine_mode) mode : 16;

0,// char strict_low; (useless for rtx-gen)

1// char eliminable; (useless for rtx-gen)

},

{ //\\ operand_data[379]

register_operand,"0",HImode,0,1

},

{ //\\ operand_data[380]

nonimmediate_operand,"qm",QImode,0,1

},

{ //\\ operand_data[1592]

nonimmediate_operand,"",SImode,0,1

},

{ //\\ operand_data[1593]

nonimmediate_operand,"",SImode,0,1

},

{ //\\ operand_data[1594]

general_operand,"",SImode,0,1

},

}

FUNCTION expand_binop()

crucial code of expand_binop()

rtxexpand_binop (optab binoptab, rtx op0, rtx op1, rtx target, …) {

int icode = (int) binoptab->handlers[(int) mode].insn_code;

... insn_data[icode].operand[1].mode ...

if ((*insn_data[icode].operand[1].predicate) (xop0, mode0)… )

GEN_FCN (icode) (temp, xop0, xop1);

}

#define GEN_FCN(CODE) (*insn_data[(int) (CODE)].genfun)

in <optabs.h>

for example, addsi3

icode = 933

(*insn_data[icode].operand[1].predicate) = nonimmediate_operand

in <recog.c>

GEN_FCN(CODE) = (*insn_data[(int) (CODE)].genfun) = gen_addsi3

in <insn-emit.c>

FUNCTION gen_divqi3

example of define_insn

generate rtx according to 2nd argument (rtx template) of define_insn of divqi3

FUNCTION gen_addsi3

example of define_expand

do 4th argument of define_expand of addsi3

may DONE or FAIL

generate rtx according to 2nd argument (rtx template) of define_expand of addsi3

RELATED MD-RTX

DEF_RTL_EXPR(DEFINE_INSN, "define_insn", "sEsTV", 'x')

s – insn name

standard name: normal string

non-standard name: string beginning with *, null string

E – rtx template (pattern)

embedded in gen_xxx()

s –condition about target-machine-typefor recognizing this pattern

HAVE_xxx

T – useless for rtx-gen

V – attributes (optional)

DEF_RTL_EXPR(DEFINE_EXPAND, "define_expand", "sEss", 'x')

s – insn name

must be standard name

E –rtx template

embedded in gen_xxx(), low priority

s –condition about target-machine-type for recognizing this pattern

HAVE_xxx

s –preparation statement, extra C code to execute before generating the insns

embedded in gen_xxx(), high priority

Rtx Template

incomplete RTL expression

DEF_RTL_EXPR(MATCH_OPERAND, "match_operand", "iss", 'm')

i – operand index

counting from 0

s – function name, a predicate

s – register allocator restrictions

'=' write-only

'+' read & write

'i' immediate data

'r' register

'm' memory

GCC Internals 13.4, 13.7, 13.8

HOMEWORK

reading Gcc Internals Chapter 13 (Machine Descriptions)

trace rtx-generation for "if statement"