xref: /dragonfly/contrib/gcc-8.0/gcc/gensupport.c (revision 38fd1498)
1*38fd1498Szrj /* Support routines for the various generation passes.
2*38fd1498Szrj    Copyright (C) 2000-2018 Free Software Foundation, Inc.
3*38fd1498Szrj 
4*38fd1498Szrj    This file is part of GCC.
5*38fd1498Szrj 
6*38fd1498Szrj    GCC is free software; you can redistribute it and/or modify it
7*38fd1498Szrj    under the terms of the GNU General Public License as published by
8*38fd1498Szrj    the Free Software Foundation; either version 3, or (at your option)
9*38fd1498Szrj    any later version.
10*38fd1498Szrj 
11*38fd1498Szrj    GCC is distributed in the hope that it will be useful, but WITHOUT
12*38fd1498Szrj    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13*38fd1498Szrj    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
14*38fd1498Szrj    License for more details.
15*38fd1498Szrj 
16*38fd1498Szrj    You should have received a copy of the GNU General Public License
17*38fd1498Szrj    along with GCC; see the file COPYING3.  If not see
18*38fd1498Szrj    <http://www.gnu.org/licenses/>.  */
19*38fd1498Szrj 
20*38fd1498Szrj #include "bconfig.h"
21*38fd1498Szrj #include "system.h"
22*38fd1498Szrj #include "coretypes.h"
23*38fd1498Szrj #include "tm.h"
24*38fd1498Szrj #include "rtl.h"
25*38fd1498Szrj #include "obstack.h"
26*38fd1498Szrj #include "errors.h"
27*38fd1498Szrj #include "read-md.h"
28*38fd1498Szrj #include "gensupport.h"
29*38fd1498Szrj #include "vec.h"
30*38fd1498Szrj 
31*38fd1498Szrj #define MAX_OPERANDS 40
32*38fd1498Szrj 
33*38fd1498Szrj static rtx operand_data[MAX_OPERANDS];
34*38fd1498Szrj static rtx match_operand_entries_in_pattern[MAX_OPERANDS];
35*38fd1498Szrj static char used_operands_numbers[MAX_OPERANDS];
36*38fd1498Szrj 
37*38fd1498Szrj 
38*38fd1498Szrj /* In case some macros used by files we include need it, define this here.  */
39*38fd1498Szrj int target_flags;
40*38fd1498Szrj 
41*38fd1498Szrj int insn_elision = 1;
42*38fd1498Szrj 
43*38fd1498Szrj static struct obstack obstack;
44*38fd1498Szrj struct obstack *rtl_obstack = &obstack;
45*38fd1498Szrj 
46*38fd1498Szrj /* Counter for named patterns and INSN_CODEs.  */
47*38fd1498Szrj static int insn_sequence_num;
48*38fd1498Szrj 
49*38fd1498Szrj /* Counter for define_splits.  */
50*38fd1498Szrj static int split_sequence_num;
51*38fd1498Szrj 
52*38fd1498Szrj /* Counter for define_peephole2s.  */
53*38fd1498Szrj static int peephole2_sequence_num;
54*38fd1498Szrj 
55*38fd1498Szrj static int predicable_default;
56*38fd1498Szrj static const char *predicable_true;
57*38fd1498Szrj static const char *predicable_false;
58*38fd1498Szrj 
59*38fd1498Szrj static const char *subst_true = "yes";
60*38fd1498Szrj static const char *subst_false = "no";
61*38fd1498Szrj 
62*38fd1498Szrj static htab_t condition_table;
63*38fd1498Szrj 
64*38fd1498Szrj /* We initially queue all patterns, process the define_insn,
65*38fd1498Szrj    define_cond_exec and define_subst patterns, then return
66*38fd1498Szrj    them one at a time.  */
67*38fd1498Szrj 
68*38fd1498Szrj struct queue_elem
69*38fd1498Szrj {
70*38fd1498Szrj   rtx data;
71*38fd1498Szrj   file_location loc;
72*38fd1498Szrj   struct queue_elem *next;
73*38fd1498Szrj   /* In a DEFINE_INSN that came from a DEFINE_INSN_AND_SPLIT, SPLIT
74*38fd1498Szrj      points to the generated DEFINE_SPLIT.  */
75*38fd1498Szrj   struct queue_elem *split;
76*38fd1498Szrj };
77*38fd1498Szrj 
78*38fd1498Szrj #define MNEMONIC_ATTR_NAME "mnemonic"
79*38fd1498Szrj #define MNEMONIC_HTAB_SIZE 1024
80*38fd1498Szrj 
81*38fd1498Szrj static struct queue_elem *define_attr_queue;
82*38fd1498Szrj static struct queue_elem **define_attr_tail = &define_attr_queue;
83*38fd1498Szrj static struct queue_elem *define_pred_queue;
84*38fd1498Szrj static struct queue_elem **define_pred_tail = &define_pred_queue;
85*38fd1498Szrj static struct queue_elem *define_insn_queue;
86*38fd1498Szrj static struct queue_elem **define_insn_tail = &define_insn_queue;
87*38fd1498Szrj static struct queue_elem *define_cond_exec_queue;
88*38fd1498Szrj static struct queue_elem **define_cond_exec_tail = &define_cond_exec_queue;
89*38fd1498Szrj static struct queue_elem *define_subst_queue;
90*38fd1498Szrj static struct queue_elem **define_subst_tail = &define_subst_queue;
91*38fd1498Szrj static struct queue_elem *other_queue;
92*38fd1498Szrj static struct queue_elem **other_tail = &other_queue;
93*38fd1498Szrj static struct queue_elem *define_subst_attr_queue;
94*38fd1498Szrj static struct queue_elem **define_subst_attr_tail = &define_subst_attr_queue;
95*38fd1498Szrj 
96*38fd1498Szrj /* Mapping from DEFINE_* rtxes to their location in the source file.  */
97*38fd1498Szrj static hash_map <rtx, file_location> *rtx_locs;
98*38fd1498Szrj 
99*38fd1498Szrj static void remove_constraints (rtx);
100*38fd1498Szrj 
101*38fd1498Szrj static int is_predicable (struct queue_elem *);
102*38fd1498Szrj static void identify_predicable_attribute (void);
103*38fd1498Szrj static int n_alternatives (const char *);
104*38fd1498Szrj static void collect_insn_data (rtx, int *, int *);
105*38fd1498Szrj static const char *alter_test_for_insn (struct queue_elem *,
106*38fd1498Szrj 					struct queue_elem *);
107*38fd1498Szrj static char *shift_output_template (char *, const char *, int);
108*38fd1498Szrj static const char *alter_output_for_insn (struct queue_elem *,
109*38fd1498Szrj 					  struct queue_elem *,
110*38fd1498Szrj 					  int, int);
111*38fd1498Szrj static void process_one_cond_exec (struct queue_elem *);
112*38fd1498Szrj static void process_define_cond_exec (void);
113*38fd1498Szrj static void init_predicate_table (void);
114*38fd1498Szrj static void record_insn_name (int, const char *);
115*38fd1498Szrj 
116*38fd1498Szrj static bool has_subst_attribute (struct queue_elem *, struct queue_elem *);
117*38fd1498Szrj static const char * alter_output_for_subst_insn (rtx, int);
118*38fd1498Szrj static void alter_attrs_for_subst_insn (struct queue_elem *, int);
119*38fd1498Szrj static void process_substs_on_one_elem (struct queue_elem *,
120*38fd1498Szrj 					struct queue_elem *);
121*38fd1498Szrj static rtx subst_dup (rtx, int, int);
122*38fd1498Szrj static void process_define_subst (void);
123*38fd1498Szrj 
124*38fd1498Szrj static const char * duplicate_alternatives (const char *, int);
125*38fd1498Szrj static const char * duplicate_each_alternative (const char * str, int n_dup);
126*38fd1498Szrj 
127*38fd1498Szrj typedef const char * (*constraints_handler_t) (const char *, int);
128*38fd1498Szrj static rtx alter_constraints (rtx, int, constraints_handler_t);
129*38fd1498Szrj static rtx adjust_operands_numbers (rtx);
130*38fd1498Szrj static rtx replace_duplicating_operands_in_pattern (rtx);
131*38fd1498Szrj 
132*38fd1498Szrj /* Make a version of gen_rtx_CONST_INT so that GEN_INT can be used in
133*38fd1498Szrj    the gensupport programs.  */
134*38fd1498Szrj 
135*38fd1498Szrj rtx
gen_rtx_CONST_INT(machine_mode ARG_UNUSED (mode),HOST_WIDE_INT arg)136*38fd1498Szrj gen_rtx_CONST_INT (machine_mode ARG_UNUSED (mode),
137*38fd1498Szrj 		   HOST_WIDE_INT arg)
138*38fd1498Szrj {
139*38fd1498Szrj   rtx rt = rtx_alloc (CONST_INT);
140*38fd1498Szrj 
141*38fd1498Szrj   XWINT (rt, 0) = arg;
142*38fd1498Szrj   return rt;
143*38fd1498Szrj }
144*38fd1498Szrj 
145*38fd1498Szrj /* Return the rtx pattern specified by the list of rtxes in a
146*38fd1498Szrj    define_insn or define_split.  */
147*38fd1498Szrj 
148*38fd1498Szrj rtx
add_implicit_parallel(rtvec vec)149*38fd1498Szrj add_implicit_parallel (rtvec vec)
150*38fd1498Szrj {
151*38fd1498Szrj   if (GET_NUM_ELEM (vec) == 1)
152*38fd1498Szrj     return RTVEC_ELT (vec, 0);
153*38fd1498Szrj   else
154*38fd1498Szrj     {
155*38fd1498Szrj       rtx pattern = rtx_alloc (PARALLEL);
156*38fd1498Szrj       XVEC (pattern, 0) = vec;
157*38fd1498Szrj       return pattern;
158*38fd1498Szrj     }
159*38fd1498Szrj }
160*38fd1498Szrj 
161*38fd1498Szrj /* Predicate handling.
162*38fd1498Szrj 
163*38fd1498Szrj    We construct from the machine description a table mapping each
164*38fd1498Szrj    predicate to a list of the rtl codes it can possibly match.  The
165*38fd1498Szrj    function 'maybe_both_true' uses it to deduce that there are no
166*38fd1498Szrj    expressions that can be matches by certain pairs of tree nodes.
167*38fd1498Szrj    Also, if a predicate can match only one code, we can hardwire that
168*38fd1498Szrj    code into the node testing the predicate.
169*38fd1498Szrj 
170*38fd1498Szrj    Some predicates are flagged as special.  validate_pattern will not
171*38fd1498Szrj    warn about modeless match_operand expressions if they have a
172*38fd1498Szrj    special predicate.  Predicates that allow only constants are also
173*38fd1498Szrj    treated as special, for this purpose.
174*38fd1498Szrj 
175*38fd1498Szrj    validate_pattern will warn about predicates that allow non-lvalues
176*38fd1498Szrj    when they appear in destination operands.
177*38fd1498Szrj 
178*38fd1498Szrj    Calculating the set of rtx codes that can possibly be accepted by a
179*38fd1498Szrj    predicate expression EXP requires a three-state logic: any given
180*38fd1498Szrj    subexpression may definitively accept a code C (Y), definitively
181*38fd1498Szrj    reject a code C (N), or may have an indeterminate effect (I).  N
182*38fd1498Szrj    and I is N; Y or I is Y; Y and I, N or I are both I.  Here are full
183*38fd1498Szrj    truth tables.
184*38fd1498Szrj 
185*38fd1498Szrj      a b  a&b  a|b
186*38fd1498Szrj      Y Y   Y    Y
187*38fd1498Szrj      N Y   N    Y
188*38fd1498Szrj      N N   N    N
189*38fd1498Szrj      I Y   I    Y
190*38fd1498Szrj      I N   N    I
191*38fd1498Szrj      I I   I    I
192*38fd1498Szrj 
193*38fd1498Szrj    We represent Y with 1, N with 0, I with 2.  If any code is left in
194*38fd1498Szrj    an I state by the complete expression, we must assume that that
195*38fd1498Szrj    code can be accepted.  */
196*38fd1498Szrj 
197*38fd1498Szrj #define N 0
198*38fd1498Szrj #define Y 1
199*38fd1498Szrj #define I 2
200*38fd1498Szrj 
201*38fd1498Szrj #define TRISTATE_AND(a,b)			\
202*38fd1498Szrj   ((a) == I ? ((b) == N ? N : I) :		\
203*38fd1498Szrj    (b) == I ? ((a) == N ? N : I) :		\
204*38fd1498Szrj    (a) && (b))
205*38fd1498Szrj 
206*38fd1498Szrj #define TRISTATE_OR(a,b)			\
207*38fd1498Szrj   ((a) == I ? ((b) == Y ? Y : I) :		\
208*38fd1498Szrj    (b) == I ? ((a) == Y ? Y : I) :		\
209*38fd1498Szrj    (a) || (b))
210*38fd1498Szrj 
211*38fd1498Szrj #define TRISTATE_NOT(a)				\
212*38fd1498Szrj   ((a) == I ? I : !(a))
213*38fd1498Szrj 
214*38fd1498Szrj /* 0 means no warning about that code yet, 1 means warned.  */
215*38fd1498Szrj static char did_you_mean_codes[NUM_RTX_CODE];
216*38fd1498Szrj 
217*38fd1498Szrj /* Recursively calculate the set of rtx codes accepted by the
218*38fd1498Szrj    predicate expression EXP, writing the result to CODES.  LOC is
219*38fd1498Szrj    the .md file location of the directive containing EXP.  */
220*38fd1498Szrj 
221*38fd1498Szrj void
compute_test_codes(rtx exp,file_location loc,char * codes)222*38fd1498Szrj compute_test_codes (rtx exp, file_location loc, char *codes)
223*38fd1498Szrj {
224*38fd1498Szrj   char op0_codes[NUM_RTX_CODE];
225*38fd1498Szrj   char op1_codes[NUM_RTX_CODE];
226*38fd1498Szrj   char op2_codes[NUM_RTX_CODE];
227*38fd1498Szrj   int i;
228*38fd1498Szrj 
229*38fd1498Szrj   switch (GET_CODE (exp))
230*38fd1498Szrj     {
231*38fd1498Szrj     case AND:
232*38fd1498Szrj       compute_test_codes (XEXP (exp, 0), loc, op0_codes);
233*38fd1498Szrj       compute_test_codes (XEXP (exp, 1), loc, op1_codes);
234*38fd1498Szrj       for (i = 0; i < NUM_RTX_CODE; i++)
235*38fd1498Szrj 	codes[i] = TRISTATE_AND (op0_codes[i], op1_codes[i]);
236*38fd1498Szrj       break;
237*38fd1498Szrj 
238*38fd1498Szrj     case IOR:
239*38fd1498Szrj       compute_test_codes (XEXP (exp, 0), loc, op0_codes);
240*38fd1498Szrj       compute_test_codes (XEXP (exp, 1), loc, op1_codes);
241*38fd1498Szrj       for (i = 0; i < NUM_RTX_CODE; i++)
242*38fd1498Szrj 	codes[i] = TRISTATE_OR (op0_codes[i], op1_codes[i]);
243*38fd1498Szrj       break;
244*38fd1498Szrj     case NOT:
245*38fd1498Szrj       compute_test_codes (XEXP (exp, 0), loc, op0_codes);
246*38fd1498Szrj       for (i = 0; i < NUM_RTX_CODE; i++)
247*38fd1498Szrj 	codes[i] = TRISTATE_NOT (op0_codes[i]);
248*38fd1498Szrj       break;
249*38fd1498Szrj 
250*38fd1498Szrj     case IF_THEN_ELSE:
251*38fd1498Szrj       /* a ? b : c  accepts the same codes as (a & b) | (!a & c).  */
252*38fd1498Szrj       compute_test_codes (XEXP (exp, 0), loc, op0_codes);
253*38fd1498Szrj       compute_test_codes (XEXP (exp, 1), loc, op1_codes);
254*38fd1498Szrj       compute_test_codes (XEXP (exp, 2), loc, op2_codes);
255*38fd1498Szrj       for (i = 0; i < NUM_RTX_CODE; i++)
256*38fd1498Szrj 	codes[i] = TRISTATE_OR (TRISTATE_AND (op0_codes[i], op1_codes[i]),
257*38fd1498Szrj 				TRISTATE_AND (TRISTATE_NOT (op0_codes[i]),
258*38fd1498Szrj 					      op2_codes[i]));
259*38fd1498Szrj       break;
260*38fd1498Szrj 
261*38fd1498Szrj     case MATCH_CODE:
262*38fd1498Szrj       /* MATCH_CODE allows a specified list of codes.  However, if it
263*38fd1498Szrj 	 does not apply to the top level of the expression, it does not
264*38fd1498Szrj 	 constrain the set of codes for the top level.  */
265*38fd1498Szrj       if (XSTR (exp, 1)[0] != '\0')
266*38fd1498Szrj 	{
267*38fd1498Szrj 	  memset (codes, Y, NUM_RTX_CODE);
268*38fd1498Szrj 	  break;
269*38fd1498Szrj 	}
270*38fd1498Szrj 
271*38fd1498Szrj       memset (codes, N, NUM_RTX_CODE);
272*38fd1498Szrj       {
273*38fd1498Szrj 	const char *next_code = XSTR (exp, 0);
274*38fd1498Szrj 	const char *code;
275*38fd1498Szrj 
276*38fd1498Szrj 	if (*next_code == '\0')
277*38fd1498Szrj 	  {
278*38fd1498Szrj 	    error_at (loc, "empty match_code expression");
279*38fd1498Szrj 	    break;
280*38fd1498Szrj 	  }
281*38fd1498Szrj 
282*38fd1498Szrj 	while ((code = scan_comma_elt (&next_code)) != 0)
283*38fd1498Szrj 	  {
284*38fd1498Szrj 	    size_t n = next_code - code;
285*38fd1498Szrj 	    int found_it = 0;
286*38fd1498Szrj 
287*38fd1498Szrj 	    for (i = 0; i < NUM_RTX_CODE; i++)
288*38fd1498Szrj 	      if (!strncmp (code, GET_RTX_NAME (i), n)
289*38fd1498Szrj 		  && GET_RTX_NAME (i)[n] == '\0')
290*38fd1498Szrj 		{
291*38fd1498Szrj 		  codes[i] = Y;
292*38fd1498Szrj 		  found_it = 1;
293*38fd1498Szrj 		  break;
294*38fd1498Szrj 		}
295*38fd1498Szrj 	    if (!found_it)
296*38fd1498Szrj 	      {
297*38fd1498Szrj 		error_at (loc, "match_code \"%.*s\" matches nothing",
298*38fd1498Szrj 			  (int) n, code);
299*38fd1498Szrj 		for (i = 0; i < NUM_RTX_CODE; i++)
300*38fd1498Szrj 		  if (!strncasecmp (code, GET_RTX_NAME (i), n)
301*38fd1498Szrj 		      && GET_RTX_NAME (i)[n] == '\0'
302*38fd1498Szrj 		      && !did_you_mean_codes[i])
303*38fd1498Szrj 		    {
304*38fd1498Szrj 		      did_you_mean_codes[i] = 1;
305*38fd1498Szrj 		      message_at (loc, "(did you mean \"%s\"?)",
306*38fd1498Szrj 				  GET_RTX_NAME (i));
307*38fd1498Szrj 		    }
308*38fd1498Szrj 	      }
309*38fd1498Szrj 	  }
310*38fd1498Szrj       }
311*38fd1498Szrj       break;
312*38fd1498Szrj 
313*38fd1498Szrj     case MATCH_OPERAND:
314*38fd1498Szrj       /* MATCH_OPERAND disallows the set of codes that the named predicate
315*38fd1498Szrj 	 disallows, and is indeterminate for the codes that it does allow.  */
316*38fd1498Szrj       {
317*38fd1498Szrj 	struct pred_data *p = lookup_predicate (XSTR (exp, 1));
318*38fd1498Szrj 	if (!p)
319*38fd1498Szrj 	  {
320*38fd1498Szrj 	    error_at (loc, "reference to unknown predicate '%s'",
321*38fd1498Szrj 		      XSTR (exp, 1));
322*38fd1498Szrj 	    break;
323*38fd1498Szrj 	  }
324*38fd1498Szrj 	for (i = 0; i < NUM_RTX_CODE; i++)
325*38fd1498Szrj 	  codes[i] = p->codes[i] ? I : N;
326*38fd1498Szrj       }
327*38fd1498Szrj       break;
328*38fd1498Szrj 
329*38fd1498Szrj 
330*38fd1498Szrj     case MATCH_TEST:
331*38fd1498Szrj       /* (match_test WHATEVER) is completely indeterminate.  */
332*38fd1498Szrj       memset (codes, I, NUM_RTX_CODE);
333*38fd1498Szrj       break;
334*38fd1498Szrj 
335*38fd1498Szrj     default:
336*38fd1498Szrj       error_at (loc, "'%s' cannot be used in predicates or constraints",
337*38fd1498Szrj 		GET_RTX_NAME (GET_CODE (exp)));
338*38fd1498Szrj       memset (codes, I, NUM_RTX_CODE);
339*38fd1498Szrj       break;
340*38fd1498Szrj     }
341*38fd1498Szrj }
342*38fd1498Szrj 
343*38fd1498Szrj #undef TRISTATE_OR
344*38fd1498Szrj #undef TRISTATE_AND
345*38fd1498Szrj #undef TRISTATE_NOT
346*38fd1498Szrj 
347*38fd1498Szrj /* Return true if NAME is a valid predicate name.  */
348*38fd1498Szrj 
349*38fd1498Szrj static bool
valid_predicate_name_p(const char * name)350*38fd1498Szrj valid_predicate_name_p (const char *name)
351*38fd1498Szrj {
352*38fd1498Szrj   const char *p;
353*38fd1498Szrj 
354*38fd1498Szrj   if (!ISALPHA (name[0]) && name[0] != '_')
355*38fd1498Szrj     return false;
356*38fd1498Szrj   for (p = name + 1; *p; p++)
357*38fd1498Szrj     if (!ISALNUM (*p) && *p != '_')
358*38fd1498Szrj       return false;
359*38fd1498Szrj   return true;
360*38fd1498Szrj }
361*38fd1498Szrj 
362*38fd1498Szrj /* Process define_predicate directive DESC, which appears at location LOC.
363*38fd1498Szrj    Compute the set of codes that can be matched, and record this as a known
364*38fd1498Szrj    predicate.  */
365*38fd1498Szrj 
366*38fd1498Szrj static void
process_define_predicate(rtx desc,file_location loc)367*38fd1498Szrj process_define_predicate (rtx desc, file_location loc)
368*38fd1498Szrj {
369*38fd1498Szrj   struct pred_data *pred;
370*38fd1498Szrj   char codes[NUM_RTX_CODE];
371*38fd1498Szrj   int i;
372*38fd1498Szrj 
373*38fd1498Szrj   if (!valid_predicate_name_p (XSTR (desc, 0)))
374*38fd1498Szrj     {
375*38fd1498Szrj       error_at (loc, "%s: predicate name must be a valid C function name",
376*38fd1498Szrj 		XSTR (desc, 0));
377*38fd1498Szrj       return;
378*38fd1498Szrj     }
379*38fd1498Szrj 
380*38fd1498Szrj   pred = XCNEW (struct pred_data);
381*38fd1498Szrj   pred->name = XSTR (desc, 0);
382*38fd1498Szrj   pred->exp = XEXP (desc, 1);
383*38fd1498Szrj   pred->c_block = XSTR (desc, 2);
384*38fd1498Szrj   if (GET_CODE (desc) == DEFINE_SPECIAL_PREDICATE)
385*38fd1498Szrj     pred->special = true;
386*38fd1498Szrj 
387*38fd1498Szrj   compute_test_codes (XEXP (desc, 1), loc, codes);
388*38fd1498Szrj 
389*38fd1498Szrj   for (i = 0; i < NUM_RTX_CODE; i++)
390*38fd1498Szrj     if (codes[i] != N)
391*38fd1498Szrj       add_predicate_code (pred, (enum rtx_code) i);
392*38fd1498Szrj 
393*38fd1498Szrj   add_predicate (pred);
394*38fd1498Szrj }
395*38fd1498Szrj #undef I
396*38fd1498Szrj #undef N
397*38fd1498Szrj #undef Y
398*38fd1498Szrj 
399*38fd1498Szrj /* Queue PATTERN on LIST_TAIL.  Return the address of the new queue
400*38fd1498Szrj    element.  */
401*38fd1498Szrj 
402*38fd1498Szrj static struct queue_elem *
queue_pattern(rtx pattern,struct queue_elem *** list_tail,file_location loc)403*38fd1498Szrj queue_pattern (rtx pattern, struct queue_elem ***list_tail,
404*38fd1498Szrj 	       file_location loc)
405*38fd1498Szrj {
406*38fd1498Szrj   struct queue_elem *e = XNEW (struct queue_elem);
407*38fd1498Szrj   e->data = pattern;
408*38fd1498Szrj   e->loc = loc;
409*38fd1498Szrj   e->next = NULL;
410*38fd1498Szrj   e->split = NULL;
411*38fd1498Szrj   **list_tail = e;
412*38fd1498Szrj   *list_tail = &e->next;
413*38fd1498Szrj   return e;
414*38fd1498Szrj }
415*38fd1498Szrj 
416*38fd1498Szrj /* Remove element ELEM from QUEUE.  */
417*38fd1498Szrj static void
remove_from_queue(struct queue_elem * elem,struct queue_elem ** queue)418*38fd1498Szrj remove_from_queue (struct queue_elem *elem, struct queue_elem **queue)
419*38fd1498Szrj {
420*38fd1498Szrj   struct queue_elem *prev, *e;
421*38fd1498Szrj   prev = NULL;
422*38fd1498Szrj   for (e = *queue; e ; e = e->next)
423*38fd1498Szrj     {
424*38fd1498Szrj       if (e == elem)
425*38fd1498Szrj 	break;
426*38fd1498Szrj       prev = e;
427*38fd1498Szrj     }
428*38fd1498Szrj   if (e == NULL)
429*38fd1498Szrj     return;
430*38fd1498Szrj 
431*38fd1498Szrj   if (prev)
432*38fd1498Szrj     prev->next = elem->next;
433*38fd1498Szrj   else
434*38fd1498Szrj     *queue = elem->next;
435*38fd1498Szrj }
436*38fd1498Szrj 
437*38fd1498Szrj /* Build a define_attr for an binary attribute with name NAME and
438*38fd1498Szrj    possible values "yes" and "no", and queue it.  */
439*38fd1498Szrj static void
add_define_attr(const char * name)440*38fd1498Szrj add_define_attr (const char *name)
441*38fd1498Szrj {
442*38fd1498Szrj   struct queue_elem *e = XNEW (struct queue_elem);
443*38fd1498Szrj   rtx t1 = rtx_alloc (DEFINE_ATTR);
444*38fd1498Szrj   XSTR (t1, 0) = name;
445*38fd1498Szrj   XSTR (t1, 1) = "no,yes";
446*38fd1498Szrj   XEXP (t1, 2) = rtx_alloc (CONST_STRING);
447*38fd1498Szrj   XSTR (XEXP (t1, 2), 0) = "yes";
448*38fd1498Szrj   e->data = t1;
449*38fd1498Szrj   e->loc = file_location ("built-in", -1, -1);
450*38fd1498Szrj   e->next = define_attr_queue;
451*38fd1498Szrj   define_attr_queue = e;
452*38fd1498Szrj 
453*38fd1498Szrj }
454*38fd1498Szrj 
455*38fd1498Szrj /* Recursively remove constraints from an rtx.  */
456*38fd1498Szrj 
457*38fd1498Szrj static void
remove_constraints(rtx part)458*38fd1498Szrj remove_constraints (rtx part)
459*38fd1498Szrj {
460*38fd1498Szrj   int i, j;
461*38fd1498Szrj   const char *format_ptr;
462*38fd1498Szrj 
463*38fd1498Szrj   if (part == 0)
464*38fd1498Szrj     return;
465*38fd1498Szrj 
466*38fd1498Szrj   if (GET_CODE (part) == MATCH_OPERAND)
467*38fd1498Szrj     XSTR (part, 2) = "";
468*38fd1498Szrj   else if (GET_CODE (part) == MATCH_SCRATCH)
469*38fd1498Szrj     XSTR (part, 1) = "";
470*38fd1498Szrj 
471*38fd1498Szrj   format_ptr = GET_RTX_FORMAT (GET_CODE (part));
472*38fd1498Szrj 
473*38fd1498Szrj   for (i = 0; i < GET_RTX_LENGTH (GET_CODE (part)); i++)
474*38fd1498Szrj     switch (*format_ptr++)
475*38fd1498Szrj       {
476*38fd1498Szrj       case 'e':
477*38fd1498Szrj       case 'u':
478*38fd1498Szrj 	remove_constraints (XEXP (part, i));
479*38fd1498Szrj 	break;
480*38fd1498Szrj       case 'E':
481*38fd1498Szrj 	if (XVEC (part, i) != NULL)
482*38fd1498Szrj 	  for (j = 0; j < XVECLEN (part, i); j++)
483*38fd1498Szrj 	    remove_constraints (XVECEXP (part, i, j));
484*38fd1498Szrj 	break;
485*38fd1498Szrj       }
486*38fd1498Szrj }
487*38fd1498Szrj 
488*38fd1498Szrj /* Process a top level rtx in some way, queuing as appropriate.  */
489*38fd1498Szrj 
490*38fd1498Szrj static void
process_rtx(rtx desc,file_location loc)491*38fd1498Szrj process_rtx (rtx desc, file_location loc)
492*38fd1498Szrj {
493*38fd1498Szrj   switch (GET_CODE (desc))
494*38fd1498Szrj     {
495*38fd1498Szrj     case DEFINE_INSN:
496*38fd1498Szrj       queue_pattern (desc, &define_insn_tail, loc);
497*38fd1498Szrj       break;
498*38fd1498Szrj 
499*38fd1498Szrj     case DEFINE_COND_EXEC:
500*38fd1498Szrj       queue_pattern (desc, &define_cond_exec_tail, loc);
501*38fd1498Szrj       break;
502*38fd1498Szrj 
503*38fd1498Szrj     case DEFINE_SUBST:
504*38fd1498Szrj       queue_pattern (desc, &define_subst_tail, loc);
505*38fd1498Szrj       break;
506*38fd1498Szrj 
507*38fd1498Szrj     case DEFINE_SUBST_ATTR:
508*38fd1498Szrj       queue_pattern (desc, &define_subst_attr_tail, loc);
509*38fd1498Szrj       break;
510*38fd1498Szrj 
511*38fd1498Szrj     case DEFINE_ATTR:
512*38fd1498Szrj     case DEFINE_ENUM_ATTR:
513*38fd1498Szrj       queue_pattern (desc, &define_attr_tail, loc);
514*38fd1498Szrj       break;
515*38fd1498Szrj 
516*38fd1498Szrj     case DEFINE_PREDICATE:
517*38fd1498Szrj     case DEFINE_SPECIAL_PREDICATE:
518*38fd1498Szrj       process_define_predicate (desc, loc);
519*38fd1498Szrj       /* Fall through.  */
520*38fd1498Szrj 
521*38fd1498Szrj     case DEFINE_CONSTRAINT:
522*38fd1498Szrj     case DEFINE_REGISTER_CONSTRAINT:
523*38fd1498Szrj     case DEFINE_MEMORY_CONSTRAINT:
524*38fd1498Szrj     case DEFINE_SPECIAL_MEMORY_CONSTRAINT:
525*38fd1498Szrj     case DEFINE_ADDRESS_CONSTRAINT:
526*38fd1498Szrj       queue_pattern (desc, &define_pred_tail, loc);
527*38fd1498Szrj       break;
528*38fd1498Szrj 
529*38fd1498Szrj     case DEFINE_INSN_AND_SPLIT:
530*38fd1498Szrj       {
531*38fd1498Szrj 	const char *split_cond;
532*38fd1498Szrj 	rtx split;
533*38fd1498Szrj 	rtvec attr;
534*38fd1498Szrj 	int i;
535*38fd1498Szrj 	struct queue_elem *insn_elem;
536*38fd1498Szrj 	struct queue_elem *split_elem;
537*38fd1498Szrj 
538*38fd1498Szrj 	/* Create a split with values from the insn_and_split.  */
539*38fd1498Szrj 	split = rtx_alloc (DEFINE_SPLIT);
540*38fd1498Szrj 
541*38fd1498Szrj 	i = XVECLEN (desc, 1);
542*38fd1498Szrj 	XVEC (split, 0) = rtvec_alloc (i);
543*38fd1498Szrj 	while (--i >= 0)
544*38fd1498Szrj 	  {
545*38fd1498Szrj 	    XVECEXP (split, 0, i) = copy_rtx (XVECEXP (desc, 1, i));
546*38fd1498Szrj 	    remove_constraints (XVECEXP (split, 0, i));
547*38fd1498Szrj 	  }
548*38fd1498Szrj 
549*38fd1498Szrj 	/* If the split condition starts with "&&", append it to the
550*38fd1498Szrj 	   insn condition to create the new split condition.  */
551*38fd1498Szrj 	split_cond = XSTR (desc, 4);
552*38fd1498Szrj 	if (split_cond[0] == '&' && split_cond[1] == '&')
553*38fd1498Szrj 	  {
554*38fd1498Szrj 	    rtx_reader_ptr->copy_md_ptr_loc (split_cond + 2, split_cond);
555*38fd1498Szrj 	    split_cond = rtx_reader_ptr->join_c_conditions (XSTR (desc, 2),
556*38fd1498Szrj 							    split_cond + 2);
557*38fd1498Szrj 	  }
558*38fd1498Szrj 	XSTR (split, 1) = split_cond;
559*38fd1498Szrj 	XVEC (split, 2) = XVEC (desc, 5);
560*38fd1498Szrj 	XSTR (split, 3) = XSTR (desc, 6);
561*38fd1498Szrj 
562*38fd1498Szrj 	/* Fix up the DEFINE_INSN.  */
563*38fd1498Szrj 	attr = XVEC (desc, 7);
564*38fd1498Szrj 	PUT_CODE (desc, DEFINE_INSN);
565*38fd1498Szrj 	XVEC (desc, 4) = attr;
566*38fd1498Szrj 
567*38fd1498Szrj 	/* Queue them.  */
568*38fd1498Szrj 	insn_elem = queue_pattern (desc, &define_insn_tail, loc);
569*38fd1498Szrj 	split_elem = queue_pattern (split, &other_tail, loc);
570*38fd1498Szrj 	insn_elem->split = split_elem;
571*38fd1498Szrj 	break;
572*38fd1498Szrj       }
573*38fd1498Szrj 
574*38fd1498Szrj     default:
575*38fd1498Szrj       queue_pattern (desc, &other_tail, loc);
576*38fd1498Szrj       break;
577*38fd1498Szrj     }
578*38fd1498Szrj }
579*38fd1498Szrj 
580*38fd1498Szrj /* Return true if attribute PREDICABLE is true for ELEM, which holds
581*38fd1498Szrj    a DEFINE_INSN.  */
582*38fd1498Szrj 
583*38fd1498Szrj static int
is_predicable(struct queue_elem * elem)584*38fd1498Szrj is_predicable (struct queue_elem *elem)
585*38fd1498Szrj {
586*38fd1498Szrj   rtvec vec = XVEC (elem->data, 4);
587*38fd1498Szrj   const char *value;
588*38fd1498Szrj   int i;
589*38fd1498Szrj 
590*38fd1498Szrj   if (! vec)
591*38fd1498Szrj     return predicable_default;
592*38fd1498Szrj 
593*38fd1498Szrj   for (i = GET_NUM_ELEM (vec) - 1; i >= 0; --i)
594*38fd1498Szrj     {
595*38fd1498Szrj       rtx sub = RTVEC_ELT (vec, i);
596*38fd1498Szrj       switch (GET_CODE (sub))
597*38fd1498Szrj 	{
598*38fd1498Szrj 	case SET_ATTR:
599*38fd1498Szrj 	  if (strcmp (XSTR (sub, 0), "predicable") == 0)
600*38fd1498Szrj 	    {
601*38fd1498Szrj 	      value = XSTR (sub, 1);
602*38fd1498Szrj 	      goto found;
603*38fd1498Szrj 	    }
604*38fd1498Szrj 	  break;
605*38fd1498Szrj 
606*38fd1498Szrj 	case SET_ATTR_ALTERNATIVE:
607*38fd1498Szrj 	  if (strcmp (XSTR (sub, 0), "predicable") == 0)
608*38fd1498Szrj 	    {
609*38fd1498Szrj 	      error_at (elem->loc, "multiple alternatives for `predicable'");
610*38fd1498Szrj 	      return 0;
611*38fd1498Szrj 	    }
612*38fd1498Szrj 	  break;
613*38fd1498Szrj 
614*38fd1498Szrj 	case SET:
615*38fd1498Szrj 	  if (GET_CODE (SET_DEST (sub)) != ATTR
616*38fd1498Szrj 	      || strcmp (XSTR (SET_DEST (sub), 0), "predicable") != 0)
617*38fd1498Szrj 	    break;
618*38fd1498Szrj 	  sub = SET_SRC (sub);
619*38fd1498Szrj 	  if (GET_CODE (sub) == CONST_STRING)
620*38fd1498Szrj 	    {
621*38fd1498Szrj 	      value = XSTR (sub, 0);
622*38fd1498Szrj 	      goto found;
623*38fd1498Szrj 	    }
624*38fd1498Szrj 
625*38fd1498Szrj 	  /* ??? It would be possible to handle this if we really tried.
626*38fd1498Szrj 	     It's not easy though, and I'm not going to bother until it
627*38fd1498Szrj 	     really proves necessary.  */
628*38fd1498Szrj 	  error_at (elem->loc, "non-constant value for `predicable'");
629*38fd1498Szrj 	  return 0;
630*38fd1498Szrj 
631*38fd1498Szrj 	default:
632*38fd1498Szrj 	  gcc_unreachable ();
633*38fd1498Szrj 	}
634*38fd1498Szrj     }
635*38fd1498Szrj 
636*38fd1498Szrj   return predicable_default;
637*38fd1498Szrj 
638*38fd1498Szrj  found:
639*38fd1498Szrj   /* Find out which value we're looking at.  Multiple alternatives means at
640*38fd1498Szrj      least one is predicable.  */
641*38fd1498Szrj   if (strchr (value, ',') != NULL)
642*38fd1498Szrj     return 1;
643*38fd1498Szrj   if (strcmp (value, predicable_true) == 0)
644*38fd1498Szrj     return 1;
645*38fd1498Szrj   if (strcmp (value, predicable_false) == 0)
646*38fd1498Szrj     return 0;
647*38fd1498Szrj 
648*38fd1498Szrj   error_at (elem->loc, "unknown value `%s' for `predicable' attribute", value);
649*38fd1498Szrj   return 0;
650*38fd1498Szrj }
651*38fd1498Szrj 
652*38fd1498Szrj /* Find attribute SUBST in ELEM and assign NEW_VALUE to it.  */
653*38fd1498Szrj static void
change_subst_attribute(struct queue_elem * elem,struct queue_elem * subst_elem,const char * new_value)654*38fd1498Szrj change_subst_attribute (struct queue_elem *elem,
655*38fd1498Szrj 			struct queue_elem *subst_elem,
656*38fd1498Szrj 			const char *new_value)
657*38fd1498Szrj {
658*38fd1498Szrj   rtvec attrs_vec = XVEC (elem->data, 4);
659*38fd1498Szrj   const char *subst_name = XSTR (subst_elem->data, 0);
660*38fd1498Szrj   int i;
661*38fd1498Szrj 
662*38fd1498Szrj   if (! attrs_vec)
663*38fd1498Szrj     return;
664*38fd1498Szrj 
665*38fd1498Szrj   for (i = GET_NUM_ELEM (attrs_vec) - 1; i >= 0; --i)
666*38fd1498Szrj     {
667*38fd1498Szrj       rtx cur_attr = RTVEC_ELT (attrs_vec, i);
668*38fd1498Szrj       if (GET_CODE (cur_attr) != SET_ATTR)
669*38fd1498Szrj 	continue;
670*38fd1498Szrj       if (strcmp (XSTR (cur_attr, 0), subst_name) == 0)
671*38fd1498Szrj 	{
672*38fd1498Szrj 	  XSTR (cur_attr, 1) = new_value;
673*38fd1498Szrj 	  return;
674*38fd1498Szrj 	}
675*38fd1498Szrj     }
676*38fd1498Szrj }
677*38fd1498Szrj 
678*38fd1498Szrj /* Return true if ELEM has the attribute with the name of DEFINE_SUBST
679*38fd1498Szrj    represented by SUBST_ELEM and this attribute has value SUBST_TRUE.
680*38fd1498Szrj    DEFINE_SUBST isn't applied to patterns without such attribute.  In other
681*38fd1498Szrj    words, we suppose the default value of the attribute to be 'no' since it is
682*38fd1498Szrj    always generated automatically in read-rtl.c.  */
683*38fd1498Szrj static bool
has_subst_attribute(struct queue_elem * elem,struct queue_elem * subst_elem)684*38fd1498Szrj has_subst_attribute (struct queue_elem *elem, struct queue_elem *subst_elem)
685*38fd1498Szrj {
686*38fd1498Szrj   rtvec attrs_vec = XVEC (elem->data, 4);
687*38fd1498Szrj   const char *value, *subst_name = XSTR (subst_elem->data, 0);
688*38fd1498Szrj   int i;
689*38fd1498Szrj 
690*38fd1498Szrj   if (! attrs_vec)
691*38fd1498Szrj     return false;
692*38fd1498Szrj 
693*38fd1498Szrj   for (i = GET_NUM_ELEM (attrs_vec) - 1; i >= 0; --i)
694*38fd1498Szrj     {
695*38fd1498Szrj       rtx cur_attr = RTVEC_ELT (attrs_vec, i);
696*38fd1498Szrj       switch (GET_CODE (cur_attr))
697*38fd1498Szrj 	{
698*38fd1498Szrj 	case SET_ATTR:
699*38fd1498Szrj 	  if (strcmp (XSTR (cur_attr, 0), subst_name) == 0)
700*38fd1498Szrj 	    {
701*38fd1498Szrj 	      value = XSTR (cur_attr, 1);
702*38fd1498Szrj 	      goto found;
703*38fd1498Szrj 	    }
704*38fd1498Szrj 	  break;
705*38fd1498Szrj 
706*38fd1498Szrj 	case SET:
707*38fd1498Szrj 	  if (GET_CODE (SET_DEST (cur_attr)) != ATTR
708*38fd1498Szrj 	      || strcmp (XSTR (SET_DEST (cur_attr), 0), subst_name) != 0)
709*38fd1498Szrj 	    break;
710*38fd1498Szrj 	  cur_attr = SET_SRC (cur_attr);
711*38fd1498Szrj 	  if (GET_CODE (cur_attr) == CONST_STRING)
712*38fd1498Szrj 	    {
713*38fd1498Szrj 	      value = XSTR (cur_attr, 0);
714*38fd1498Szrj 	      goto found;
715*38fd1498Szrj 	    }
716*38fd1498Szrj 
717*38fd1498Szrj 	  /* Only (set_attr "subst" "yes/no") and
718*38fd1498Szrj 		  (set (attr "subst" (const_string "yes/no")))
719*38fd1498Szrj 	     are currently allowed.  */
720*38fd1498Szrj 	  error_at (elem->loc, "unsupported value for `%s'", subst_name);
721*38fd1498Szrj 	  return false;
722*38fd1498Szrj 
723*38fd1498Szrj 	case SET_ATTR_ALTERNATIVE:
724*38fd1498Szrj 	  error_at (elem->loc,
725*38fd1498Szrj 		    "%s: `set_attr_alternative' is unsupported by "
726*38fd1498Szrj 		    "`define_subst'", XSTR (elem->data, 0));
727*38fd1498Szrj 	  return false;
728*38fd1498Szrj 
729*38fd1498Szrj 
730*38fd1498Szrj 	default:
731*38fd1498Szrj 	  gcc_unreachable ();
732*38fd1498Szrj 	}
733*38fd1498Szrj     }
734*38fd1498Szrj 
735*38fd1498Szrj   return false;
736*38fd1498Szrj 
737*38fd1498Szrj  found:
738*38fd1498Szrj   if (strcmp (value, subst_true) == 0)
739*38fd1498Szrj     return true;
740*38fd1498Szrj   if (strcmp (value, subst_false) == 0)
741*38fd1498Szrj     return false;
742*38fd1498Szrj 
743*38fd1498Szrj   error_at (elem->loc, "unknown value `%s' for `%s' attribute",
744*38fd1498Szrj 	    value, subst_name);
745*38fd1498Szrj   return false;
746*38fd1498Szrj }
747*38fd1498Szrj 
748*38fd1498Szrj /* Compare RTL-template of original define_insn X to input RTL-template of
749*38fd1498Szrj    define_subst PT.  Return 1 if the templates match, 0 otherwise.
750*38fd1498Szrj    During the comparison, the routine also fills global_array OPERAND_DATA.  */
751*38fd1498Szrj static bool
subst_pattern_match(rtx x,rtx pt,file_location loc)752*38fd1498Szrj subst_pattern_match (rtx x, rtx pt, file_location loc)
753*38fd1498Szrj {
754*38fd1498Szrj   RTX_CODE code, code_pt;
755*38fd1498Szrj   int i, j, len;
756*38fd1498Szrj   const char *fmt, *pred_name;
757*38fd1498Szrj 
758*38fd1498Szrj   code = GET_CODE (x);
759*38fd1498Szrj   code_pt = GET_CODE (pt);
760*38fd1498Szrj 
761*38fd1498Szrj   if (code_pt == MATCH_OPERAND)
762*38fd1498Szrj     {
763*38fd1498Szrj       /* MATCH_DUP, and MATCH_OP_DUP don't have a specified mode, so we
764*38fd1498Szrj 	 always accept them.  */
765*38fd1498Szrj       if (GET_MODE (pt) != VOIDmode && GET_MODE (x) != GET_MODE (pt)
766*38fd1498Szrj 	  && (code != MATCH_DUP && code != MATCH_OP_DUP))
767*38fd1498Szrj 	return false; /* Modes don't match.  */
768*38fd1498Szrj 
769*38fd1498Szrj       if (code == MATCH_OPERAND)
770*38fd1498Szrj 	{
771*38fd1498Szrj 	  pred_name = XSTR (pt, 1);
772*38fd1498Szrj 	  if (pred_name[0] != 0)
773*38fd1498Szrj 	    {
774*38fd1498Szrj 	      const struct pred_data *pred_pt = lookup_predicate (pred_name);
775*38fd1498Szrj 	      if (!pred_pt || pred_pt != lookup_predicate (XSTR (x, 1)))
776*38fd1498Szrj 		return false; /* Predicates don't match.  */
777*38fd1498Szrj 	    }
778*38fd1498Szrj 	}
779*38fd1498Szrj 
780*38fd1498Szrj       gcc_assert (XINT (pt, 0) >= 0 && XINT (pt, 0) < MAX_OPERANDS);
781*38fd1498Szrj       operand_data[XINT (pt, 0)] = x;
782*38fd1498Szrj       return true;
783*38fd1498Szrj     }
784*38fd1498Szrj 
785*38fd1498Szrj   if (code_pt == MATCH_OPERATOR)
786*38fd1498Szrj     {
787*38fd1498Szrj       int x_vecexp_pos = -1;
788*38fd1498Szrj 
789*38fd1498Szrj       /* Compare modes.  */
790*38fd1498Szrj       if (GET_MODE (pt) != VOIDmode && GET_MODE (x) != GET_MODE (pt))
791*38fd1498Szrj 	return false;
792*38fd1498Szrj 
793*38fd1498Szrj       /* In case X is also match_operator, compare predicates.  */
794*38fd1498Szrj       if (code == MATCH_OPERATOR)
795*38fd1498Szrj 	{
796*38fd1498Szrj 	  pred_name = XSTR (pt, 1);
797*38fd1498Szrj 	  if (pred_name[0] != 0)
798*38fd1498Szrj 	    {
799*38fd1498Szrj 	      const struct pred_data *pred_pt = lookup_predicate (pred_name);
800*38fd1498Szrj 	      if (!pred_pt || pred_pt != lookup_predicate (XSTR (x, 1)))
801*38fd1498Szrj 		return false;
802*38fd1498Szrj 	    }
803*38fd1498Szrj 	}
804*38fd1498Szrj 
805*38fd1498Szrj       /* Compare operands.
806*38fd1498Szrj 	 MATCH_OPERATOR in input template could match in original template
807*38fd1498Szrj 	 either 1) MATCH_OPERAND, 2) UNSPEC, 3) ordinary operation (like PLUS).
808*38fd1498Szrj 	 In the first case operands are at (XVECEXP (x, 2, j)), in the second
809*38fd1498Szrj 	 - at (XVECEXP (x, 0, j)), in the last one - (XEXP (x, j)).
810*38fd1498Szrj 	 X_VECEXP_POS variable shows, where to look for these operands.  */
811*38fd1498Szrj       if (code == UNSPEC
812*38fd1498Szrj 	  || code == UNSPEC_VOLATILE)
813*38fd1498Szrj 	x_vecexp_pos = 0;
814*38fd1498Szrj       else if (code == MATCH_OPERATOR)
815*38fd1498Szrj 	x_vecexp_pos = 2;
816*38fd1498Szrj       else
817*38fd1498Szrj 	x_vecexp_pos = -1;
818*38fd1498Szrj 
819*38fd1498Szrj       /* MATCH_OPERATOR or UNSPEC case.  */
820*38fd1498Szrj       if (x_vecexp_pos >= 0)
821*38fd1498Szrj 	{
822*38fd1498Szrj 	  /* Compare operands number in X and PT.  */
823*38fd1498Szrj 	  if (XVECLEN (x, x_vecexp_pos) != XVECLEN (pt, 2))
824*38fd1498Szrj 	    return false;
825*38fd1498Szrj 	  for (j = 0; j < XVECLEN (pt, 2); j++)
826*38fd1498Szrj 	    if (!subst_pattern_match (XVECEXP (x, x_vecexp_pos, j),
827*38fd1498Szrj 				      XVECEXP (pt, 2, j), loc))
828*38fd1498Szrj 	      return false;
829*38fd1498Szrj 	}
830*38fd1498Szrj 
831*38fd1498Szrj       /* Ordinary operator.  */
832*38fd1498Szrj       else
833*38fd1498Szrj 	{
834*38fd1498Szrj 	  /* Compare operands number in X and PT.
835*38fd1498Szrj 	     We count operands differently for X and PT since we compare
836*38fd1498Szrj 	     an operator (with operands directly in RTX) and MATCH_OPERATOR
837*38fd1498Szrj 	     (that has a vector with operands).  */
838*38fd1498Szrj 	  if (GET_RTX_LENGTH (code) != XVECLEN (pt, 2))
839*38fd1498Szrj 	    return false;
840*38fd1498Szrj 	  for (j = 0; j < XVECLEN (pt, 2); j++)
841*38fd1498Szrj 	    if (!subst_pattern_match (XEXP (x, j), XVECEXP (pt, 2, j), loc))
842*38fd1498Szrj 	      return false;
843*38fd1498Szrj 	}
844*38fd1498Szrj 
845*38fd1498Szrj       /* Store the operand to OPERAND_DATA array.  */
846*38fd1498Szrj       gcc_assert (XINT (pt, 0) >= 0 && XINT (pt, 0) < MAX_OPERANDS);
847*38fd1498Szrj       operand_data[XINT (pt, 0)] = x;
848*38fd1498Szrj       return true;
849*38fd1498Szrj     }
850*38fd1498Szrj 
851*38fd1498Szrj   if (code_pt == MATCH_PAR_DUP
852*38fd1498Szrj       || code_pt == MATCH_DUP
853*38fd1498Szrj       || code_pt == MATCH_OP_DUP
854*38fd1498Szrj       || code_pt == MATCH_SCRATCH
855*38fd1498Szrj       || code_pt == MATCH_PARALLEL)
856*38fd1498Szrj     {
857*38fd1498Szrj       /* Currently interface for these constructions isn't defined -
858*38fd1498Szrj 	 probably they aren't needed in input template of define_subst at all.
859*38fd1498Szrj 	 So, for now their usage in define_subst is forbidden.  */
860*38fd1498Szrj       error_at (loc, "%s cannot be used in define_subst",
861*38fd1498Szrj 		GET_RTX_NAME (code_pt));
862*38fd1498Szrj     }
863*38fd1498Szrj 
864*38fd1498Szrj   gcc_assert (code != MATCH_PAR_DUP
865*38fd1498Szrj       && code_pt != MATCH_DUP
866*38fd1498Szrj       && code_pt != MATCH_OP_DUP
867*38fd1498Szrj       && code_pt != MATCH_SCRATCH
868*38fd1498Szrj       && code_pt != MATCH_PARALLEL
869*38fd1498Szrj       && code_pt != MATCH_OPERAND
870*38fd1498Szrj       && code_pt != MATCH_OPERATOR);
871*38fd1498Szrj   /* If PT is none of the handled above, then we match only expressions with
872*38fd1498Szrj      the same code in X.  */
873*38fd1498Szrj   if (code != code_pt)
874*38fd1498Szrj     return false;
875*38fd1498Szrj 
876*38fd1498Szrj   fmt = GET_RTX_FORMAT (code_pt);
877*38fd1498Szrj   len = GET_RTX_LENGTH (code_pt);
878*38fd1498Szrj 
879*38fd1498Szrj   for (i = 0; i < len; i++)
880*38fd1498Szrj     {
881*38fd1498Szrj       if (fmt[i] == '0')
882*38fd1498Szrj 	break;
883*38fd1498Szrj 
884*38fd1498Szrj       switch (fmt[i])
885*38fd1498Szrj 	{
886*38fd1498Szrj 	case 'r': case 'p': case 'i': case 'w': case 's':
887*38fd1498Szrj 	  continue;
888*38fd1498Szrj 
889*38fd1498Szrj 	case 'e': case 'u':
890*38fd1498Szrj 	  if (!subst_pattern_match (XEXP (x, i), XEXP (pt, i), loc))
891*38fd1498Szrj 	    return false;
892*38fd1498Szrj 	  break;
893*38fd1498Szrj 	case 'E':
894*38fd1498Szrj 	  {
895*38fd1498Szrj 	    if (XVECLEN (x, i) != XVECLEN (pt, i))
896*38fd1498Szrj 	      return false;
897*38fd1498Szrj 	    for (j = 0; j < XVECLEN (pt, i); j++)
898*38fd1498Szrj 	      if (!subst_pattern_match (XVECEXP (x, i, j),
899*38fd1498Szrj 					XVECEXP (pt, i, j), loc))
900*38fd1498Szrj 		return false;
901*38fd1498Szrj 	    break;
902*38fd1498Szrj 	  }
903*38fd1498Szrj 	default:
904*38fd1498Szrj 	  gcc_unreachable ();
905*38fd1498Szrj 	}
906*38fd1498Szrj     }
907*38fd1498Szrj 
908*38fd1498Szrj   return true;
909*38fd1498Szrj }
910*38fd1498Szrj 
911*38fd1498Szrj /* Examine the attribute "predicable"; discover its boolean values
912*38fd1498Szrj    and its default.  */
913*38fd1498Szrj 
914*38fd1498Szrj static void
identify_predicable_attribute(void)915*38fd1498Szrj identify_predicable_attribute (void)
916*38fd1498Szrj {
917*38fd1498Szrj   struct queue_elem *elem;
918*38fd1498Szrj   char *p_true, *p_false;
919*38fd1498Szrj   const char *value;
920*38fd1498Szrj 
921*38fd1498Szrj   /* Look for the DEFINE_ATTR for `predicable', which must exist.  */
922*38fd1498Szrj   for (elem = define_attr_queue; elem ; elem = elem->next)
923*38fd1498Szrj     if (strcmp (XSTR (elem->data, 0), "predicable") == 0)
924*38fd1498Szrj       goto found;
925*38fd1498Szrj 
926*38fd1498Szrj   error_at (define_cond_exec_queue->loc,
927*38fd1498Szrj 	    "attribute `predicable' not defined");
928*38fd1498Szrj   return;
929*38fd1498Szrj 
930*38fd1498Szrj  found:
931*38fd1498Szrj   value = XSTR (elem->data, 1);
932*38fd1498Szrj   p_false = xstrdup (value);
933*38fd1498Szrj   p_true = strchr (p_false, ',');
934*38fd1498Szrj   if (p_true == NULL || strchr (++p_true, ',') != NULL)
935*38fd1498Szrj     {
936*38fd1498Szrj       error_at (elem->loc, "attribute `predicable' is not a boolean");
937*38fd1498Szrj       free (p_false);
938*38fd1498Szrj       return;
939*38fd1498Szrj     }
940*38fd1498Szrj   p_true[-1] = '\0';
941*38fd1498Szrj 
942*38fd1498Szrj   predicable_true = p_true;
943*38fd1498Szrj   predicable_false = p_false;
944*38fd1498Szrj 
945*38fd1498Szrj   switch (GET_CODE (XEXP (elem->data, 2)))
946*38fd1498Szrj     {
947*38fd1498Szrj     case CONST_STRING:
948*38fd1498Szrj       value = XSTR (XEXP (elem->data, 2), 0);
949*38fd1498Szrj       break;
950*38fd1498Szrj 
951*38fd1498Szrj     case CONST:
952*38fd1498Szrj       error_at (elem->loc, "attribute `predicable' cannot be const");
953*38fd1498Szrj       free (p_false);
954*38fd1498Szrj       return;
955*38fd1498Szrj 
956*38fd1498Szrj     default:
957*38fd1498Szrj       error_at (elem->loc,
958*38fd1498Szrj 		"attribute `predicable' must have a constant default");
959*38fd1498Szrj       free (p_false);
960*38fd1498Szrj       return;
961*38fd1498Szrj     }
962*38fd1498Szrj 
963*38fd1498Szrj   if (strcmp (value, p_true) == 0)
964*38fd1498Szrj     predicable_default = 1;
965*38fd1498Szrj   else if (strcmp (value, p_false) == 0)
966*38fd1498Szrj     predicable_default = 0;
967*38fd1498Szrj   else
968*38fd1498Szrj     {
969*38fd1498Szrj       error_at (elem->loc, "unknown value `%s' for `predicable' attribute",
970*38fd1498Szrj 		value);
971*38fd1498Szrj       free (p_false);
972*38fd1498Szrj     }
973*38fd1498Szrj }
974*38fd1498Szrj 
975*38fd1498Szrj /* Return the number of alternatives in constraint S.  */
976*38fd1498Szrj 
977*38fd1498Szrj static int
n_alternatives(const char * s)978*38fd1498Szrj n_alternatives (const char *s)
979*38fd1498Szrj {
980*38fd1498Szrj   int n = 1;
981*38fd1498Szrj 
982*38fd1498Szrj   if (s)
983*38fd1498Szrj     while (*s)
984*38fd1498Szrj       n += (*s++ == ',');
985*38fd1498Szrj 
986*38fd1498Szrj   return n;
987*38fd1498Szrj }
988*38fd1498Szrj 
989*38fd1498Szrj /* The routine scans rtl PATTERN, find match_operand in it and counts
990*38fd1498Szrj    number of alternatives.  If PATTERN contains several match_operands
991*38fd1498Szrj    with different number of alternatives, error is emitted, and the
992*38fd1498Szrj    routine returns 0.  If all match_operands in PATTERN have the same
993*38fd1498Szrj    number of alternatives, it's stored in N_ALT, and the routine returns 1.
994*38fd1498Szrj    LOC is the location of PATTERN, for error reporting.  */
995*38fd1498Szrj static int
get_alternatives_number(rtx pattern,int * n_alt,file_location loc)996*38fd1498Szrj get_alternatives_number (rtx pattern, int *n_alt, file_location loc)
997*38fd1498Szrj {
998*38fd1498Szrj   const char *fmt;
999*38fd1498Szrj   enum rtx_code code;
1000*38fd1498Szrj   int i, j, len;
1001*38fd1498Szrj 
1002*38fd1498Szrj   if (!n_alt)
1003*38fd1498Szrj     return 0;
1004*38fd1498Szrj 
1005*38fd1498Szrj   code = GET_CODE (pattern);
1006*38fd1498Szrj   switch (code)
1007*38fd1498Szrj     {
1008*38fd1498Szrj     case MATCH_OPERAND:
1009*38fd1498Szrj       i = n_alternatives (XSTR (pattern, 2));
1010*38fd1498Szrj       /* n_alternatives returns 1 if constraint string is empty -
1011*38fd1498Szrj 	 here we fix it up.  */
1012*38fd1498Szrj       if (!*(XSTR (pattern, 2)))
1013*38fd1498Szrj 	i = 0;
1014*38fd1498Szrj       if (*n_alt <= 0)
1015*38fd1498Szrj 	*n_alt = i;
1016*38fd1498Szrj 
1017*38fd1498Szrj       else if (i && i != *n_alt)
1018*38fd1498Szrj 	{
1019*38fd1498Szrj 	  error_at (loc, "wrong number of alternatives in operand %d",
1020*38fd1498Szrj 		    XINT (pattern, 0));
1021*38fd1498Szrj 	  return 0;
1022*38fd1498Szrj 	}
1023*38fd1498Szrj 
1024*38fd1498Szrj     default:
1025*38fd1498Szrj       break;
1026*38fd1498Szrj     }
1027*38fd1498Szrj 
1028*38fd1498Szrj   fmt = GET_RTX_FORMAT (code);
1029*38fd1498Szrj   len = GET_RTX_LENGTH (code);
1030*38fd1498Szrj   for (i = 0; i < len; i++)
1031*38fd1498Szrj     {
1032*38fd1498Szrj       switch (fmt[i])
1033*38fd1498Szrj 	{
1034*38fd1498Szrj 	case 'e': case 'u':
1035*38fd1498Szrj 	  if (!get_alternatives_number (XEXP (pattern, i), n_alt, loc))
1036*38fd1498Szrj 	    return 0;
1037*38fd1498Szrj 	  break;
1038*38fd1498Szrj 
1039*38fd1498Szrj 	case 'V':
1040*38fd1498Szrj 	  if (XVEC (pattern, i) == NULL)
1041*38fd1498Szrj 	    break;
1042*38fd1498Szrj 	  /* FALLTHRU */
1043*38fd1498Szrj 
1044*38fd1498Szrj 	case 'E':
1045*38fd1498Szrj 	  for (j = XVECLEN (pattern, i) - 1; j >= 0; --j)
1046*38fd1498Szrj 	    if (!get_alternatives_number (XVECEXP (pattern, i, j), n_alt, loc))
1047*38fd1498Szrj 	      return 0;
1048*38fd1498Szrj 	  break;
1049*38fd1498Szrj 
1050*38fd1498Szrj 	case 'r': case 'p': case 'i': case 'w':
1051*38fd1498Szrj 	case '0': case 's': case 'S': case 'T':
1052*38fd1498Szrj 	  break;
1053*38fd1498Szrj 
1054*38fd1498Szrj 	default:
1055*38fd1498Szrj 	  gcc_unreachable ();
1056*38fd1498Szrj 	}
1057*38fd1498Szrj     }
1058*38fd1498Szrj     return 1;
1059*38fd1498Szrj }
1060*38fd1498Szrj 
1061*38fd1498Szrj /* Determine how many alternatives there are in INSN, and how many
1062*38fd1498Szrj    operands.  */
1063*38fd1498Szrj 
1064*38fd1498Szrj static void
collect_insn_data(rtx pattern,int * palt,int * pmax)1065*38fd1498Szrj collect_insn_data (rtx pattern, int *palt, int *pmax)
1066*38fd1498Szrj {
1067*38fd1498Szrj   const char *fmt;
1068*38fd1498Szrj   enum rtx_code code;
1069*38fd1498Szrj   int i, j, len;
1070*38fd1498Szrj 
1071*38fd1498Szrj   code = GET_CODE (pattern);
1072*38fd1498Szrj   switch (code)
1073*38fd1498Szrj     {
1074*38fd1498Szrj     case MATCH_OPERAND:
1075*38fd1498Szrj     case MATCH_SCRATCH:
1076*38fd1498Szrj       i = n_alternatives (XSTR (pattern, code == MATCH_SCRATCH ? 1 : 2));
1077*38fd1498Szrj       *palt = (i > *palt ? i : *palt);
1078*38fd1498Szrj       /* Fall through.  */
1079*38fd1498Szrj 
1080*38fd1498Szrj     case MATCH_OPERATOR:
1081*38fd1498Szrj     case MATCH_PARALLEL:
1082*38fd1498Szrj       i = XINT (pattern, 0);
1083*38fd1498Szrj       if (i > *pmax)
1084*38fd1498Szrj 	*pmax = i;
1085*38fd1498Szrj       break;
1086*38fd1498Szrj 
1087*38fd1498Szrj     default:
1088*38fd1498Szrj       break;
1089*38fd1498Szrj     }
1090*38fd1498Szrj 
1091*38fd1498Szrj   fmt = GET_RTX_FORMAT (code);
1092*38fd1498Szrj   len = GET_RTX_LENGTH (code);
1093*38fd1498Szrj   for (i = 0; i < len; i++)
1094*38fd1498Szrj     {
1095*38fd1498Szrj       switch (fmt[i])
1096*38fd1498Szrj 	{
1097*38fd1498Szrj 	case 'e': case 'u':
1098*38fd1498Szrj 	  collect_insn_data (XEXP (pattern, i), palt, pmax);
1099*38fd1498Szrj 	  break;
1100*38fd1498Szrj 
1101*38fd1498Szrj 	case 'V':
1102*38fd1498Szrj 	  if (XVEC (pattern, i) == NULL)
1103*38fd1498Szrj 	    break;
1104*38fd1498Szrj 	  /* Fall through.  */
1105*38fd1498Szrj 	case 'E':
1106*38fd1498Szrj 	  for (j = XVECLEN (pattern, i) - 1; j >= 0; --j)
1107*38fd1498Szrj 	    collect_insn_data (XVECEXP (pattern, i, j), palt, pmax);
1108*38fd1498Szrj 	  break;
1109*38fd1498Szrj 
1110*38fd1498Szrj 	case 'r': case 'p': case 'i': case 'w':
1111*38fd1498Szrj 	case '0': case 's': case 'S': case 'T':
1112*38fd1498Szrj 	  break;
1113*38fd1498Szrj 
1114*38fd1498Szrj 	default:
1115*38fd1498Szrj 	  gcc_unreachable ();
1116*38fd1498Szrj 	}
1117*38fd1498Szrj     }
1118*38fd1498Szrj }
1119*38fd1498Szrj 
1120*38fd1498Szrj static rtx
alter_predicate_for_insn(rtx pattern,int alt,int max_op,file_location loc)1121*38fd1498Szrj alter_predicate_for_insn (rtx pattern, int alt, int max_op,
1122*38fd1498Szrj 			  file_location loc)
1123*38fd1498Szrj {
1124*38fd1498Szrj   const char *fmt;
1125*38fd1498Szrj   enum rtx_code code;
1126*38fd1498Szrj   int i, j, len;
1127*38fd1498Szrj 
1128*38fd1498Szrj   code = GET_CODE (pattern);
1129*38fd1498Szrj   switch (code)
1130*38fd1498Szrj     {
1131*38fd1498Szrj     case MATCH_OPERAND:
1132*38fd1498Szrj       {
1133*38fd1498Szrj 	const char *c = XSTR (pattern, 2);
1134*38fd1498Szrj 
1135*38fd1498Szrj 	if (n_alternatives (c) != 1)
1136*38fd1498Szrj 	  {
1137*38fd1498Szrj 	    error_at (loc, "too many alternatives for operand %d",
1138*38fd1498Szrj 		      XINT (pattern, 0));
1139*38fd1498Szrj 	    return NULL;
1140*38fd1498Szrj 	  }
1141*38fd1498Szrj 
1142*38fd1498Szrj 	/* Replicate C as needed to fill out ALT alternatives.  */
1143*38fd1498Szrj 	if (c && *c && alt > 1)
1144*38fd1498Szrj 	  {
1145*38fd1498Szrj 	    size_t c_len = strlen (c);
1146*38fd1498Szrj 	    size_t len = alt * (c_len + 1);
1147*38fd1498Szrj 	    char *new_c = XNEWVEC (char, len);
1148*38fd1498Szrj 
1149*38fd1498Szrj 	    memcpy (new_c, c, c_len);
1150*38fd1498Szrj 	    for (i = 1; i < alt; ++i)
1151*38fd1498Szrj 	      {
1152*38fd1498Szrj 		new_c[i * (c_len + 1) - 1] = ',';
1153*38fd1498Szrj 		memcpy (&new_c[i * (c_len + 1)], c, c_len);
1154*38fd1498Szrj 	      }
1155*38fd1498Szrj 	    new_c[len - 1] = '\0';
1156*38fd1498Szrj 	    XSTR (pattern, 2) = new_c;
1157*38fd1498Szrj 	  }
1158*38fd1498Szrj       }
1159*38fd1498Szrj       /* Fall through.  */
1160*38fd1498Szrj 
1161*38fd1498Szrj     case MATCH_OPERATOR:
1162*38fd1498Szrj     case MATCH_SCRATCH:
1163*38fd1498Szrj     case MATCH_PARALLEL:
1164*38fd1498Szrj       XINT (pattern, 0) += max_op;
1165*38fd1498Szrj       break;
1166*38fd1498Szrj 
1167*38fd1498Szrj     default:
1168*38fd1498Szrj       break;
1169*38fd1498Szrj     }
1170*38fd1498Szrj 
1171*38fd1498Szrj   fmt = GET_RTX_FORMAT (code);
1172*38fd1498Szrj   len = GET_RTX_LENGTH (code);
1173*38fd1498Szrj   for (i = 0; i < len; i++)
1174*38fd1498Szrj     {
1175*38fd1498Szrj       rtx r;
1176*38fd1498Szrj 
1177*38fd1498Szrj       switch (fmt[i])
1178*38fd1498Szrj 	{
1179*38fd1498Szrj 	case 'e': case 'u':
1180*38fd1498Szrj 	  r = alter_predicate_for_insn (XEXP (pattern, i), alt, max_op, loc);
1181*38fd1498Szrj 	  if (r == NULL)
1182*38fd1498Szrj 	    return r;
1183*38fd1498Szrj 	  break;
1184*38fd1498Szrj 
1185*38fd1498Szrj 	case 'E':
1186*38fd1498Szrj 	  for (j = XVECLEN (pattern, i) - 1; j >= 0; --j)
1187*38fd1498Szrj 	    {
1188*38fd1498Szrj 	      r = alter_predicate_for_insn (XVECEXP (pattern, i, j),
1189*38fd1498Szrj 					    alt, max_op, loc);
1190*38fd1498Szrj 	      if (r == NULL)
1191*38fd1498Szrj 		return r;
1192*38fd1498Szrj 	    }
1193*38fd1498Szrj 	  break;
1194*38fd1498Szrj 
1195*38fd1498Szrj 	case 'r': case 'p': case 'i': case 'w': case '0': case 's':
1196*38fd1498Szrj 	  break;
1197*38fd1498Szrj 
1198*38fd1498Szrj 	default:
1199*38fd1498Szrj 	  gcc_unreachable ();
1200*38fd1498Szrj 	}
1201*38fd1498Szrj     }
1202*38fd1498Szrj 
1203*38fd1498Szrj   return pattern;
1204*38fd1498Szrj }
1205*38fd1498Szrj 
1206*38fd1498Szrj /* Duplicate constraints in PATTERN.  If pattern is from original
1207*38fd1498Szrj    rtl-template, we need to duplicate each alternative - for that we
1208*38fd1498Szrj    need to use duplicate_each_alternative () as a functor ALTER.
1209*38fd1498Szrj    If pattern is from output-pattern of define_subst, we need to
1210*38fd1498Szrj    duplicate constraints in another way - with duplicate_alternatives ().
1211*38fd1498Szrj    N_DUP is multiplication factor.  */
1212*38fd1498Szrj static rtx
alter_constraints(rtx pattern,int n_dup,constraints_handler_t alter)1213*38fd1498Szrj alter_constraints (rtx pattern, int n_dup, constraints_handler_t alter)
1214*38fd1498Szrj {
1215*38fd1498Szrj   const char *fmt;
1216*38fd1498Szrj   enum rtx_code code;
1217*38fd1498Szrj   int i, j, len;
1218*38fd1498Szrj 
1219*38fd1498Szrj   code = GET_CODE (pattern);
1220*38fd1498Szrj   switch (code)
1221*38fd1498Szrj     {
1222*38fd1498Szrj     case MATCH_OPERAND:
1223*38fd1498Szrj       XSTR (pattern, 2) = alter (XSTR (pattern, 2), n_dup);
1224*38fd1498Szrj       break;
1225*38fd1498Szrj 
1226*38fd1498Szrj     default:
1227*38fd1498Szrj       break;
1228*38fd1498Szrj     }
1229*38fd1498Szrj 
1230*38fd1498Szrj   fmt = GET_RTX_FORMAT (code);
1231*38fd1498Szrj   len = GET_RTX_LENGTH (code);
1232*38fd1498Szrj   for (i = 0; i < len; i++)
1233*38fd1498Szrj     {
1234*38fd1498Szrj       rtx r;
1235*38fd1498Szrj 
1236*38fd1498Szrj       switch (fmt[i])
1237*38fd1498Szrj 	{
1238*38fd1498Szrj 	case 'e': case 'u':
1239*38fd1498Szrj 	  r = alter_constraints (XEXP (pattern, i), n_dup, alter);
1240*38fd1498Szrj 	  if (r == NULL)
1241*38fd1498Szrj 	    return r;
1242*38fd1498Szrj 	  break;
1243*38fd1498Szrj 
1244*38fd1498Szrj 	case 'E':
1245*38fd1498Szrj 	  for (j = XVECLEN (pattern, i) - 1; j >= 0; --j)
1246*38fd1498Szrj 	    {
1247*38fd1498Szrj 	      r = alter_constraints (XVECEXP (pattern, i, j), n_dup, alter);
1248*38fd1498Szrj 	      if (r == NULL)
1249*38fd1498Szrj 		return r;
1250*38fd1498Szrj 	    }
1251*38fd1498Szrj 	  break;
1252*38fd1498Szrj 
1253*38fd1498Szrj 	case 'r': case 'p': case 'i': case 'w': case '0': case 's':
1254*38fd1498Szrj 	  break;
1255*38fd1498Szrj 
1256*38fd1498Szrj 	default:
1257*38fd1498Szrj 	  break;
1258*38fd1498Szrj 	}
1259*38fd1498Szrj     }
1260*38fd1498Szrj 
1261*38fd1498Szrj   return pattern;
1262*38fd1498Szrj }
1263*38fd1498Szrj 
1264*38fd1498Szrj static const char *
alter_test_for_insn(struct queue_elem * ce_elem,struct queue_elem * insn_elem)1265*38fd1498Szrj alter_test_for_insn (struct queue_elem *ce_elem,
1266*38fd1498Szrj 		     struct queue_elem *insn_elem)
1267*38fd1498Szrj {
1268*38fd1498Szrj   return rtx_reader_ptr->join_c_conditions (XSTR (ce_elem->data, 1),
1269*38fd1498Szrj 					    XSTR (insn_elem->data, 2));
1270*38fd1498Szrj }
1271*38fd1498Szrj 
1272*38fd1498Szrj /* Modify VAL, which is an attribute expression for the "enabled" attribute,
1273*38fd1498Szrj    to take "ce_enabled" into account.  Return the new expression.  */
1274*38fd1498Szrj static rtx
modify_attr_enabled_ce(rtx val)1275*38fd1498Szrj modify_attr_enabled_ce (rtx val)
1276*38fd1498Szrj {
1277*38fd1498Szrj   rtx eq_attr, str;
1278*38fd1498Szrj   rtx ite;
1279*38fd1498Szrj   eq_attr = rtx_alloc (EQ_ATTR);
1280*38fd1498Szrj   ite = rtx_alloc (IF_THEN_ELSE);
1281*38fd1498Szrj   str = rtx_alloc (CONST_STRING);
1282*38fd1498Szrj 
1283*38fd1498Szrj   XSTR (eq_attr, 0) = "ce_enabled";
1284*38fd1498Szrj   XSTR (eq_attr, 1) = "yes";
1285*38fd1498Szrj   XSTR (str, 0) = "no";
1286*38fd1498Szrj   XEXP (ite, 0) = eq_attr;
1287*38fd1498Szrj   XEXP (ite, 1) = val;
1288*38fd1498Szrj   XEXP (ite, 2) = str;
1289*38fd1498Szrj 
1290*38fd1498Szrj   return ite;
1291*38fd1498Szrj }
1292*38fd1498Szrj 
1293*38fd1498Szrj /* Alter the attribute vector of INSN, which is a COND_EXEC variant created
1294*38fd1498Szrj    from a define_insn pattern.  We must modify the "predicable" attribute
1295*38fd1498Szrj    to be named "ce_enabled", and also change any "enabled" attribute that's
1296*38fd1498Szrj    present so that it takes ce_enabled into account.
1297*38fd1498Szrj    We rely on the fact that INSN was created with copy_rtx, and modify data
1298*38fd1498Szrj    in-place.  */
1299*38fd1498Szrj 
1300*38fd1498Szrj static void
alter_attrs_for_insn(rtx insn)1301*38fd1498Szrj alter_attrs_for_insn (rtx insn)
1302*38fd1498Szrj {
1303*38fd1498Szrj   static bool global_changes_made = false;
1304*38fd1498Szrj   rtvec vec = XVEC (insn, 4);
1305*38fd1498Szrj   rtvec new_vec;
1306*38fd1498Szrj   rtx val, set;
1307*38fd1498Szrj   int num_elem;
1308*38fd1498Szrj   int predicable_idx = -1;
1309*38fd1498Szrj   int enabled_idx = -1;
1310*38fd1498Szrj   int i;
1311*38fd1498Szrj 
1312*38fd1498Szrj   if (! vec)
1313*38fd1498Szrj     return;
1314*38fd1498Szrj 
1315*38fd1498Szrj   num_elem = GET_NUM_ELEM (vec);
1316*38fd1498Szrj   for (i = num_elem - 1; i >= 0; --i)
1317*38fd1498Szrj     {
1318*38fd1498Szrj       rtx sub = RTVEC_ELT (vec, i);
1319*38fd1498Szrj       switch (GET_CODE (sub))
1320*38fd1498Szrj 	{
1321*38fd1498Szrj 	case SET_ATTR:
1322*38fd1498Szrj 	  if (strcmp (XSTR (sub, 0), "predicable") == 0)
1323*38fd1498Szrj 	    {
1324*38fd1498Szrj 	      predicable_idx = i;
1325*38fd1498Szrj 	      XSTR (sub, 0) = "ce_enabled";
1326*38fd1498Szrj 	    }
1327*38fd1498Szrj 	  else if (strcmp (XSTR (sub, 0), "enabled") == 0)
1328*38fd1498Szrj 	    {
1329*38fd1498Szrj 	      enabled_idx = i;
1330*38fd1498Szrj 	      XSTR (sub, 0) = "nonce_enabled";
1331*38fd1498Szrj 	    }
1332*38fd1498Szrj 	  break;
1333*38fd1498Szrj 
1334*38fd1498Szrj 	case SET_ATTR_ALTERNATIVE:
1335*38fd1498Szrj 	  if (strcmp (XSTR (sub, 0), "predicable") == 0)
1336*38fd1498Szrj 	    /* We already give an error elsewhere.  */
1337*38fd1498Szrj 	    return;
1338*38fd1498Szrj 	  else if (strcmp (XSTR (sub, 0), "enabled") == 0)
1339*38fd1498Szrj 	    {
1340*38fd1498Szrj 	      enabled_idx = i;
1341*38fd1498Szrj 	      XSTR (sub, 0) = "nonce_enabled";
1342*38fd1498Szrj 	    }
1343*38fd1498Szrj 	  break;
1344*38fd1498Szrj 
1345*38fd1498Szrj 	case SET:
1346*38fd1498Szrj 	  if (GET_CODE (SET_DEST (sub)) != ATTR)
1347*38fd1498Szrj 	    break;
1348*38fd1498Szrj 	  if (strcmp (XSTR (SET_DEST (sub), 0), "predicable") == 0)
1349*38fd1498Szrj 	    {
1350*38fd1498Szrj 	      sub = SET_SRC (sub);
1351*38fd1498Szrj 	      if (GET_CODE (sub) == CONST_STRING)
1352*38fd1498Szrj 		{
1353*38fd1498Szrj 		  predicable_idx = i;
1354*38fd1498Szrj 		  XSTR (sub, 0) = "ce_enabled";
1355*38fd1498Szrj 		}
1356*38fd1498Szrj 	      else
1357*38fd1498Szrj 		/* We already give an error elsewhere.  */
1358*38fd1498Szrj 		return;
1359*38fd1498Szrj 	      break;
1360*38fd1498Szrj 	    }
1361*38fd1498Szrj 	  if (strcmp (XSTR (SET_DEST (sub), 0), "enabled") == 0)
1362*38fd1498Szrj 	    {
1363*38fd1498Szrj 	      enabled_idx = i;
1364*38fd1498Szrj 	      XSTR (SET_DEST (sub), 0) = "nonce_enabled";
1365*38fd1498Szrj 	    }
1366*38fd1498Szrj 	  break;
1367*38fd1498Szrj 
1368*38fd1498Szrj 	default:
1369*38fd1498Szrj 	  gcc_unreachable ();
1370*38fd1498Szrj 	}
1371*38fd1498Szrj     }
1372*38fd1498Szrj   if (predicable_idx == -1)
1373*38fd1498Szrj     return;
1374*38fd1498Szrj 
1375*38fd1498Szrj   if (!global_changes_made)
1376*38fd1498Szrj     {
1377*38fd1498Szrj       struct queue_elem *elem;
1378*38fd1498Szrj 
1379*38fd1498Szrj       global_changes_made = true;
1380*38fd1498Szrj       add_define_attr ("ce_enabled");
1381*38fd1498Szrj       add_define_attr ("nonce_enabled");
1382*38fd1498Szrj 
1383*38fd1498Szrj       for (elem = define_attr_queue; elem ; elem = elem->next)
1384*38fd1498Szrj 	if (strcmp (XSTR (elem->data, 0), "enabled") == 0)
1385*38fd1498Szrj 	  {
1386*38fd1498Szrj 	    XEXP (elem->data, 2)
1387*38fd1498Szrj 	      = modify_attr_enabled_ce (XEXP (elem->data, 2));
1388*38fd1498Szrj 	  }
1389*38fd1498Szrj     }
1390*38fd1498Szrj   if (enabled_idx == -1)
1391*38fd1498Szrj     return;
1392*38fd1498Szrj 
1393*38fd1498Szrj   new_vec = rtvec_alloc (num_elem + 1);
1394*38fd1498Szrj   for (i = 0; i < num_elem; i++)
1395*38fd1498Szrj     RTVEC_ELT (new_vec, i) = RTVEC_ELT (vec, i);
1396*38fd1498Szrj   val = rtx_alloc (IF_THEN_ELSE);
1397*38fd1498Szrj   XEXP (val, 0) = rtx_alloc (EQ_ATTR);
1398*38fd1498Szrj   XEXP (val, 1) = rtx_alloc (CONST_STRING);
1399*38fd1498Szrj   XEXP (val, 2) = rtx_alloc (CONST_STRING);
1400*38fd1498Szrj   XSTR (XEXP (val, 0), 0) = "nonce_enabled";
1401*38fd1498Szrj   XSTR (XEXP (val, 0), 1) = "yes";
1402*38fd1498Szrj   XSTR (XEXP (val, 1), 0) = "yes";
1403*38fd1498Szrj   XSTR (XEXP (val, 2), 0) = "no";
1404*38fd1498Szrj   set = rtx_alloc (SET);
1405*38fd1498Szrj   SET_DEST (set) = rtx_alloc (ATTR);
1406*38fd1498Szrj   XSTR (SET_DEST (set), 0) = "enabled";
1407*38fd1498Szrj   SET_SRC (set) = modify_attr_enabled_ce (val);
1408*38fd1498Szrj   RTVEC_ELT (new_vec, i) = set;
1409*38fd1498Szrj   XVEC (insn, 4) = new_vec;
1410*38fd1498Szrj }
1411*38fd1498Szrj 
1412*38fd1498Szrj /* As number of constraints is changed after define_subst, we need to
1413*38fd1498Szrj    process attributes as well - we need to duplicate them the same way
1414*38fd1498Szrj    that we duplicated constraints in original pattern
1415*38fd1498Szrj    ELEM is a queue element, containing our rtl-template,
1416*38fd1498Szrj    N_DUP - multiplication factor.  */
1417*38fd1498Szrj static void
alter_attrs_for_subst_insn(struct queue_elem * elem,int n_dup)1418*38fd1498Szrj alter_attrs_for_subst_insn (struct queue_elem * elem, int n_dup)
1419*38fd1498Szrj {
1420*38fd1498Szrj   rtvec vec = XVEC (elem->data, 4);
1421*38fd1498Szrj   int num_elem;
1422*38fd1498Szrj   int i;
1423*38fd1498Szrj 
1424*38fd1498Szrj   if (n_dup < 2 || ! vec)
1425*38fd1498Szrj     return;
1426*38fd1498Szrj 
1427*38fd1498Szrj   num_elem = GET_NUM_ELEM (vec);
1428*38fd1498Szrj   for (i = num_elem - 1; i >= 0; --i)
1429*38fd1498Szrj     {
1430*38fd1498Szrj       rtx sub = RTVEC_ELT (vec, i);
1431*38fd1498Szrj       switch (GET_CODE (sub))
1432*38fd1498Szrj 	{
1433*38fd1498Szrj 	case SET_ATTR:
1434*38fd1498Szrj 	  if (strchr (XSTR (sub, 1), ',') != NULL)
1435*38fd1498Szrj 	    XSTR (sub, 1) = duplicate_alternatives (XSTR (sub, 1), n_dup);
1436*38fd1498Szrj 	    break;
1437*38fd1498Szrj 
1438*38fd1498Szrj 	case SET_ATTR_ALTERNATIVE:
1439*38fd1498Szrj 	case SET:
1440*38fd1498Szrj 	  error_at (elem->loc,
1441*38fd1498Szrj 		    "%s: `define_subst' does not support attributes "
1442*38fd1498Szrj 		    "assigned by `set' and `set_attr_alternative'",
1443*38fd1498Szrj 		    XSTR (elem->data, 0));
1444*38fd1498Szrj 	  return;
1445*38fd1498Szrj 
1446*38fd1498Szrj 	default:
1447*38fd1498Szrj 	  gcc_unreachable ();
1448*38fd1498Szrj 	}
1449*38fd1498Szrj     }
1450*38fd1498Szrj }
1451*38fd1498Szrj 
1452*38fd1498Szrj /* Adjust all of the operand numbers in SRC to match the shift they'll
1453*38fd1498Szrj    get from an operand displacement of DISP.  Return a pointer after the
1454*38fd1498Szrj    adjusted string.  */
1455*38fd1498Szrj 
1456*38fd1498Szrj static char *
shift_output_template(char * dest,const char * src,int disp)1457*38fd1498Szrj shift_output_template (char *dest, const char *src, int disp)
1458*38fd1498Szrj {
1459*38fd1498Szrj   while (*src)
1460*38fd1498Szrj     {
1461*38fd1498Szrj       char c = *src++;
1462*38fd1498Szrj       *dest++ = c;
1463*38fd1498Szrj       if (c == '%')
1464*38fd1498Szrj 	{
1465*38fd1498Szrj 	  c = *src++;
1466*38fd1498Szrj 	  if (ISDIGIT ((unsigned char) c))
1467*38fd1498Szrj 	    c += disp;
1468*38fd1498Szrj 	  else if (ISALPHA (c))
1469*38fd1498Szrj 	    {
1470*38fd1498Szrj 	      *dest++ = c;
1471*38fd1498Szrj 	      c = *src++ + disp;
1472*38fd1498Szrj 	    }
1473*38fd1498Szrj 	  *dest++ = c;
1474*38fd1498Szrj 	}
1475*38fd1498Szrj     }
1476*38fd1498Szrj 
1477*38fd1498Szrj   return dest;
1478*38fd1498Szrj }
1479*38fd1498Szrj 
1480*38fd1498Szrj static const char *
alter_output_for_insn(struct queue_elem * ce_elem,struct queue_elem * insn_elem,int alt,int max_op)1481*38fd1498Szrj alter_output_for_insn (struct queue_elem *ce_elem,
1482*38fd1498Szrj 		       struct queue_elem *insn_elem,
1483*38fd1498Szrj 		       int alt, int max_op)
1484*38fd1498Szrj {
1485*38fd1498Szrj   const char *ce_out, *insn_out;
1486*38fd1498Szrj   char *result, *p;
1487*38fd1498Szrj   size_t len, ce_len, insn_len;
1488*38fd1498Szrj 
1489*38fd1498Szrj   /* ??? Could coordinate with genoutput to not duplicate code here.  */
1490*38fd1498Szrj 
1491*38fd1498Szrj   ce_out = XSTR (ce_elem->data, 2);
1492*38fd1498Szrj   insn_out = XTMPL (insn_elem->data, 3);
1493*38fd1498Szrj   if (!ce_out || *ce_out == '\0')
1494*38fd1498Szrj     return insn_out;
1495*38fd1498Szrj 
1496*38fd1498Szrj   ce_len = strlen (ce_out);
1497*38fd1498Szrj   insn_len = strlen (insn_out);
1498*38fd1498Szrj 
1499*38fd1498Szrj   if (*insn_out == '*')
1500*38fd1498Szrj     /* You must take care of the predicate yourself.  */
1501*38fd1498Szrj     return insn_out;
1502*38fd1498Szrj 
1503*38fd1498Szrj   if (*insn_out == '@')
1504*38fd1498Szrj     {
1505*38fd1498Szrj       len = (ce_len + 1) * alt + insn_len + 1;
1506*38fd1498Szrj       p = result = XNEWVEC (char, len);
1507*38fd1498Szrj 
1508*38fd1498Szrj       do
1509*38fd1498Szrj 	{
1510*38fd1498Szrj 	  do
1511*38fd1498Szrj 	    *p++ = *insn_out++;
1512*38fd1498Szrj 	  while (ISSPACE ((unsigned char) *insn_out));
1513*38fd1498Szrj 
1514*38fd1498Szrj 	  if (*insn_out != '#')
1515*38fd1498Szrj 	    {
1516*38fd1498Szrj 	      p = shift_output_template (p, ce_out, max_op);
1517*38fd1498Szrj 	      *p++ = ' ';
1518*38fd1498Szrj 	    }
1519*38fd1498Szrj 
1520*38fd1498Szrj 	  do
1521*38fd1498Szrj 	    *p++ = *insn_out++;
1522*38fd1498Szrj 	  while (*insn_out && *insn_out != '\n');
1523*38fd1498Szrj 	}
1524*38fd1498Szrj       while (*insn_out);
1525*38fd1498Szrj       *p = '\0';
1526*38fd1498Szrj     }
1527*38fd1498Szrj   else
1528*38fd1498Szrj     {
1529*38fd1498Szrj       len = ce_len + 1 + insn_len + 1;
1530*38fd1498Szrj       result = XNEWVEC (char, len);
1531*38fd1498Szrj 
1532*38fd1498Szrj       p = shift_output_template (result, ce_out, max_op);
1533*38fd1498Szrj       *p++ = ' ';
1534*38fd1498Szrj       memcpy (p, insn_out, insn_len + 1);
1535*38fd1498Szrj     }
1536*38fd1498Szrj 
1537*38fd1498Szrj   return result;
1538*38fd1498Szrj }
1539*38fd1498Szrj 
1540*38fd1498Szrj /* From string STR "a,b,c" produce "a,b,c,a,b,c,a,b,c", i.e. original
1541*38fd1498Szrj    string, duplicated N_DUP times.  */
1542*38fd1498Szrj 
1543*38fd1498Szrj static const char *
duplicate_alternatives(const char * str,int n_dup)1544*38fd1498Szrj duplicate_alternatives (const char * str, int n_dup)
1545*38fd1498Szrj {
1546*38fd1498Szrj   int i, len, new_len;
1547*38fd1498Szrj   char *result, *sp;
1548*38fd1498Szrj   const char *cp;
1549*38fd1498Szrj 
1550*38fd1498Szrj   if (n_dup < 2)
1551*38fd1498Szrj     return str;
1552*38fd1498Szrj 
1553*38fd1498Szrj   while (ISSPACE (*str))
1554*38fd1498Szrj     str++;
1555*38fd1498Szrj 
1556*38fd1498Szrj   if (*str == '\0')
1557*38fd1498Szrj     return str;
1558*38fd1498Szrj 
1559*38fd1498Szrj   cp = str;
1560*38fd1498Szrj   len = strlen (str);
1561*38fd1498Szrj   new_len = (len + 1) * n_dup;
1562*38fd1498Szrj 
1563*38fd1498Szrj   sp = result = XNEWVEC (char, new_len);
1564*38fd1498Szrj 
1565*38fd1498Szrj   /* Global modifier characters mustn't be duplicated: skip if found.  */
1566*38fd1498Szrj   if (*cp == '=' || *cp == '+' || *cp == '%')
1567*38fd1498Szrj     {
1568*38fd1498Szrj       *sp++ = *cp++;
1569*38fd1498Szrj       len--;
1570*38fd1498Szrj     }
1571*38fd1498Szrj 
1572*38fd1498Szrj   /* Copy original constraints N_DUP times.  */
1573*38fd1498Szrj   for (i = 0; i < n_dup; i++, sp += len+1)
1574*38fd1498Szrj     {
1575*38fd1498Szrj       memcpy (sp, cp, len);
1576*38fd1498Szrj       *(sp+len) = (i == n_dup - 1) ? '\0' : ',';
1577*38fd1498Szrj     }
1578*38fd1498Szrj 
1579*38fd1498Szrj   return result;
1580*38fd1498Szrj }
1581*38fd1498Szrj 
1582*38fd1498Szrj /* From string STR "a,b,c" produce "a,a,a,b,b,b,c,c,c", i.e. string where
1583*38fd1498Szrj    each alternative from the original string is duplicated N_DUP times.  */
1584*38fd1498Szrj static const char *
duplicate_each_alternative(const char * str,int n_dup)1585*38fd1498Szrj duplicate_each_alternative (const char * str, int n_dup)
1586*38fd1498Szrj {
1587*38fd1498Szrj   int i, len, new_len;
1588*38fd1498Szrj   char *result, *sp, *ep, *cp;
1589*38fd1498Szrj 
1590*38fd1498Szrj   if (n_dup < 2)
1591*38fd1498Szrj     return str;
1592*38fd1498Szrj 
1593*38fd1498Szrj   while (ISSPACE (*str))
1594*38fd1498Szrj     str++;
1595*38fd1498Szrj 
1596*38fd1498Szrj   if (*str == '\0')
1597*38fd1498Szrj     return str;
1598*38fd1498Szrj 
1599*38fd1498Szrj   cp = xstrdup (str);
1600*38fd1498Szrj 
1601*38fd1498Szrj   new_len = (strlen (cp) + 1) * n_dup;
1602*38fd1498Szrj 
1603*38fd1498Szrj   sp = result = XNEWVEC (char, new_len);
1604*38fd1498Szrj 
1605*38fd1498Szrj   /* Global modifier characters mustn't be duplicated: skip if found.  */
1606*38fd1498Szrj   if (*cp == '=' || *cp == '+' || *cp == '%')
1607*38fd1498Szrj       *sp++ = *cp++;
1608*38fd1498Szrj 
1609*38fd1498Szrj   do
1610*38fd1498Szrj     {
1611*38fd1498Szrj       if ((ep = strchr (cp, ',')) != NULL)
1612*38fd1498Szrj 	*ep++ = '\0';
1613*38fd1498Szrj       len = strlen (cp);
1614*38fd1498Szrj 
1615*38fd1498Szrj       /* Copy a constraint N_DUP times.  */
1616*38fd1498Szrj       for (i = 0; i < n_dup; i++, sp += len + 1)
1617*38fd1498Szrj 	{
1618*38fd1498Szrj 	  memcpy (sp, cp, len);
1619*38fd1498Szrj 	  *(sp+len) = (ep == NULL && i == n_dup - 1) ? '\0' : ',';
1620*38fd1498Szrj 	}
1621*38fd1498Szrj 
1622*38fd1498Szrj       cp = ep;
1623*38fd1498Szrj     }
1624*38fd1498Szrj   while (cp != NULL);
1625*38fd1498Szrj 
1626*38fd1498Szrj   return result;
1627*38fd1498Szrj }
1628*38fd1498Szrj 
1629*38fd1498Szrj /* Alter the output of INSN whose pattern was modified by
1630*38fd1498Szrj    DEFINE_SUBST.  We must replicate output strings according
1631*38fd1498Szrj    to the new number of alternatives ALT in substituted pattern.
1632*38fd1498Szrj    If ALT equals 1, output has one alternative or defined by C
1633*38fd1498Szrj    code, then output is returned without any changes.  */
1634*38fd1498Szrj 
1635*38fd1498Szrj static const char *
alter_output_for_subst_insn(rtx insn,int alt)1636*38fd1498Szrj alter_output_for_subst_insn (rtx insn, int alt)
1637*38fd1498Szrj {
1638*38fd1498Szrj   const char *insn_out, *old_out;
1639*38fd1498Szrj   char *new_out, *cp;
1640*38fd1498Szrj   size_t old_len, new_len;
1641*38fd1498Szrj   int j;
1642*38fd1498Szrj 
1643*38fd1498Szrj   insn_out = XTMPL (insn, 3);
1644*38fd1498Szrj 
1645*38fd1498Szrj   if (alt < 2 || *insn_out != '@')
1646*38fd1498Szrj     return insn_out;
1647*38fd1498Szrj 
1648*38fd1498Szrj   old_out = insn_out + 1;
1649*38fd1498Szrj   while (ISSPACE (*old_out))
1650*38fd1498Szrj     old_out++;
1651*38fd1498Szrj   old_len = strlen (old_out);
1652*38fd1498Szrj 
1653*38fd1498Szrj   new_len = alt * (old_len + 1) + 1;
1654*38fd1498Szrj 
1655*38fd1498Szrj   new_out = XNEWVEC (char, new_len);
1656*38fd1498Szrj   new_out[0] = '@';
1657*38fd1498Szrj 
1658*38fd1498Szrj   for (j = 0, cp = new_out + 1; j < alt; j++, cp += old_len + 1)
1659*38fd1498Szrj     {
1660*38fd1498Szrj       memcpy (cp, old_out, old_len);
1661*38fd1498Szrj       cp[old_len] = (j == alt - 1) ? '\0' : '\n';
1662*38fd1498Szrj     }
1663*38fd1498Szrj 
1664*38fd1498Szrj   return new_out;
1665*38fd1498Szrj }
1666*38fd1498Szrj 
1667*38fd1498Szrj /* Replicate insns as appropriate for the given DEFINE_COND_EXEC.  */
1668*38fd1498Szrj 
1669*38fd1498Szrj static void
process_one_cond_exec(struct queue_elem * ce_elem)1670*38fd1498Szrj process_one_cond_exec (struct queue_elem *ce_elem)
1671*38fd1498Szrj {
1672*38fd1498Szrj   struct queue_elem *insn_elem;
1673*38fd1498Szrj   for (insn_elem = define_insn_queue; insn_elem ; insn_elem = insn_elem->next)
1674*38fd1498Szrj     {
1675*38fd1498Szrj       int alternatives, max_operand;
1676*38fd1498Szrj       rtx pred, insn, pattern, split;
1677*38fd1498Szrj       char *new_name;
1678*38fd1498Szrj       int i;
1679*38fd1498Szrj 
1680*38fd1498Szrj       if (! is_predicable (insn_elem))
1681*38fd1498Szrj 	continue;
1682*38fd1498Szrj 
1683*38fd1498Szrj       alternatives = 1;
1684*38fd1498Szrj       max_operand = -1;
1685*38fd1498Szrj       collect_insn_data (insn_elem->data, &alternatives, &max_operand);
1686*38fd1498Szrj       max_operand += 1;
1687*38fd1498Szrj 
1688*38fd1498Szrj       if (XVECLEN (ce_elem->data, 0) != 1)
1689*38fd1498Szrj 	{
1690*38fd1498Szrj 	  error_at (ce_elem->loc, "too many patterns in predicate");
1691*38fd1498Szrj 	  return;
1692*38fd1498Szrj 	}
1693*38fd1498Szrj 
1694*38fd1498Szrj       pred = copy_rtx (XVECEXP (ce_elem->data, 0, 0));
1695*38fd1498Szrj       pred = alter_predicate_for_insn (pred, alternatives, max_operand,
1696*38fd1498Szrj 				       ce_elem->loc);
1697*38fd1498Szrj       if (pred == NULL)
1698*38fd1498Szrj 	return;
1699*38fd1498Szrj 
1700*38fd1498Szrj       /* Construct a new pattern for the new insn.  */
1701*38fd1498Szrj       insn = copy_rtx (insn_elem->data);
1702*38fd1498Szrj       new_name = XNEWVAR (char, strlen XSTR (insn_elem->data, 0) + 4);
1703*38fd1498Szrj       sprintf (new_name, "*p %s", XSTR (insn_elem->data, 0));
1704*38fd1498Szrj       XSTR (insn, 0) = new_name;
1705*38fd1498Szrj       pattern = rtx_alloc (COND_EXEC);
1706*38fd1498Szrj       XEXP (pattern, 0) = pred;
1707*38fd1498Szrj       XEXP (pattern, 1) = add_implicit_parallel (XVEC (insn, 1));
1708*38fd1498Szrj       XVEC (insn, 1) = rtvec_alloc (1);
1709*38fd1498Szrj       XVECEXP (insn, 1, 0) = pattern;
1710*38fd1498Szrj 
1711*38fd1498Szrj        if (XVEC (ce_elem->data, 3) != NULL)
1712*38fd1498Szrj 	{
1713*38fd1498Szrj 	  rtvec attributes = rtvec_alloc (XVECLEN (insn, 4)
1714*38fd1498Szrj 	                                  + XVECLEN (ce_elem->data, 3));
1715*38fd1498Szrj 	  int i = 0;
1716*38fd1498Szrj 	  int j = 0;
1717*38fd1498Szrj 	  for (i = 0; i < XVECLEN (insn, 4); i++)
1718*38fd1498Szrj 	    RTVEC_ELT (attributes, i) = XVECEXP (insn, 4, i);
1719*38fd1498Szrj 
1720*38fd1498Szrj 	  for (j = 0; j < XVECLEN (ce_elem->data, 3); j++, i++)
1721*38fd1498Szrj 	    RTVEC_ELT (attributes, i) = XVECEXP (ce_elem->data, 3, j);
1722*38fd1498Szrj 
1723*38fd1498Szrj 	  XVEC (insn, 4) = attributes;
1724*38fd1498Szrj 	}
1725*38fd1498Szrj 
1726*38fd1498Szrj       XSTR (insn, 2) = alter_test_for_insn (ce_elem, insn_elem);
1727*38fd1498Szrj       XTMPL (insn, 3) = alter_output_for_insn (ce_elem, insn_elem,
1728*38fd1498Szrj 					      alternatives, max_operand);
1729*38fd1498Szrj       alter_attrs_for_insn (insn);
1730*38fd1498Szrj 
1731*38fd1498Szrj       /* Put the new pattern on the `other' list so that it
1732*38fd1498Szrj 	 (a) is not reprocessed by other define_cond_exec patterns
1733*38fd1498Szrj 	 (b) appears after all normal define_insn patterns.
1734*38fd1498Szrj 
1735*38fd1498Szrj 	 ??? B is debatable.  If one has normal insns that match
1736*38fd1498Szrj 	 cond_exec patterns, they will be preferred over these
1737*38fd1498Szrj 	 generated patterns.  Whether this matters in practice, or if
1738*38fd1498Szrj 	 it's a good thing, or whether we should thread these new
1739*38fd1498Szrj 	 patterns into the define_insn chain just after their generator
1740*38fd1498Szrj 	 is something we'll have to experiment with.  */
1741*38fd1498Szrj 
1742*38fd1498Szrj       queue_pattern (insn, &other_tail, insn_elem->loc);
1743*38fd1498Szrj 
1744*38fd1498Szrj       if (!insn_elem->split)
1745*38fd1498Szrj 	continue;
1746*38fd1498Szrj 
1747*38fd1498Szrj       /* If the original insn came from a define_insn_and_split,
1748*38fd1498Szrj 	 generate a new split to handle the predicated insn.  */
1749*38fd1498Szrj       split = copy_rtx (insn_elem->split->data);
1750*38fd1498Szrj       /* Predicate the pattern matched by the split.  */
1751*38fd1498Szrj       pattern = rtx_alloc (COND_EXEC);
1752*38fd1498Szrj       XEXP (pattern, 0) = pred;
1753*38fd1498Szrj       XEXP (pattern, 1) = add_implicit_parallel (XVEC (split, 0));
1754*38fd1498Szrj       XVEC (split, 0) = rtvec_alloc (1);
1755*38fd1498Szrj       XVECEXP (split, 0, 0) = pattern;
1756*38fd1498Szrj 
1757*38fd1498Szrj       /* Predicate all of the insns generated by the split.  */
1758*38fd1498Szrj       for (i = 0; i < XVECLEN (split, 2); i++)
1759*38fd1498Szrj 	{
1760*38fd1498Szrj 	  pattern = rtx_alloc (COND_EXEC);
1761*38fd1498Szrj 	  XEXP (pattern, 0) = pred;
1762*38fd1498Szrj 	  XEXP (pattern, 1) = XVECEXP (split, 2, i);
1763*38fd1498Szrj 	  XVECEXP (split, 2, i) = pattern;
1764*38fd1498Szrj 	}
1765*38fd1498Szrj       /* Add the new split to the queue.  */
1766*38fd1498Szrj       queue_pattern (split, &other_tail, insn_elem->split->loc);
1767*38fd1498Szrj     }
1768*38fd1498Szrj }
1769*38fd1498Szrj 
1770*38fd1498Szrj /* Try to apply define_substs to the given ELEM.
1771*38fd1498Szrj    Only define_substs, specified via attributes would be applied.
1772*38fd1498Szrj    If attribute, requiring define_subst, is set, but no define_subst
1773*38fd1498Szrj    was applied, ELEM would be deleted.  */
1774*38fd1498Szrj 
1775*38fd1498Szrj static void
process_substs_on_one_elem(struct queue_elem * elem,struct queue_elem * queue)1776*38fd1498Szrj process_substs_on_one_elem (struct queue_elem *elem,
1777*38fd1498Szrj 			    struct queue_elem *queue)
1778*38fd1498Szrj {
1779*38fd1498Szrj   struct queue_elem *subst_elem;
1780*38fd1498Szrj   int i, j, patterns_match;
1781*38fd1498Szrj 
1782*38fd1498Szrj   for (subst_elem = define_subst_queue;
1783*38fd1498Szrj        subst_elem; subst_elem = subst_elem->next)
1784*38fd1498Szrj     {
1785*38fd1498Szrj       int alternatives, alternatives_subst;
1786*38fd1498Szrj       rtx subst_pattern;
1787*38fd1498Szrj       rtvec subst_pattern_vec;
1788*38fd1498Szrj 
1789*38fd1498Szrj       if (!has_subst_attribute (elem, subst_elem))
1790*38fd1498Szrj 	continue;
1791*38fd1498Szrj 
1792*38fd1498Szrj       /* Compare original rtl-pattern from define_insn with input
1793*38fd1498Szrj 	 pattern from define_subst.
1794*38fd1498Szrj 	 Also, check if numbers of alternatives are the same in all
1795*38fd1498Szrj 	 match_operands.  */
1796*38fd1498Szrj       if (XVECLEN (elem->data, 1) != XVECLEN (subst_elem->data, 1))
1797*38fd1498Szrj 	continue;
1798*38fd1498Szrj       patterns_match = 1;
1799*38fd1498Szrj       alternatives = -1;
1800*38fd1498Szrj       alternatives_subst = -1;
1801*38fd1498Szrj       for (j = 0; j < XVECLEN (elem->data, 1); j++)
1802*38fd1498Szrj 	{
1803*38fd1498Szrj 	  if (!subst_pattern_match (XVECEXP (elem->data, 1, j),
1804*38fd1498Szrj 				    XVECEXP (subst_elem->data, 1, j),
1805*38fd1498Szrj 				    subst_elem->loc))
1806*38fd1498Szrj 	    {
1807*38fd1498Szrj 	      patterns_match = 0;
1808*38fd1498Szrj 	      break;
1809*38fd1498Szrj 	    }
1810*38fd1498Szrj 
1811*38fd1498Szrj 	  if (!get_alternatives_number (XVECEXP (elem->data, 1, j),
1812*38fd1498Szrj 					&alternatives, subst_elem->loc))
1813*38fd1498Szrj 	    {
1814*38fd1498Szrj 	      patterns_match = 0;
1815*38fd1498Szrj 	      break;
1816*38fd1498Szrj 	    }
1817*38fd1498Szrj 	}
1818*38fd1498Szrj 
1819*38fd1498Szrj       /* Check if numbers of alternatives are the same in all
1820*38fd1498Szrj 	 match_operands in output template of define_subst.  */
1821*38fd1498Szrj       for (j = 0; j < XVECLEN (subst_elem->data, 3); j++)
1822*38fd1498Szrj 	{
1823*38fd1498Szrj 	  if (!get_alternatives_number (XVECEXP (subst_elem->data, 3, j),
1824*38fd1498Szrj 					&alternatives_subst,
1825*38fd1498Szrj 					subst_elem->loc))
1826*38fd1498Szrj 	    {
1827*38fd1498Szrj 	      patterns_match = 0;
1828*38fd1498Szrj 	      break;
1829*38fd1498Szrj 	    }
1830*38fd1498Szrj 	}
1831*38fd1498Szrj 
1832*38fd1498Szrj       if (!patterns_match)
1833*38fd1498Szrj 	continue;
1834*38fd1498Szrj 
1835*38fd1498Szrj       /* Clear array in which we save occupied indexes of operands.  */
1836*38fd1498Szrj       memset (used_operands_numbers, 0, sizeof (used_operands_numbers));
1837*38fd1498Szrj 
1838*38fd1498Szrj       /* Create a pattern, based on the output one from define_subst.  */
1839*38fd1498Szrj       subst_pattern_vec = rtvec_alloc (XVECLEN (subst_elem->data, 3));
1840*38fd1498Szrj       for (j = 0; j < XVECLEN (subst_elem->data, 3); j++)
1841*38fd1498Szrj 	{
1842*38fd1498Szrj 	  subst_pattern = copy_rtx (XVECEXP (subst_elem->data, 3, j));
1843*38fd1498Szrj 
1844*38fd1498Szrj 	  /* Duplicate constraints in substitute-pattern.  */
1845*38fd1498Szrj 	  subst_pattern = alter_constraints (subst_pattern, alternatives,
1846*38fd1498Szrj 					     duplicate_each_alternative);
1847*38fd1498Szrj 
1848*38fd1498Szrj 	  subst_pattern = adjust_operands_numbers (subst_pattern);
1849*38fd1498Szrj 
1850*38fd1498Szrj 	  /* Substitute match_dup and match_op_dup in the new pattern and
1851*38fd1498Szrj 	     duplicate constraints.  */
1852*38fd1498Szrj 	  subst_pattern = subst_dup (subst_pattern, alternatives,
1853*38fd1498Szrj 				     alternatives_subst);
1854*38fd1498Szrj 
1855*38fd1498Szrj 	  replace_duplicating_operands_in_pattern (subst_pattern);
1856*38fd1498Szrj 
1857*38fd1498Szrj 	  /* We don't need any constraints in DEFINE_EXPAND.  */
1858*38fd1498Szrj 	  if (GET_CODE (elem->data) == DEFINE_EXPAND)
1859*38fd1498Szrj 	    remove_constraints (subst_pattern);
1860*38fd1498Szrj 
1861*38fd1498Szrj 	  RTVEC_ELT (subst_pattern_vec, j) = subst_pattern;
1862*38fd1498Szrj 	}
1863*38fd1498Szrj       XVEC (elem->data, 1) = subst_pattern_vec;
1864*38fd1498Szrj 
1865*38fd1498Szrj       for (i = 0; i < MAX_OPERANDS; i++)
1866*38fd1498Szrj 	  match_operand_entries_in_pattern[i] = NULL;
1867*38fd1498Szrj 
1868*38fd1498Szrj       if (GET_CODE (elem->data) == DEFINE_INSN)
1869*38fd1498Szrj 	{
1870*38fd1498Szrj 	  XTMPL (elem->data, 3) =
1871*38fd1498Szrj 	    alter_output_for_subst_insn (elem->data, alternatives_subst);
1872*38fd1498Szrj 	  alter_attrs_for_subst_insn (elem, alternatives_subst);
1873*38fd1498Szrj 	}
1874*38fd1498Szrj 
1875*38fd1498Szrj       /* Recalculate condition, joining conditions from original and
1876*38fd1498Szrj 	 DEFINE_SUBST input patterns.  */
1877*38fd1498Szrj       XSTR (elem->data, 2)
1878*38fd1498Szrj 	= rtx_reader_ptr->join_c_conditions (XSTR (subst_elem->data, 2),
1879*38fd1498Szrj 					     XSTR (elem->data, 2));
1880*38fd1498Szrj       /* Mark that subst was applied by changing attribute from "yes"
1881*38fd1498Szrj 	 to "no".  */
1882*38fd1498Szrj       change_subst_attribute (elem, subst_elem, subst_false);
1883*38fd1498Szrj     }
1884*38fd1498Szrj 
1885*38fd1498Szrj   /* If ELEM contains a subst attribute with value "yes", then we
1886*38fd1498Szrj      expected that a subst would be applied, but it wasn't - so,
1887*38fd1498Szrj      we need to remove that elementto avoid duplicating.  */
1888*38fd1498Szrj   for (subst_elem = define_subst_queue;
1889*38fd1498Szrj        subst_elem; subst_elem = subst_elem->next)
1890*38fd1498Szrj     {
1891*38fd1498Szrj       if (has_subst_attribute (elem, subst_elem))
1892*38fd1498Szrj 	{
1893*38fd1498Szrj 	  remove_from_queue (elem, &queue);
1894*38fd1498Szrj 	  return;
1895*38fd1498Szrj 	}
1896*38fd1498Szrj     }
1897*38fd1498Szrj }
1898*38fd1498Szrj 
1899*38fd1498Szrj /* This is a subroutine of mark_operands_used_in_match_dup.
1900*38fd1498Szrj    This routine is marks all MATCH_OPERANDs inside PATTERN as occupied.  */
1901*38fd1498Szrj static void
mark_operands_from_match_dup(rtx pattern)1902*38fd1498Szrj mark_operands_from_match_dup (rtx pattern)
1903*38fd1498Szrj {
1904*38fd1498Szrj   const char *fmt;
1905*38fd1498Szrj   int i, j, len, opno;
1906*38fd1498Szrj 
1907*38fd1498Szrj   if (GET_CODE (pattern) == MATCH_OPERAND
1908*38fd1498Szrj       || GET_CODE (pattern) == MATCH_OPERATOR
1909*38fd1498Szrj       || GET_CODE (pattern) == MATCH_PARALLEL)
1910*38fd1498Szrj     {
1911*38fd1498Szrj       opno = XINT (pattern, 0);
1912*38fd1498Szrj       gcc_assert (opno >= 0 && opno < MAX_OPERANDS);
1913*38fd1498Szrj       used_operands_numbers [opno] = 1;
1914*38fd1498Szrj     }
1915*38fd1498Szrj   fmt = GET_RTX_FORMAT (GET_CODE (pattern));
1916*38fd1498Szrj   len = GET_RTX_LENGTH (GET_CODE (pattern));
1917*38fd1498Szrj   for (i = 0; i < len; i++)
1918*38fd1498Szrj     {
1919*38fd1498Szrj       switch (fmt[i])
1920*38fd1498Szrj 	{
1921*38fd1498Szrj 	case 'e': case 'u':
1922*38fd1498Szrj 	  mark_operands_from_match_dup (XEXP (pattern, i));
1923*38fd1498Szrj 	  break;
1924*38fd1498Szrj 	case 'E':
1925*38fd1498Szrj 	  for (j = XVECLEN (pattern, i) - 1; j >= 0; --j)
1926*38fd1498Szrj 	    mark_operands_from_match_dup (XVECEXP (pattern, i, j));
1927*38fd1498Szrj 	  break;
1928*38fd1498Szrj 	}
1929*38fd1498Szrj     }
1930*38fd1498Szrj }
1931*38fd1498Szrj 
1932*38fd1498Szrj /* This is a subroutine of adjust_operands_numbers.
1933*38fd1498Szrj    It goes through all expressions in PATTERN and when MATCH_DUP is
1934*38fd1498Szrj    met, all MATCH_OPERANDs inside it is marked as occupied.  The
1935*38fd1498Szrj    process of marking is done by routin mark_operands_from_match_dup.  */
1936*38fd1498Szrj static void
mark_operands_used_in_match_dup(rtx pattern)1937*38fd1498Szrj mark_operands_used_in_match_dup (rtx pattern)
1938*38fd1498Szrj {
1939*38fd1498Szrj   const char *fmt;
1940*38fd1498Szrj   int i, j, len, opno;
1941*38fd1498Szrj 
1942*38fd1498Szrj   if (GET_CODE (pattern) == MATCH_DUP)
1943*38fd1498Szrj     {
1944*38fd1498Szrj       opno = XINT (pattern, 0);
1945*38fd1498Szrj       gcc_assert (opno >= 0 && opno < MAX_OPERANDS);
1946*38fd1498Szrj       mark_operands_from_match_dup (operand_data[opno]);
1947*38fd1498Szrj       return;
1948*38fd1498Szrj     }
1949*38fd1498Szrj   fmt = GET_RTX_FORMAT (GET_CODE (pattern));
1950*38fd1498Szrj   len = GET_RTX_LENGTH (GET_CODE (pattern));
1951*38fd1498Szrj   for (i = 0; i < len; i++)
1952*38fd1498Szrj     {
1953*38fd1498Szrj       switch (fmt[i])
1954*38fd1498Szrj 	{
1955*38fd1498Szrj 	case 'e': case 'u':
1956*38fd1498Szrj 	  mark_operands_used_in_match_dup (XEXP (pattern, i));
1957*38fd1498Szrj 	  break;
1958*38fd1498Szrj 	case 'E':
1959*38fd1498Szrj 	  for (j = XVECLEN (pattern, i) - 1; j >= 0; --j)
1960*38fd1498Szrj 	    mark_operands_used_in_match_dup (XVECEXP (pattern, i, j));
1961*38fd1498Szrj 	  break;
1962*38fd1498Szrj 	}
1963*38fd1498Szrj     }
1964*38fd1498Szrj }
1965*38fd1498Szrj 
1966*38fd1498Szrj /* This is subroutine of renumerate_operands_in_pattern.
1967*38fd1498Szrj    It finds first not-occupied operand-index.  */
1968*38fd1498Szrj static int
find_first_unused_number_of_operand()1969*38fd1498Szrj find_first_unused_number_of_operand ()
1970*38fd1498Szrj {
1971*38fd1498Szrj   int i;
1972*38fd1498Szrj   for (i = 0; i < MAX_OPERANDS; i++)
1973*38fd1498Szrj     if (!used_operands_numbers[i])
1974*38fd1498Szrj       return i;
1975*38fd1498Szrj   return MAX_OPERANDS;
1976*38fd1498Szrj }
1977*38fd1498Szrj 
1978*38fd1498Szrj /* This is subroutine of adjust_operands_numbers.
1979*38fd1498Szrj    It visits all expressions in PATTERN and assigns not-occupied
1980*38fd1498Szrj    operand indexes to MATCH_OPERANDs and MATCH_OPERATORs of this
1981*38fd1498Szrj    PATTERN.  */
1982*38fd1498Szrj static void
renumerate_operands_in_pattern(rtx pattern)1983*38fd1498Szrj renumerate_operands_in_pattern (rtx pattern)
1984*38fd1498Szrj {
1985*38fd1498Szrj   const char *fmt;
1986*38fd1498Szrj   enum rtx_code code;
1987*38fd1498Szrj   int i, j, len, new_opno;
1988*38fd1498Szrj   code = GET_CODE (pattern);
1989*38fd1498Szrj 
1990*38fd1498Szrj   if (code == MATCH_OPERAND
1991*38fd1498Szrj       || code == MATCH_OPERATOR)
1992*38fd1498Szrj     {
1993*38fd1498Szrj       new_opno = find_first_unused_number_of_operand ();
1994*38fd1498Szrj       gcc_assert (new_opno >= 0 && new_opno < MAX_OPERANDS);
1995*38fd1498Szrj       XINT (pattern, 0) = new_opno;
1996*38fd1498Szrj       used_operands_numbers [new_opno] = 1;
1997*38fd1498Szrj     }
1998*38fd1498Szrj 
1999*38fd1498Szrj   fmt = GET_RTX_FORMAT (GET_CODE (pattern));
2000*38fd1498Szrj   len = GET_RTX_LENGTH (GET_CODE (pattern));
2001*38fd1498Szrj   for (i = 0; i < len; i++)
2002*38fd1498Szrj     {
2003*38fd1498Szrj       switch (fmt[i])
2004*38fd1498Szrj 	{
2005*38fd1498Szrj 	case 'e': case 'u':
2006*38fd1498Szrj 	  renumerate_operands_in_pattern (XEXP (pattern, i));
2007*38fd1498Szrj 	  break;
2008*38fd1498Szrj 	case 'E':
2009*38fd1498Szrj 	  for (j = XVECLEN (pattern, i) - 1; j >= 0; --j)
2010*38fd1498Szrj 	    renumerate_operands_in_pattern (XVECEXP (pattern, i, j));
2011*38fd1498Szrj 	  break;
2012*38fd1498Szrj 	}
2013*38fd1498Szrj     }
2014*38fd1498Szrj }
2015*38fd1498Szrj 
2016*38fd1498Szrj /* If output pattern of define_subst contains MATCH_DUP, then this
2017*38fd1498Szrj    expression would be replaced with the pattern, matched with
2018*38fd1498Szrj    MATCH_OPERAND from input pattern.  This pattern could contain any
2019*38fd1498Szrj    number of MATCH_OPERANDs, MATCH_OPERATORs etc., so it's possible
2020*38fd1498Szrj    that a MATCH_OPERAND from output_pattern (if any) would have the
2021*38fd1498Szrj    same number, as MATCH_OPERAND from copied pattern.  To avoid such
2022*38fd1498Szrj    indexes overlapping, we assign new indexes to MATCH_OPERANDs,
2023*38fd1498Szrj    laying in the output pattern outside of MATCH_DUPs.  */
2024*38fd1498Szrj static rtx
adjust_operands_numbers(rtx pattern)2025*38fd1498Szrj adjust_operands_numbers (rtx pattern)
2026*38fd1498Szrj {
2027*38fd1498Szrj   mark_operands_used_in_match_dup (pattern);
2028*38fd1498Szrj 
2029*38fd1498Szrj   renumerate_operands_in_pattern (pattern);
2030*38fd1498Szrj 
2031*38fd1498Szrj   return pattern;
2032*38fd1498Szrj }
2033*38fd1498Szrj 
2034*38fd1498Szrj /* Generate RTL expression
2035*38fd1498Szrj    (match_dup OPNO)
2036*38fd1498Szrj    */
2037*38fd1498Szrj static rtx
generate_match_dup(int opno)2038*38fd1498Szrj generate_match_dup (int opno)
2039*38fd1498Szrj {
2040*38fd1498Szrj   rtx return_rtx = rtx_alloc (MATCH_DUP);
2041*38fd1498Szrj   PUT_CODE (return_rtx, MATCH_DUP);
2042*38fd1498Szrj   XINT (return_rtx, 0) = opno;
2043*38fd1498Szrj   return return_rtx;
2044*38fd1498Szrj }
2045*38fd1498Szrj 
2046*38fd1498Szrj /* This routine checks all match_operands in PATTERN and if some of
2047*38fd1498Szrj    have the same index, it replaces all of them except the first one  to
2048*38fd1498Szrj    match_dup.
2049*38fd1498Szrj    Usually, match_operands with the same indexes are forbidden, but
2050*38fd1498Szrj    after define_subst copy an RTL-expression from original template,
2051*38fd1498Szrj    indexes of existed and just-copied match_operands could coincide.
2052*38fd1498Szrj    To fix it, we replace one of them with match_dup.  */
2053*38fd1498Szrj static rtx
replace_duplicating_operands_in_pattern(rtx pattern)2054*38fd1498Szrj replace_duplicating_operands_in_pattern (rtx pattern)
2055*38fd1498Szrj {
2056*38fd1498Szrj   const char *fmt;
2057*38fd1498Szrj   int i, j, len, opno;
2058*38fd1498Szrj   rtx mdup;
2059*38fd1498Szrj 
2060*38fd1498Szrj   if (GET_CODE (pattern) == MATCH_OPERAND)
2061*38fd1498Szrj     {
2062*38fd1498Szrj       opno = XINT (pattern, 0);
2063*38fd1498Szrj       gcc_assert (opno >= 0 && opno < MAX_OPERANDS);
2064*38fd1498Szrj       if (match_operand_entries_in_pattern[opno] == NULL)
2065*38fd1498Szrj 	{
2066*38fd1498Szrj 	  match_operand_entries_in_pattern[opno] = pattern;
2067*38fd1498Szrj 	  return NULL;
2068*38fd1498Szrj 	}
2069*38fd1498Szrj       else
2070*38fd1498Szrj 	{
2071*38fd1498Szrj 	  /* Compare predicates before replacing with match_dup.  */
2072*38fd1498Szrj 	  if (strcmp (XSTR (pattern, 1),
2073*38fd1498Szrj 		      XSTR (match_operand_entries_in_pattern[opno], 1)))
2074*38fd1498Szrj 	    {
2075*38fd1498Szrj 	      error ("duplicated match_operands with different predicates were"
2076*38fd1498Szrj 		     " found.");
2077*38fd1498Szrj 	      return NULL;
2078*38fd1498Szrj 	    }
2079*38fd1498Szrj 	  return generate_match_dup (opno);
2080*38fd1498Szrj 	}
2081*38fd1498Szrj     }
2082*38fd1498Szrj   fmt = GET_RTX_FORMAT (GET_CODE (pattern));
2083*38fd1498Szrj   len = GET_RTX_LENGTH (GET_CODE (pattern));
2084*38fd1498Szrj   for (i = 0; i < len; i++)
2085*38fd1498Szrj     {
2086*38fd1498Szrj       switch (fmt[i])
2087*38fd1498Szrj 	{
2088*38fd1498Szrj 	case 'e': case 'u':
2089*38fd1498Szrj 	  mdup = replace_duplicating_operands_in_pattern (XEXP (pattern, i));
2090*38fd1498Szrj 	  if (mdup)
2091*38fd1498Szrj 	    XEXP (pattern, i) = mdup;
2092*38fd1498Szrj 	  break;
2093*38fd1498Szrj 	case 'E':
2094*38fd1498Szrj 	  for (j = XVECLEN (pattern, i) - 1; j >= 0; --j)
2095*38fd1498Szrj 	    {
2096*38fd1498Szrj 	      mdup =
2097*38fd1498Szrj 		replace_duplicating_operands_in_pattern (XVECEXP
2098*38fd1498Szrj 							 (pattern, i, j));
2099*38fd1498Szrj 	      if (mdup)
2100*38fd1498Szrj 		XVECEXP (pattern, i, j) = mdup;
2101*38fd1498Szrj 	    }
2102*38fd1498Szrj 	  break;
2103*38fd1498Szrj 	}
2104*38fd1498Szrj     }
2105*38fd1498Szrj   return NULL;
2106*38fd1498Szrj }
2107*38fd1498Szrj 
2108*38fd1498Szrj /* The routine modifies given input PATTERN of define_subst, replacing
2109*38fd1498Szrj    MATCH_DUP and MATCH_OP_DUP with operands from define_insn original
2110*38fd1498Szrj    pattern, whose operands are stored in OPERAND_DATA array.
2111*38fd1498Szrj    It also duplicates constraints in operands - constraints from
2112*38fd1498Szrj    define_insn operands are duplicated N_SUBST_ALT times, constraints
2113*38fd1498Szrj    from define_subst operands are duplicated N_ALT times.
2114*38fd1498Szrj    After the duplication, returned output rtl-pattern contains every
2115*38fd1498Szrj    combination of input constraints Vs constraints from define_subst
2116*38fd1498Szrj    output.  */
2117*38fd1498Szrj static rtx
subst_dup(rtx pattern,int n_alt,int n_subst_alt)2118*38fd1498Szrj subst_dup (rtx pattern, int n_alt, int n_subst_alt)
2119*38fd1498Szrj {
2120*38fd1498Szrj   const char *fmt;
2121*38fd1498Szrj   enum rtx_code code;
2122*38fd1498Szrj   int i, j, len, opno;
2123*38fd1498Szrj 
2124*38fd1498Szrj   code = GET_CODE (pattern);
2125*38fd1498Szrj   switch (code)
2126*38fd1498Szrj     {
2127*38fd1498Szrj     case MATCH_DUP:
2128*38fd1498Szrj     case MATCH_OP_DUP:
2129*38fd1498Szrj       opno = XINT (pattern, 0);
2130*38fd1498Szrj 
2131*38fd1498Szrj       gcc_assert (opno >= 0 && opno < MAX_OPERANDS);
2132*38fd1498Szrj 
2133*38fd1498Szrj       if (operand_data[opno])
2134*38fd1498Szrj 	{
2135*38fd1498Szrj 	  pattern = copy_rtx (operand_data[opno]);
2136*38fd1498Szrj 
2137*38fd1498Szrj 	  /* Duplicate constraints.  */
2138*38fd1498Szrj 	  pattern = alter_constraints (pattern, n_subst_alt,
2139*38fd1498Szrj 				       duplicate_alternatives);
2140*38fd1498Szrj 	}
2141*38fd1498Szrj       break;
2142*38fd1498Szrj 
2143*38fd1498Szrj     default:
2144*38fd1498Szrj       break;
2145*38fd1498Szrj     }
2146*38fd1498Szrj 
2147*38fd1498Szrj   fmt = GET_RTX_FORMAT (GET_CODE (pattern));
2148*38fd1498Szrj   len = GET_RTX_LENGTH (GET_CODE (pattern));
2149*38fd1498Szrj   for (i = 0; i < len; i++)
2150*38fd1498Szrj     {
2151*38fd1498Szrj       switch (fmt[i])
2152*38fd1498Szrj 	{
2153*38fd1498Szrj 	case 'e': case 'u':
2154*38fd1498Szrj 	  if (code != MATCH_DUP && code != MATCH_OP_DUP)
2155*38fd1498Szrj 	    XEXP (pattern, i) = subst_dup (XEXP (pattern, i),
2156*38fd1498Szrj 					   n_alt, n_subst_alt);
2157*38fd1498Szrj 	  break;
2158*38fd1498Szrj 	case 'V':
2159*38fd1498Szrj 	  if (XVEC (pattern, i) == NULL)
2160*38fd1498Szrj 	    break;
2161*38fd1498Szrj 	  /* FALLTHRU */
2162*38fd1498Szrj 	case 'E':
2163*38fd1498Szrj 	  if (code != MATCH_DUP && code != MATCH_OP_DUP)
2164*38fd1498Szrj 	    for (j = XVECLEN (pattern, i) - 1; j >= 0; --j)
2165*38fd1498Szrj 	      XVECEXP (pattern, i, j) = subst_dup (XVECEXP (pattern, i, j),
2166*38fd1498Szrj 						   n_alt, n_subst_alt);
2167*38fd1498Szrj 	  break;
2168*38fd1498Szrj 
2169*38fd1498Szrj 	case 'r': case 'p': case 'i': case 'w':
2170*38fd1498Szrj 	case '0': case 's': case 'S': case 'T':
2171*38fd1498Szrj 	  break;
2172*38fd1498Szrj 
2173*38fd1498Szrj 	default:
2174*38fd1498Szrj 	  gcc_unreachable ();
2175*38fd1498Szrj 	}
2176*38fd1498Szrj     }
2177*38fd1498Szrj   return pattern;
2178*38fd1498Szrj }
2179*38fd1498Szrj 
2180*38fd1498Szrj /* If we have any DEFINE_COND_EXEC patterns, expand the DEFINE_INSN
2181*38fd1498Szrj    patterns appropriately.  */
2182*38fd1498Szrj 
2183*38fd1498Szrj static void
process_define_cond_exec(void)2184*38fd1498Szrj process_define_cond_exec (void)
2185*38fd1498Szrj {
2186*38fd1498Szrj   struct queue_elem *elem;
2187*38fd1498Szrj 
2188*38fd1498Szrj   identify_predicable_attribute ();
2189*38fd1498Szrj   if (have_error)
2190*38fd1498Szrj     return;
2191*38fd1498Szrj 
2192*38fd1498Szrj   for (elem = define_cond_exec_queue; elem ; elem = elem->next)
2193*38fd1498Szrj     process_one_cond_exec (elem);
2194*38fd1498Szrj }
2195*38fd1498Szrj 
2196*38fd1498Szrj /* If we have any DEFINE_SUBST patterns, expand DEFINE_INSN and
2197*38fd1498Szrj    DEFINE_EXPAND patterns appropriately.  */
2198*38fd1498Szrj 
2199*38fd1498Szrj static void
process_define_subst(void)2200*38fd1498Szrj process_define_subst (void)
2201*38fd1498Szrj {
2202*38fd1498Szrj   struct queue_elem *elem, *elem_attr;
2203*38fd1498Szrj 
2204*38fd1498Szrj   /* Check if each define_subst has corresponding define_subst_attr.  */
2205*38fd1498Szrj   for (elem = define_subst_queue; elem ; elem = elem->next)
2206*38fd1498Szrj     {
2207*38fd1498Szrj       for (elem_attr = define_subst_attr_queue;
2208*38fd1498Szrj 	   elem_attr;
2209*38fd1498Szrj 	   elem_attr = elem_attr->next)
2210*38fd1498Szrj 	if (strcmp (XSTR (elem->data, 0), XSTR (elem_attr->data, 1)) == 0)
2211*38fd1498Szrj 	    goto found;
2212*38fd1498Szrj 
2213*38fd1498Szrj       error_at (elem->loc,
2214*38fd1498Szrj 		"%s: `define_subst' must have at least one "
2215*38fd1498Szrj 		"corresponding `define_subst_attr'",
2216*38fd1498Szrj 		XSTR (elem->data, 0));
2217*38fd1498Szrj       return;
2218*38fd1498Szrj 
2219*38fd1498Szrj       found:
2220*38fd1498Szrj 	continue;
2221*38fd1498Szrj     }
2222*38fd1498Szrj 
2223*38fd1498Szrj   for (elem = define_insn_queue; elem ; elem = elem->next)
2224*38fd1498Szrj     process_substs_on_one_elem (elem, define_insn_queue);
2225*38fd1498Szrj   for (elem = other_queue; elem ; elem = elem->next)
2226*38fd1498Szrj     {
2227*38fd1498Szrj       if (GET_CODE (elem->data) != DEFINE_EXPAND)
2228*38fd1498Szrj 	continue;
2229*38fd1498Szrj       process_substs_on_one_elem (elem, other_queue);
2230*38fd1498Szrj     }
2231*38fd1498Szrj }
2232*38fd1498Szrj 
2233*38fd1498Szrj /* A subclass of rtx_reader which reads .md files and calls process_rtx on
2234*38fd1498Szrj    the top-level elements.  */
2235*38fd1498Szrj 
2236*38fd1498Szrj class gen_reader : public rtx_reader
2237*38fd1498Szrj {
2238*38fd1498Szrj  public:
gen_reader()2239*38fd1498Szrj   gen_reader () : rtx_reader (false) {}
2240*38fd1498Szrj   void handle_unknown_directive (file_location, const char *);
2241*38fd1498Szrj };
2242*38fd1498Szrj 
2243*38fd1498Szrj void
handle_unknown_directive(file_location loc,const char * rtx_name)2244*38fd1498Szrj gen_reader::handle_unknown_directive (file_location loc, const char *rtx_name)
2245*38fd1498Szrj {
2246*38fd1498Szrj   auto_vec<rtx, 32> subrtxs;
2247*38fd1498Szrj   if (!read_rtx (rtx_name, &subrtxs))
2248*38fd1498Szrj     return;
2249*38fd1498Szrj 
2250*38fd1498Szrj   rtx x;
2251*38fd1498Szrj   unsigned int i;
2252*38fd1498Szrj   FOR_EACH_VEC_ELT (subrtxs, i, x)
2253*38fd1498Szrj     process_rtx (x, loc);
2254*38fd1498Szrj }
2255*38fd1498Szrj 
2256*38fd1498Szrj /* Comparison function for the mnemonic hash table.  */
2257*38fd1498Szrj 
2258*38fd1498Szrj static int
htab_eq_string(const void * s1,const void * s2)2259*38fd1498Szrj htab_eq_string (const void *s1, const void *s2)
2260*38fd1498Szrj {
2261*38fd1498Szrj   return strcmp ((const char*)s1, (const char*)s2) == 0;
2262*38fd1498Szrj }
2263*38fd1498Szrj 
2264*38fd1498Szrj /* Add mnemonic STR with length LEN to the mnemonic hash table
2265*38fd1498Szrj    MNEMONIC_HTAB.  A trailing zero end character is appended to STR
2266*38fd1498Szrj    and a permanent heap copy of STR is created.  */
2267*38fd1498Szrj 
2268*38fd1498Szrj static void
add_mnemonic_string(htab_t mnemonic_htab,const char * str,size_t len)2269*38fd1498Szrj add_mnemonic_string (htab_t mnemonic_htab, const char *str, size_t len)
2270*38fd1498Szrj {
2271*38fd1498Szrj   char *new_str;
2272*38fd1498Szrj   void **slot;
2273*38fd1498Szrj   char *str_zero = (char*)alloca (len + 1);
2274*38fd1498Szrj 
2275*38fd1498Szrj   memcpy (str_zero, str, len);
2276*38fd1498Szrj   str_zero[len] = '\0';
2277*38fd1498Szrj 
2278*38fd1498Szrj   slot = htab_find_slot (mnemonic_htab, str_zero, INSERT);
2279*38fd1498Szrj 
2280*38fd1498Szrj   if (*slot)
2281*38fd1498Szrj     return;
2282*38fd1498Szrj 
2283*38fd1498Szrj   /* Not found; create a permanent copy and add it to the hash table.  */
2284*38fd1498Szrj   new_str = XNEWVAR (char, len + 1);
2285*38fd1498Szrj   memcpy (new_str, str_zero, len + 1);
2286*38fd1498Szrj   *slot = new_str;
2287*38fd1498Szrj }
2288*38fd1498Szrj 
2289*38fd1498Szrj /* Scan INSN for mnemonic strings and add them to the mnemonic hash
2290*38fd1498Szrj    table in MNEMONIC_HTAB.
2291*38fd1498Szrj 
2292*38fd1498Szrj    The mnemonics cannot be found if they are emitted using C code.
2293*38fd1498Szrj 
2294*38fd1498Szrj    If a mnemonic string contains ';' or a newline the string assumed
2295*38fd1498Szrj    to consist of more than a single instruction.  The attribute value
2296*38fd1498Szrj    will then be set to the user defined default value.  */
2297*38fd1498Szrj 
2298*38fd1498Szrj static void
gen_mnemonic_setattr(htab_t mnemonic_htab,rtx insn)2299*38fd1498Szrj gen_mnemonic_setattr (htab_t mnemonic_htab, rtx insn)
2300*38fd1498Szrj {
2301*38fd1498Szrj   const char *template_code, *cp;
2302*38fd1498Szrj   int i;
2303*38fd1498Szrj   int vec_len;
2304*38fd1498Szrj   rtx set_attr;
2305*38fd1498Szrj   char *attr_name;
2306*38fd1498Szrj   rtvec new_vec;
2307*38fd1498Szrj   struct obstack *string_obstack = rtx_reader_ptr->get_string_obstack ();
2308*38fd1498Szrj 
2309*38fd1498Szrj   template_code = XTMPL (insn, 3);
2310*38fd1498Szrj 
2311*38fd1498Szrj   /* Skip patterns which use C code to emit the template.  */
2312*38fd1498Szrj   if (template_code[0] == '*')
2313*38fd1498Szrj     return;
2314*38fd1498Szrj 
2315*38fd1498Szrj   if (template_code[0] == '@')
2316*38fd1498Szrj     cp = &template_code[1];
2317*38fd1498Szrj   else
2318*38fd1498Szrj     cp = &template_code[0];
2319*38fd1498Szrj 
2320*38fd1498Szrj   for (i = 0; *cp; )
2321*38fd1498Szrj     {
2322*38fd1498Szrj       const char *ep, *sp;
2323*38fd1498Szrj       size_t size = 0;
2324*38fd1498Szrj 
2325*38fd1498Szrj       while (ISSPACE (*cp))
2326*38fd1498Szrj 	cp++;
2327*38fd1498Szrj 
2328*38fd1498Szrj       for (ep = sp = cp; !IS_VSPACE (*ep) && *ep != '\0'; ++ep)
2329*38fd1498Szrj 	if (!ISSPACE (*ep))
2330*38fd1498Szrj 	  sp = ep + 1;
2331*38fd1498Szrj 
2332*38fd1498Szrj       if (i > 0)
2333*38fd1498Szrj 	obstack_1grow (string_obstack, ',');
2334*38fd1498Szrj 
2335*38fd1498Szrj       while (cp < sp && ((*cp >= '0' && *cp <= '9')
2336*38fd1498Szrj 			 || (*cp >= 'a' && *cp <= 'z')))
2337*38fd1498Szrj 
2338*38fd1498Szrj 	{
2339*38fd1498Szrj 	  obstack_1grow (string_obstack, *cp);
2340*38fd1498Szrj 	  cp++;
2341*38fd1498Szrj 	  size++;
2342*38fd1498Szrj 	}
2343*38fd1498Szrj 
2344*38fd1498Szrj       while (cp < sp)
2345*38fd1498Szrj 	{
2346*38fd1498Szrj 	  if (*cp == ';' || (*cp == '\\' && cp[1] == 'n'))
2347*38fd1498Szrj 	    {
2348*38fd1498Szrj 	      /* Don't set a value if there are more than one
2349*38fd1498Szrj 		 instruction in the string.  */
2350*38fd1498Szrj 	      obstack_blank_fast (string_obstack, -size);
2351*38fd1498Szrj 	      size = 0;
2352*38fd1498Szrj 
2353*38fd1498Szrj 	      cp = sp;
2354*38fd1498Szrj 	      break;
2355*38fd1498Szrj 	    }
2356*38fd1498Szrj 	  cp++;
2357*38fd1498Szrj 	}
2358*38fd1498Szrj       if (size == 0)
2359*38fd1498Szrj 	obstack_1grow (string_obstack, '*');
2360*38fd1498Szrj       else
2361*38fd1498Szrj 	add_mnemonic_string (mnemonic_htab,
2362*38fd1498Szrj 			     (char *) obstack_next_free (string_obstack) - size,
2363*38fd1498Szrj 			     size);
2364*38fd1498Szrj       i++;
2365*38fd1498Szrj     }
2366*38fd1498Szrj 
2367*38fd1498Szrj   /* An insn definition might emit an empty string.  */
2368*38fd1498Szrj   if (obstack_object_size (string_obstack) == 0)
2369*38fd1498Szrj     return;
2370*38fd1498Szrj 
2371*38fd1498Szrj   obstack_1grow (string_obstack, '\0');
2372*38fd1498Szrj 
2373*38fd1498Szrj   set_attr = rtx_alloc (SET_ATTR);
2374*38fd1498Szrj   XSTR (set_attr, 1) = XOBFINISH (string_obstack, char *);
2375*38fd1498Szrj   attr_name = XNEWVAR (char, strlen (MNEMONIC_ATTR_NAME) + 1);
2376*38fd1498Szrj   strcpy (attr_name, MNEMONIC_ATTR_NAME);
2377*38fd1498Szrj   XSTR (set_attr, 0) = attr_name;
2378*38fd1498Szrj 
2379*38fd1498Szrj   if (!XVEC (insn, 4))
2380*38fd1498Szrj     vec_len = 0;
2381*38fd1498Szrj   else
2382*38fd1498Szrj     vec_len = XVECLEN (insn, 4);
2383*38fd1498Szrj 
2384*38fd1498Szrj   new_vec = rtvec_alloc (vec_len + 1);
2385*38fd1498Szrj   for (i = 0; i < vec_len; i++)
2386*38fd1498Szrj     RTVEC_ELT (new_vec, i) = XVECEXP (insn, 4, i);
2387*38fd1498Szrj   RTVEC_ELT (new_vec, vec_len) = set_attr;
2388*38fd1498Szrj   XVEC (insn, 4) = new_vec;
2389*38fd1498Szrj }
2390*38fd1498Szrj 
2391*38fd1498Szrj /* This function is called for the elements in the mnemonic hashtable
2392*38fd1498Szrj    and generates a comma separated list of the mnemonics.  */
2393*38fd1498Szrj 
2394*38fd1498Szrj static int
mnemonic_htab_callback(void ** slot,void * info ATTRIBUTE_UNUSED)2395*38fd1498Szrj mnemonic_htab_callback (void **slot, void *info ATTRIBUTE_UNUSED)
2396*38fd1498Szrj {
2397*38fd1498Szrj   struct obstack *string_obstack = rtx_reader_ptr->get_string_obstack ();
2398*38fd1498Szrj 
2399*38fd1498Szrj   obstack_grow (string_obstack, (char*) *slot, strlen ((char*) *slot));
2400*38fd1498Szrj   obstack_1grow (string_obstack, ',');
2401*38fd1498Szrj   return 1;
2402*38fd1498Szrj }
2403*38fd1498Szrj 
2404*38fd1498Szrj /* Generate (set_attr "mnemonic" "..") RTXs and append them to every
2405*38fd1498Szrj    insn definition in case the back end requests it by defining the
2406*38fd1498Szrj    mnemonic attribute.  The values for the attribute will be extracted
2407*38fd1498Szrj    from the output patterns of the insn definitions as far as
2408*38fd1498Szrj    possible.  */
2409*38fd1498Szrj 
2410*38fd1498Szrj static void
gen_mnemonic_attr(void)2411*38fd1498Szrj gen_mnemonic_attr (void)
2412*38fd1498Szrj {
2413*38fd1498Szrj   struct queue_elem *elem;
2414*38fd1498Szrj   rtx mnemonic_attr = NULL;
2415*38fd1498Szrj   htab_t mnemonic_htab;
2416*38fd1498Szrj   const char *str, *p;
2417*38fd1498Szrj   int i;
2418*38fd1498Szrj   struct obstack *string_obstack = rtx_reader_ptr->get_string_obstack ();
2419*38fd1498Szrj 
2420*38fd1498Szrj   if (have_error)
2421*38fd1498Szrj     return;
2422*38fd1498Szrj 
2423*38fd1498Szrj   /* Look for the DEFINE_ATTR for `mnemonic'.  */
2424*38fd1498Szrj   for (elem = define_attr_queue; elem != *define_attr_tail; elem = elem->next)
2425*38fd1498Szrj     if (GET_CODE (elem->data) == DEFINE_ATTR
2426*38fd1498Szrj 	&& strcmp (XSTR (elem->data, 0), MNEMONIC_ATTR_NAME) == 0)
2427*38fd1498Szrj       {
2428*38fd1498Szrj 	mnemonic_attr = elem->data;
2429*38fd1498Szrj 	break;
2430*38fd1498Szrj       }
2431*38fd1498Szrj 
2432*38fd1498Szrj   /* A (define_attr "mnemonic" "...") indicates that the back-end
2433*38fd1498Szrj      wants a mnemonic attribute to be generated.  */
2434*38fd1498Szrj   if (!mnemonic_attr)
2435*38fd1498Szrj     return;
2436*38fd1498Szrj 
2437*38fd1498Szrj   mnemonic_htab = htab_create_alloc (MNEMONIC_HTAB_SIZE, htab_hash_string,
2438*38fd1498Szrj 				     htab_eq_string, 0, xcalloc, free);
2439*38fd1498Szrj 
2440*38fd1498Szrj   for (elem = define_insn_queue; elem; elem = elem->next)
2441*38fd1498Szrj     {
2442*38fd1498Szrj       rtx insn = elem->data;
2443*38fd1498Szrj       bool found = false;
2444*38fd1498Szrj 
2445*38fd1498Szrj       /* Check if the insn definition already has
2446*38fd1498Szrj 	 (set_attr "mnemonic" ...) or (set (attr "mnemonic") ...).  */
2447*38fd1498Szrj       if (XVEC (insn, 4))
2448*38fd1498Szrj  	for (i = 0; i < XVECLEN (insn, 4); i++)
2449*38fd1498Szrj 	  {
2450*38fd1498Szrj 	    rtx set_attr = XVECEXP (insn, 4, i);
2451*38fd1498Szrj 
2452*38fd1498Szrj 	    switch (GET_CODE (set_attr))
2453*38fd1498Szrj 	      {
2454*38fd1498Szrj 	      case SET_ATTR:
2455*38fd1498Szrj 	      case SET_ATTR_ALTERNATIVE:
2456*38fd1498Szrj 		if (strcmp (XSTR (set_attr, 0), MNEMONIC_ATTR_NAME) == 0)
2457*38fd1498Szrj 		  found = true;
2458*38fd1498Szrj 		break;
2459*38fd1498Szrj 	      case SET:
2460*38fd1498Szrj 		if (GET_CODE (SET_DEST (set_attr)) == ATTR
2461*38fd1498Szrj 		    && strcmp (XSTR (SET_DEST (set_attr), 0),
2462*38fd1498Szrj 			       MNEMONIC_ATTR_NAME) == 0)
2463*38fd1498Szrj 		  found = true;
2464*38fd1498Szrj 		break;
2465*38fd1498Szrj 	      default:
2466*38fd1498Szrj 		break;
2467*38fd1498Szrj 	      }
2468*38fd1498Szrj 	  }
2469*38fd1498Szrj 
2470*38fd1498Szrj       if (!found)
2471*38fd1498Szrj 	gen_mnemonic_setattr (mnemonic_htab, insn);
2472*38fd1498Szrj     }
2473*38fd1498Szrj 
2474*38fd1498Szrj   /* Add the user defined values to the hash table.  */
2475*38fd1498Szrj   str = XSTR (mnemonic_attr, 1);
2476*38fd1498Szrj   while ((p = scan_comma_elt (&str)) != NULL)
2477*38fd1498Szrj     add_mnemonic_string (mnemonic_htab, p, str - p);
2478*38fd1498Szrj 
2479*38fd1498Szrj   htab_traverse (mnemonic_htab, mnemonic_htab_callback, NULL);
2480*38fd1498Szrj 
2481*38fd1498Szrj   /* Replace the last ',' with the zero end character.  */
2482*38fd1498Szrj   *((char *) obstack_next_free (string_obstack) - 1) = '\0';
2483*38fd1498Szrj   XSTR (mnemonic_attr, 1) = XOBFINISH (string_obstack, char *);
2484*38fd1498Szrj }
2485*38fd1498Szrj 
2486*38fd1498Szrj /* Check if there are DEFINE_ATTRs with the same name.  */
2487*38fd1498Szrj static void
check_define_attr_duplicates()2488*38fd1498Szrj check_define_attr_duplicates ()
2489*38fd1498Szrj {
2490*38fd1498Szrj   struct queue_elem *elem;
2491*38fd1498Szrj   htab_t attr_htab;
2492*38fd1498Szrj   char * attr_name;
2493*38fd1498Szrj   void **slot;
2494*38fd1498Szrj 
2495*38fd1498Szrj   attr_htab = htab_create (500, htab_hash_string, htab_eq_string, NULL);
2496*38fd1498Szrj 
2497*38fd1498Szrj   for (elem = define_attr_queue; elem; elem = elem->next)
2498*38fd1498Szrj     {
2499*38fd1498Szrj       attr_name = xstrdup (XSTR (elem->data, 0));
2500*38fd1498Szrj 
2501*38fd1498Szrj       slot = htab_find_slot (attr_htab, attr_name, INSERT);
2502*38fd1498Szrj 
2503*38fd1498Szrj       /* Duplicate.  */
2504*38fd1498Szrj       if (*slot)
2505*38fd1498Szrj 	{
2506*38fd1498Szrj 	  error_at (elem->loc, "redefinition of attribute '%s'", attr_name);
2507*38fd1498Szrj 	  htab_delete (attr_htab);
2508*38fd1498Szrj 	  return;
2509*38fd1498Szrj 	}
2510*38fd1498Szrj 
2511*38fd1498Szrj       *slot = attr_name;
2512*38fd1498Szrj     }
2513*38fd1498Szrj 
2514*38fd1498Szrj   htab_delete (attr_htab);
2515*38fd1498Szrj }
2516*38fd1498Szrj 
2517*38fd1498Szrj /* The entry point for initializing the reader.  */
2518*38fd1498Szrj 
2519*38fd1498Szrj rtx_reader *
init_rtx_reader_args_cb(int argc,const char ** argv,bool (* parse_opt)(const char *))2520*38fd1498Szrj init_rtx_reader_args_cb (int argc, const char **argv,
2521*38fd1498Szrj 			 bool (*parse_opt) (const char *))
2522*38fd1498Szrj {
2523*38fd1498Szrj   /* Prepare to read input.  */
2524*38fd1498Szrj   condition_table = htab_create (500, hash_c_test, cmp_c_test, NULL);
2525*38fd1498Szrj   init_predicate_table ();
2526*38fd1498Szrj   obstack_init (rtl_obstack);
2527*38fd1498Szrj 
2528*38fd1498Szrj   /* Start at 1, to make 0 available for CODE_FOR_nothing.  */
2529*38fd1498Szrj   insn_sequence_num = 1;
2530*38fd1498Szrj 
2531*38fd1498Szrj   /* These sequences are not used as indices, so can start at 1 also.  */
2532*38fd1498Szrj   split_sequence_num = 1;
2533*38fd1498Szrj   peephole2_sequence_num = 1;
2534*38fd1498Szrj 
2535*38fd1498Szrj   gen_reader *reader = new gen_reader ();
2536*38fd1498Szrj   reader->read_md_files (argc, argv, parse_opt);
2537*38fd1498Szrj 
2538*38fd1498Szrj   if (define_attr_queue != NULL)
2539*38fd1498Szrj     check_define_attr_duplicates ();
2540*38fd1498Szrj 
2541*38fd1498Szrj   /* Process define_cond_exec patterns.  */
2542*38fd1498Szrj   if (define_cond_exec_queue != NULL)
2543*38fd1498Szrj     process_define_cond_exec ();
2544*38fd1498Szrj 
2545*38fd1498Szrj   /* Process define_subst patterns.  */
2546*38fd1498Szrj   if (define_subst_queue != NULL)
2547*38fd1498Szrj     process_define_subst ();
2548*38fd1498Szrj 
2549*38fd1498Szrj   if (define_attr_queue != NULL)
2550*38fd1498Szrj     gen_mnemonic_attr ();
2551*38fd1498Szrj 
2552*38fd1498Szrj   if (have_error)
2553*38fd1498Szrj     {
2554*38fd1498Szrj       delete reader;
2555*38fd1498Szrj       return NULL;
2556*38fd1498Szrj     }
2557*38fd1498Szrj 
2558*38fd1498Szrj   return reader;
2559*38fd1498Szrj }
2560*38fd1498Szrj 
2561*38fd1498Szrj /* Programs that don't have their own options can use this entry point
2562*38fd1498Szrj    instead.  */
2563*38fd1498Szrj rtx_reader *
init_rtx_reader_args(int argc,const char ** argv)2564*38fd1498Szrj init_rtx_reader_args (int argc, const char **argv)
2565*38fd1498Szrj {
2566*38fd1498Szrj   return init_rtx_reader_args_cb (argc, argv, 0);
2567*38fd1498Szrj }
2568*38fd1498Szrj 
2569*38fd1498Szrj /* Try to read a single rtx from the file.  Return true on success,
2570*38fd1498Szrj    describing it in *INFO.  */
2571*38fd1498Szrj 
2572*38fd1498Szrj bool
read_md_rtx(md_rtx_info * info)2573*38fd1498Szrj read_md_rtx (md_rtx_info *info)
2574*38fd1498Szrj {
2575*38fd1498Szrj   int truth, *counter;
2576*38fd1498Szrj   rtx def;
2577*38fd1498Szrj 
2578*38fd1498Szrj   /* Discard insn patterns which we know can never match (because
2579*38fd1498Szrj      their C test is provably always false).  If insn_elision is
2580*38fd1498Szrj      false, our caller needs to see all the patterns.  Note that the
2581*38fd1498Szrj      elided patterns are never counted by the sequence numbering; it
2582*38fd1498Szrj      is the caller's responsibility, when insn_elision is false, not
2583*38fd1498Szrj      to use elided pattern numbers for anything.  */
2584*38fd1498Szrj   do
2585*38fd1498Szrj     {
2586*38fd1498Szrj       struct queue_elem **queue, *elem;
2587*38fd1498Szrj 
2588*38fd1498Szrj       /* Read all patterns from a given queue before moving on to the next.  */
2589*38fd1498Szrj       if (define_attr_queue != NULL)
2590*38fd1498Szrj 	queue = &define_attr_queue;
2591*38fd1498Szrj       else if (define_pred_queue != NULL)
2592*38fd1498Szrj 	queue = &define_pred_queue;
2593*38fd1498Szrj       else if (define_insn_queue != NULL)
2594*38fd1498Szrj 	queue = &define_insn_queue;
2595*38fd1498Szrj       else if (other_queue != NULL)
2596*38fd1498Szrj 	queue = &other_queue;
2597*38fd1498Szrj       else
2598*38fd1498Szrj 	return false;
2599*38fd1498Szrj 
2600*38fd1498Szrj       elem = *queue;
2601*38fd1498Szrj       *queue = elem->next;
2602*38fd1498Szrj       def = elem->data;
2603*38fd1498Szrj       info->def = def;
2604*38fd1498Szrj       info->loc = elem->loc;
2605*38fd1498Szrj       free (elem);
2606*38fd1498Szrj 
2607*38fd1498Szrj       truth = maybe_eval_c_test (get_c_test (def));
2608*38fd1498Szrj     }
2609*38fd1498Szrj   while (truth == 0 && insn_elision);
2610*38fd1498Szrj 
2611*38fd1498Szrj   /* Perform code-specific processing and pick the appropriate sequence
2612*38fd1498Szrj      number counter.  */
2613*38fd1498Szrj   switch (GET_CODE (def))
2614*38fd1498Szrj     {
2615*38fd1498Szrj     case DEFINE_INSN:
2616*38fd1498Szrj     case DEFINE_EXPAND:
2617*38fd1498Szrj       /* insn_sequence_num is used here so the name table will match caller's
2618*38fd1498Szrj 	 idea of insn numbering, whether or not elision is active.  */
2619*38fd1498Szrj       record_insn_name (insn_sequence_num, XSTR (def, 0));
2620*38fd1498Szrj 
2621*38fd1498Szrj       /* Fall through.  */
2622*38fd1498Szrj     case DEFINE_PEEPHOLE:
2623*38fd1498Szrj       counter = &insn_sequence_num;
2624*38fd1498Szrj       break;
2625*38fd1498Szrj 
2626*38fd1498Szrj     case DEFINE_SPLIT:
2627*38fd1498Szrj       counter = &split_sequence_num;
2628*38fd1498Szrj       break;
2629*38fd1498Szrj 
2630*38fd1498Szrj     case DEFINE_PEEPHOLE2:
2631*38fd1498Szrj       counter = &peephole2_sequence_num;
2632*38fd1498Szrj       break;
2633*38fd1498Szrj 
2634*38fd1498Szrj     default:
2635*38fd1498Szrj       counter = NULL;
2636*38fd1498Szrj       break;
2637*38fd1498Szrj     }
2638*38fd1498Szrj 
2639*38fd1498Szrj   if (counter)
2640*38fd1498Szrj     {
2641*38fd1498Szrj       info->index = *counter;
2642*38fd1498Szrj       if (truth != 0)
2643*38fd1498Szrj 	*counter += 1;
2644*38fd1498Szrj     }
2645*38fd1498Szrj   else
2646*38fd1498Szrj     info->index = -1;
2647*38fd1498Szrj 
2648*38fd1498Szrj   if (!rtx_locs)
2649*38fd1498Szrj     rtx_locs = new hash_map <rtx, file_location>;
2650*38fd1498Szrj   rtx_locs->put (info->def, info->loc);
2651*38fd1498Szrj 
2652*38fd1498Szrj   return true;
2653*38fd1498Szrj }
2654*38fd1498Szrj 
2655*38fd1498Szrj /* Return the file location of DEFINE_* rtx X, which was previously
2656*38fd1498Szrj    returned by read_md_rtx.  */
2657*38fd1498Szrj file_location
get_file_location(rtx x)2658*38fd1498Szrj get_file_location (rtx x)
2659*38fd1498Szrj {
2660*38fd1498Szrj   gcc_assert (rtx_locs);
2661*38fd1498Szrj   file_location *entry = rtx_locs->get (x);
2662*38fd1498Szrj   gcc_assert (entry);
2663*38fd1498Szrj   return *entry;
2664*38fd1498Szrj }
2665*38fd1498Szrj 
2666*38fd1498Szrj /* Return the number of possible INSN_CODEs.  Only meaningful once the
2667*38fd1498Szrj    whole file has been processed.  */
2668*38fd1498Szrj unsigned int
get_num_insn_codes()2669*38fd1498Szrj get_num_insn_codes ()
2670*38fd1498Szrj {
2671*38fd1498Szrj   return insn_sequence_num;
2672*38fd1498Szrj }
2673*38fd1498Szrj 
2674*38fd1498Szrj /* Return the C test that says whether definition rtx DEF can be used,
2675*38fd1498Szrj    or "" if it can be used unconditionally.  */
2676*38fd1498Szrj 
2677*38fd1498Szrj const char *
get_c_test(rtx x)2678*38fd1498Szrj get_c_test (rtx x)
2679*38fd1498Szrj {
2680*38fd1498Szrj   switch (GET_CODE (x))
2681*38fd1498Szrj     {
2682*38fd1498Szrj     case DEFINE_INSN:
2683*38fd1498Szrj     case DEFINE_EXPAND:
2684*38fd1498Szrj     case DEFINE_SUBST:
2685*38fd1498Szrj       return XSTR (x, 2);
2686*38fd1498Szrj 
2687*38fd1498Szrj     case DEFINE_SPLIT:
2688*38fd1498Szrj     case DEFINE_PEEPHOLE:
2689*38fd1498Szrj     case DEFINE_PEEPHOLE2:
2690*38fd1498Szrj       return XSTR (x, 1);
2691*38fd1498Szrj 
2692*38fd1498Szrj     default:
2693*38fd1498Szrj       return "";
2694*38fd1498Szrj     }
2695*38fd1498Szrj }
2696*38fd1498Szrj 
2697*38fd1498Szrj /* Helper functions for insn elision.  */
2698*38fd1498Szrj 
2699*38fd1498Szrj /* Compute a hash function of a c_test structure, which is keyed
2700*38fd1498Szrj    by its ->expr field.  */
2701*38fd1498Szrj hashval_t
hash_c_test(const void * x)2702*38fd1498Szrj hash_c_test (const void *x)
2703*38fd1498Szrj {
2704*38fd1498Szrj   const struct c_test *a = (const struct c_test *) x;
2705*38fd1498Szrj   const unsigned char *base, *s = (const unsigned char *) a->expr;
2706*38fd1498Szrj   hashval_t hash;
2707*38fd1498Szrj   unsigned char c;
2708*38fd1498Szrj   unsigned int len;
2709*38fd1498Szrj 
2710*38fd1498Szrj   base = s;
2711*38fd1498Szrj   hash = 0;
2712*38fd1498Szrj 
2713*38fd1498Szrj   while ((c = *s++) != '\0')
2714*38fd1498Szrj     {
2715*38fd1498Szrj       hash += c + (c << 17);
2716*38fd1498Szrj       hash ^= hash >> 2;
2717*38fd1498Szrj     }
2718*38fd1498Szrj 
2719*38fd1498Szrj   len = s - base;
2720*38fd1498Szrj   hash += len + (len << 17);
2721*38fd1498Szrj   hash ^= hash >> 2;
2722*38fd1498Szrj 
2723*38fd1498Szrj   return hash;
2724*38fd1498Szrj }
2725*38fd1498Szrj 
2726*38fd1498Szrj /* Compare two c_test expression structures.  */
2727*38fd1498Szrj int
cmp_c_test(const void * x,const void * y)2728*38fd1498Szrj cmp_c_test (const void *x, const void *y)
2729*38fd1498Szrj {
2730*38fd1498Szrj   const struct c_test *a = (const struct c_test *) x;
2731*38fd1498Szrj   const struct c_test *b = (const struct c_test *) y;
2732*38fd1498Szrj 
2733*38fd1498Szrj   return !strcmp (a->expr, b->expr);
2734*38fd1498Szrj }
2735*38fd1498Szrj 
2736*38fd1498Szrj /* Given a string representing a C test expression, look it up in the
2737*38fd1498Szrj    condition_table and report whether or not its value is known
2738*38fd1498Szrj    at compile time.  Returns a tristate: 1 for known true, 0 for
2739*38fd1498Szrj    known false, -1 for unknown.  */
2740*38fd1498Szrj int
maybe_eval_c_test(const char * expr)2741*38fd1498Szrj maybe_eval_c_test (const char *expr)
2742*38fd1498Szrj {
2743*38fd1498Szrj   const struct c_test *test;
2744*38fd1498Szrj   struct c_test dummy;
2745*38fd1498Szrj 
2746*38fd1498Szrj   if (expr[0] == 0)
2747*38fd1498Szrj     return 1;
2748*38fd1498Szrj 
2749*38fd1498Szrj   dummy.expr = expr;
2750*38fd1498Szrj   test = (const struct c_test *)htab_find (condition_table, &dummy);
2751*38fd1498Szrj   if (!test)
2752*38fd1498Szrj     return -1;
2753*38fd1498Szrj   return test->value;
2754*38fd1498Szrj }
2755*38fd1498Szrj 
2756*38fd1498Szrj /* Record the C test expression EXPR in the condition_table, with
2757*38fd1498Szrj    value VAL.  Duplicates clobber previous entries.  */
2758*38fd1498Szrj 
2759*38fd1498Szrj void
add_c_test(const char * expr,int value)2760*38fd1498Szrj add_c_test (const char *expr, int value)
2761*38fd1498Szrj {
2762*38fd1498Szrj   struct c_test *test;
2763*38fd1498Szrj 
2764*38fd1498Szrj   if (expr[0] == 0)
2765*38fd1498Szrj     return;
2766*38fd1498Szrj 
2767*38fd1498Szrj   test = XNEW (struct c_test);
2768*38fd1498Szrj   test->expr = expr;
2769*38fd1498Szrj   test->value = value;
2770*38fd1498Szrj 
2771*38fd1498Szrj   *(htab_find_slot (condition_table, test, INSERT)) = test;
2772*38fd1498Szrj }
2773*38fd1498Szrj 
2774*38fd1498Szrj /* For every C test, call CALLBACK with two arguments: a pointer to
2775*38fd1498Szrj    the condition structure and INFO.  Stops when CALLBACK returns zero.  */
2776*38fd1498Szrj void
traverse_c_tests(htab_trav callback,void * info)2777*38fd1498Szrj traverse_c_tests (htab_trav callback, void *info)
2778*38fd1498Szrj {
2779*38fd1498Szrj   if (condition_table)
2780*38fd1498Szrj     htab_traverse (condition_table, callback, info);
2781*38fd1498Szrj }
2782*38fd1498Szrj 
2783*38fd1498Szrj /* Helper functions for define_predicate and define_special_predicate
2784*38fd1498Szrj    processing.  Shared between genrecog.c and genpreds.c.  */
2785*38fd1498Szrj 
2786*38fd1498Szrj static htab_t predicate_table;
2787*38fd1498Szrj struct pred_data *first_predicate;
2788*38fd1498Szrj static struct pred_data **last_predicate = &first_predicate;
2789*38fd1498Szrj 
2790*38fd1498Szrj static hashval_t
hash_struct_pred_data(const void * ptr)2791*38fd1498Szrj hash_struct_pred_data (const void *ptr)
2792*38fd1498Szrj {
2793*38fd1498Szrj   return htab_hash_string (((const struct pred_data *)ptr)->name);
2794*38fd1498Szrj }
2795*38fd1498Szrj 
2796*38fd1498Szrj static int
eq_struct_pred_data(const void * a,const void * b)2797*38fd1498Szrj eq_struct_pred_data (const void *a, const void *b)
2798*38fd1498Szrj {
2799*38fd1498Szrj   return !strcmp (((const struct pred_data *)a)->name,
2800*38fd1498Szrj 		  ((const struct pred_data *)b)->name);
2801*38fd1498Szrj }
2802*38fd1498Szrj 
2803*38fd1498Szrj struct pred_data *
lookup_predicate(const char * name)2804*38fd1498Szrj lookup_predicate (const char *name)
2805*38fd1498Szrj {
2806*38fd1498Szrj   struct pred_data key;
2807*38fd1498Szrj   key.name = name;
2808*38fd1498Szrj   return (struct pred_data *) htab_find (predicate_table, &key);
2809*38fd1498Szrj }
2810*38fd1498Szrj 
2811*38fd1498Szrj /* Record that predicate PRED can accept CODE.  */
2812*38fd1498Szrj 
2813*38fd1498Szrj void
add_predicate_code(struct pred_data * pred,enum rtx_code code)2814*38fd1498Szrj add_predicate_code (struct pred_data *pred, enum rtx_code code)
2815*38fd1498Szrj {
2816*38fd1498Szrj   if (!pred->codes[code])
2817*38fd1498Szrj     {
2818*38fd1498Szrj       pred->num_codes++;
2819*38fd1498Szrj       pred->codes[code] = true;
2820*38fd1498Szrj 
2821*38fd1498Szrj       if (GET_RTX_CLASS (code) != RTX_CONST_OBJ)
2822*38fd1498Szrj 	pred->allows_non_const = true;
2823*38fd1498Szrj 
2824*38fd1498Szrj       if (code != REG
2825*38fd1498Szrj 	  && code != SUBREG
2826*38fd1498Szrj 	  && code != MEM
2827*38fd1498Szrj 	  && code != CONCAT
2828*38fd1498Szrj 	  && code != PARALLEL
2829*38fd1498Szrj 	  && code != STRICT_LOW_PART
2830*38fd1498Szrj 	  && code != SCRATCH)
2831*38fd1498Szrj 	pred->allows_non_lvalue = true;
2832*38fd1498Szrj 
2833*38fd1498Szrj       if (pred->num_codes == 1)
2834*38fd1498Szrj 	pred->singleton = code;
2835*38fd1498Szrj       else if (pred->num_codes == 2)
2836*38fd1498Szrj 	pred->singleton = UNKNOWN;
2837*38fd1498Szrj     }
2838*38fd1498Szrj }
2839*38fd1498Szrj 
2840*38fd1498Szrj void
add_predicate(struct pred_data * pred)2841*38fd1498Szrj add_predicate (struct pred_data *pred)
2842*38fd1498Szrj {
2843*38fd1498Szrj   void **slot = htab_find_slot (predicate_table, pred, INSERT);
2844*38fd1498Szrj   if (*slot)
2845*38fd1498Szrj     {
2846*38fd1498Szrj       error ("duplicate predicate definition for '%s'", pred->name);
2847*38fd1498Szrj       return;
2848*38fd1498Szrj     }
2849*38fd1498Szrj   *slot = pred;
2850*38fd1498Szrj   *last_predicate = pred;
2851*38fd1498Szrj   last_predicate = &pred->next;
2852*38fd1498Szrj }
2853*38fd1498Szrj 
2854*38fd1498Szrj /* This array gives the initial content of the predicate table.  It
2855*38fd1498Szrj    has entries for all predicates defined in recog.c.  */
2856*38fd1498Szrj 
2857*38fd1498Szrj struct std_pred_table
2858*38fd1498Szrj {
2859*38fd1498Szrj   const char *name;
2860*38fd1498Szrj   bool special;
2861*38fd1498Szrj   bool allows_const_p;
2862*38fd1498Szrj   RTX_CODE codes[NUM_RTX_CODE];
2863*38fd1498Szrj };
2864*38fd1498Szrj 
2865*38fd1498Szrj static const struct std_pred_table std_preds[] = {
2866*38fd1498Szrj   {"general_operand", false, true, {SUBREG, REG, MEM}},
2867*38fd1498Szrj   {"address_operand", true, true, {SUBREG, REG, MEM, PLUS, MINUS, MULT,
2868*38fd1498Szrj 				   ZERO_EXTEND, SIGN_EXTEND, AND}},
2869*38fd1498Szrj   {"register_operand", false, false, {SUBREG, REG}},
2870*38fd1498Szrj   {"pmode_register_operand", true, false, {SUBREG, REG}},
2871*38fd1498Szrj   {"scratch_operand", false, false, {SCRATCH, REG}},
2872*38fd1498Szrj   {"immediate_operand", false, true, {UNKNOWN}},
2873*38fd1498Szrj   {"const_int_operand", false, false, {CONST_INT}},
2874*38fd1498Szrj #if TARGET_SUPPORTS_WIDE_INT
2875*38fd1498Szrj   {"const_scalar_int_operand", false, false, {CONST_INT, CONST_WIDE_INT}},
2876*38fd1498Szrj   {"const_double_operand", false, false, {CONST_DOUBLE}},
2877*38fd1498Szrj #else
2878*38fd1498Szrj   {"const_double_operand", false, false, {CONST_INT, CONST_DOUBLE}},
2879*38fd1498Szrj #endif
2880*38fd1498Szrj   {"nonimmediate_operand", false, false, {SUBREG, REG, MEM}},
2881*38fd1498Szrj   {"nonmemory_operand", false, true, {SUBREG, REG}},
2882*38fd1498Szrj   {"push_operand", false, false, {MEM}},
2883*38fd1498Szrj   {"pop_operand", false, false, {MEM}},
2884*38fd1498Szrj   {"memory_operand", false, false, {SUBREG, MEM}},
2885*38fd1498Szrj   {"indirect_operand", false, false, {SUBREG, MEM}},
2886*38fd1498Szrj   {"ordered_comparison_operator", false, false, {EQ, NE,
2887*38fd1498Szrj 						 LE, LT, GE, GT,
2888*38fd1498Szrj 						 LEU, LTU, GEU, GTU}},
2889*38fd1498Szrj   {"comparison_operator", false, false, {EQ, NE,
2890*38fd1498Szrj 					 LE, LT, GE, GT,
2891*38fd1498Szrj 					 LEU, LTU, GEU, GTU,
2892*38fd1498Szrj 					 UNORDERED, ORDERED,
2893*38fd1498Szrj 					 UNEQ, UNGE, UNGT,
2894*38fd1498Szrj 					 UNLE, UNLT, LTGT}}
2895*38fd1498Szrj };
2896*38fd1498Szrj #define NUM_KNOWN_STD_PREDS ARRAY_SIZE (std_preds)
2897*38fd1498Szrj 
2898*38fd1498Szrj /* Initialize the table of predicate definitions, starting with
2899*38fd1498Szrj    the information we have on generic predicates.  */
2900*38fd1498Szrj 
2901*38fd1498Szrj static void
init_predicate_table(void)2902*38fd1498Szrj init_predicate_table (void)
2903*38fd1498Szrj {
2904*38fd1498Szrj   size_t i, j;
2905*38fd1498Szrj   struct pred_data *pred;
2906*38fd1498Szrj 
2907*38fd1498Szrj   predicate_table = htab_create_alloc (37, hash_struct_pred_data,
2908*38fd1498Szrj 				       eq_struct_pred_data, 0,
2909*38fd1498Szrj 				       xcalloc, free);
2910*38fd1498Szrj 
2911*38fd1498Szrj   for (i = 0; i < NUM_KNOWN_STD_PREDS; i++)
2912*38fd1498Szrj     {
2913*38fd1498Szrj       pred = XCNEW (struct pred_data);
2914*38fd1498Szrj       pred->name = std_preds[i].name;
2915*38fd1498Szrj       pred->special = std_preds[i].special;
2916*38fd1498Szrj 
2917*38fd1498Szrj       for (j = 0; std_preds[i].codes[j] != 0; j++)
2918*38fd1498Szrj 	add_predicate_code (pred, std_preds[i].codes[j]);
2919*38fd1498Szrj 
2920*38fd1498Szrj       if (std_preds[i].allows_const_p)
2921*38fd1498Szrj 	for (j = 0; j < NUM_RTX_CODE; j++)
2922*38fd1498Szrj 	  if (GET_RTX_CLASS (j) == RTX_CONST_OBJ)
2923*38fd1498Szrj 	    add_predicate_code (pred, (enum rtx_code) j);
2924*38fd1498Szrj 
2925*38fd1498Szrj       add_predicate (pred);
2926*38fd1498Szrj     }
2927*38fd1498Szrj }
2928*38fd1498Szrj 
2929*38fd1498Szrj /* These functions allow linkage with print-rtl.c.  Also, some generators
2930*38fd1498Szrj    like to annotate their output with insn names.  */
2931*38fd1498Szrj 
2932*38fd1498Szrj /* Holds an array of names indexed by insn_code_number.  */
2933*38fd1498Szrj static char **insn_name_ptr = 0;
2934*38fd1498Szrj static int insn_name_ptr_size = 0;
2935*38fd1498Szrj 
2936*38fd1498Szrj const char *
get_insn_name(int code)2937*38fd1498Szrj get_insn_name (int code)
2938*38fd1498Szrj {
2939*38fd1498Szrj   if (code < insn_name_ptr_size)
2940*38fd1498Szrj     return insn_name_ptr[code];
2941*38fd1498Szrj   else
2942*38fd1498Szrj     return NULL;
2943*38fd1498Szrj }
2944*38fd1498Szrj 
2945*38fd1498Szrj static void
record_insn_name(int code,const char * name)2946*38fd1498Szrj record_insn_name (int code, const char *name)
2947*38fd1498Szrj {
2948*38fd1498Szrj   static const char *last_real_name = "insn";
2949*38fd1498Szrj   static int last_real_code = 0;
2950*38fd1498Szrj   char *new_name;
2951*38fd1498Szrj 
2952*38fd1498Szrj   if (insn_name_ptr_size <= code)
2953*38fd1498Szrj     {
2954*38fd1498Szrj       int new_size;
2955*38fd1498Szrj       new_size = (insn_name_ptr_size ? insn_name_ptr_size * 2 : 512);
2956*38fd1498Szrj       insn_name_ptr = XRESIZEVEC (char *, insn_name_ptr, new_size);
2957*38fd1498Szrj       memset (insn_name_ptr + insn_name_ptr_size, 0,
2958*38fd1498Szrj 	      sizeof (char *) * (new_size - insn_name_ptr_size));
2959*38fd1498Szrj       insn_name_ptr_size = new_size;
2960*38fd1498Szrj     }
2961*38fd1498Szrj 
2962*38fd1498Szrj   if (!name || name[0] == '\0')
2963*38fd1498Szrj     {
2964*38fd1498Szrj       new_name = XNEWVAR (char, strlen (last_real_name) + 10);
2965*38fd1498Szrj       sprintf (new_name, "%s+%d", last_real_name, code - last_real_code);
2966*38fd1498Szrj     }
2967*38fd1498Szrj   else
2968*38fd1498Szrj     {
2969*38fd1498Szrj       last_real_name = new_name = xstrdup (name);
2970*38fd1498Szrj       last_real_code = code;
2971*38fd1498Szrj     }
2972*38fd1498Szrj 
2973*38fd1498Szrj   insn_name_ptr[code] = new_name;
2974*38fd1498Szrj }
2975*38fd1498Szrj 
2976*38fd1498Szrj /* Make STATS describe the operands that appear in rtx X.  */
2977*38fd1498Szrj 
2978*38fd1498Szrj static void
get_pattern_stats_1(struct pattern_stats * stats,rtx x)2979*38fd1498Szrj get_pattern_stats_1 (struct pattern_stats *stats, rtx x)
2980*38fd1498Szrj {
2981*38fd1498Szrj   RTX_CODE code;
2982*38fd1498Szrj   int i;
2983*38fd1498Szrj   int len;
2984*38fd1498Szrj   const char *fmt;
2985*38fd1498Szrj 
2986*38fd1498Szrj   if (x == NULL_RTX)
2987*38fd1498Szrj     return;
2988*38fd1498Szrj 
2989*38fd1498Szrj   code = GET_CODE (x);
2990*38fd1498Szrj   switch (code)
2991*38fd1498Szrj     {
2992*38fd1498Szrj     case MATCH_OPERAND:
2993*38fd1498Szrj     case MATCH_OPERATOR:
2994*38fd1498Szrj     case MATCH_PARALLEL:
2995*38fd1498Szrj       stats->max_opno = MAX (stats->max_opno, XINT (x, 0));
2996*38fd1498Szrj       break;
2997*38fd1498Szrj 
2998*38fd1498Szrj     case MATCH_DUP:
2999*38fd1498Szrj     case MATCH_OP_DUP:
3000*38fd1498Szrj     case MATCH_PAR_DUP:
3001*38fd1498Szrj       stats->num_dups++;
3002*38fd1498Szrj       stats->max_dup_opno = MAX (stats->max_dup_opno, XINT (x, 0));
3003*38fd1498Szrj       break;
3004*38fd1498Szrj 
3005*38fd1498Szrj     case MATCH_SCRATCH:
3006*38fd1498Szrj       if (stats->min_scratch_opno == -1)
3007*38fd1498Szrj 	stats->min_scratch_opno = XINT (x, 0);
3008*38fd1498Szrj       else
3009*38fd1498Szrj 	stats->min_scratch_opno = MIN (stats->min_scratch_opno, XINT (x, 0));
3010*38fd1498Szrj       stats->max_scratch_opno = MAX (stats->max_scratch_opno, XINT (x, 0));
3011*38fd1498Szrj       break;
3012*38fd1498Szrj 
3013*38fd1498Szrj     default:
3014*38fd1498Szrj       break;
3015*38fd1498Szrj     }
3016*38fd1498Szrj 
3017*38fd1498Szrj   fmt = GET_RTX_FORMAT (code);
3018*38fd1498Szrj   len = GET_RTX_LENGTH (code);
3019*38fd1498Szrj   for (i = 0; i < len; i++)
3020*38fd1498Szrj     {
3021*38fd1498Szrj       if (fmt[i] == 'e' || fmt[i] == 'u')
3022*38fd1498Szrj 	get_pattern_stats_1 (stats, XEXP (x, i));
3023*38fd1498Szrj       else if (fmt[i] == 'E')
3024*38fd1498Szrj 	{
3025*38fd1498Szrj 	  int j;
3026*38fd1498Szrj 	  for (j = 0; j < XVECLEN (x, i); j++)
3027*38fd1498Szrj 	    get_pattern_stats_1 (stats, XVECEXP (x, i, j));
3028*38fd1498Szrj 	}
3029*38fd1498Szrj     }
3030*38fd1498Szrj }
3031*38fd1498Szrj 
3032*38fd1498Szrj /* Make STATS describe the operands that appear in instruction pattern
3033*38fd1498Szrj    PATTERN.  */
3034*38fd1498Szrj 
3035*38fd1498Szrj void
get_pattern_stats(struct pattern_stats * stats,rtvec pattern)3036*38fd1498Szrj get_pattern_stats (struct pattern_stats *stats, rtvec pattern)
3037*38fd1498Szrj {
3038*38fd1498Szrj   int i, len;
3039*38fd1498Szrj 
3040*38fd1498Szrj   stats->max_opno = -1;
3041*38fd1498Szrj   stats->max_dup_opno = -1;
3042*38fd1498Szrj   stats->min_scratch_opno = -1;
3043*38fd1498Szrj   stats->max_scratch_opno = -1;
3044*38fd1498Szrj   stats->num_dups = 0;
3045*38fd1498Szrj 
3046*38fd1498Szrj   len = GET_NUM_ELEM (pattern);
3047*38fd1498Szrj   for (i = 0; i < len; i++)
3048*38fd1498Szrj     get_pattern_stats_1 (stats, RTVEC_ELT (pattern, i));
3049*38fd1498Szrj 
3050*38fd1498Szrj   stats->num_generator_args = stats->max_opno + 1;
3051*38fd1498Szrj   stats->num_insn_operands = MAX (stats->max_opno,
3052*38fd1498Szrj 				  stats->max_scratch_opno) + 1;
3053*38fd1498Szrj   stats->num_operand_vars = MAX (stats->max_opno,
3054*38fd1498Szrj 				  MAX (stats->max_dup_opno,
3055*38fd1498Szrj 				       stats->max_scratch_opno)) + 1;
3056*38fd1498Szrj }
3057*38fd1498Szrj 
3058*38fd1498Szrj /* Return the emit_* function that should be used for pattern X, or NULL
3059*38fd1498Szrj    if we can't pick a particular type at compile time and should instead
3060*38fd1498Szrj    fall back to "emit".  */
3061*38fd1498Szrj 
3062*38fd1498Szrj const char *
get_emit_function(rtx x)3063*38fd1498Szrj get_emit_function (rtx x)
3064*38fd1498Szrj {
3065*38fd1498Szrj   switch (classify_insn (x))
3066*38fd1498Szrj     {
3067*38fd1498Szrj     case INSN:
3068*38fd1498Szrj       return "emit_insn";
3069*38fd1498Szrj 
3070*38fd1498Szrj     case CALL_INSN:
3071*38fd1498Szrj       return "emit_call_insn";
3072*38fd1498Szrj 
3073*38fd1498Szrj     case JUMP_INSN:
3074*38fd1498Szrj       return "emit_jump_insn";
3075*38fd1498Szrj 
3076*38fd1498Szrj     case UNKNOWN:
3077*38fd1498Szrj       return NULL;
3078*38fd1498Szrj 
3079*38fd1498Szrj     default:
3080*38fd1498Szrj       gcc_unreachable ();
3081*38fd1498Szrj     }
3082*38fd1498Szrj }
3083*38fd1498Szrj 
3084*38fd1498Szrj /* Return true if we must emit a barrier after pattern X.  */
3085*38fd1498Szrj 
3086*38fd1498Szrj bool
needs_barrier_p(rtx x)3087*38fd1498Szrj needs_barrier_p (rtx x)
3088*38fd1498Szrj {
3089*38fd1498Szrj   return (GET_CODE (x) == SET
3090*38fd1498Szrj 	  && GET_CODE (SET_DEST (x)) == PC
3091*38fd1498Szrj 	  && GET_CODE (SET_SRC (x)) == LABEL_REF);
3092*38fd1498Szrj }
3093*38fd1498Szrj 
3094*38fd1498Szrj #define NS "NULL"
3095*38fd1498Szrj #define ZS "'\\0'"
3096*38fd1498Szrj #define OPTAB_CL(o, p, c, b, l)    { #o, p, #b, ZS, #l, o, c, UNKNOWN, 1 },
3097*38fd1498Szrj #define OPTAB_CX(o, p) { #o, p, NULL, NULL, NULL, o, UNKNOWN, UNKNOWN, 1 },
3098*38fd1498Szrj #define OPTAB_CD(o, p) { #o, p, NS, ZS, NS, o, UNKNOWN, UNKNOWN, 2 },
3099*38fd1498Szrj #define OPTAB_NL(o, p, c, b, s, l) { #o, p, #b, #s, #l, o, c, c, 3 },
3100*38fd1498Szrj #define OPTAB_NC(o, p, c)          { #o, p, NS, ZS, NS, o, c, c, 3 },
3101*38fd1498Szrj #define OPTAB_NX(o, p) { #o, p, NULL, NULL, NULL, o, UNKNOWN, UNKNOWN, 3 },
3102*38fd1498Szrj #define OPTAB_VL(o, p, c, b, s, l) { #o, p, #b, #s, #l, o, c, UNKNOWN, 3 },
3103*38fd1498Szrj #define OPTAB_VC(o, p, c)          { #o, p, NS, ZS, NS, o, c, UNKNOWN, 3 },
3104*38fd1498Szrj #define OPTAB_VX(o, p) { #o, p, NULL, NULL, NULL, o, UNKNOWN, UNKNOWN, 3 },
3105*38fd1498Szrj #define OPTAB_DC(o, p, c)          { #o, p, NS, ZS, NS, o, c, c, 4 },
3106*38fd1498Szrj #define OPTAB_D(o, p)  { #o, p, NS, ZS, NS, o, UNKNOWN, UNKNOWN, 4 },
3107*38fd1498Szrj 
3108*38fd1498Szrj /* An array of all optabs.  Note that the same optab can appear more
3109*38fd1498Szrj    than once, with a different pattern.  */
3110*38fd1498Szrj optab_def optabs[] = {
3111*38fd1498Szrj   { "unknown_optab", NULL, NS, ZS, NS, unknown_optab, UNKNOWN, UNKNOWN, 0 },
3112*38fd1498Szrj #include "optabs.def"
3113*38fd1498Szrj };
3114*38fd1498Szrj 
3115*38fd1498Szrj /* The number of entries in optabs[].  */
3116*38fd1498Szrj unsigned int num_optabs = ARRAY_SIZE (optabs);
3117*38fd1498Szrj 
3118*38fd1498Szrj #undef OPTAB_CL
3119*38fd1498Szrj #undef OPTAB_CX
3120*38fd1498Szrj #undef OPTAB_CD
3121*38fd1498Szrj #undef OPTAB_NL
3122*38fd1498Szrj #undef OPTAB_NC
3123*38fd1498Szrj #undef OPTAB_NX
3124*38fd1498Szrj #undef OPTAB_VL
3125*38fd1498Szrj #undef OPTAB_VC
3126*38fd1498Szrj #undef OPTAB_VX
3127*38fd1498Szrj #undef OPTAB_DC
3128*38fd1498Szrj #undef OPTAB_D
3129*38fd1498Szrj 
3130*38fd1498Szrj /* Return true if instruction NAME matches pattern PAT, storing information
3131*38fd1498Szrj    about the match in P if so.  */
3132*38fd1498Szrj 
3133*38fd1498Szrj static bool
match_pattern(optab_pattern * p,const char * name,const char * pat)3134*38fd1498Szrj match_pattern (optab_pattern *p, const char *name, const char *pat)
3135*38fd1498Szrj {
3136*38fd1498Szrj   bool force_float = false;
3137*38fd1498Szrj   bool force_int = false;
3138*38fd1498Szrj   bool force_partial_int = false;
3139*38fd1498Szrj   bool force_fixed = false;
3140*38fd1498Szrj 
3141*38fd1498Szrj   if (pat == NULL)
3142*38fd1498Szrj     return false;
3143*38fd1498Szrj   for (; ; ++pat)
3144*38fd1498Szrj     {
3145*38fd1498Szrj       if (*pat != '$')
3146*38fd1498Szrj 	{
3147*38fd1498Szrj 	  if (*pat != *name++)
3148*38fd1498Szrj 	    return false;
3149*38fd1498Szrj 	  if (*pat == '\0')
3150*38fd1498Szrj 	    return true;
3151*38fd1498Szrj 	  continue;
3152*38fd1498Szrj 	}
3153*38fd1498Szrj       switch (*++pat)
3154*38fd1498Szrj 	{
3155*38fd1498Szrj 	case 'I':
3156*38fd1498Szrj 	  force_int = 1;
3157*38fd1498Szrj 	  break;
3158*38fd1498Szrj 	case 'P':
3159*38fd1498Szrj 	  force_partial_int = 1;
3160*38fd1498Szrj 	  break;
3161*38fd1498Szrj 	case 'F':
3162*38fd1498Szrj 	  force_float = 1;
3163*38fd1498Szrj 	  break;
3164*38fd1498Szrj 	case 'Q':
3165*38fd1498Szrj 	  force_fixed = 1;
3166*38fd1498Szrj 	  break;
3167*38fd1498Szrj 
3168*38fd1498Szrj 	case 'a':
3169*38fd1498Szrj 	case 'b':
3170*38fd1498Szrj 	  {
3171*38fd1498Szrj 	    int i;
3172*38fd1498Szrj 
3173*38fd1498Szrj 	    /* This loop will stop at the first prefix match, so
3174*38fd1498Szrj 	       look through the modes in reverse order, in case
3175*38fd1498Szrj 	       there are extra CC modes and CC is a prefix of the
3176*38fd1498Szrj 	       CC modes (as it should be).  */
3177*38fd1498Szrj 	    for (i = (MAX_MACHINE_MODE) - 1; i >= 0; i--)
3178*38fd1498Szrj 	      {
3179*38fd1498Szrj 		const char *p, *q;
3180*38fd1498Szrj 		for (p = GET_MODE_NAME (i), q = name; *p; p++, q++)
3181*38fd1498Szrj 		  if (TOLOWER (*p) != *q)
3182*38fd1498Szrj 		    break;
3183*38fd1498Szrj 		if (*p == 0
3184*38fd1498Szrj 		    && (! force_int || mode_class[i] == MODE_INT
3185*38fd1498Szrj 			|| mode_class[i] == MODE_VECTOR_INT)
3186*38fd1498Szrj 		    && (! force_partial_int
3187*38fd1498Szrj 			|| mode_class[i] == MODE_INT
3188*38fd1498Szrj 			|| mode_class[i] == MODE_PARTIAL_INT
3189*38fd1498Szrj 			|| mode_class[i] == MODE_VECTOR_INT)
3190*38fd1498Szrj 		    && (! force_float
3191*38fd1498Szrj 			|| mode_class[i] == MODE_FLOAT
3192*38fd1498Szrj 			|| mode_class[i] == MODE_DECIMAL_FLOAT
3193*38fd1498Szrj 			|| mode_class[i] == MODE_COMPLEX_FLOAT
3194*38fd1498Szrj 			|| mode_class[i] == MODE_VECTOR_FLOAT)
3195*38fd1498Szrj 		    && (! force_fixed
3196*38fd1498Szrj 			|| mode_class[i] == MODE_FRACT
3197*38fd1498Szrj 			|| mode_class[i] == MODE_UFRACT
3198*38fd1498Szrj 			|| mode_class[i] == MODE_ACCUM
3199*38fd1498Szrj 			|| mode_class[i] == MODE_UACCUM
3200*38fd1498Szrj 			|| mode_class[i] == MODE_VECTOR_FRACT
3201*38fd1498Szrj 			|| mode_class[i] == MODE_VECTOR_UFRACT
3202*38fd1498Szrj 			|| mode_class[i] == MODE_VECTOR_ACCUM
3203*38fd1498Szrj 			|| mode_class[i] == MODE_VECTOR_UACCUM))
3204*38fd1498Szrj 		  break;
3205*38fd1498Szrj 	      }
3206*38fd1498Szrj 
3207*38fd1498Szrj 	    if (i < 0)
3208*38fd1498Szrj 	      return false;
3209*38fd1498Szrj 	    name += strlen (GET_MODE_NAME (i));
3210*38fd1498Szrj 	    if (*pat == 'a')
3211*38fd1498Szrj 	      p->m1 = i;
3212*38fd1498Szrj 	    else
3213*38fd1498Szrj 	      p->m2 = i;
3214*38fd1498Szrj 
3215*38fd1498Szrj 	    force_int = false;
3216*38fd1498Szrj 	    force_partial_int = false;
3217*38fd1498Szrj 	    force_float = false;
3218*38fd1498Szrj 	    force_fixed = false;
3219*38fd1498Szrj 	  }
3220*38fd1498Szrj 	  break;
3221*38fd1498Szrj 
3222*38fd1498Szrj 	default:
3223*38fd1498Szrj 	  gcc_unreachable ();
3224*38fd1498Szrj 	}
3225*38fd1498Szrj     }
3226*38fd1498Szrj }
3227*38fd1498Szrj 
3228*38fd1498Szrj /* Return true if NAME is the name of an optab, describing it in P if so.  */
3229*38fd1498Szrj 
3230*38fd1498Szrj bool
find_optab(optab_pattern * p,const char * name)3231*38fd1498Szrj find_optab (optab_pattern *p, const char *name)
3232*38fd1498Szrj {
3233*38fd1498Szrj   if (*name == 0 || *name == '*')
3234*38fd1498Szrj     return false;
3235*38fd1498Szrj 
3236*38fd1498Szrj   /* See if NAME matches one of the patterns we have for the optabs
3237*38fd1498Szrj      we know about.  */
3238*38fd1498Szrj   for (unsigned int pindex = 0; pindex < ARRAY_SIZE (optabs); pindex++)
3239*38fd1498Szrj     {
3240*38fd1498Szrj       p->m1 = p->m2 = 0;
3241*38fd1498Szrj       if (match_pattern (p, name, optabs[pindex].pattern))
3242*38fd1498Szrj 	{
3243*38fd1498Szrj 	  p->name = name;
3244*38fd1498Szrj 	  p->op = optabs[pindex].op;
3245*38fd1498Szrj 	  p->sort_num = (p->op << 16) | (p->m2 << 8) | p->m1;
3246*38fd1498Szrj 	  return true;
3247*38fd1498Szrj 	}
3248*38fd1498Szrj     }
3249*38fd1498Szrj   return false;
3250*38fd1498Szrj }
3251