1 /* Support routines for the various generation passes.
2 Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
3 2010, 2012 Free Software Foundation, Inc.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
12 GCC is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
23 #include "coretypes.h"
30 #include "gensupport.h"
33 /* In case some macros used by files we include need it, define this here. */
38 static struct obstack obstack
;
39 struct obstack
*rtl_obstack
= &obstack
;
41 /* Counter for patterns that generate code: define_insn, define_expand,
42 define_split, define_peephole, and define_peephole2. See read_md_rtx().
43 Any define_insn_and_splits are already in separate queues so that the
44 insn and the splitter get a unique number also. */
45 static int sequence_num
;
47 static int predicable_default
;
48 static const char *predicable_true
;
49 static const char *predicable_false
;
51 static htab_t condition_table
;
53 /* We initially queue all patterns, process the define_insn and
54 define_cond_exec patterns, then return them one at a time. */
61 struct queue_elem
*next
;
62 /* In a DEFINE_INSN that came from a DEFINE_INSN_AND_SPLIT, SPLIT
63 points to the generated DEFINE_SPLIT. */
64 struct queue_elem
*split
;
67 #define MNEMONIC_ATTR_NAME "mnemonic"
68 #define MNEMONIC_HTAB_SIZE 1024
70 static struct queue_elem
*define_attr_queue
;
71 static struct queue_elem
**define_attr_tail
= &define_attr_queue
;
72 static struct queue_elem
*define_pred_queue
;
73 static struct queue_elem
**define_pred_tail
= &define_pred_queue
;
74 static struct queue_elem
*define_insn_queue
;
75 static struct queue_elem
**define_insn_tail
= &define_insn_queue
;
76 static struct queue_elem
*define_cond_exec_queue
;
77 static struct queue_elem
**define_cond_exec_tail
= &define_cond_exec_queue
;
78 static struct queue_elem
*other_queue
;
79 static struct queue_elem
**other_tail
= &other_queue
;
81 static struct queue_elem
*queue_pattern (rtx
, struct queue_elem
***,
84 static void remove_constraints (rtx
);
85 static void process_rtx (rtx
, int);
87 static int is_predicable (struct queue_elem
*);
88 static void identify_predicable_attribute (void);
89 static int n_alternatives (const char *);
90 static void collect_insn_data (rtx
, int *, int *);
91 static rtx
alter_predicate_for_insn (rtx
, int, int, int);
92 static const char *alter_test_for_insn (struct queue_elem
*,
94 static char *shift_output_template (char *, const char *, int);
95 static const char *alter_output_for_insn (struct queue_elem
*,
98 static void process_one_cond_exec (struct queue_elem
*);
99 static void process_define_cond_exec (void);
100 static void init_predicate_table (void);
101 static void record_insn_name (int, const char *);
103 /* Make a version of gen_rtx_CONST_INT so that GEN_INT can be used in
104 the gensupport programs. */
107 gen_rtx_CONST_INT (enum machine_mode
ARG_UNUSED (mode
),
110 rtx rt
= rtx_alloc (CONST_INT
);
116 /* Predicate handling.
118 We construct from the machine description a table mapping each
119 predicate to a list of the rtl codes it can possibly match. The
120 function 'maybe_both_true' uses it to deduce that there are no
121 expressions that can be matches by certain pairs of tree nodes.
122 Also, if a predicate can match only one code, we can hardwire that
123 code into the node testing the predicate.
125 Some predicates are flagged as special. validate_pattern will not
126 warn about modeless match_operand expressions if they have a
127 special predicate. Predicates that allow only constants are also
128 treated as special, for this purpose.
130 validate_pattern will warn about predicates that allow non-lvalues
131 when they appear in destination operands.
133 Calculating the set of rtx codes that can possibly be accepted by a
134 predicate expression EXP requires a three-state logic: any given
135 subexpression may definitively accept a code C (Y), definitively
136 reject a code C (N), or may have an indeterminate effect (I). N
137 and I is N; Y or I is Y; Y and I, N or I are both I. Here are full
148 We represent Y with 1, N with 0, I with 2. If any code is left in
149 an I state by the complete expression, we must assume that that
150 code can be accepted. */
156 #define TRISTATE_AND(a,b) \
157 ((a) == I ? ((b) == N ? N : I) : \
158 (b) == I ? ((a) == N ? N : I) : \
161 #define TRISTATE_OR(a,b) \
162 ((a) == I ? ((b) == Y ? Y : I) : \
163 (b) == I ? ((a) == Y ? Y : I) : \
166 #define TRISTATE_NOT(a) \
167 ((a) == I ? I : !(a))
169 /* 0 means no warning about that code yet, 1 means warned. */
170 static char did_you_mean_codes
[NUM_RTX_CODE
];
172 /* Recursively calculate the set of rtx codes accepted by the
173 predicate expression EXP, writing the result to CODES. LINENO is
174 the line number on which the directive containing EXP appeared. */
177 compute_predicate_codes (rtx exp
, int lineno
, char codes
[NUM_RTX_CODE
])
179 char op0_codes
[NUM_RTX_CODE
];
180 char op1_codes
[NUM_RTX_CODE
];
181 char op2_codes
[NUM_RTX_CODE
];
184 switch (GET_CODE (exp
))
187 compute_predicate_codes (XEXP (exp
, 0), lineno
, op0_codes
);
188 compute_predicate_codes (XEXP (exp
, 1), lineno
, op1_codes
);
189 for (i
= 0; i
< NUM_RTX_CODE
; i
++)
190 codes
[i
] = TRISTATE_AND (op0_codes
[i
], op1_codes
[i
]);
194 compute_predicate_codes (XEXP (exp
, 0), lineno
, op0_codes
);
195 compute_predicate_codes (XEXP (exp
, 1), lineno
, op1_codes
);
196 for (i
= 0; i
< NUM_RTX_CODE
; i
++)
197 codes
[i
] = TRISTATE_OR (op0_codes
[i
], op1_codes
[i
]);
200 compute_predicate_codes (XEXP (exp
, 0), lineno
, op0_codes
);
201 for (i
= 0; i
< NUM_RTX_CODE
; i
++)
202 codes
[i
] = TRISTATE_NOT (op0_codes
[i
]);
206 /* a ? b : c accepts the same codes as (a & b) | (!a & c). */
207 compute_predicate_codes (XEXP (exp
, 0), lineno
, op0_codes
);
208 compute_predicate_codes (XEXP (exp
, 1), lineno
, op1_codes
);
209 compute_predicate_codes (XEXP (exp
, 2), lineno
, op2_codes
);
210 for (i
= 0; i
< NUM_RTX_CODE
; i
++)
211 codes
[i
] = TRISTATE_OR (TRISTATE_AND (op0_codes
[i
], op1_codes
[i
]),
212 TRISTATE_AND (TRISTATE_NOT (op0_codes
[i
]),
217 /* MATCH_CODE allows a specified list of codes. However, if it
218 does not apply to the top level of the expression, it does not
219 constrain the set of codes for the top level. */
220 if (XSTR (exp
, 1)[0] != '\0')
222 memset (codes
, Y
, NUM_RTX_CODE
);
226 memset (codes
, N
, NUM_RTX_CODE
);
228 const char *next_code
= XSTR (exp
, 0);
231 if (*next_code
== '\0')
233 error_with_line (lineno
, "empty match_code expression");
237 while ((code
= scan_comma_elt (&next_code
)) != 0)
239 size_t n
= next_code
- code
;
242 for (i
= 0; i
< NUM_RTX_CODE
; i
++)
243 if (!strncmp (code
, GET_RTX_NAME (i
), n
)
244 && GET_RTX_NAME (i
)[n
] == '\0')
252 error_with_line (lineno
,
253 "match_code \"%.*s\" matches nothing",
255 for (i
= 0; i
< NUM_RTX_CODE
; i
++)
256 if (!strncasecmp (code
, GET_RTX_NAME (i
), n
)
257 && GET_RTX_NAME (i
)[n
] == '\0'
258 && !did_you_mean_codes
[i
])
260 did_you_mean_codes
[i
] = 1;
261 message_with_line (lineno
, "(did you mean \"%s\"?)",
270 /* MATCH_OPERAND disallows the set of codes that the named predicate
271 disallows, and is indeterminate for the codes that it does allow. */
273 struct pred_data
*p
= lookup_predicate (XSTR (exp
, 1));
276 error_with_line (lineno
, "reference to unknown predicate '%s'",
280 for (i
= 0; i
< NUM_RTX_CODE
; i
++)
281 codes
[i
] = p
->codes
[i
] ? I
: N
;
287 /* (match_test WHATEVER) is completely indeterminate. */
288 memset (codes
, I
, NUM_RTX_CODE
);
292 error_with_line (lineno
,
293 "'%s' cannot be used in a define_predicate expression",
294 GET_RTX_NAME (GET_CODE (exp
)));
295 memset (codes
, I
, NUM_RTX_CODE
);
304 /* Return true if NAME is a valid predicate name. */
307 valid_predicate_name_p (const char *name
)
311 if (!ISALPHA (name
[0]) && name
[0] != '_')
313 for (p
= name
+ 1; *p
; p
++)
314 if (!ISALNUM (*p
) && *p
!= '_')
319 /* Process define_predicate directive DESC, which appears on line number
320 LINENO. Compute the set of codes that can be matched, and record this
321 as a known predicate. */
324 process_define_predicate (rtx desc
, int lineno
)
326 struct pred_data
*pred
;
327 char codes
[NUM_RTX_CODE
];
330 if (!valid_predicate_name_p (XSTR (desc
, 0)))
332 error_with_line (lineno
,
333 "%s: predicate name must be a valid C function name",
338 pred
= XCNEW (struct pred_data
);
339 pred
->name
= XSTR (desc
, 0);
340 pred
->exp
= XEXP (desc
, 1);
341 pred
->c_block
= XSTR (desc
, 2);
342 if (GET_CODE (desc
) == DEFINE_SPECIAL_PREDICATE
)
343 pred
->special
= true;
345 compute_predicate_codes (XEXP (desc
, 1), lineno
, codes
);
347 for (i
= 0; i
< NUM_RTX_CODE
; i
++)
349 add_predicate_code (pred
, (enum rtx_code
) i
);
351 add_predicate (pred
);
357 /* Queue PATTERN on LIST_TAIL. Return the address of the new queue
360 static struct queue_elem
*
361 queue_pattern (rtx pattern
, struct queue_elem
***list_tail
,
362 const char *filename
, int lineno
)
364 struct queue_elem
*e
= XNEW(struct queue_elem
);
366 e
->filename
= filename
;
371 *list_tail
= &e
->next
;
375 /* Build a define_attr for an binary attribute with name NAME and
376 possible values "yes" and "no", and queue it. */
378 add_define_attr (const char *name
)
380 struct queue_elem
*e
= XNEW(struct queue_elem
);
381 rtx t1
= rtx_alloc (DEFINE_ATTR
);
383 XSTR (t1
, 1) = "no,yes";
384 XEXP (t1
, 2) = rtx_alloc (CONST_STRING
);
385 XSTR (XEXP (t1
, 2), 0) = "yes";
387 e
->filename
= "built-in";
389 e
->next
= define_attr_queue
;
390 define_attr_queue
= e
;
394 /* Recursively remove constraints from an rtx. */
397 remove_constraints (rtx part
)
400 const char *format_ptr
;
405 if (GET_CODE (part
) == MATCH_OPERAND
)
407 else if (GET_CODE (part
) == MATCH_SCRATCH
)
410 format_ptr
= GET_RTX_FORMAT (GET_CODE (part
));
412 for (i
= 0; i
< GET_RTX_LENGTH (GET_CODE (part
)); i
++)
413 switch (*format_ptr
++)
417 remove_constraints (XEXP (part
, i
));
420 if (XVEC (part
, i
) != NULL
)
421 for (j
= 0; j
< XVECLEN (part
, i
); j
++)
422 remove_constraints (XVECEXP (part
, i
, j
));
427 /* Process a top level rtx in some way, queuing as appropriate. */
430 process_rtx (rtx desc
, int lineno
)
432 switch (GET_CODE (desc
))
435 queue_pattern (desc
, &define_insn_tail
, read_md_filename
, lineno
);
438 case DEFINE_COND_EXEC
:
439 queue_pattern (desc
, &define_cond_exec_tail
, read_md_filename
, lineno
);
443 case DEFINE_ENUM_ATTR
:
444 queue_pattern (desc
, &define_attr_tail
, read_md_filename
, lineno
);
447 case DEFINE_PREDICATE
:
448 case DEFINE_SPECIAL_PREDICATE
:
449 process_define_predicate (desc
, lineno
);
452 case DEFINE_CONSTRAINT
:
453 case DEFINE_REGISTER_CONSTRAINT
:
454 case DEFINE_MEMORY_CONSTRAINT
:
455 case DEFINE_ADDRESS_CONSTRAINT
:
456 queue_pattern (desc
, &define_pred_tail
, read_md_filename
, lineno
);
459 case DEFINE_INSN_AND_SPLIT
:
461 const char *split_cond
;
465 struct queue_elem
*insn_elem
;
466 struct queue_elem
*split_elem
;
468 /* Create a split with values from the insn_and_split. */
469 split
= rtx_alloc (DEFINE_SPLIT
);
471 i
= XVECLEN (desc
, 1);
472 XVEC (split
, 0) = rtvec_alloc (i
);
475 XVECEXP (split
, 0, i
) = copy_rtx (XVECEXP (desc
, 1, i
));
476 remove_constraints (XVECEXP (split
, 0, i
));
479 /* If the split condition starts with "&&", append it to the
480 insn condition to create the new split condition. */
481 split_cond
= XSTR (desc
, 4);
482 if (split_cond
[0] == '&' && split_cond
[1] == '&')
484 copy_md_ptr_loc (split_cond
+ 2, split_cond
);
485 split_cond
= join_c_conditions (XSTR (desc
, 2), split_cond
+ 2);
487 XSTR (split
, 1) = split_cond
;
488 XVEC (split
, 2) = XVEC (desc
, 5);
489 XSTR (split
, 3) = XSTR (desc
, 6);
491 /* Fix up the DEFINE_INSN. */
492 attr
= XVEC (desc
, 7);
493 PUT_CODE (desc
, DEFINE_INSN
);
494 XVEC (desc
, 4) = attr
;
498 = queue_pattern (desc
, &define_insn_tail
, read_md_filename
,
501 = queue_pattern (split
, &other_tail
, read_md_filename
, lineno
);
502 insn_elem
->split
= split_elem
;
507 queue_pattern (desc
, &other_tail
, read_md_filename
, lineno
);
512 /* Return true if attribute PREDICABLE is true for ELEM, which holds
516 is_predicable (struct queue_elem
*elem
)
518 rtvec vec
= XVEC (elem
->data
, 4);
523 return predicable_default
;
525 for (i
= GET_NUM_ELEM (vec
) - 1; i
>= 0; --i
)
527 rtx sub
= RTVEC_ELT (vec
, i
);
528 switch (GET_CODE (sub
))
531 if (strcmp (XSTR (sub
, 0), "predicable") == 0)
533 value
= XSTR (sub
, 1);
538 case SET_ATTR_ALTERNATIVE
:
539 if (strcmp (XSTR (sub
, 0), "predicable") == 0)
541 error_with_line (elem
->lineno
,
542 "multiple alternatives for `predicable'");
548 if (GET_CODE (SET_DEST (sub
)) != ATTR
549 || strcmp (XSTR (SET_DEST (sub
), 0), "predicable") != 0)
552 if (GET_CODE (sub
) == CONST_STRING
)
554 value
= XSTR (sub
, 0);
558 /* ??? It would be possible to handle this if we really tried.
559 It's not easy though, and I'm not going to bother until it
560 really proves necessary. */
561 error_with_line (elem
->lineno
,
562 "non-constant value for `predicable'");
570 return predicable_default
;
573 /* Find out which value we're looking at. Multiple alternatives means at
574 least one is predicable. */
575 if (strchr (value
, ',') != NULL
)
577 if (strcmp (value
, predicable_true
) == 0)
579 if (strcmp (value
, predicable_false
) == 0)
582 error_with_line (elem
->lineno
,
583 "unknown value `%s' for `predicable' attribute", value
);
587 /* Examine the attribute "predicable"; discover its boolean values
591 identify_predicable_attribute (void)
593 struct queue_elem
*elem
;
594 char *p_true
, *p_false
;
597 /* Look for the DEFINE_ATTR for `predicable', which must exist. */
598 for (elem
= define_attr_queue
; elem
; elem
= elem
->next
)
599 if (strcmp (XSTR (elem
->data
, 0), "predicable") == 0)
602 error_with_line (define_cond_exec_queue
->lineno
,
603 "attribute `predicable' not defined");
607 value
= XSTR (elem
->data
, 1);
608 p_false
= xstrdup (value
);
609 p_true
= strchr (p_false
, ',');
610 if (p_true
== NULL
|| strchr (++p_true
, ',') != NULL
)
612 error_with_line (elem
->lineno
, "attribute `predicable' is not a boolean");
618 predicable_true
= p_true
;
619 predicable_false
= p_false
;
621 switch (GET_CODE (XEXP (elem
->data
, 2)))
624 value
= XSTR (XEXP (elem
->data
, 2), 0);
628 error_with_line (elem
->lineno
, "attribute `predicable' cannot be const");
633 error_with_line (elem
->lineno
,
634 "attribute `predicable' must have a constant default");
639 if (strcmp (value
, p_true
) == 0)
640 predicable_default
= 1;
641 else if (strcmp (value
, p_false
) == 0)
642 predicable_default
= 0;
645 error_with_line (elem
->lineno
,
646 "unknown value `%s' for `predicable' attribute", value
);
651 /* Return the number of alternatives in constraint S. */
654 n_alternatives (const char *s
)
665 /* Determine how many alternatives there are in INSN, and how many
669 collect_insn_data (rtx pattern
, int *palt
, int *pmax
)
675 code
= GET_CODE (pattern
);
679 i
= n_alternatives (XSTR (pattern
, 2));
680 *palt
= (i
> *palt
? i
: *palt
);
686 i
= XINT (pattern
, 0);
695 fmt
= GET_RTX_FORMAT (code
);
696 len
= GET_RTX_LENGTH (code
);
697 for (i
= 0; i
< len
; i
++)
702 collect_insn_data (XEXP (pattern
, i
), palt
, pmax
);
706 if (XVEC (pattern
, i
) == NULL
)
710 for (j
= XVECLEN (pattern
, i
) - 1; j
>= 0; --j
)
711 collect_insn_data (XVECEXP (pattern
, i
, j
), palt
, pmax
);
714 case 'i': case 'w': case '0': case 's': case 'S': case 'T':
724 alter_predicate_for_insn (rtx pattern
, int alt
, int max_op
, int lineno
)
730 code
= GET_CODE (pattern
);
735 const char *c
= XSTR (pattern
, 2);
737 if (n_alternatives (c
) != 1)
739 error_with_line (lineno
, "too many alternatives for operand %d",
744 /* Replicate C as needed to fill out ALT alternatives. */
745 if (c
&& *c
&& alt
> 1)
747 size_t c_len
= strlen (c
);
748 size_t len
= alt
* (c_len
+ 1);
749 char *new_c
= XNEWVEC(char, len
);
751 memcpy (new_c
, c
, c_len
);
752 for (i
= 1; i
< alt
; ++i
)
754 new_c
[i
* (c_len
+ 1) - 1] = ',';
755 memcpy (&new_c
[i
* (c_len
+ 1)], c
, c_len
);
757 new_c
[len
- 1] = '\0';
758 XSTR (pattern
, 2) = new_c
;
766 XINT (pattern
, 0) += max_op
;
773 fmt
= GET_RTX_FORMAT (code
);
774 len
= GET_RTX_LENGTH (code
);
775 for (i
= 0; i
< len
; i
++)
782 r
= alter_predicate_for_insn (XEXP (pattern
, i
), alt
,
789 for (j
= XVECLEN (pattern
, i
) - 1; j
>= 0; --j
)
791 r
= alter_predicate_for_insn (XVECEXP (pattern
, i
, j
),
792 alt
, max_op
, lineno
);
798 case 'i': case 'w': case '0': case 's':
810 alter_test_for_insn (struct queue_elem
*ce_elem
,
811 struct queue_elem
*insn_elem
)
813 return join_c_conditions (XSTR (ce_elem
->data
, 1),
814 XSTR (insn_elem
->data
, 2));
817 /* Modify VAL, which is an attribute expression for the "enabled" attribute,
818 to take "ce_enabled" into account. Return the new expression. */
820 modify_attr_enabled_ce (rtx val
)
824 eq_attr
= rtx_alloc (EQ_ATTR
);
825 ite
= rtx_alloc (IF_THEN_ELSE
);
826 str
= rtx_alloc (CONST_STRING
);
828 XSTR (eq_attr
, 0) = "ce_enabled";
829 XSTR (eq_attr
, 1) = "yes";
830 XSTR (str
, 0) = "no";
831 XEXP (ite
, 0) = eq_attr
;
838 /* Alter the attribute vector of INSN, which is a COND_EXEC variant created
839 from a define_insn pattern. We must modify the "predicable" attribute
840 to be named "ce_enabled", and also change any "enabled" attribute that's
841 present so that it takes ce_enabled into account.
842 We rely on the fact that INSN was created with copy_rtx, and modify data
846 alter_attrs_for_insn (rtx insn
)
848 static bool global_changes_made
= false;
849 rtvec vec
= XVEC (insn
, 4);
853 int predicable_idx
= -1;
854 int enabled_idx
= -1;
860 num_elem
= GET_NUM_ELEM (vec
);
861 for (i
= num_elem
- 1; i
>= 0; --i
)
863 rtx sub
= RTVEC_ELT (vec
, i
);
864 switch (GET_CODE (sub
))
867 if (strcmp (XSTR (sub
, 0), "predicable") == 0)
870 XSTR (sub
, 0) = "ce_enabled";
872 else if (strcmp (XSTR (sub
, 0), "enabled") == 0)
875 XSTR (sub
, 0) = "nonce_enabled";
879 case SET_ATTR_ALTERNATIVE
:
880 if (strcmp (XSTR (sub
, 0), "predicable") == 0)
881 /* We already give an error elsewhere. */
883 else if (strcmp (XSTR (sub
, 0), "enabled") == 0)
886 XSTR (sub
, 0) = "nonce_enabled";
891 if (GET_CODE (SET_DEST (sub
)) != ATTR
)
893 if (strcmp (XSTR (SET_DEST (sub
), 0), "predicable") == 0)
896 if (GET_CODE (sub
) == CONST_STRING
)
899 XSTR (sub
, 0) = "ce_enabled";
902 /* We already give an error elsewhere. */
906 if (strcmp (XSTR (SET_DEST (sub
), 0), "enabled") == 0)
909 XSTR (SET_DEST (sub
), 0) = "nonce_enabled";
917 if (predicable_idx
== -1)
920 if (!global_changes_made
)
922 struct queue_elem
*elem
;
924 global_changes_made
= true;
925 add_define_attr ("ce_enabled");
926 add_define_attr ("nonce_enabled");
928 for (elem
= define_attr_queue
; elem
; elem
= elem
->next
)
929 if (strcmp (XSTR (elem
->data
, 0), "enabled") == 0)
932 = modify_attr_enabled_ce (XEXP (elem
->data
, 2));
935 if (enabled_idx
== -1)
938 new_vec
= rtvec_alloc (num_elem
+ 1);
939 for (i
= 0; i
< num_elem
; i
++)
940 RTVEC_ELT (new_vec
, i
) = RTVEC_ELT (vec
, i
);
941 val
= rtx_alloc (IF_THEN_ELSE
);
942 XEXP (val
, 0) = rtx_alloc (EQ_ATTR
);
943 XEXP (val
, 1) = rtx_alloc (CONST_STRING
);
944 XEXP (val
, 2) = rtx_alloc (CONST_STRING
);
945 XSTR (XEXP (val
, 0), 0) = "nonce_enabled";
946 XSTR (XEXP (val
, 0), 1) = "yes";
947 XSTR (XEXP (val
, 1), 0) = "yes";
948 XSTR (XEXP (val
, 2), 0) = "no";
949 set
= rtx_alloc (SET
);
950 SET_DEST (set
) = rtx_alloc (ATTR
);
951 XSTR (SET_DEST (set
), 0) = "enabled";
952 SET_SRC (set
) = modify_attr_enabled_ce (val
);
953 RTVEC_ELT (new_vec
, i
) = set
;
954 XVEC (insn
, 4) = new_vec
;
957 /* Adjust all of the operand numbers in SRC to match the shift they'll
958 get from an operand displacement of DISP. Return a pointer after the
962 shift_output_template (char *dest
, const char *src
, int disp
)
971 if (ISDIGIT ((unsigned char) c
))
973 else if (ISALPHA (c
))
986 alter_output_for_insn (struct queue_elem
*ce_elem
,
987 struct queue_elem
*insn_elem
,
990 const char *ce_out
, *insn_out
;
992 size_t len
, ce_len
, insn_len
;
994 /* ??? Could coordinate with genoutput to not duplicate code here. */
996 ce_out
= XSTR (ce_elem
->data
, 2);
997 insn_out
= XTMPL (insn_elem
->data
, 3);
998 if (!ce_out
|| *ce_out
== '\0')
1001 ce_len
= strlen (ce_out
);
1002 insn_len
= strlen (insn_out
);
1004 if (*insn_out
== '*')
1005 /* You must take care of the predicate yourself. */
1008 if (*insn_out
== '@')
1010 len
= (ce_len
+ 1) * alt
+ insn_len
+ 1;
1011 p
= result
= XNEWVEC(char, len
);
1017 while (ISSPACE ((unsigned char) *insn_out
));
1019 if (*insn_out
!= '#')
1021 p
= shift_output_template (p
, ce_out
, max_op
);
1027 while (*insn_out
&& *insn_out
!= '\n');
1034 len
= ce_len
+ 1 + insn_len
+ 1;
1035 result
= XNEWVEC (char, len
);
1037 p
= shift_output_template (result
, ce_out
, max_op
);
1039 memcpy (p
, insn_out
, insn_len
+ 1);
1045 /* Replicate insns as appropriate for the given DEFINE_COND_EXEC. */
1048 process_one_cond_exec (struct queue_elem
*ce_elem
)
1050 struct queue_elem
*insn_elem
;
1051 for (insn_elem
= define_insn_queue
; insn_elem
; insn_elem
= insn_elem
->next
)
1053 int alternatives
, max_operand
;
1054 rtx pred
, insn
, pattern
, split
;
1058 if (! is_predicable (insn_elem
))
1063 collect_insn_data (insn_elem
->data
, &alternatives
, &max_operand
);
1066 if (XVECLEN (ce_elem
->data
, 0) != 1)
1068 error_with_line (ce_elem
->lineno
, "too many patterns in predicate");
1072 pred
= copy_rtx (XVECEXP (ce_elem
->data
, 0, 0));
1073 pred
= alter_predicate_for_insn (pred
, alternatives
, max_operand
,
1078 /* Construct a new pattern for the new insn. */
1079 insn
= copy_rtx (insn_elem
->data
);
1080 new_name
= XNEWVAR (char, strlen
XSTR (insn_elem
->data
, 0) + 4);
1081 sprintf (new_name
, "*p %s", XSTR (insn_elem
->data
, 0));
1082 XSTR (insn
, 0) = new_name
;
1083 pattern
= rtx_alloc (COND_EXEC
);
1084 XEXP (pattern
, 0) = pred
;
1085 if (XVECLEN (insn
, 1) == 1)
1087 XEXP (pattern
, 1) = XVECEXP (insn
, 1, 0);
1088 XVECEXP (insn
, 1, 0) = pattern
;
1089 PUT_NUM_ELEM (XVEC (insn
, 1), 1);
1093 XEXP (pattern
, 1) = rtx_alloc (PARALLEL
);
1094 XVEC (XEXP (pattern
, 1), 0) = XVEC (insn
, 1);
1095 XVEC (insn
, 1) = rtvec_alloc (1);
1096 XVECEXP (insn
, 1, 0) = pattern
;
1099 XSTR (insn
, 2) = alter_test_for_insn (ce_elem
, insn_elem
);
1100 XTMPL (insn
, 3) = alter_output_for_insn (ce_elem
, insn_elem
,
1101 alternatives
, max_operand
);
1102 alter_attrs_for_insn (insn
);
1104 /* Put the new pattern on the `other' list so that it
1105 (a) is not reprocessed by other define_cond_exec patterns
1106 (b) appears after all normal define_insn patterns.
1108 ??? B is debatable. If one has normal insns that match
1109 cond_exec patterns, they will be preferred over these
1110 generated patterns. Whether this matters in practice, or if
1111 it's a good thing, or whether we should thread these new
1112 patterns into the define_insn chain just after their generator
1113 is something we'll have to experiment with. */
1115 queue_pattern (insn
, &other_tail
, insn_elem
->filename
,
1118 if (!insn_elem
->split
)
1121 /* If the original insn came from a define_insn_and_split,
1122 generate a new split to handle the predicated insn. */
1123 split
= copy_rtx (insn_elem
->split
->data
);
1124 /* Predicate the pattern matched by the split. */
1125 pattern
= rtx_alloc (COND_EXEC
);
1126 XEXP (pattern
, 0) = pred
;
1127 if (XVECLEN (split
, 0) == 1)
1129 XEXP (pattern
, 1) = XVECEXP (split
, 0, 0);
1130 XVECEXP (split
, 0, 0) = pattern
;
1131 PUT_NUM_ELEM (XVEC (split
, 0), 1);
1135 XEXP (pattern
, 1) = rtx_alloc (PARALLEL
);
1136 XVEC (XEXP (pattern
, 1), 0) = XVEC (split
, 0);
1137 XVEC (split
, 0) = rtvec_alloc (1);
1138 XVECEXP (split
, 0, 0) = pattern
;
1140 /* Predicate all of the insns generated by the split. */
1141 for (i
= 0; i
< XVECLEN (split
, 2); i
++)
1143 pattern
= rtx_alloc (COND_EXEC
);
1144 XEXP (pattern
, 0) = pred
;
1145 XEXP (pattern
, 1) = XVECEXP (split
, 2, i
);
1146 XVECEXP (split
, 2, i
) = pattern
;
1148 /* Add the new split to the queue. */
1149 queue_pattern (split
, &other_tail
, read_md_filename
,
1150 insn_elem
->split
->lineno
);
1154 /* If we have any DEFINE_COND_EXEC patterns, expand the DEFINE_INSN
1155 patterns appropriately. */
1158 process_define_cond_exec (void)
1160 struct queue_elem
*elem
;
1162 identify_predicable_attribute ();
1166 for (elem
= define_cond_exec_queue
; elem
; elem
= elem
->next
)
1167 process_one_cond_exec (elem
);
1170 /* A read_md_files callback for reading an rtx. */
1173 rtx_handle_directive (int lineno
, const char *rtx_name
)
1177 if (read_rtx (rtx_name
, &queue
))
1178 for (x
= queue
; x
; x
= XEXP (x
, 1))
1179 process_rtx (XEXP (x
, 0), lineno
);
1182 /* Comparison function for the mnemonic hash table. */
1185 htab_eq_string (const void *s1
, const void *s2
)
1187 return strcmp ((const char*)s1
, (const char*)s2
) == 0;
1190 /* Add mnemonic STR with length LEN to the mnemonic hash table
1191 MNEMONIC_HTAB. A trailing zero end character is appendend to STR
1192 and a permanent heap copy of STR is created. */
1195 add_mnemonic_string (htab_t mnemonic_htab
, const char *str
, int len
)
1199 char *str_zero
= (char*)alloca (len
+ 1);
1201 memcpy (str_zero
, str
, len
);
1202 str_zero
[len
] = '\0';
1204 slot
= htab_find_slot (mnemonic_htab
, str_zero
, INSERT
);
1209 /* Not found; create a permanent copy and add it to the hash table. */
1210 new_str
= XNEWVAR (char, len
+ 1);
1211 memcpy (new_str
, str_zero
, len
+ 1);
1215 /* Scan INSN for mnemonic strings and add them to the mnemonic hash
1216 table in MNEMONIC_HTAB.
1218 The mnemonics cannot be found if they are emitted using C code.
1220 If a mnemonic string contains ';' or a newline the string assumed
1221 to consist of more than a single instruction. The attribute value
1222 will then be set to the user defined default value. */
1225 gen_mnemonic_setattr (htab_t mnemonic_htab
, rtx insn
)
1227 const char *template_code
, *cp
;
1234 template_code
= XTMPL (insn
, 3);
1236 /* Skip patterns which use C code to emit the template. */
1237 if (template_code
[0] == '*')
1240 if (template_code
[0] == '@')
1241 cp
= &template_code
[1];
1243 cp
= &template_code
[0];
1247 const char *ep
, *sp
;
1250 while (ISSPACE (*cp
))
1253 for (ep
= sp
= cp
; !IS_VSPACE (*ep
) && *ep
!= '\0'; ++ep
)
1258 obstack_1grow (&string_obstack
, ',');
1260 while (cp
< sp
&& ((*cp
>= '0' && *cp
<= '9')
1261 || (*cp
>= 'a' && *cp
<= 'z')))
1264 obstack_1grow (&string_obstack
, *cp
);
1271 if (*cp
== ';' || (*cp
== '\\' && cp
[1] == 'n'))
1273 /* Don't set a value if there are more than one
1274 instruction in the string. */
1275 obstack_next_free (&string_obstack
) =
1276 obstack_next_free (&string_obstack
) - size
;
1285 obstack_1grow (&string_obstack
, '*');
1287 add_mnemonic_string (mnemonic_htab
,
1288 obstack_next_free (&string_obstack
) - size
,
1293 /* An insn definition might emit an empty string. */
1294 if (obstack_object_size (&string_obstack
) == 0)
1297 obstack_1grow (&string_obstack
, '\0');
1299 set_attr
= rtx_alloc (SET_ATTR
);
1300 XSTR (set_attr
, 1) = XOBFINISH (&string_obstack
, char *);
1301 attr_name
= XNEWVAR (char, strlen (MNEMONIC_ATTR_NAME
) + 1);
1302 strcpy (attr_name
, MNEMONIC_ATTR_NAME
);
1303 XSTR (set_attr
, 0) = attr_name
;
1305 if (!XVEC (insn
, 4))
1308 vec_len
= XVECLEN (insn
, 4);
1310 new_vec
= rtvec_alloc (vec_len
+ 1);
1311 for (i
= 0; i
< vec_len
; i
++)
1312 RTVEC_ELT (new_vec
, i
) = XVECEXP (insn
, 4, i
);
1313 RTVEC_ELT (new_vec
, vec_len
) = set_attr
;
1314 XVEC (insn
, 4) = new_vec
;
1317 /* This function is called for the elements in the mnemonic hashtable
1318 and generates a comma separated list of the mnemonics. */
1321 mnemonic_htab_callback (void **slot
, void *info ATTRIBUTE_UNUSED
)
1323 obstack_grow (&string_obstack
, (char*)*slot
, strlen ((char*)*slot
));
1324 obstack_1grow (&string_obstack
, ',');
1328 /* Generate (set_attr "mnemonic" "..") RTXs and append them to every
1329 insn definition in case the back end requests it by defining the
1330 mnemonic attribute. The values for the attribute will be extracted
1331 from the output patterns of the insn definitions as far as
1335 gen_mnemonic_attr (void)
1337 struct queue_elem
*elem
;
1338 rtx mnemonic_attr
= NULL
;
1339 htab_t mnemonic_htab
;
1340 const char *str
, *p
;
1346 /* Look for the DEFINE_ATTR for `mnemonic'. */
1347 for (elem
= define_attr_queue
; elem
!= *define_attr_tail
; elem
= elem
->next
)
1348 if (GET_CODE (elem
->data
) == DEFINE_ATTR
1349 && strcmp (XSTR (elem
->data
, 0), MNEMONIC_ATTR_NAME
) == 0)
1351 mnemonic_attr
= elem
->data
;
1355 /* A (define_attr "mnemonic" "...") indicates that the back-end
1356 wants a mnemonic attribute to be generated. */
1360 mnemonic_htab
= htab_create_alloc (MNEMONIC_HTAB_SIZE
, htab_hash_string
,
1361 htab_eq_string
, 0, xcalloc
, free
);
1363 for (elem
= define_insn_queue
; elem
; elem
= elem
->next
)
1365 rtx insn
= elem
->data
;
1368 /* Check if the insn definition already has
1369 (set_attr "mnemonic" ...). */
1371 for (i
= 0; i
< XVECLEN (insn
, 4); i
++)
1372 if (strcmp (XSTR (XVECEXP (insn
, 4, i
), 0), MNEMONIC_ATTR_NAME
) == 0)
1379 gen_mnemonic_setattr (mnemonic_htab
, insn
);
1382 /* Add the user defined values to the hash table. */
1383 str
= XSTR (mnemonic_attr
, 1);
1384 while ((p
= scan_comma_elt (&str
)) != NULL
)
1385 add_mnemonic_string (mnemonic_htab
, p
, str
- p
);
1387 htab_traverse (mnemonic_htab
, mnemonic_htab_callback
, NULL
);
1389 /* Replace the last ',' with the zero end character. */
1390 *((char *)obstack_next_free (&string_obstack
) - 1) = '\0';
1391 XSTR (mnemonic_attr
, 1) = XOBFINISH (&string_obstack
, char *);
1394 /* The entry point for initializing the reader. */
1397 init_rtx_reader_args_cb (int argc
, char **argv
,
1398 bool (*parse_opt
) (const char *))
1400 /* Prepare to read input. */
1401 condition_table
= htab_create (500, hash_c_test
, cmp_c_test
, NULL
);
1402 init_predicate_table ();
1403 obstack_init (rtl_obstack
);
1405 /* Start at 1, to make 0 available for CODE_FOR_nothing. */
1408 read_md_files (argc
, argv
, parse_opt
, rtx_handle_directive
);
1410 /* Process define_cond_exec patterns. */
1411 if (define_cond_exec_queue
!= NULL
)
1412 process_define_cond_exec ();
1414 if (define_attr_queue
!= NULL
)
1415 gen_mnemonic_attr ();
1420 /* Programs that don't have their own options can use this entry point
1423 init_rtx_reader_args (int argc
, char **argv
)
1425 return init_rtx_reader_args_cb (argc
, argv
, 0);
1428 /* The entry point for reading a single rtx from an md file. Return
1429 the rtx, or NULL if the md file has been fully processed.
1430 Return the line where the rtx was found in LINENO.
1431 Return the number of code generating rtx'en read since the start
1432 of the md file in SEQNR. */
1435 read_md_rtx (int *lineno
, int *seqnr
)
1437 struct queue_elem
**queue
, *elem
;
1442 /* Read all patterns from a given queue before moving on to the next. */
1443 if (define_attr_queue
!= NULL
)
1444 queue
= &define_attr_queue
;
1445 else if (define_pred_queue
!= NULL
)
1446 queue
= &define_pred_queue
;
1447 else if (define_insn_queue
!= NULL
)
1448 queue
= &define_insn_queue
;
1449 else if (other_queue
!= NULL
)
1450 queue
= &other_queue
;
1455 *queue
= elem
->next
;
1457 read_md_filename
= elem
->filename
;
1458 *lineno
= elem
->lineno
;
1459 *seqnr
= sequence_num
;
1463 /* Discard insn patterns which we know can never match (because
1464 their C test is provably always false). If insn_elision is
1465 false, our caller needs to see all the patterns. Note that the
1466 elided patterns are never counted by the sequence numbering; it
1467 is the caller's responsibility, when insn_elision is false, not
1468 to use elided pattern numbers for anything. */
1469 switch (GET_CODE (desc
))
1473 if (maybe_eval_c_test (XSTR (desc
, 2)) != 0)
1475 else if (insn_elision
)
1478 /* *seqnr is used here so the name table will match caller's
1479 idea of insn numbering, whether or not elision is active. */
1480 record_insn_name (*seqnr
, XSTR (desc
, 0));
1484 case DEFINE_PEEPHOLE
:
1485 case DEFINE_PEEPHOLE2
:
1486 if (maybe_eval_c_test (XSTR (desc
, 1)) != 0)
1488 else if (insn_elision
)
1499 /* Helper functions for insn elision. */
1501 /* Compute a hash function of a c_test structure, which is keyed
1502 by its ->expr field. */
1504 hash_c_test (const void *x
)
1506 const struct c_test
*a
= (const struct c_test
*) x
;
1507 const unsigned char *base
, *s
= (const unsigned char *) a
->expr
;
1515 while ((c
= *s
++) != '\0')
1517 hash
+= c
+ (c
<< 17);
1522 hash
+= len
+ (len
<< 17);
1528 /* Compare two c_test expression structures. */
1530 cmp_c_test (const void *x
, const void *y
)
1532 const struct c_test
*a
= (const struct c_test
*) x
;
1533 const struct c_test
*b
= (const struct c_test
*) y
;
1535 return !strcmp (a
->expr
, b
->expr
);
1538 /* Given a string representing a C test expression, look it up in the
1539 condition_table and report whether or not its value is known
1540 at compile time. Returns a tristate: 1 for known true, 0 for
1541 known false, -1 for unknown. */
1543 maybe_eval_c_test (const char *expr
)
1545 const struct c_test
*test
;
1546 struct c_test dummy
;
1552 test
= (const struct c_test
*)htab_find (condition_table
, &dummy
);
1558 /* Record the C test expression EXPR in the condition_table, with
1559 value VAL. Duplicates clobber previous entries. */
1562 add_c_test (const char *expr
, int value
)
1564 struct c_test
*test
;
1569 test
= XNEW (struct c_test
);
1571 test
->value
= value
;
1573 *(htab_find_slot (condition_table
, test
, INSERT
)) = test
;
1576 /* For every C test, call CALLBACK with two arguments: a pointer to
1577 the condition structure and INFO. Stops when CALLBACK returns zero. */
1579 traverse_c_tests (htab_trav callback
, void *info
)
1581 if (condition_table
)
1582 htab_traverse (condition_table
, callback
, info
);
1585 /* Helper functions for define_predicate and define_special_predicate
1586 processing. Shared between genrecog.c and genpreds.c. */
1588 static htab_t predicate_table
;
1589 struct pred_data
*first_predicate
;
1590 static struct pred_data
**last_predicate
= &first_predicate
;
1593 hash_struct_pred_data (const void *ptr
)
1595 return htab_hash_string (((const struct pred_data
*)ptr
)->name
);
1599 eq_struct_pred_data (const void *a
, const void *b
)
1601 return !strcmp (((const struct pred_data
*)a
)->name
,
1602 ((const struct pred_data
*)b
)->name
);
1606 lookup_predicate (const char *name
)
1608 struct pred_data key
;
1610 return (struct pred_data
*) htab_find (predicate_table
, &key
);
1613 /* Record that predicate PRED can accept CODE. */
1616 add_predicate_code (struct pred_data
*pred
, enum rtx_code code
)
1618 if (!pred
->codes
[code
])
1621 pred
->codes
[code
] = true;
1623 if (GET_RTX_CLASS (code
) != RTX_CONST_OBJ
)
1624 pred
->allows_non_const
= true;
1631 && code
!= STRICT_LOW_PART
)
1632 pred
->allows_non_lvalue
= true;
1634 if (pred
->num_codes
== 1)
1635 pred
->singleton
= code
;
1636 else if (pred
->num_codes
== 2)
1637 pred
->singleton
= UNKNOWN
;
1642 add_predicate (struct pred_data
*pred
)
1644 void **slot
= htab_find_slot (predicate_table
, pred
, INSERT
);
1647 error ("duplicate predicate definition for '%s'", pred
->name
);
1651 *last_predicate
= pred
;
1652 last_predicate
= &pred
->next
;
1655 /* This array gives the initial content of the predicate table. It
1656 has entries for all predicates defined in recog.c. */
1658 struct std_pred_table
1662 bool allows_const_p
;
1663 RTX_CODE codes
[NUM_RTX_CODE
];
1666 static const struct std_pred_table std_preds
[] = {
1667 {"general_operand", false, true, {SUBREG
, REG
, MEM
}},
1668 {"address_operand", true, true, {SUBREG
, REG
, MEM
, PLUS
, MINUS
, MULT
}},
1669 {"register_operand", false, false, {SUBREG
, REG
}},
1670 {"pmode_register_operand", true, false, {SUBREG
, REG
}},
1671 {"scratch_operand", false, false, {SCRATCH
, REG
}},
1672 {"immediate_operand", false, true, {UNKNOWN
}},
1673 {"const_int_operand", false, false, {CONST_INT
}},
1674 {"const_double_operand", false, false, {CONST_INT
, CONST_DOUBLE
}},
1675 {"nonimmediate_operand", false, false, {SUBREG
, REG
, MEM
}},
1676 {"nonmemory_operand", false, true, {SUBREG
, REG
}},
1677 {"push_operand", false, false, {MEM
}},
1678 {"pop_operand", false, false, {MEM
}},
1679 {"memory_operand", false, false, {SUBREG
, MEM
}},
1680 {"indirect_operand", false, false, {SUBREG
, MEM
}},
1681 {"ordered_comparison_operator", false, false, {EQ
, NE
,
1683 LEU
, LTU
, GEU
, GTU
}},
1684 {"comparison_operator", false, false, {EQ
, NE
,
1691 #define NUM_KNOWN_STD_PREDS ARRAY_SIZE (std_preds)
1693 /* Initialize the table of predicate definitions, starting with
1694 the information we have on generic predicates. */
1697 init_predicate_table (void)
1700 struct pred_data
*pred
;
1702 predicate_table
= htab_create_alloc (37, hash_struct_pred_data
,
1703 eq_struct_pred_data
, 0,
1706 for (i
= 0; i
< NUM_KNOWN_STD_PREDS
; i
++)
1708 pred
= XCNEW (struct pred_data
);
1709 pred
->name
= std_preds
[i
].name
;
1710 pred
->special
= std_preds
[i
].special
;
1712 for (j
= 0; std_preds
[i
].codes
[j
] != 0; j
++)
1713 add_predicate_code (pred
, std_preds
[i
].codes
[j
]);
1715 if (std_preds
[i
].allows_const_p
)
1716 for (j
= 0; j
< NUM_RTX_CODE
; j
++)
1717 if (GET_RTX_CLASS (j
) == RTX_CONST_OBJ
)
1718 add_predicate_code (pred
, (enum rtx_code
) j
);
1720 add_predicate (pred
);
1724 /* These functions allow linkage with print-rtl.c. Also, some generators
1725 like to annotate their output with insn names. */
1727 /* Holds an array of names indexed by insn_code_number. */
1728 static char **insn_name_ptr
= 0;
1729 static int insn_name_ptr_size
= 0;
1732 get_insn_name (int code
)
1734 if (code
< insn_name_ptr_size
)
1735 return insn_name_ptr
[code
];
1741 record_insn_name (int code
, const char *name
)
1743 static const char *last_real_name
= "insn";
1744 static int last_real_code
= 0;
1747 if (insn_name_ptr_size
<= code
)
1750 new_size
= (insn_name_ptr_size
? insn_name_ptr_size
* 2 : 512);
1751 insn_name_ptr
= XRESIZEVEC (char *, insn_name_ptr
, new_size
);
1752 memset (insn_name_ptr
+ insn_name_ptr_size
, 0,
1753 sizeof(char *) * (new_size
- insn_name_ptr_size
));
1754 insn_name_ptr_size
= new_size
;
1757 if (!name
|| name
[0] == '\0')
1759 new_name
= XNEWVAR (char, strlen (last_real_name
) + 10);
1760 sprintf (new_name
, "%s+%d", last_real_name
, code
- last_real_code
);
1764 last_real_name
= new_name
= xstrdup (name
);
1765 last_real_code
= code
;
1768 insn_name_ptr
[code
] = new_name
;
1771 /* Make STATS describe the operands that appear in rtx X. */
1774 get_pattern_stats_1 (struct pattern_stats
*stats
, rtx x
)
1784 code
= GET_CODE (x
);
1788 case MATCH_OPERATOR
:
1789 case MATCH_PARALLEL
:
1790 stats
->max_opno
= MAX (stats
->max_opno
, XINT (x
, 0));
1797 stats
->max_dup_opno
= MAX (stats
->max_dup_opno
, XINT (x
, 0));
1801 stats
->max_scratch_opno
= MAX (stats
->max_scratch_opno
, XINT (x
, 0));
1808 fmt
= GET_RTX_FORMAT (code
);
1809 len
= GET_RTX_LENGTH (code
);
1810 for (i
= 0; i
< len
; i
++)
1812 if (fmt
[i
] == 'e' || fmt
[i
] == 'u')
1813 get_pattern_stats_1 (stats
, XEXP (x
, i
));
1814 else if (fmt
[i
] == 'E')
1817 for (j
= 0; j
< XVECLEN (x
, i
); j
++)
1818 get_pattern_stats_1 (stats
, XVECEXP (x
, i
, j
));
1823 /* Make STATS describe the operands that appear in instruction pattern
1827 get_pattern_stats (struct pattern_stats
*stats
, rtvec pattern
)
1831 stats
->max_opno
= -1;
1832 stats
->max_dup_opno
= -1;
1833 stats
->max_scratch_opno
= -1;
1834 stats
->num_dups
= 0;
1836 len
= GET_NUM_ELEM (pattern
);
1837 for (i
= 0; i
< len
; i
++)
1838 get_pattern_stats_1 (stats
, RTVEC_ELT (pattern
, i
));
1840 stats
->num_generator_args
= stats
->max_opno
+ 1;
1841 stats
->num_insn_operands
= MAX (stats
->max_opno
,
1842 stats
->max_scratch_opno
) + 1;
1843 stats
->num_operand_vars
= MAX (stats
->max_opno
,
1844 MAX (stats
->max_dup_opno
,
1845 stats
->max_scratch_opno
)) + 1;