您的位置:首页 > 其它

GCC后端及汇编发布(18)

2011-05-28 08:32 369 查看

9.3.4.

读入
DEFINE_DELAY
模式

DEFINE_DELAY
的细节请参考
DEFINE_DELAY模式的概览

。对于这种模式,我们使用以下例子:

278

(define_delay (and (eq_attr
"type" "branch")

in mips.md

279

(eq (symbol_ref "TARGET_MIPS16")
(const_int 0)))

280

[(eq_attr "can_delay" "yes")

281

(nil)

282

(and (eq_attr "branch_likely" "yes")

283

(eq_attr
"can_delay" "yes"))])

在经过
init_md_reader_args

的处理后,上面的模式被作为以下
rtx
对象载入内存。




41


DEFINE_DELAY
模式的例子

gen_delay

简单地把这些对象链接在一起。

4430

static
void

4431

gen_delay (rtx def,
int lineno)

in genattrtab.c

4432

{

4433

struct
delay_desc
*delay;

4434

int i;

4435

4436

if (XVECLEN (def, 1) % 3 != 0)

4437

{

4438

message_with_line (lineno,

4439

"number of elements in
DEFINE_DELAY must be multiple of three");

4440

have_error

= 1;

4441

return
;

4442

}

4443

4444

for
(i = 0; i < XVECLEN (def, 1); i += 3)

4445

{

4446

if (XVECEXP (def, 1, i + 1))

4447

have_annul_true

= 1;

4448

if (XVECEXP (def, 1, i + 2))

4449

have_annul_false

= 1;

4450

}

4451

4452

delay = oballoc (sizeof
(struct
delay_desc));

4453

delay->def = def;

4454

delay->num = ++num_delays

;

4455

delay->next = delays

;

4456

delay->lineno = lineno;

4457

delays

= delay;

4458

}


4433
行,
delay_desc
是一个简单结构体,它具有如下定义。

213

struct
delay_desc

in genattrtab.c

214

{

215

rtx def;
/* DEFINE_DELAY expression.

*/

216

struct
delay_desc *next;
/* Next
DEFINE_DELAY.
*/

217

int num;
/* Number of DEFINE_DELAY, starting at 1.

*/

218

int lineno;
/* Line number.
*/

219

};



9.3.5.

读入
DEFINE_FUNCTION_UNIT
模式

DEFINE_FUNCTION_UNIT模式的概览

一节描述了
DEFINE_FUNCTION_UINT
模式的细节。在于这个模式,我们使用以下的这里:

43

(define_function_unit
"k6_alux" 1 0

in k6.md

44

(and (eq_attr "cpu" "k6")

45

(eq_attr "type"
"ishift,ishift1,rotate,rotate1,alu1,negnot,cld"))

46

1 1)

比较与我们下面将要看到的模式,这个模式是旧式的指令级别的并行性描述。两者的目的都是产生流水线危险识别器。在同一个机器描述文件中,这两个形式不能共存。至于与新描述比较,这个旧式的描述的缺点,请参考
gccint

10.18.8.3
节。

事实上,从其定义我们可以看到,这个模式以功能单元的角度来描述系统——它告诉我们如果被占据了,这个单元将多久才能再次可用,如果输出的结果要被作为输入使用,要多久才可行,同样它也给出了将占据它的指令列表。

而对于新的形式,也就是说我们将在下面看到的
define_insn_reservation
,它从指令的角度来描述系统——它告诉我们,在指令执行过程中,在流水线的每个阶段,哪些单元将被占据(使用模式来定义之),然后多长时间后其结果可用。这无疑是个更好的形式,因为调度器的目的是尽可能多地发布指令。以指令的角度来描述系统,可用更好地服务于这个目的。

在经过
init_md_reader_args

的处理后,上面的模式被作为以下的
rtx
对象载入内存。




42


DEFINE_FUNCTION_UNIT
模式的例子

gen_unit

从这个
rtx
对象获取信息。每个
define_funciton_unit
模式应该具有唯一的名字,这个名字用作甄别器。

4466

static
void

4467

gen_unit

(rtx def, int lineno)

in genattrtab.c

4468

{

4469

struct

function_unit

*unit;

4470

struct

function_unit_op

*op;

4471

const
char
*name = XSTR (def, 0);

4472

int multiplicity = XINT
(def,
1);

4473

int simultaneity = XINT
(def,
2);

4474

rtx condexp =
XEXP

(def, 3);

4475

int ready_cost = MAX (XINT
(def, 4), 1);

4476

int issue_delay = MAX (XINT
(def, 5), 1);

4477

4478

/* See if we have
already seen this function unit. If so, check that

4479

the multiplicity and simultaneity values
are the same. If not, make

4480

a structure for this function unit.
*/

4481

for
(unit = units

;
unit; unit = unit->next)

4482

if (! strcmp (unit->name, name))

4483

{

4484

if (unit->multiplicity != multiplicity

4485

||
unit->simultaneity != simultaneity)

4486

{

4487

message_with_line (lineno,

4488

"differing specifications given for
function unit %s",

4489

unit->name);

4490

message_with_line (unit->first_lineno,
"previous definition");

4491

have_error

= 1;

4492

return
;

4493

}

4494

break
;

4495

}

4496

4497

if (unit == 0)

4498

{

4499

unit = oballoc (sizeof
(struct

function_unit

));

4500

unit->name = name;

4501

unit->multiplicity = multiplicity;

4502

unit->simultaneity = simultaneity;

4503

unit->issue_delay.min =
unit->issue_delay.max = issue_delay;

4504

unit->num = num_units

++;

4505

unit->num_opclasses = 0;

4506

unit->condexp = false_rtx

;

4507

unit->ops
= 0;

4508

unit->next = units

;

4509

unit->first_lineno = lineno;

4510

units

= unit;

4511

}

4512

else

4513

XSTR (def, 0) = unit->name;

4514

4515

/* Make a new
operation class structure entry and initialize it.
*/

4516

op = oballoc (sizeof
(struct

function_unit_op

));

4517

op->condexp = condexp;

4518

op->num = unit->num_opclasses++;

4519

op->ready
= ready_cost;

4520

op->issue_delay = issue_delay;

4521

op->next = unit->ops;

4522

op->lineno = lineno;

4523

unit->ops = op;

4524

num_unit_opclasses

++;

4525

4526

/* Set our issue
expression based on whether or not an optional conflict

4527

vector was specified.
*/

4528

if (XVEC (def, 6))

4529

{

4530

/* Compute the
IOR of all the specified expressions.

*/

4531

rtx orexp = false_rtx

;

4532

int i;

4533

4534

for
(i = 0; i < XVECLEN (def, 6); i++)

4535

orexp =
insert_right_side

(IOR, orexp, XVECEXP (def, 6, i), -2, -2);

4536

4537

op->conflict_exp = orexp;

4538

extend_range (&unit->issue_delay, 1,
issue_delay);

4539

}

4540

else

4541

{

4542

op->conflict_exp = true_rtx

;

4543

extend_range (&unit->issue_delay,
issue_delay, issue_delay);

4544

}

4545

4546

/* Merge our
conditional into that of the function unit so we can determine

4547

which insns are used by the function
unit.
*/

4548

unit->condexp =
insert_right_side

(IOR, unit->condexp, op->condexp, -2, -2);

4549

}

function_unit

condexp

域指向一个表达式,如果其值是
TURE
,表示需要这个单元。构建出来的
function_unit object
被保存在数组
units

里。

238

struct
function_unit

in
genattrtab.c

239

{

240

const
char *name;
/* Function unit name.
*/

241

struct
function_unit *next;
/* Next function
unit.
*/

242

int num;
/* Ordinal of this unit type.
*/

243

int multiplicity;
/* Number of units of this type.
*/

244

int simultaneity;
/* Maximum number of simultaneous insns

245

on this function unit or 0 if unlimited.
*/

246

rtx condexp;
/* Expression TRUE for insn needing unit.
*/

247

int num_opclasses;
/* Number of different operation types.
*/

248

struct

function_unit_op

*ops;
/* Pointer to first operation type.
*/

249

int needs_conflict_function;
/* Nonzero if a conflict function required.
*/

250

int needs_blockage_function;
/* Nonzero if a blockage function
required.
*/

251

int needs_range_function;
/* Nonzero if blockage range function needed.
*/

252

rtx default_cost;
/* Conflict cost, if constant.
*/

253

struct
range issue_delay;
/* Range of issue
delay values.
*/

254

int max_blockage;
/* Maximum time an insn blocks the unit.
*/

255

int first_lineno;
/* First seen line number.

*/

256

};

某些功能单元可能被多个指令组所使用(在一个
define_function_unit
里可以出现多个指令,我们称之为一组,因为如果出现,它们具有相似的发布延迟,就绪代价,及冲突列表)。因为每个组可能包含所涉及的特有的参数,这需要额外的数据结构。结构体
function_unit_op
为这个目的而设计。

223

struct
function_unit_op

in
genattrtab.c

224

{

225

rtx condexp;
/* Expression TRUE for applicable insn.
*/

226

struct
function_unit_op *next; /* Next operation for this function unit.
*/

227

int num;
/* Ordinal for this operation type in unit.
*/

228

int ready;
/* Cost until data is ready.
*/

229

int issue_delay;
/* Cost until unit can accept another insn.
*/

230

rtx conflict_exp;
/* Expression TRUE for insns incurring issue delay.
*/

231

rtx issue_exp;
/* Expression computing issue delay.
*/

232

int lineno;
/* Line number.
*/

233

};

在这里,
function_unit_op
中的
condexp

域包含了识别组的测试的
rtx
对象。这很容易理解,在
gen_unit

里处理了所有相关的
define_cpu_unit
模式后,
function_unit

condexp

域由
insert_right_side

通过
IOR
所有从属的
function_unit_op

condexp

得到。

insert_right_side

接受两个表达式,从它们来构建一个规范的
OR


表达式。这个函数具有以下定义。

2653

static
rtx

in
genattrtab.c

2654

insert_right_side

(enum
rtx_code code, rtx exp, rtx term, int insn_code,
int insn_index)

2655

{

2656

rtx newexp;

2657

2658

/* Avoid consing in
some special cases.
*/

2659

if (code == AND && term == true_rtx

)

2660

return
exp;

2661

if (code == AND && term == false_rtx

)

2662

return
false_rtx

;

2663

if (code == AND && exp == true_rtx

)

2664

return
term;

2665

if (code == AND && exp == false_rtx

)

2666

return
false_rtx

;

2667

if (code == IOR && term == true_rtx

)

2668

return
true_rtx

;

2669

if (code == IOR && term == false_rtx

)

2670

return
exp;

2671

if (code == IOR && exp == true_rtx

)

2672

return true_rtx

;

2673

if (code == IOR && exp == false_rtx

)

2674

return
term;

2675

if (attr_equal_p (exp, term))

2676

return
exp;

2677

2678

if (GET_CODE (term) == code)

2679

{

2680

exp = insert_right_side
(code, exp, XEXP
(term, 0),

2681

insn_code, insn_index);

2682

exp = insert_right_side
(code, exp, XEXP
(term, 1),

2683

insn_code, insn_index);

2684

2685

return
exp;

2686

}

2687

2688

if (GET_CODE (exp) == code)

2689

{

2690

rtx new = insert_right_side
(code, XEXP
(exp, 1),

2691

term, insn_code, insn_index);

2692

if (new !=
XEXP

(exp, 1))

2693

/* Make a copy of this expression and
call recursively.
*/

2694

newexp = attr_rtx
(code, XEXP
(exp, 0), new);

2695

else

2696

newexp = exp;

2697

}

2698

else

2699

{

2700

/* Insert the new
term.
*/

2701

newexp = attr_rtx
(code, exp, term);

2702

}

2703

2704

return
simplify_test_exp_in_temp
(newexp,
insn_code, insn_index);

2705

}

对于我们的例子,我们在
2674
行返回。在
2678
行以下的代码用于复杂的情形来简化测试。在
2678
行的代码块用于转换形如:
A AND B, B = C AND D
的表达式。在于这种情形,它将被转换为:
(A AND C) AND D


类似的,对于形如:
A AND B, A = C AND D
的表达式,它将被转换为
C AND (D AND B)
,其值如果“
D AND B
”等于
D
,“
A AND B
”可以被“
A
”所替代,这就是
2696
行的含义。并且如果“
D AND B
”不等于
D
,把语句分解为“
C
”,“
D AND B
”,这正是
2690

2696
行的目的。


2704
行,
simplify_test_exp_in_temp

将执行更多的简化。我们在后面来看它。



9.3.6.

读入
DEFINE_CPU_UNIT
模式

DEFINE_INSN_RESERVATION模式的概览

一节描述了
define_cpu_unit
模式的细节。对于这个模式,我们使用以下的例子:

88

(define_cpu_unit "pentium-portu,pentium-portv"
"pentium")
in pentium.md

从这个模式开始,余下的这些模式用于构建基于
DFA
的流水线危险识别器,这是更新式的,与我们之前看到的指令级别并行性描述比较而言。至于这个新式形式的好处,同样参考
gccint

10.18.8
.3
节。这个模式不能与
define_function_unit
共存在同一个机器描述文件中。

在经过
init_md_reader_args

的处理后,上面的模式将作为以下的
rtx
对象载入内存。




43


DEFINE_CPU_UNIT
模式的例子

Rtx
形式并不是我们所希望的,我们需要
gen_cpu_unit

来打包这些数据。

1652

void

1653

gen_cpu_unit (rtx def)
in
genattrtab.c

1654

{

1655

decl_t

decl;

1656

char **str_cpu_units;

1657

int vect_length;

1658

int i;

1659

1660

str_cpu_units = get_str_vect ((char *) XSTR
(def, 0), &vect_length, ',',

1661

FALSE);

1662

if (str_cpu_units == NULL)

1663

fatal ("invalid string `%s' in
define_cpu_unit", XSTR (def, 0));

1664

for
(i = 0; i
< vect_length; i++)

1665

{

1666

decl = create_node (sizeof
(struct
decl));

1667

decl->mode = dm_unit;

1668

decl->pos = 0;

1669

DECL_UNIT

(decl)->name = check_name (str_cpu_units [i], decl->pos);

1670

DECL_UNIT

(decl)->automaton_name = (char *) XSTR (def, 1);

1671

DECL_UNIT

(decl)->query_p = 0;

1672

DECL_UNIT

(decl)->min_occ_cycle_num = -1;

1673

DECL_UNIT

(decl)->in_set_p = 0;

1674

VLA_PTR_ADD
(decls

,
decl);

1675

num_dfa_decls

++;

1676

}

1677

}

所有单元的信息被保存在由
decls

指向的列表中

其类型如下。

907

struct
decl

in
genautomata.c

908

{

909

/* What
node in the union? */

910

enum
decl_mode mode;

911

pos_t pos;

912

union

913

{

914

struct

unit_decl

unit;

915

struct

bypass_decl

bypass;

916

struct

automaton_decl

automaton;

917

struct

excl_rel_decl

excl;

918

struct

unit_pattern_rel_decl

presence;

919

struct

unit_pattern_rel_decl

absence;

920

struct

reserv_decl

reserv;

921

struct
insn_reserv_decl
insn_reserv;

922

} decl;

923

};

196

typedef struct

decl

*decl_t
;

in
genautomata.c

Decl
是由所有类型的模式共享的类型,用于构建基于
DFA
的流水线危险识别器。对于
define_cup_unit
模式,使用了
unit_decl

域。

727

struct
unit_decl

in
genautomata.c

728

{

729

char *name;

730

/* NULL if the automaton name is absent.
*/

731

char *automaton_name;

732

/* If the following value is not zero, the cpu
unit reservation is

733

described in define_query_cpu_unit.
*/

734

char query_p;

735

736

/* The following fields are defined by
checker.
*/

737

738

/* The following field value is nonzero if the
unit is used in an

739

regexp.

*/

740

char unit_is_used;

741

742

/* The following field value is order number
(0, 1, ...) of given

743

unit.

*/

744

int unit_num;

745

/* The following field value is corresponding
declaration of

746

automaton which was given in description. If
the field value is

747

NULL then automaton in the unit declaration
was absent.
*/

748

struct

automaton_decl

*automaton_decl;

749

/* The following field value is maximal cycle
number (1, ...) on

750

which given unit occurs in insns. Zero
value means that given

751

unit is not used in insns.

*/

752

int max_occ_cycle_num;

753

/* The following field value is minimal cycle
number (0, ...) on

754

which given unit occurs in insns. -1 value
means that given

755

unit is not used in insns.

*/

756

int min_occ_cycle_num;

757

/* The following list contains units which
conflict with given

758

unit.

*/

759

unit_set_el_t

excl_list;

760

/* The following list contains patterns which
are required to

761

reservation of given unit.
*/

762

pattern_set_el_t presence_list;

763

pattern_set_el_t final_presence_list;

764

/* The following list contains patterns which
should be not present

765

i
n reservation for given unit.
*/

766

pattern_set_el_t absence_list;

767

pattern_set_el_t final_absence_list;

768

/* The following is used only when `query_p'
has nonzero value.

769

This is query number for the unit.
*/

770

int query_num;

771

/* The following is the last cycle on which
the unit was checked for

772

correct distributions of units to automata
in a regexp.
*/

773

int last_distribution_check_cycle;

774

775

/* The following fields are defined by
automaton generator.
*/

776

777

/* The following field value is number of the
automaton to which

778

given unit belongs.
*/

779

int corresponding_automaton_num;

780

/* If the following value is not zero, the cpu
unit is present in a

781

`exclusion_set' or in right part of a
`presence_set',

782

`final_presence_set', `absence_set', and

783

`final_absence_set'define_query_cpu_unit.
*/

784

char in_set_p;

785

};

在上面的
1660
行,
get_str_vec

获取由“
,
”分隔的单元名。宏
DECL_UNIT

将访问
decl

unit_decl

域。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: