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
相关文章推荐
- GCC后端及汇编发布(22 续)
- GCC后端及汇编发布(38)
- GCC后端及汇编发布(44)
- GCC后端及汇编发布(4)
- GCC后端及汇编发布(12)
- GCC后端及汇编发布(21)
- GCC后端及汇编发布(27-续)
- GCC后端及汇编发布 当前目录
- GCC后端及汇编发布(33)
- GCC后端及汇编发布(36)
- GCC后端及汇编发布(5)
- GCC后端及汇编发布(45)
- GCC后端及汇编发布(13)
- GCC后端及汇编发布(34)
- GCC后端及汇编发布(46)
- GCC后端及汇编发布(23)
- GCC后端及汇编发布(39)
- GCC后端及汇编发布(47)
- GCC后端及汇编发布(1)
- GCC后端及汇编发布(6)