3.2.3.
Add RTL Template of Patterns into Decision
Sequence
For our define_insn example above, the type passed to add_to_sequence
at line 2467, is RECOG. And the parameter pattern
is the RTL template of the define_insn
pattern. For our example is:
[(set (reg 17)
(compare
(match_operand:DI 0 "nonimmediate_operand" "r,?mr")
(match_operand:DI 1 "const0_operand"
"n,n")))]
767
static
struct
decision
*
768
add_to_sequence
(rtx pattern, struct
decision_head
*last,
in genrecog.c
769
const
char *position, enum
routine_type insn_type, int top)
770
{
771
RTX_CODE code;
772
struct
decision
*this, *sub;
773
struct
decision_test
*test;
774
struct
decision_test
**place;
775
char *subpos;
776
size_t i;
777
const
char *fmt;
778
int depth = strlen (position);
779
int len;
780
enum
machine_mode mode;
781
782
if (depth > max_depth
)
783
max_depth
= depth;
784
785
subpos = xmalloc (depth + 2);
786
strcpy (subpos, position);
787
subpos[depth + 1] = 0;
788
789
sub = this = new_decision
(position, last);
790
place = &this->tests;
791
792
restart:
793
mode = GET_MODE (pattern);
794
code = GET_CODE (pattern);
795
796
switch
(code)
797
{
798
case
PARALLEL:
…
819
break
;
820
821
case
MATCH_PARALLEL:
…
831
case
MATCH_OPERAND:
832
case
MATCH_SCRATCH:
833
case
MATCH_OPERATOR:
834
case
MATCH_INSN:
835
{
…
915
}
916
917
case
MATCH_OP_DUP:
…
932
goto
fini;
933
934
case
MATCH_DUP:
935
case
MATCH_PAR_DUP:
936
code = UNKNOWN;
937
938
test = new_decision_test
(DT_dup,
&place);
939
test->u.dup = XINT (pattern, 0);
940
goto
fini;
941
942
case
ADDRESS:
943
pattern = XEXP (pattern, 0);
944
goto
restart;
945
946
default
:
947
break
;
948
}
When it first enters this function with the SET code, it will go to
the default statement at line 946. At this top level, the parameter position
is a null string (“”). And notice that at line 789, variable sub
and test
point to the same new allocated descision instance. See new_decision
below.
316
static
struct
decision
*
317
new_decision (const
char *position, struct
decision_head *last)
in
genrecog.c
318
{
319
struct
decision
*new = xcalloc (1, sizeof
(struct
decision));
320
321
new->success = *last;
322
new->position = xstrdup (position);
323
new->number = next_number
++;
324
325
last->first = last->last = new;
326
return
new;
327
}
At line 789, the second parameter passed to new_decision
is the variable
head
declared in make_insn_sequence
at line 2421. The new decision is linked at head, as following figure
indicates.
figure
5
: add RTL template into decistion sequence, figure 1
add_to_sequence (continued)
950
fmt = GET_RTX_FORMAT (code);
951
len = GET_RTX_LENGTH (code);
952
953
/* Do tests against the current node
first.
*/
954
for
(i = 0; i < (size_t) len; i++)
955
{
956
if (fmt[i] == 'i')
957
{
958
if (i == 0)
959
{
960
test = new_decision_test
(DT_elt_zero_int, &place);
961
test->u.intval = XINT
(pattern, i);
962
}
963
else if (i == 1)
964
{
965
test = new_decision_test
(DT_elt_one_int, &place);
966
test->u.intval = XINT
(pattern, i);
967
}
968
else
969
abort ();
970
}
971
else if (fmt[i] == 'w')
972
{
973
/* If this value actually fits in an int, we
can use a switch
974
statement here, so indicate that.
*/
975
enum
decision_type
type
976
= ((int) XWINT
(pattern, i) == XWINT
(pattern, i))
977
? DT_elt_zero_wide_safe :
DT_elt_zero_wide;
978
979
if (i != 0)
980
abort ();
981
982
test = new_decision_test
(type,
&place);
983
test->u.intval = XWINT
(pattern, i);
984
}
985
else if (fmt[i] == 'E')
986
{
987
if (i != 0)
988
abort ();
989
990
test = new_decision_test
(DT_veclen,
&place);
991
test->u.veclen = XVECLEN (pattern, i);
992
}
993
}
Here, we again begin handle the pattern according to its format set.
For every element in the format, an instance of decision_test is created via new_decision_test
,
which defines the test being taken.
331
static
struct
decision_test
*
in
genrecog.c
332
new_decision_test
(enum
decision_type
type, struct
decision_test
***pplace)
333
{
334
struct
decision_test
**place = *pplace;
335
struct
decision_test
*test;
336
337
test = xmalloc (sizeof
(*test));
338
test->next = *place;
339
test->type = type;
340
*place = test;
341
342
place = &test->next;
343
*pplace = place;
344
345
return
test;
346
}
Above, here the second parameter passed to new_decision_test
– variable place
is
declared in add_to_sequence
at line 790, which points to the tests
field of variable this
– an instance of decision
created at line 789 in add_to_sequence
,
while this
is linked in the list beginning with variable head
in make_insn_sequence
at line 2421.
The function
looks giddily, let’s look it step by step.
figure
6
: new_decision_test, step 1
Till line 339,
we can get data indicated by above figure. See that the next
field of new created
decision_test points to the old decision_test. Then at line 440, pplace
, place
and this->tests
all point to the new node as inidcating by following figure.
figure
7
: new_decision_test, step 2
In rest of new_decision_test
, place
and pplace
will point to the address of
next
field of created node as shown by following figure.
figure
8
: new_decision_test, step 3
Then for next
node added in (in yellow
), till line
340, we can get following diagram.
figure
9
: new_decision_test, step 4
At last, pplace
, place
will point to the new adding node (in yellow
).
figure
10
: new_decision_test, step 5
From these figures