您的位置:首页 > 其它

GCC后端及汇编发布(22)

2011-05-29 10:59 465 查看

9.4.2.

处理
DEFINE_FUNCTION_UNIT
模式

我们已经知道
define_function_unit
从功能单元的角度来描述芯片。不过,这个模式仍然主要是人类可读的形式。我们必须构建可以容易被工具处理,来为流水线危险识别器输出函数的数据。这个旧式的芯片描述比新式的要简单得多,这里构建的数据仍然是属性。

main (continued)

6128

if (num_units

|| num_dfa_decls

)

6129

{

6130

/*
Expand DEFINE_FUNCTION_UNIT information into new attributes.
*/

6131

expand_units

();

6132

/* Build DFA, output some functions and expand
DFA information

6133

into
new attributes.
*/

6134

expand_automata

();

6135

}

对于我们的例子,在由
gen_unit

生成之后,我们可以得到如下数据(至于没有显示的域,表示其内容为
0
)。




51


FUNCTION_UNIT
的例子

以上形式的数据并不适合简单、直接地用于构建流水线危险识别器。我们需要
expand_units

来获取信息,然后通过把这些信息放入哈希表及构建相应的属性,使它们永久化。

1812

static
void

1813

expand_units

(void)
in
genattrtab.c

1814

{

1815

struct
function_unit
*unit, **unit_num;

1816

struct
function_unit_op
*op, **op_array, ***unit_ops;

1817

rtx unitsmask;

1818

rtx readycost;

1819

rtx newexp;

1820

const
char
*str;

1821

int i, j, u, num, nvalues;

1822

1823

/* Rebuild the
condition for the unit to share the RTL expressions.

1824

Sharing is required by
simplify_by_exploding. Build the issue delay

1825

expressions. Validate the expressions we
were given for the conditions

1826

and conflict vector. Then make attributes
for use in the conflict

1827

function.

*/

1828

1829

for
(unit = units

;
unit; unit = unit->next)

1830

{

1831

unit->condexp = check_attr_test
(unit->condexp, 0, unit->first_lineno);

1832

1833

for
(op = unit->ops; op; op = op->next)

1834

{

1835

rtx
issue_delay = make_numeric_value
(op->issue_delay);

1836

rtx
issue_exp = issue_delay;

1837

1838

/* Build, validate, and simplify the issue delay
expression.
*/

1839

if
(op->conflict_exp != true_rtx

)

1840

issue_exp = attr_rtx
(IF_THEN_ELSE, op->conflict_exp,

1841

issue_exp, make_numeric_value
(0));

1842

issue_exp = check_attr_value
(make_canonical
(NULL_ATTR,

1843

issue_exp),

1844

NULL_ATTR);

1845

issue_exp = simplify_knowing
(issue_exp, unit->condexp);

1846

op->issue_exp = issue_exp;

1847

1848

/* Make an attribute for use in the conflict function if
needed.
*/

1849

unit->needs_conflict_function =
(unit->issue_delay.min

1850

!= unit->issue_delay.max);

1851

if
(unit->needs_conflict_function)

1852

{

1853

str = attr_printf ((strlen (unit->name)
+ sizeof
"*_cost_"

1854

+ MAX_DIGITS),

1855

"*%s_cost_%d",
unit->name, op->num);

1856

make_internal_attr
(str, issue_exp,
ATTR_SPECIAL);

1857

}

1858

1859

/* Validate the
condition.
*/

1860

op->condexp = check_attr_test
(op->condexp, 0, op->lineno);

1861

}

1862

}

正如我们在
读入

DEFINE_FUNCTION_UNIT模式

一节中所看到的,对于被多条指令所使用的功能单元,
function_unit


condexp

部分将是所有的
function_unit_op


condexp

部分
OR


操作的结果。因此在
1831

1860
行,
check_attr_test

实际用于不同的目的。

至于
check_attr_test

,给定一个属性的测试表达式,该函数确保它是一个有效形式。参数
is_const

显示,对于每次编译器运行,该表达式是否为常量(一个常量表达式不可能测试任意具体的指令)。这个函数把
(eq_attr
"att" "a1,a2")

转换为
(ior (eq_attr “att” “a1 ) (eq_attr “att” “a2”))

,以及把
(eq_attr
"att" "!a1")

转换为
(not
(eq_attr "att" "a1"))

。它首先执行后一个的转换,因此
(eq_attr
"att" "!a1,a2,a3")

可以按预期的工作。并且它把在
EQ_ATTR
表达式中的字符串为,在属性所使用的相同的字符串(或
alternative_name

),来加速后面调用的
find_attr

,以及消除绝大多数的
strcmp

调用。这个函数返回新的表达式,如果有的话。

919

rtx

920

check_attr_test

(rtx exp, int is_const,
int lineno)

in
genattrtab.c

921

{

922

struct
attr_desc
*attr;

923

struct
attr_value
*av;

924

const
char
*name_ptr, *p;

925

rtx orexp, newexp;

926

927

switch
(GET_CODE (exp))

928

{

929

case
EQ_ATTR:

930

/* Handle
negation test.
*/

931

if (XSTR (exp, 1)[0] == '!')

932

return
check_attr_test
(attr_rtx
(NOT,

933

attr_eq
(XSTR (exp, 0),

934

&XSTR (exp, 1)[1])),

935

is_const, lineno);

936

937

else if (n_comma_elts (XSTR (exp, 1)) ==
1)

938

{

939

attr = find_attr
(&XSTR (exp, 0), 0);

940

if (attr == NULL)

941

{

942

if (! strcmp (XSTR (exp, 0),
"alternative"))

943

return
mk_attr_alt (1 << atoi (XSTR (exp, 1)));

944

else

945

fatal ("unknown attribute `%s'
in EQ_ATTR", XSTR (exp, 0));

946

}

947

948

if (is_const && !
attr->is_const)

949

fatal ("constant expression uses
insn attribute `%s' in EQ_ATTR",

950

XSTR (exp, 0));

951

952

/* Copy this just to make it permanent,

953

so expressions using it can be permanent
too.
*/

954

exp = attr_eq
(XSTR (exp, 0), XSTR (exp, 1));

955

956

/* It shouldn't be possible to simplify the
value given to a

957

constant attribute, so don't expand this
until it's time to

958

write the test expression.
*/

959

if (attr->is_const)

960

ATTR_IND_SIMPLIFIED_P
(exp) = 1;

961

962

if (attr->is_numeric)

963

{

964

for
(p = XSTR (exp, 1); *p; p++)

965

if (! ISDIGIT (*p))

966

fatal ("attribute `%s' takes
only numeric values",

967

XSTR (exp, 0));

968

}

969

else

970

{

971

for
(av = attr->first_value; av; av = av->next)

972

if (GET_CODE (av->value) ==
CONST_STRING

973

&& ! strcmp (XSTR (exp,
1), XSTR (av->value, 0)))

974

break
;

975

976

if (av == NULL)

977

fatal ("unknown value `%s' for
`%s' attribute",

978

XSTR (exp, 1), XSTR (exp, 0));

979

}

980

}

981

else

982

{

983

if (! strcmp (XSTR (exp, 0),
"alternative"))

984

{

985

int set = 0;

986

987

name_ptr = XSTR (exp, 1);

988

while
((p = next_comma_elt (&name_ptr)) != NULL)

989

set |= 1 << atoi (p);

990

991

return
mk_attr_alt (set);

992

}

993

else

994

{

995

/* Make an
IOR tree of the possible values.
*/

996

orexp = false_rtx

;

997

name_ptr = XSTR (exp, 1);

998

while
((p = next_comma_elt (&name_ptr)) != NULL)

999

{

1000

newexp = attr_eq
(XSTR (exp, 0), p);

1001

orexp = insert_right_side
(IOR, orexp, newexp, -2, -2);

1002

}

1003

1004

return
check_attr_test
(orexp, is_const, lineno);

1005

}

1006

}

1007

break
;

1008

1009

case
ATTR_FLAG:

1010

break
;

1011

1012

case
CONST_INT:

1013

/* Either TRUE
or FALSE.
*/

1014

if (XWINT
(exp, 0))

1015

return
true_rtx

;

1016

else

1017

return
false_rtx

;

1018

1019

case
IOR:

1020

case
AND:

1021

XEXP
(exp, 0) = check_attr_test
(XEXP
(exp, 0),
is_const, lineno);

1022

XEXP
(exp, 1) = check_attr_test
(XEXP
(exp, 1),
is_const, lineno);

1023

break
;

1024

1025

case
NOT:

1026

XEXP
(exp, 0) = check_attr_test
(XEXP
(exp, 0),
is_const, lineno);

1027

break
;

1028

1029

case
MATCH_INSN:

1030

case
MATCH_OPERAND:

1031

if (is_const)

1032

fatal ("RTL operator /"%s/"
not valid in constant attribute test",

1033

GET_RTX_NAME (GET_CODE (exp)));

1034

/* These cases
can't be simplified.
*/

1035

ATTR_IND_SIMPLIFIED_P
(exp) = 1;

1036

break
;

1037

1038

case
LE:
case
LT:
case
GT:
case
GE:

1039

case
LEU: case
LTU: case
GTU: case
GEU:

1040

case
NE:
case
EQ:

1041

if (GET_CODE (XEXP
(exp, 0)) == SYMBOL_REF

1042

&& GET_CODE (XEXP
(exp, 1)) == SYMBOL_REF)

1043

exp = attr_rtx
(GET_CODE (exp),

1044

attr_rtx
(SYMBOL_REF, XSTR (XEXP
(exp, 0), 0)),

1045

attr_rtx
(SYMBOL_REF, XSTR (XEXP
(exp, 1), 0)));

1046

/* These cases
can't be simplified.
*/

1047

ATTR_IND_SIMPLIFIED_P
(exp) = 1;

1048

break
;

1049

1050

case
SYMBOL_REF:

1051

if (is_const)

1052

{

1053

/* These cases are valid for constant
attributes, but can't be

1054

simplified.
*/

1055

exp = attr_rtx
(SYMBOL_REF, XSTR (exp, 0));

1056

ATTR_IND_SIMPLIFIED_P
(exp) = 1;

1057

break
;

1058

}

1059

default
:

1060

fatal ("RTL operator
/"%s/" not valid in attribute test",

1061

GET_RTX_NAME (GET_CODE (exp)));

1062

}

1063

1064

return
exp;

1065

}

函数
n_comma_elts

计算在传入字符串中“
,
”的数目。如果该属性具有名字“
alternative
”,它指向编译器变量
which_alternative

,这个变量必须是一个数值。这个值在
943
行通过
mk_attr_alt

保存入
EQ_ATTR_ALT
。在
960
行的
ATTR_IND_SIMPLIFIED_P

访问这个
rtx
对象的
unchanging

域。这个域如果是
1
,表示该
rtx
对象所代表的表达式不能被简化。
attr_eq

则构建操作数保存在
attr_hash_table


EQ_ATTR
对象。

763

static
rtx

764

attr_eq

(const
char *name, const
char *value)

in
genattrtab.c

765

{

766

return
attr_rtx
(EQ_ATTR, DEF_ATTR_STRING
(name), DEF_ATTR_STRING
(value));

767

}

然后,在
expand_units


1845
行,注意到
simplify_knowing

的第二个参数是由
check_attr_test

生成的
unit


condexp

域,我们例子中的
condexp

显示在下图。

http://hi.csdn.net/attachment/201105/29/4457637_13066374946oze.jpg" border="0" >


52

:由
check_attr_test
生成的
condexp

此处在我们的例子中,
simplify_knowing

的第一个参数
exp

是一个
rtx
对象,它等效于:

IF op->conflict_exp THEN

op->issue_delay

ELSE

0

或者
op->issue_delay
。(如果没有定义
conflict_exp


比较上面的表达式与
gccint
中的描述,特别是黑体部分:

CONFLICT-LIST
是一个可选的列表,它给出了这个单元详细的冲突代价。如果指定了,它就是一个条件测试表达式列表,这些表达式将应用到被选择在
NAME
中执行的指令上,而这些指令跟在匹配
TEST
并且正在
NAME
中执行的指令后。对于在该列表中的每条指令,
ISSUE-DELAY
指出了冲突代价;而对于不在列表中的指令,这个代价为
0
如果没有指定,

CONFLICT-LIST

默认用于所有使用这个功能单元的指令。


2173

static
rtx

2174

simplify_knowing

(rtx exp, rtx
known_true)

in genattrtab.c

2175

{

2176

if (GET_CODE (exp) != CONST_STRING)

2177

{

2178

int unknown = 0, max;

2179

max = max_attr_value
(exp, &unknown);

2180

if (! unknown)

2181

{

2182

exp = attr_rtx
(IF_THEN_ELSE, known_true, exp,

2183

make_numeric_value
(max));

2184

exp = simplify_by_exploding
(exp);

2185

}

2186

}

2187

return
exp;

2188

}


2179
行,
max_attr_value

,给定一个属性,返回在该属性里找到的最大的数值,如果该属性不是正确的类型,设置
UNKNOWNP

并返回
INT_MAX
。因此它返回的
max

是由于冲突导致的
issue_delay

,如果一切顺利的话。

4850

static
int

4851

max_attr_value

(rtx exp, int *unknownp)

in
genattrtab.c

4852

{

4853

int current_max;

4854

int i, n;

4855

4856

switch
(GET_CODE (exp))

4857

{

4858

case
CONST_STRING:

4859

current_max = atoi (XSTR (exp, 0));

4860

break
;

4861

4862

case
COND:

4863

current_max = max_attr_value
(XEXP
(exp, 1), unknownp);

4864

for
(i = 0; i < XVECLEN (exp, 0); i
+= 2)

4865

{

4866

n = max_attr_value
(XVECEXP (exp, 0, i + 1), unknownp);

4867

if (n > current_max)

4868

current_max = n;

4869

}

4870

break
;

4871

4872

case
IF_THEN_ELSE:

4873

current_max = max_attr_value
(XEXP
(exp, 1), unknownp);

4874

n = max_attr_value
(XEXP
(exp, 2), unknownp);

4875

if (n > current_max)

4876

current_max = n;

4877

break
;

4878

4879

default
:

4880

*unknownp = 1;

4881

current_max = INT_MAX;

4882

break
;

4883

}

4884

4885

return
current_max;

4886

}

回到
expand_units


simplify_knowing

被包含在一个
FOR

循环里,并且为每一条指令进行调用。在
simplify_knowing


2182
行,它构建了
IF_THEN_ELSE

rtx
对象,它等效于:

IF unit->condexp THEN

IF
op->conflict_exp THEN

op->issue_delay.

ELSE

0

ELSE

op->issue_delay

或者(如果
op->conflict_exp

null
):

IF
unit->condexp THEN

op->issue_delay

ELSE

op->issue_delay

该表达式,在执行的某个点上给定参数,返回在该功能单元上的发布延迟。这是旧式流水线危险识别器的核心。不过正如所见的,它还不是简化的形式,因此在
2184
行调用
simplify_by_exploding

来把这个表达式转换为规范及简化的形式。

3724

static
rtx

3725

simplify_by_exploding

(rtx exp)

in
genattrtab.c

3726

{

3727

rtx list = 0, link, condexp, defval =
NULL_RTX;

3728

struct
dimension *space;

3729

rtx *condtest, *condval;

3730

int i, j, total, ndim = 0;

3731

int most_tests, num_marks, new_marks;

3732

rtx ret;

3733

3734

/* Locate all the
EQ_ATTR expressions.
*/

3735

if (! find_and_mark_used_attributes
(exp, &list, &ndim) || ndim == 0)

3736

{

3737

unmark_used_attributes (list, 0, 0);

3738

return
exp;

3739

}

find_and_mark_used_attributes

只是把所有的
EQ_ATTR
链接在一起,
ATTR_EQ_ATTR_P
访问
exp


volatil

域,该域在
3896
行设置,以防止
exp

被多次链接。

3881

static
int

3882

find_and_mark_used_attributes

(rtx exp, rtx *terms, int *nterms)
in
genattrtab.c

3883

{

3884

int i;

3885

3886

switch
(GET_CODE (exp))

3887

{

3888

case
EQ_ATTR:

3889

if (! ATTR_EQ_ATTR_P
(exp))

3890

{

3891

rtx link = rtx_alloc (EXPR_LIST);

3892

XEXP
(link, 0) =
exp;

3893

XEXP
(link, 1) =
*terms;

3894

*terms = link;

3895

*nterms += 1;

3896

ATTR_EQ_ATTR_P
(exp) = 1;

3897

}

3898

return
1;

3899

3900

case
CONST_STRING:

3901

case
CONST_INT:

3902

return
1;

3903

3904

case
IF_THEN_ELSE:

3905

if (! find_and_mark_used_attributes
(XEXP
(exp, 2), terms, nterms))

3906

return
0;

3907

case
IOR:

3908

case
AND:

3909

if (!find_and_mark_used_attributes
(XEXP
(exp, 1), terms, nterms))

3910

return
0;

3911

case
NOT:

3912

if (!find_and_mark_used_attributes
(XEXP
(exp, 0), terms, nterms))

3913

return
0;

3914

return
1;

3915

3916

case
COND:

3917

for
(i =
0; i < XVECLEN (exp, 0); i++)

3918

if (!find_and_mark_used_attributes
(XVECEXP (exp, 0, i), terms, nterms))

3919

return
0;

3920

if (!find_and_mark_used_attributes
(XEXP
(exp, 1), terms, nterms))

3921

return
0;

3922

return
1;

3923

3924

default
:

3925

return
0;

3926

}

3927

}

101

#define
ATTR_EQ_ATTR_P
(RTX) (RTX_FLAG((RTX),
volatil))

in genattrtab.c

继续
simpilify_by_exploding

,现在
ndim

,对于我们的例子,是
7

exp

参考

52
,并假定它是仅有的描述相关单元的
define_funtion_unit
——即在
op

中没有
conflict_exp

)。

simplify_by_exploding (continued)

3741

/* Create an attribute space from the list of
used attributes. For each

3742

dimension in the attribute space, record
the attribute, list of values

3743

used, and number of values used. Add
members to the list of values to

3744

cover the domain of the attribute. This
makes the expanded COND form

3745

order independent.
*/

3746

3747

space = xmalloc (ndim * sizeof
(struct
dimension
));

3748

3749

total = 1;

3750

for
(ndim =
0; list; ndim++)

3751

{

3752

/* Pull the first
attribute value from the list and record that

3753

attribute as another dimension in the
attribute space.
*/

3754

const
char
*name = XSTR (XEXP
(list, 0), 0);

3755

rtx *prev;

3756

3757

space[ndim].attr = find_attr
(&name, 0);

3758

XSTR (XEXP
(list, 0),
0) = name;

3759

3760

if (space[ndim].attr == 0

3761

|| space[ndim].attr->is_numeric)

3762

{

3763

unmark_used_attributes (list, space,
ndim);

3764

return
exp;

3765

}

3766

3767

/* Add all
remaining attribute values that refer to this attribute.
*/

3768

space[ndim].num_values = 0;

3769

space[ndim].values = 0;

3770

prev = &list;

3771

for
(link =
list; link; link = *prev)

3772

if (! strcmp_check (XSTR (XEXP
(link, 0), 0), name))

3773

{

3774

space[ndim].num_values++;

3775

*prev = XEXP
(link, 1);

3776

XEXP
(link, 1) = space[ndim].values;

3777

space[ndim].values = link;

3778

}

3779

else

3780

prev = &XEXP
(link, 1);

3781

3782

/* Add sufficient
members to the list of values to make the list

3783

mutually exclusive and record the total
size of the attribute

3784

space.

*/

3785

total *= add_values_to_cover
(&space[ndim]);

3786

}


3747
行的
dimension

具有如下的定义。在
3757
行,
find_attr

构建了与
attr_hash_table

中的
name

关联的属性,并返回之。注意参数
name

为在
attr_hash_table

中的对等对象所替换。在
3758
行,这个节点的
name

被更新。因此在
3772
行,
strcmp_check

可以仅比较这两个字符串的地址。

302

struct
dimension

in genattrtab.c

303

{

304

struct
attr_desc
*attr;
/*
Attribute for this dimension.
*/

305

rtx values;
/* List of attribute values used.
*/

306

rtx current_value;
/* Position in the list for the TRUE value.
*/

307

int num_values;
/* Length of the values list.
*/

308

}


3750
行的整个
FOR

循环,其每次循环将找出同名的属性,并把它们链接入
space


同一个元素里,然后为这个
space

的元素调用
add_values_to_cover

(属性名是
EQ_ATTR
的第一个孩子的)。

例如,一开始我们得到如下的布局。第一个节点必定通过
3772
行的测试。




53


define_function_unit
处理的案例,图
1

在执行了
3774 ~ 3777
行的代码,以及下一次循环时
3771
行后,我们可以得到如下布局。节点
0
是具有名字“
cpu
”的
EQ_ATTR
,它被链入
space[0]
,其它节点是具有名字“
type
”的
EQ_ATTR
,它们被链入
space[1]
(参见


52

)。注意到,任意由功能单元描述模式所产生的链表组,在执行的任一点上,每个链表最多有一个节点被匹配,因为属性在一个时间点上不能取多个值。




54


define_function_unit
处理的案例,图
2

然后调用
add_values_to_cover

来把该属性其它未被提及的数值链入这个链表。通过这个方式,这个链表完整代表了这个令人感兴趣的属性。

3952

static
int

3953

add_values_to_cover

(struct
dimension
*dim)

in genattrtab.c

3954

{

3955

struct
attr_value
*av;

3956

rtx exp, link, *prev;

3957

int nalt = 0;

3958

3959

for
(av =
dim->attr->first_value; av; av = av->next)

3960

if (GET_CODE (av->value) ==
CONST_STRING)

3961

nalt++;

3962

3963

if (nalt < dim->num_values)

3964

abort ();

3965

else if (nalt == dim->num_values)

3966

/* OK.

*/

3967

;

3968

else if (nalt * 2 < dim->num_values *
3)

3969

{

3970

/* Most all the
values of the attribute are used, so add all the unused

3971

values.

*/

3972

prev = &dim->values;

3973

for
(link =
dim->values; link; link = *prev)

3974

prev = &XEXP
(link, 1);

3975

3976

for
(av =
dim->attr->first_value; av; av = av->next)

3977

if (GET_CODE (av->value) ==
CONST_STRING)

3978

{

3979

exp = attr_eq
(dim->attr->name, XSTR (av->value, 0));

3980

if (ATTR_EQ_ATTR_P
(exp))

3981

continue
;

3982

3983

link = rtx_alloc (EXPR_LIST);

3984

XEXP
(link, 0) =
exp;

3985

XEXP
(link, 1) = 0;

3986

*prev = link;

3987

prev = &XEXP
(link, 1);

3988

}

3989

dim->num_values = nalt;

3990

}

3991

else

3992

{

3993

rtx orexp = false_rtx

;

3994

3995

/* Very few
values are used, so compute a mutually exclusive

3996

expression. (We could do this for numeric
values if that becomes

3997

important.)
*/

3998

prev = &dim->values;

3999

for
(link =
dim->values; link; link = *prev)

4000

{

4001

orexp = insert_right_side
(IOR, orexp, XEXP
(link, 0), -2, -2);

4002

prev = &XEXP
(link,
1);

4003

}

4004

link = rtx_alloc (EXPR_LIST);

4005

XEXP
(link, 0) = attr_rtx
(NOT, orexp);

4006

XEXP
(link, 1) = 0;

4007

*prev = link;

4008

dim->num_values++;

4009

}

4010

return
dim->num_values;

4011

}

dimension


attr

域指向描述该属性的
attr_desc
对象,其中的
first_value

域维护记录了所有属性值的一个链表。而
dimension


values

域只是记录了用在这个
define_function_unit
模式里的属性的值。显然,
values

必定是
attr


first_value

的一个子集。这里是我们整合该链表的方式——如果所使用值的数目接近于属性值的总数,把余下未引用的属性值加到链表末尾(
3969 ~ 3989
行),而如果差别相当大的话,则构建一个新的
EXPR_LIST
来代表余下的值(看到它是一个对于所有未被引用值的
NOT
表达式),并从末尾链入。如下图所示。




55


define_function_unit
处理的案例,图
3

上面的把同名属性链接起来,还有整合链表的过程,一再重复,直到所有的属性都得到处理。然后在下面这些链表被排序,常量及数值多优先。

simplify_by_exploding (continued)

3788

/* Sort the
attribute space so that the attributes go from non-constant

3789

to constant and from most values to least
values.

*/

3790

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

3791

for
(j = ndim - 1; j > i; j--)

3792

if ((space[j-1].attr->is_const
&& !space[j].attr->is_const)

3793

|| space[j-1].num_values <
space[j].num_values)

3794

{

3795

struct
dimension
tmp;

3796

tmp = space[j];

3797

space[j] = space[j - 1];

3798

space[j - 1] = tmp;

3799

}

3800

3801

/* Estabusagelish
the initial current value.

*/

3802

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

3803

space[i].current_value = space[i].values;

3804

3805

condtest = xmalloc (total * sizeof
(rtx));

3806

condval = xmalloc (total * sizeof
(rtx));

3807

3808

/* Expand the tests
and values by iterating over all values in the

3809

attribute space.
*/

3810

for
(i = 0;;
i++)

3811

{

3812

condtest[i] = test_for_current_value
(space, ndim);

3813

condval[i] = simplify_with_current_value
(exp,
space, ndim);

3814

if (! increment_current_value
(space, ndim))

3815

break
;

3816

}

3817

if (i != total - 1)

3818

abort ();


3790
行的
ndim

表示
space

被使用的元素数目,在
3805
行的
total

则显示了所需的
rtx
对象的数目。在
3803
行,
space


current_value

域被初始化为
values

的第一个元素。
test_for_current_value

为这个测试构建初始化表达式。

4034

static
rtx

4035

test_for_current_value

(struct
dimension
*space, int
ndim)

in genattrtab.c

4036

{

4037

int i;

4038

rtx exp = true_rtx

;

4039

4040

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

4041

exp = insert_right_side
(AND, exp, XEXP
(space[i].current_value, 0),

4042

-2, -2);

4043

4044

return
exp;

4045

}

注意实际上
current_value

总是指向
exp

当前未被处理的部分。因此
condtest

数组穷举了所有的测试表达式。接着
simplify_with_current_value

开始约简表达式
exp



4052

static
rtx

4053

simplify_with_current_value

(rtx exp, struct
dimension
*space, int
ndim)
in genattrtab.c

4054

{

4055

int i;

4056

rtx x;

4057

4058

/* Mark each
current value as TRUE.

*/

4059

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

4060

{

4061

x = XEXP
(space[i].current_value, 0);

4062

if (GET_CODE (x) == EQ_ATTR)

4063

ATTR_EQ_ATTR_P
(x) = 0;

4064

}

4065

4066

exp = simplify_with_current_value_aux
(exp);

4067

4068

/* Change each
current value back to FALSE.

*/

4069

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

4070

{

4071

x = XEXP
(space[i].current_value, 0);

4072

if (GET_CODE (x) == EQ_ATTR)

4073

ATTR_EQ_ATTR_P
(x) = 1;

4074

}

4075

4076

return
exp;

4077

}


find_and_mark_used_attributes

中,在构建这个链表的时候,其节点的
volital

域已经被设置为
1
。在
4061
行,
current_value

总是指向
exp

当前未被处理的部分。如果
current_value

是一个
EQ_ATTR
,我们把
ATTR_EQ_ATTR_P
设为
0
,在下面
simplify_with_current_value_aux


4094
行将依此返回
true_rtx

,假定已经被处理部分的值为
true
,这样才能产生与
condtest

对应的
condval

的值。
EXP
元素的访问次序大致地显示如下(方框内的数字表示序号)。



(注意:由虚线指针指向的是
IOR
对象。
XEXP(exp,
0)
指向的实际上是


52

中的树节点,因为上面的方框是由
rtx
对象及
space
共享的。节点
1
是第一个
IOR
对象的第二个孩子,节点
2
是被第一个
IOR
对象的第一个孩子指向的
IOR
对象的第二个孩子,依此类推。不过,节点
7
与节点
8
之间的关系是
AND
。因此虚线指针给出了访问的次序)


56


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