xref: /dragonfly/contrib/gcc-4.7/gcc/gensupport.c (revision e4b17023)
1*e4b17023SJohn Marino /* Support routines for the various generation passes.
2*e4b17023SJohn Marino    Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
3*e4b17023SJohn Marino    2010, Free Software Foundation, Inc.
4*e4b17023SJohn Marino 
5*e4b17023SJohn Marino    This file is part of GCC.
6*e4b17023SJohn Marino 
7*e4b17023SJohn Marino    GCC is free software; you can redistribute it and/or modify it
8*e4b17023SJohn Marino    under the terms of the GNU General Public License as published by
9*e4b17023SJohn Marino    the Free Software Foundation; either version 3, or (at your option)
10*e4b17023SJohn Marino    any later version.
11*e4b17023SJohn Marino 
12*e4b17023SJohn Marino    GCC is distributed in the hope that it will be useful, but WITHOUT
13*e4b17023SJohn Marino    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14*e4b17023SJohn Marino    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
15*e4b17023SJohn Marino    License for more details.
16*e4b17023SJohn Marino 
17*e4b17023SJohn Marino    You should have received a copy of the GNU General Public License
18*e4b17023SJohn Marino    along with GCC; see the file COPYING3.  If not see
19*e4b17023SJohn Marino    <http://www.gnu.org/licenses/>.  */
20*e4b17023SJohn Marino 
21*e4b17023SJohn Marino #include "bconfig.h"
22*e4b17023SJohn Marino #include "system.h"
23*e4b17023SJohn Marino #include "coretypes.h"
24*e4b17023SJohn Marino #include "tm.h"
25*e4b17023SJohn Marino #include "rtl.h"
26*e4b17023SJohn Marino #include "obstack.h"
27*e4b17023SJohn Marino #include "errors.h"
28*e4b17023SJohn Marino #include "hashtab.h"
29*e4b17023SJohn Marino #include "read-md.h"
30*e4b17023SJohn Marino #include "gensupport.h"
31*e4b17023SJohn Marino 
32*e4b17023SJohn Marino 
33*e4b17023SJohn Marino /* In case some macros used by files we include need it, define this here.  */
34*e4b17023SJohn Marino int target_flags;
35*e4b17023SJohn Marino 
36*e4b17023SJohn Marino int insn_elision = 1;
37*e4b17023SJohn Marino 
38*e4b17023SJohn Marino static struct obstack obstack;
39*e4b17023SJohn Marino struct obstack *rtl_obstack = &obstack;
40*e4b17023SJohn Marino 
41*e4b17023SJohn Marino static int sequence_num;
42*e4b17023SJohn Marino 
43*e4b17023SJohn Marino static int predicable_default;
44*e4b17023SJohn Marino static const char *predicable_true;
45*e4b17023SJohn Marino static const char *predicable_false;
46*e4b17023SJohn Marino 
47*e4b17023SJohn Marino static htab_t condition_table;
48*e4b17023SJohn Marino 
49*e4b17023SJohn Marino /* We initially queue all patterns, process the define_insn and
50*e4b17023SJohn Marino    define_cond_exec patterns, then return them one at a time.  */
51*e4b17023SJohn Marino 
52*e4b17023SJohn Marino struct queue_elem
53*e4b17023SJohn Marino {
54*e4b17023SJohn Marino   rtx data;
55*e4b17023SJohn Marino   const char *filename;
56*e4b17023SJohn Marino   int lineno;
57*e4b17023SJohn Marino   struct queue_elem *next;
58*e4b17023SJohn Marino   /* In a DEFINE_INSN that came from a DEFINE_INSN_AND_SPLIT, SPLIT
59*e4b17023SJohn Marino      points to the generated DEFINE_SPLIT.  */
60*e4b17023SJohn Marino   struct queue_elem *split;
61*e4b17023SJohn Marino };
62*e4b17023SJohn Marino 
63*e4b17023SJohn Marino #define MNEMONIC_ATTR_NAME "mnemonic"
64*e4b17023SJohn Marino #define MNEMONIC_HTAB_SIZE 1024
65*e4b17023SJohn Marino 
66*e4b17023SJohn Marino static struct queue_elem *define_attr_queue;
67*e4b17023SJohn Marino static struct queue_elem **define_attr_tail = &define_attr_queue;
68*e4b17023SJohn Marino static struct queue_elem *define_pred_queue;
69*e4b17023SJohn Marino static struct queue_elem **define_pred_tail = &define_pred_queue;
70*e4b17023SJohn Marino static struct queue_elem *define_insn_queue;
71*e4b17023SJohn Marino static struct queue_elem **define_insn_tail = &define_insn_queue;
72*e4b17023SJohn Marino static struct queue_elem *define_cond_exec_queue;
73*e4b17023SJohn Marino static struct queue_elem **define_cond_exec_tail = &define_cond_exec_queue;
74*e4b17023SJohn Marino static struct queue_elem *other_queue;
75*e4b17023SJohn Marino static struct queue_elem **other_tail = &other_queue;
76*e4b17023SJohn Marino 
77*e4b17023SJohn Marino static struct queue_elem *queue_pattern (rtx, struct queue_elem ***,
78*e4b17023SJohn Marino 					 const char *, int);
79*e4b17023SJohn Marino 
80*e4b17023SJohn Marino static void remove_constraints (rtx);
81*e4b17023SJohn Marino static void process_rtx (rtx, int);
82*e4b17023SJohn Marino 
83*e4b17023SJohn Marino static int is_predicable (struct queue_elem *);
84*e4b17023SJohn Marino static void identify_predicable_attribute (void);
85*e4b17023SJohn Marino static int n_alternatives (const char *);
86*e4b17023SJohn Marino static void collect_insn_data (rtx, int *, int *);
87*e4b17023SJohn Marino static rtx alter_predicate_for_insn (rtx, int, int, int);
88*e4b17023SJohn Marino static const char *alter_test_for_insn (struct queue_elem *,
89*e4b17023SJohn Marino 					struct queue_elem *);
90*e4b17023SJohn Marino static char *shift_output_template (char *, const char *, int);
91*e4b17023SJohn Marino static const char *alter_output_for_insn (struct queue_elem *,
92*e4b17023SJohn Marino 					  struct queue_elem *,
93*e4b17023SJohn Marino 					  int, int);
94*e4b17023SJohn Marino static void process_one_cond_exec (struct queue_elem *);
95*e4b17023SJohn Marino static void process_define_cond_exec (void);
96*e4b17023SJohn Marino static void init_predicate_table (void);
97*e4b17023SJohn Marino static void record_insn_name (int, const char *);
98*e4b17023SJohn Marino 
99*e4b17023SJohn Marino /* Make a version of gen_rtx_CONST_INT so that GEN_INT can be used in
100*e4b17023SJohn Marino    the gensupport programs.  */
101*e4b17023SJohn Marino 
102*e4b17023SJohn Marino rtx
gen_rtx_CONST_INT(enum machine_mode ARG_UNUSED (mode),HOST_WIDE_INT arg)103*e4b17023SJohn Marino gen_rtx_CONST_INT (enum machine_mode ARG_UNUSED (mode),
104*e4b17023SJohn Marino 		   HOST_WIDE_INT arg)
105*e4b17023SJohn Marino {
106*e4b17023SJohn Marino   rtx rt = rtx_alloc (CONST_INT);
107*e4b17023SJohn Marino 
108*e4b17023SJohn Marino   XWINT (rt, 0) = arg;
109*e4b17023SJohn Marino   return rt;
110*e4b17023SJohn Marino }
111*e4b17023SJohn Marino 
112*e4b17023SJohn Marino /* Predicate handling.
113*e4b17023SJohn Marino 
114*e4b17023SJohn Marino    We construct from the machine description a table mapping each
115*e4b17023SJohn Marino    predicate to a list of the rtl codes it can possibly match.  The
116*e4b17023SJohn Marino    function 'maybe_both_true' uses it to deduce that there are no
117*e4b17023SJohn Marino    expressions that can be matches by certain pairs of tree nodes.
118*e4b17023SJohn Marino    Also, if a predicate can match only one code, we can hardwire that
119*e4b17023SJohn Marino    code into the node testing the predicate.
120*e4b17023SJohn Marino 
121*e4b17023SJohn Marino    Some predicates are flagged as special.  validate_pattern will not
122*e4b17023SJohn Marino    warn about modeless match_operand expressions if they have a
123*e4b17023SJohn Marino    special predicate.  Predicates that allow only constants are also
124*e4b17023SJohn Marino    treated as special, for this purpose.
125*e4b17023SJohn Marino 
126*e4b17023SJohn Marino    validate_pattern will warn about predicates that allow non-lvalues
127*e4b17023SJohn Marino    when they appear in destination operands.
128*e4b17023SJohn Marino 
129*e4b17023SJohn Marino    Calculating the set of rtx codes that can possibly be accepted by a
130*e4b17023SJohn Marino    predicate expression EXP requires a three-state logic: any given
131*e4b17023SJohn Marino    subexpression may definitively accept a code C (Y), definitively
132*e4b17023SJohn Marino    reject a code C (N), or may have an indeterminate effect (I).  N
133*e4b17023SJohn Marino    and I is N; Y or I is Y; Y and I, N or I are both I.  Here are full
134*e4b17023SJohn Marino    truth tables.
135*e4b17023SJohn Marino 
136*e4b17023SJohn Marino      a b  a&b  a|b
137*e4b17023SJohn Marino      Y Y   Y    Y
138*e4b17023SJohn Marino      N Y   N    Y
139*e4b17023SJohn Marino      N N   N    N
140*e4b17023SJohn Marino      I Y   I    Y
141*e4b17023SJohn Marino      I N   N    I
142*e4b17023SJohn Marino      I I   I    I
143*e4b17023SJohn Marino 
144*e4b17023SJohn Marino    We represent Y with 1, N with 0, I with 2.  If any code is left in
145*e4b17023SJohn Marino    an I state by the complete expression, we must assume that that
146*e4b17023SJohn Marino    code can be accepted.  */
147*e4b17023SJohn Marino 
148*e4b17023SJohn Marino #define N 0
149*e4b17023SJohn Marino #define Y 1
150*e4b17023SJohn Marino #define I 2
151*e4b17023SJohn Marino 
152*e4b17023SJohn Marino #define TRISTATE_AND(a,b)			\
153*e4b17023SJohn Marino   ((a) == I ? ((b) == N ? N : I) :		\
154*e4b17023SJohn Marino    (b) == I ? ((a) == N ? N : I) :		\
155*e4b17023SJohn Marino    (a) && (b))
156*e4b17023SJohn Marino 
157*e4b17023SJohn Marino #define TRISTATE_OR(a,b)			\
158*e4b17023SJohn Marino   ((a) == I ? ((b) == Y ? Y : I) :		\
159*e4b17023SJohn Marino    (b) == I ? ((a) == Y ? Y : I) :		\
160*e4b17023SJohn Marino    (a) || (b))
161*e4b17023SJohn Marino 
162*e4b17023SJohn Marino #define TRISTATE_NOT(a)				\
163*e4b17023SJohn Marino   ((a) == I ? I : !(a))
164*e4b17023SJohn Marino 
165*e4b17023SJohn Marino /* 0 means no warning about that code yet, 1 means warned.  */
166*e4b17023SJohn Marino static char did_you_mean_codes[NUM_RTX_CODE];
167*e4b17023SJohn Marino 
168*e4b17023SJohn Marino /* Recursively calculate the set of rtx codes accepted by the
169*e4b17023SJohn Marino    predicate expression EXP, writing the result to CODES.  LINENO is
170*e4b17023SJohn Marino    the line number on which the directive containing EXP appeared.  */
171*e4b17023SJohn Marino 
172*e4b17023SJohn Marino static void
compute_predicate_codes(rtx exp,int lineno,char codes[NUM_RTX_CODE])173*e4b17023SJohn Marino compute_predicate_codes (rtx exp, int lineno, char codes[NUM_RTX_CODE])
174*e4b17023SJohn Marino {
175*e4b17023SJohn Marino   char op0_codes[NUM_RTX_CODE];
176*e4b17023SJohn Marino   char op1_codes[NUM_RTX_CODE];
177*e4b17023SJohn Marino   char op2_codes[NUM_RTX_CODE];
178*e4b17023SJohn Marino   int i;
179*e4b17023SJohn Marino 
180*e4b17023SJohn Marino   switch (GET_CODE (exp))
181*e4b17023SJohn Marino     {
182*e4b17023SJohn Marino     case AND:
183*e4b17023SJohn Marino       compute_predicate_codes (XEXP (exp, 0), lineno, op0_codes);
184*e4b17023SJohn Marino       compute_predicate_codes (XEXP (exp, 1), lineno, op1_codes);
185*e4b17023SJohn Marino       for (i = 0; i < NUM_RTX_CODE; i++)
186*e4b17023SJohn Marino 	codes[i] = TRISTATE_AND (op0_codes[i], op1_codes[i]);
187*e4b17023SJohn Marino       break;
188*e4b17023SJohn Marino 
189*e4b17023SJohn Marino     case IOR:
190*e4b17023SJohn Marino       compute_predicate_codes (XEXP (exp, 0), lineno, op0_codes);
191*e4b17023SJohn Marino       compute_predicate_codes (XEXP (exp, 1), lineno, op1_codes);
192*e4b17023SJohn Marino       for (i = 0; i < NUM_RTX_CODE; i++)
193*e4b17023SJohn Marino 	codes[i] = TRISTATE_OR (op0_codes[i], op1_codes[i]);
194*e4b17023SJohn Marino       break;
195*e4b17023SJohn Marino     case NOT:
196*e4b17023SJohn Marino       compute_predicate_codes (XEXP (exp, 0), lineno, op0_codes);
197*e4b17023SJohn Marino       for (i = 0; i < NUM_RTX_CODE; i++)
198*e4b17023SJohn Marino 	codes[i] = TRISTATE_NOT (op0_codes[i]);
199*e4b17023SJohn Marino       break;
200*e4b17023SJohn Marino 
201*e4b17023SJohn Marino     case IF_THEN_ELSE:
202*e4b17023SJohn Marino       /* a ? b : c  accepts the same codes as (a & b) | (!a & c).  */
203*e4b17023SJohn Marino       compute_predicate_codes (XEXP (exp, 0), lineno, op0_codes);
204*e4b17023SJohn Marino       compute_predicate_codes (XEXP (exp, 1), lineno, op1_codes);
205*e4b17023SJohn Marino       compute_predicate_codes (XEXP (exp, 2), lineno, op2_codes);
206*e4b17023SJohn Marino       for (i = 0; i < NUM_RTX_CODE; i++)
207*e4b17023SJohn Marino 	codes[i] = TRISTATE_OR (TRISTATE_AND (op0_codes[i], op1_codes[i]),
208*e4b17023SJohn Marino 				TRISTATE_AND (TRISTATE_NOT (op0_codes[i]),
209*e4b17023SJohn Marino 					      op2_codes[i]));
210*e4b17023SJohn Marino       break;
211*e4b17023SJohn Marino 
212*e4b17023SJohn Marino     case MATCH_CODE:
213*e4b17023SJohn Marino       /* MATCH_CODE allows a specified list of codes.  However, if it
214*e4b17023SJohn Marino 	 does not apply to the top level of the expression, it does not
215*e4b17023SJohn Marino 	 constrain the set of codes for the top level.  */
216*e4b17023SJohn Marino       if (XSTR (exp, 1)[0] != '\0')
217*e4b17023SJohn Marino 	{
218*e4b17023SJohn Marino 	  memset (codes, Y, NUM_RTX_CODE);
219*e4b17023SJohn Marino 	  break;
220*e4b17023SJohn Marino 	}
221*e4b17023SJohn Marino 
222*e4b17023SJohn Marino       memset (codes, N, NUM_RTX_CODE);
223*e4b17023SJohn Marino       {
224*e4b17023SJohn Marino 	const char *next_code = XSTR (exp, 0);
225*e4b17023SJohn Marino 	const char *code;
226*e4b17023SJohn Marino 
227*e4b17023SJohn Marino 	if (*next_code == '\0')
228*e4b17023SJohn Marino 	  {
229*e4b17023SJohn Marino 	    error_with_line (lineno, "empty match_code expression");
230*e4b17023SJohn Marino 	    break;
231*e4b17023SJohn Marino 	  }
232*e4b17023SJohn Marino 
233*e4b17023SJohn Marino 	while ((code = scan_comma_elt (&next_code)) != 0)
234*e4b17023SJohn Marino 	  {
235*e4b17023SJohn Marino 	    size_t n = next_code - code;
236*e4b17023SJohn Marino 	    int found_it = 0;
237*e4b17023SJohn Marino 
238*e4b17023SJohn Marino 	    for (i = 0; i < NUM_RTX_CODE; i++)
239*e4b17023SJohn Marino 	      if (!strncmp (code, GET_RTX_NAME (i), n)
240*e4b17023SJohn Marino 		  && GET_RTX_NAME (i)[n] == '\0')
241*e4b17023SJohn Marino 		{
242*e4b17023SJohn Marino 		  codes[i] = Y;
243*e4b17023SJohn Marino 		  found_it = 1;
244*e4b17023SJohn Marino 		  break;
245*e4b17023SJohn Marino 		}
246*e4b17023SJohn Marino 	    if (!found_it)
247*e4b17023SJohn Marino 	      {
248*e4b17023SJohn Marino 		error_with_line (lineno,
249*e4b17023SJohn Marino 				 "match_code \"%.*s\" matches nothing",
250*e4b17023SJohn Marino 				 (int) n, code);
251*e4b17023SJohn Marino 		for (i = 0; i < NUM_RTX_CODE; i++)
252*e4b17023SJohn Marino 		  if (!strncasecmp (code, GET_RTX_NAME (i), n)
253*e4b17023SJohn Marino 		      && GET_RTX_NAME (i)[n] == '\0'
254*e4b17023SJohn Marino 		      && !did_you_mean_codes[i])
255*e4b17023SJohn Marino 		    {
256*e4b17023SJohn Marino 		      did_you_mean_codes[i] = 1;
257*e4b17023SJohn Marino 		      message_with_line (lineno, "(did you mean \"%s\"?)",
258*e4b17023SJohn Marino 					 GET_RTX_NAME (i));
259*e4b17023SJohn Marino 		    }
260*e4b17023SJohn Marino 	      }
261*e4b17023SJohn Marino 	  }
262*e4b17023SJohn Marino       }
263*e4b17023SJohn Marino       break;
264*e4b17023SJohn Marino 
265*e4b17023SJohn Marino     case MATCH_OPERAND:
266*e4b17023SJohn Marino       /* MATCH_OPERAND disallows the set of codes that the named predicate
267*e4b17023SJohn Marino 	 disallows, and is indeterminate for the codes that it does allow.  */
268*e4b17023SJohn Marino       {
269*e4b17023SJohn Marino 	struct pred_data *p = lookup_predicate (XSTR (exp, 1));
270*e4b17023SJohn Marino 	if (!p)
271*e4b17023SJohn Marino 	  {
272*e4b17023SJohn Marino 	    error_with_line (lineno, "reference to unknown predicate '%s'",
273*e4b17023SJohn Marino 			     XSTR (exp, 1));
274*e4b17023SJohn Marino 	    break;
275*e4b17023SJohn Marino 	  }
276*e4b17023SJohn Marino 	for (i = 0; i < NUM_RTX_CODE; i++)
277*e4b17023SJohn Marino 	  codes[i] = p->codes[i] ? I : N;
278*e4b17023SJohn Marino       }
279*e4b17023SJohn Marino       break;
280*e4b17023SJohn Marino 
281*e4b17023SJohn Marino 
282*e4b17023SJohn Marino     case MATCH_TEST:
283*e4b17023SJohn Marino       /* (match_test WHATEVER) is completely indeterminate.  */
284*e4b17023SJohn Marino       memset (codes, I, NUM_RTX_CODE);
285*e4b17023SJohn Marino       break;
286*e4b17023SJohn Marino 
287*e4b17023SJohn Marino     default:
288*e4b17023SJohn Marino       error_with_line (lineno,
289*e4b17023SJohn Marino 		       "'%s' cannot be used in a define_predicate expression",
290*e4b17023SJohn Marino 		       GET_RTX_NAME (GET_CODE (exp)));
291*e4b17023SJohn Marino       memset (codes, I, NUM_RTX_CODE);
292*e4b17023SJohn Marino       break;
293*e4b17023SJohn Marino     }
294*e4b17023SJohn Marino }
295*e4b17023SJohn Marino 
296*e4b17023SJohn Marino #undef TRISTATE_OR
297*e4b17023SJohn Marino #undef TRISTATE_AND
298*e4b17023SJohn Marino #undef TRISTATE_NOT
299*e4b17023SJohn Marino 
300*e4b17023SJohn Marino /* Return true if NAME is a valid predicate name.  */
301*e4b17023SJohn Marino 
302*e4b17023SJohn Marino static bool
valid_predicate_name_p(const char * name)303*e4b17023SJohn Marino valid_predicate_name_p (const char *name)
304*e4b17023SJohn Marino {
305*e4b17023SJohn Marino   const char *p;
306*e4b17023SJohn Marino 
307*e4b17023SJohn Marino   if (!ISALPHA (name[0]) && name[0] != '_')
308*e4b17023SJohn Marino     return false;
309*e4b17023SJohn Marino   for (p = name + 1; *p; p++)
310*e4b17023SJohn Marino     if (!ISALNUM (*p) && *p != '_')
311*e4b17023SJohn Marino       return false;
312*e4b17023SJohn Marino   return true;
313*e4b17023SJohn Marino }
314*e4b17023SJohn Marino 
315*e4b17023SJohn Marino /* Process define_predicate directive DESC, which appears on line number
316*e4b17023SJohn Marino    LINENO.  Compute the set of codes that can be matched, and record this
317*e4b17023SJohn Marino    as a known predicate.  */
318*e4b17023SJohn Marino 
319*e4b17023SJohn Marino static void
process_define_predicate(rtx desc,int lineno)320*e4b17023SJohn Marino process_define_predicate (rtx desc, int lineno)
321*e4b17023SJohn Marino {
322*e4b17023SJohn Marino   struct pred_data *pred;
323*e4b17023SJohn Marino   char codes[NUM_RTX_CODE];
324*e4b17023SJohn Marino   int i;
325*e4b17023SJohn Marino 
326*e4b17023SJohn Marino   if (!valid_predicate_name_p (XSTR (desc, 0)))
327*e4b17023SJohn Marino     {
328*e4b17023SJohn Marino       error_with_line (lineno,
329*e4b17023SJohn Marino 		       "%s: predicate name must be a valid C function name",
330*e4b17023SJohn Marino 		       XSTR (desc, 0));
331*e4b17023SJohn Marino       return;
332*e4b17023SJohn Marino     }
333*e4b17023SJohn Marino 
334*e4b17023SJohn Marino   pred = XCNEW (struct pred_data);
335*e4b17023SJohn Marino   pred->name = XSTR (desc, 0);
336*e4b17023SJohn Marino   pred->exp = XEXP (desc, 1);
337*e4b17023SJohn Marino   pred->c_block = XSTR (desc, 2);
338*e4b17023SJohn Marino   if (GET_CODE (desc) == DEFINE_SPECIAL_PREDICATE)
339*e4b17023SJohn Marino     pred->special = true;
340*e4b17023SJohn Marino 
341*e4b17023SJohn Marino   compute_predicate_codes (XEXP (desc, 1), lineno, codes);
342*e4b17023SJohn Marino 
343*e4b17023SJohn Marino   for (i = 0; i < NUM_RTX_CODE; i++)
344*e4b17023SJohn Marino     if (codes[i] != N)
345*e4b17023SJohn Marino       add_predicate_code (pred, (enum rtx_code) i);
346*e4b17023SJohn Marino 
347*e4b17023SJohn Marino   add_predicate (pred);
348*e4b17023SJohn Marino }
349*e4b17023SJohn Marino #undef I
350*e4b17023SJohn Marino #undef N
351*e4b17023SJohn Marino #undef Y
352*e4b17023SJohn Marino 
353*e4b17023SJohn Marino /* Queue PATTERN on LIST_TAIL.  Return the address of the new queue
354*e4b17023SJohn Marino    element.  */
355*e4b17023SJohn Marino 
356*e4b17023SJohn Marino static struct queue_elem *
queue_pattern(rtx pattern,struct queue_elem *** list_tail,const char * filename,int lineno)357*e4b17023SJohn Marino queue_pattern (rtx pattern, struct queue_elem ***list_tail,
358*e4b17023SJohn Marino 	       const char *filename, int lineno)
359*e4b17023SJohn Marino {
360*e4b17023SJohn Marino   struct queue_elem *e = XNEW(struct queue_elem);
361*e4b17023SJohn Marino   e->data = pattern;
362*e4b17023SJohn Marino   e->filename = filename;
363*e4b17023SJohn Marino   e->lineno = lineno;
364*e4b17023SJohn Marino   e->next = NULL;
365*e4b17023SJohn Marino   e->split = NULL;
366*e4b17023SJohn Marino   **list_tail = e;
367*e4b17023SJohn Marino   *list_tail = &e->next;
368*e4b17023SJohn Marino   return e;
369*e4b17023SJohn Marino }
370*e4b17023SJohn Marino 
371*e4b17023SJohn Marino /* Build a define_attr for an binary attribute with name NAME and
372*e4b17023SJohn Marino    possible values "yes" and "no", and queue it.  */
373*e4b17023SJohn Marino static void
add_define_attr(const char * name)374*e4b17023SJohn Marino add_define_attr (const char *name)
375*e4b17023SJohn Marino {
376*e4b17023SJohn Marino   struct queue_elem *e = XNEW(struct queue_elem);
377*e4b17023SJohn Marino   rtx t1 = rtx_alloc (DEFINE_ATTR);
378*e4b17023SJohn Marino   XSTR (t1, 0) = name;
379*e4b17023SJohn Marino   XSTR (t1, 1) = "no,yes";
380*e4b17023SJohn Marino   XEXP (t1, 2) = rtx_alloc (CONST_STRING);
381*e4b17023SJohn Marino   XSTR (XEXP (t1, 2), 0) = "yes";
382*e4b17023SJohn Marino   e->data = t1;
383*e4b17023SJohn Marino   e->filename = "built-in";
384*e4b17023SJohn Marino   e->lineno = -1;
385*e4b17023SJohn Marino   e->next = define_attr_queue;
386*e4b17023SJohn Marino   define_attr_queue = e;
387*e4b17023SJohn Marino 
388*e4b17023SJohn Marino }
389*e4b17023SJohn Marino 
390*e4b17023SJohn Marino /* Recursively remove constraints from an rtx.  */
391*e4b17023SJohn Marino 
392*e4b17023SJohn Marino static void
remove_constraints(rtx part)393*e4b17023SJohn Marino remove_constraints (rtx part)
394*e4b17023SJohn Marino {
395*e4b17023SJohn Marino   int i, j;
396*e4b17023SJohn Marino   const char *format_ptr;
397*e4b17023SJohn Marino 
398*e4b17023SJohn Marino   if (part == 0)
399*e4b17023SJohn Marino     return;
400*e4b17023SJohn Marino 
401*e4b17023SJohn Marino   if (GET_CODE (part) == MATCH_OPERAND)
402*e4b17023SJohn Marino     XSTR (part, 2) = "";
403*e4b17023SJohn Marino   else if (GET_CODE (part) == MATCH_SCRATCH)
404*e4b17023SJohn Marino     XSTR (part, 1) = "";
405*e4b17023SJohn Marino 
406*e4b17023SJohn Marino   format_ptr = GET_RTX_FORMAT (GET_CODE (part));
407*e4b17023SJohn Marino 
408*e4b17023SJohn Marino   for (i = 0; i < GET_RTX_LENGTH (GET_CODE (part)); i++)
409*e4b17023SJohn Marino     switch (*format_ptr++)
410*e4b17023SJohn Marino       {
411*e4b17023SJohn Marino       case 'e':
412*e4b17023SJohn Marino       case 'u':
413*e4b17023SJohn Marino 	remove_constraints (XEXP (part, i));
414*e4b17023SJohn Marino 	break;
415*e4b17023SJohn Marino       case 'E':
416*e4b17023SJohn Marino 	if (XVEC (part, i) != NULL)
417*e4b17023SJohn Marino 	  for (j = 0; j < XVECLEN (part, i); j++)
418*e4b17023SJohn Marino 	    remove_constraints (XVECEXP (part, i, j));
419*e4b17023SJohn Marino 	break;
420*e4b17023SJohn Marino       }
421*e4b17023SJohn Marino }
422*e4b17023SJohn Marino 
423*e4b17023SJohn Marino /* Process a top level rtx in some way, queuing as appropriate.  */
424*e4b17023SJohn Marino 
425*e4b17023SJohn Marino static void
process_rtx(rtx desc,int lineno)426*e4b17023SJohn Marino process_rtx (rtx desc, int lineno)
427*e4b17023SJohn Marino {
428*e4b17023SJohn Marino   switch (GET_CODE (desc))
429*e4b17023SJohn Marino     {
430*e4b17023SJohn Marino     case DEFINE_INSN:
431*e4b17023SJohn Marino       queue_pattern (desc, &define_insn_tail, read_md_filename, lineno);
432*e4b17023SJohn Marino       break;
433*e4b17023SJohn Marino 
434*e4b17023SJohn Marino     case DEFINE_COND_EXEC:
435*e4b17023SJohn Marino       queue_pattern (desc, &define_cond_exec_tail, read_md_filename, lineno);
436*e4b17023SJohn Marino       break;
437*e4b17023SJohn Marino 
438*e4b17023SJohn Marino     case DEFINE_ATTR:
439*e4b17023SJohn Marino     case DEFINE_ENUM_ATTR:
440*e4b17023SJohn Marino       queue_pattern (desc, &define_attr_tail, read_md_filename, lineno);
441*e4b17023SJohn Marino       break;
442*e4b17023SJohn Marino 
443*e4b17023SJohn Marino     case DEFINE_PREDICATE:
444*e4b17023SJohn Marino     case DEFINE_SPECIAL_PREDICATE:
445*e4b17023SJohn Marino       process_define_predicate (desc, lineno);
446*e4b17023SJohn Marino       /* Fall through.  */
447*e4b17023SJohn Marino 
448*e4b17023SJohn Marino     case DEFINE_CONSTRAINT:
449*e4b17023SJohn Marino     case DEFINE_REGISTER_CONSTRAINT:
450*e4b17023SJohn Marino     case DEFINE_MEMORY_CONSTRAINT:
451*e4b17023SJohn Marino     case DEFINE_ADDRESS_CONSTRAINT:
452*e4b17023SJohn Marino       queue_pattern (desc, &define_pred_tail, read_md_filename, lineno);
453*e4b17023SJohn Marino       break;
454*e4b17023SJohn Marino 
455*e4b17023SJohn Marino     case DEFINE_INSN_AND_SPLIT:
456*e4b17023SJohn Marino       {
457*e4b17023SJohn Marino 	const char *split_cond;
458*e4b17023SJohn Marino 	rtx split;
459*e4b17023SJohn Marino 	rtvec attr;
460*e4b17023SJohn Marino 	int i;
461*e4b17023SJohn Marino 	struct queue_elem *insn_elem;
462*e4b17023SJohn Marino 	struct queue_elem *split_elem;
463*e4b17023SJohn Marino 
464*e4b17023SJohn Marino 	/* Create a split with values from the insn_and_split.  */
465*e4b17023SJohn Marino 	split = rtx_alloc (DEFINE_SPLIT);
466*e4b17023SJohn Marino 
467*e4b17023SJohn Marino 	i = XVECLEN (desc, 1);
468*e4b17023SJohn Marino 	XVEC (split, 0) = rtvec_alloc (i);
469*e4b17023SJohn Marino 	while (--i >= 0)
470*e4b17023SJohn Marino 	  {
471*e4b17023SJohn Marino 	    XVECEXP (split, 0, i) = copy_rtx (XVECEXP (desc, 1, i));
472*e4b17023SJohn Marino 	    remove_constraints (XVECEXP (split, 0, i));
473*e4b17023SJohn Marino 	  }
474*e4b17023SJohn Marino 
475*e4b17023SJohn Marino 	/* If the split condition starts with "&&", append it to the
476*e4b17023SJohn Marino 	   insn condition to create the new split condition.  */
477*e4b17023SJohn Marino 	split_cond = XSTR (desc, 4);
478*e4b17023SJohn Marino 	if (split_cond[0] == '&' && split_cond[1] == '&')
479*e4b17023SJohn Marino 	  {
480*e4b17023SJohn Marino 	    copy_md_ptr_loc (split_cond + 2, split_cond);
481*e4b17023SJohn Marino 	    split_cond = join_c_conditions (XSTR (desc, 2), split_cond + 2);
482*e4b17023SJohn Marino 	  }
483*e4b17023SJohn Marino 	XSTR (split, 1) = split_cond;
484*e4b17023SJohn Marino 	XVEC (split, 2) = XVEC (desc, 5);
485*e4b17023SJohn Marino 	XSTR (split, 3) = XSTR (desc, 6);
486*e4b17023SJohn Marino 
487*e4b17023SJohn Marino 	/* Fix up the DEFINE_INSN.  */
488*e4b17023SJohn Marino 	attr = XVEC (desc, 7);
489*e4b17023SJohn Marino 	PUT_CODE (desc, DEFINE_INSN);
490*e4b17023SJohn Marino 	XVEC (desc, 4) = attr;
491*e4b17023SJohn Marino 
492*e4b17023SJohn Marino 	/* Queue them.  */
493*e4b17023SJohn Marino 	insn_elem
494*e4b17023SJohn Marino 	  = queue_pattern (desc, &define_insn_tail, read_md_filename,
495*e4b17023SJohn Marino 			   lineno);
496*e4b17023SJohn Marino 	split_elem
497*e4b17023SJohn Marino 	  = queue_pattern (split, &other_tail, read_md_filename, lineno);
498*e4b17023SJohn Marino 	insn_elem->split = split_elem;
499*e4b17023SJohn Marino 	break;
500*e4b17023SJohn Marino       }
501*e4b17023SJohn Marino 
502*e4b17023SJohn Marino     default:
503*e4b17023SJohn Marino       queue_pattern (desc, &other_tail, read_md_filename, lineno);
504*e4b17023SJohn Marino       break;
505*e4b17023SJohn Marino     }
506*e4b17023SJohn Marino }
507*e4b17023SJohn Marino 
508*e4b17023SJohn Marino /* Return true if attribute PREDICABLE is true for ELEM, which holds
509*e4b17023SJohn Marino    a DEFINE_INSN.  */
510*e4b17023SJohn Marino 
511*e4b17023SJohn Marino static int
is_predicable(struct queue_elem * elem)512*e4b17023SJohn Marino is_predicable (struct queue_elem *elem)
513*e4b17023SJohn Marino {
514*e4b17023SJohn Marino   rtvec vec = XVEC (elem->data, 4);
515*e4b17023SJohn Marino   const char *value;
516*e4b17023SJohn Marino   int i;
517*e4b17023SJohn Marino 
518*e4b17023SJohn Marino   if (! vec)
519*e4b17023SJohn Marino     return predicable_default;
520*e4b17023SJohn Marino 
521*e4b17023SJohn Marino   for (i = GET_NUM_ELEM (vec) - 1; i >= 0; --i)
522*e4b17023SJohn Marino     {
523*e4b17023SJohn Marino       rtx sub = RTVEC_ELT (vec, i);
524*e4b17023SJohn Marino       switch (GET_CODE (sub))
525*e4b17023SJohn Marino 	{
526*e4b17023SJohn Marino 	case SET_ATTR:
527*e4b17023SJohn Marino 	  if (strcmp (XSTR (sub, 0), "predicable") == 0)
528*e4b17023SJohn Marino 	    {
529*e4b17023SJohn Marino 	      value = XSTR (sub, 1);
530*e4b17023SJohn Marino 	      goto found;
531*e4b17023SJohn Marino 	    }
532*e4b17023SJohn Marino 	  break;
533*e4b17023SJohn Marino 
534*e4b17023SJohn Marino 	case SET_ATTR_ALTERNATIVE:
535*e4b17023SJohn Marino 	  if (strcmp (XSTR (sub, 0), "predicable") == 0)
536*e4b17023SJohn Marino 	    {
537*e4b17023SJohn Marino 	      error_with_line (elem->lineno,
538*e4b17023SJohn Marino 			       "multiple alternatives for `predicable'");
539*e4b17023SJohn Marino 	      return 0;
540*e4b17023SJohn Marino 	    }
541*e4b17023SJohn Marino 	  break;
542*e4b17023SJohn Marino 
543*e4b17023SJohn Marino 	case SET:
544*e4b17023SJohn Marino 	  if (GET_CODE (SET_DEST (sub)) != ATTR
545*e4b17023SJohn Marino 	      || strcmp (XSTR (SET_DEST (sub), 0), "predicable") != 0)
546*e4b17023SJohn Marino 	    break;
547*e4b17023SJohn Marino 	  sub = SET_SRC (sub);
548*e4b17023SJohn Marino 	  if (GET_CODE (sub) == CONST_STRING)
549*e4b17023SJohn Marino 	    {
550*e4b17023SJohn Marino 	      value = XSTR (sub, 0);
551*e4b17023SJohn Marino 	      goto found;
552*e4b17023SJohn Marino 	    }
553*e4b17023SJohn Marino 
554*e4b17023SJohn Marino 	  /* ??? It would be possible to handle this if we really tried.
555*e4b17023SJohn Marino 	     It's not easy though, and I'm not going to bother until it
556*e4b17023SJohn Marino 	     really proves necessary.  */
557*e4b17023SJohn Marino 	  error_with_line (elem->lineno,
558*e4b17023SJohn Marino 			   "non-constant value for `predicable'");
559*e4b17023SJohn Marino 	  return 0;
560*e4b17023SJohn Marino 
561*e4b17023SJohn Marino 	default:
562*e4b17023SJohn Marino 	  gcc_unreachable ();
563*e4b17023SJohn Marino 	}
564*e4b17023SJohn Marino     }
565*e4b17023SJohn Marino 
566*e4b17023SJohn Marino   return predicable_default;
567*e4b17023SJohn Marino 
568*e4b17023SJohn Marino  found:
569*e4b17023SJohn Marino   /* Find out which value we're looking at.  Multiple alternatives means at
570*e4b17023SJohn Marino      least one is predicable.  */
571*e4b17023SJohn Marino   if (strchr (value, ',') != NULL)
572*e4b17023SJohn Marino     return 1;
573*e4b17023SJohn Marino   if (strcmp (value, predicable_true) == 0)
574*e4b17023SJohn Marino     return 1;
575*e4b17023SJohn Marino   if (strcmp (value, predicable_false) == 0)
576*e4b17023SJohn Marino     return 0;
577*e4b17023SJohn Marino 
578*e4b17023SJohn Marino   error_with_line (elem->lineno,
579*e4b17023SJohn Marino 		   "unknown value `%s' for `predicable' attribute", value);
580*e4b17023SJohn Marino   return 0;
581*e4b17023SJohn Marino }
582*e4b17023SJohn Marino 
583*e4b17023SJohn Marino /* Examine the attribute "predicable"; discover its boolean values
584*e4b17023SJohn Marino    and its default.  */
585*e4b17023SJohn Marino 
586*e4b17023SJohn Marino static void
identify_predicable_attribute(void)587*e4b17023SJohn Marino identify_predicable_attribute (void)
588*e4b17023SJohn Marino {
589*e4b17023SJohn Marino   struct queue_elem *elem;
590*e4b17023SJohn Marino   char *p_true, *p_false;
591*e4b17023SJohn Marino   const char *value;
592*e4b17023SJohn Marino 
593*e4b17023SJohn Marino   /* Look for the DEFINE_ATTR for `predicable', which must exist.  */
594*e4b17023SJohn Marino   for (elem = define_attr_queue; elem ; elem = elem->next)
595*e4b17023SJohn Marino     if (strcmp (XSTR (elem->data, 0), "predicable") == 0)
596*e4b17023SJohn Marino       goto found;
597*e4b17023SJohn Marino 
598*e4b17023SJohn Marino   error_with_line (define_cond_exec_queue->lineno,
599*e4b17023SJohn Marino 		   "attribute `predicable' not defined");
600*e4b17023SJohn Marino   return;
601*e4b17023SJohn Marino 
602*e4b17023SJohn Marino  found:
603*e4b17023SJohn Marino   value = XSTR (elem->data, 1);
604*e4b17023SJohn Marino   p_false = xstrdup (value);
605*e4b17023SJohn Marino   p_true = strchr (p_false, ',');
606*e4b17023SJohn Marino   if (p_true == NULL || strchr (++p_true, ',') != NULL)
607*e4b17023SJohn Marino     {
608*e4b17023SJohn Marino       error_with_line (elem->lineno, "attribute `predicable' is not a boolean");
609*e4b17023SJohn Marino       free (p_false);
610*e4b17023SJohn Marino       return;
611*e4b17023SJohn Marino     }
612*e4b17023SJohn Marino   p_true[-1] = '\0';
613*e4b17023SJohn Marino 
614*e4b17023SJohn Marino   predicable_true = p_true;
615*e4b17023SJohn Marino   predicable_false = p_false;
616*e4b17023SJohn Marino 
617*e4b17023SJohn Marino   switch (GET_CODE (XEXP (elem->data, 2)))
618*e4b17023SJohn Marino     {
619*e4b17023SJohn Marino     case CONST_STRING:
620*e4b17023SJohn Marino       value = XSTR (XEXP (elem->data, 2), 0);
621*e4b17023SJohn Marino       break;
622*e4b17023SJohn Marino 
623*e4b17023SJohn Marino     case CONST:
624*e4b17023SJohn Marino       error_with_line (elem->lineno, "attribute `predicable' cannot be const");
625*e4b17023SJohn Marino       free (p_false);
626*e4b17023SJohn Marino       return;
627*e4b17023SJohn Marino 
628*e4b17023SJohn Marino     default:
629*e4b17023SJohn Marino       error_with_line (elem->lineno,
630*e4b17023SJohn Marino 		       "attribute `predicable' must have a constant default");
631*e4b17023SJohn Marino       free (p_false);
632*e4b17023SJohn Marino       return;
633*e4b17023SJohn Marino     }
634*e4b17023SJohn Marino 
635*e4b17023SJohn Marino   if (strcmp (value, p_true) == 0)
636*e4b17023SJohn Marino     predicable_default = 1;
637*e4b17023SJohn Marino   else if (strcmp (value, p_false) == 0)
638*e4b17023SJohn Marino     predicable_default = 0;
639*e4b17023SJohn Marino   else
640*e4b17023SJohn Marino     {
641*e4b17023SJohn Marino       error_with_line (elem->lineno,
642*e4b17023SJohn Marino 		       "unknown value `%s' for `predicable' attribute", value);
643*e4b17023SJohn Marino       free (p_false);
644*e4b17023SJohn Marino     }
645*e4b17023SJohn Marino }
646*e4b17023SJohn Marino 
647*e4b17023SJohn Marino /* Return the number of alternatives in constraint S.  */
648*e4b17023SJohn Marino 
649*e4b17023SJohn Marino static int
n_alternatives(const char * s)650*e4b17023SJohn Marino n_alternatives (const char *s)
651*e4b17023SJohn Marino {
652*e4b17023SJohn Marino   int n = 1;
653*e4b17023SJohn Marino 
654*e4b17023SJohn Marino   if (s)
655*e4b17023SJohn Marino     while (*s)
656*e4b17023SJohn Marino       n += (*s++ == ',');
657*e4b17023SJohn Marino 
658*e4b17023SJohn Marino   return n;
659*e4b17023SJohn Marino }
660*e4b17023SJohn Marino 
661*e4b17023SJohn Marino /* Determine how many alternatives there are in INSN, and how many
662*e4b17023SJohn Marino    operands.  */
663*e4b17023SJohn Marino 
664*e4b17023SJohn Marino static void
collect_insn_data(rtx pattern,int * palt,int * pmax)665*e4b17023SJohn Marino collect_insn_data (rtx pattern, int *palt, int *pmax)
666*e4b17023SJohn Marino {
667*e4b17023SJohn Marino   const char *fmt;
668*e4b17023SJohn Marino   enum rtx_code code;
669*e4b17023SJohn Marino   int i, j, len;
670*e4b17023SJohn Marino 
671*e4b17023SJohn Marino   code = GET_CODE (pattern);
672*e4b17023SJohn Marino   switch (code)
673*e4b17023SJohn Marino     {
674*e4b17023SJohn Marino     case MATCH_OPERAND:
675*e4b17023SJohn Marino       i = n_alternatives (XSTR (pattern, 2));
676*e4b17023SJohn Marino       *palt = (i > *palt ? i : *palt);
677*e4b17023SJohn Marino       /* Fall through.  */
678*e4b17023SJohn Marino 
679*e4b17023SJohn Marino     case MATCH_OPERATOR:
680*e4b17023SJohn Marino     case MATCH_SCRATCH:
681*e4b17023SJohn Marino     case MATCH_PARALLEL:
682*e4b17023SJohn Marino       i = XINT (pattern, 0);
683*e4b17023SJohn Marino       if (i > *pmax)
684*e4b17023SJohn Marino 	*pmax = i;
685*e4b17023SJohn Marino       break;
686*e4b17023SJohn Marino 
687*e4b17023SJohn Marino     default:
688*e4b17023SJohn Marino       break;
689*e4b17023SJohn Marino     }
690*e4b17023SJohn Marino 
691*e4b17023SJohn Marino   fmt = GET_RTX_FORMAT (code);
692*e4b17023SJohn Marino   len = GET_RTX_LENGTH (code);
693*e4b17023SJohn Marino   for (i = 0; i < len; i++)
694*e4b17023SJohn Marino     {
695*e4b17023SJohn Marino       switch (fmt[i])
696*e4b17023SJohn Marino 	{
697*e4b17023SJohn Marino 	case 'e': case 'u':
698*e4b17023SJohn Marino 	  collect_insn_data (XEXP (pattern, i), palt, pmax);
699*e4b17023SJohn Marino 	  break;
700*e4b17023SJohn Marino 
701*e4b17023SJohn Marino 	case 'V':
702*e4b17023SJohn Marino 	  if (XVEC (pattern, i) == NULL)
703*e4b17023SJohn Marino 	    break;
704*e4b17023SJohn Marino 	  /* Fall through.  */
705*e4b17023SJohn Marino 	case 'E':
706*e4b17023SJohn Marino 	  for (j = XVECLEN (pattern, i) - 1; j >= 0; --j)
707*e4b17023SJohn Marino 	    collect_insn_data (XVECEXP (pattern, i, j), palt, pmax);
708*e4b17023SJohn Marino 	  break;
709*e4b17023SJohn Marino 
710*e4b17023SJohn Marino 	case 'i': case 'w': case '0': case 's': case 'S': case 'T':
711*e4b17023SJohn Marino 	  break;
712*e4b17023SJohn Marino 
713*e4b17023SJohn Marino 	default:
714*e4b17023SJohn Marino 	  gcc_unreachable ();
715*e4b17023SJohn Marino 	}
716*e4b17023SJohn Marino     }
717*e4b17023SJohn Marino }
718*e4b17023SJohn Marino 
719*e4b17023SJohn Marino static rtx
alter_predicate_for_insn(rtx pattern,int alt,int max_op,int lineno)720*e4b17023SJohn Marino alter_predicate_for_insn (rtx pattern, int alt, int max_op, int lineno)
721*e4b17023SJohn Marino {
722*e4b17023SJohn Marino   const char *fmt;
723*e4b17023SJohn Marino   enum rtx_code code;
724*e4b17023SJohn Marino   int i, j, len;
725*e4b17023SJohn Marino 
726*e4b17023SJohn Marino   code = GET_CODE (pattern);
727*e4b17023SJohn Marino   switch (code)
728*e4b17023SJohn Marino     {
729*e4b17023SJohn Marino     case MATCH_OPERAND:
730*e4b17023SJohn Marino       {
731*e4b17023SJohn Marino 	const char *c = XSTR (pattern, 2);
732*e4b17023SJohn Marino 
733*e4b17023SJohn Marino 	if (n_alternatives (c) != 1)
734*e4b17023SJohn Marino 	  {
735*e4b17023SJohn Marino 	    error_with_line (lineno, "too many alternatives for operand %d",
736*e4b17023SJohn Marino 			     XINT (pattern, 0));
737*e4b17023SJohn Marino 	    return NULL;
738*e4b17023SJohn Marino 	  }
739*e4b17023SJohn Marino 
740*e4b17023SJohn Marino 	/* Replicate C as needed to fill out ALT alternatives.  */
741*e4b17023SJohn Marino 	if (c && *c && alt > 1)
742*e4b17023SJohn Marino 	  {
743*e4b17023SJohn Marino 	    size_t c_len = strlen (c);
744*e4b17023SJohn Marino 	    size_t len = alt * (c_len + 1);
745*e4b17023SJohn Marino 	    char *new_c = XNEWVEC(char, len);
746*e4b17023SJohn Marino 
747*e4b17023SJohn Marino 	    memcpy (new_c, c, c_len);
748*e4b17023SJohn Marino 	    for (i = 1; i < alt; ++i)
749*e4b17023SJohn Marino 	      {
750*e4b17023SJohn Marino 		new_c[i * (c_len + 1) - 1] = ',';
751*e4b17023SJohn Marino 		memcpy (&new_c[i * (c_len + 1)], c, c_len);
752*e4b17023SJohn Marino 	      }
753*e4b17023SJohn Marino 	    new_c[len - 1] = '\0';
754*e4b17023SJohn Marino 	    XSTR (pattern, 2) = new_c;
755*e4b17023SJohn Marino 	  }
756*e4b17023SJohn Marino       }
757*e4b17023SJohn Marino       /* Fall through.  */
758*e4b17023SJohn Marino 
759*e4b17023SJohn Marino     case MATCH_OPERATOR:
760*e4b17023SJohn Marino     case MATCH_SCRATCH:
761*e4b17023SJohn Marino     case MATCH_PARALLEL:
762*e4b17023SJohn Marino       XINT (pattern, 0) += max_op;
763*e4b17023SJohn Marino       break;
764*e4b17023SJohn Marino 
765*e4b17023SJohn Marino     default:
766*e4b17023SJohn Marino       break;
767*e4b17023SJohn Marino     }
768*e4b17023SJohn Marino 
769*e4b17023SJohn Marino   fmt = GET_RTX_FORMAT (code);
770*e4b17023SJohn Marino   len = GET_RTX_LENGTH (code);
771*e4b17023SJohn Marino   for (i = 0; i < len; i++)
772*e4b17023SJohn Marino     {
773*e4b17023SJohn Marino       rtx r;
774*e4b17023SJohn Marino 
775*e4b17023SJohn Marino       switch (fmt[i])
776*e4b17023SJohn Marino 	{
777*e4b17023SJohn Marino 	case 'e': case 'u':
778*e4b17023SJohn Marino 	  r = alter_predicate_for_insn (XEXP (pattern, i), alt,
779*e4b17023SJohn Marino 					max_op, lineno);
780*e4b17023SJohn Marino 	  if (r == NULL)
781*e4b17023SJohn Marino 	    return r;
782*e4b17023SJohn Marino 	  break;
783*e4b17023SJohn Marino 
784*e4b17023SJohn Marino 	case 'E':
785*e4b17023SJohn Marino 	  for (j = XVECLEN (pattern, i) - 1; j >= 0; --j)
786*e4b17023SJohn Marino 	    {
787*e4b17023SJohn Marino 	      r = alter_predicate_for_insn (XVECEXP (pattern, i, j),
788*e4b17023SJohn Marino 					    alt, max_op, lineno);
789*e4b17023SJohn Marino 	      if (r == NULL)
790*e4b17023SJohn Marino 		return r;
791*e4b17023SJohn Marino 	    }
792*e4b17023SJohn Marino 	  break;
793*e4b17023SJohn Marino 
794*e4b17023SJohn Marino 	case 'i': case 'w': case '0': case 's':
795*e4b17023SJohn Marino 	  break;
796*e4b17023SJohn Marino 
797*e4b17023SJohn Marino 	default:
798*e4b17023SJohn Marino 	  gcc_unreachable ();
799*e4b17023SJohn Marino 	}
800*e4b17023SJohn Marino     }
801*e4b17023SJohn Marino 
802*e4b17023SJohn Marino   return pattern;
803*e4b17023SJohn Marino }
804*e4b17023SJohn Marino 
805*e4b17023SJohn Marino static const char *
alter_test_for_insn(struct queue_elem * ce_elem,struct queue_elem * insn_elem)806*e4b17023SJohn Marino alter_test_for_insn (struct queue_elem *ce_elem,
807*e4b17023SJohn Marino 		     struct queue_elem *insn_elem)
808*e4b17023SJohn Marino {
809*e4b17023SJohn Marino   return join_c_conditions (XSTR (ce_elem->data, 1),
810*e4b17023SJohn Marino 			    XSTR (insn_elem->data, 2));
811*e4b17023SJohn Marino }
812*e4b17023SJohn Marino 
813*e4b17023SJohn Marino /* Modify VAL, which is an attribute expression for the "enabled" attribute,
814*e4b17023SJohn Marino    to take "ce_enabled" into account.  Return the new expression.  */
815*e4b17023SJohn Marino static rtx
modify_attr_enabled_ce(rtx val)816*e4b17023SJohn Marino modify_attr_enabled_ce (rtx val)
817*e4b17023SJohn Marino {
818*e4b17023SJohn Marino   rtx eq_attr, str;
819*e4b17023SJohn Marino   rtx ite;
820*e4b17023SJohn Marino   eq_attr = rtx_alloc (EQ_ATTR);
821*e4b17023SJohn Marino   ite = rtx_alloc (IF_THEN_ELSE);
822*e4b17023SJohn Marino   str = rtx_alloc (CONST_STRING);
823*e4b17023SJohn Marino 
824*e4b17023SJohn Marino   XSTR (eq_attr, 0) = "ce_enabled";
825*e4b17023SJohn Marino   XSTR (eq_attr, 1) = "yes";
826*e4b17023SJohn Marino   XSTR (str, 0) = "no";
827*e4b17023SJohn Marino   XEXP (ite, 0) = eq_attr;
828*e4b17023SJohn Marino   XEXP (ite, 1) = val;
829*e4b17023SJohn Marino   XEXP (ite, 2) = str;
830*e4b17023SJohn Marino 
831*e4b17023SJohn Marino   return ite;
832*e4b17023SJohn Marino }
833*e4b17023SJohn Marino 
834*e4b17023SJohn Marino /* Alter the attribute vector of INSN, which is a COND_EXEC variant created
835*e4b17023SJohn Marino    from a define_insn pattern.  We must modify the "predicable" attribute
836*e4b17023SJohn Marino    to be named "ce_enabled", and also change any "enabled" attribute that's
837*e4b17023SJohn Marino    present so that it takes ce_enabled into account.
838*e4b17023SJohn Marino    We rely on the fact that INSN was created with copy_rtx, and modify data
839*e4b17023SJohn Marino    in-place.  */
840*e4b17023SJohn Marino 
841*e4b17023SJohn Marino static void
alter_attrs_for_insn(rtx insn)842*e4b17023SJohn Marino alter_attrs_for_insn (rtx insn)
843*e4b17023SJohn Marino {
844*e4b17023SJohn Marino   static bool global_changes_made = false;
845*e4b17023SJohn Marino   rtvec vec = XVEC (insn, 4);
846*e4b17023SJohn Marino   rtvec new_vec;
847*e4b17023SJohn Marino   rtx val, set;
848*e4b17023SJohn Marino   int num_elem;
849*e4b17023SJohn Marino   int predicable_idx = -1;
850*e4b17023SJohn Marino   int enabled_idx = -1;
851*e4b17023SJohn Marino   int i;
852*e4b17023SJohn Marino 
853*e4b17023SJohn Marino   if (! vec)
854*e4b17023SJohn Marino     return;
855*e4b17023SJohn Marino 
856*e4b17023SJohn Marino   num_elem = GET_NUM_ELEM (vec);
857*e4b17023SJohn Marino   for (i = num_elem - 1; i >= 0; --i)
858*e4b17023SJohn Marino     {
859*e4b17023SJohn Marino       rtx sub = RTVEC_ELT (vec, i);
860*e4b17023SJohn Marino       switch (GET_CODE (sub))
861*e4b17023SJohn Marino 	{
862*e4b17023SJohn Marino 	case SET_ATTR:
863*e4b17023SJohn Marino 	  if (strcmp (XSTR (sub, 0), "predicable") == 0)
864*e4b17023SJohn Marino 	    {
865*e4b17023SJohn Marino 	      predicable_idx = i;
866*e4b17023SJohn Marino 	      XSTR (sub, 0) = "ce_enabled";
867*e4b17023SJohn Marino 	    }
868*e4b17023SJohn Marino 	  else if (strcmp (XSTR (sub, 0), "enabled") == 0)
869*e4b17023SJohn Marino 	    {
870*e4b17023SJohn Marino 	      enabled_idx = i;
871*e4b17023SJohn Marino 	      XSTR (sub, 0) = "nonce_enabled";
872*e4b17023SJohn Marino 	    }
873*e4b17023SJohn Marino 	  break;
874*e4b17023SJohn Marino 
875*e4b17023SJohn Marino 	case SET_ATTR_ALTERNATIVE:
876*e4b17023SJohn Marino 	  if (strcmp (XSTR (sub, 0), "predicable") == 0)
877*e4b17023SJohn Marino 	    /* We already give an error elsewhere.  */
878*e4b17023SJohn Marino 	    return;
879*e4b17023SJohn Marino 	  else if (strcmp (XSTR (sub, 0), "enabled") == 0)
880*e4b17023SJohn Marino 	    {
881*e4b17023SJohn Marino 	      enabled_idx = i;
882*e4b17023SJohn Marino 	      XSTR (sub, 0) = "nonce_enabled";
883*e4b17023SJohn Marino 	    }
884*e4b17023SJohn Marino 	  break;
885*e4b17023SJohn Marino 
886*e4b17023SJohn Marino 	case SET:
887*e4b17023SJohn Marino 	  if (GET_CODE (SET_DEST (sub)) != ATTR)
888*e4b17023SJohn Marino 	    break;
889*e4b17023SJohn Marino 	  if (strcmp (XSTR (SET_DEST (sub), 0), "predicable") == 0)
890*e4b17023SJohn Marino 	    {
891*e4b17023SJohn Marino 	      sub = SET_SRC (sub);
892*e4b17023SJohn Marino 	      if (GET_CODE (sub) == CONST_STRING)
893*e4b17023SJohn Marino 		{
894*e4b17023SJohn Marino 		  predicable_idx = i;
895*e4b17023SJohn Marino 		  XSTR (sub, 0) = "ce_enabled";
896*e4b17023SJohn Marino 		}
897*e4b17023SJohn Marino 	      else
898*e4b17023SJohn Marino 		/* We already give an error elsewhere.  */
899*e4b17023SJohn Marino 		return;
900*e4b17023SJohn Marino 	      break;
901*e4b17023SJohn Marino 	    }
902*e4b17023SJohn Marino 	  if (strcmp (XSTR (SET_DEST (sub), 0), "enabled") == 0)
903*e4b17023SJohn Marino 	    {
904*e4b17023SJohn Marino 	      enabled_idx = i;
905*e4b17023SJohn Marino 	      XSTR (SET_DEST (sub), 0) = "nonce_enabled";
906*e4b17023SJohn Marino 	    }
907*e4b17023SJohn Marino 	  break;
908*e4b17023SJohn Marino 
909*e4b17023SJohn Marino 	default:
910*e4b17023SJohn Marino 	  gcc_unreachable ();
911*e4b17023SJohn Marino 	}
912*e4b17023SJohn Marino     }
913*e4b17023SJohn Marino   if (predicable_idx == -1)
914*e4b17023SJohn Marino     return;
915*e4b17023SJohn Marino 
916*e4b17023SJohn Marino   if (!global_changes_made)
917*e4b17023SJohn Marino     {
918*e4b17023SJohn Marino       struct queue_elem *elem;
919*e4b17023SJohn Marino 
920*e4b17023SJohn Marino       global_changes_made = true;
921*e4b17023SJohn Marino       add_define_attr ("ce_enabled");
922*e4b17023SJohn Marino       add_define_attr ("nonce_enabled");
923*e4b17023SJohn Marino 
924*e4b17023SJohn Marino       for (elem = define_attr_queue; elem ; elem = elem->next)
925*e4b17023SJohn Marino 	if (strcmp (XSTR (elem->data, 0), "enabled") == 0)
926*e4b17023SJohn Marino 	  {
927*e4b17023SJohn Marino 	    XEXP (elem->data, 2)
928*e4b17023SJohn Marino 	      = modify_attr_enabled_ce (XEXP (elem->data, 2));
929*e4b17023SJohn Marino 	  }
930*e4b17023SJohn Marino     }
931*e4b17023SJohn Marino   if (enabled_idx == -1)
932*e4b17023SJohn Marino     return;
933*e4b17023SJohn Marino 
934*e4b17023SJohn Marino   new_vec = rtvec_alloc (num_elem + 1);
935*e4b17023SJohn Marino   for (i = 0; i < num_elem; i++)
936*e4b17023SJohn Marino     RTVEC_ELT (new_vec, i) = RTVEC_ELT (vec, i);
937*e4b17023SJohn Marino   val = rtx_alloc (IF_THEN_ELSE);
938*e4b17023SJohn Marino   XEXP (val, 0) = rtx_alloc (EQ_ATTR);
939*e4b17023SJohn Marino   XEXP (val, 1) = rtx_alloc (CONST_STRING);
940*e4b17023SJohn Marino   XEXP (val, 2) = rtx_alloc (CONST_STRING);
941*e4b17023SJohn Marino   XSTR (XEXP (val, 0), 0) = "nonce_enabled";
942*e4b17023SJohn Marino   XSTR (XEXP (val, 0), 1) = "yes";
943*e4b17023SJohn Marino   XSTR (XEXP (val, 1), 0) = "yes";
944*e4b17023SJohn Marino   XSTR (XEXP (val, 2), 0) = "no";
945*e4b17023SJohn Marino   set = rtx_alloc (SET);
946*e4b17023SJohn Marino   SET_DEST (set) = rtx_alloc (ATTR);
947*e4b17023SJohn Marino   XSTR (SET_DEST (set), 0) = "enabled";
948*e4b17023SJohn Marino   SET_SRC (set) = modify_attr_enabled_ce (val);
949*e4b17023SJohn Marino   RTVEC_ELT (new_vec, i) = set;
950*e4b17023SJohn Marino   XVEC (insn, 4) = new_vec;
951*e4b17023SJohn Marino }
952*e4b17023SJohn Marino 
953*e4b17023SJohn Marino /* Adjust all of the operand numbers in SRC to match the shift they'll
954*e4b17023SJohn Marino    get from an operand displacement of DISP.  Return a pointer after the
955*e4b17023SJohn Marino    adjusted string.  */
956*e4b17023SJohn Marino 
957*e4b17023SJohn Marino static char *
shift_output_template(char * dest,const char * src,int disp)958*e4b17023SJohn Marino shift_output_template (char *dest, const char *src, int disp)
959*e4b17023SJohn Marino {
960*e4b17023SJohn Marino   while (*src)
961*e4b17023SJohn Marino     {
962*e4b17023SJohn Marino       char c = *src++;
963*e4b17023SJohn Marino       *dest++ = c;
964*e4b17023SJohn Marino       if (c == '%')
965*e4b17023SJohn Marino 	{
966*e4b17023SJohn Marino 	  c = *src++;
967*e4b17023SJohn Marino 	  if (ISDIGIT ((unsigned char) c))
968*e4b17023SJohn Marino 	    c += disp;
969*e4b17023SJohn Marino 	  else if (ISALPHA (c))
970*e4b17023SJohn Marino 	    {
971*e4b17023SJohn Marino 	      *dest++ = c;
972*e4b17023SJohn Marino 	      c = *src++ + disp;
973*e4b17023SJohn Marino 	    }
974*e4b17023SJohn Marino 	  *dest++ = c;
975*e4b17023SJohn Marino 	}
976*e4b17023SJohn Marino     }
977*e4b17023SJohn Marino 
978*e4b17023SJohn Marino   return dest;
979*e4b17023SJohn Marino }
980*e4b17023SJohn Marino 
981*e4b17023SJohn Marino static const char *
alter_output_for_insn(struct queue_elem * ce_elem,struct queue_elem * insn_elem,int alt,int max_op)982*e4b17023SJohn Marino alter_output_for_insn (struct queue_elem *ce_elem,
983*e4b17023SJohn Marino 		       struct queue_elem *insn_elem,
984*e4b17023SJohn Marino 		       int alt, int max_op)
985*e4b17023SJohn Marino {
986*e4b17023SJohn Marino   const char *ce_out, *insn_out;
987*e4b17023SJohn Marino   char *result, *p;
988*e4b17023SJohn Marino   size_t len, ce_len, insn_len;
989*e4b17023SJohn Marino 
990*e4b17023SJohn Marino   /* ??? Could coordinate with genoutput to not duplicate code here.  */
991*e4b17023SJohn Marino 
992*e4b17023SJohn Marino   ce_out = XSTR (ce_elem->data, 2);
993*e4b17023SJohn Marino   insn_out = XTMPL (insn_elem->data, 3);
994*e4b17023SJohn Marino   if (!ce_out || *ce_out == '\0')
995*e4b17023SJohn Marino     return insn_out;
996*e4b17023SJohn Marino 
997*e4b17023SJohn Marino   ce_len = strlen (ce_out);
998*e4b17023SJohn Marino   insn_len = strlen (insn_out);
999*e4b17023SJohn Marino 
1000*e4b17023SJohn Marino   if (*insn_out == '*')
1001*e4b17023SJohn Marino     /* You must take care of the predicate yourself.  */
1002*e4b17023SJohn Marino     return insn_out;
1003*e4b17023SJohn Marino 
1004*e4b17023SJohn Marino   if (*insn_out == '@')
1005*e4b17023SJohn Marino     {
1006*e4b17023SJohn Marino       len = (ce_len + 1) * alt + insn_len + 1;
1007*e4b17023SJohn Marino       p = result = XNEWVEC(char, len);
1008*e4b17023SJohn Marino 
1009*e4b17023SJohn Marino       do
1010*e4b17023SJohn Marino 	{
1011*e4b17023SJohn Marino 	  do
1012*e4b17023SJohn Marino 	    *p++ = *insn_out++;
1013*e4b17023SJohn Marino 	  while (ISSPACE ((unsigned char) *insn_out));
1014*e4b17023SJohn Marino 
1015*e4b17023SJohn Marino 	  if (*insn_out != '#')
1016*e4b17023SJohn Marino 	    {
1017*e4b17023SJohn Marino 	      p = shift_output_template (p, ce_out, max_op);
1018*e4b17023SJohn Marino 	      *p++ = ' ';
1019*e4b17023SJohn Marino 	    }
1020*e4b17023SJohn Marino 
1021*e4b17023SJohn Marino 	  do
1022*e4b17023SJohn Marino 	    *p++ = *insn_out++;
1023*e4b17023SJohn Marino 	  while (*insn_out && *insn_out != '\n');
1024*e4b17023SJohn Marino 	}
1025*e4b17023SJohn Marino       while (*insn_out);
1026*e4b17023SJohn Marino       *p = '\0';
1027*e4b17023SJohn Marino     }
1028*e4b17023SJohn Marino   else
1029*e4b17023SJohn Marino     {
1030*e4b17023SJohn Marino       len = ce_len + 1 + insn_len + 1;
1031*e4b17023SJohn Marino       result = XNEWVEC (char, len);
1032*e4b17023SJohn Marino 
1033*e4b17023SJohn Marino       p = shift_output_template (result, ce_out, max_op);
1034*e4b17023SJohn Marino       *p++ = ' ';
1035*e4b17023SJohn Marino       memcpy (p, insn_out, insn_len + 1);
1036*e4b17023SJohn Marino     }
1037*e4b17023SJohn Marino 
1038*e4b17023SJohn Marino   return result;
1039*e4b17023SJohn Marino }
1040*e4b17023SJohn Marino 
1041*e4b17023SJohn Marino /* Replicate insns as appropriate for the given DEFINE_COND_EXEC.  */
1042*e4b17023SJohn Marino 
1043*e4b17023SJohn Marino static void
process_one_cond_exec(struct queue_elem * ce_elem)1044*e4b17023SJohn Marino process_one_cond_exec (struct queue_elem *ce_elem)
1045*e4b17023SJohn Marino {
1046*e4b17023SJohn Marino   struct queue_elem *insn_elem;
1047*e4b17023SJohn Marino   for (insn_elem = define_insn_queue; insn_elem ; insn_elem = insn_elem->next)
1048*e4b17023SJohn Marino     {
1049*e4b17023SJohn Marino       int alternatives, max_operand;
1050*e4b17023SJohn Marino       rtx pred, insn, pattern, split;
1051*e4b17023SJohn Marino       char *new_name;
1052*e4b17023SJohn Marino       int i;
1053*e4b17023SJohn Marino 
1054*e4b17023SJohn Marino       if (! is_predicable (insn_elem))
1055*e4b17023SJohn Marino 	continue;
1056*e4b17023SJohn Marino 
1057*e4b17023SJohn Marino       alternatives = 1;
1058*e4b17023SJohn Marino       max_operand = -1;
1059*e4b17023SJohn Marino       collect_insn_data (insn_elem->data, &alternatives, &max_operand);
1060*e4b17023SJohn Marino       max_operand += 1;
1061*e4b17023SJohn Marino 
1062*e4b17023SJohn Marino       if (XVECLEN (ce_elem->data, 0) != 1)
1063*e4b17023SJohn Marino 	{
1064*e4b17023SJohn Marino 	  error_with_line (ce_elem->lineno, "too many patterns in predicate");
1065*e4b17023SJohn Marino 	  return;
1066*e4b17023SJohn Marino 	}
1067*e4b17023SJohn Marino 
1068*e4b17023SJohn Marino       pred = copy_rtx (XVECEXP (ce_elem->data, 0, 0));
1069*e4b17023SJohn Marino       pred = alter_predicate_for_insn (pred, alternatives, max_operand,
1070*e4b17023SJohn Marino 				       ce_elem->lineno);
1071*e4b17023SJohn Marino       if (pred == NULL)
1072*e4b17023SJohn Marino 	return;
1073*e4b17023SJohn Marino 
1074*e4b17023SJohn Marino       /* Construct a new pattern for the new insn.  */
1075*e4b17023SJohn Marino       insn = copy_rtx (insn_elem->data);
1076*e4b17023SJohn Marino       new_name = XNEWVAR (char, strlen XSTR (insn_elem->data, 0) + 4);
1077*e4b17023SJohn Marino       sprintf (new_name, "*p %s", XSTR (insn_elem->data, 0));
1078*e4b17023SJohn Marino       XSTR (insn, 0) = new_name;
1079*e4b17023SJohn Marino       pattern = rtx_alloc (COND_EXEC);
1080*e4b17023SJohn Marino       XEXP (pattern, 0) = pred;
1081*e4b17023SJohn Marino       if (XVECLEN (insn, 1) == 1)
1082*e4b17023SJohn Marino 	{
1083*e4b17023SJohn Marino 	  XEXP (pattern, 1) = XVECEXP (insn, 1, 0);
1084*e4b17023SJohn Marino 	  XVECEXP (insn, 1, 0) = pattern;
1085*e4b17023SJohn Marino 	  PUT_NUM_ELEM (XVEC (insn, 1), 1);
1086*e4b17023SJohn Marino 	}
1087*e4b17023SJohn Marino       else
1088*e4b17023SJohn Marino 	{
1089*e4b17023SJohn Marino 	  XEXP (pattern, 1) = rtx_alloc (PARALLEL);
1090*e4b17023SJohn Marino 	  XVEC (XEXP (pattern, 1), 0) = XVEC (insn, 1);
1091*e4b17023SJohn Marino 	  XVEC (insn, 1) = rtvec_alloc (1);
1092*e4b17023SJohn Marino 	  XVECEXP (insn, 1, 0) = pattern;
1093*e4b17023SJohn Marino 	}
1094*e4b17023SJohn Marino 
1095*e4b17023SJohn Marino       XSTR (insn, 2) = alter_test_for_insn (ce_elem, insn_elem);
1096*e4b17023SJohn Marino       XTMPL (insn, 3) = alter_output_for_insn (ce_elem, insn_elem,
1097*e4b17023SJohn Marino 					      alternatives, max_operand);
1098*e4b17023SJohn Marino       alter_attrs_for_insn (insn);
1099*e4b17023SJohn Marino 
1100*e4b17023SJohn Marino       /* Put the new pattern on the `other' list so that it
1101*e4b17023SJohn Marino 	 (a) is not reprocessed by other define_cond_exec patterns
1102*e4b17023SJohn Marino 	 (b) appears after all normal define_insn patterns.
1103*e4b17023SJohn Marino 
1104*e4b17023SJohn Marino 	 ??? B is debatable.  If one has normal insns that match
1105*e4b17023SJohn Marino 	 cond_exec patterns, they will be preferred over these
1106*e4b17023SJohn Marino 	 generated patterns.  Whether this matters in practice, or if
1107*e4b17023SJohn Marino 	 it's a good thing, or whether we should thread these new
1108*e4b17023SJohn Marino 	 patterns into the define_insn chain just after their generator
1109*e4b17023SJohn Marino 	 is something we'll have to experiment with.  */
1110*e4b17023SJohn Marino 
1111*e4b17023SJohn Marino       queue_pattern (insn, &other_tail, insn_elem->filename,
1112*e4b17023SJohn Marino 		     insn_elem->lineno);
1113*e4b17023SJohn Marino 
1114*e4b17023SJohn Marino       if (!insn_elem->split)
1115*e4b17023SJohn Marino 	continue;
1116*e4b17023SJohn Marino 
1117*e4b17023SJohn Marino       /* If the original insn came from a define_insn_and_split,
1118*e4b17023SJohn Marino 	 generate a new split to handle the predicated insn.  */
1119*e4b17023SJohn Marino       split = copy_rtx (insn_elem->split->data);
1120*e4b17023SJohn Marino       /* Predicate the pattern matched by the split.  */
1121*e4b17023SJohn Marino       pattern = rtx_alloc (COND_EXEC);
1122*e4b17023SJohn Marino       XEXP (pattern, 0) = pred;
1123*e4b17023SJohn Marino       if (XVECLEN (split, 0) == 1)
1124*e4b17023SJohn Marino 	{
1125*e4b17023SJohn Marino 	  XEXP (pattern, 1) = XVECEXP (split, 0, 0);
1126*e4b17023SJohn Marino 	  XVECEXP (split, 0, 0) = pattern;
1127*e4b17023SJohn Marino 	  PUT_NUM_ELEM (XVEC (split, 0), 1);
1128*e4b17023SJohn Marino 	}
1129*e4b17023SJohn Marino       else
1130*e4b17023SJohn Marino 	{
1131*e4b17023SJohn Marino 	  XEXP (pattern, 1) = rtx_alloc (PARALLEL);
1132*e4b17023SJohn Marino 	  XVEC (XEXP (pattern, 1), 0) = XVEC (split, 0);
1133*e4b17023SJohn Marino 	  XVEC (split, 0) = rtvec_alloc (1);
1134*e4b17023SJohn Marino 	  XVECEXP (split, 0, 0) = pattern;
1135*e4b17023SJohn Marino 	}
1136*e4b17023SJohn Marino       /* Predicate all of the insns generated by the split.  */
1137*e4b17023SJohn Marino       for (i = 0; i < XVECLEN (split, 2); i++)
1138*e4b17023SJohn Marino 	{
1139*e4b17023SJohn Marino 	  pattern = rtx_alloc (COND_EXEC);
1140*e4b17023SJohn Marino 	  XEXP (pattern, 0) = pred;
1141*e4b17023SJohn Marino 	  XEXP (pattern, 1) = XVECEXP (split, 2, i);
1142*e4b17023SJohn Marino 	  XVECEXP (split, 2, i) = pattern;
1143*e4b17023SJohn Marino 	}
1144*e4b17023SJohn Marino       /* Add the new split to the queue.  */
1145*e4b17023SJohn Marino       queue_pattern (split, &other_tail, read_md_filename,
1146*e4b17023SJohn Marino 		     insn_elem->split->lineno);
1147*e4b17023SJohn Marino     }
1148*e4b17023SJohn Marino }
1149*e4b17023SJohn Marino 
1150*e4b17023SJohn Marino /* If we have any DEFINE_COND_EXEC patterns, expand the DEFINE_INSN
1151*e4b17023SJohn Marino    patterns appropriately.  */
1152*e4b17023SJohn Marino 
1153*e4b17023SJohn Marino static void
process_define_cond_exec(void)1154*e4b17023SJohn Marino process_define_cond_exec (void)
1155*e4b17023SJohn Marino {
1156*e4b17023SJohn Marino   struct queue_elem *elem;
1157*e4b17023SJohn Marino 
1158*e4b17023SJohn Marino   identify_predicable_attribute ();
1159*e4b17023SJohn Marino   if (have_error)
1160*e4b17023SJohn Marino     return;
1161*e4b17023SJohn Marino 
1162*e4b17023SJohn Marino   for (elem = define_cond_exec_queue; elem ; elem = elem->next)
1163*e4b17023SJohn Marino     process_one_cond_exec (elem);
1164*e4b17023SJohn Marino }
1165*e4b17023SJohn Marino 
1166*e4b17023SJohn Marino /* A read_md_files callback for reading an rtx.  */
1167*e4b17023SJohn Marino 
1168*e4b17023SJohn Marino static void
rtx_handle_directive(int lineno,const char * rtx_name)1169*e4b17023SJohn Marino rtx_handle_directive (int lineno, const char *rtx_name)
1170*e4b17023SJohn Marino {
1171*e4b17023SJohn Marino   rtx queue, x;
1172*e4b17023SJohn Marino 
1173*e4b17023SJohn Marino   if (read_rtx (rtx_name, &queue))
1174*e4b17023SJohn Marino     for (x = queue; x; x = XEXP (x, 1))
1175*e4b17023SJohn Marino       process_rtx (XEXP (x, 0), lineno);
1176*e4b17023SJohn Marino }
1177*e4b17023SJohn Marino 
1178*e4b17023SJohn Marino /* Comparison function for the mnemonic hash table.  */
1179*e4b17023SJohn Marino 
1180*e4b17023SJohn Marino static int
htab_eq_string(const void * s1,const void * s2)1181*e4b17023SJohn Marino htab_eq_string (const void *s1, const void *s2)
1182*e4b17023SJohn Marino {
1183*e4b17023SJohn Marino   return strcmp ((const char*)s1, (const char*)s2) == 0;
1184*e4b17023SJohn Marino }
1185*e4b17023SJohn Marino 
1186*e4b17023SJohn Marino /* Add mnemonic STR with length LEN to the mnemonic hash table
1187*e4b17023SJohn Marino    MNEMONIC_HTAB.  A trailing zero end character is appendend to STR
1188*e4b17023SJohn Marino    and a permanent heap copy of STR is created.  */
1189*e4b17023SJohn Marino 
1190*e4b17023SJohn Marino static void
add_mnemonic_string(htab_t mnemonic_htab,const char * str,int len)1191*e4b17023SJohn Marino add_mnemonic_string (htab_t mnemonic_htab, const char *str, int len)
1192*e4b17023SJohn Marino {
1193*e4b17023SJohn Marino   char *new_str;
1194*e4b17023SJohn Marino   void **slot;
1195*e4b17023SJohn Marino   char *str_zero = (char*)alloca (len + 1);
1196*e4b17023SJohn Marino 
1197*e4b17023SJohn Marino   memcpy (str_zero, str, len);
1198*e4b17023SJohn Marino   str_zero[len] = '\0';
1199*e4b17023SJohn Marino 
1200*e4b17023SJohn Marino   slot = htab_find_slot (mnemonic_htab, str_zero, INSERT);
1201*e4b17023SJohn Marino 
1202*e4b17023SJohn Marino   if (*slot)
1203*e4b17023SJohn Marino     return;
1204*e4b17023SJohn Marino 
1205*e4b17023SJohn Marino   /* Not found; create a permanent copy and add it to the hash table.  */
1206*e4b17023SJohn Marino   new_str = XNEWVAR (char, len + 1);
1207*e4b17023SJohn Marino   memcpy (new_str, str_zero, len + 1);
1208*e4b17023SJohn Marino   *slot = new_str;
1209*e4b17023SJohn Marino }
1210*e4b17023SJohn Marino 
1211*e4b17023SJohn Marino /* Scan INSN for mnemonic strings and add them to the mnemonic hash
1212*e4b17023SJohn Marino    table in MNEMONIC_HTAB.
1213*e4b17023SJohn Marino 
1214*e4b17023SJohn Marino    The mnemonics cannot be found if they are emitted using C code.
1215*e4b17023SJohn Marino 
1216*e4b17023SJohn Marino    If a mnemonic string contains ';' or a newline the string assumed
1217*e4b17023SJohn Marino    to consist of more than a single instruction.  The attribute value
1218*e4b17023SJohn Marino    will then be set to the user defined default value.  */
1219*e4b17023SJohn Marino 
1220*e4b17023SJohn Marino static void
gen_mnemonic_setattr(htab_t mnemonic_htab,rtx insn)1221*e4b17023SJohn Marino gen_mnemonic_setattr (htab_t mnemonic_htab, rtx insn)
1222*e4b17023SJohn Marino {
1223*e4b17023SJohn Marino   const char *template_code, *cp;
1224*e4b17023SJohn Marino   int i;
1225*e4b17023SJohn Marino   int vec_len;
1226*e4b17023SJohn Marino   rtx set_attr;
1227*e4b17023SJohn Marino   char *attr_name;
1228*e4b17023SJohn Marino   rtvec new_vec;
1229*e4b17023SJohn Marino 
1230*e4b17023SJohn Marino   template_code = XTMPL (insn, 3);
1231*e4b17023SJohn Marino 
1232*e4b17023SJohn Marino   /* Skip patterns which use C code to emit the template.  */
1233*e4b17023SJohn Marino   if (template_code[0] == '*')
1234*e4b17023SJohn Marino     return;
1235*e4b17023SJohn Marino 
1236*e4b17023SJohn Marino   if (template_code[0] == '@')
1237*e4b17023SJohn Marino     cp = &template_code[1];
1238*e4b17023SJohn Marino   else
1239*e4b17023SJohn Marino     cp = &template_code[0];
1240*e4b17023SJohn Marino 
1241*e4b17023SJohn Marino   for (i = 0; *cp; )
1242*e4b17023SJohn Marino     {
1243*e4b17023SJohn Marino       const char *ep, *sp;
1244*e4b17023SJohn Marino       int size = 0;
1245*e4b17023SJohn Marino 
1246*e4b17023SJohn Marino       while (ISSPACE (*cp))
1247*e4b17023SJohn Marino 	cp++;
1248*e4b17023SJohn Marino 
1249*e4b17023SJohn Marino       for (ep = sp = cp; !IS_VSPACE (*ep) && *ep != '\0'; ++ep)
1250*e4b17023SJohn Marino 	if (!ISSPACE (*ep))
1251*e4b17023SJohn Marino 	  sp = ep + 1;
1252*e4b17023SJohn Marino 
1253*e4b17023SJohn Marino       if (i > 0)
1254*e4b17023SJohn Marino 	obstack_1grow (&string_obstack, ',');
1255*e4b17023SJohn Marino 
1256*e4b17023SJohn Marino       while (cp < sp && ((*cp >= '0' && *cp <= '9')
1257*e4b17023SJohn Marino 			 || (*cp >= 'a' && *cp <= 'z')))
1258*e4b17023SJohn Marino 
1259*e4b17023SJohn Marino 	{
1260*e4b17023SJohn Marino 	  obstack_1grow (&string_obstack, *cp);
1261*e4b17023SJohn Marino 	  cp++;
1262*e4b17023SJohn Marino 	  size++;
1263*e4b17023SJohn Marino 	}
1264*e4b17023SJohn Marino 
1265*e4b17023SJohn Marino       while (cp < sp)
1266*e4b17023SJohn Marino 	{
1267*e4b17023SJohn Marino 	  if (*cp == ';' || (*cp == '\\' && cp[1] == 'n'))
1268*e4b17023SJohn Marino 	    {
1269*e4b17023SJohn Marino 	      /* Don't set a value if there are more than one
1270*e4b17023SJohn Marino 		 instruction in the string.  */
1271*e4b17023SJohn Marino 	      obstack_next_free (&string_obstack) =
1272*e4b17023SJohn Marino 		obstack_next_free (&string_obstack) - size;
1273*e4b17023SJohn Marino 	      size = 0;
1274*e4b17023SJohn Marino 
1275*e4b17023SJohn Marino 	      cp = sp;
1276*e4b17023SJohn Marino 	      break;
1277*e4b17023SJohn Marino 	    }
1278*e4b17023SJohn Marino 	  cp++;
1279*e4b17023SJohn Marino 	}
1280*e4b17023SJohn Marino       if (size == 0)
1281*e4b17023SJohn Marino 	obstack_1grow (&string_obstack, '*');
1282*e4b17023SJohn Marino       else
1283*e4b17023SJohn Marino 	add_mnemonic_string (mnemonic_htab,
1284*e4b17023SJohn Marino 			     obstack_next_free (&string_obstack) - size,
1285*e4b17023SJohn Marino 			     size);
1286*e4b17023SJohn Marino       i++;
1287*e4b17023SJohn Marino     }
1288*e4b17023SJohn Marino 
1289*e4b17023SJohn Marino   /* An insn definition might emit an empty string.  */
1290*e4b17023SJohn Marino   if (obstack_object_size (&string_obstack) == 0)
1291*e4b17023SJohn Marino     return;
1292*e4b17023SJohn Marino 
1293*e4b17023SJohn Marino   obstack_1grow (&string_obstack, '\0');
1294*e4b17023SJohn Marino 
1295*e4b17023SJohn Marino   set_attr = rtx_alloc (SET_ATTR);
1296*e4b17023SJohn Marino   XSTR (set_attr, 1) = XOBFINISH (&string_obstack, char *);
1297*e4b17023SJohn Marino   attr_name = XNEWVAR (char, strlen (MNEMONIC_ATTR_NAME) + 1);
1298*e4b17023SJohn Marino   strcpy (attr_name, MNEMONIC_ATTR_NAME);
1299*e4b17023SJohn Marino   XSTR (set_attr, 0) = attr_name;
1300*e4b17023SJohn Marino 
1301*e4b17023SJohn Marino   if (!XVEC (insn, 4))
1302*e4b17023SJohn Marino     vec_len = 0;
1303*e4b17023SJohn Marino   else
1304*e4b17023SJohn Marino     vec_len = XVECLEN (insn, 4);
1305*e4b17023SJohn Marino 
1306*e4b17023SJohn Marino   new_vec = rtvec_alloc (vec_len + 1);
1307*e4b17023SJohn Marino   for (i = 0; i < vec_len; i++)
1308*e4b17023SJohn Marino     RTVEC_ELT (new_vec, i) = XVECEXP (insn, 4, i);
1309*e4b17023SJohn Marino   RTVEC_ELT (new_vec, vec_len) = set_attr;
1310*e4b17023SJohn Marino   XVEC (insn, 4) = new_vec;
1311*e4b17023SJohn Marino }
1312*e4b17023SJohn Marino 
1313*e4b17023SJohn Marino /* This function is called for the elements in the mnemonic hashtable
1314*e4b17023SJohn Marino    and generates a comma separated list of the mnemonics.  */
1315*e4b17023SJohn Marino 
1316*e4b17023SJohn Marino static int
mnemonic_htab_callback(void ** slot,void * info ATTRIBUTE_UNUSED)1317*e4b17023SJohn Marino mnemonic_htab_callback (void **slot, void *info ATTRIBUTE_UNUSED)
1318*e4b17023SJohn Marino {
1319*e4b17023SJohn Marino   obstack_grow (&string_obstack, (char*)*slot, strlen ((char*)*slot));
1320*e4b17023SJohn Marino   obstack_1grow (&string_obstack, ',');
1321*e4b17023SJohn Marino   return 1;
1322*e4b17023SJohn Marino }
1323*e4b17023SJohn Marino 
1324*e4b17023SJohn Marino /* Generate (set_attr "mnemonic" "..") RTXs and append them to every
1325*e4b17023SJohn Marino    insn definition in case the back end requests it by defining the
1326*e4b17023SJohn Marino    mnemonic attribute.  The values for the attribute will be extracted
1327*e4b17023SJohn Marino    from the output patterns of the insn definitions as far as
1328*e4b17023SJohn Marino    possible.  */
1329*e4b17023SJohn Marino 
1330*e4b17023SJohn Marino static void
gen_mnemonic_attr(void)1331*e4b17023SJohn Marino gen_mnemonic_attr (void)
1332*e4b17023SJohn Marino {
1333*e4b17023SJohn Marino   struct queue_elem *elem;
1334*e4b17023SJohn Marino   rtx mnemonic_attr = NULL;
1335*e4b17023SJohn Marino   htab_t mnemonic_htab;
1336*e4b17023SJohn Marino   const char *str, *p;
1337*e4b17023SJohn Marino   int i;
1338*e4b17023SJohn Marino 
1339*e4b17023SJohn Marino   if (have_error)
1340*e4b17023SJohn Marino     return;
1341*e4b17023SJohn Marino 
1342*e4b17023SJohn Marino   /* Look for the DEFINE_ATTR for `mnemonic'.  */
1343*e4b17023SJohn Marino   for (elem = define_attr_queue; elem != *define_attr_tail; elem = elem->next)
1344*e4b17023SJohn Marino     if (GET_CODE (elem->data) == DEFINE_ATTR
1345*e4b17023SJohn Marino 	&& strcmp (XSTR (elem->data, 0), MNEMONIC_ATTR_NAME) == 0)
1346*e4b17023SJohn Marino       {
1347*e4b17023SJohn Marino 	mnemonic_attr = elem->data;
1348*e4b17023SJohn Marino 	break;
1349*e4b17023SJohn Marino       }
1350*e4b17023SJohn Marino 
1351*e4b17023SJohn Marino   /* A (define_attr "mnemonic" "...") indicates that the back-end
1352*e4b17023SJohn Marino      wants a mnemonic attribute to be generated.  */
1353*e4b17023SJohn Marino   if (!mnemonic_attr)
1354*e4b17023SJohn Marino     return;
1355*e4b17023SJohn Marino 
1356*e4b17023SJohn Marino   mnemonic_htab = htab_create_alloc (MNEMONIC_HTAB_SIZE, htab_hash_string,
1357*e4b17023SJohn Marino 				     htab_eq_string, 0, xcalloc, free);
1358*e4b17023SJohn Marino 
1359*e4b17023SJohn Marino   for (elem = define_insn_queue; elem; elem = elem->next)
1360*e4b17023SJohn Marino     {
1361*e4b17023SJohn Marino       rtx insn = elem->data;
1362*e4b17023SJohn Marino       bool found = false;
1363*e4b17023SJohn Marino 
1364*e4b17023SJohn Marino       /* Check if the insn definition already has
1365*e4b17023SJohn Marino 	 (set_attr "mnemonic" ...).  */
1366*e4b17023SJohn Marino       if (XVEC (insn, 4))
1367*e4b17023SJohn Marino  	for (i = 0; i < XVECLEN (insn, 4); i++)
1368*e4b17023SJohn Marino 	  if (strcmp (XSTR (XVECEXP (insn, 4, i), 0), MNEMONIC_ATTR_NAME) == 0)
1369*e4b17023SJohn Marino 	    {
1370*e4b17023SJohn Marino 	      found = true;
1371*e4b17023SJohn Marino 	      break;
1372*e4b17023SJohn Marino 	    }
1373*e4b17023SJohn Marino 
1374*e4b17023SJohn Marino       if (!found)
1375*e4b17023SJohn Marino 	gen_mnemonic_setattr (mnemonic_htab, insn);
1376*e4b17023SJohn Marino     }
1377*e4b17023SJohn Marino 
1378*e4b17023SJohn Marino   /* Add the user defined values to the hash table.  */
1379*e4b17023SJohn Marino   str = XSTR (mnemonic_attr, 1);
1380*e4b17023SJohn Marino   while ((p = scan_comma_elt (&str)) != NULL)
1381*e4b17023SJohn Marino     add_mnemonic_string (mnemonic_htab, p, str - p);
1382*e4b17023SJohn Marino 
1383*e4b17023SJohn Marino   htab_traverse (mnemonic_htab, mnemonic_htab_callback, NULL);
1384*e4b17023SJohn Marino 
1385*e4b17023SJohn Marino   /* Replace the last ',' with the zero end character.  */
1386*e4b17023SJohn Marino   *((char *)obstack_next_free (&string_obstack) - 1) = '\0';
1387*e4b17023SJohn Marino   XSTR (mnemonic_attr, 1) = XOBFINISH (&string_obstack, char *);
1388*e4b17023SJohn Marino }
1389*e4b17023SJohn Marino 
1390*e4b17023SJohn Marino /* The entry point for initializing the reader.  */
1391*e4b17023SJohn Marino 
1392*e4b17023SJohn Marino bool
init_rtx_reader_args_cb(int argc,char ** argv,bool (* parse_opt)(const char *))1393*e4b17023SJohn Marino init_rtx_reader_args_cb (int argc, char **argv,
1394*e4b17023SJohn Marino 			 bool (*parse_opt) (const char *))
1395*e4b17023SJohn Marino {
1396*e4b17023SJohn Marino   /* Prepare to read input.  */
1397*e4b17023SJohn Marino   condition_table = htab_create (500, hash_c_test, cmp_c_test, NULL);
1398*e4b17023SJohn Marino   init_predicate_table ();
1399*e4b17023SJohn Marino   obstack_init (rtl_obstack);
1400*e4b17023SJohn Marino   sequence_num = 0;
1401*e4b17023SJohn Marino 
1402*e4b17023SJohn Marino   read_md_files (argc, argv, parse_opt, rtx_handle_directive);
1403*e4b17023SJohn Marino 
1404*e4b17023SJohn Marino   /* Process define_cond_exec patterns.  */
1405*e4b17023SJohn Marino   if (define_cond_exec_queue != NULL)
1406*e4b17023SJohn Marino     process_define_cond_exec ();
1407*e4b17023SJohn Marino 
1408*e4b17023SJohn Marino   if (define_attr_queue != NULL)
1409*e4b17023SJohn Marino     gen_mnemonic_attr ();
1410*e4b17023SJohn Marino 
1411*e4b17023SJohn Marino   return !have_error;
1412*e4b17023SJohn Marino }
1413*e4b17023SJohn Marino 
1414*e4b17023SJohn Marino /* Programs that don't have their own options can use this entry point
1415*e4b17023SJohn Marino    instead.  */
1416*e4b17023SJohn Marino bool
init_rtx_reader_args(int argc,char ** argv)1417*e4b17023SJohn Marino init_rtx_reader_args (int argc, char **argv)
1418*e4b17023SJohn Marino {
1419*e4b17023SJohn Marino   return init_rtx_reader_args_cb (argc, argv, 0);
1420*e4b17023SJohn Marino }
1421*e4b17023SJohn Marino 
1422*e4b17023SJohn Marino /* The entry point for reading a single rtx from an md file.  */
1423*e4b17023SJohn Marino 
1424*e4b17023SJohn Marino rtx
read_md_rtx(int * lineno,int * seqnr)1425*e4b17023SJohn Marino read_md_rtx (int *lineno, int *seqnr)
1426*e4b17023SJohn Marino {
1427*e4b17023SJohn Marino   struct queue_elem **queue, *elem;
1428*e4b17023SJohn Marino   rtx desc;
1429*e4b17023SJohn Marino 
1430*e4b17023SJohn Marino  discard:
1431*e4b17023SJohn Marino 
1432*e4b17023SJohn Marino   /* Read all patterns from a given queue before moving on to the next.  */
1433*e4b17023SJohn Marino   if (define_attr_queue != NULL)
1434*e4b17023SJohn Marino     queue = &define_attr_queue;
1435*e4b17023SJohn Marino   else if (define_pred_queue != NULL)
1436*e4b17023SJohn Marino     queue = &define_pred_queue;
1437*e4b17023SJohn Marino   else if (define_insn_queue != NULL)
1438*e4b17023SJohn Marino     queue = &define_insn_queue;
1439*e4b17023SJohn Marino   else if (other_queue != NULL)
1440*e4b17023SJohn Marino     queue = &other_queue;
1441*e4b17023SJohn Marino   else
1442*e4b17023SJohn Marino     return NULL_RTX;
1443*e4b17023SJohn Marino 
1444*e4b17023SJohn Marino   elem = *queue;
1445*e4b17023SJohn Marino   *queue = elem->next;
1446*e4b17023SJohn Marino   desc = elem->data;
1447*e4b17023SJohn Marino   read_md_filename = elem->filename;
1448*e4b17023SJohn Marino   *lineno = elem->lineno;
1449*e4b17023SJohn Marino   *seqnr = sequence_num;
1450*e4b17023SJohn Marino 
1451*e4b17023SJohn Marino   free (elem);
1452*e4b17023SJohn Marino 
1453*e4b17023SJohn Marino   /* Discard insn patterns which we know can never match (because
1454*e4b17023SJohn Marino      their C test is provably always false).  If insn_elision is
1455*e4b17023SJohn Marino      false, our caller needs to see all the patterns.  Note that the
1456*e4b17023SJohn Marino      elided patterns are never counted by the sequence numbering; it
1457*e4b17023SJohn Marino      is the caller's responsibility, when insn_elision is false, not
1458*e4b17023SJohn Marino      to use elided pattern numbers for anything.  */
1459*e4b17023SJohn Marino   switch (GET_CODE (desc))
1460*e4b17023SJohn Marino     {
1461*e4b17023SJohn Marino     case DEFINE_INSN:
1462*e4b17023SJohn Marino     case DEFINE_EXPAND:
1463*e4b17023SJohn Marino       if (maybe_eval_c_test (XSTR (desc, 2)) != 0)
1464*e4b17023SJohn Marino 	sequence_num++;
1465*e4b17023SJohn Marino       else if (insn_elision)
1466*e4b17023SJohn Marino 	goto discard;
1467*e4b17023SJohn Marino 
1468*e4b17023SJohn Marino       /* *seqnr is used here so the name table will match caller's
1469*e4b17023SJohn Marino 	 idea of insn numbering, whether or not elision is active.  */
1470*e4b17023SJohn Marino       record_insn_name (*seqnr, XSTR (desc, 0));
1471*e4b17023SJohn Marino       break;
1472*e4b17023SJohn Marino 
1473*e4b17023SJohn Marino     case DEFINE_SPLIT:
1474*e4b17023SJohn Marino     case DEFINE_PEEPHOLE:
1475*e4b17023SJohn Marino     case DEFINE_PEEPHOLE2:
1476*e4b17023SJohn Marino       if (maybe_eval_c_test (XSTR (desc, 1)) != 0)
1477*e4b17023SJohn Marino 	sequence_num++;
1478*e4b17023SJohn Marino       else if (insn_elision)
1479*e4b17023SJohn Marino 	    goto discard;
1480*e4b17023SJohn Marino       break;
1481*e4b17023SJohn Marino 
1482*e4b17023SJohn Marino     default:
1483*e4b17023SJohn Marino       break;
1484*e4b17023SJohn Marino     }
1485*e4b17023SJohn Marino 
1486*e4b17023SJohn Marino   return desc;
1487*e4b17023SJohn Marino }
1488*e4b17023SJohn Marino 
1489*e4b17023SJohn Marino /* Helper functions for insn elision.  */
1490*e4b17023SJohn Marino 
1491*e4b17023SJohn Marino /* Compute a hash function of a c_test structure, which is keyed
1492*e4b17023SJohn Marino    by its ->expr field.  */
1493*e4b17023SJohn Marino hashval_t
hash_c_test(const void * x)1494*e4b17023SJohn Marino hash_c_test (const void *x)
1495*e4b17023SJohn Marino {
1496*e4b17023SJohn Marino   const struct c_test *a = (const struct c_test *) x;
1497*e4b17023SJohn Marino   const unsigned char *base, *s = (const unsigned char *) a->expr;
1498*e4b17023SJohn Marino   hashval_t hash;
1499*e4b17023SJohn Marino   unsigned char c;
1500*e4b17023SJohn Marino   unsigned int len;
1501*e4b17023SJohn Marino 
1502*e4b17023SJohn Marino   base = s;
1503*e4b17023SJohn Marino   hash = 0;
1504*e4b17023SJohn Marino 
1505*e4b17023SJohn Marino   while ((c = *s++) != '\0')
1506*e4b17023SJohn Marino     {
1507*e4b17023SJohn Marino       hash += c + (c << 17);
1508*e4b17023SJohn Marino       hash ^= hash >> 2;
1509*e4b17023SJohn Marino     }
1510*e4b17023SJohn Marino 
1511*e4b17023SJohn Marino   len = s - base;
1512*e4b17023SJohn Marino   hash += len + (len << 17);
1513*e4b17023SJohn Marino   hash ^= hash >> 2;
1514*e4b17023SJohn Marino 
1515*e4b17023SJohn Marino   return hash;
1516*e4b17023SJohn Marino }
1517*e4b17023SJohn Marino 
1518*e4b17023SJohn Marino /* Compare two c_test expression structures.  */
1519*e4b17023SJohn Marino int
cmp_c_test(const void * x,const void * y)1520*e4b17023SJohn Marino cmp_c_test (const void *x, const void *y)
1521*e4b17023SJohn Marino {
1522*e4b17023SJohn Marino   const struct c_test *a = (const struct c_test *) x;
1523*e4b17023SJohn Marino   const struct c_test *b = (const struct c_test *) y;
1524*e4b17023SJohn Marino 
1525*e4b17023SJohn Marino   return !strcmp (a->expr, b->expr);
1526*e4b17023SJohn Marino }
1527*e4b17023SJohn Marino 
1528*e4b17023SJohn Marino /* Given a string representing a C test expression, look it up in the
1529*e4b17023SJohn Marino    condition_table and report whether or not its value is known
1530*e4b17023SJohn Marino    at compile time.  Returns a tristate: 1 for known true, 0 for
1531*e4b17023SJohn Marino    known false, -1 for unknown.  */
1532*e4b17023SJohn Marino int
maybe_eval_c_test(const char * expr)1533*e4b17023SJohn Marino maybe_eval_c_test (const char *expr)
1534*e4b17023SJohn Marino {
1535*e4b17023SJohn Marino   const struct c_test *test;
1536*e4b17023SJohn Marino   struct c_test dummy;
1537*e4b17023SJohn Marino 
1538*e4b17023SJohn Marino   if (expr[0] == 0)
1539*e4b17023SJohn Marino     return 1;
1540*e4b17023SJohn Marino 
1541*e4b17023SJohn Marino   dummy.expr = expr;
1542*e4b17023SJohn Marino   test = (const struct c_test *)htab_find (condition_table, &dummy);
1543*e4b17023SJohn Marino   if (!test)
1544*e4b17023SJohn Marino     return -1;
1545*e4b17023SJohn Marino   return test->value;
1546*e4b17023SJohn Marino }
1547*e4b17023SJohn Marino 
1548*e4b17023SJohn Marino /* Record the C test expression EXPR in the condition_table, with
1549*e4b17023SJohn Marino    value VAL.  Duplicates clobber previous entries.  */
1550*e4b17023SJohn Marino 
1551*e4b17023SJohn Marino void
add_c_test(const char * expr,int value)1552*e4b17023SJohn Marino add_c_test (const char *expr, int value)
1553*e4b17023SJohn Marino {
1554*e4b17023SJohn Marino   struct c_test *test;
1555*e4b17023SJohn Marino 
1556*e4b17023SJohn Marino   if (expr[0] == 0)
1557*e4b17023SJohn Marino     return;
1558*e4b17023SJohn Marino 
1559*e4b17023SJohn Marino   test = XNEW (struct c_test);
1560*e4b17023SJohn Marino   test->expr = expr;
1561*e4b17023SJohn Marino   test->value = value;
1562*e4b17023SJohn Marino 
1563*e4b17023SJohn Marino   *(htab_find_slot (condition_table, test, INSERT)) = test;
1564*e4b17023SJohn Marino }
1565*e4b17023SJohn Marino 
1566*e4b17023SJohn Marino /* For every C test, call CALLBACK with two arguments: a pointer to
1567*e4b17023SJohn Marino    the condition structure and INFO.  Stops when CALLBACK returns zero.  */
1568*e4b17023SJohn Marino void
traverse_c_tests(htab_trav callback,void * info)1569*e4b17023SJohn Marino traverse_c_tests (htab_trav callback, void *info)
1570*e4b17023SJohn Marino {
1571*e4b17023SJohn Marino   if (condition_table)
1572*e4b17023SJohn Marino     htab_traverse (condition_table, callback, info);
1573*e4b17023SJohn Marino }
1574*e4b17023SJohn Marino 
1575*e4b17023SJohn Marino /* Helper functions for define_predicate and define_special_predicate
1576*e4b17023SJohn Marino    processing.  Shared between genrecog.c and genpreds.c.  */
1577*e4b17023SJohn Marino 
1578*e4b17023SJohn Marino static htab_t predicate_table;
1579*e4b17023SJohn Marino struct pred_data *first_predicate;
1580*e4b17023SJohn Marino static struct pred_data **last_predicate = &first_predicate;
1581*e4b17023SJohn Marino 
1582*e4b17023SJohn Marino static hashval_t
hash_struct_pred_data(const void * ptr)1583*e4b17023SJohn Marino hash_struct_pred_data (const void *ptr)
1584*e4b17023SJohn Marino {
1585*e4b17023SJohn Marino   return htab_hash_string (((const struct pred_data *)ptr)->name);
1586*e4b17023SJohn Marino }
1587*e4b17023SJohn Marino 
1588*e4b17023SJohn Marino static int
eq_struct_pred_data(const void * a,const void * b)1589*e4b17023SJohn Marino eq_struct_pred_data (const void *a, const void *b)
1590*e4b17023SJohn Marino {
1591*e4b17023SJohn Marino   return !strcmp (((const struct pred_data *)a)->name,
1592*e4b17023SJohn Marino 		  ((const struct pred_data *)b)->name);
1593*e4b17023SJohn Marino }
1594*e4b17023SJohn Marino 
1595*e4b17023SJohn Marino struct pred_data *
lookup_predicate(const char * name)1596*e4b17023SJohn Marino lookup_predicate (const char *name)
1597*e4b17023SJohn Marino {
1598*e4b17023SJohn Marino   struct pred_data key;
1599*e4b17023SJohn Marino   key.name = name;
1600*e4b17023SJohn Marino   return (struct pred_data *) htab_find (predicate_table, &key);
1601*e4b17023SJohn Marino }
1602*e4b17023SJohn Marino 
1603*e4b17023SJohn Marino /* Record that predicate PRED can accept CODE.  */
1604*e4b17023SJohn Marino 
1605*e4b17023SJohn Marino void
add_predicate_code(struct pred_data * pred,enum rtx_code code)1606*e4b17023SJohn Marino add_predicate_code (struct pred_data *pred, enum rtx_code code)
1607*e4b17023SJohn Marino {
1608*e4b17023SJohn Marino   if (!pred->codes[code])
1609*e4b17023SJohn Marino     {
1610*e4b17023SJohn Marino       pred->num_codes++;
1611*e4b17023SJohn Marino       pred->codes[code] = true;
1612*e4b17023SJohn Marino 
1613*e4b17023SJohn Marino       if (GET_RTX_CLASS (code) != RTX_CONST_OBJ)
1614*e4b17023SJohn Marino 	pred->allows_non_const = true;
1615*e4b17023SJohn Marino 
1616*e4b17023SJohn Marino       if (code != REG
1617*e4b17023SJohn Marino 	  && code != SUBREG
1618*e4b17023SJohn Marino 	  && code != MEM
1619*e4b17023SJohn Marino 	  && code != CONCAT
1620*e4b17023SJohn Marino 	  && code != PARALLEL
1621*e4b17023SJohn Marino 	  && code != STRICT_LOW_PART)
1622*e4b17023SJohn Marino 	pred->allows_non_lvalue = true;
1623*e4b17023SJohn Marino 
1624*e4b17023SJohn Marino       if (pred->num_codes == 1)
1625*e4b17023SJohn Marino 	pred->singleton = code;
1626*e4b17023SJohn Marino       else if (pred->num_codes == 2)
1627*e4b17023SJohn Marino 	pred->singleton = UNKNOWN;
1628*e4b17023SJohn Marino     }
1629*e4b17023SJohn Marino }
1630*e4b17023SJohn Marino 
1631*e4b17023SJohn Marino void
add_predicate(struct pred_data * pred)1632*e4b17023SJohn Marino add_predicate (struct pred_data *pred)
1633*e4b17023SJohn Marino {
1634*e4b17023SJohn Marino   void **slot = htab_find_slot (predicate_table, pred, INSERT);
1635*e4b17023SJohn Marino   if (*slot)
1636*e4b17023SJohn Marino     {
1637*e4b17023SJohn Marino       error ("duplicate predicate definition for '%s'", pred->name);
1638*e4b17023SJohn Marino       return;
1639*e4b17023SJohn Marino     }
1640*e4b17023SJohn Marino   *slot = pred;
1641*e4b17023SJohn Marino   *last_predicate = pred;
1642*e4b17023SJohn Marino   last_predicate = &pred->next;
1643*e4b17023SJohn Marino }
1644*e4b17023SJohn Marino 
1645*e4b17023SJohn Marino /* This array gives the initial content of the predicate table.  It
1646*e4b17023SJohn Marino    has entries for all predicates defined in recog.c.  */
1647*e4b17023SJohn Marino 
1648*e4b17023SJohn Marino struct std_pred_table
1649*e4b17023SJohn Marino {
1650*e4b17023SJohn Marino   const char *name;
1651*e4b17023SJohn Marino   bool special;
1652*e4b17023SJohn Marino   bool allows_const_p;
1653*e4b17023SJohn Marino   RTX_CODE codes[NUM_RTX_CODE];
1654*e4b17023SJohn Marino };
1655*e4b17023SJohn Marino 
1656*e4b17023SJohn Marino static const struct std_pred_table std_preds[] = {
1657*e4b17023SJohn Marino   {"general_operand", false, true, {SUBREG, REG, MEM}},
1658*e4b17023SJohn Marino   {"address_operand", true, true, {SUBREG, REG, MEM, PLUS, MINUS, MULT}},
1659*e4b17023SJohn Marino   {"register_operand", false, false, {SUBREG, REG}},
1660*e4b17023SJohn Marino   {"pmode_register_operand", true, false, {SUBREG, REG}},
1661*e4b17023SJohn Marino   {"scratch_operand", false, false, {SCRATCH, REG}},
1662*e4b17023SJohn Marino   {"immediate_operand", false, true, {UNKNOWN}},
1663*e4b17023SJohn Marino   {"const_int_operand", false, false, {CONST_INT}},
1664*e4b17023SJohn Marino   {"const_double_operand", false, false, {CONST_INT, CONST_DOUBLE}},
1665*e4b17023SJohn Marino   {"nonimmediate_operand", false, false, {SUBREG, REG, MEM}},
1666*e4b17023SJohn Marino   {"nonmemory_operand", false, true, {SUBREG, REG}},
1667*e4b17023SJohn Marino   {"push_operand", false, false, {MEM}},
1668*e4b17023SJohn Marino   {"pop_operand", false, false, {MEM}},
1669*e4b17023SJohn Marino   {"memory_operand", false, false, {SUBREG, MEM}},
1670*e4b17023SJohn Marino   {"indirect_operand", false, false, {SUBREG, MEM}},
1671*e4b17023SJohn Marino   {"ordered_comparison_operator", false, false, {EQ, NE,
1672*e4b17023SJohn Marino 						 LE, LT, GE, GT,
1673*e4b17023SJohn Marino 						 LEU, LTU, GEU, GTU}},
1674*e4b17023SJohn Marino   {"comparison_operator", false, false, {EQ, NE,
1675*e4b17023SJohn Marino 					 LE, LT, GE, GT,
1676*e4b17023SJohn Marino 					 LEU, LTU, GEU, GTU,
1677*e4b17023SJohn Marino 					 UNORDERED, ORDERED,
1678*e4b17023SJohn Marino 					 UNEQ, UNGE, UNGT,
1679*e4b17023SJohn Marino 					 UNLE, UNLT, LTGT}}
1680*e4b17023SJohn Marino };
1681*e4b17023SJohn Marino #define NUM_KNOWN_STD_PREDS ARRAY_SIZE (std_preds)
1682*e4b17023SJohn Marino 
1683*e4b17023SJohn Marino /* Initialize the table of predicate definitions, starting with
1684*e4b17023SJohn Marino    the information we have on generic predicates.  */
1685*e4b17023SJohn Marino 
1686*e4b17023SJohn Marino static void
init_predicate_table(void)1687*e4b17023SJohn Marino init_predicate_table (void)
1688*e4b17023SJohn Marino {
1689*e4b17023SJohn Marino   size_t i, j;
1690*e4b17023SJohn Marino   struct pred_data *pred;
1691*e4b17023SJohn Marino 
1692*e4b17023SJohn Marino   predicate_table = htab_create_alloc (37, hash_struct_pred_data,
1693*e4b17023SJohn Marino 				       eq_struct_pred_data, 0,
1694*e4b17023SJohn Marino 				       xcalloc, free);
1695*e4b17023SJohn Marino 
1696*e4b17023SJohn Marino   for (i = 0; i < NUM_KNOWN_STD_PREDS; i++)
1697*e4b17023SJohn Marino     {
1698*e4b17023SJohn Marino       pred = XCNEW (struct pred_data);
1699*e4b17023SJohn Marino       pred->name = std_preds[i].name;
1700*e4b17023SJohn Marino       pred->special = std_preds[i].special;
1701*e4b17023SJohn Marino 
1702*e4b17023SJohn Marino       for (j = 0; std_preds[i].codes[j] != 0; j++)
1703*e4b17023SJohn Marino 	add_predicate_code (pred, std_preds[i].codes[j]);
1704*e4b17023SJohn Marino 
1705*e4b17023SJohn Marino       if (std_preds[i].allows_const_p)
1706*e4b17023SJohn Marino 	for (j = 0; j < NUM_RTX_CODE; j++)
1707*e4b17023SJohn Marino 	  if (GET_RTX_CLASS (j) == RTX_CONST_OBJ)
1708*e4b17023SJohn Marino 	    add_predicate_code (pred, (enum rtx_code) j);
1709*e4b17023SJohn Marino 
1710*e4b17023SJohn Marino       add_predicate (pred);
1711*e4b17023SJohn Marino     }
1712*e4b17023SJohn Marino }
1713*e4b17023SJohn Marino 
1714*e4b17023SJohn Marino /* These functions allow linkage with print-rtl.c.  Also, some generators
1715*e4b17023SJohn Marino    like to annotate their output with insn names.  */
1716*e4b17023SJohn Marino 
1717*e4b17023SJohn Marino /* Holds an array of names indexed by insn_code_number.  */
1718*e4b17023SJohn Marino static char **insn_name_ptr = 0;
1719*e4b17023SJohn Marino static int insn_name_ptr_size = 0;
1720*e4b17023SJohn Marino 
1721*e4b17023SJohn Marino const char *
get_insn_name(int code)1722*e4b17023SJohn Marino get_insn_name (int code)
1723*e4b17023SJohn Marino {
1724*e4b17023SJohn Marino   if (code < insn_name_ptr_size)
1725*e4b17023SJohn Marino     return insn_name_ptr[code];
1726*e4b17023SJohn Marino   else
1727*e4b17023SJohn Marino     return NULL;
1728*e4b17023SJohn Marino }
1729*e4b17023SJohn Marino 
1730*e4b17023SJohn Marino static void
record_insn_name(int code,const char * name)1731*e4b17023SJohn Marino record_insn_name (int code, const char *name)
1732*e4b17023SJohn Marino {
1733*e4b17023SJohn Marino   static const char *last_real_name = "insn";
1734*e4b17023SJohn Marino   static int last_real_code = 0;
1735*e4b17023SJohn Marino   char *new_name;
1736*e4b17023SJohn Marino 
1737*e4b17023SJohn Marino   if (insn_name_ptr_size <= code)
1738*e4b17023SJohn Marino     {
1739*e4b17023SJohn Marino       int new_size;
1740*e4b17023SJohn Marino       new_size = (insn_name_ptr_size ? insn_name_ptr_size * 2 : 512);
1741*e4b17023SJohn Marino       insn_name_ptr = XRESIZEVEC (char *, insn_name_ptr, new_size);
1742*e4b17023SJohn Marino       memset (insn_name_ptr + insn_name_ptr_size, 0,
1743*e4b17023SJohn Marino 	      sizeof(char *) * (new_size - insn_name_ptr_size));
1744*e4b17023SJohn Marino       insn_name_ptr_size = new_size;
1745*e4b17023SJohn Marino     }
1746*e4b17023SJohn Marino 
1747*e4b17023SJohn Marino   if (!name || name[0] == '\0')
1748*e4b17023SJohn Marino     {
1749*e4b17023SJohn Marino       new_name = XNEWVAR (char, strlen (last_real_name) + 10);
1750*e4b17023SJohn Marino       sprintf (new_name, "%s+%d", last_real_name, code - last_real_code);
1751*e4b17023SJohn Marino     }
1752*e4b17023SJohn Marino   else
1753*e4b17023SJohn Marino     {
1754*e4b17023SJohn Marino       last_real_name = new_name = xstrdup (name);
1755*e4b17023SJohn Marino       last_real_code = code;
1756*e4b17023SJohn Marino     }
1757*e4b17023SJohn Marino 
1758*e4b17023SJohn Marino   insn_name_ptr[code] = new_name;
1759*e4b17023SJohn Marino }
1760*e4b17023SJohn Marino 
1761*e4b17023SJohn Marino /* Make STATS describe the operands that appear in rtx X.  */
1762*e4b17023SJohn Marino 
1763*e4b17023SJohn Marino static void
get_pattern_stats_1(struct pattern_stats * stats,rtx x)1764*e4b17023SJohn Marino get_pattern_stats_1 (struct pattern_stats *stats, rtx x)
1765*e4b17023SJohn Marino {
1766*e4b17023SJohn Marino   RTX_CODE code;
1767*e4b17023SJohn Marino   int i;
1768*e4b17023SJohn Marino   int len;
1769*e4b17023SJohn Marino   const char *fmt;
1770*e4b17023SJohn Marino 
1771*e4b17023SJohn Marino   if (x == NULL_RTX)
1772*e4b17023SJohn Marino     return;
1773*e4b17023SJohn Marino 
1774*e4b17023SJohn Marino   code = GET_CODE (x);
1775*e4b17023SJohn Marino   switch (code)
1776*e4b17023SJohn Marino     {
1777*e4b17023SJohn Marino     case MATCH_OPERAND:
1778*e4b17023SJohn Marino     case MATCH_OPERATOR:
1779*e4b17023SJohn Marino     case MATCH_PARALLEL:
1780*e4b17023SJohn Marino       stats->max_opno = MAX (stats->max_opno, XINT (x, 0));
1781*e4b17023SJohn Marino       break;
1782*e4b17023SJohn Marino 
1783*e4b17023SJohn Marino     case MATCH_DUP:
1784*e4b17023SJohn Marino     case MATCH_OP_DUP:
1785*e4b17023SJohn Marino     case MATCH_PAR_DUP:
1786*e4b17023SJohn Marino       stats->num_dups++;
1787*e4b17023SJohn Marino       stats->max_dup_opno = MAX (stats->max_dup_opno, XINT (x, 0));
1788*e4b17023SJohn Marino       break;
1789*e4b17023SJohn Marino 
1790*e4b17023SJohn Marino     case MATCH_SCRATCH:
1791*e4b17023SJohn Marino       stats->max_scratch_opno = MAX (stats->max_scratch_opno, XINT (x, 0));
1792*e4b17023SJohn Marino       break;
1793*e4b17023SJohn Marino 
1794*e4b17023SJohn Marino     default:
1795*e4b17023SJohn Marino       break;
1796*e4b17023SJohn Marino     }
1797*e4b17023SJohn Marino 
1798*e4b17023SJohn Marino   fmt = GET_RTX_FORMAT (code);
1799*e4b17023SJohn Marino   len = GET_RTX_LENGTH (code);
1800*e4b17023SJohn Marino   for (i = 0; i < len; i++)
1801*e4b17023SJohn Marino     {
1802*e4b17023SJohn Marino       if (fmt[i] == 'e' || fmt[i] == 'u')
1803*e4b17023SJohn Marino 	get_pattern_stats_1 (stats, XEXP (x, i));
1804*e4b17023SJohn Marino       else if (fmt[i] == 'E')
1805*e4b17023SJohn Marino 	{
1806*e4b17023SJohn Marino 	  int j;
1807*e4b17023SJohn Marino 	  for (j = 0; j < XVECLEN (x, i); j++)
1808*e4b17023SJohn Marino 	    get_pattern_stats_1 (stats, XVECEXP (x, i, j));
1809*e4b17023SJohn Marino 	}
1810*e4b17023SJohn Marino     }
1811*e4b17023SJohn Marino }
1812*e4b17023SJohn Marino 
1813*e4b17023SJohn Marino /* Make STATS describe the operands that appear in instruction pattern
1814*e4b17023SJohn Marino    PATTERN.  */
1815*e4b17023SJohn Marino 
1816*e4b17023SJohn Marino void
get_pattern_stats(struct pattern_stats * stats,rtvec pattern)1817*e4b17023SJohn Marino get_pattern_stats (struct pattern_stats *stats, rtvec pattern)
1818*e4b17023SJohn Marino {
1819*e4b17023SJohn Marino   int i, len;
1820*e4b17023SJohn Marino 
1821*e4b17023SJohn Marino   stats->max_opno = -1;
1822*e4b17023SJohn Marino   stats->max_dup_opno = -1;
1823*e4b17023SJohn Marino   stats->max_scratch_opno = -1;
1824*e4b17023SJohn Marino   stats->num_dups = 0;
1825*e4b17023SJohn Marino 
1826*e4b17023SJohn Marino   len = GET_NUM_ELEM (pattern);
1827*e4b17023SJohn Marino   for (i = 0; i < len; i++)
1828*e4b17023SJohn Marino     get_pattern_stats_1 (stats, RTVEC_ELT (pattern, i));
1829*e4b17023SJohn Marino 
1830*e4b17023SJohn Marino   stats->num_generator_args = stats->max_opno + 1;
1831*e4b17023SJohn Marino   stats->num_insn_operands = MAX (stats->max_opno,
1832*e4b17023SJohn Marino 				  stats->max_scratch_opno) + 1;
1833*e4b17023SJohn Marino   stats->num_operand_vars = MAX (stats->max_opno,
1834*e4b17023SJohn Marino 				  MAX (stats->max_dup_opno,
1835*e4b17023SJohn Marino 				       stats->max_scratch_opno)) + 1;
1836*e4b17023SJohn Marino }
1837