1 /* Support routines for the various generation passes.
2 Copyright (C) 2000-2023 Free Software Foundation, Inc.
4 This file is part of GCC.
6 GCC is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
11 GCC is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
14 License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3. If not see
18 <http://www.gnu.org/licenses/>. */
21 #define INCLUDE_STRING
22 #define INCLUDE_VECTOR
24 #include "coretypes.h"
30 #include "gensupport.h"
33 #define MAX_OPERANDS 40
35 static rtx operand_data
[MAX_OPERANDS
];
36 static rtx match_operand_entries_in_pattern
[MAX_OPERANDS
];
37 static char used_operands_numbers
[MAX_OPERANDS
];
38 /* List of entries which are part of the new syntax. */
39 hash_set
<rtx
> compact_syntax
;
42 /* In case some macros used by files we include need it, define this here. */
47 static struct obstack obstack
;
48 struct obstack
*rtl_obstack
= &obstack
;
50 /* Counter for named patterns and INSN_CODEs. */
51 static int insn_sequence_num
;
53 /* Counter for define_splits. */
54 static int split_sequence_num
;
56 /* Counter for define_peephole2s. */
57 static int peephole2_sequence_num
;
59 static int predicable_default
;
60 static const char *predicable_true
;
61 static const char *predicable_false
;
63 static const char *subst_true
= "yes";
64 static const char *subst_false
= "no";
66 static htab_t condition_table
;
68 /* We initially queue all patterns, process the define_insn,
69 define_cond_exec and define_subst patterns, then return
70 them one at a time. */
77 class queue_elem
*next
;
78 /* In a DEFINE_INSN that came from a DEFINE_INSN_AND_SPLIT or
79 DEFINE_INSN_AND_REWRITE, SPLIT points to the generated DEFINE_SPLIT. */
80 class queue_elem
*split
;
83 #define MNEMONIC_ATTR_NAME "mnemonic"
84 #define MNEMONIC_HTAB_SIZE 1024
86 static class queue_elem
*define_attr_queue
;
87 static class queue_elem
**define_attr_tail
= &define_attr_queue
;
88 static class queue_elem
*define_pred_queue
;
89 static class queue_elem
**define_pred_tail
= &define_pred_queue
;
90 static class queue_elem
*define_insn_queue
;
91 static class queue_elem
**define_insn_tail
= &define_insn_queue
;
92 static class queue_elem
*define_cond_exec_queue
;
93 static class queue_elem
**define_cond_exec_tail
= &define_cond_exec_queue
;
94 static class queue_elem
*define_subst_queue
;
95 static class queue_elem
**define_subst_tail
= &define_subst_queue
;
96 static class queue_elem
*other_queue
;
97 static class queue_elem
**other_tail
= &other_queue
;
98 static class queue_elem
*define_subst_attr_queue
;
99 static class queue_elem
**define_subst_attr_tail
= &define_subst_attr_queue
;
101 /* Mapping from DEFINE_* rtxes to their location in the source file. */
102 static hash_map
<rtx
, file_location
> *rtx_locs
;
104 static void remove_constraints (rtx
);
106 static int is_predicable (class queue_elem
*);
107 static void identify_predicable_attribute (void);
108 static int n_alternatives (const char *);
109 static void collect_insn_data (rtx
, int *, int *);
110 static const char *alter_test_for_insn (class queue_elem
*,
112 static char *shift_output_template (char *, const char *, int);
113 static const char *alter_output_for_insn (class queue_elem
*,
116 static void process_one_cond_exec (class queue_elem
*);
117 static void process_define_cond_exec (void);
118 static void init_predicate_table (void);
119 static void record_insn_name (int, const char *);
121 static bool has_subst_attribute (class queue_elem
*, class queue_elem
*);
122 static const char * alter_output_for_subst_insn (rtx
, int);
123 static void alter_attrs_for_subst_insn (class queue_elem
*, int);
124 static void process_substs_on_one_elem (class queue_elem
*,
126 static rtx
subst_dup (rtx
, int, int);
127 static void process_define_subst (void);
129 static const char * duplicate_alternatives (const char *, int);
130 static const char * duplicate_each_alternative (const char * str
, int n_dup
);
132 typedef const char * (*constraints_handler_t
) (const char *, int);
133 static rtx
alter_constraints (rtx
, int, constraints_handler_t
);
134 static rtx
adjust_operands_numbers (rtx
);
135 static rtx
replace_duplicating_operands_in_pattern (rtx
);
137 /* Make a version of gen_rtx_CONST_INT so that GEN_INT can be used in
138 the gensupport programs. */
141 gen_rtx_CONST_INT (machine_mode
ARG_UNUSED (mode
),
144 rtx rt
= rtx_alloc (CONST_INT
);
150 /* Return the rtx pattern specified by the list of rtxes in a
151 define_insn or define_split. */
154 add_implicit_parallel (rtvec vec
)
156 if (GET_NUM_ELEM (vec
) == 1)
157 return RTVEC_ELT (vec
, 0);
160 rtx pattern
= rtx_alloc (PARALLEL
);
161 XVEC (pattern
, 0) = vec
;
166 /* Predicate handling.
168 We construct from the machine description a table mapping each
169 predicate to a list of the rtl codes it can possibly match. The
170 function 'maybe_both_true' uses it to deduce that there are no
171 expressions that can be matches by certain pairs of tree nodes.
172 Also, if a predicate can match only one code, we can hardwire that
173 code into the node testing the predicate.
175 Some predicates are flagged as special. validate_pattern will not
176 warn about modeless match_operand expressions if they have a
177 special predicate. Predicates that allow only constants are also
178 treated as special, for this purpose.
180 validate_pattern will warn about predicates that allow non-lvalues
181 when they appear in destination operands.
183 Calculating the set of rtx codes that can possibly be accepted by a
184 predicate expression EXP requires a three-state logic: any given
185 subexpression may definitively accept a code C (Y), definitively
186 reject a code C (N), or may have an indeterminate effect (I). N
187 and I is N; Y or I is Y; Y and I, N or I are both I. Here are full
198 We represent Y with 1, N with 0, I with 2. If any code is left in
199 an I state by the complete expression, we must assume that that
200 code can be accepted. */
206 #define TRISTATE_AND(a,b) \
207 ((a) == I ? ((b) == N ? N : I) : \
208 (b) == I ? ((a) == N ? N : I) : \
211 #define TRISTATE_OR(a,b) \
212 ((a) == I ? ((b) == Y ? Y : I) : \
213 (b) == I ? ((a) == Y ? Y : I) : \
216 #define TRISTATE_NOT(a) \
217 ((a) == I ? I : !(a))
219 /* 0 means no warning about that code yet, 1 means warned. */
220 static char did_you_mean_codes
[NUM_RTX_CODE
];
222 /* Recursively calculate the set of rtx codes accepted by the
223 predicate expression EXP, writing the result to CODES. LOC is
224 the .md file location of the directive containing EXP. */
227 compute_test_codes (rtx exp
, file_location loc
, char *codes
)
229 char op0_codes
[NUM_RTX_CODE
];
230 char op1_codes
[NUM_RTX_CODE
];
231 char op2_codes
[NUM_RTX_CODE
];
234 switch (GET_CODE (exp
))
237 compute_test_codes (XEXP (exp
, 0), loc
, op0_codes
);
238 compute_test_codes (XEXP (exp
, 1), loc
, op1_codes
);
239 for (i
= 0; i
< NUM_RTX_CODE
; i
++)
240 codes
[i
] = TRISTATE_AND (op0_codes
[i
], op1_codes
[i
]);
244 compute_test_codes (XEXP (exp
, 0), loc
, op0_codes
);
245 compute_test_codes (XEXP (exp
, 1), loc
, op1_codes
);
246 for (i
= 0; i
< NUM_RTX_CODE
; i
++)
247 codes
[i
] = TRISTATE_OR (op0_codes
[i
], op1_codes
[i
]);
250 compute_test_codes (XEXP (exp
, 0), loc
, op0_codes
);
251 for (i
= 0; i
< NUM_RTX_CODE
; i
++)
252 codes
[i
] = TRISTATE_NOT (op0_codes
[i
]);
256 /* a ? b : c accepts the same codes as (a & b) | (!a & c). */
257 compute_test_codes (XEXP (exp
, 0), loc
, op0_codes
);
258 compute_test_codes (XEXP (exp
, 1), loc
, op1_codes
);
259 compute_test_codes (XEXP (exp
, 2), loc
, op2_codes
);
260 for (i
= 0; i
< NUM_RTX_CODE
; i
++)
261 codes
[i
] = TRISTATE_OR (TRISTATE_AND (op0_codes
[i
], op1_codes
[i
]),
262 TRISTATE_AND (TRISTATE_NOT (op0_codes
[i
]),
267 /* MATCH_CODE allows a specified list of codes. However, if it
268 does not apply to the top level of the expression, it does not
269 constrain the set of codes for the top level. */
270 if (XSTR (exp
, 1)[0] != '\0')
272 memset (codes
, Y
, NUM_RTX_CODE
);
276 memset (codes
, N
, NUM_RTX_CODE
);
278 const char *next_code
= XSTR (exp
, 0);
281 if (*next_code
== '\0')
283 error_at (loc
, "empty match_code expression");
287 while ((code
= scan_comma_elt (&next_code
)) != 0)
289 size_t n
= next_code
- code
;
292 for (i
= 0; i
< NUM_RTX_CODE
; i
++)
293 if (!strncmp (code
, GET_RTX_NAME (i
), n
)
294 && GET_RTX_NAME (i
)[n
] == '\0')
302 error_at (loc
, "match_code \"%.*s\" matches nothing",
304 for (i
= 0; i
< NUM_RTX_CODE
; i
++)
305 if (!strncasecmp (code
, GET_RTX_NAME (i
), n
)
306 && GET_RTX_NAME (i
)[n
] == '\0'
307 && !did_you_mean_codes
[i
])
309 did_you_mean_codes
[i
] = 1;
310 message_at (loc
, "(did you mean \"%s\"?)",
319 /* MATCH_OPERAND disallows the set of codes that the named predicate
320 disallows, and is indeterminate for the codes that it does allow. */
322 struct pred_data
*p
= lookup_predicate (XSTR (exp
, 1));
325 error_at (loc
, "reference to unknown predicate '%s'",
329 for (i
= 0; i
< NUM_RTX_CODE
; i
++)
330 codes
[i
] = p
->codes
[i
] ? I
: N
;
336 /* (match_test WHATEVER) is completely indeterminate. */
337 memset (codes
, I
, NUM_RTX_CODE
);
341 error_at (loc
, "'%s' cannot be used in predicates or constraints",
342 GET_RTX_NAME (GET_CODE (exp
)));
343 memset (codes
, I
, NUM_RTX_CODE
);
352 /* Return true if NAME is a valid predicate name. */
355 valid_predicate_name_p (const char *name
)
359 if (!ISALPHA (name
[0]) && name
[0] != '_')
361 for (p
= name
+ 1; *p
; p
++)
362 if (!ISALNUM (*p
) && *p
!= '_')
367 /* Process define_predicate directive DESC, which appears at location LOC.
368 Compute the set of codes that can be matched, and record this as a known
372 process_define_predicate (rtx desc
, file_location loc
)
374 struct pred_data
*pred
;
375 char codes
[NUM_RTX_CODE
];
378 if (!valid_predicate_name_p (XSTR (desc
, 0)))
380 error_at (loc
, "%s: predicate name must be a valid C function name",
385 pred
= XCNEW (struct pred_data
);
386 pred
->name
= XSTR (desc
, 0);
387 pred
->exp
= XEXP (desc
, 1);
388 pred
->c_block
= XSTR (desc
, 2);
389 if (GET_CODE (desc
) == DEFINE_SPECIAL_PREDICATE
)
390 pred
->special
= true;
392 compute_test_codes (XEXP (desc
, 1), loc
, codes
);
394 for (i
= 0; i
< NUM_RTX_CODE
; i
++)
396 add_predicate_code (pred
, (enum rtx_code
) i
);
398 add_predicate (pred
);
404 /* Queue PATTERN on LIST_TAIL. Return the address of the new queue
407 static class queue_elem
*
408 queue_pattern (rtx pattern
, class queue_elem
***list_tail
,
411 class queue_elem
*e
= XNEW (class queue_elem
);
417 *list_tail
= &e
->next
;
421 /* Remove element ELEM from QUEUE. */
423 remove_from_queue (class queue_elem
*elem
, class queue_elem
**queue
)
425 class queue_elem
*prev
, *e
;
427 for (e
= *queue
; e
; e
= e
->next
)
437 prev
->next
= elem
->next
;
442 /* Build a define_attr for an binary attribute with name NAME and
443 possible values "yes" and "no", and queue it. */
445 add_define_attr (const char *name
)
447 class queue_elem
*e
= XNEW (class queue_elem
);
448 rtx t1
= rtx_alloc (DEFINE_ATTR
);
450 XSTR (t1
, 1) = "no,yes";
451 XEXP (t1
, 2) = rtx_alloc (CONST_STRING
);
452 XSTR (XEXP (t1
, 2), 0) = "yes";
454 e
->loc
= file_location ("built-in", -1, -1);
455 e
->next
= define_attr_queue
;
456 define_attr_queue
= e
;
460 /* Recursively remove constraints from an rtx. */
463 remove_constraints (rtx part
)
466 const char *format_ptr
;
471 if (GET_CODE (part
) == MATCH_OPERAND
)
473 else if (GET_CODE (part
) == MATCH_SCRATCH
)
476 format_ptr
= GET_RTX_FORMAT (GET_CODE (part
));
478 for (i
= 0; i
< GET_RTX_LENGTH (GET_CODE (part
)); i
++)
479 switch (*format_ptr
++)
483 remove_constraints (XEXP (part
, i
));
486 if (XVEC (part
, i
) != NULL
)
487 for (j
= 0; j
< XVECLEN (part
, i
); j
++)
488 remove_constraints (XVECEXP (part
, i
, j
));
493 /* Recursively replace MATCH_OPERANDs with MATCH_DUPs and MATCH_OPERATORs
494 with MATCH_OP_DUPs in X. */
497 replace_operands_with_dups (rtx x
)
503 if (GET_CODE (x
) == MATCH_OPERAND
)
505 newx
= rtx_alloc (MATCH_DUP
);
506 XINT (newx
, 0) = XINT (x
, 0);
509 else if (GET_CODE (x
) == MATCH_OPERATOR
)
511 newx
= rtx_alloc (MATCH_OP_DUP
);
512 XINT (newx
, 0) = XINT (x
, 0);
513 XVEC (newx
, 1) = XVEC (x
, 2);
517 newx
= shallow_copy_rtx (x
);
519 const char *format_ptr
= GET_RTX_FORMAT (GET_CODE (x
));
520 for (int i
= 0; i
< GET_RTX_LENGTH (GET_CODE (x
)); i
++)
521 switch (*format_ptr
++)
525 XEXP (newx
, i
) = replace_operands_with_dups (XEXP (x
, i
));
528 if (XVEC (x
, i
) != NULL
)
530 XVEC (newx
, i
) = rtvec_alloc (XVECLEN (x
, i
));
531 for (int j
= 0; j
< XVECLEN (x
, i
); j
++)
533 = replace_operands_with_dups (XVECEXP (x
, i
, j
));
540 /* Convert matching pattern VEC from a DEFINE_INSN_AND_REWRITE into
541 a sequence that should be generated by the splitter. */
544 gen_rewrite_sequence (rtvec vec
)
546 rtvec new_vec
= rtvec_alloc (1);
547 rtx x
= add_implicit_parallel (vec
);
548 RTVEC_ELT (new_vec
, 0) = replace_operands_with_dups (x
);
552 /* The following is for handling the compact syntax for constraints and
555 The normal syntax looks like this:
558 (match_operand: 0 "s_register_operand" "r,I,k")
559 (match_operand: 2 "s_register_operand" "r,k,I")
566 (set_attr "length" "4,8,8")
568 The compact syntax looks like this:
571 (match_operand: 0 "s_register_operand")
572 (match_operand: 2 "s_register_operand")
574 {@ [cons: 0, 2; attrs: length]
582 This is the only place where this syntax needs to be handled. Relevant
583 patterns are transformed from compact to the normal syntax before they are
584 queued, so none of the gen* programs need to know about this syntax at all.
586 Conversion process (convert_syntax):
588 0) Check that pattern actually uses new syntax (check for {@ ... }).
590 1) Get the "layout", i.e. the "[cons: 0 2; attrs: length]" from the above
591 example. cons must come first; both are optional. Set up two vecs,
592 convec and attrvec, for holding the results of the transformation.
594 2) For each alternative: parse the list of constraints and/or attributes,
595 and enqueue them in the relevant lists in convec and attrvec. By the end
596 of this process, convec[N].con and attrvec[N].con should contain regular
597 syntax constraint/attribute lists like "r,I,k". Copy the asm to a string
600 3) Search the rtx and write the constraint and attribute lists into the
601 correct places. Write the asm back into the template. */
603 /* Helper class for shuffling constraints/attributes in convert_syntax and
604 add_constraints/add_attributes. This includes commas but not whitespace. */
614 conlist () = default;
616 /* [ns..ns + len) should be a string with the id of the rtx to match
617 i.e. if rtx is the relevant match_operand or match_scratch then
618 [ns..ns + len) should equal itoa (XINT (rtx, 0)), and if set_attr then
619 [ns..ns + len) should equal XSTR (rtx, 0). */
620 conlist (const char *ns
, unsigned int len
, bool numeric
)
622 /* Trim leading whitespaces. */
623 while (len
> 0 && ISBLANK (*ns
))
629 /* Trim trailing whitespace. */
630 for (int i
= len
- 1; i
>= 0; i
--, len
--)
631 if (!ISBLANK (ns
[i
]))
634 /* Parse off any modifiers. */
635 while (len
> 0 && !ISALNUM (*ns
))
641 name
.assign (ns
, len
);
643 idx
= strtol (name
.c_str (), (char **)NULL
, 10);
646 /* Adds a character to the end of the string. */
652 /* Output the string in the form of a brand-new char *, then effectively
653 clear the internal string by resetting len to 0. */
656 /* Final character is always a trailing comma, so strip it out. */
657 char *q
= xstrndup (con
.c_str (), con
.size () - 1);
663 typedef std::vector
<conlist
> vec_conlist
;
665 /* Add constraints to an rtx. This function is similar to remove_constraints.
666 Errors if adding the constraints would overwrite existing constraints. */
669 add_constraints (rtx part
, file_location loc
, vec_conlist
&cons
)
671 const char *format_ptr
;
673 if (part
== NULL_RTX
)
676 /* If match_op or match_scr, check if we have the right one, and if so, copy
677 over the constraint list. */
678 if (GET_CODE (part
) == MATCH_OPERAND
|| GET_CODE (part
) == MATCH_SCRATCH
)
680 int field
= GET_CODE (part
) == MATCH_OPERAND
? 2 : 1;
681 unsigned id
= XINT (part
, 0);
683 if (id
>= cons
.size () || cons
[id
].idx
== -1)
686 if (XSTR (part
, field
)[0] != '\0')
688 error_at (loc
, "can't mix normal and compact constraint syntax");
691 XSTR (part
, field
) = cons
[id
].out ();
695 format_ptr
= GET_RTX_FORMAT (GET_CODE (part
));
697 /* Recursively search the rtx. */
698 for (int i
= 0; i
< GET_RTX_LENGTH (GET_CODE (part
)); i
++)
699 switch (*format_ptr
++)
703 add_constraints (XEXP (part
, i
), loc
, cons
);
706 if (XVEC (part
, i
) != NULL
)
707 for (int j
= 0; j
< XVECLEN (part
, i
); j
++)
708 add_constraints (XVECEXP (part
, i
, j
), loc
, cons
);
715 /* Add ATTRS to definition X's attribute list. */
718 add_attributes (rtx x
, vec_conlist
&attrs
)
720 unsigned int attr_index
= GET_CODE (x
) == DEFINE_INSN
? 4 : 3;
721 rtvec orig
= XVEC (x
, attr_index
);
724 size_t n_curr
= XVECLEN (x
, attr_index
);
725 rtvec copy
= rtvec_alloc (n_curr
+ attrs
.size ());
727 /* Create a shallow copy of existing entries. */
728 memcpy (©
->elem
[attrs
.size ()], &orig
->elem
[0],
729 sizeof (rtx
) * n_curr
);
730 XVEC (x
, attr_index
) = copy
;
733 XVEC (x
, attr_index
) = rtvec_alloc (attrs
.size ());
735 /* Create the new elements. */
736 for (unsigned i
= 0; i
< attrs
.size (); i
++)
738 rtx attr
= rtx_alloc (SET_ATTR
);
739 XSTR (attr
, 0) = xstrdup (attrs
[i
].name
.c_str ());
740 XSTR (attr
, 1) = attrs
[i
].out ();
741 XVECEXP (x
, attr_index
, i
) = attr
;
745 /* Consumes spaces and tabs. */
748 skip_spaces (const char **str
)
750 while (ISBLANK (**str
))
754 /* Consumes the given character, if it's there. */
757 expect_char (const char **str
, char c
)
765 /* Parses the section layout that follows a "{@" if using new syntax. Builds
766 a vector for a single section. E.g. if we have "attrs: length, arch]..."
767 then list will have two elements, the first for "length" and the second
771 parse_section_layout (file_location loc
, const char **templ
, const char *label
,
772 vec_conlist
&list
, bool numeric
)
774 const char *name_start
;
775 size_t label_len
= strlen (label
);
776 if (strncmp (label
, *templ
, label_len
) == 0)
780 /* Gather the names. */
781 while (**templ
!= ';' && **templ
!= ']')
786 char val
= (*templ
)[len
];
787 while (val
!= ',' && val
!= ';' && val
!= ']')
789 if (val
== 0 || val
== '\n')
790 fatal_at (loc
, "missing ']'");
791 val
= (*templ
)[++len
];
796 list
.push_back (conlist (name_start
, len
, numeric
));
801 /* Parse a section, a section is defined as a named space separated list, e.g.
805 is a section named "foo" with entries a, b and c. */
808 parse_section (const char **templ
, unsigned int n_elems
, unsigned int alt_no
,
809 vec_conlist
&list
, file_location loc
, const char *name
)
813 /* Go through the list, one character at a time, adding said character
814 to the correct string. */
815 for (i
= 0; **templ
!= ']' && **templ
!= ';'; (*templ
)++)
816 if (!ISBLANK (**templ
))
818 if (**templ
== 0 || **templ
== '\n')
819 fatal_at (loc
, "missing ']'");
820 list
[i
].add (**templ
);
825 fatal_at (loc
, "too many %ss in alternative %d: expected %d",
826 name
, alt_no
, n_elems
);
831 fatal_at (loc
, "too few %ss in alternative %d: expected %d, got %d",
832 name
, alt_no
, n_elems
, i
);
837 /* The compact syntax has more convience syntaxes. As such we post process
838 the lines to get them back to something the normal syntax understands. */
841 preprocess_compact_syntax (file_location loc
, int alt_no
, std::string
&line
,
842 std::string
&last_line
)
844 /* Check if we're copying the last statement. */
845 if (line
.find ("^") == 0 && line
.size () == 1)
847 if (last_line
.empty ())
848 fatal_at (loc
, "found instruction to copy previous line (^) in"
849 "alternative %d but no previous line to copy", alt_no
);
856 /* Check if we have << which means return c statement. */
857 if (line
.find ("<<") == 0)
859 result
.append ("* return ");
860 const char *chunk
= line
.c_str () + 2;
861 skip_spaces (&chunk
);
862 result
.append (chunk
);
865 result
.append (line
);
871 /* Converts an rtx from compact syntax to normal syntax if possible. */
874 convert_syntax (rtx x
, file_location loc
)
877 unsigned int templ_index
;
879 vec_conlist tconvec
, convec
, attrvec
;
882 gcc_assert (GET_CODE (x
) == DEFINE_INSN
);
884 templ
= XTMPL (x
, templ_index
);
886 /* Templates with constraints start with "{@". */
887 if (strncmp ("*{@", templ
, 3))
890 /* Get the layout for the template. */
892 skip_spaces (&templ
);
894 if (!expect_char (&templ
, '['))
895 fatal_at (loc
, "expecing `[' to begin section list");
897 skip_spaces (&templ
);
899 parse_section_layout (loc
, &templ
, "cons:", tconvec
, true);
904 skip_spaces (&(++templ
));
905 parse_section_layout (loc
, &templ
, "attrs:", attrvec
, false);
908 if (!expect_char (&templ
, ']'))
909 fatal_at (loc
, "expecting `]` to end section list - section list must have "
910 "cons first, attrs second");
912 /* We will write the un-constrainified template into new_templ. */
913 std::string new_templ
;
914 new_templ
.append ("@");
916 /* Skip to the first proper line. */
917 skip_spaces (&templ
);
919 fatal_at (loc
, "'{@...}' blocks must have at least one alternative");
921 fatal_at (loc
, "unexpected character '%c' after ']'", *templ
);
925 std::string last_line
;
927 /* Process the alternatives. */
928 while (*(templ
- 1) != '\0')
930 /* Skip leading whitespace. */
932 skip_spaces (&templ
);
934 /* Check if we're at the end. */
935 if (templ
[0] == '}' && templ
[1] == '\0')
938 if (expect_char (&templ
, '['))
941 new_templ
.append (buffer
);
942 /* Parse the constraint list, then the attribute list. */
943 if (tconvec
.size () > 0)
944 parse_section (&templ
, tconvec
.size (), alt_no
, tconvec
, loc
,
947 if (attrvec
.size () > 0)
949 if (tconvec
.size () > 0 && !expect_char (&templ
, ';'))
950 fatal_at (loc
, "expected `;' to separate constraints "
951 "and attributes in alternative %d", alt_no
);
953 parse_section (&templ
, attrvec
.size (), alt_no
,
954 attrvec
, loc
, "attribute");
957 if (!expect_char (&templ
, ']'))
958 fatal_at (loc
, "expected end of constraint/attribute list but "
959 "missing an ending `]' in alternative %d", alt_no
);
961 else if (templ
[0] == '/' && templ
[1] == '/')
964 /* Glob till newline or end of string. */
965 while (*templ
!= '\n' || *templ
!= '\0')
968 /* Skip any newlines or whitespaces needed. */
969 while (ISSPACE(*templ
))
973 else if (templ
[0] == '/' && templ
[1] == '*')
976 /* Glob till newline or end of multiline comment. */
977 while (templ
[0] != 0 && templ
[0] != '*' && templ
[1] != '/')
980 while (templ
[0] != '*' || templ
[1] != '/')
983 fatal_at (loc
, "unterminated '/*'");
988 /* Skip any newlines or whitespaces needed. */
989 while (ISSPACE(*templ
))
994 fatal_at (loc
, "expected constraint/attribute list at beginning of "
995 "alternative %d but missing a starting `['", alt_no
);
997 /* Skip whitespace between list and asm. */
998 skip_spaces (&templ
);
1000 /* Copy asm to new template. */
1002 while (*templ
!= '\n' && *templ
!= '\0')
1005 /* Apply any pre-processing needed to the line. */
1006 preprocess_compact_syntax (loc
, alt_no
, line
, last_line
);
1007 new_templ
.append (line
);
1010 /* Normal "*..." syntax expects the closing quote to be on the final
1011 line of asm, whereas we allow the closing "}" to be on its own line.
1012 Postpone copying the '\n' until we know that there is another
1013 alternative in the list. */
1014 while (ISSPACE (*templ
))
1019 /* Check for any duplicate cons entries and sort based on i. */
1020 for (auto e
: tconvec
)
1022 unsigned idx
= e
.idx
;
1023 if (idx
>= convec
.size ())
1024 convec
.resize (idx
+ 1);
1026 if (convec
[idx
].idx
>= 0)
1027 fatal_at (loc
, "duplicate cons number found: %d", idx
);
1032 /* Write the constraints and attributes into their proper places. */
1033 if (convec
.size () > 0)
1034 add_constraints (x
, loc
, convec
);
1036 if (attrvec
.size () > 0)
1037 add_attributes (x
, attrvec
);
1039 /* Copy over the new un-constrainified template. */
1040 XTMPL (x
, templ_index
) = xstrdup (new_templ
.c_str ());
1042 /* Register for later checks during iterator expansions. */
1043 compact_syntax
.add (x
);
1046 /* Process a top level rtx in some way, queuing as appropriate. */
1049 process_rtx (rtx desc
, file_location loc
)
1051 switch (GET_CODE (desc
))
1054 convert_syntax (desc
, loc
);
1055 queue_pattern (desc
, &define_insn_tail
, loc
);
1058 case DEFINE_COND_EXEC
:
1059 queue_pattern (desc
, &define_cond_exec_tail
, loc
);
1063 queue_pattern (desc
, &define_subst_tail
, loc
);
1066 case DEFINE_SUBST_ATTR
:
1067 queue_pattern (desc
, &define_subst_attr_tail
, loc
);
1071 case DEFINE_ENUM_ATTR
:
1072 queue_pattern (desc
, &define_attr_tail
, loc
);
1075 case DEFINE_PREDICATE
:
1076 case DEFINE_SPECIAL_PREDICATE
:
1077 process_define_predicate (desc
, loc
);
1080 case DEFINE_CONSTRAINT
:
1081 case DEFINE_REGISTER_CONSTRAINT
:
1082 case DEFINE_MEMORY_CONSTRAINT
:
1083 case DEFINE_SPECIAL_MEMORY_CONSTRAINT
:
1084 case DEFINE_RELAXED_MEMORY_CONSTRAINT
:
1085 case DEFINE_ADDRESS_CONSTRAINT
:
1086 queue_pattern (desc
, &define_pred_tail
, loc
);
1089 case DEFINE_INSN_AND_SPLIT
:
1090 case DEFINE_INSN_AND_REWRITE
:
1092 const char *split_cond
;
1096 class queue_elem
*insn_elem
;
1097 class queue_elem
*split_elem
;
1098 int split_code
= (GET_CODE (desc
) == DEFINE_INSN_AND_REWRITE
? 5 : 6);
1100 /* Create a split with values from the insn_and_split. */
1101 split
= rtx_alloc (DEFINE_SPLIT
);
1103 i
= XVECLEN (desc
, 1);
1104 XVEC (split
, 0) = rtvec_alloc (i
);
1107 XVECEXP (split
, 0, i
) = copy_rtx (XVECEXP (desc
, 1, i
));
1108 remove_constraints (XVECEXP (split
, 0, i
));
1111 /* If the split condition starts with "&&", append it to the
1112 insn condition to create the new split condition. */
1113 split_cond
= XSTR (desc
, 4);
1114 if (split_cond
[0] == '&' && split_cond
[1] == '&')
1116 rtx_reader_ptr
->copy_md_ptr_loc (split_cond
+ 2, split_cond
);
1117 split_cond
= rtx_reader_ptr
->join_c_conditions (XSTR (desc
, 2),
1120 else if (GET_CODE (desc
) == DEFINE_INSN_AND_REWRITE
)
1121 error_at (loc
, "the rewrite condition must start with `&&'");
1122 XSTR (split
, 1) = split_cond
;
1123 if (GET_CODE (desc
) == DEFINE_INSN_AND_REWRITE
)
1124 XVEC (split
, 2) = gen_rewrite_sequence (XVEC (desc
, 1));
1126 XVEC (split
, 2) = XVEC (desc
, 5);
1127 XSTR (split
, 3) = XSTR (desc
, split_code
);
1129 /* Fix up the DEFINE_INSN. */
1130 attr
= XVEC (desc
, split_code
+ 1);
1131 PUT_CODE (desc
, DEFINE_INSN
);
1132 XVEC (desc
, 4) = attr
;
1133 convert_syntax (desc
, loc
);
1136 insn_elem
= queue_pattern (desc
, &define_insn_tail
, loc
);
1137 split_elem
= queue_pattern (split
, &other_tail
, loc
);
1138 insn_elem
->split
= split_elem
;
1143 queue_pattern (desc
, &other_tail
, loc
);
1148 /* Return true if attribute PREDICABLE is true for ELEM, which holds
1152 is_predicable (class queue_elem
*elem
)
1154 rtvec vec
= XVEC (elem
->data
, 4);
1159 return predicable_default
;
1161 for (i
= GET_NUM_ELEM (vec
) - 1; i
>= 0; --i
)
1163 rtx sub
= RTVEC_ELT (vec
, i
);
1164 switch (GET_CODE (sub
))
1167 if (strcmp (XSTR (sub
, 0), "predicable") == 0)
1169 value
= XSTR (sub
, 1);
1174 case SET_ATTR_ALTERNATIVE
:
1175 if (strcmp (XSTR (sub
, 0), "predicable") == 0)
1177 error_at (elem
->loc
, "multiple alternatives for `predicable'");
1183 if (GET_CODE (SET_DEST (sub
)) != ATTR
1184 || strcmp (XSTR (SET_DEST (sub
), 0), "predicable") != 0)
1186 sub
= SET_SRC (sub
);
1187 if (GET_CODE (sub
) == CONST_STRING
)
1189 value
= XSTR (sub
, 0);
1193 /* ??? It would be possible to handle this if we really tried.
1194 It's not easy though, and I'm not going to bother until it
1195 really proves necessary. */
1196 error_at (elem
->loc
, "non-constant value for `predicable'");
1204 return predicable_default
;
1207 /* Find out which value we're looking at. Multiple alternatives means at
1208 least one is predicable. */
1209 if (strchr (value
, ',') != NULL
)
1211 if (strcmp (value
, predicable_true
) == 0)
1213 if (strcmp (value
, predicable_false
) == 0)
1216 error_at (elem
->loc
, "unknown value `%s' for `predicable' attribute", value
);
1220 /* Find attribute SUBST in ELEM and assign NEW_VALUE to it. */
1222 change_subst_attribute (class queue_elem
*elem
,
1223 class queue_elem
*subst_elem
,
1224 const char *new_value
)
1226 rtvec attrs_vec
= XVEC (elem
->data
, 4);
1227 const char *subst_name
= XSTR (subst_elem
->data
, 0);
1233 for (i
= GET_NUM_ELEM (attrs_vec
) - 1; i
>= 0; --i
)
1235 rtx cur_attr
= RTVEC_ELT (attrs_vec
, i
);
1236 if (GET_CODE (cur_attr
) != SET_ATTR
)
1238 if (strcmp (XSTR (cur_attr
, 0), subst_name
) == 0)
1240 XSTR (cur_attr
, 1) = new_value
;
1246 /* Return true if ELEM has the attribute with the name of DEFINE_SUBST
1247 represented by SUBST_ELEM and this attribute has value SUBST_TRUE.
1248 DEFINE_SUBST isn't applied to patterns without such attribute. In other
1249 words, we suppose the default value of the attribute to be 'no' since it is
1250 always generated automatically in read-rtl.cc. */
1252 has_subst_attribute (class queue_elem
*elem
, class queue_elem
*subst_elem
)
1254 rtvec attrs_vec
= XVEC (elem
->data
, 4);
1255 const char *value
, *subst_name
= XSTR (subst_elem
->data
, 0);
1261 for (i
= GET_NUM_ELEM (attrs_vec
) - 1; i
>= 0; --i
)
1263 rtx cur_attr
= RTVEC_ELT (attrs_vec
, i
);
1264 switch (GET_CODE (cur_attr
))
1267 if (strcmp (XSTR (cur_attr
, 0), subst_name
) == 0)
1269 value
= XSTR (cur_attr
, 1);
1275 if (GET_CODE (SET_DEST (cur_attr
)) != ATTR
1276 || strcmp (XSTR (SET_DEST (cur_attr
), 0), subst_name
) != 0)
1278 cur_attr
= SET_SRC (cur_attr
);
1279 if (GET_CODE (cur_attr
) == CONST_STRING
)
1281 value
= XSTR (cur_attr
, 0);
1285 /* Only (set_attr "subst" "yes/no") and
1286 (set (attr "subst" (const_string "yes/no")))
1287 are currently allowed. */
1288 error_at (elem
->loc
, "unsupported value for `%s'", subst_name
);
1291 case SET_ATTR_ALTERNATIVE
:
1292 if (strcmp (XSTR (cur_attr
, 0), subst_name
) == 0)
1293 error_at (elem
->loc
,
1294 "%s: `set_attr_alternative' is unsupported by "
1295 "`define_subst'", XSTR (elem
->data
, 0));
1307 if (strcmp (value
, subst_true
) == 0)
1309 if (strcmp (value
, subst_false
) == 0)
1312 error_at (elem
->loc
, "unknown value `%s' for `%s' attribute",
1317 /* Compare RTL-template of original define_insn X to input RTL-template of
1318 define_subst PT. Return 1 if the templates match, 0 otherwise.
1319 During the comparison, the routine also fills global_array OPERAND_DATA. */
1321 subst_pattern_match (rtx x
, rtx pt
, file_location loc
)
1323 RTX_CODE code
, code_pt
;
1325 const char *fmt
, *pred_name
;
1327 code
= GET_CODE (x
);
1328 code_pt
= GET_CODE (pt
);
1330 if (code_pt
== MATCH_OPERAND
)
1332 /* MATCH_DUP, and MATCH_OP_DUP don't have a specified mode, so we
1333 always accept them. */
1334 if (GET_MODE (pt
) != VOIDmode
&& GET_MODE (x
) != GET_MODE (pt
)
1335 && (code
!= MATCH_DUP
&& code
!= MATCH_OP_DUP
))
1336 return false; /* Modes don't match. */
1338 if (code
== MATCH_OPERAND
)
1340 pred_name
= XSTR (pt
, 1);
1341 if (pred_name
[0] != 0)
1343 const struct pred_data
*pred_pt
= lookup_predicate (pred_name
);
1344 if (!pred_pt
|| pred_pt
!= lookup_predicate (XSTR (x
, 1)))
1345 return false; /* Predicates don't match. */
1349 gcc_assert (XINT (pt
, 0) >= 0 && XINT (pt
, 0) < MAX_OPERANDS
);
1350 operand_data
[XINT (pt
, 0)] = x
;
1354 if (code_pt
== MATCH_OPERATOR
)
1356 int x_vecexp_pos
= -1;
1358 /* Compare modes. */
1359 if (GET_MODE (pt
) != VOIDmode
&& GET_MODE (x
) != GET_MODE (pt
))
1362 /* In case X is also match_operator, compare predicates. */
1363 if (code
== MATCH_OPERATOR
)
1365 pred_name
= XSTR (pt
, 1);
1366 if (pred_name
[0] != 0)
1368 const struct pred_data
*pred_pt
= lookup_predicate (pred_name
);
1369 if (!pred_pt
|| pred_pt
!= lookup_predicate (XSTR (x
, 1)))
1374 /* Compare operands.
1375 MATCH_OPERATOR in input template could match in original template
1376 either 1) MATCH_OPERAND, 2) UNSPEC, 3) ordinary operation (like PLUS).
1377 In the first case operands are at (XVECEXP (x, 2, j)), in the second
1378 - at (XVECEXP (x, 0, j)), in the last one - (XEXP (x, j)).
1379 X_VECEXP_POS variable shows, where to look for these operands. */
1381 || code
== UNSPEC_VOLATILE
)
1383 else if (code
== MATCH_OPERATOR
)
1388 /* MATCH_OPERATOR or UNSPEC case. */
1389 if (x_vecexp_pos
>= 0)
1391 /* Compare operands number in X and PT. */
1392 if (XVECLEN (x
, x_vecexp_pos
) != XVECLEN (pt
, 2))
1394 for (j
= 0; j
< XVECLEN (pt
, 2); j
++)
1395 if (!subst_pattern_match (XVECEXP (x
, x_vecexp_pos
, j
),
1396 XVECEXP (pt
, 2, j
), loc
))
1400 /* Ordinary operator. */
1403 /* Compare operands number in X and PT.
1404 We count operands differently for X and PT since we compare
1405 an operator (with operands directly in RTX) and MATCH_OPERATOR
1406 (that has a vector with operands). */
1407 if (GET_RTX_LENGTH (code
) != XVECLEN (pt
, 2))
1409 for (j
= 0; j
< XVECLEN (pt
, 2); j
++)
1410 if (!subst_pattern_match (XEXP (x
, j
), XVECEXP (pt
, 2, j
), loc
))
1414 /* Store the operand to OPERAND_DATA array. */
1415 gcc_assert (XINT (pt
, 0) >= 0 && XINT (pt
, 0) < MAX_OPERANDS
);
1416 operand_data
[XINT (pt
, 0)] = x
;
1420 if (code_pt
== MATCH_PAR_DUP
1421 || code_pt
== MATCH_DUP
1422 || code_pt
== MATCH_OP_DUP
1423 || code_pt
== MATCH_SCRATCH
1424 || code_pt
== MATCH_PARALLEL
)
1426 /* Currently interface for these constructions isn't defined -
1427 probably they aren't needed in input template of define_subst at all.
1428 So, for now their usage in define_subst is forbidden. */
1429 error_at (loc
, "%s cannot be used in define_subst",
1430 GET_RTX_NAME (code_pt
));
1433 gcc_assert (code
!= MATCH_PAR_DUP
1434 && code_pt
!= MATCH_DUP
1435 && code_pt
!= MATCH_OP_DUP
1436 && code_pt
!= MATCH_SCRATCH
1437 && code_pt
!= MATCH_PARALLEL
1438 && code_pt
!= MATCH_OPERAND
1439 && code_pt
!= MATCH_OPERATOR
);
1440 /* If PT is none of the handled above, then we match only expressions with
1441 the same code in X. */
1442 if (code
!= code_pt
)
1445 fmt
= GET_RTX_FORMAT (code_pt
);
1446 len
= GET_RTX_LENGTH (code_pt
);
1448 for (i
= 0; i
< len
; i
++)
1455 case 'r': case 'p': case 'i': case 'w': case 's':
1459 if (!subst_pattern_match (XEXP (x
, i
), XEXP (pt
, i
), loc
))
1464 if (XVECLEN (x
, i
) != XVECLEN (pt
, i
))
1466 for (j
= 0; j
< XVECLEN (pt
, i
); j
++)
1467 if (!subst_pattern_match (XVECEXP (x
, i
, j
),
1468 XVECEXP (pt
, i
, j
), loc
))
1480 /* Examine the attribute "predicable"; discover its boolean values
1484 identify_predicable_attribute (void)
1486 class queue_elem
*elem
;
1487 char *p_true
, *p_false
;
1490 /* Look for the DEFINE_ATTR for `predicable', which must exist. */
1491 for (elem
= define_attr_queue
; elem
; elem
= elem
->next
)
1492 if (strcmp (XSTR (elem
->data
, 0), "predicable") == 0)
1495 error_at (define_cond_exec_queue
->loc
,
1496 "attribute `predicable' not defined");
1500 value
= XSTR (elem
->data
, 1);
1501 p_false
= xstrdup (value
);
1502 p_true
= strchr (p_false
, ',');
1503 if (p_true
== NULL
|| strchr (++p_true
, ',') != NULL
)
1505 error_at (elem
->loc
, "attribute `predicable' is not a boolean");
1511 predicable_true
= p_true
;
1512 predicable_false
= p_false
;
1514 switch (GET_CODE (XEXP (elem
->data
, 2)))
1517 value
= XSTR (XEXP (elem
->data
, 2), 0);
1521 error_at (elem
->loc
, "attribute `predicable' cannot be const");
1526 error_at (elem
->loc
,
1527 "attribute `predicable' must have a constant default");
1532 if (strcmp (value
, p_true
) == 0)
1533 predicable_default
= 1;
1534 else if (strcmp (value
, p_false
) == 0)
1535 predicable_default
= 0;
1538 error_at (elem
->loc
, "unknown value `%s' for `predicable' attribute",
1544 /* Return the number of alternatives in constraint S. */
1547 n_alternatives (const char *s
)
1558 /* The routine scans rtl PATTERN, find match_operand in it and counts
1559 number of alternatives. If PATTERN contains several match_operands
1560 with different number of alternatives, error is emitted, and the
1561 routine returns 0. If all match_operands in PATTERN have the same
1562 number of alternatives, it's stored in N_ALT, and the routine returns 1.
1563 LOC is the location of PATTERN, for error reporting. */
1565 get_alternatives_number (rtx pattern
, int *n_alt
, file_location loc
)
1574 code
= GET_CODE (pattern
);
1578 i
= n_alternatives (XSTR (pattern
, 2));
1579 /* n_alternatives returns 1 if constraint string is empty -
1580 here we fix it up. */
1581 if (!*(XSTR (pattern
, 2)))
1586 else if (i
&& i
!= *n_alt
)
1588 error_at (loc
, "wrong number of alternatives in operand %d",
1597 fmt
= GET_RTX_FORMAT (code
);
1598 len
= GET_RTX_LENGTH (code
);
1599 for (i
= 0; i
< len
; i
++)
1604 if (!get_alternatives_number (XEXP (pattern
, i
), n_alt
, loc
))
1609 if (XVEC (pattern
, i
) == NULL
)
1614 for (j
= XVECLEN (pattern
, i
) - 1; j
>= 0; --j
)
1615 if (!get_alternatives_number (XVECEXP (pattern
, i
, j
), n_alt
, loc
))
1619 case 'r': case 'p': case 'i': case 'w':
1620 case '0': case 's': case 'S': case 'T':
1630 /* Determine how many alternatives there are in INSN, and how many
1634 collect_insn_data (rtx pattern
, int *palt
, int *pmax
)
1640 code
= GET_CODE (pattern
);
1645 i
= n_alternatives (XSTR (pattern
, code
== MATCH_SCRATCH
? 1 : 2));
1646 *palt
= (i
> *palt
? i
: *palt
);
1649 case MATCH_OPERATOR
:
1650 case MATCH_PARALLEL
:
1651 i
= XINT (pattern
, 0);
1660 fmt
= GET_RTX_FORMAT (code
);
1661 len
= GET_RTX_LENGTH (code
);
1662 for (i
= 0; i
< len
; i
++)
1667 collect_insn_data (XEXP (pattern
, i
), palt
, pmax
);
1671 if (XVEC (pattern
, i
) == NULL
)
1675 for (j
= XVECLEN (pattern
, i
) - 1; j
>= 0; --j
)
1676 collect_insn_data (XVECEXP (pattern
, i
, j
), palt
, pmax
);
1679 case 'r': case 'p': case 'i': case 'w':
1680 case '0': case 's': case 'S': case 'T':
1690 alter_predicate_for_insn (rtx pattern
, int alt
, int max_op
,
1697 code
= GET_CODE (pattern
);
1702 const char *c
= XSTR (pattern
, 2);
1704 if (n_alternatives (c
) != 1)
1706 error_at (loc
, "too many alternatives for operand %d",
1711 /* Replicate C as needed to fill out ALT alternatives. */
1712 if (c
&& *c
&& alt
> 1)
1714 size_t c_len
= strlen (c
);
1715 size_t len
= alt
* (c_len
+ 1);
1716 char *new_c
= XNEWVEC (char, len
);
1718 memcpy (new_c
, c
, c_len
);
1719 for (i
= 1; i
< alt
; ++i
)
1721 new_c
[i
* (c_len
+ 1) - 1] = ',';
1722 memcpy (&new_c
[i
* (c_len
+ 1)], c
, c_len
);
1724 new_c
[len
- 1] = '\0';
1725 XSTR (pattern
, 2) = new_c
;
1730 case MATCH_OPERATOR
:
1732 case MATCH_PARALLEL
:
1734 XINT (pattern
, 0) += max_op
;
1741 fmt
= GET_RTX_FORMAT (code
);
1742 len
= GET_RTX_LENGTH (code
);
1743 for (i
= 0; i
< len
; i
++)
1750 r
= alter_predicate_for_insn (XEXP (pattern
, i
), alt
, max_op
, loc
);
1756 for (j
= XVECLEN (pattern
, i
) - 1; j
>= 0; --j
)
1758 r
= alter_predicate_for_insn (XVECEXP (pattern
, i
, j
),
1765 case 'r': case 'p': case 'i': case 'w': case '0': case 's':
1776 /* Duplicate constraints in PATTERN. If pattern is from original
1777 rtl-template, we need to duplicate each alternative - for that we
1778 need to use duplicate_each_alternative () as a functor ALTER.
1779 If pattern is from output-pattern of define_subst, we need to
1780 duplicate constraints in another way - with duplicate_alternatives ().
1781 N_DUP is multiplication factor. */
1783 alter_constraints (rtx pattern
, int n_dup
, constraints_handler_t alter
)
1789 code
= GET_CODE (pattern
);
1793 XSTR (pattern
, 2) = alter (XSTR (pattern
, 2), n_dup
);
1796 XSTR (pattern
, 1) = alter (XSTR (pattern
, 1), n_dup
);
1803 fmt
= GET_RTX_FORMAT (code
);
1804 len
= GET_RTX_LENGTH (code
);
1805 for (i
= 0; i
< len
; i
++)
1812 r
= alter_constraints (XEXP (pattern
, i
), n_dup
, alter
);
1818 for (j
= XVECLEN (pattern
, i
) - 1; j
>= 0; --j
)
1820 r
= alter_constraints (XVECEXP (pattern
, i
, j
), n_dup
, alter
);
1826 case 'r': case 'p': case 'i': case 'w': case '0': case 's':
1838 alter_test_for_insn (class queue_elem
*ce_elem
,
1839 class queue_elem
*insn_elem
)
1841 return rtx_reader_ptr
->join_c_conditions (XSTR (ce_elem
->data
, 1),
1842 XSTR (insn_elem
->data
, 2));
1845 /* Modify VAL, which is an attribute expression for the "enabled" attribute,
1846 to take "ce_enabled" into account. Return the new expression. */
1848 modify_attr_enabled_ce (rtx val
)
1852 eq_attr
= rtx_alloc (EQ_ATTR
);
1853 ite
= rtx_alloc (IF_THEN_ELSE
);
1854 str
= rtx_alloc (CONST_STRING
);
1856 XSTR (eq_attr
, 0) = "ce_enabled";
1857 XSTR (eq_attr
, 1) = "yes";
1858 XSTR (str
, 0) = "no";
1859 XEXP (ite
, 0) = eq_attr
;
1860 XEXP (ite
, 1) = val
;
1861 XEXP (ite
, 2) = str
;
1866 /* Alter the attribute vector of INSN, which is a COND_EXEC variant created
1867 from a define_insn pattern. We must modify the "predicable" attribute
1868 to be named "ce_enabled", and also change any "enabled" attribute that's
1869 present so that it takes ce_enabled into account.
1870 We rely on the fact that INSN was created with copy_rtx, and modify data
1874 alter_attrs_for_insn (rtx insn
)
1876 static bool global_changes_made
= false;
1877 rtvec vec
= XVEC (insn
, 4);
1881 int predicable_idx
= -1;
1882 int enabled_idx
= -1;
1888 num_elem
= GET_NUM_ELEM (vec
);
1889 for (i
= num_elem
- 1; i
>= 0; --i
)
1891 rtx sub
= RTVEC_ELT (vec
, i
);
1892 switch (GET_CODE (sub
))
1895 if (strcmp (XSTR (sub
, 0), "predicable") == 0)
1898 XSTR (sub
, 0) = "ce_enabled";
1900 else if (strcmp (XSTR (sub
, 0), "enabled") == 0)
1903 XSTR (sub
, 0) = "nonce_enabled";
1907 case SET_ATTR_ALTERNATIVE
:
1908 if (strcmp (XSTR (sub
, 0), "predicable") == 0)
1909 /* We already give an error elsewhere. */
1911 else if (strcmp (XSTR (sub
, 0), "enabled") == 0)
1914 XSTR (sub
, 0) = "nonce_enabled";
1919 if (GET_CODE (SET_DEST (sub
)) != ATTR
)
1921 if (strcmp (XSTR (SET_DEST (sub
), 0), "predicable") == 0)
1923 sub
= SET_SRC (sub
);
1924 if (GET_CODE (sub
) == CONST_STRING
)
1927 XSTR (sub
, 0) = "ce_enabled";
1930 /* We already give an error elsewhere. */
1934 if (strcmp (XSTR (SET_DEST (sub
), 0), "enabled") == 0)
1937 XSTR (SET_DEST (sub
), 0) = "nonce_enabled";
1945 if (predicable_idx
== -1)
1948 if (!global_changes_made
)
1950 class queue_elem
*elem
;
1952 global_changes_made
= true;
1953 add_define_attr ("ce_enabled");
1954 add_define_attr ("nonce_enabled");
1956 for (elem
= define_attr_queue
; elem
; elem
= elem
->next
)
1957 if (strcmp (XSTR (elem
->data
, 0), "enabled") == 0)
1959 XEXP (elem
->data
, 2)
1960 = modify_attr_enabled_ce (XEXP (elem
->data
, 2));
1963 if (enabled_idx
== -1)
1966 new_vec
= rtvec_alloc (num_elem
+ 1);
1967 for (i
= 0; i
< num_elem
; i
++)
1968 RTVEC_ELT (new_vec
, i
) = RTVEC_ELT (vec
, i
);
1969 val
= rtx_alloc (IF_THEN_ELSE
);
1970 XEXP (val
, 0) = rtx_alloc (EQ_ATTR
);
1971 XEXP (val
, 1) = rtx_alloc (CONST_STRING
);
1972 XEXP (val
, 2) = rtx_alloc (CONST_STRING
);
1973 XSTR (XEXP (val
, 0), 0) = "nonce_enabled";
1974 XSTR (XEXP (val
, 0), 1) = "yes";
1975 XSTR (XEXP (val
, 1), 0) = "yes";
1976 XSTR (XEXP (val
, 2), 0) = "no";
1977 set
= rtx_alloc (SET
);
1978 SET_DEST (set
) = rtx_alloc (ATTR
);
1979 XSTR (SET_DEST (set
), 0) = "enabled";
1980 SET_SRC (set
) = modify_attr_enabled_ce (val
);
1981 RTVEC_ELT (new_vec
, i
) = set
;
1982 XVEC (insn
, 4) = new_vec
;
1985 /* As number of constraints is changed after define_subst, we need to
1986 process attributes as well - we need to duplicate them the same way
1987 that we duplicated constraints in original pattern
1988 ELEM is a queue element, containing our rtl-template,
1989 N_DUP - multiplication factor. */
1991 alter_attrs_for_subst_insn (class queue_elem
* elem
, int n_dup
)
1993 rtvec vec
= XVEC (elem
->data
, 4);
1997 if (n_dup
< 2 || ! vec
)
2000 num_elem
= GET_NUM_ELEM (vec
);
2001 for (i
= num_elem
- 1; i
>= 0; --i
)
2003 rtx sub
= RTVEC_ELT (vec
, i
);
2004 switch (GET_CODE (sub
))
2007 if (strchr (XSTR (sub
, 1), ',') != NULL
)
2008 XSTR (sub
, 1) = duplicate_alternatives (XSTR (sub
, 1), n_dup
);
2011 case SET_ATTR_ALTERNATIVE
:
2013 error_at (elem
->loc
,
2014 "%s: `define_subst' does not support attributes "
2015 "assigned by `set' and `set_attr_alternative'",
2016 XSTR (elem
->data
, 0));
2025 /* Adjust all of the operand numbers in SRC to match the shift they'll
2026 get from an operand displacement of DISP. Return a pointer after the
2030 shift_output_template (char *dest
, const char *src
, int disp
)
2039 if (ISDIGIT ((unsigned char) c
))
2041 else if (ISALPHA (c
))
2054 alter_output_for_insn (class queue_elem
*ce_elem
,
2055 class queue_elem
*insn_elem
,
2056 int alt
, int max_op
)
2058 const char *ce_out
, *insn_out
;
2060 size_t len
, ce_len
, insn_len
;
2062 /* ??? Could coordinate with genoutput to not duplicate code here. */
2064 ce_out
= XSTR (ce_elem
->data
, 2);
2065 insn_out
= XTMPL (insn_elem
->data
, 3);
2066 if (!ce_out
|| *ce_out
== '\0')
2069 ce_len
= strlen (ce_out
);
2070 insn_len
= strlen (insn_out
);
2072 if (*insn_out
== '*')
2073 /* You must take care of the predicate yourself. */
2076 if (*insn_out
== '@')
2078 len
= (ce_len
+ 1) * alt
+ insn_len
+ 1;
2079 p
= result
= XNEWVEC (char, len
);
2085 while (ISSPACE ((unsigned char) *insn_out
));
2087 if (*insn_out
!= '#')
2089 p
= shift_output_template (p
, ce_out
, max_op
);
2095 while (*insn_out
&& *insn_out
!= '\n');
2102 len
= ce_len
+ 1 + insn_len
+ 1;
2103 result
= XNEWVEC (char, len
);
2105 p
= shift_output_template (result
, ce_out
, max_op
);
2107 memcpy (p
, insn_out
, insn_len
+ 1);
2113 /* From string STR "a,b,c" produce "a,b,c,a,b,c,a,b,c", i.e. original
2114 string, duplicated N_DUP times. */
2117 duplicate_alternatives (const char * str
, int n_dup
)
2119 int i
, len
, new_len
;
2126 while (ISSPACE (*str
))
2134 new_len
= (len
+ 1) * n_dup
;
2136 sp
= result
= XNEWVEC (char, new_len
);
2138 /* Global modifier characters mustn't be duplicated: skip if found. */
2139 if (*cp
== '=' || *cp
== '+' || *cp
== '%')
2145 /* Copy original constraints N_DUP times. */
2146 for (i
= 0; i
< n_dup
; i
++, sp
+= len
+1)
2148 memcpy (sp
, cp
, len
);
2149 *(sp
+len
) = (i
== n_dup
- 1) ? '\0' : ',';
2155 /* From string STR "a,b,c" produce "a,a,a,b,b,b,c,c,c", i.e. string where
2156 each alternative from the original string is duplicated N_DUP times. */
2158 duplicate_each_alternative (const char * str
, int n_dup
)
2160 int i
, len
, new_len
;
2161 char *result
, *sp
, *ep
, *cp
;
2166 while (ISSPACE (*str
))
2174 new_len
= (strlen (cp
) + 1) * n_dup
;
2176 sp
= result
= XNEWVEC (char, new_len
);
2178 /* Global modifier characters mustn't be duplicated: skip if found. */
2179 if (*cp
== '=' || *cp
== '+' || *cp
== '%')
2184 if ((ep
= strchr (cp
, ',')) != NULL
)
2188 /* Copy a constraint N_DUP times. */
2189 for (i
= 0; i
< n_dup
; i
++, sp
+= len
+ 1)
2191 memcpy (sp
, cp
, len
);
2192 *(sp
+len
) = (ep
== NULL
&& i
== n_dup
- 1) ? '\0' : ',';
2202 /* Alter the output of INSN whose pattern was modified by
2203 DEFINE_SUBST. We must replicate output strings according
2204 to the new number of alternatives ALT in substituted pattern.
2205 If ALT equals 1, output has one alternative or defined by C
2206 code, then output is returned without any changes. */
2209 alter_output_for_subst_insn (rtx insn
, int alt
)
2211 const char *insn_out
, *old_out
;
2213 size_t old_len
, new_len
;
2216 insn_out
= XTMPL (insn
, 3);
2218 if (alt
< 2 || *insn_out
!= '@')
2221 old_out
= insn_out
+ 1;
2222 while (ISSPACE (*old_out
))
2224 old_len
= strlen (old_out
);
2226 new_len
= alt
* (old_len
+ 1) + 1;
2228 new_out
= XNEWVEC (char, new_len
);
2231 for (j
= 0, cp
= new_out
+ 1; j
< alt
; j
++, cp
+= old_len
+ 1)
2233 memcpy (cp
, old_out
, old_len
);
2234 cp
[old_len
] = (j
== alt
- 1) ? '\0' : '\n';
2240 /* Replicate insns as appropriate for the given DEFINE_COND_EXEC. */
2243 process_one_cond_exec (class queue_elem
*ce_elem
)
2245 class queue_elem
*insn_elem
;
2246 for (insn_elem
= define_insn_queue
; insn_elem
; insn_elem
= insn_elem
->next
)
2248 int alternatives
, max_operand
;
2249 rtx pred
, insn
, pattern
, split
;
2253 if (! is_predicable (insn_elem
))
2258 collect_insn_data (insn_elem
->data
, &alternatives
, &max_operand
);
2261 if (XVECLEN (ce_elem
->data
, 0) != 1)
2263 error_at (ce_elem
->loc
, "too many patterns in predicate");
2267 pred
= copy_rtx (XVECEXP (ce_elem
->data
, 0, 0));
2268 pred
= alter_predicate_for_insn (pred
, alternatives
, max_operand
,
2273 /* Construct a new pattern for the new insn. */
2274 insn
= copy_rtx (insn_elem
->data
);
2275 new_name
= XNEWVAR (char, strlen
XSTR (insn_elem
->data
, 0) + 4);
2276 sprintf (new_name
, "*p %s", XSTR (insn_elem
->data
, 0));
2277 XSTR (insn
, 0) = new_name
;
2278 pattern
= rtx_alloc (COND_EXEC
);
2279 XEXP (pattern
, 0) = pred
;
2280 XEXP (pattern
, 1) = add_implicit_parallel (XVEC (insn
, 1));
2281 XVEC (insn
, 1) = rtvec_alloc (1);
2282 XVECEXP (insn
, 1, 0) = pattern
;
2284 if (XVEC (ce_elem
->data
, 3) != NULL
)
2286 rtvec attributes
= rtvec_alloc (XVECLEN (insn
, 4)
2287 + XVECLEN (ce_elem
->data
, 3));
2290 for (i
= 0; i
< XVECLEN (insn
, 4); i
++)
2291 RTVEC_ELT (attributes
, i
) = XVECEXP (insn
, 4, i
);
2293 for (j
= 0; j
< XVECLEN (ce_elem
->data
, 3); j
++, i
++)
2294 RTVEC_ELT (attributes
, i
) = XVECEXP (ce_elem
->data
, 3, j
);
2296 XVEC (insn
, 4) = attributes
;
2299 XSTR (insn
, 2) = alter_test_for_insn (ce_elem
, insn_elem
);
2300 XTMPL (insn
, 3) = alter_output_for_insn (ce_elem
, insn_elem
,
2301 alternatives
, max_operand
);
2302 alter_attrs_for_insn (insn
);
2304 /* Put the new pattern on the `other' list so that it
2305 (a) is not reprocessed by other define_cond_exec patterns
2306 (b) appears after all normal define_insn patterns.
2308 ??? B is debatable. If one has normal insns that match
2309 cond_exec patterns, they will be preferred over these
2310 generated patterns. Whether this matters in practice, or if
2311 it's a good thing, or whether we should thread these new
2312 patterns into the define_insn chain just after their generator
2313 is something we'll have to experiment with. */
2315 queue_pattern (insn
, &other_tail
, insn_elem
->loc
);
2317 if (!insn_elem
->split
)
2320 /* If the original insn came from a define_insn_and_split,
2321 generate a new split to handle the predicated insn. */
2322 split
= copy_rtx (insn_elem
->split
->data
);
2323 /* Predicate the pattern matched by the split. */
2324 pattern
= rtx_alloc (COND_EXEC
);
2325 XEXP (pattern
, 0) = pred
;
2326 XEXP (pattern
, 1) = add_implicit_parallel (XVEC (split
, 0));
2327 XVEC (split
, 0) = rtvec_alloc (1);
2328 XVECEXP (split
, 0, 0) = pattern
;
2330 /* Predicate all of the insns generated by the split. */
2331 for (i
= 0; i
< XVECLEN (split
, 2); i
++)
2333 pattern
= rtx_alloc (COND_EXEC
);
2334 XEXP (pattern
, 0) = pred
;
2335 XEXP (pattern
, 1) = XVECEXP (split
, 2, i
);
2336 XVECEXP (split
, 2, i
) = pattern
;
2338 /* Add the new split to the queue. */
2339 queue_pattern (split
, &other_tail
, insn_elem
->split
->loc
);
2343 /* Try to apply define_substs to the given ELEM.
2344 Only define_substs, specified via attributes would be applied.
2345 If attribute, requiring define_subst, is set, but no define_subst
2346 was applied, ELEM would be deleted. */
2349 process_substs_on_one_elem (class queue_elem
*elem
,
2350 class queue_elem
*queue
)
2352 class queue_elem
*subst_elem
;
2353 int i
, j
, patterns_match
;
2355 for (subst_elem
= define_subst_queue
;
2356 subst_elem
; subst_elem
= subst_elem
->next
)
2358 int alternatives
, alternatives_subst
;
2360 rtvec subst_pattern_vec
;
2362 if (!has_subst_attribute (elem
, subst_elem
))
2365 /* Compare original rtl-pattern from define_insn with input
2366 pattern from define_subst.
2367 Also, check if numbers of alternatives are the same in all
2369 if (XVECLEN (elem
->data
, 1) != XVECLEN (subst_elem
->data
, 1))
2373 alternatives_subst
= -1;
2374 for (j
= 0; j
< XVECLEN (elem
->data
, 1); j
++)
2376 if (!subst_pattern_match (XVECEXP (elem
->data
, 1, j
),
2377 XVECEXP (subst_elem
->data
, 1, j
),
2384 if (!get_alternatives_number (XVECEXP (elem
->data
, 1, j
),
2385 &alternatives
, subst_elem
->loc
))
2392 /* Check if numbers of alternatives are the same in all
2393 match_operands in output template of define_subst. */
2394 for (j
= 0; j
< XVECLEN (subst_elem
->data
, 3); j
++)
2396 if (!get_alternatives_number (XVECEXP (subst_elem
->data
, 3, j
),
2397 &alternatives_subst
,
2405 if (!patterns_match
)
2408 /* Clear array in which we save occupied indexes of operands. */
2409 memset (used_operands_numbers
, 0, sizeof (used_operands_numbers
));
2411 /* Create a pattern, based on the output one from define_subst. */
2412 subst_pattern_vec
= rtvec_alloc (XVECLEN (subst_elem
->data
, 3));
2413 for (j
= 0; j
< XVECLEN (subst_elem
->data
, 3); j
++)
2415 subst_pattern
= copy_rtx (XVECEXP (subst_elem
->data
, 3, j
));
2417 /* Duplicate constraints in substitute-pattern. */
2418 subst_pattern
= alter_constraints (subst_pattern
, alternatives
,
2419 duplicate_each_alternative
);
2421 subst_pattern
= adjust_operands_numbers (subst_pattern
);
2423 /* Substitute match_dup and match_op_dup in the new pattern and
2424 duplicate constraints. */
2425 subst_pattern
= subst_dup (subst_pattern
, alternatives
,
2426 alternatives_subst
);
2428 replace_duplicating_operands_in_pattern (subst_pattern
);
2430 /* We don't need any constraints in DEFINE_EXPAND. */
2431 if (GET_CODE (elem
->data
) == DEFINE_EXPAND
)
2432 remove_constraints (subst_pattern
);
2434 RTVEC_ELT (subst_pattern_vec
, j
) = subst_pattern
;
2436 XVEC (elem
->data
, 1) = subst_pattern_vec
;
2438 for (i
= 0; i
< MAX_OPERANDS
; i
++)
2439 match_operand_entries_in_pattern
[i
] = NULL
;
2441 if (GET_CODE (elem
->data
) == DEFINE_INSN
)
2443 XTMPL (elem
->data
, 3) =
2444 alter_output_for_subst_insn (elem
->data
, alternatives_subst
);
2445 alter_attrs_for_subst_insn (elem
, alternatives_subst
);
2448 /* Recalculate condition, joining conditions from original and
2449 DEFINE_SUBST input patterns. */
2450 XSTR (elem
->data
, 2)
2451 = rtx_reader_ptr
->join_c_conditions (XSTR (subst_elem
->data
, 2),
2452 XSTR (elem
->data
, 2));
2453 /* Mark that subst was applied by changing attribute from "yes"
2455 change_subst_attribute (elem
, subst_elem
, subst_false
);
2458 /* If ELEM contains a subst attribute with value "yes", then we
2459 expected that a subst would be applied, but it wasn't - so,
2460 we need to remove that elementto avoid duplicating. */
2461 for (subst_elem
= define_subst_queue
;
2462 subst_elem
; subst_elem
= subst_elem
->next
)
2464 if (has_subst_attribute (elem
, subst_elem
))
2466 remove_from_queue (elem
, &queue
);
2472 /* This is a subroutine of mark_operands_used_in_match_dup.
2473 This routine is marks all MATCH_OPERANDs inside PATTERN as occupied. */
2475 mark_operands_from_match_dup (rtx pattern
)
2478 int i
, j
, len
, opno
;
2480 if (GET_CODE (pattern
) == MATCH_OPERAND
2481 || GET_CODE (pattern
) == MATCH_OPERATOR
2482 || GET_CODE (pattern
) == MATCH_PARALLEL
)
2484 opno
= XINT (pattern
, 0);
2485 gcc_assert (opno
>= 0 && opno
< MAX_OPERANDS
);
2486 used_operands_numbers
[opno
] = 1;
2488 fmt
= GET_RTX_FORMAT (GET_CODE (pattern
));
2489 len
= GET_RTX_LENGTH (GET_CODE (pattern
));
2490 for (i
= 0; i
< len
; i
++)
2495 mark_operands_from_match_dup (XEXP (pattern
, i
));
2498 for (j
= XVECLEN (pattern
, i
) - 1; j
>= 0; --j
)
2499 mark_operands_from_match_dup (XVECEXP (pattern
, i
, j
));
2505 /* This is a subroutine of adjust_operands_numbers.
2506 It goes through all expressions in PATTERN and when MATCH_DUP is
2507 met, all MATCH_OPERANDs inside it is marked as occupied. The
2508 process of marking is done by routin mark_operands_from_match_dup. */
2510 mark_operands_used_in_match_dup (rtx pattern
)
2513 int i
, j
, len
, opno
;
2515 if (GET_CODE (pattern
) == MATCH_DUP
)
2517 opno
= XINT (pattern
, 0);
2518 gcc_assert (opno
>= 0 && opno
< MAX_OPERANDS
);
2519 mark_operands_from_match_dup (operand_data
[opno
]);
2522 fmt
= GET_RTX_FORMAT (GET_CODE (pattern
));
2523 len
= GET_RTX_LENGTH (GET_CODE (pattern
));
2524 for (i
= 0; i
< len
; i
++)
2529 mark_operands_used_in_match_dup (XEXP (pattern
, i
));
2532 for (j
= XVECLEN (pattern
, i
) - 1; j
>= 0; --j
)
2533 mark_operands_used_in_match_dup (XVECEXP (pattern
, i
, j
));
2539 /* This is subroutine of renumerate_operands_in_pattern.
2540 It finds first not-occupied operand-index. */
2542 find_first_unused_number_of_operand ()
2545 for (i
= 0; i
< MAX_OPERANDS
; i
++)
2546 if (!used_operands_numbers
[i
])
2548 return MAX_OPERANDS
;
2551 /* This is subroutine of adjust_operands_numbers.
2552 It visits all expressions in PATTERN and assigns not-occupied
2553 operand indexes to MATCH_OPERANDs and MATCH_OPERATORs of this
2556 renumerate_operands_in_pattern (rtx pattern
)
2560 int i
, j
, len
, new_opno
;
2561 code
= GET_CODE (pattern
);
2563 if (code
== MATCH_OPERAND
2564 || code
== MATCH_OPERATOR
)
2566 new_opno
= find_first_unused_number_of_operand ();
2567 gcc_assert (new_opno
>= 0 && new_opno
< MAX_OPERANDS
);
2568 XINT (pattern
, 0) = new_opno
;
2569 used_operands_numbers
[new_opno
] = 1;
2572 fmt
= GET_RTX_FORMAT (GET_CODE (pattern
));
2573 len
= GET_RTX_LENGTH (GET_CODE (pattern
));
2574 for (i
= 0; i
< len
; i
++)
2579 renumerate_operands_in_pattern (XEXP (pattern
, i
));
2582 for (j
= XVECLEN (pattern
, i
) - 1; j
>= 0; --j
)
2583 renumerate_operands_in_pattern (XVECEXP (pattern
, i
, j
));
2589 /* If output pattern of define_subst contains MATCH_DUP, then this
2590 expression would be replaced with the pattern, matched with
2591 MATCH_OPERAND from input pattern. This pattern could contain any
2592 number of MATCH_OPERANDs, MATCH_OPERATORs etc., so it's possible
2593 that a MATCH_OPERAND from output_pattern (if any) would have the
2594 same number, as MATCH_OPERAND from copied pattern. To avoid such
2595 indexes overlapping, we assign new indexes to MATCH_OPERANDs,
2596 laying in the output pattern outside of MATCH_DUPs. */
2598 adjust_operands_numbers (rtx pattern
)
2600 mark_operands_used_in_match_dup (pattern
);
2602 renumerate_operands_in_pattern (pattern
);
2607 /* Generate RTL expression
2611 generate_match_dup (int opno
)
2613 rtx return_rtx
= rtx_alloc (MATCH_DUP
);
2614 PUT_CODE (return_rtx
, MATCH_DUP
);
2615 XINT (return_rtx
, 0) = opno
;
2619 /* This routine checks all match_operands in PATTERN and if some of
2620 have the same index, it replaces all of them except the first one to
2622 Usually, match_operands with the same indexes are forbidden, but
2623 after define_subst copy an RTL-expression from original template,
2624 indexes of existed and just-copied match_operands could coincide.
2625 To fix it, we replace one of them with match_dup. */
2627 replace_duplicating_operands_in_pattern (rtx pattern
)
2630 int i
, j
, len
, opno
;
2633 if (GET_CODE (pattern
) == MATCH_OPERAND
)
2635 opno
= XINT (pattern
, 0);
2636 gcc_assert (opno
>= 0 && opno
< MAX_OPERANDS
);
2637 if (match_operand_entries_in_pattern
[opno
] == NULL
)
2639 match_operand_entries_in_pattern
[opno
] = pattern
;
2644 /* Compare predicates before replacing with match_dup. */
2645 if (strcmp (XSTR (pattern
, 1),
2646 XSTR (match_operand_entries_in_pattern
[opno
], 1)))
2648 error ("duplicated match_operands with different predicates were"
2652 return generate_match_dup (opno
);
2655 fmt
= GET_RTX_FORMAT (GET_CODE (pattern
));
2656 len
= GET_RTX_LENGTH (GET_CODE (pattern
));
2657 for (i
= 0; i
< len
; i
++)
2662 mdup
= replace_duplicating_operands_in_pattern (XEXP (pattern
, i
));
2664 XEXP (pattern
, i
) = mdup
;
2667 for (j
= XVECLEN (pattern
, i
) - 1; j
>= 0; --j
)
2670 replace_duplicating_operands_in_pattern (XVECEXP
2673 XVECEXP (pattern
, i
, j
) = mdup
;
2681 /* The routine modifies given input PATTERN of define_subst, replacing
2682 MATCH_DUP and MATCH_OP_DUP with operands from define_insn original
2683 pattern, whose operands are stored in OPERAND_DATA array.
2684 It also duplicates constraints in operands - constraints from
2685 define_insn operands are duplicated N_SUBST_ALT times, constraints
2686 from define_subst operands are duplicated N_ALT times.
2687 After the duplication, returned output rtl-pattern contains every
2688 combination of input constraints Vs constraints from define_subst
2691 subst_dup (rtx pattern
, int n_alt
, int n_subst_alt
)
2695 int i
, j
, len
, opno
;
2697 code
= GET_CODE (pattern
);
2702 opno
= XINT (pattern
, 0);
2704 gcc_assert (opno
>= 0 && opno
< MAX_OPERANDS
);
2706 if (operand_data
[opno
])
2708 pattern
= copy_rtx (operand_data
[opno
]);
2710 /* Duplicate constraints. */
2711 pattern
= alter_constraints (pattern
, n_subst_alt
,
2712 duplicate_alternatives
);
2720 fmt
= GET_RTX_FORMAT (GET_CODE (pattern
));
2721 len
= GET_RTX_LENGTH (GET_CODE (pattern
));
2722 for (i
= 0; i
< len
; i
++)
2727 if (code
!= MATCH_DUP
&& code
!= MATCH_OP_DUP
)
2728 XEXP (pattern
, i
) = subst_dup (XEXP (pattern
, i
),
2729 n_alt
, n_subst_alt
);
2732 if (XVEC (pattern
, i
) == NULL
)
2736 if (code
!= MATCH_DUP
&& code
!= MATCH_OP_DUP
)
2737 for (j
= XVECLEN (pattern
, i
) - 1; j
>= 0; --j
)
2738 XVECEXP (pattern
, i
, j
) = subst_dup (XVECEXP (pattern
, i
, j
),
2739 n_alt
, n_subst_alt
);
2742 case 'r': case 'p': case 'i': case 'w':
2743 case '0': case 's': case 'S': case 'T':
2753 /* If we have any DEFINE_COND_EXEC patterns, expand the DEFINE_INSN
2754 patterns appropriately. */
2757 process_define_cond_exec (void)
2759 class queue_elem
*elem
;
2761 identify_predicable_attribute ();
2765 for (elem
= define_cond_exec_queue
; elem
; elem
= elem
->next
)
2766 process_one_cond_exec (elem
);
2769 /* If we have any DEFINE_SUBST patterns, expand DEFINE_INSN and
2770 DEFINE_EXPAND patterns appropriately. */
2773 process_define_subst (void)
2775 class queue_elem
*elem
, *elem_attr
;
2777 /* Check if each define_subst has corresponding define_subst_attr. */
2778 for (elem
= define_subst_queue
; elem
; elem
= elem
->next
)
2780 for (elem_attr
= define_subst_attr_queue
;
2782 elem_attr
= elem_attr
->next
)
2783 if (strcmp (XSTR (elem
->data
, 0), XSTR (elem_attr
->data
, 1)) == 0)
2786 error_at (elem
->loc
,
2787 "%s: `define_subst' must have at least one "
2788 "corresponding `define_subst_attr'",
2789 XSTR (elem
->data
, 0));
2796 for (elem
= define_insn_queue
; elem
; elem
= elem
->next
)
2797 process_substs_on_one_elem (elem
, define_insn_queue
);
2798 for (elem
= other_queue
; elem
; elem
= elem
->next
)
2800 if (GET_CODE (elem
->data
) != DEFINE_EXPAND
)
2802 process_substs_on_one_elem (elem
, other_queue
);
2806 /* A subclass of rtx_reader which reads .md files and calls process_rtx on
2807 the top-level elements. */
2809 class gen_reader
: public rtx_reader
2812 gen_reader () : rtx_reader (false) {}
2813 void handle_unknown_directive (file_location
, const char *) final override
;
2817 gen_reader::handle_unknown_directive (file_location loc
, const char *rtx_name
)
2819 auto_vec
<rtx
, 32> subrtxs
;
2820 if (!read_rtx (rtx_name
, &subrtxs
))
2825 FOR_EACH_VEC_ELT (subrtxs
, i
, x
)
2826 process_rtx (x
, loc
);
2829 /* Add mnemonic STR with length LEN to the mnemonic hash table
2830 MNEMONIC_HTAB. A trailing zero end character is appended to STR
2831 and a permanent heap copy of STR is created. */
2834 add_mnemonic_string (htab_t mnemonic_htab
, const char *str
, size_t len
)
2838 char *str_zero
= (char*)alloca (len
+ 1);
2840 memcpy (str_zero
, str
, len
);
2841 str_zero
[len
] = '\0';
2843 slot
= htab_find_slot (mnemonic_htab
, str_zero
, INSERT
);
2848 /* Not found; create a permanent copy and add it to the hash table. */
2849 new_str
= XNEWVAR (char, len
+ 1);
2850 memcpy (new_str
, str_zero
, len
+ 1);
2854 /* Scan INSN for mnemonic strings and add them to the mnemonic hash
2855 table in MNEMONIC_HTAB.
2857 The mnemonics cannot be found if they are emitted using C code.
2859 If a mnemonic string contains ';' or a newline the string assumed
2860 to consist of more than a single instruction. The attribute value
2861 will then be set to the user defined default value. */
2864 gen_mnemonic_setattr (htab_t mnemonic_htab
, rtx insn
)
2866 const char *template_code
, *cp
;
2872 struct obstack
*string_obstack
= rtx_reader_ptr
->get_string_obstack ();
2874 template_code
= XTMPL (insn
, 3);
2876 /* Skip patterns which use C code to emit the template. */
2877 if (template_code
[0] == '*')
2880 if (template_code
[0] == '@')
2881 cp
= &template_code
[1];
2883 cp
= &template_code
[0];
2887 const char *ep
, *sp
;
2890 while (ISSPACE (*cp
))
2893 for (ep
= sp
= cp
; !IS_VSPACE (*ep
) && *ep
!= '\0'; ++ep
)
2898 obstack_1grow (string_obstack
, ',');
2900 while (cp
< sp
&& ((*cp
>= '0' && *cp
<= '9')
2901 || (*cp
>= 'a' && *cp
<= 'z')))
2904 obstack_1grow (string_obstack
, *cp
);
2911 if (*cp
== ';' || (*cp
== '\\' && cp
[1] == 'n'))
2913 /* Don't set a value if there are more than one
2914 instruction in the string. */
2915 obstack_blank_fast (string_obstack
, -size
);
2924 obstack_1grow (string_obstack
, '*');
2926 add_mnemonic_string (mnemonic_htab
,
2927 (char *) obstack_next_free (string_obstack
) - size
,
2932 /* An insn definition might emit an empty string. */
2933 if (obstack_object_size (string_obstack
) == 0)
2936 obstack_1grow (string_obstack
, '\0');
2938 set_attr
= rtx_alloc (SET_ATTR
);
2939 XSTR (set_attr
, 1) = XOBFINISH (string_obstack
, char *);
2940 attr_name
= XNEWVAR (char, strlen (MNEMONIC_ATTR_NAME
) + 1);
2941 strcpy (attr_name
, MNEMONIC_ATTR_NAME
);
2942 XSTR (set_attr
, 0) = attr_name
;
2944 if (!XVEC (insn
, 4))
2947 vec_len
= XVECLEN (insn
, 4);
2949 new_vec
= rtvec_alloc (vec_len
+ 1);
2950 for (i
= 0; i
< vec_len
; i
++)
2951 RTVEC_ELT (new_vec
, i
) = XVECEXP (insn
, 4, i
);
2952 RTVEC_ELT (new_vec
, vec_len
) = set_attr
;
2953 XVEC (insn
, 4) = new_vec
;
2956 /* This function is called for the elements in the mnemonic hashtable
2957 and generates a comma separated list of the mnemonics. */
2960 mnemonic_htab_callback (void **slot
, void *info ATTRIBUTE_UNUSED
)
2962 struct obstack
*string_obstack
= rtx_reader_ptr
->get_string_obstack ();
2964 obstack_grow (string_obstack
, (char*) *slot
, strlen ((char*) *slot
));
2965 obstack_1grow (string_obstack
, ',');
2969 /* Generate (set_attr "mnemonic" "..") RTXs and append them to every
2970 insn definition in case the back end requests it by defining the
2971 mnemonic attribute. The values for the attribute will be extracted
2972 from the output patterns of the insn definitions as far as
2976 gen_mnemonic_attr (void)
2978 class queue_elem
*elem
;
2979 rtx mnemonic_attr
= NULL
;
2980 htab_t mnemonic_htab
;
2981 const char *str
, *p
;
2983 struct obstack
*string_obstack
= rtx_reader_ptr
->get_string_obstack ();
2988 /* Look for the DEFINE_ATTR for `mnemonic'. */
2989 for (elem
= define_attr_queue
; elem
!= *define_attr_tail
; elem
= elem
->next
)
2990 if (GET_CODE (elem
->data
) == DEFINE_ATTR
2991 && strcmp (XSTR (elem
->data
, 0), MNEMONIC_ATTR_NAME
) == 0)
2993 mnemonic_attr
= elem
->data
;
2997 /* A (define_attr "mnemonic" "...") indicates that the back-end
2998 wants a mnemonic attribute to be generated. */
3002 mnemonic_htab
= htab_create_alloc (MNEMONIC_HTAB_SIZE
, htab_hash_string
,
3003 htab_eq_string
, 0, xcalloc
, free
);
3005 for (elem
= define_insn_queue
; elem
; elem
= elem
->next
)
3007 rtx insn
= elem
->data
;
3010 /* Check if the insn definition already has
3011 (set_attr "mnemonic" ...) or (set (attr "mnemonic") ...). */
3013 for (i
= 0; i
< XVECLEN (insn
, 4); i
++)
3015 rtx set_attr
= XVECEXP (insn
, 4, i
);
3017 switch (GET_CODE (set_attr
))
3020 case SET_ATTR_ALTERNATIVE
:
3021 if (strcmp (XSTR (set_attr
, 0), MNEMONIC_ATTR_NAME
) == 0)
3025 if (GET_CODE (SET_DEST (set_attr
)) == ATTR
3026 && strcmp (XSTR (SET_DEST (set_attr
), 0),
3027 MNEMONIC_ATTR_NAME
) == 0)
3036 gen_mnemonic_setattr (mnemonic_htab
, insn
);
3039 /* Add the user defined values to the hash table. */
3040 str
= XSTR (mnemonic_attr
, 1);
3041 while ((p
= scan_comma_elt (&str
)) != NULL
)
3042 add_mnemonic_string (mnemonic_htab
, p
, str
- p
);
3044 htab_traverse (mnemonic_htab
, mnemonic_htab_callback
, NULL
);
3046 /* Replace the last ',' with the zero end character. */
3047 *((char *) obstack_next_free (string_obstack
) - 1) = '\0';
3048 XSTR (mnemonic_attr
, 1) = XOBFINISH (string_obstack
, char *);
3051 /* Check if there are DEFINE_ATTRs with the same name. */
3053 check_define_attr_duplicates ()
3055 class queue_elem
*elem
;
3060 attr_htab
= htab_create (500, htab_hash_string
, htab_eq_string
, NULL
);
3062 for (elem
= define_attr_queue
; elem
; elem
= elem
->next
)
3064 attr_name
= xstrdup (XSTR (elem
->data
, 0));
3066 slot
= htab_find_slot (attr_htab
, attr_name
, INSERT
);
3071 error_at (elem
->loc
, "redefinition of attribute '%s'", attr_name
);
3072 htab_delete (attr_htab
);
3079 htab_delete (attr_htab
);
3082 /* The entry point for initializing the reader. */
3085 init_rtx_reader_args_cb (int argc
, const char **argv
,
3086 bool (*parse_opt
) (const char *))
3088 /* Prepare to read input. */
3089 condition_table
= htab_create (500, hash_c_test
, cmp_c_test
, NULL
);
3090 init_predicate_table ();
3091 obstack_init (rtl_obstack
);
3093 /* Start at 1, to make 0 available for CODE_FOR_nothing. */
3094 insn_sequence_num
= 1;
3096 /* These sequences are not used as indices, so can start at 1 also. */
3097 split_sequence_num
= 1;
3098 peephole2_sequence_num
= 1;
3100 gen_reader
*reader
= new gen_reader ();
3101 reader
->read_md_files (argc
, argv
, parse_opt
);
3103 if (define_attr_queue
!= NULL
)
3104 check_define_attr_duplicates ();
3106 /* Process define_cond_exec patterns. */
3107 if (define_cond_exec_queue
!= NULL
)
3108 process_define_cond_exec ();
3110 /* Process define_subst patterns. */
3111 if (define_subst_queue
!= NULL
)
3112 process_define_subst ();
3114 if (define_attr_queue
!= NULL
)
3115 gen_mnemonic_attr ();
3126 /* Programs that don't have their own options can use this entry point
3129 init_rtx_reader_args (int argc
, const char **argv
)
3131 return init_rtx_reader_args_cb (argc
, argv
, 0);
3134 /* Try to read a single rtx from the file. Return true on success,
3135 describing it in *INFO. */
3138 read_md_rtx (md_rtx_info
*info
)
3140 int truth
, *counter
;
3143 /* Discard insn patterns which we know can never match (because
3144 their C test is provably always false). If insn_elision is
3145 false, our caller needs to see all the patterns. Note that the
3146 elided patterns are never counted by the sequence numbering; it
3147 is the caller's responsibility, when insn_elision is false, not
3148 to use elided pattern numbers for anything. */
3151 class queue_elem
**queue
, *elem
;
3153 /* Read all patterns from a given queue before moving on to the next. */
3154 if (define_attr_queue
!= NULL
)
3155 queue
= &define_attr_queue
;
3156 else if (define_pred_queue
!= NULL
)
3157 queue
= &define_pred_queue
;
3158 else if (define_insn_queue
!= NULL
)
3159 queue
= &define_insn_queue
;
3160 else if (other_queue
!= NULL
)
3161 queue
= &other_queue
;
3166 *queue
= elem
->next
;
3169 info
->loc
= elem
->loc
;
3172 truth
= maybe_eval_c_test (get_c_test (def
));
3174 while (truth
== 0 && insn_elision
);
3176 /* Perform code-specific processing and pick the appropriate sequence
3178 switch (GET_CODE (def
))
3182 /* insn_sequence_num is used here so the name table will match caller's
3183 idea of insn numbering, whether or not elision is active. */
3184 record_insn_name (insn_sequence_num
, XSTR (def
, 0));
3187 case DEFINE_PEEPHOLE
:
3188 counter
= &insn_sequence_num
;
3192 counter
= &split_sequence_num
;
3195 case DEFINE_PEEPHOLE2
:
3196 counter
= &peephole2_sequence_num
;
3206 info
->index
= *counter
;
3214 rtx_locs
= new hash_map
<rtx
, file_location
>;
3215 rtx_locs
->put (info
->def
, info
->loc
);
3220 /* Return the file location of DEFINE_* rtx X, which was previously
3221 returned by read_md_rtx. */
3223 get_file_location (rtx x
)
3225 gcc_assert (rtx_locs
);
3226 file_location
*entry
= rtx_locs
->get (x
);
3231 /* Return the number of possible INSN_CODEs. Only meaningful once the
3232 whole file has been processed. */
3234 get_num_insn_codes ()
3236 return insn_sequence_num
;
3239 /* Return the C test that says whether definition rtx DEF can be used,
3240 or "" if it can be used unconditionally. */
3245 switch (GET_CODE (x
))
3253 case DEFINE_PEEPHOLE
:
3254 case DEFINE_PEEPHOLE2
:
3262 /* Helper functions for insn elision. */
3264 /* Compute a hash function of a c_test structure, which is keyed
3265 by its ->expr field. */
3267 hash_c_test (const void *x
)
3269 const struct c_test
*a
= (const struct c_test
*) x
;
3270 const unsigned char *base
, *s
= (const unsigned char *) a
->expr
;
3278 while ((c
= *s
++) != '\0')
3280 hash
+= c
+ (c
<< 17);
3285 hash
+= len
+ (len
<< 17);
3291 /* Compare two c_test expression structures. */
3293 cmp_c_test (const void *x
, const void *y
)
3295 const struct c_test
*a
= (const struct c_test
*) x
;
3296 const struct c_test
*b
= (const struct c_test
*) y
;
3298 return !strcmp (a
->expr
, b
->expr
);
3301 /* Given a string representing a C test expression, look it up in the
3302 condition_table and report whether or not its value is known
3303 at compile time. Returns a tristate: 1 for known true, 0 for
3304 known false, -1 for unknown. */
3306 maybe_eval_c_test (const char *expr
)
3308 const struct c_test
*test
;
3309 struct c_test dummy
;
3315 test
= (const struct c_test
*)htab_find (condition_table
, &dummy
);
3321 /* Record the C test expression EXPR in the condition_table, with
3322 value VAL. Duplicates clobber previous entries. */
3325 add_c_test (const char *expr
, int value
)
3327 struct c_test
*test
;
3332 test
= XNEW (struct c_test
);
3334 test
->value
= value
;
3336 *(htab_find_slot (condition_table
, test
, INSERT
)) = test
;
3339 /* For every C test, call CALLBACK with two arguments: a pointer to
3340 the condition structure and INFO. Stops when CALLBACK returns zero. */
3342 traverse_c_tests (htab_trav callback
, void *info
)
3344 if (condition_table
)
3345 htab_traverse (condition_table
, callback
, info
);
3348 /* Helper functions for define_predicate and define_special_predicate
3349 processing. Shared between genrecog.cc and genpreds.cc. */
3351 static htab_t predicate_table
;
3352 struct pred_data
*first_predicate
;
3353 static struct pred_data
**last_predicate
= &first_predicate
;
3356 hash_struct_pred_data (const void *ptr
)
3358 return htab_hash_string (((const struct pred_data
*)ptr
)->name
);
3362 eq_struct_pred_data (const void *a
, const void *b
)
3364 return !strcmp (((const struct pred_data
*)a
)->name
,
3365 ((const struct pred_data
*)b
)->name
);
3369 lookup_predicate (const char *name
)
3371 struct pred_data key
;
3373 return (struct pred_data
*) htab_find (predicate_table
, &key
);
3376 /* Record that predicate PRED can accept CODE. */
3379 add_predicate_code (struct pred_data
*pred
, enum rtx_code code
)
3381 if (!pred
->codes
[code
])
3384 pred
->codes
[code
] = true;
3386 if (GET_RTX_CLASS (code
) != RTX_CONST_OBJ
)
3387 pred
->allows_non_const
= true;
3394 && code
!= STRICT_LOW_PART
3395 && code
!= ZERO_EXTRACT
3397 pred
->allows_non_lvalue
= true;
3399 if (pred
->num_codes
== 1)
3400 pred
->singleton
= code
;
3401 else if (pred
->num_codes
== 2)
3402 pred
->singleton
= UNKNOWN
;
3407 add_predicate (struct pred_data
*pred
)
3409 void **slot
= htab_find_slot (predicate_table
, pred
, INSERT
);
3412 error ("duplicate predicate definition for '%s'", pred
->name
);
3416 *last_predicate
= pred
;
3417 last_predicate
= &pred
->next
;
3420 /* This array gives the initial content of the predicate table. It
3421 has entries for all predicates defined in recog.cc. */
3423 struct std_pred_table
3427 bool allows_const_p
;
3428 RTX_CODE codes
[NUM_RTX_CODE
];
3431 static const struct std_pred_table std_preds
[] = {
3432 {"general_operand", false, true, {SUBREG
, REG
, MEM
}},
3433 {"address_operand", true, true, {SUBREG
, REG
, MEM
, PLUS
, MINUS
, MULT
,
3434 ZERO_EXTEND
, SIGN_EXTEND
, AND
}},
3435 {"register_operand", false, false, {SUBREG
, REG
}},
3436 {"pmode_register_operand", true, false, {SUBREG
, REG
}},
3437 {"scratch_operand", false, false, {SCRATCH
, REG
}},
3438 {"immediate_operand", false, true, {UNKNOWN
}},
3439 {"const_int_operand", false, false, {CONST_INT
}},
3440 #if TARGET_SUPPORTS_WIDE_INT
3441 {"const_scalar_int_operand", false, false, {CONST_INT
, CONST_WIDE_INT
}},
3442 {"const_double_operand", false, false, {CONST_DOUBLE
}},
3444 {"const_double_operand", false, false, {CONST_INT
, CONST_DOUBLE
}},
3446 {"nonimmediate_operand", false, false, {SUBREG
, REG
, MEM
}},
3447 {"nonmemory_operand", false, true, {SUBREG
, REG
}},
3448 {"push_operand", false, false, {MEM
}},
3449 {"pop_operand", false, false, {MEM
}},
3450 {"memory_operand", false, false, {SUBREG
, MEM
}},
3451 {"indirect_operand", false, false, {SUBREG
, MEM
}},
3452 {"ordered_comparison_operator", false, false, {EQ
, NE
,
3454 LEU
, LTU
, GEU
, GTU
}},
3455 {"comparison_operator", false, false, {EQ
, NE
,
3462 #define NUM_KNOWN_STD_PREDS ARRAY_SIZE (std_preds)
3464 /* Initialize the table of predicate definitions, starting with
3465 the information we have on generic predicates. */
3468 init_predicate_table (void)
3471 struct pred_data
*pred
;
3473 predicate_table
= htab_create_alloc (37, hash_struct_pred_data
,
3474 eq_struct_pred_data
, 0,
3477 for (i
= 0; i
< NUM_KNOWN_STD_PREDS
; i
++)
3479 pred
= XCNEW (struct pred_data
);
3480 pred
->name
= std_preds
[i
].name
;
3481 pred
->special
= std_preds
[i
].special
;
3483 for (j
= 0; std_preds
[i
].codes
[j
] != 0; j
++)
3484 add_predicate_code (pred
, std_preds
[i
].codes
[j
]);
3486 if (std_preds
[i
].allows_const_p
)
3487 for (j
= 0; j
< NUM_RTX_CODE
; j
++)
3488 if (GET_RTX_CLASS (j
) == RTX_CONST_OBJ
)
3489 add_predicate_code (pred
, (enum rtx_code
) j
);
3491 add_predicate (pred
);
3495 /* These functions allow linkage with print-rtl.cc. Also, some generators
3496 like to annotate their output with insn names. */
3498 /* Holds an array of names indexed by insn_code_number. */
3499 static char **insn_name_ptr
= 0;
3500 static int insn_name_ptr_size
= 0;
3503 get_insn_name (int code
)
3505 if (code
< insn_name_ptr_size
)
3506 return insn_name_ptr
[code
];
3512 record_insn_name (int code
, const char *name
)
3514 static const char *last_real_name
= "insn";
3515 static int last_real_code
= 0;
3518 if (insn_name_ptr_size
<= code
)
3521 new_size
= (insn_name_ptr_size
? insn_name_ptr_size
* 2 : 512);
3522 insn_name_ptr
= XRESIZEVEC (char *, insn_name_ptr
, new_size
);
3523 memset (insn_name_ptr
+ insn_name_ptr_size
, 0,
3524 sizeof (char *) * (new_size
- insn_name_ptr_size
));
3525 insn_name_ptr_size
= new_size
;
3528 if (!name
|| name
[0] == '\0')
3530 new_name
= XNEWVAR (char, strlen (last_real_name
) + 10);
3531 sprintf (new_name
, "%s+%d", last_real_name
, code
- last_real_code
);
3535 last_real_name
= new_name
= xstrdup (name
);
3536 last_real_code
= code
;
3539 insn_name_ptr
[code
] = new_name
;
3542 /* Make STATS describe the operands that appear in rtx X. */
3545 get_pattern_stats_1 (struct pattern_stats
*stats
, rtx x
)
3555 code
= GET_CODE (x
);
3559 case MATCH_OPERATOR
:
3560 case MATCH_PARALLEL
:
3561 stats
->max_opno
= MAX (stats
->max_opno
, XINT (x
, 0));
3568 stats
->max_dup_opno
= MAX (stats
->max_dup_opno
, XINT (x
, 0));
3572 if (stats
->min_scratch_opno
== -1)
3573 stats
->min_scratch_opno
= XINT (x
, 0);
3575 stats
->min_scratch_opno
= MIN (stats
->min_scratch_opno
, XINT (x
, 0));
3576 stats
->max_scratch_opno
= MAX (stats
->max_scratch_opno
, XINT (x
, 0));
3583 fmt
= GET_RTX_FORMAT (code
);
3584 len
= GET_RTX_LENGTH (code
);
3585 for (i
= 0; i
< len
; i
++)
3587 if (fmt
[i
] == 'e' || fmt
[i
] == 'u')
3588 get_pattern_stats_1 (stats
, XEXP (x
, i
));
3589 else if (fmt
[i
] == 'E')
3592 for (j
= 0; j
< XVECLEN (x
, i
); j
++)
3593 get_pattern_stats_1 (stats
, XVECEXP (x
, i
, j
));
3598 /* Make STATS describe the operands that appear in instruction pattern
3602 get_pattern_stats (struct pattern_stats
*stats
, rtvec pattern
)
3606 stats
->max_opno
= -1;
3607 stats
->max_dup_opno
= -1;
3608 stats
->min_scratch_opno
= -1;
3609 stats
->max_scratch_opno
= -1;
3610 stats
->num_dups
= 0;
3612 len
= GET_NUM_ELEM (pattern
);
3613 for (i
= 0; i
< len
; i
++)
3614 get_pattern_stats_1 (stats
, RTVEC_ELT (pattern
, i
));
3616 stats
->num_generator_args
= stats
->max_opno
+ 1;
3617 stats
->num_insn_operands
= MAX (stats
->max_opno
,
3618 stats
->max_scratch_opno
) + 1;
3619 stats
->num_operand_vars
= MAX (stats
->max_opno
,
3620 MAX (stats
->max_dup_opno
,
3621 stats
->max_scratch_opno
)) + 1;
3624 /* Return the emit_* function that should be used for pattern X, or NULL
3625 if we can't pick a particular type at compile time and should instead
3626 fall back to "emit". */
3629 get_emit_function (rtx x
)
3631 switch (classify_insn (x
))
3637 return "emit_call_insn";
3640 return "emit_jump_insn";
3650 /* Return true if we must emit a barrier after pattern X. */
3653 needs_barrier_p (rtx x
)
3655 return (GET_CODE (x
) == SET
3656 && GET_CODE (SET_DEST (x
)) == PC
3657 && GET_CODE (SET_SRC (x
)) == LABEL_REF
);
3662 #define OPTAB_CL(o, p, c, b, l) { #o, p, #b, ZS, #l, o, c, UNKNOWN, 1 },
3663 #define OPTAB_CX(o, p) { #o, p, NULL, NULL, NULL, o, UNKNOWN, UNKNOWN, 1 },
3664 #define OPTAB_CD(o, p) { #o, p, NS, ZS, NS, o, UNKNOWN, UNKNOWN, 2 },
3665 #define OPTAB_NL(o, p, c, b, s, l) { #o, p, #b, #s, #l, o, c, c, 3 },
3666 #define OPTAB_NC(o, p, c) { #o, p, NS, ZS, NS, o, c, c, 3 },
3667 #define OPTAB_NX(o, p) { #o, p, NULL, NULL, NULL, o, UNKNOWN, UNKNOWN, 3 },
3668 #define OPTAB_VL(o, p, c, b, s, l) { #o, p, #b, #s, #l, o, c, UNKNOWN, 3 },
3669 #define OPTAB_VC(o, p, c) { #o, p, NS, ZS, NS, o, c, UNKNOWN, 3 },
3670 #define OPTAB_VX(o, p) { #o, p, NULL, NULL, NULL, o, UNKNOWN, UNKNOWN, 3 },
3671 #define OPTAB_DC(o, p, c) { #o, p, NS, ZS, NS, o, c, c, 4 },
3672 #define OPTAB_D(o, p) { #o, p, NS, ZS, NS, o, UNKNOWN, UNKNOWN, 4 },
3674 /* An array of all optabs. Note that the same optab can appear more
3675 than once, with a different pattern. */
3676 optab_def optabs
[] = {
3677 { "unknown_optab", NULL
, NS
, ZS
, NS
, unknown_optab
, UNKNOWN
, UNKNOWN
, 0 },
3678 #include "optabs.def"
3681 /* The number of entries in optabs[]. */
3682 unsigned int num_optabs
= ARRAY_SIZE (optabs
);
3696 /* Return true if instruction NAME matches pattern PAT, storing information
3697 about the match in P if so. */
3700 match_pattern (optab_pattern
*p
, const char *name
, const char *pat
)
3702 bool force_float
= false;
3703 bool force_int
= false;
3704 bool force_partial_int
= false;
3705 bool force_fixed
= false;
3713 if (*pat
!= *name
++)
3725 force_partial_int
= 1;
3739 /* This loop will stop at the first prefix match, so
3740 look through the modes in reverse order, in case
3741 there are extra CC modes and CC is a prefix of the
3742 CC modes (as it should be). */
3743 for (i
= (MAX_MACHINE_MODE
) - 1; i
>= 0; i
--)
3746 for (p
= GET_MODE_NAME (i
), q
= name
; *p
; p
++, q
++)
3747 if (TOLOWER (*p
) != *q
)
3750 && (! force_int
|| mode_class
[i
] == MODE_INT
3751 || mode_class
[i
] == MODE_VECTOR_INT
)
3752 && (! force_partial_int
3753 || mode_class
[i
] == MODE_INT
3754 || mode_class
[i
] == MODE_PARTIAL_INT
3755 || mode_class
[i
] == MODE_VECTOR_INT
)
3757 || mode_class
[i
] == MODE_FLOAT
3758 || mode_class
[i
] == MODE_DECIMAL_FLOAT
3759 || mode_class
[i
] == MODE_COMPLEX_FLOAT
3760 || mode_class
[i
] == MODE_VECTOR_FLOAT
)
3762 || mode_class
[i
] == MODE_FRACT
3763 || mode_class
[i
] == MODE_UFRACT
3764 || mode_class
[i
] == MODE_ACCUM
3765 || mode_class
[i
] == MODE_UACCUM
3766 || mode_class
[i
] == MODE_VECTOR_FRACT
3767 || mode_class
[i
] == MODE_VECTOR_UFRACT
3768 || mode_class
[i
] == MODE_VECTOR_ACCUM
3769 || mode_class
[i
] == MODE_VECTOR_UACCUM
))
3775 name
+= strlen (GET_MODE_NAME (i
));
3782 force_partial_int
= false;
3783 force_float
= false;
3784 force_fixed
= false;
3794 /* Return true if NAME is the name of an optab, describing it in P if so. */
3797 find_optab (optab_pattern
*p
, const char *name
)
3799 if (*name
== 0 || *name
== '*')
3802 /* See if NAME matches one of the patterns we have for the optabs
3804 for (unsigned int pindex
= 0; pindex
< ARRAY_SIZE (optabs
); pindex
++)
3807 if (match_pattern (p
, name
, optabs
[pindex
].pattern
))
3810 p
->op
= optabs
[pindex
].op
;
3811 p
->sort_num
= (p
->op
<< 20) | (p
->m2
<< 10) | p
->m1
;