genrecog.c revision 169690
1189251Ssam/* Generate code from machine description to recognize rtl as insns.
2189251Ssam   Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1997, 1998,
3281806Srpaulo   1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
4189251Ssam
5252726Srpaulo   This file is part of GCC.
6252726Srpaulo
7189251Ssam   GCC is free software; you can redistribute it and/or modify it
8189251Ssam   under the terms of the GNU General Public License as published by
9189251Ssam   the Free Software Foundation; either version 2, or (at your option)
10189251Ssam   any later version.
11189251Ssam
12189251Ssam   GCC is distributed in the hope that it will be useful, but WITHOUT
13189251Ssam   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14189251Ssam   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
15189251Ssam   License for more details.
16189251Ssam
17189251Ssam   You should have received a copy of the GNU General Public License
18189251Ssam   along with GCC; see the file COPYING.  If not, write to the Free
19189251Ssam   Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
20189251Ssam   02110-1301, USA.  */
21189251Ssam
22189251Ssam
23252726Srpaulo/* This program is used to produce insn-recog.c, which contains a
24214734Srpaulo   function called `recog' plus its subroutines.  These functions
25214734Srpaulo   contain a decision tree that recognizes whether an rtx, the
26281806Srpaulo   argument given to recog, is a valid instruction.
27214734Srpaulo
28189251Ssam   recog returns -1 if the rtx is not valid.  If the rtx is valid,
29214734Srpaulo   recog returns a nonnegative number which is the insn code number
30214734Srpaulo   for the pattern that matched.  This is the same as the order in the
31189251Ssam   machine description of the entry that matched.  This number can be
32189251Ssam   used as an index into various insn_* tables, such as insn_template,
33189251Ssam   insn_outfun, and insn_n_operands (found in insn-output.c).
34189251Ssam
35189251Ssam   The third argument to recog is an optional pointer to an int.  If
36252726Srpaulo   present, recog will accept a pattern if it matches except for
37189251Ssam   missing CLOBBER expressions at the end.  In that case, the value
38189251Ssam   pointed to by the optional pointer will be set to the number of
39189251Ssam   CLOBBERs that need to be added (it should be initialized to zero by
40189251Ssam   the caller).  If it is set nonzero, the caller should allocate a
41189251Ssam   PARALLEL of the appropriate size, copy the initial entries, and
42189251Ssam   call add_clobbers (found in insn-emit.c) to fill in the CLOBBERs.
43189251Ssam
44189251Ssam   This program also generates the function `split_insns', which
45189251Ssam   returns 0 if the rtl could not be split, or it returns the split
46189251Ssam   rtl as an INSN list.
47189251Ssam
48189251Ssam   This program also generates the function `peephole2_insns', which
49189251Ssam   returns 0 if the rtl could not be matched.  If there was a match,
50189251Ssam   the new rtl is returned in an INSN list, and LAST_INSN will point
51337817Scy   to the last recognized insn in the old sequence.  */
52337817Scy
53189251Ssam#include "bconfig.h"
54189251Ssam#include "system.h"
55189251Ssam#include "coretypes.h"
56189251Ssam#include "tm.h"
57189251Ssam#include "rtl.h"
58189251Ssam#include "errors.h"
59189251Ssam#include "gensupport.h"
60189251Ssam
61189251Ssam#define OUTPUT_LABEL(INDENT_STRING, LABEL_NUMBER) \
62189251Ssam  printf("%sL%d: ATTRIBUTE_UNUSED_LABEL\n", (INDENT_STRING), (LABEL_NUMBER))
63189251Ssam
64189251Ssam/* A listhead of decision trees.  The alternatives to a node are kept
65189251Ssam   in a doubly-linked list so we can easily add nodes to the proper
66189251Ssam   place when merging.  */
67189251Ssam
68189251Ssamstruct decision_head
69189251Ssam{
70189251Ssam  struct decision *first;
71189251Ssam  struct decision *last;
72189251Ssam};
73189251Ssam
74189251Ssam/* A single test.  The two accept types aren't tests per-se, but
75189251Ssam   their equality (or lack thereof) does affect tree merging so
76189251Ssam   it is convenient to keep them here.  */
77189251Ssam
78189251Ssamstruct decision_test
79189251Ssam{
80189251Ssam  /* A linked list through the tests attached to a node.  */
81189251Ssam  struct decision_test *next;
82189251Ssam
83189251Ssam  /* These types are roughly in the order in which we'd like to test them.  */
84189251Ssam  enum decision_type
85189251Ssam    {
86189251Ssam      DT_num_insns,
87189251Ssam      DT_mode, DT_code, DT_veclen,
88252726Srpaulo      DT_elt_zero_int, DT_elt_one_int, DT_elt_zero_wide, DT_elt_zero_wide_safe,
89252726Srpaulo      DT_const_int,
90252726Srpaulo      DT_veclen_ge, DT_dup, DT_pred, DT_c_test,
91252726Srpaulo      DT_accept_op, DT_accept_insn
92252726Srpaulo    } type;
93252726Srpaulo
94252726Srpaulo  union
95252726Srpaulo  {
96252726Srpaulo    int num_insns;		/* Number if insn in a define_peephole2.  */
97252726Srpaulo    enum machine_mode mode;	/* Machine mode of node.  */
98346981Scy    RTX_CODE code;		/* Code to test.  */
99346981Scy
100346981Scy    struct
101346981Scy    {
102346981Scy      const char *name;		/* Predicate to call.  */
103346981Scy      const struct pred_data *data;
104346981Scy                                /* Optimization hints for this predicate.  */
105346981Scy      enum machine_mode mode;	/* Machine mode for node.  */
106281806Srpaulo    } pred;
107281806Srpaulo
108281806Srpaulo    const char *c_test;		/* Additional test to perform.  */
109281806Srpaulo    int veclen;			/* Length of vector.  */
110281806Srpaulo    int dup;			/* Number of operand to compare against.  */
111281806Srpaulo    HOST_WIDE_INT intval;	/* Value for XINT for XWINT.  */
112281806Srpaulo    int opno;			/* Operand number matched.  */
113281806Srpaulo
114281806Srpaulo    struct {
115189251Ssam      int code_number;		/* Insn number matched.  */
116189251Ssam      int lineno;		/* Line number of the insn.  */
117252726Srpaulo      int num_clobbers_to_add;	/* Number of CLOBBERs to be added.  */
118252726Srpaulo    } insn;
119252726Srpaulo  } u;
120189251Ssam};
121189251Ssam
122189251Ssam/* Data structure for decision tree for recognizing legitimate insns.  */
123189251Ssam
124189251Ssamstruct decision
125189251Ssam{
126189251Ssam  struct decision_head success;	/* Nodes to test on success.  */
127189251Ssam  struct decision *next;	/* Node to test on failure.  */
128189251Ssam  struct decision *prev;	/* Node whose failure tests us.  */
129189251Ssam  struct decision *afterward;	/* Node to test on success,
130189251Ssam				   but failure of successor nodes.  */
131189251Ssam
132346981Scy  const char *position;		/* String denoting position in pattern.  */
133189251Ssam
134346981Scy  struct decision_test *tests;	/* The tests for this node.  */
135189251Ssam
136189251Ssam  int number;			/* Node number, used for labels */
137189251Ssam  int subroutine_number;	/* Number of subroutine this node starts */
138189251Ssam  int need_label;		/* Label needs to be output.  */
139346981Scy};
140346981Scy
141346981Scy#define SUBROUTINE_THRESHOLD	100
142189251Ssam
143189251Ssamstatic int next_subroutine_number;
144189251Ssam
145189251Ssam/* We can write three types of subroutines: One for insn recognition,
146189251Ssam   one to split insns, and one for peephole-type optimizations.  This
147189251Ssam   defines which type is being written.  */
148189251Ssam
149189251Ssamenum routine_type {
150189251Ssam  RECOG, SPLIT, PEEPHOLE2
151189251Ssam};
152189251Ssam
153189251Ssam#define IS_SPLIT(X) ((X) != RECOG)
154189251Ssam
155189251Ssam/* Next available node number for tree nodes.  */
156189251Ssam
157189251Ssamstatic int next_number;
158189251Ssam
159346981Scy/* Next number to use as an insn_code.  */
160346981Scy
161346981Scystatic int next_insn_code;
162346981Scy
163346981Scy/* Record the highest depth we ever have so we know how many variables to
164346981Scy   allocate in each subroutine we make.  */
165346981Scy
166346981Scystatic int max_depth;
167346981Scy
168346981Scy/* The line number of the start of the pattern currently being processed.  */
169346981Scystatic int pattern_lineno;
170346981Scy
171346981Scy/* Count of errors.  */
172346981Scystatic int error_count;
173346981Scy
174346981Scy/* Predicate handling.
175346981Scy
176346981Scy   We construct from the machine description a table mapping each
177346981Scy   predicate to a list of the rtl codes it can possibly match.  The
178346981Scy   function 'maybe_both_true' uses it to deduce that there are no
179346981Scy   expressions that can be matches by certain pairs of tree nodes.
180346981Scy   Also, if a predicate can match only one code, we can hardwire that
181346981Scy   code into the node testing the predicate.
182346981Scy
183346981Scy   Some predicates are flagged as special.  validate_pattern will not
184346981Scy   warn about modeless match_operand expressions if they have a
185346981Scy   special predicate.  Predicates that allow only constants are also
186346981Scy   treated as special, for this purpose.
187346981Scy
188346981Scy   validate_pattern will warn about predicates that allow non-lvalues
189346981Scy   when they appear in destination operands.
190346981Scy
191346981Scy   Calculating the set of rtx codes that can possibly be accepted by a
192346981Scy   predicate expression EXP requires a three-state logic: any given
193346981Scy   subexpression may definitively accept a code C (Y), definitively
194346981Scy   reject a code C (N), or may have an indeterminate effect (I).  N
195346981Scy   and I is N; Y or I is Y; Y and I, N or I are both I.  Here are full
196346981Scy   truth tables.
197346981Scy
198346981Scy     a b  a&b  a|b
199346981Scy     Y Y   Y    Y
200346981Scy     N Y   N    Y
201346981Scy     N N   N    N
202346981Scy     I Y   I    Y
203346981Scy     I N   N    I
204346981Scy     I I   I    I
205346981Scy
206346981Scy   We represent Y with 1, N with 0, I with 2.  If any code is left in
207346981Scy   an I state by the complete expression, we must assume that that
208346981Scy   code can be accepted.  */
209346981Scy
210189251Ssam#define N 0
211189251Ssam#define Y 1
212189251Ssam#define I 2
213189251Ssam
214189251Ssam#define TRISTATE_AND(a,b)			\
215189251Ssam  ((a) == I ? ((b) == N ? N : I) :		\
216189251Ssam   (b) == I ? ((a) == N ? N : I) :		\
217189251Ssam   (a) && (b))
218189251Ssam
219189251Ssam#define TRISTATE_OR(a,b)			\
220281806Srpaulo  ((a) == I ? ((b) == Y ? Y : I) :		\
221281806Srpaulo   (b) == I ? ((a) == Y ? Y : I) :		\
222189251Ssam   (a) || (b))
223189251Ssam
224189251Ssam#define TRISTATE_NOT(a)				\
225189251Ssam  ((a) == I ? I : !(a))
226281806Srpaulo
227189251Ssam/* 0 means no warning about that code yet, 1 means warned.  */
228189251Ssamstatic char did_you_mean_codes[NUM_RTX_CODE];
229189251Ssam
230189251Ssam/* Recursively calculate the set of rtx codes accepted by the
231189251Ssam   predicate expression EXP, writing the result to CODES.  */
232189251Ssamstatic void
233252726Srpaulocompute_predicate_codes (rtx exp, char codes[NUM_RTX_CODE])
234189251Ssam{
235189251Ssam  char op0_codes[NUM_RTX_CODE];
236189251Ssam  char op1_codes[NUM_RTX_CODE];
237281806Srpaulo  char op2_codes[NUM_RTX_CODE];
238281806Srpaulo  int i;
239281806Srpaulo
240189251Ssam  switch (GET_CODE (exp))
241189251Ssam    {
242189251Ssam    case AND:
243189251Ssam      compute_predicate_codes (XEXP (exp, 0), op0_codes);
244189251Ssam      compute_predicate_codes (XEXP (exp, 1), op1_codes);
245189251Ssam      for (i = 0; i < NUM_RTX_CODE; i++)
246189251Ssam	codes[i] = TRISTATE_AND (op0_codes[i], op1_codes[i]);
247189251Ssam      break;
248189251Ssam
249189251Ssam    case IOR:
250189251Ssam      compute_predicate_codes (XEXP (exp, 0), op0_codes);
251189251Ssam      compute_predicate_codes (XEXP (exp, 1), op1_codes);
252189251Ssam      for (i = 0; i < NUM_RTX_CODE; i++)
253189251Ssam	codes[i] = TRISTATE_OR (op0_codes[i], op1_codes[i]);
254337817Scy      break;
255337817Scy    case NOT:
256337817Scy      compute_predicate_codes (XEXP (exp, 0), op0_codes);
257337817Scy      for (i = 0; i < NUM_RTX_CODE; i++)
258337817Scy	codes[i] = TRISTATE_NOT (op0_codes[i]);
259337817Scy      break;
260337817Scy
261337817Scy    case IF_THEN_ELSE:
262189251Ssam      /* a ? b : c  accepts the same codes as (a & b) | (!a & c).  */
263189251Ssam      compute_predicate_codes (XEXP (exp, 0), op0_codes);
264281806Srpaulo      compute_predicate_codes (XEXP (exp, 1), op1_codes);
265281806Srpaulo      compute_predicate_codes (XEXP (exp, 2), op2_codes);
266281806Srpaulo      for (i = 0; i < NUM_RTX_CODE; i++)
267189251Ssam	codes[i] = TRISTATE_OR (TRISTATE_AND (op0_codes[i], op1_codes[i]),
268189251Ssam				TRISTATE_AND (TRISTATE_NOT (op0_codes[i]),
269189251Ssam					      op2_codes[i]));
270189251Ssam      break;
271189251Ssam
272189251Ssam    case MATCH_CODE:
273189251Ssam      /* MATCH_CODE allows a specified list of codes.  However, if it
274189251Ssam	 does not apply to the top level of the expression, it does not
275189251Ssam	 constrain the set of codes for the top level.  */
276189251Ssam      if (XSTR (exp, 1)[0] != '\0')
277189251Ssam	{
278189251Ssam	  memset (codes, Y, NUM_RTX_CODE);
279252726Srpaulo	  break;
280252726Srpaulo	}
281252726Srpaulo
282252726Srpaulo      memset (codes, N, NUM_RTX_CODE);
283252726Srpaulo      {
284252726Srpaulo	const char *next_code = XSTR (exp, 0);
285189251Ssam	const char *code;
286189251Ssam
287189251Ssam	if (*next_code == '\0')
288189251Ssam	  {
289189251Ssam	    message_with_line (pattern_lineno, "empty match_code expression");
290189251Ssam	    error_count++;
291189251Ssam	    break;
292189251Ssam	  }
293189251Ssam
294189251Ssam	while ((code = scan_comma_elt (&next_code)) != 0)
295189251Ssam	  {
296189251Ssam	    size_t n = next_code - code;
297189251Ssam	    int found_it = 0;
298189251Ssam
299189251Ssam	    for (i = 0; i < NUM_RTX_CODE; i++)
300189251Ssam	      if (!strncmp (code, GET_RTX_NAME (i), n)
301189251Ssam		  && GET_RTX_NAME (i)[n] == '\0')
302189251Ssam		{
303189251Ssam		  codes[i] = Y;
304189251Ssam		  found_it = 1;
305189251Ssam		  break;
306189251Ssam		}
307189251Ssam	    if (!found_it)
308189251Ssam	      {
309189251Ssam		message_with_line (pattern_lineno, "match_code \"%.*s\" matches nothing",
310189251Ssam				   (int) n, code);
311189251Ssam		error_count ++;
312189251Ssam		for (i = 0; i < NUM_RTX_CODE; i++)
313189251Ssam		  if (!strncasecmp (code, GET_RTX_NAME (i), n)
314189251Ssam		      && GET_RTX_NAME (i)[n] == '\0'
315189251Ssam		      && !did_you_mean_codes[i])
316189251Ssam		    {
317189251Ssam		      did_you_mean_codes[i] = 1;
318189251Ssam		      message_with_line (pattern_lineno, "(did you mean \"%s\"?)", GET_RTX_NAME (i));
319189251Ssam		    }
320189251Ssam	      }
321189251Ssam
322189251Ssam	  }
323252726Srpaulo      }
324189251Ssam      break;
325189251Ssam
326189251Ssam    case MATCH_OPERAND:
327189251Ssam      /* MATCH_OPERAND disallows the set of codes that the named predicate
328189251Ssam	 disallows, and is indeterminate for the codes that it does allow.  */
329189251Ssam      {
330189251Ssam	struct pred_data *p = lookup_predicate (XSTR (exp, 1));
331189251Ssam	if (!p)
332252726Srpaulo	  {
333252726Srpaulo	    message_with_line (pattern_lineno,
334189251Ssam			       "reference to unknown predicate '%s'",
335189251Ssam			       XSTR (exp, 1));
336189251Ssam	    error_count++;
337214734Srpaulo	    break;
338214734Srpaulo	  }
339214734Srpaulo	for (i = 0; i < NUM_RTX_CODE; i++)
340252726Srpaulo	  codes[i] = p->codes[i] ? I : N;
341252726Srpaulo      }
342189251Ssam      break;
343189251Ssam
344189251Ssam
345214734Srpaulo    case MATCH_TEST:
346214734Srpaulo      /* (match_test WHATEVER) is completely indeterminate.  */
347214734Srpaulo      memset (codes, I, NUM_RTX_CODE);
348252726Srpaulo      break;
349252726Srpaulo
350189251Ssam    default:
351189251Ssam      message_with_line (pattern_lineno,
352189251Ssam	 "'%s' cannot be used in a define_predicate expression",
353189251Ssam	 GET_RTX_NAME (GET_CODE (exp)));
354189251Ssam      error_count++;
355189251Ssam      memset (codes, I, NUM_RTX_CODE);
356189251Ssam      break;
357189251Ssam    }
358189251Ssam}
359189251Ssam
360189251Ssam#undef TRISTATE_OR
361189251Ssam#undef TRISTATE_AND
362189251Ssam#undef TRISTATE_NOT
363189251Ssam
364189251Ssam/* Process a define_predicate expression: compute the set of predicates
365189251Ssam   that can be matched, and record this as a known predicate.  */
366189251Ssamstatic void
367189251Ssamprocess_define_predicate (rtx desc)
368189251Ssam{
369189251Ssam  struct pred_data *pred = xcalloc (sizeof (struct pred_data), 1);
370189251Ssam  char codes[NUM_RTX_CODE];
371189251Ssam  bool seen_one = false;
372189251Ssam  int i;
373252726Srpaulo
374189251Ssam  pred->name = XSTR (desc, 0);
375189251Ssam  if (GET_CODE (desc) == DEFINE_SPECIAL_PREDICATE)
376189251Ssam    pred->special = 1;
377189251Ssam
378189251Ssam  compute_predicate_codes (XEXP (desc, 1), codes);
379189251Ssam
380189251Ssam  for (i = 0; i < NUM_RTX_CODE; i++)
381252726Srpaulo    if (codes[i] != N)
382252726Srpaulo      {
383189251Ssam	pred->codes[i] = true;
384189251Ssam	if (GET_RTX_CLASS (i) != RTX_CONST_OBJ)
385189251Ssam	  pred->allows_non_const = true;
386337817Scy	if (i != REG
387189251Ssam	    && i != SUBREG
388189251Ssam	    && i != MEM
389337817Scy	    && i != CONCAT
390337817Scy	    && i != PARALLEL
391337817Scy	    && i != STRICT_LOW_PART)
392189251Ssam	  pred->allows_non_lvalue = true;
393337817Scy
394189251Ssam	if (seen_one)
395189251Ssam	  pred->singleton = UNKNOWN;
396189251Ssam	else
397189251Ssam	  {
398189251Ssam	    pred->singleton = i;
399189251Ssam	    seen_one = true;
400189251Ssam	  }
401189251Ssam      }
402189251Ssam  add_predicate (pred);
403189251Ssam}
404189251Ssam#undef I
405189251Ssam#undef N
406189251Ssam#undef Y
407189251Ssam
408189251Ssam
409189251Ssamstatic struct decision *new_decision
410189251Ssam  (const char *, struct decision_head *);
411189251Ssamstatic struct decision_test *new_decision_test
412189251Ssam  (enum decision_type, struct decision_test ***);
413189251Ssamstatic rtx find_operand
414189251Ssam  (rtx, int, rtx);
415189251Ssamstatic rtx find_matching_operand
416189251Ssam  (rtx, int);
417189251Ssamstatic void validate_pattern
418189251Ssam  (rtx, rtx, rtx, int);
419189251Ssamstatic struct decision *add_to_sequence
420189251Ssam  (rtx, struct decision_head *, const char *, enum routine_type, int);
421189251Ssam
422189251Ssamstatic int maybe_both_true_2
423189251Ssam  (struct decision_test *, struct decision_test *);
424189251Ssamstatic int maybe_both_true_1
425189251Ssam  (struct decision_test *, struct decision_test *);
426189251Ssamstatic int maybe_both_true
427189251Ssam  (struct decision *, struct decision *, int);
428189251Ssam
429189251Ssamstatic int nodes_identical_1
430189251Ssam  (struct decision_test *, struct decision_test *);
431189251Ssamstatic int nodes_identical
432189251Ssam  (struct decision *, struct decision *);
433281806Srpaulostatic void merge_accept_insn
434281806Srpaulo  (struct decision *, struct decision *);
435346981Scystatic void merge_trees
436281806Srpaulo  (struct decision_head *, struct decision_head *);
437281806Srpaulo
438281806Srpaulostatic void factor_tests
439281806Srpaulo  (struct decision_head *);
440281806Srpaulostatic void simplify_tests
441281806Srpaulo  (struct decision_head *);
442281806Srpaulostatic int break_out_subroutines
443281806Srpaulo  (struct decision_head *, int);
444281806Srpaulostatic void find_afterward
445281806Srpaulo  (struct decision_head *, struct decision *);
446281806Srpaulo
447281806Srpaulostatic void change_state
448281806Srpaulo  (const char *, const char *, const char *);
449281806Srpaulostatic void print_code
450281806Srpaulo  (enum rtx_code);
451281806Srpaulostatic void write_afterward
452281806Srpaulo  (struct decision *, struct decision *, const char *);
453281806Srpaulostatic struct decision *write_switch
454281806Srpaulo  (struct decision *, int);
455281806Srpaulostatic void write_cond
456281806Srpaulo  (struct decision_test *, int, enum routine_type);
457281806Srpaulostatic void write_action
458281806Srpaulo  (struct decision *, struct decision_test *, int, int,
459281806Srpaulo   struct decision *, enum routine_type);
460281806Srpaulostatic int is_unconditional
461281806Srpaulo  (struct decision_test *, enum routine_type);
462281806Srpaulostatic int write_node
463281806Srpaulo  (struct decision *, int, enum routine_type);
464281806Srpaulostatic void write_tree_1
465281806Srpaulo  (struct decision_head *, int, enum routine_type);
466281806Srpaulostatic void write_tree
467281806Srpaulo  (struct decision_head *, const char *, enum routine_type, int);
468281806Srpaulostatic void write_subroutine
469281806Srpaulo  (struct decision_head *, enum routine_type);
470281806Srpaulostatic void write_subroutines
471281806Srpaulo  (struct decision_head *, enum routine_type);
472281806Srpaulostatic void write_header
473281806Srpaulo  (void);
474281806Srpaulo
475281806Srpaulostatic struct decision_head make_insn_sequence
476346981Scy  (rtx, enum routine_type);
477346981Scystatic void process_tree
478346981Scy  (struct decision_head *, enum routine_type);
479346981Scy
480346981Scystatic void debug_decision_0
481346981Scy  (struct decision *, int, int);
482346981Scystatic void debug_decision_1
483346981Scy  (struct decision *, int);
484346981Scystatic void debug_decision_2
485346981Scy  (struct decision_test *);
486346981Scyextern void debug_decision
487346981Scy  (struct decision *);
488346981Scyextern void debug_decision_list
489346981Scy  (struct decision *);
490346981Scy
491346981Scy/* Create a new node in sequence after LAST.  */
492346981Scy
493346981Scystatic struct decision *
494346981Scynew_decision (const char *position, struct decision_head *last)
495346981Scy{
496346981Scy  struct decision *new = xcalloc (1, sizeof (struct decision));
497346981Scy
498346981Scy  new->success = *last;
499346981Scy  new->position = xstrdup (position);
500346981Scy  new->number = next_number++;
501346981Scy
502346981Scy  last->first = last->last = new;
503346981Scy  return new;
504346981Scy}
505346981Scy
506346981Scy/* Create a new test and link it in at PLACE.  */
507346981Scy
508346981Scystatic struct decision_test *
509346981Scynew_decision_test (enum decision_type type, struct decision_test ***pplace)
510346981Scy{
511346981Scy  struct decision_test **place = *pplace;
512346981Scy  struct decision_test *test;
513346981Scy
514346981Scy  test = XNEW (struct decision_test);
515281806Srpaulo  test->next = *place;
516281806Srpaulo  test->type = type;
517281806Srpaulo  *place = test;
518346981Scy
519346981Scy  place = &test->next;
520346981Scy  *pplace = place;
521346981Scy
522346981Scy  return test;
523346981Scy}
524281806Srpaulo
525281806Srpaulo/* Search for and return operand N, stop when reaching node STOP.  */
526281806Srpaulo
527281806Srpaulostatic rtx
528281806Srpaulofind_operand (rtx pattern, int n, rtx stop)
529281806Srpaulo{
530281806Srpaulo  const char *fmt;
531281806Srpaulo  RTX_CODE code;
532281806Srpaulo  int i, j, len;
533281806Srpaulo  rtx r;
534281806Srpaulo
535281806Srpaulo  if (pattern == stop)
536281806Srpaulo    return stop;
537281806Srpaulo
538281806Srpaulo  code = GET_CODE (pattern);
539281806Srpaulo  if ((code == MATCH_SCRATCH
540281806Srpaulo       || code == MATCH_OPERAND
541281806Srpaulo       || code == MATCH_OPERATOR
542281806Srpaulo       || code == MATCH_PARALLEL)
543281806Srpaulo      && XINT (pattern, 0) == n)
544281806Srpaulo    return pattern;
545281806Srpaulo
546281806Srpaulo  fmt = GET_RTX_FORMAT (code);
547281806Srpaulo  len = GET_RTX_LENGTH (code);
548281806Srpaulo  for (i = 0; i < len; i++)
549281806Srpaulo    {
550281806Srpaulo      switch (fmt[i])
551281806Srpaulo	{
552281806Srpaulo	case 'e': case 'u':
553281806Srpaulo	  if ((r = find_operand (XEXP (pattern, i), n, stop)) != NULL_RTX)
554281806Srpaulo	    return r;
555281806Srpaulo	  break;
556281806Srpaulo
557281806Srpaulo	case 'V':
558281806Srpaulo	  if (! XVEC (pattern, i))
559281806Srpaulo	    break;
560281806Srpaulo	  /* Fall through.  */
561281806Srpaulo
562281806Srpaulo	case 'E':
563281806Srpaulo	  for (j = 0; j < XVECLEN (pattern, i); j++)
564281806Srpaulo	    if ((r = find_operand (XVECEXP (pattern, i, j), n, stop))
565281806Srpaulo		!= NULL_RTX)
566281806Srpaulo	      return r;
567281806Srpaulo	  break;
568281806Srpaulo
569281806Srpaulo	case 'i': case 'w': case '0': case 's':
570281806Srpaulo	  break;
571281806Srpaulo
572281806Srpaulo	default:
573281806Srpaulo	  gcc_unreachable ();
574281806Srpaulo	}
575281806Srpaulo    }
576346981Scy
577346981Scy  return NULL;
578346981Scy}
579346981Scy
580346981Scy/* Search for and return operand M, such that it has a matching
581346981Scy   constraint for operand N.  */
582346981Scy
583346981Scystatic rtx
584346981Scyfind_matching_operand (rtx pattern, int n)
585346981Scy{
586346981Scy  const char *fmt;
587346981Scy  RTX_CODE code;
588346981Scy  int i, j, len;
589346981Scy  rtx r;
590346981Scy
591346981Scy  code = GET_CODE (pattern);
592346981Scy  if (code == MATCH_OPERAND
593346981Scy      && (XSTR (pattern, 2)[0] == '0' + n
594346981Scy	  || (XSTR (pattern, 2)[0] == '%'
595346981Scy	      && XSTR (pattern, 2)[1] == '0' + n)))
596346981Scy    return pattern;
597346981Scy
598346981Scy  fmt = GET_RTX_FORMAT (code);
599346981Scy  len = GET_RTX_LENGTH (code);
600346981Scy  for (i = 0; i < len; i++)
601346981Scy    {
602346981Scy      switch (fmt[i])
603346981Scy	{
604346981Scy	case 'e': case 'u':
605346981Scy	  if ((r = find_matching_operand (XEXP (pattern, i), n)))
606346981Scy	    return r;
607346981Scy	  break;
608346981Scy
609346981Scy	case 'V':
610346981Scy	  if (! XVEC (pattern, i))
611346981Scy	    break;
612346981Scy	  /* Fall through.  */
613346981Scy
614346981Scy	case 'E':
615346981Scy	  for (j = 0; j < XVECLEN (pattern, i); j++)
616346981Scy	    if ((r = find_matching_operand (XVECEXP (pattern, i, j), n)))
617346981Scy	      return r;
618346981Scy	  break;
619346981Scy
620346981Scy	case 'i': case 'w': case '0': case 's':
621346981Scy	  break;
622346981Scy
623346981Scy	default:
624346981Scy	  gcc_unreachable ();
625346981Scy	}
626346981Scy    }
627346981Scy
628346981Scy  return NULL;
629346981Scy}
630346981Scy
631346981Scy
632346981Scy/* Check for various errors in patterns.  SET is nonnull for a destination,
633346981Scy   and is the complete set pattern.  SET_CODE is '=' for normal sets, and
634346981Scy   '+' within a context that requires in-out constraints.  */
635346981Scy
636346981Scystatic void
637346981Scyvalidate_pattern (rtx pattern, rtx insn, rtx set, int set_code)
638346981Scy{
639346981Scy  const char *fmt;
640346981Scy  RTX_CODE code;
641346981Scy  size_t i, len;
642346981Scy  int j;
643346981Scy
644346981Scy  code = GET_CODE (pattern);
645346981Scy  switch (code)
646346981Scy    {
647346981Scy    case MATCH_SCRATCH:
648346981Scy      return;
649346981Scy    case MATCH_DUP:
650346981Scy    case MATCH_OP_DUP:
651346981Scy    case MATCH_PAR_DUP:
652346981Scy      if (find_operand (insn, XINT (pattern, 0), pattern) == pattern)
653346981Scy	{
654346981Scy	  message_with_line (pattern_lineno,
655346981Scy			     "operand %i duplicated before defined",
656346981Scy			     XINT (pattern, 0));
657346981Scy          error_count++;
658346981Scy	}
659281806Srpaulo      break;
660281806Srpaulo    case MATCH_OPERAND:
661281806Srpaulo    case MATCH_OPERATOR:
662281806Srpaulo      {
663281806Srpaulo	const char *pred_name = XSTR (pattern, 1);
664281806Srpaulo	const struct pred_data *pred;
665281806Srpaulo	const char *c_test;
666281806Srpaulo
667281806Srpaulo	if (GET_CODE (insn) == DEFINE_INSN)
668281806Srpaulo	  c_test = XSTR (insn, 2);
669281806Srpaulo	else
670281806Srpaulo	  c_test = XSTR (insn, 1);
671281806Srpaulo
672281806Srpaulo	if (pred_name[0] != 0)
673346981Scy	  {
674346981Scy	    pred = lookup_predicate (pred_name);
675346981Scy	    if (!pred)
676346981Scy	      message_with_line (pattern_lineno,
677346981Scy				 "warning: unknown predicate '%s'",
678346981Scy				 pred_name);
679281806Srpaulo	  }
680281806Srpaulo	else
681281806Srpaulo	  pred = 0;
682281806Srpaulo
683346981Scy	if (code == MATCH_OPERAND)
684346981Scy	  {
685281806Srpaulo	    const char constraints0 = XSTR (pattern, 2)[0];
686346981Scy
687281806Srpaulo	    /* In DEFINE_EXPAND, DEFINE_SPLIT, and DEFINE_PEEPHOLE2, we
688281806Srpaulo	       don't use the MATCH_OPERAND constraint, only the predicate.
689281806Srpaulo	       This is confusing to folks doing new ports, so help them
690281806Srpaulo	       not make the mistake.  */
691281806Srpaulo	    if (GET_CODE (insn) == DEFINE_EXPAND
692281806Srpaulo		|| GET_CODE (insn) == DEFINE_SPLIT
693281806Srpaulo		|| GET_CODE (insn) == DEFINE_PEEPHOLE2)
694346981Scy	      {
695281806Srpaulo		if (constraints0)
696281806Srpaulo		  message_with_line (pattern_lineno,
697281806Srpaulo				     "warning: constraints not supported in %s",
698281806Srpaulo				     rtx_name[GET_CODE (insn)]);
699281806Srpaulo	      }
700281806Srpaulo
701281806Srpaulo	    /* A MATCH_OPERAND that is a SET should have an output reload.  */
702281806Srpaulo	    else if (set && constraints0)
703281806Srpaulo	      {
704281806Srpaulo		if (set_code == '+')
705281806Srpaulo		  {
706281806Srpaulo		    if (constraints0 == '+')
707281806Srpaulo		      ;
708281806Srpaulo		    /* If we've only got an output reload for this operand,
709281806Srpaulo		       we'd better have a matching input operand.  */
710281806Srpaulo		    else if (constraints0 == '='
711281806Srpaulo			     && find_matching_operand (insn, XINT (pattern, 0)))
712281806Srpaulo		      ;
713281806Srpaulo		    else
714346981Scy		      {
715346981Scy			message_with_line (pattern_lineno,
716346981Scy					   "operand %d missing in-out reload",
717346981Scy					   XINT (pattern, 0));
718346981Scy			error_count++;
719346981Scy		      }
720346981Scy		  }
721281806Srpaulo		else if (constraints0 != '=' && constraints0 != '+')
722281806Srpaulo		  {
723281806Srpaulo		    message_with_line (pattern_lineno,
724281806Srpaulo				       "operand %d missing output reload",
725281806Srpaulo				       XINT (pattern, 0));
726281806Srpaulo		    error_count++;
727281806Srpaulo		  }
728281806Srpaulo	      }
729346981Scy	  }
730346981Scy
731346981Scy	/* Allowing non-lvalues in destinations -- particularly CONST_INT --
732346981Scy	   while not likely to occur at runtime, results in less efficient
733346981Scy	   code from insn-recog.c.  */
734346981Scy	if (set && pred && pred->allows_non_lvalue)
735346981Scy	  message_with_line (pattern_lineno,
736346981Scy			     "warning: destination operand %d "
737346981Scy			     "allows non-lvalue",
738346981Scy			     XINT (pattern, 0));
739346981Scy
740346981Scy	/* A modeless MATCH_OPERAND can be handy when we can check for
741346981Scy	   multiple modes in the c_test.  In most other cases, it is a
742346981Scy	   mistake.  Only DEFINE_INSN is eligible, since SPLIT and
743346981Scy	   PEEP2 can FAIL within the output pattern.  Exclude special
744346981Scy	   predicates, which check the mode themselves.  Also exclude
745346981Scy	   predicates that allow only constants.  Exclude the SET_DEST
746281806Srpaulo	   of a call instruction, as that is a common idiom.  */
747281806Srpaulo
748281806Srpaulo	if (GET_MODE (pattern) == VOIDmode
749281806Srpaulo	    && code == MATCH_OPERAND
750281806Srpaulo	    && GET_CODE (insn) == DEFINE_INSN
751281806Srpaulo	    && pred
752281806Srpaulo	    && !pred->special
753281806Srpaulo	    && pred->allows_non_const
754281806Srpaulo	    && strstr (c_test, "operands") == NULL
755281806Srpaulo	    && ! (set
756281806Srpaulo		  && GET_CODE (set) == SET
757281806Srpaulo		  && GET_CODE (SET_SRC (set)) == CALL))
758281806Srpaulo	  message_with_line (pattern_lineno,
759281806Srpaulo			     "warning: operand %d missing mode?",
760281806Srpaulo			     XINT (pattern, 0));
761281806Srpaulo	return;
762281806Srpaulo      }
763281806Srpaulo
764281806Srpaulo    case SET:
765281806Srpaulo      {
766346981Scy	enum machine_mode dmode, smode;
767346981Scy	rtx dest, src;
768281806Srpaulo
769346981Scy	dest = SET_DEST (pattern);
770346981Scy	src = SET_SRC (pattern);
771281806Srpaulo
772281806Srpaulo	/* STRICT_LOW_PART is a wrapper.  Its argument is the real
773281806Srpaulo	   destination, and it's mode should match the source.  */
774281806Srpaulo	if (GET_CODE (dest) == STRICT_LOW_PART)
775281806Srpaulo	  dest = XEXP (dest, 0);
776281806Srpaulo
777281806Srpaulo	/* Find the referent for a DUP.  */
778281806Srpaulo
779281806Srpaulo	if (GET_CODE (dest) == MATCH_DUP
780281806Srpaulo	    || GET_CODE (dest) == MATCH_OP_DUP
781346981Scy	    || GET_CODE (dest) == MATCH_PAR_DUP)
782346981Scy	  dest = find_operand (insn, XINT (dest, 0), NULL);
783346981Scy
784346981Scy	if (GET_CODE (src) == MATCH_DUP
785346981Scy	    || GET_CODE (src) == MATCH_OP_DUP
786281806Srpaulo	    || GET_CODE (src) == MATCH_PAR_DUP)
787281806Srpaulo	  src = find_operand (insn, XINT (src, 0), NULL);
788281806Srpaulo
789281806Srpaulo	dmode = GET_MODE (dest);
790281806Srpaulo	smode = GET_MODE (src);
791281806Srpaulo
792281806Srpaulo	/* The mode of an ADDRESS_OPERAND is the mode of the memory
793346981Scy	   reference, not the mode of the address.  */
794281806Srpaulo	if (GET_CODE (src) == MATCH_OPERAND
795281806Srpaulo	    && ! strcmp (XSTR (src, 1), "address_operand"))
796281806Srpaulo	  ;
797281806Srpaulo
798281806Srpaulo        /* The operands of a SET must have the same mode unless one
799281806Srpaulo	   is VOIDmode.  */
800281806Srpaulo        else if (dmode != VOIDmode && smode != VOIDmode && dmode != smode)
801281806Srpaulo	  {
802346981Scy	    message_with_line (pattern_lineno,
803281806Srpaulo			       "mode mismatch in set: %smode vs %smode",
804281806Srpaulo			       GET_MODE_NAME (dmode), GET_MODE_NAME (smode));
805281806Srpaulo	    error_count++;
806281806Srpaulo	  }
807281806Srpaulo
808346981Scy	/* If only one of the operands is VOIDmode, and PC or CC0 is
809281806Srpaulo	   not involved, it's probably a mistake.  */
810281806Srpaulo	else if (dmode != smode
811346981Scy		 && GET_CODE (dest) != PC
812281806Srpaulo		 && GET_CODE (dest) != CC0
813281806Srpaulo		 && GET_CODE (src) != PC
814281806Srpaulo		 && GET_CODE (src) != CC0
815281806Srpaulo		 && GET_CODE (src) != CONST_INT)
816281806Srpaulo	  {
817281806Srpaulo	    const char *which;
818289549Srpaulo	    which = (dmode == VOIDmode ? "destination" : "source");
819281806Srpaulo	    message_with_line (pattern_lineno,
820346981Scy			       "warning: %s missing a mode?", which);
821281806Srpaulo	  }
822346981Scy
823281806Srpaulo	if (dest != SET_DEST (pattern))
824281806Srpaulo	  validate_pattern (dest, insn, pattern, '=');
825281806Srpaulo	validate_pattern (SET_DEST (pattern), insn, pattern, '=');
826281806Srpaulo        validate_pattern (SET_SRC (pattern), insn, NULL_RTX, 0);
827281806Srpaulo        return;
828281806Srpaulo      }
829281806Srpaulo
830281806Srpaulo    case CLOBBER:
831281806Srpaulo      validate_pattern (SET_DEST (pattern), insn, pattern, '=');
832281806Srpaulo      return;
833281806Srpaulo
834281806Srpaulo    case ZERO_EXTRACT:
835281806Srpaulo      validate_pattern (XEXP (pattern, 0), insn, set, set ? '+' : 0);
836346981Scy      validate_pattern (XEXP (pattern, 1), insn, NULL_RTX, 0);
837281806Srpaulo      validate_pattern (XEXP (pattern, 2), insn, NULL_RTX, 0);
838281806Srpaulo      return;
839281806Srpaulo
840281806Srpaulo    case STRICT_LOW_PART:
841281806Srpaulo      validate_pattern (XEXP (pattern, 0), insn, set, set ? '+' : 0);
842346981Scy      return;
843346981Scy
844346981Scy    case LABEL_REF:
845346981Scy      if (GET_MODE (XEXP (pattern, 0)) != VOIDmode)
846346981Scy	{
847346981Scy	  message_with_line (pattern_lineno,
848346981Scy			     "operand to label_ref %smode not VOIDmode",
849346981Scy			     GET_MODE_NAME (GET_MODE (XEXP (pattern, 0))));
850346981Scy	  error_count++;
851346981Scy	}
852346981Scy      break;
853346981Scy
854346981Scy    default:
855346981Scy      break;
856346981Scy    }
857346981Scy
858281806Srpaulo  fmt = GET_RTX_FORMAT (code);
859281806Srpaulo  len = GET_RTX_LENGTH (code);
860281806Srpaulo  for (i = 0; i < len; i++)
861281806Srpaulo    {
862281806Srpaulo      switch (fmt[i])
863281806Srpaulo	{
864281806Srpaulo	case 'e': case 'u':
865281806Srpaulo	  validate_pattern (XEXP (pattern, i), insn, NULL_RTX, 0);
866189251Ssam	  break;
867189251Ssam
868189251Ssam	case 'E':
869189251Ssam	  for (j = 0; j < XVECLEN (pattern, i); j++)
870189251Ssam	    validate_pattern (XVECEXP (pattern, i, j), insn, NULL_RTX, 0);
871189251Ssam	  break;
872189251Ssam
873189251Ssam	case 'i': case 'w': case '0': case 's':
874252726Srpaulo	  break;
875189251Ssam
876189251Ssam	default:
877189251Ssam	  gcc_unreachable ();
878189251Ssam	}
879189251Ssam    }
880189251Ssam}
881189251Ssam
882189251Ssam/* Create a chain of nodes to verify that an rtl expression matches
883252726Srpaulo   PATTERN.
884252726Srpaulo
885252726Srpaulo   LAST is a pointer to the listhead in the previous node in the chain (or
886252726Srpaulo   in the calling function, for the first node).
887189251Ssam
888189251Ssam   POSITION is the string representing the current position in the insn.
889189251Ssam
890189251Ssam   INSN_TYPE is the type of insn for which we are emitting code.
891189251Ssam
892189251Ssam   A pointer to the final node in the chain is returned.  */
893189251Ssam
894189251Ssamstatic struct decision *
895189251Ssamadd_to_sequence (rtx pattern, struct decision_head *last, const char *position,
896189251Ssam		 enum routine_type insn_type, int top)
897189251Ssam{
898189251Ssam  RTX_CODE code;
899189251Ssam  struct decision *this, *sub;
900189251Ssam  struct decision_test *test;
901189251Ssam  struct decision_test **place;
902189251Ssam  char *subpos;
903189251Ssam  size_t i;
904189251Ssam  const char *fmt;
905189251Ssam  int depth = strlen (position);
906189251Ssam  int len;
907189251Ssam  enum machine_mode mode;
908189251Ssam
909189251Ssam  if (depth > max_depth)
910189251Ssam    max_depth = depth;
911189251Ssam
912281806Srpaulo  subpos = xmalloc (depth + 2);
913189251Ssam  strcpy (subpos, position);
914189251Ssam  subpos[depth + 1] = 0;
915281806Srpaulo
916281806Srpaulo  sub = this = new_decision (position, last);
917189251Ssam  place = &this->tests;
918189251Ssam
919189251Ssam restart:
920189251Ssam  mode = GET_MODE (pattern);
921189251Ssam  code = GET_CODE (pattern);
922189251Ssam
923189251Ssam  switch (code)
924189251Ssam    {
925189251Ssam    case PARALLEL:
926189251Ssam      /* Toplevel peephole pattern.  */
927281806Srpaulo      if (insn_type == PEEPHOLE2 && top)
928189251Ssam	{
929189251Ssam	  int num_insns;
930281806Srpaulo
931281806Srpaulo	  /* Check we have sufficient insns.  This avoids complications
932281806Srpaulo	     because we then know peep2_next_insn never fails.  */
933281806Srpaulo	  num_insns = XVECLEN (pattern, 0);
934281806Srpaulo	  if (num_insns > 1)
935281806Srpaulo	    {
936281806Srpaulo	      test = new_decision_test (DT_num_insns, &place);
937281806Srpaulo	      test->u.num_insns = num_insns;
938281806Srpaulo	      last = &sub->success;
939189251Ssam	    }
940189251Ssam	  else
941189251Ssam	    {
942189251Ssam	      /* We don't need the node we just created -- unlink it.  */
943189251Ssam	      last->first = last->last = NULL;
944189251Ssam	    }
945189251Ssam
946189251Ssam	  for (i = 0; i < (size_t) XVECLEN (pattern, 0); i++)
947189251Ssam	    {
948189251Ssam	      /* Which insn we're looking at is represented by A-Z. We don't
949189251Ssam	         ever use 'A', however; it is always implied.  */
950189251Ssam
951189251Ssam	      subpos[depth] = (i > 0 ? 'A' + i : 0);
952189251Ssam	      sub = add_to_sequence (XVECEXP (pattern, 0, i),
953289549Srpaulo				     last, subpos, insn_type, 0);
954189251Ssam	      last = &sub->success;
955189251Ssam	    }
956189251Ssam	  goto ret;
957281806Srpaulo	}
958281806Srpaulo
959189251Ssam      /* Else nothing special.  */
960281806Srpaulo      break;
961189251Ssam
962189251Ssam    case MATCH_PARALLEL:
963281806Srpaulo      /* The explicit patterns within a match_parallel enforce a minimum
964189251Ssam	 length on the vector.  The match_parallel predicate may allow
965189251Ssam	 for more elements.  We do need to check for this minimum here
966189251Ssam	 or the code generated to match the internals may reference data
967189251Ssam	 beyond the end of the vector.  */
968189251Ssam      test = new_decision_test (DT_veclen_ge, &place);
969189251Ssam      test->u.veclen = XVECLEN (pattern, 2);
970189251Ssam      /* Fall through.  */
971189251Ssam
972189251Ssam    case MATCH_OPERAND:
973189251Ssam    case MATCH_SCRATCH:
974189251Ssam    case MATCH_OPERATOR:
975189251Ssam      {
976189251Ssam	RTX_CODE was_code = code;
977189251Ssam	const char *pred_name;
978189251Ssam	bool allows_const_int = true;
979189251Ssam
980189251Ssam	if (code == MATCH_SCRATCH)
981189251Ssam	  {
982189251Ssam	    pred_name = "scratch_operand";
983189251Ssam	    code = UNKNOWN;
984189251Ssam	  }
985189251Ssam	else
986189251Ssam	  {
987189251Ssam	    pred_name = XSTR (pattern, 1);
988252726Srpaulo	    if (code == MATCH_PARALLEL)
989252726Srpaulo	      code = PARALLEL;
990189251Ssam	    else
991189251Ssam	      code = UNKNOWN;
992189251Ssam	  }
993189251Ssam
994189251Ssam	if (pred_name[0] != 0)
995189251Ssam	  {
996189251Ssam	    const struct pred_data *pred;
997189251Ssam
998189251Ssam	    test = new_decision_test (DT_pred, &place);
999189251Ssam	    test->u.pred.name = pred_name;
1000189251Ssam	    test->u.pred.mode = mode;
1001189251Ssam
1002189251Ssam	    /* See if we know about this predicate.
1003189251Ssam	       If we do, remember it for use below.
1004189251Ssam
1005189251Ssam	       We can optimize the generated code a little if either
1006252726Srpaulo	       (a) the predicate only accepts one code, or (b) the
1007252726Srpaulo	       predicate does not allow CONST_INT, in which case it
1008189251Ssam	       can match only if the modes match.  */
1009189251Ssam	    pred = lookup_predicate (pred_name);
1010189251Ssam	    if (pred)
1011189251Ssam	      {
1012189251Ssam		test->u.pred.data = pred;
1013189251Ssam		allows_const_int = pred->codes[CONST_INT];
1014189251Ssam		if (was_code == MATCH_PARALLEL
1015189251Ssam		    && pred->singleton != PARALLEL)
1016189251Ssam		  message_with_line (pattern_lineno,
1017189251Ssam			"predicate '%s' used in match_parallel "
1018189251Ssam			"does not allow only PARALLEL", pred->name);
1019189251Ssam		else
1020189251Ssam		  code = pred->singleton;
1021189251Ssam	      }
1022189251Ssam	    else
1023189251Ssam	      message_with_line (pattern_lineno,
1024189251Ssam			"warning: unknown predicate '%s' in '%s' expression",
1025189251Ssam			pred_name, GET_RTX_NAME (was_code));
1026189251Ssam	  }
1027189251Ssam
1028189251Ssam	/* Can't enforce a mode if we allow const_int.  */
1029189251Ssam	if (allows_const_int)
1030189251Ssam	  mode = VOIDmode;
1031189251Ssam
1032189251Ssam	/* Accept the operand, i.e. record it in `operands'.  */
1033189251Ssam	test = new_decision_test (DT_accept_op, &place);
1034189251Ssam	test->u.opno = XINT (pattern, 0);
1035189251Ssam
1036346981Scy	if (was_code == MATCH_OPERATOR || was_code == MATCH_PARALLEL)
1037346981Scy	  {
1038189251Ssam	    char base = (was_code == MATCH_OPERATOR ? '0' : 'a');
1039189251Ssam	    for (i = 0; i < (size_t) XVECLEN (pattern, 2); i++)
1040189251Ssam	      {
1041189251Ssam		subpos[depth] = i + base;
1042189251Ssam		sub = add_to_sequence (XVECEXP (pattern, 2, i),
1043189251Ssam				       &sub->success, subpos, insn_type, 0);
1044189251Ssam	      }
1045189251Ssam	  }
1046189251Ssam	goto fini;
1047189251Ssam      }
1048189251Ssam
1049189251Ssam    case MATCH_OP_DUP:
1050189251Ssam      code = UNKNOWN;
1051189251Ssam
1052189251Ssam      test = new_decision_test (DT_dup, &place);
1053189251Ssam      test->u.dup = XINT (pattern, 0);
1054189251Ssam
1055189251Ssam      test = new_decision_test (DT_accept_op, &place);
1056189251Ssam      test->u.opno = XINT (pattern, 0);
1057189251Ssam
1058189251Ssam      for (i = 0; i < (size_t) XVECLEN (pattern, 1); i++)
1059189251Ssam	{
1060346981Scy	  subpos[depth] = i + '0';
1061346981Scy	  sub = add_to_sequence (XVECEXP (pattern, 1, i),
1062346981Scy				 &sub->success, subpos, insn_type, 0);
1063346981Scy	}
1064346981Scy      goto fini;
1065189251Ssam
1066189251Ssam    case MATCH_DUP:
1067189251Ssam    case MATCH_PAR_DUP:
1068189251Ssam      code = UNKNOWN;
1069189251Ssam
1070189251Ssam      test = new_decision_test (DT_dup, &place);
1071189251Ssam      test->u.dup = XINT (pattern, 0);
1072189251Ssam      goto fini;
1073189251Ssam
1074189251Ssam    case ADDRESS:
1075189251Ssam      pattern = XEXP (pattern, 0);
1076189251Ssam      goto restart;
1077189251Ssam
1078189251Ssam    default:
1079189251Ssam      break;
1080189251Ssam    }
1081189251Ssam
1082189251Ssam  fmt = GET_RTX_FORMAT (code);
1083189251Ssam  len = GET_RTX_LENGTH (code);
1084189251Ssam
1085189251Ssam  /* Do tests against the current node first.  */
1086189251Ssam  for (i = 0; i < (size_t) len; i++)
1087189251Ssam    {
1088189251Ssam      if (fmt[i] == 'i')
1089189251Ssam	{
1090189251Ssam	  gcc_assert (i < 2);
1091189251Ssam
1092189251Ssam	  if (!i)
1093189251Ssam	    {
1094189251Ssam	      test = new_decision_test (DT_elt_zero_int, &place);
1095189251Ssam	      test->u.intval = XINT (pattern, i);
1096189251Ssam	    }
1097189251Ssam	  else
1098189251Ssam	    {
1099189251Ssam	      test = new_decision_test (DT_elt_one_int, &place);
1100189251Ssam	      test->u.intval = XINT (pattern, i);
1101189251Ssam	    }
1102189251Ssam	}
1103189251Ssam      else if (fmt[i] == 'w')
1104189251Ssam	{
1105189251Ssam	  /* If this value actually fits in an int, we can use a switch
1106189251Ssam	     statement here, so indicate that.  */
1107189251Ssam	  enum decision_type type
1108189251Ssam	    = ((int) XWINT (pattern, i) == XWINT (pattern, i))
1109189251Ssam	      ? DT_elt_zero_wide_safe : DT_elt_zero_wide;
1110189251Ssam
1111189251Ssam	  gcc_assert (!i);
1112189251Ssam
1113189251Ssam	  test = new_decision_test (type, &place);
1114189251Ssam	  test->u.intval = XWINT (pattern, i);
1115189251Ssam	}
1116189251Ssam      else if (fmt[i] == 'E')
1117189251Ssam	{
1118189251Ssam	  gcc_assert (!i);
1119189251Ssam
1120189251Ssam	  test = new_decision_test (DT_veclen, &place);
1121189251Ssam	  test->u.veclen = XVECLEN (pattern, i);
1122189251Ssam	}
1123189251Ssam    }
1124189251Ssam
1125189251Ssam  /* Now test our sub-patterns.  */
1126189251Ssam  for (i = 0; i < (size_t) len; i++)
1127189251Ssam    {
1128189251Ssam      switch (fmt[i])
1129189251Ssam	{
1130189251Ssam	case 'e': case 'u':
1131189251Ssam	  subpos[depth] = '0' + i;
1132189251Ssam	  sub = add_to_sequence (XEXP (pattern, i), &sub->success,
1133189251Ssam				 subpos, insn_type, 0);
1134189251Ssam	  break;
1135189251Ssam
1136189251Ssam	case 'E':
1137189251Ssam	  {
1138189251Ssam	    int j;
1139189251Ssam	    for (j = 0; j < XVECLEN (pattern, i); j++)
1140189251Ssam	      {
1141189251Ssam		subpos[depth] = 'a' + j;
1142189251Ssam		sub = add_to_sequence (XVECEXP (pattern, i, j),
1143189251Ssam				       &sub->success, subpos, insn_type, 0);
1144189251Ssam	      }
1145189251Ssam	    break;
1146189251Ssam	  }
1147189251Ssam
1148189251Ssam	case 'i': case 'w':
1149189251Ssam	  /* Handled above.  */
1150189251Ssam	  break;
1151189251Ssam	case '0':
1152189251Ssam	  break;
1153189251Ssam
1154189251Ssam	default:
1155189251Ssam	  gcc_unreachable ();
1156189251Ssam	}
1157189251Ssam    }
1158189251Ssam
1159189251Ssam fini:
1160189251Ssam  /* Insert nodes testing mode and code, if they're still relevant,
1161189251Ssam     before any of the nodes we may have added above.  */
1162189251Ssam  if (code != UNKNOWN)
1163189251Ssam    {
1164189251Ssam      place = &this->tests;
1165189251Ssam      test = new_decision_test (DT_code, &place);
1166289549Srpaulo      test->u.code = code;
1167189251Ssam    }
1168189251Ssam
1169189251Ssam  if (mode != VOIDmode)
1170189251Ssam    {
1171289549Srpaulo      place = &this->tests;
1172189251Ssam      test = new_decision_test (DT_mode, &place);
1173189251Ssam      test->u.mode = mode;
1174189251Ssam    }
1175189251Ssam
1176189251Ssam  /* If we didn't insert any tests or accept nodes, hork.  */
1177189251Ssam  gcc_assert (this->tests);
1178189251Ssam
1179189251Ssam ret:
1180189251Ssam  free (subpos);
1181189251Ssam  return sub;
1182189251Ssam}
1183189251Ssam
1184189251Ssam/* A subroutine of maybe_both_true; examines only one test.
1185189251Ssam   Returns > 0 for "definitely both true" and < 0 for "maybe both true".  */
1186281806Srpaulo
1187281806Srpaulostatic int
1188281806Srpaulomaybe_both_true_2 (struct decision_test *d1, struct decision_test *d2)
1189281806Srpaulo{
1190281806Srpaulo  if (d1->type == d2->type)
1191281806Srpaulo    {
1192281806Srpaulo      switch (d1->type)
1193281806Srpaulo	{
1194281806Srpaulo	case DT_num_insns:
1195189251Ssam	  if (d1->u.num_insns == d2->u.num_insns)
1196189251Ssam	    return 1;
1197189251Ssam	  else
1198189251Ssam	    return -1;
1199189251Ssam
1200189251Ssam	case DT_mode:
1201189251Ssam	  return d1->u.mode == d2->u.mode;
1202189251Ssam
1203189251Ssam	case DT_code:
1204189251Ssam	  return d1->u.code == d2->u.code;
1205189251Ssam
1206189251Ssam	case DT_veclen:
1207189251Ssam	  return d1->u.veclen == d2->u.veclen;
1208281806Srpaulo
1209281806Srpaulo	case DT_elt_zero_int:
1210281806Srpaulo	case DT_elt_one_int:
1211281806Srpaulo	case DT_elt_zero_wide:
1212281806Srpaulo	case DT_elt_zero_wide_safe:
1213281806Srpaulo	  return d1->u.intval == d2->u.intval;
1214281806Srpaulo
1215281806Srpaulo	default:
1216281806Srpaulo	  break;
1217281806Srpaulo	}
1218281806Srpaulo    }
1219189251Ssam
1220189251Ssam  /* If either has a predicate that we know something about, set
1221189251Ssam     things up so that D1 is the one that always has a known
1222189251Ssam     predicate.  Then see if they have any codes in common.  */
1223189251Ssam
1224189251Ssam  if (d1->type == DT_pred || d2->type == DT_pred)
1225189251Ssam    {
1226189251Ssam      if (d2->type == DT_pred)
1227189251Ssam	{
1228189251Ssam	  struct decision_test *tmp;
1229189251Ssam	  tmp = d1, d1 = d2, d2 = tmp;
1230189251Ssam	}
1231189251Ssam
1232189251Ssam      /* If D2 tests a mode, see if it matches D1.  */
1233189251Ssam      if (d1->u.pred.mode != VOIDmode)
1234189251Ssam	{
1235189251Ssam	  if (d2->type == DT_mode)
1236189251Ssam	    {
1237189251Ssam	      if (d1->u.pred.mode != d2->u.mode
1238189251Ssam		  /* The mode of an address_operand predicate is the
1239189251Ssam		     mode of the memory, not the operand.  It can only
1240189251Ssam		     be used for testing the predicate, so we must
1241189251Ssam		     ignore it here.  */
1242189251Ssam		  && strcmp (d1->u.pred.name, "address_operand") != 0)
1243189251Ssam		return 0;
1244189251Ssam	    }
1245189251Ssam	  /* Don't check two predicate modes here, because if both predicates
1246189251Ssam	     accept CONST_INT, then both can still be true even if the modes
1247189251Ssam	     are different.  If they don't accept CONST_INT, there will be a
1248189251Ssam	     separate DT_mode that will make maybe_both_true_1 return 0.  */
1249189251Ssam	}
1250281806Srpaulo
1251281806Srpaulo      if (d1->u.pred.data)
1252189251Ssam	{
1253189251Ssam	  /* If D2 tests a code, see if it is in the list of valid
1254189251Ssam	     codes for D1's predicate.  */
1255189251Ssam	  if (d2->type == DT_code)
1256189251Ssam	    {
1257189251Ssam	      if (!d1->u.pred.data->codes[d2->u.code])
1258189251Ssam		return 0;
1259189251Ssam	    }
1260189251Ssam
1261189251Ssam	  /* Otherwise see if the predicates have any codes in common.  */
1262189251Ssam	  else if (d2->type == DT_pred && d2->u.pred.data)
1263189251Ssam	    {
1264189251Ssam	      bool common = false;
1265189251Ssam	      enum rtx_code c;
1266189251Ssam
1267189251Ssam	      for (c = 0; c < NUM_RTX_CODE; c++)
1268189251Ssam		if (d1->u.pred.data->codes[c] && d2->u.pred.data->codes[c])
1269189251Ssam		  {
1270189251Ssam		    common = true;
1271189251Ssam		    break;
1272189251Ssam		  }
1273189251Ssam
1274189251Ssam	      if (!common)
1275189251Ssam		return 0;
1276189251Ssam	    }
1277189251Ssam	}
1278189251Ssam    }
1279189251Ssam
1280189251Ssam  /* Tests vs veclen may be known when strict equality is involved.  */
1281281806Srpaulo  if (d1->type == DT_veclen && d2->type == DT_veclen_ge)
1282281806Srpaulo    return d1->u.veclen >= d2->u.veclen;
1283281806Srpaulo  if (d1->type == DT_veclen_ge && d2->type == DT_veclen)
1284281806Srpaulo    return d2->u.veclen >= d1->u.veclen;
1285281806Srpaulo
1286281806Srpaulo  return -1;
1287281806Srpaulo}
1288281806Srpaulo
1289189251Ssam/* A subroutine of maybe_both_true; examines all the tests for a given node.
1290189251Ssam   Returns > 0 for "definitely both true" and < 0 for "maybe both true".  */
1291281806Srpaulo
1292281806Srpaulostatic int
1293281806Srpaulomaybe_both_true_1 (struct decision_test *d1, struct decision_test *d2)
1294189251Ssam{
1295189251Ssam  struct decision_test *t1, *t2;
1296189251Ssam
1297189251Ssam  /* A match_operand with no predicate can match anything.  Recognize
1298189251Ssam     this by the existence of a lone DT_accept_op test.  */
1299189251Ssam  if (d1->type == DT_accept_op || d2->type == DT_accept_op)
1300189251Ssam    return 1;
1301189251Ssam
1302189251Ssam  /* Eliminate pairs of tests while they can exactly match.  */
1303189251Ssam  while (d1 && d2 && d1->type == d2->type)
1304189251Ssam    {
1305189251Ssam      if (maybe_both_true_2 (d1, d2) == 0)
1306189251Ssam	return 0;
1307189251Ssam      d1 = d1->next, d2 = d2->next;
1308189251Ssam    }
1309189251Ssam
1310189251Ssam  /* After that, consider all pairs.  */
1311189251Ssam  for (t1 = d1; t1 ; t1 = t1->next)
1312189251Ssam    for (t2 = d2; t2 ; t2 = t2->next)
1313189251Ssam      if (maybe_both_true_2 (t1, t2) == 0)
1314189251Ssam	return 0;
1315189251Ssam
1316189251Ssam  return -1;
1317189251Ssam}
1318189251Ssam
1319189251Ssam/* Return 0 if we can prove that there is no RTL that can match both
1320189251Ssam   D1 and D2.  Otherwise, return 1 (it may be that there is an RTL that
1321189251Ssam   can match both or just that we couldn't prove there wasn't such an RTL).
1322189251Ssam
1323189251Ssam   TOPLEVEL is nonzero if we are to only look at the top level and not
1324189251Ssam   recursively descend.  */
1325189251Ssam
1326189251Ssamstatic int
1327189251Ssammaybe_both_true (struct decision *d1, struct decision *d2,
1328189251Ssam		 int toplevel)
1329189251Ssam{
1330189251Ssam  struct decision *p1, *p2;
1331189251Ssam  int cmp;
1332189251Ssam
1333189251Ssam  /* Don't compare strings on the different positions in insn.  Doing so
1334189251Ssam     is incorrect and results in false matches from constructs like
1335189251Ssam
1336189251Ssam	[(set (subreg:HI (match_operand:SI "register_operand" "r") 0)
1337189251Ssam	      (subreg:HI (match_operand:SI "register_operand" "r") 0))]
1338189251Ssam     vs
1339189251Ssam	[(set (match_operand:HI "register_operand" "r")
1340189251Ssam	      (match_operand:HI "register_operand" "r"))]
1341189251Ssam
1342189251Ssam     If we are presented with such, we are recursing through the remainder
1343189251Ssam     of a node's success nodes (from the loop at the end of this function).
1344189251Ssam     Skip forward until we come to a position that matches.
1345189251Ssam
1346189251Ssam     Due to the way position strings are constructed, we know that iterating
1347189251Ssam     forward from the lexically lower position (e.g. "00") will run into
1348189251Ssam     the lexically higher position (e.g. "1") and not the other way around.
1349189251Ssam     This saves a bit of effort.  */
1350189251Ssam
1351189251Ssam  cmp = strcmp (d1->position, d2->position);
1352189251Ssam  if (cmp != 0)
1353189251Ssam    {
1354189251Ssam      gcc_assert (!toplevel);
1355189251Ssam
1356189251Ssam      /* If the d2->position was lexically lower, swap.  */
1357189251Ssam      if (cmp > 0)
1358189251Ssam	p1 = d1, d1 = d2, d2 = p1;
1359189251Ssam
1360189251Ssam      if (d1->success.first == 0)
1361189251Ssam	return 1;
1362189251Ssam      for (p1 = d1->success.first; p1; p1 = p1->next)
1363189251Ssam	if (maybe_both_true (p1, d2, 0))
1364189251Ssam	  return 1;
1365189251Ssam
1366189251Ssam      return 0;
1367189251Ssam    }
1368189251Ssam
1369189251Ssam  /* Test the current level.  */
1370189251Ssam  cmp = maybe_both_true_1 (d1->tests, d2->tests);
1371189251Ssam  if (cmp >= 0)
1372189251Ssam    return cmp;
1373189251Ssam
1374189251Ssam  /* We can't prove that D1 and D2 cannot both be true.  If we are only
1375189251Ssam     to check the top level, return 1.  Otherwise, see if we can prove
1376189251Ssam     that all choices in both successors are mutually exclusive.  If
1377189251Ssam     either does not have any successors, we can't prove they can't both
1378189251Ssam     be true.  */
1379189251Ssam
1380189251Ssam  if (toplevel || d1->success.first == 0 || d2->success.first == 0)
1381189251Ssam    return 1;
1382189251Ssam
1383189251Ssam  for (p1 = d1->success.first; p1; p1 = p1->next)
1384189251Ssam    for (p2 = d2->success.first; p2; p2 = p2->next)
1385189251Ssam      if (maybe_both_true (p1, p2, 0))
1386189251Ssam	return 1;
1387189251Ssam
1388189251Ssam  return 0;
1389189251Ssam}
1390189251Ssam
1391189251Ssam/* A subroutine of nodes_identical.  Examine two tests for equivalence.  */
1392189251Ssam
1393189251Ssamstatic int
1394189251Ssamnodes_identical_1 (struct decision_test *d1, struct decision_test *d2)
1395189251Ssam{
1396189251Ssam  switch (d1->type)
1397189251Ssam    {
1398189251Ssam    case DT_num_insns:
1399189251Ssam      return d1->u.num_insns == d2->u.num_insns;
1400189251Ssam
1401189251Ssam    case DT_mode:
1402189251Ssam      return d1->u.mode == d2->u.mode;
1403189251Ssam
1404189251Ssam    case DT_code:
1405189251Ssam      return d1->u.code == d2->u.code;
1406189251Ssam
1407189251Ssam    case DT_pred:
1408189251Ssam      return (d1->u.pred.mode == d2->u.pred.mode
1409189251Ssam	      && strcmp (d1->u.pred.name, d2->u.pred.name) == 0);
1410189251Ssam
1411189251Ssam    case DT_c_test:
1412189251Ssam      return strcmp (d1->u.c_test, d2->u.c_test) == 0;
1413189251Ssam
1414189251Ssam    case DT_veclen:
1415189251Ssam    case DT_veclen_ge:
1416189251Ssam      return d1->u.veclen == d2->u.veclen;
1417189251Ssam
1418189251Ssam    case DT_dup:
1419189251Ssam      return d1->u.dup == d2->u.dup;
1420189251Ssam
1421189251Ssam    case DT_elt_zero_int:
1422189251Ssam    case DT_elt_one_int:
1423189251Ssam    case DT_elt_zero_wide:
1424189251Ssam    case DT_elt_zero_wide_safe:
1425189251Ssam      return d1->u.intval == d2->u.intval;
1426189251Ssam
1427189251Ssam    case DT_accept_op:
1428189251Ssam      return d1->u.opno == d2->u.opno;
1429189251Ssam
1430189251Ssam    case DT_accept_insn:
1431189251Ssam      /* Differences will be handled in merge_accept_insn.  */
1432189251Ssam      return 1;
1433189251Ssam
1434189251Ssam    default:
1435189251Ssam      gcc_unreachable ();
1436189251Ssam    }
1437189251Ssam}
1438189251Ssam
1439189251Ssam/* True iff the two nodes are identical (on one level only).  Due
1440189251Ssam   to the way these lists are constructed, we shouldn't have to
1441189251Ssam   consider different orderings on the tests.  */
1442189251Ssam
1443189251Ssamstatic int
1444189251Ssamnodes_identical (struct decision *d1, struct decision *d2)
1445189251Ssam{
1446189251Ssam  struct decision_test *t1, *t2;
1447189251Ssam
1448189251Ssam  for (t1 = d1->tests, t2 = d2->tests; t1 && t2; t1 = t1->next, t2 = t2->next)
1449189251Ssam    {
1450189251Ssam      if (t1->type != t2->type)
1451189251Ssam	return 0;
1452189251Ssam      if (! nodes_identical_1 (t1, t2))
1453189251Ssam	return 0;
1454189251Ssam    }
1455189251Ssam
1456189251Ssam  /* For success, they should now both be null.  */
1457189251Ssam  if (t1 != t2)
1458189251Ssam    return 0;
1459189251Ssam
1460189251Ssam  /* Check that their subnodes are at the same position, as any one set
1461189251Ssam     of sibling decisions must be at the same position.  Allowing this
1462189251Ssam     requires complications to find_afterward and when change_state is
1463189251Ssam     invoked.  */
1464189251Ssam  if (d1->success.first
1465252726Srpaulo      && d2->success.first
1466252726Srpaulo      && strcmp (d1->success.first->position, d2->success.first->position))
1467189251Ssam    return 0;
1468189251Ssam
1469189251Ssam  return 1;
1470281806Srpaulo}
1471189251Ssam
1472252726Srpaulo/* A subroutine of merge_trees; given two nodes that have been declared
1473252726Srpaulo   identical, cope with two insn accept states.  If they differ in the
1474252726Srpaulo   number of clobbers, then the conflict was created by make_insn_sequence
1475252726Srpaulo   and we can drop the with-clobbers version on the floor.  If both
1476252726Srpaulo   nodes have no additional clobbers, we have found an ambiguity in the
1477189251Ssam   source machine description.  */
1478189251Ssam
1479189251Ssamstatic void
1480189251Ssammerge_accept_insn (struct decision *oldd, struct decision *addd)
1481189251Ssam{
1482189251Ssam  struct decision_test *old, *add;
1483189251Ssam
1484189251Ssam  for (old = oldd->tests; old; old = old->next)
1485189251Ssam    if (old->type == DT_accept_insn)
1486189251Ssam      break;
1487252726Srpaulo  if (old == NULL)
1488189251Ssam    return;
1489189251Ssam
1490189251Ssam  for (add = addd->tests; add; add = add->next)
1491189251Ssam    if (add->type == DT_accept_insn)
1492252726Srpaulo      break;
1493252726Srpaulo  if (add == NULL)
1494252726Srpaulo    return;
1495252726Srpaulo
1496252726Srpaulo  /* If one node is for a normal insn and the second is for the base
1497252726Srpaulo     insn with clobbers stripped off, the second node should be ignored.  */
1498252726Srpaulo
1499252726Srpaulo  if (old->u.insn.num_clobbers_to_add == 0
1500252726Srpaulo      && add->u.insn.num_clobbers_to_add > 0)
1501252726Srpaulo    {
1502252726Srpaulo      /* Nothing to do here.  */
1503252726Srpaulo    }
1504252726Srpaulo  else if (old->u.insn.num_clobbers_to_add > 0
1505252726Srpaulo	   && add->u.insn.num_clobbers_to_add == 0)
1506281806Srpaulo    {
1507281806Srpaulo      /* In this case, replace OLD with ADD.  */
1508252726Srpaulo      old->u.insn = add->u.insn;
1509252726Srpaulo    }
1510252726Srpaulo  else
1511252726Srpaulo    {
1512252726Srpaulo      message_with_line (add->u.insn.lineno, "`%s' matches `%s'",
1513252726Srpaulo			 get_insn_name (add->u.insn.code_number),
1514252726Srpaulo			 get_insn_name (old->u.insn.code_number));
1515189251Ssam      message_with_line (old->u.insn.lineno, "previous definition of `%s'",
1516189251Ssam			 get_insn_name (old->u.insn.code_number));
1517189251Ssam      error_count++;
1518252726Srpaulo    }
1519189251Ssam}
1520189251Ssam
1521189251Ssam/* Merge two decision trees OLDH and ADDH, modifying OLDH destructively.  */
1522346981Scy
1523189251Ssamstatic void
1524189251Ssammerge_trees (struct decision_head *oldh, struct decision_head *addh)
1525189251Ssam{
1526189251Ssam  struct decision *next, *add;
1527189251Ssam
1528189251Ssam  if (addh->first == 0)
1529189251Ssam    return;
1530189251Ssam  if (oldh->first == 0)
1531189251Ssam    {
1532252726Srpaulo      *oldh = *addh;
1533252726Srpaulo      return;
1534252726Srpaulo    }
1535252726Srpaulo
1536252726Srpaulo  /* Trying to merge bits at different positions isn't possible.  */
1537346981Scy  gcc_assert (!strcmp (oldh->first->position, addh->first->position));
1538346981Scy
1539346981Scy  for (add = addh->first; add ; add = next)
1540346981Scy    {
1541346981Scy      struct decision *old, *insert_before = NULL;
1542346981Scy
1543346981Scy      next = add->next;
1544346981Scy
1545346981Scy      /* The semantics of pattern matching state that the tests are
1546346981Scy	 done in the order given in the MD file so that if an insn
1547346981Scy	 matches two patterns, the first one will be used.  However,
1548346981Scy	 in practice, most, if not all, patterns are unambiguous so
1549252726Srpaulo	 that their order is independent.  In that case, we can merge
1550252726Srpaulo	 identical tests and group all similar modes and codes together.
1551252726Srpaulo
1552252726Srpaulo	 Scan starting from the end of OLDH until we reach a point
1553252726Srpaulo	 where we reach the head of the list or where we pass a
1554189251Ssam	 pattern that could also be true if NEW is true.  If we find
1555189251Ssam	 an identical pattern, we can merge them.  Also, record the
1556189251Ssam	 last node that tests the same code and mode and the last one
1557252726Srpaulo	 that tests just the same mode.
1558252726Srpaulo
1559252726Srpaulo	 If we have no match, place NEW after the closest match we found.  */
1560252726Srpaulo
1561252726Srpaulo      for (old = oldh->last; old; old = old->prev)
1562252726Srpaulo	{
1563189251Ssam	  if (nodes_identical (old, add))
1564252726Srpaulo	    {
1565189251Ssam	      merge_accept_insn (old, add);
1566189251Ssam	      merge_trees (&old->success, &add->success);
1567189251Ssam	      goto merged_nodes;
1568189251Ssam	    }
1569189251Ssam
1570189251Ssam	  if (maybe_both_true (old, add, 0))
1571189251Ssam	    break;
1572189251Ssam
1573189251Ssam	  /* Insert the nodes in DT test type order, which is roughly
1574189251Ssam	     how expensive/important the test is.  Given that the tests
1575189251Ssam	     are also ordered within the list, examining the first is
1576189251Ssam	     sufficient.  */
1577252726Srpaulo	  if ((int) add->tests->type < (int) old->tests->type)
1578252726Srpaulo	    insert_before = old;
1579252726Srpaulo	}
1580252726Srpaulo
1581252726Srpaulo      if (insert_before == NULL)
1582252726Srpaulo	{
1583252726Srpaulo	  add->next = NULL;
1584252726Srpaulo	  add->prev = oldh->last;
1585252726Srpaulo	  oldh->last->next = add;
1586252726Srpaulo	  oldh->last = add;
1587252726Srpaulo	}
1588189251Ssam      else
1589189251Ssam	{
1590189251Ssam	  if ((add->prev = insert_before->prev) != NULL)
1591189251Ssam	    add->prev->next = add;
1592189251Ssam	  else
1593252726Srpaulo	    oldh->first = add;
1594189251Ssam	  add->next = insert_before;
1595189251Ssam	  insert_before->prev = add;
1596189251Ssam	}
1597189251Ssam
1598189251Ssam    merged_nodes:;
1599189251Ssam    }
1600189251Ssam}
1601189251Ssam
1602189251Ssam/* Walk the tree looking for sub-nodes that perform common tests.
1603189251Ssam   Factor out the common test into a new node.  This enables us
1604189251Ssam   (depending on the test type) to emit switch statements later.  */
1605189251Ssam
1606189251Ssamstatic void
1607189251Ssamfactor_tests (struct decision_head *head)
1608189251Ssam{
1609189251Ssam  struct decision *first, *next;
1610189251Ssam
1611189251Ssam  for (first = head->first; first && first->next; first = next)
1612189251Ssam    {
1613337817Scy      enum decision_type type;
1614189251Ssam      struct decision *new, *old_last;
1615189251Ssam
1616189251Ssam      type = first->tests->type;
1617189251Ssam      next = first->next;
1618189251Ssam
1619189251Ssam      /* Want at least two compatible sequential nodes.  */
1620189251Ssam      if (next->tests->type != type)
1621189251Ssam	continue;
1622189251Ssam
1623337817Scy      /* Don't want all node types, just those we can turn into
1624189251Ssam	 switch statements.  */
1625337817Scy      if (type != DT_mode
1626189251Ssam	  && type != DT_code
1627189251Ssam	  && type != DT_veclen
1628189251Ssam	  && type != DT_elt_zero_int
1629189251Ssam	  && type != DT_elt_one_int
1630189251Ssam	  && type != DT_elt_zero_wide_safe)
1631189251Ssam	continue;
1632189251Ssam
1633189251Ssam      /* If we'd been performing more than one test, create a new node
1634189251Ssam         below our first test.  */
1635189251Ssam      if (first->tests->next != NULL)
1636189251Ssam	{
1637189251Ssam	  new = new_decision (first->position, &first->success);
1638189251Ssam	  new->tests = first->tests->next;
1639189251Ssam	  first->tests->next = NULL;
1640189251Ssam	}
1641189251Ssam
1642189251Ssam      /* Crop the node tree off after our first test.  */
1643189251Ssam      first->next = NULL;
1644189251Ssam      old_last = head->last;
1645189251Ssam      head->last = first;
1646189251Ssam
1647189251Ssam      /* For each compatible test, adjust to perform only one test in
1648189251Ssam	 the top level node, then merge the node back into the tree.  */
1649189251Ssam      do
1650189251Ssam	{
1651189251Ssam	  struct decision_head h;
1652189251Ssam
1653189251Ssam	  if (next->tests->next != NULL)
1654189251Ssam	    {
1655189251Ssam	      new = new_decision (next->position, &next->success);
1656189251Ssam	      new->tests = next->tests->next;
1657189251Ssam	      next->tests->next = NULL;
1658189251Ssam	    }
1659189251Ssam	  new = next;
1660189251Ssam	  next = next->next;
1661189251Ssam	  new->next = NULL;
1662189251Ssam	  h.first = h.last = new;
1663189251Ssam
1664189251Ssam	  merge_trees (head, &h);
1665189251Ssam	}
1666189251Ssam      while (next && next->tests->type == type);
1667337817Scy
1668337817Scy      /* After we run out of compatible tests, graft the remaining nodes
1669337817Scy	 back onto the tree.  */
1670189251Ssam      if (next)
1671189251Ssam	{
1672189251Ssam	  next->prev = head->last;
1673189251Ssam	  head->last->next = next;
1674337817Scy	  head->last = old_last;
1675337817Scy	}
1676337817Scy    }
1677337817Scy
1678189251Ssam  /* Recurse.  */
1679189251Ssam  for (first = head->first; first; first = first->next)
1680337817Scy    factor_tests (&first->success);
1681337817Scy}
1682337817Scy
1683337817Scy/* After factoring, try to simplify the tests on any one node.
1684337817Scy   Tests that are useful for switch statements are recognizable
1685337817Scy   by having only a single test on a node -- we'll be manipulating
1686337817Scy   nodes with multiple tests:
1687337817Scy
1688189251Ssam   If we have mode tests or code tests that are redundant with
1689189251Ssam   predicates, remove them.  */
1690189251Ssam
1691189251Ssamstatic void
1692189251Ssamsimplify_tests (struct decision_head *head)
1693189251Ssam{
1694189251Ssam  struct decision *tree;
1695189251Ssam
1696189251Ssam  for (tree = head->first; tree; tree = tree->next)
1697189251Ssam    {
1698189251Ssam      struct decision_test *a, *b;
1699189251Ssam
1700189251Ssam      a = tree->tests;
1701189251Ssam      b = a->next;
1702189251Ssam      if (b == NULL)
1703189251Ssam	continue;
1704189251Ssam
1705189251Ssam      /* Find a predicate node.  */
1706189251Ssam      while (b && b->type != DT_pred)
1707189251Ssam	b = b->next;
1708189251Ssam      if (b)
1709189251Ssam	{
1710189251Ssam	  /* Due to how these tests are constructed, we don't even need
1711189251Ssam	     to check that the mode and code are compatible -- they were
1712189251Ssam	     generated from the predicate in the first place.  */
1713189251Ssam	  while (a->type == DT_mode || a->type == DT_code)
1714189251Ssam	    a = a->next;
1715189251Ssam	  tree->tests = a;
1716189251Ssam	}
1717189251Ssam    }
1718189251Ssam
1719189251Ssam  /* Recurse.  */
1720189251Ssam  for (tree = head->first; tree; tree = tree->next)
1721189251Ssam    simplify_tests (&tree->success);
1722189251Ssam}
1723189251Ssam
1724189251Ssam/* Count the number of subnodes of HEAD.  If the number is high enough,
1725189251Ssam   make the first node in HEAD start a separate subroutine in the C code
1726189251Ssam   that is generated.  */
1727189251Ssam
1728189251Ssamstatic int
1729337817Scybreak_out_subroutines (struct decision_head *head, int initial)
1730337817Scy{
1731189251Ssam  int size = 0;
1732189251Ssam  struct decision *sub;
1733189251Ssam
1734281806Srpaulo  for (sub = head->first; sub; sub = sub->next)
1735281806Srpaulo    size += 1 + break_out_subroutines (&sub->success, 0);
1736281806Srpaulo
1737281806Srpaulo  if (size > SUBROUTINE_THRESHOLD && ! initial)
1738281806Srpaulo    {
1739281806Srpaulo      head->first->subroutine_number = ++next_subroutine_number;
1740281806Srpaulo      size = 1;
1741281806Srpaulo    }
1742281806Srpaulo  return size;
1743281806Srpaulo}
1744281806Srpaulo
1745281806Srpaulo/* For each node p, find the next alternative that might be true
1746281806Srpaulo   when p is true.  */
1747281806Srpaulo
1748281806Srpaulostatic void
1749281806Srpaulofind_afterward (struct decision_head *head, struct decision *real_afterward)
1750281806Srpaulo{
1751281806Srpaulo  struct decision *p, *q, *afterward;
1752281806Srpaulo
1753281806Srpaulo  /* We can't propagate alternatives across subroutine boundaries.
1754281806Srpaulo     This is not incorrect, merely a minor optimization loss.  */
1755281806Srpaulo
1756281806Srpaulo  p = head->first;
1757281806Srpaulo  afterward = (p->subroutine_number > 0 ? NULL : real_afterward);
1758281806Srpaulo
1759281806Srpaulo  for ( ; p ; p = p->next)
1760281806Srpaulo    {
1761281806Srpaulo      /* Find the next node that might be true if this one fails.  */
1762281806Srpaulo      for (q = p->next; q ; q = q->next)
1763281806Srpaulo	if (maybe_both_true (p, q, 1))
1764281806Srpaulo	  break;
1765281806Srpaulo
1766281806Srpaulo      /* If we reached the end of the list without finding one,
1767281806Srpaulo	 use the incoming afterward position.  */
1768281806Srpaulo      if (!q)
1769281806Srpaulo	q = afterward;
1770281806Srpaulo      p->afterward = q;
1771281806Srpaulo      if (q)
1772281806Srpaulo	q->need_label = 1;
1773281806Srpaulo    }
1774346981Scy
1775281806Srpaulo  /* Recurse.  */
1776281806Srpaulo  for (p = head->first; p ; p = p->next)
1777281806Srpaulo    if (p->success.first)
1778281806Srpaulo      find_afterward (&p->success, p->afterward);
1779281806Srpaulo
1780281806Srpaulo  /* When we are generating a subroutine, record the real afterward
1781281806Srpaulo     position in the first node where write_tree can find it, and we
1782281806Srpaulo     can do the right thing at the subroutine call site.  */
1783281806Srpaulo  p = head->first;
1784281806Srpaulo  if (p->subroutine_number > 0)
1785346981Scy    p->afterward = real_afterward;
1786281806Srpaulo}
1787281806Srpaulo
1788281806Srpaulo/* Assuming that the state of argument is denoted by OLDPOS, take whatever
1789281806Srpaulo   actions are necessary to move to NEWPOS.  If we fail to move to the
1790281806Srpaulo   new state, branch to node AFTERWARD if nonzero, otherwise return.
1791281806Srpaulo
1792281806Srpaulo   Failure to move to the new state can only occur if we are trying to
1793281806Srpaulo   match multiple insns and we try to step past the end of the stream.  */
1794281806Srpaulo
1795281806Srpaulostatic void
1796281806Srpaulochange_state (const char *oldpos, const char *newpos, const char *indent)
1797281806Srpaulo{
1798281806Srpaulo  int odepth = strlen (oldpos);
1799281806Srpaulo  int ndepth = strlen (newpos);
1800281806Srpaulo  int depth;
1801281806Srpaulo  int old_has_insn, new_has_insn;
1802281806Srpaulo
1803281806Srpaulo  /* Pop up as many levels as necessary.  */
1804281806Srpaulo  for (depth = odepth; strncmp (oldpos, newpos, depth) != 0; --depth)
1805281806Srpaulo    continue;
1806281806Srpaulo
1807281806Srpaulo  /* Hunt for the last [A-Z] in both strings.  */
1808281806Srpaulo  for (old_has_insn = odepth - 1; old_has_insn >= 0; --old_has_insn)
1809281806Srpaulo    if (ISUPPER (oldpos[old_has_insn]))
1810281806Srpaulo      break;
1811281806Srpaulo  for (new_has_insn = ndepth - 1; new_has_insn >= 0; --new_has_insn)
1812281806Srpaulo    if (ISUPPER (newpos[new_has_insn]))
1813281806Srpaulo      break;
1814281806Srpaulo
1815281806Srpaulo  /* Go down to desired level.  */
1816281806Srpaulo  while (depth < ndepth)
1817281806Srpaulo    {
1818281806Srpaulo      /* It's a different insn from the first one.  */
1819281806Srpaulo      if (ISUPPER (newpos[depth]))
1820281806Srpaulo	{
1821281806Srpaulo	  printf ("%stem = peep2_next_insn (%d);\n",
1822281806Srpaulo		  indent, newpos[depth] - 'A');
1823281806Srpaulo	  printf ("%sx%d = PATTERN (tem);\n", indent, depth + 1);
1824281806Srpaulo	}
1825281806Srpaulo      else if (ISLOWER (newpos[depth]))
1826281806Srpaulo	printf ("%sx%d = XVECEXP (x%d, 0, %d);\n",
1827281806Srpaulo		indent, depth + 1, depth, newpos[depth] - 'a');
1828281806Srpaulo      else
1829281806Srpaulo	printf ("%sx%d = XEXP (x%d, %c);\n",
1830281806Srpaulo		indent, depth + 1, depth, newpos[depth]);
1831281806Srpaulo      ++depth;
1832281806Srpaulo    }
1833281806Srpaulo}
1834281806Srpaulo
1835281806Srpaulo/* Print the enumerator constant for CODE -- the upcase version of
1836281806Srpaulo   the name.  */
1837281806Srpaulo
1838281806Srpaulostatic void
1839281806Srpauloprint_code (enum rtx_code code)
1840281806Srpaulo{
1841281806Srpaulo  const char *p;
1842281806Srpaulo  for (p = GET_RTX_NAME (code); *p; p++)
1843281806Srpaulo    putchar (TOUPPER (*p));
1844281806Srpaulo}
1845281806Srpaulo
1846281806Srpaulo/* Emit code to cross an afterward link -- change state and branch.  */
1847281806Srpaulo
1848281806Srpaulostatic void
1849281806Srpaulowrite_afterward (struct decision *start, struct decision *afterward,
1850281806Srpaulo		 const char *indent)
1851281806Srpaulo{
1852281806Srpaulo  if (!afterward || start->subroutine_number > 0)
1853281806Srpaulo    printf("%sgoto ret0;\n", indent);
1854281806Srpaulo  else
1855281806Srpaulo    {
1856281806Srpaulo      change_state (start->position, afterward->position, indent);
1857281806Srpaulo      printf ("%sgoto L%d;\n", indent, afterward->number);
1858281806Srpaulo    }
1859281806Srpaulo}
1860281806Srpaulo
1861281806Srpaulo/* Emit a HOST_WIDE_INT as an integer constant expression.  We need to take
1862281806Srpaulo   special care to avoid "decimal constant is so large that it is unsigned"
1863281806Srpaulo   warnings in the resulting code.  */
1864281806Srpaulo
1865281806Srpaulostatic void
1866281806Srpauloprint_host_wide_int (HOST_WIDE_INT val)
1867281806Srpaulo{
1868281806Srpaulo  HOST_WIDE_INT min = (unsigned HOST_WIDE_INT)1 << (HOST_BITS_PER_WIDE_INT-1);
1869281806Srpaulo  if (val == min)
1870281806Srpaulo    printf ("(" HOST_WIDE_INT_PRINT_DEC_C "-1)", val + 1);
1871281806Srpaulo  else
1872281806Srpaulo    printf (HOST_WIDE_INT_PRINT_DEC_C, val);
1873281806Srpaulo}
1874281806Srpaulo
1875281806Srpaulo/* Emit a switch statement, if possible, for an initial sequence of
1876281806Srpaulo   nodes at START.  Return the first node yet untested.  */
1877281806Srpaulo
1878281806Srpaulostatic struct decision *
1879281806Srpaulowrite_switch (struct decision *start, int depth)
1880281806Srpaulo{
1881281806Srpaulo  struct decision *p = start;
1882281806Srpaulo  enum decision_type type = p->tests->type;
1883281806Srpaulo  struct decision *needs_label = NULL;
1884281806Srpaulo
1885281806Srpaulo  /* If we have two or more nodes in sequence that test the same one
1886281806Srpaulo     thing, we may be able to use a switch statement.  */
1887281806Srpaulo
1888281806Srpaulo  if (!p->next
1889281806Srpaulo      || p->tests->next
1890281806Srpaulo      || p->next->tests->type != type
1891281806Srpaulo      || p->next->tests->next
1892281806Srpaulo      || nodes_identical_1 (p->tests, p->next->tests))
1893281806Srpaulo    return p;
1894281806Srpaulo
1895281806Srpaulo  /* DT_code is special in that we can do interesting things with
1896281806Srpaulo     known predicates at the same time.  */
1897281806Srpaulo  if (type == DT_code)
1898281806Srpaulo    {
1899281806Srpaulo      char codemap[NUM_RTX_CODE];
1900281806Srpaulo      struct decision *ret;
1901281806Srpaulo      RTX_CODE code;
1902281806Srpaulo
1903281806Srpaulo      memset (codemap, 0, sizeof(codemap));
1904281806Srpaulo
1905281806Srpaulo      printf ("  switch (GET_CODE (x%d))\n    {\n", depth);
1906281806Srpaulo      code = p->tests->u.code;
1907281806Srpaulo      do
1908281806Srpaulo	{
1909281806Srpaulo	  if (p != start && p->need_label && needs_label == NULL)
1910281806Srpaulo	    needs_label = p;
1911281806Srpaulo
1912281806Srpaulo	  printf ("    case ");
1913281806Srpaulo	  print_code (code);
1914281806Srpaulo	  printf (":\n      goto L%d;\n", p->success.first->number);
1915281806Srpaulo	  p->success.first->need_label = 1;
1916281806Srpaulo
1917281806Srpaulo	  codemap[code] = 1;
1918281806Srpaulo	  p = p->next;
1919281806Srpaulo	}
1920281806Srpaulo      while (p
1921281806Srpaulo	     && ! p->tests->next
1922281806Srpaulo	     && p->tests->type == DT_code
1923281806Srpaulo	     && ! codemap[code = p->tests->u.code]);
1924281806Srpaulo
1925281806Srpaulo      /* If P is testing a predicate that we know about and we haven't
1926281806Srpaulo	 seen any of the codes that are valid for the predicate, we can
1927281806Srpaulo	 write a series of "case" statement, one for each possible code.
1928281806Srpaulo	 Since we are already in a switch, these redundant tests are very
1929281806Srpaulo	 cheap and will reduce the number of predicates called.  */
1930281806Srpaulo
1931281806Srpaulo      /* Note that while we write out cases for these predicates here,
1932281806Srpaulo	 we don't actually write the test here, as it gets kinda messy.
1933281806Srpaulo	 It is trivial to leave this to later by telling our caller that
1934281806Srpaulo	 we only processed the CODE tests.  */
1935281806Srpaulo      if (needs_label != NULL)
1936281806Srpaulo	ret = needs_label;
1937281806Srpaulo      else
1938281806Srpaulo	ret = p;
1939281806Srpaulo
1940281806Srpaulo      while (p && p->tests->type == DT_pred && p->tests->u.pred.data)
1941281806Srpaulo	{
1942281806Srpaulo	  const struct pred_data *data = p->tests->u.pred.data;
1943281806Srpaulo	  RTX_CODE c;
1944281806Srpaulo	  for (c = 0; c < NUM_RTX_CODE; c++)
1945281806Srpaulo	    if (codemap[c] && data->codes[c])
1946189251Ssam	      goto pred_done;
1947189251Ssam
1948189251Ssam	  for (c = 0; c < NUM_RTX_CODE; c++)
1949189251Ssam	    if (data->codes[c])
1950189251Ssam	      {
1951189251Ssam		fputs ("    case ", stdout);
1952189251Ssam		print_code (c);
1953189251Ssam		fputs (":\n", stdout);
1954189251Ssam		codemap[c] = 1;
1955189251Ssam	      }
1956189251Ssam
1957189251Ssam	  printf ("      goto L%d;\n", p->number);
1958189251Ssam	  p->need_label = 1;
1959189251Ssam	  p = p->next;
1960189251Ssam	}
1961189251Ssam
1962189251Ssam    pred_done:
1963189251Ssam      /* Make the default case skip the predicates we managed to match.  */
1964189251Ssam
1965189251Ssam      printf ("    default:\n");
1966189251Ssam      if (p != ret)
1967189251Ssam	{
1968189251Ssam	  if (p)
1969189251Ssam	    {
1970189251Ssam	      printf ("      goto L%d;\n", p->number);
1971189251Ssam	      p->need_label = 1;
1972189251Ssam	    }
1973189251Ssam	  else
1974189251Ssam	    write_afterward (start, start->afterward, "      ");
1975189251Ssam	}
1976289549Srpaulo      else
1977189251Ssam	printf ("     break;\n");
1978189251Ssam      printf ("   }\n");
1979189251Ssam
1980189251Ssam      return ret;
1981189251Ssam    }
1982189251Ssam  else if (type == DT_mode
1983189251Ssam	   || type == DT_veclen
1984189251Ssam	   || type == DT_elt_zero_int
1985189251Ssam	   || type == DT_elt_one_int
1986189251Ssam	   || type == DT_elt_zero_wide_safe)
1987189251Ssam    {
1988189251Ssam      const char *indent = "";
1989189251Ssam
1990189251Ssam      /* We cast switch parameter to integer, so we must ensure that the value
1991189251Ssam	 fits.  */
1992189251Ssam      if (type == DT_elt_zero_wide_safe)
1993189251Ssam	{
1994189251Ssam	  indent = "  ";
1995189251Ssam	  printf("  if ((int) XWINT (x%d, 0) == XWINT (x%d, 0))\n", depth, depth);
1996189251Ssam	}
1997189251Ssam      printf ("%s  switch (", indent);
1998189251Ssam      switch (type)
1999189251Ssam	{
2000189251Ssam	case DT_mode:
2001189251Ssam	  printf ("GET_MODE (x%d)", depth);
2002189251Ssam	  break;
2003189251Ssam	case DT_veclen:
2004189251Ssam	  printf ("XVECLEN (x%d, 0)", depth);
2005189251Ssam	  break;
2006189251Ssam	case DT_elt_zero_int:
2007189251Ssam	  printf ("XINT (x%d, 0)", depth);
2008189251Ssam	  break;
2009189251Ssam	case DT_elt_one_int:
2010189251Ssam	  printf ("XINT (x%d, 1)", depth);
2011189251Ssam	  break;
2012189251Ssam	case DT_elt_zero_wide_safe:
2013189251Ssam	  /* Convert result of XWINT to int for portability since some C
2014189251Ssam	     compilers won't do it and some will.  */
2015189251Ssam	  printf ("(int) XWINT (x%d, 0)", depth);
2016189251Ssam	  break;
2017189251Ssam	default:
2018189251Ssam	  gcc_unreachable ();
2019189251Ssam	}
2020189251Ssam      printf (")\n%s    {\n", indent);
2021189251Ssam
2022189251Ssam      do
2023189251Ssam	{
2024189251Ssam	  /* Merge trees will not unify identical nodes if their
2025189251Ssam	     sub-nodes are at different levels.  Thus we must check
2026189251Ssam	     for duplicate cases.  */
2027189251Ssam	  struct decision *q;
2028189251Ssam	  for (q = start; q != p; q = q->next)
2029252726Srpaulo	    if (nodes_identical_1 (p->tests, q->tests))
2030189251Ssam	      goto case_done;
2031189251Ssam
2032189251Ssam	  if (p != start && p->need_label && needs_label == NULL)
2033189251Ssam	    needs_label = p;
2034252726Srpaulo
2035346981Scy	  printf ("%s    case ", indent);
2036346981Scy	  switch (type)
2037346981Scy	    {
2038346981Scy	    case DT_mode:
2039346981Scy	      printf ("%smode", GET_MODE_NAME (p->tests->u.mode));
2040346981Scy	      break;
2041346981Scy	    case DT_veclen:
2042346981Scy	      printf ("%d", p->tests->u.veclen);
2043346981Scy	      break;
2044189251Ssam	    case DT_elt_zero_int:
2045189251Ssam	    case DT_elt_one_int:
2046281806Srpaulo	    case DT_elt_zero_wide:
2047281806Srpaulo	    case DT_elt_zero_wide_safe:
2048281806Srpaulo	      print_host_wide_int (p->tests->u.intval);
2049281806Srpaulo	      break;
2050281806Srpaulo	    default:
2051281806Srpaulo	      gcc_unreachable ();
2052189251Ssam	    }
2053189251Ssam	  printf (":\n%s      goto L%d;\n", indent, p->success.first->number);
2054189251Ssam	  p->success.first->need_label = 1;
2055189251Ssam
2056189251Ssam	  p = p->next;
2057189251Ssam	}
2058189251Ssam      while (p && p->tests->type == type && !p->tests->next);
2059189251Ssam
2060214734Srpaulo    case_done:
2061214734Srpaulo      printf ("%s    default:\n%s      break;\n%s    }\n",
2062214734Srpaulo	      indent, indent, indent);
2063214734Srpaulo
2064214734Srpaulo      return needs_label != NULL ? needs_label : p;
2065214734Srpaulo    }
2066214734Srpaulo  else
2067252726Srpaulo    {
2068252726Srpaulo      /* None of the other tests are amenable.  */
2069252726Srpaulo      return p;
2070337817Scy    }
2071337817Scy}
2072337817Scy
2073337817Scy/* Emit code for one test.  */
2074337817Scy
2075252726Srpaulostatic void
2076214734Srpaulowrite_cond (struct decision_test *p, int depth,
2077214734Srpaulo	    enum routine_type subroutine_type)
2078214734Srpaulo{
2079214734Srpaulo  switch (p->type)
2080214734Srpaulo    {
2081214734Srpaulo    case DT_num_insns:
2082214734Srpaulo      printf ("peep2_current_count >= %d", p->u.num_insns);
2083252726Srpaulo      break;
2084252726Srpaulo
2085214734Srpaulo    case DT_mode:
2086214734Srpaulo      printf ("GET_MODE (x%d) == %smode", depth, GET_MODE_NAME (p->u.mode));
2087252726Srpaulo      break;
2088252726Srpaulo
2089252726Srpaulo    case DT_code:
2090214734Srpaulo      printf ("GET_CODE (x%d) == ", depth);
2091214734Srpaulo      print_code (p->u.code);
2092214734Srpaulo      break;
2093214734Srpaulo
2094214734Srpaulo    case DT_veclen:
2095214734Srpaulo      printf ("XVECLEN (x%d, 0) == %d", depth, p->u.veclen);
2096214734Srpaulo      break;
2097214734Srpaulo
2098214734Srpaulo    case DT_elt_zero_int:
2099214734Srpaulo      printf ("XINT (x%d, 0) == %d", depth, (int) p->u.intval);
2100351611Scy      break;
2101351611Scy
2102214734Srpaulo    case DT_elt_one_int:
2103252726Srpaulo      printf ("XINT (x%d, 1) == %d", depth, (int) p->u.intval);
2104252726Srpaulo      break;
2105252726Srpaulo
2106252726Srpaulo    case DT_elt_zero_wide:
2107252726Srpaulo    case DT_elt_zero_wide_safe:
2108252726Srpaulo      printf ("XWINT (x%d, 0) == ", depth);
2109252726Srpaulo      print_host_wide_int (p->u.intval);
2110252726Srpaulo      break;
2111214734Srpaulo
2112214734Srpaulo    case DT_const_int:
2113214734Srpaulo      printf ("x%d == const_int_rtx[MAX_SAVED_CONST_INT + (%d)]",
2114214734Srpaulo	      depth, (int) p->u.intval);
2115214734Srpaulo      break;
2116214734Srpaulo
2117189251Ssam    case DT_veclen_ge:
2118189251Ssam      printf ("XVECLEN (x%d, 0) >= %d", depth, p->u.veclen);
2119189251Ssam      break;
2120189251Ssam
2121189251Ssam    case DT_dup:
2122189251Ssam      printf ("rtx_equal_p (x%d, operands[%d])", depth, p->u.dup);
2123189251Ssam      break;
2124189251Ssam
2125189251Ssam    case DT_pred:
2126189251Ssam      printf ("%s (x%d, %smode)", p->u.pred.name, depth,
2127189251Ssam	      GET_MODE_NAME (p->u.pred.mode));
2128189251Ssam      break;
2129189251Ssam
2130189251Ssam    case DT_c_test:
2131189251Ssam      print_c_condition (p->u.c_test);
2132289549Srpaulo      break;
2133189251Ssam
2134189251Ssam    case DT_accept_insn:
2135189251Ssam      gcc_assert (subroutine_type == RECOG);
2136189251Ssam      gcc_assert (p->u.insn.num_clobbers_to_add);
2137189251Ssam      printf ("pnum_clobbers != NULL");
2138189251Ssam      break;
2139189251Ssam
2140189251Ssam    default:
2141189251Ssam      gcc_unreachable ();
2142189251Ssam    }
2143189251Ssam}
2144252726Srpaulo
2145189251Ssam/* Emit code for one action.  The previous tests have succeeded;
2146281806Srpaulo   TEST is the last of the chain.  In the normal case we simply
2147189251Ssam   perform a state change.  For the `accept' tests we must do more work.  */
2148189251Ssam
2149189251Ssamstatic void
2150189251Ssamwrite_action (struct decision *p, struct decision_test *test,
2151189251Ssam	      int depth, int uncond, struct decision *success,
2152281806Srpaulo	      enum routine_type subroutine_type)
2153214734Srpaulo{
2154214734Srpaulo  const char *indent;
2155214734Srpaulo  int want_close = 0;
2156214734Srpaulo
2157214734Srpaulo  if (uncond)
2158252726Srpaulo    indent = "  ";
2159189251Ssam  else if (test->type == DT_accept_op || test->type == DT_accept_insn)
2160189251Ssam    {
2161189251Ssam      fputs ("    {\n", stdout);
2162189251Ssam      indent = "      ";
2163189251Ssam      want_close = 1;
2164189251Ssam    }
2165189251Ssam  else
2166189251Ssam    indent = "    ";
2167252726Srpaulo
2168252726Srpaulo  if (test->type == DT_accept_op)
2169252726Srpaulo    {
2170252726Srpaulo      printf("%soperands[%d] = x%d;\n", indent, test->u.opno, depth);
2171252726Srpaulo
2172252726Srpaulo      /* Only allow DT_accept_insn to follow.  */
2173252726Srpaulo      if (test->next)
2174189251Ssam	{
2175189251Ssam	  test = test->next;
2176189251Ssam	  gcc_assert (test->type == DT_accept_insn);
2177189251Ssam	}
2178189251Ssam    }
2179189251Ssam
2180189251Ssam  /* Sanity check that we're now at the end of the list of tests.  */
2181189251Ssam  gcc_assert (!test->next);
2182189251Ssam
2183189251Ssam  if (test->type == DT_accept_insn)
2184189251Ssam    {
2185189251Ssam      switch (subroutine_type)
2186189251Ssam	{
2187189251Ssam	case RECOG:
2188189251Ssam	  if (test->u.insn.num_clobbers_to_add != 0)
2189189251Ssam	    printf ("%s*pnum_clobbers = %d;\n",
2190189251Ssam		    indent, test->u.insn.num_clobbers_to_add);
2191252726Srpaulo	  printf ("%sreturn %d;  /* %s */\n", indent,
2192252726Srpaulo		  test->u.insn.code_number,
2193189251Ssam		  get_insn_name (test->u.insn.code_number));
2194281806Srpaulo	  break;
2195189251Ssam
2196189251Ssam	case SPLIT:
2197189251Ssam	  printf ("%sreturn gen_split_%d (insn, operands);\n",
2198189251Ssam		  indent, test->u.insn.code_number);
2199189251Ssam	  break;
2200189251Ssam
2201189251Ssam	case PEEPHOLE2:
2202189251Ssam	  {
2203189251Ssam	    int match_len = 0, i;
2204189251Ssam
2205189251Ssam	    for (i = strlen (p->position) - 1; i >= 0; --i)
2206189251Ssam	      if (ISUPPER (p->position[i]))
2207189251Ssam		{
2208189251Ssam		  match_len = p->position[i] - 'A';
2209189251Ssam		  break;
2210189251Ssam		}
2211189251Ssam	    printf ("%s*_pmatch_len = %d;\n", indent, match_len);
2212189251Ssam	    printf ("%stem = gen_peephole2_%d (insn, operands);\n",
2213189251Ssam		    indent, test->u.insn.code_number);
2214189251Ssam	    printf ("%sif (tem != 0)\n%s  return tem;\n", indent, indent);
2215189251Ssam	  }
2216189251Ssam	  break;
2217189251Ssam
2218189251Ssam	default:
2219189251Ssam	  gcc_unreachable ();
2220189251Ssam	}
2221189251Ssam    }
2222189251Ssam  else
2223189251Ssam    {
2224189251Ssam      printf("%sgoto L%d;\n", indent, success->number);
2225189251Ssam      success->need_label = 1;
2226189251Ssam    }
2227189251Ssam
2228189251Ssam  if (want_close)
2229189251Ssam    fputs ("    }\n", stdout);
2230189251Ssam}
2231189251Ssam
2232189251Ssam/* Return 1 if the test is always true and has no fallthru path.  Return -1
2233189251Ssam   if the test does have a fallthru path, but requires that the condition be
2234281806Srpaulo   terminated.  Otherwise return 0 for a normal test.  */
2235281806Srpaulo/* ??? is_unconditional is a stupid name for a tri-state function.  */
2236281806Srpaulo
2237189251Ssamstatic int
2238189251Ssamis_unconditional (struct decision_test *t, enum routine_type subroutine_type)
2239189251Ssam{
2240189251Ssam  if (t->type == DT_accept_op)
2241189251Ssam    return 1;
2242189251Ssam
2243189251Ssam  if (t->type == DT_accept_insn)
2244189251Ssam    {
2245189251Ssam      switch (subroutine_type)
2246189251Ssam	{
2247189251Ssam	case RECOG:
2248189251Ssam	  return (t->u.insn.num_clobbers_to_add == 0);
2249189251Ssam	case SPLIT:
2250189251Ssam	  return 1;
2251189251Ssam	case PEEPHOLE2:
2252189251Ssam	  return -1;
2253189251Ssam	default:
2254189251Ssam	  gcc_unreachable ();
2255189251Ssam	}
2256189251Ssam    }
2257189251Ssam
2258189251Ssam  return 0;
2259189251Ssam}
2260189251Ssam
2261189251Ssam/* Emit code for one node -- the conditional and the accompanying action.
2262189251Ssam   Return true if there is no fallthru path.  */
2263189251Ssam
2264189251Ssamstatic int
2265189251Ssamwrite_node (struct decision *p, int depth,
2266189251Ssam	    enum routine_type subroutine_type)
2267189251Ssam{
2268189251Ssam  struct decision_test *test, *last_test;
2269189251Ssam  int uncond;
2270189251Ssam
2271189251Ssam  /* Scan the tests and simplify comparisons against small
2272189251Ssam     constants.  */
2273189251Ssam  for (test = p->tests; test; test = test->next)
2274189251Ssam    {
2275189251Ssam      if (test->type == DT_code
2276189251Ssam	  && test->u.code == CONST_INT
2277189251Ssam	  && test->next
2278189251Ssam	  && test->next->type == DT_elt_zero_wide_safe
2279189251Ssam	  && -MAX_SAVED_CONST_INT <= test->next->u.intval
2280189251Ssam	  && test->next->u.intval <= MAX_SAVED_CONST_INT)
2281189251Ssam	{
2282189251Ssam	  test->type = DT_const_int;
2283189251Ssam	  test->u.intval = test->next->u.intval;
2284189251Ssam	  test->next = test->next->next;
2285189251Ssam	}
2286189251Ssam    }
2287189251Ssam
2288189251Ssam  last_test = test = p->tests;
2289189251Ssam  uncond = is_unconditional (test, subroutine_type);
2290189251Ssam  if (uncond == 0)
2291189251Ssam    {
2292189251Ssam      printf ("  if (");
2293189251Ssam      write_cond (test, depth, subroutine_type);
2294189251Ssam
2295189251Ssam      while ((test = test->next) != NULL)
2296189251Ssam	{
2297189251Ssam	  last_test = test;
2298189251Ssam	  if (is_unconditional (test, subroutine_type))
2299189251Ssam	    break;
2300189251Ssam
2301189251Ssam	  printf ("\n      && ");
2302189251Ssam	  write_cond (test, depth, subroutine_type);
2303189251Ssam	}
2304189251Ssam
2305189251Ssam      printf (")\n");
2306189251Ssam    }
2307189251Ssam
2308189251Ssam  write_action (p, last_test, depth, uncond, p->success.first, subroutine_type);
2309189251Ssam
2310189251Ssam  return uncond > 0;
2311189251Ssam}
2312189251Ssam
2313189251Ssam/* Emit code for all of the sibling nodes of HEAD.  */
2314189251Ssam
2315189251Ssamstatic void
2316189251Ssamwrite_tree_1 (struct decision_head *head, int depth,
2317189251Ssam	      enum routine_type subroutine_type)
2318189251Ssam{
2319189251Ssam  struct decision *p, *next;
2320189251Ssam  int uncond = 0;
2321189251Ssam
2322189251Ssam  for (p = head->first; p ; p = next)
2323189251Ssam    {
2324189251Ssam      /* The label for the first element was printed in write_tree.  */
2325189251Ssam      if (p != head->first && p->need_label)
2326189251Ssam	OUTPUT_LABEL (" ", p->number);
2327189251Ssam
2328189251Ssam      /* Attempt to write a switch statement for a whole sequence.  */
2329189251Ssam      next = write_switch (p, depth);
2330189251Ssam      if (p != next)
2331189251Ssam	uncond = 0;
2332189251Ssam      else
2333189251Ssam	{
2334189251Ssam	  /* Failed -- fall back and write one node.  */
2335189251Ssam	  uncond = write_node (p, depth, subroutine_type);
2336189251Ssam	  next = p->next;
2337189251Ssam	}
2338189251Ssam    }
2339189251Ssam
2340189251Ssam  /* Finished with this chain.  Close a fallthru path by branching
2341189251Ssam     to the afterward node.  */
2342189251Ssam  if (! uncond)
2343281806Srpaulo    write_afterward (head->last, head->last->afterward, "  ");
2344189251Ssam}
2345189251Ssam
2346189251Ssam/* Write out the decision tree starting at HEAD.  PREVPOS is the
2347189251Ssam   position at the node that branched to this node.  */
2348189251Ssam
2349189251Ssamstatic void
2350189251Ssamwrite_tree (struct decision_head *head, const char *prevpos,
2351189251Ssam	    enum routine_type type, int initial)
2352189251Ssam{
2353189251Ssam  struct decision *p = head->first;
2354189251Ssam
2355189251Ssam  putchar ('\n');
2356189251Ssam  if (p->need_label)
2357189251Ssam    OUTPUT_LABEL (" ", p->number);
2358189251Ssam
2359189251Ssam  if (! initial && p->subroutine_number > 0)
2360189251Ssam    {
2361189251Ssam      static const char * const name_prefix[] = {
2362281806Srpaulo	  "recog", "split", "peephole2"
2363189251Ssam      };
2364189251Ssam
2365189251Ssam      static const char * const call_suffix[] = {
2366189251Ssam	  ", pnum_clobbers", "", ", _pmatch_len"
2367189251Ssam      };
2368189251Ssam
2369189251Ssam      /* This node has been broken out into a separate subroutine.
2370189251Ssam	 Call it, test the result, and branch accordingly.  */
2371189251Ssam
2372189251Ssam      if (p->afterward)
2373189251Ssam	{
2374189251Ssam	  printf ("  tem = %s_%d (x0, insn%s);\n",
2375189251Ssam		  name_prefix[type], p->subroutine_number, call_suffix[type]);
2376189251Ssam	  if (IS_SPLIT (type))
2377189251Ssam	    printf ("  if (tem != 0)\n    return tem;\n");
2378189251Ssam	  else
2379189251Ssam	    printf ("  if (tem >= 0)\n    return tem;\n");
2380189251Ssam
2381189251Ssam	  change_state (p->position, p->afterward->position, "  ");
2382189251Ssam	  printf ("  goto L%d;\n", p->afterward->number);
2383281806Srpaulo	}
2384189251Ssam      else
2385189251Ssam	{
2386189251Ssam	  printf ("  return %s_%d (x0, insn%s);\n",
2387189251Ssam		  name_prefix[type], p->subroutine_number, call_suffix[type]);
2388189251Ssam	}
2389189251Ssam    }
2390189251Ssam  else
2391189251Ssam    {
2392189251Ssam      int depth = strlen (p->position);
2393252726Srpaulo
2394189251Ssam      change_state (prevpos, p->position, "  ");
2395189251Ssam      write_tree_1 (head, depth, type);
2396337817Scy
2397189251Ssam      for (p = head->first; p; p = p->next)
2398281806Srpaulo        if (p->success.first)
2399281806Srpaulo          write_tree (&p->success, p->position, type, 0);
2400189251Ssam    }
2401189251Ssam}
2402189251Ssam
2403189251Ssam/* Write out a subroutine of type TYPE to do comparisons starting at
2404189251Ssam   node TREE.  */
2405189251Ssam
2406189251Ssamstatic void
2407252726Srpaulowrite_subroutine (struct decision_head *head, enum routine_type type)
2408252726Srpaulo{
2409189251Ssam  int subfunction = head->first ? head->first->subroutine_number : 0;
2410189251Ssam  const char *s_or_e;
2411252726Srpaulo  char extension[32];
2412189251Ssam  int i;
2413189251Ssam
2414252726Srpaulo  s_or_e = subfunction ? "static " : "";
2415189251Ssam
2416189251Ssam  if (subfunction)
2417252726Srpaulo    sprintf (extension, "_%d", subfunction);
2418189251Ssam  else if (type == RECOG)
2419189251Ssam    extension[0] = '\0';
2420252726Srpaulo  else
2421189251Ssam    strcpy (extension, "_insns");
2422189251Ssam
2423189251Ssam  switch (type)
2424189251Ssam    {
2425189251Ssam    case RECOG:
2426189251Ssam      printf ("%sint\n\
2427189251Ssamrecog%s (rtx x0 ATTRIBUTE_UNUSED,\n\trtx insn ATTRIBUTE_UNUSED,\n\tint *pnum_clobbers ATTRIBUTE_UNUSED)\n", s_or_e, extension);
2428189251Ssam      break;
2429189251Ssam    case SPLIT:
2430189251Ssam      printf ("%srtx\n\
2431189251Ssamsplit%s (rtx x0 ATTRIBUTE_UNUSED, rtx insn ATTRIBUTE_UNUSED)\n",
2432189251Ssam	      s_or_e, extension);
2433189251Ssam      break;
2434189251Ssam    case PEEPHOLE2:
2435189251Ssam      printf ("%srtx\n\
2436189251Ssampeephole2%s (rtx x0 ATTRIBUTE_UNUSED,\n\trtx insn ATTRIBUTE_UNUSED,\n\tint *_pmatch_len ATTRIBUTE_UNUSED)\n",
2437189251Ssam	      s_or_e, extension);
2438189251Ssam      break;
2439252726Srpaulo    }
2440189251Ssam
2441189251Ssam  printf ("{\n  rtx * const operands ATTRIBUTE_UNUSED = &recog_data.operand[0];\n");
2442281806Srpaulo  for (i = 1; i <= max_depth; i++)
2443346981Scy    printf ("  rtx x%d ATTRIBUTE_UNUSED;\n", i);
2444281806Srpaulo
2445281806Srpaulo  printf ("  %s tem ATTRIBUTE_UNUSED;\n", IS_SPLIT (type) ? "rtx" : "int");
2446337817Scy
2447337817Scy  if (!subfunction)
2448189251Ssam    printf ("  recog_data.insn = NULL_RTX;\n");
2449189251Ssam
2450189251Ssam  if (head->first)
2451189251Ssam    write_tree (head, "", type, 1);
2452189251Ssam  else
2453189251Ssam    printf ("  goto ret0;\n");
2454337817Scy
2455189251Ssam  printf (" ret0:\n  return %d;\n}\n\n", IS_SPLIT (type) ? 0 : -1);
2456189251Ssam}
2457337817Scy
2458252726Srpaulo/* In break_out_subroutines, we discovered the boundaries for the
2459252726Srpaulo   subroutines, but did not write them out.  Do so now.  */
2460252726Srpaulo
2461252726Srpaulostatic void
2462252726Srpaulowrite_subroutines (struct decision_head *head, enum routine_type type)
2463252726Srpaulo{
2464189251Ssam  struct decision *p;
2465252726Srpaulo
2466189251Ssam  for (p = head->first; p ; p = p->next)
2467189251Ssam    if (p->success.first)
2468189251Ssam      write_subroutines (&p->success, type);
2469189251Ssam
2470189251Ssam  if (head->first->subroutine_number > 0)
2471189251Ssam    write_subroutine (head, type);
2472189251Ssam}
2473189251Ssam
2474189251Ssam/* Begin the output file.  */
2475189251Ssam
2476189251Ssamstatic void
2477252726Srpaulowrite_header (void)
2478189251Ssam{
2479189251Ssam  puts ("\
2480189251Ssam/* Generated automatically by the program `genrecog' from the target\n\
2481189251Ssam   machine description file.  */\n\
2482189251Ssam\n\
2483189251Ssam#include \"config.h\"\n\
2484189251Ssam#include \"system.h\"\n\
2485189251Ssam#include \"coretypes.h\"\n\
2486189251Ssam#include \"tm.h\"\n\
2487189251Ssam#include \"rtl.h\"\n\
2488189251Ssam#include \"tm_p.h\"\n\
2489189251Ssam#include \"function.h\"\n\
2490189251Ssam#include \"insn-config.h\"\n\
2491189251Ssam#include \"recog.h\"\n\
2492252726Srpaulo#include \"real.h\"\n\
2493189251Ssam#include \"output.h\"\n\
2494189251Ssam#include \"flags.h\"\n\
2495189251Ssam#include \"hard-reg-set.h\"\n\
2496189251Ssam#include \"resource.h\"\n\
2497189251Ssam#include \"toplev.h\"\n\
2498189251Ssam#include \"reload.h\"\n\
2499189251Ssam#include \"tm-constrs.h\"\n\
2500189251Ssam\n");
2501189251Ssam
2502189251Ssam  puts ("\n\
2503189251Ssam/* `recog' contains a decision tree that recognizes whether the rtx\n\
2504189251Ssam   X0 is a valid instruction.\n\
2505189251Ssam\n\
2506189251Ssam   recog returns -1 if the rtx is not valid.  If the rtx is valid, recog\n\
2507252726Srpaulo   returns a nonnegative number which is the insn code number for the\n\
2508189251Ssam   pattern that matched.  This is the same as the order in the machine\n\
2509189251Ssam   description of the entry that matched.  This number can be used as an\n\
2510189251Ssam   index into `insn_data' and other tables.\n");
2511189251Ssam  puts ("\
2512189251Ssam   The third argument to recog is an optional pointer to an int.  If\n\
2513189251Ssam   present, recog will accept a pattern if it matches except for missing\n\
2514189251Ssam   CLOBBER expressions at the end.  In that case, the value pointed to by\n\
2515189251Ssam   the optional pointer will be set to the number of CLOBBERs that need\n\
2516189251Ssam   to be added (it should be initialized to zero by the caller).  If it");
2517189251Ssam  puts ("\
2518189251Ssam   is set nonzero, the caller should allocate a PARALLEL of the\n\
2519189251Ssam   appropriate size, copy the initial entries, and call add_clobbers\n\
2520189251Ssam   (found in insn-emit.c) to fill in the CLOBBERs.\n\
2521189251Ssam");
2522252726Srpaulo
2523189251Ssam  puts ("\n\
2524189251Ssam   The function split_insns returns 0 if the rtl could not\n\
2525189251Ssam   be split or the split rtl as an INSN list if it can be.\n\
2526189251Ssam\n\
2527189251Ssam   The function peephole2_insns returns 0 if the rtl could not\n\
2528189251Ssam   be matched. If there was a match, the new rtl is returned in an INSN list,\n\
2529189251Ssam   and LAST_INSN will point to the last recognized insn in the old sequence.\n\
2530189251Ssam*/\n\n");
2531189251Ssam}
2532189251Ssam
2533189251Ssam
2534189251Ssam/* Construct and return a sequence of decisions
2535189251Ssam   that will recognize INSN.
2536189251Ssam
2537189251Ssam   TYPE says what type of routine we are recognizing (RECOG or SPLIT).  */
2538252726Srpaulo
2539189251Ssamstatic struct decision_head
2540189251Ssammake_insn_sequence (rtx insn, enum routine_type type)
2541189251Ssam{
2542189251Ssam  rtx x;
2543189251Ssam  const char *c_test = XSTR (insn, type == RECOG ? 2 : 1);
2544189251Ssam  int truth = maybe_eval_c_test (c_test);
2545189251Ssam  struct decision *last;
2546189251Ssam  struct decision_test *test, **place;
2547189251Ssam  struct decision_head head;
2548189251Ssam  char c_test_pos[2];
2549189251Ssam
2550189251Ssam  /* We should never see an insn whose C test is false at compile time.  */
2551189251Ssam  gcc_assert (truth);
2552189251Ssam
2553252726Srpaulo  c_test_pos[0] = '\0';
2554189251Ssam  if (type == PEEPHOLE2)
2555189251Ssam    {
2556189251Ssam      int i, j;
2557189251Ssam
2558281806Srpaulo      /* peephole2 gets special treatment:
2559281806Srpaulo	 - X always gets an outer parallel even if it's only one entry
2560281806Srpaulo	 - we remove all traces of outer-level match_scratch and match_dup
2561281806Srpaulo           expressions here.  */
2562281806Srpaulo      x = rtx_alloc (PARALLEL);
2563281806Srpaulo      PUT_MODE (x, VOIDmode);
2564281806Srpaulo      XVEC (x, 0) = rtvec_alloc (XVECLEN (insn, 0));
2565281806Srpaulo      for (i = j = 0; i < XVECLEN (insn, 0); i++)
2566281806Srpaulo	{
2567281806Srpaulo	  rtx tmp = XVECEXP (insn, 0, i);
2568281806Srpaulo	  if (GET_CODE (tmp) != MATCH_SCRATCH && GET_CODE (tmp) != MATCH_DUP)
2569189251Ssam	    {
2570189251Ssam	      XVECEXP (x, 0, j) = tmp;
2571189251Ssam	      j++;
2572189251Ssam	    }
2573189251Ssam	}
2574189251Ssam      XVECLEN (x, 0) = j;
2575189251Ssam
2576189251Ssam      c_test_pos[0] = 'A' + j - 1;
2577189251Ssam      c_test_pos[1] = '\0';
2578189251Ssam    }
2579189251Ssam  else if (XVECLEN (insn, type == RECOG) == 1)
2580189251Ssam    x = XVECEXP (insn, type == RECOG, 0);
2581189251Ssam  else
2582189251Ssam    {
2583189251Ssam      x = rtx_alloc (PARALLEL);
2584189251Ssam      XVEC (x, 0) = XVEC (insn, type == RECOG);
2585189251Ssam      PUT_MODE (x, VOIDmode);
2586189251Ssam    }
2587189251Ssam
2588189251Ssam  validate_pattern (x, insn, NULL_RTX, 0);
2589189251Ssam
2590189251Ssam  memset(&head, 0, sizeof(head));
2591189251Ssam  last = add_to_sequence (x, &head, "", type, 1);
2592189251Ssam
2593189251Ssam  /* Find the end of the test chain on the last node.  */
2594189251Ssam  for (test = last->tests; test->next; test = test->next)
2595189251Ssam    continue;
2596189251Ssam  place = &test->next;
2597189251Ssam
2598189251Ssam  /* Skip the C test if it's known to be true at compile time.  */
2599189251Ssam  if (truth == -1)
2600189251Ssam    {
2601189251Ssam      /* Need a new node if we have another test to add.  */
2602189251Ssam      if (test->type == DT_accept_op)
2603189251Ssam	{
2604189251Ssam	  last = new_decision (c_test_pos, &last->success);
2605189251Ssam	  place = &last->tests;
2606351611Scy	}
2607189251Ssam      test = new_decision_test (DT_c_test, &place);
2608189251Ssam      test->u.c_test = c_test;
2609189251Ssam    }
2610189251Ssam
2611189251Ssam  test = new_decision_test (DT_accept_insn, &place);
2612189251Ssam  test->u.insn.code_number = next_insn_code;
2613189251Ssam  test->u.insn.lineno = pattern_lineno;
2614189251Ssam  test->u.insn.num_clobbers_to_add = 0;
2615189251Ssam
2616189251Ssam  switch (type)
2617189251Ssam    {
2618189251Ssam    case RECOG:
2619189251Ssam      /* If this is a DEFINE_INSN and X is a PARALLEL, see if it ends
2620189251Ssam	 with a group of CLOBBERs of (hard) registers or MATCH_SCRATCHes.
2621189251Ssam	 If so, set up to recognize the pattern without these CLOBBERs.  */
2622189251Ssam
2623289549Srpaulo      if (GET_CODE (x) == PARALLEL)
2624189251Ssam	{
2625189251Ssam	  int i;
2626189251Ssam
2627189251Ssam	  /* Find the last non-clobber in the parallel.  */
2628189251Ssam	  for (i = XVECLEN (x, 0); i > 0; i--)
2629189251Ssam	    {
2630189251Ssam	      rtx y = XVECEXP (x, 0, i - 1);
2631189251Ssam	      if (GET_CODE (y) != CLOBBER
2632189251Ssam		  || (!REG_P (XEXP (y, 0))
2633189251Ssam		      && GET_CODE (XEXP (y, 0)) != MATCH_SCRATCH))
2634189251Ssam		break;
2635189251Ssam	    }
2636189251Ssam
2637189251Ssam	  if (i != XVECLEN (x, 0))
2638189251Ssam	    {
2639189251Ssam	      rtx new;
2640189251Ssam	      struct decision_head clobber_head;
2641189251Ssam
2642189251Ssam	      /* Build a similar insn without the clobbers.  */
2643189251Ssam	      if (i == 1)
2644189251Ssam		new = XVECEXP (x, 0, 0);
2645189251Ssam	      else
2646189251Ssam		{
2647189251Ssam		  int j;
2648189251Ssam
2649189251Ssam		  new = rtx_alloc (PARALLEL);
2650189251Ssam		  XVEC (new, 0) = rtvec_alloc (i);
2651189251Ssam		  for (j = i - 1; j >= 0; j--)
2652189251Ssam		    XVECEXP (new, 0, j) = XVECEXP (x, 0, j);
2653189251Ssam		}
2654189251Ssam
2655189251Ssam	      /* Recognize it.  */
2656189251Ssam	      memset (&clobber_head, 0, sizeof(clobber_head));
2657189251Ssam	      last = add_to_sequence (new, &clobber_head, "", type, 1);
2658189251Ssam
2659189251Ssam	      /* Find the end of the test chain on the last node.  */
2660189251Ssam	      for (test = last->tests; test->next; test = test->next)
2661189251Ssam		continue;
2662189251Ssam
2663189251Ssam	      /* We definitely have a new test to add -- create a new
2664189251Ssam		 node if needed.  */
2665189251Ssam	      place = &test->next;
2666189251Ssam	      if (test->type == DT_accept_op)
2667189251Ssam		{
2668189251Ssam		  last = new_decision ("", &last->success);
2669189251Ssam		  place = &last->tests;
2670189251Ssam		}
2671189251Ssam
2672189251Ssam	      /* Skip the C test if it's known to be true at compile
2673189251Ssam                 time.  */
2674189251Ssam	      if (truth == -1)
2675189251Ssam		{
2676189251Ssam		  test = new_decision_test (DT_c_test, &place);
2677189251Ssam		  test->u.c_test = c_test;
2678189251Ssam		}
2679189251Ssam
2680189251Ssam	      test = new_decision_test (DT_accept_insn, &place);
2681189251Ssam	      test->u.insn.code_number = next_insn_code;
2682189251Ssam	      test->u.insn.lineno = pattern_lineno;
2683189251Ssam	      test->u.insn.num_clobbers_to_add = XVECLEN (x, 0) - i;
2684189251Ssam
2685189251Ssam	      merge_trees (&head, &clobber_head);
2686189251Ssam	    }
2687189251Ssam	}
2688189251Ssam      break;
2689189251Ssam
2690189251Ssam    case SPLIT:
2691189251Ssam      /* Define the subroutine we will call below and emit in genemit.  */
2692189251Ssam      printf ("extern rtx gen_split_%d (rtx, rtx *);\n", next_insn_code);
2693189251Ssam      break;
2694189251Ssam
2695189251Ssam    case PEEPHOLE2:
2696189251Ssam      /* Define the subroutine we will call below and emit in genemit.  */
2697189251Ssam      printf ("extern rtx gen_peephole2_%d (rtx, rtx *);\n",
2698189251Ssam	      next_insn_code);
2699189251Ssam      break;
2700189251Ssam    }
2701189251Ssam
2702189251Ssam  return head;
2703189251Ssam}
2704189251Ssam
2705189251Ssamstatic void
2706189251Ssamprocess_tree (struct decision_head *head, enum routine_type subroutine_type)
2707189251Ssam{
2708189251Ssam  if (head->first == NULL)
2709189251Ssam    {
2710189251Ssam      /* We can elide peephole2_insns, but not recog or split_insns.  */
2711189251Ssam      if (subroutine_type == PEEPHOLE2)
2712189251Ssam	return;
2713189251Ssam    }
2714189251Ssam  else
2715189251Ssam    {
2716189251Ssam      factor_tests (head);
2717189251Ssam
2718189251Ssam      next_subroutine_number = 0;
2719189251Ssam      break_out_subroutines (head, 1);
2720189251Ssam      find_afterward (head, NULL);
2721189251Ssam
2722189251Ssam      /* We run this after find_afterward, because find_afterward needs
2723189251Ssam	 the redundant DT_mode tests on predicates to determine whether
2724189251Ssam	 two tests can both be true or not.  */
2725189251Ssam      simplify_tests(head);
2726189251Ssam
2727189251Ssam      write_subroutines (head, subroutine_type);
2728189251Ssam    }
2729189251Ssam
2730189251Ssam  write_subroutine (head, subroutine_type);
2731252726Srpaulo}
2732252726Srpaulo
2733252726Srpauloextern int main (int, char **);
2734252726Srpaulo
2735252726Srpauloint
2736252726Srpaulomain (int argc, char **argv)
2737252726Srpaulo{
2738252726Srpaulo  rtx desc;
2739252726Srpaulo  struct decision_head recog_tree, split_tree, peephole2_tree, h;
2740252726Srpaulo
2741252726Srpaulo  progname = "genrecog";
2742252726Srpaulo
2743252726Srpaulo  memset (&recog_tree, 0, sizeof recog_tree);
2744252726Srpaulo  memset (&split_tree, 0, sizeof split_tree);
2745252726Srpaulo  memset (&peephole2_tree, 0, sizeof peephole2_tree);
2746252726Srpaulo
2747252726Srpaulo  if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
2748252726Srpaulo    return (FATAL_EXIT_CODE);
2749252726Srpaulo
2750252726Srpaulo  next_insn_code = 0;
2751252726Srpaulo
2752189251Ssam  write_header ();
2753189251Ssam
2754189251Ssam  /* Read the machine description.  */
2755189251Ssam
2756189251Ssam  while (1)
2757189251Ssam    {
2758189251Ssam      desc = read_md_rtx (&pattern_lineno, &next_insn_code);
2759189251Ssam      if (desc == NULL)
2760189251Ssam	break;
2761189251Ssam
2762189251Ssam      switch (GET_CODE (desc))
2763252726Srpaulo	{
2764252726Srpaulo	case DEFINE_PREDICATE:
2765252726Srpaulo	case DEFINE_SPECIAL_PREDICATE:
2766252726Srpaulo	  process_define_predicate (desc);
2767252726Srpaulo	  break;
2768252726Srpaulo
2769252726Srpaulo	case DEFINE_INSN:
2770252726Srpaulo	  h = make_insn_sequence (desc, RECOG);
2771189251Ssam	  merge_trees (&recog_tree, &h);
2772189251Ssam	  break;
2773189251Ssam
2774189251Ssam	case DEFINE_SPLIT:
2775189251Ssam	  h = make_insn_sequence (desc, SPLIT);
2776189251Ssam	  merge_trees (&split_tree, &h);
2777189251Ssam	  break;
2778189251Ssam
2779189251Ssam	case DEFINE_PEEPHOLE2:
2780189251Ssam	  h = make_insn_sequence (desc, PEEPHOLE2);
2781189251Ssam	  merge_trees (&peephole2_tree, &h);
2782189251Ssam
2783189251Ssam	default:
2784189251Ssam	  /* do nothing */;
2785189251Ssam	}
2786189251Ssam    }
2787189251Ssam
2788189251Ssam  if (error_count || have_error)
2789189251Ssam    return FATAL_EXIT_CODE;
2790252726Srpaulo
2791252726Srpaulo  puts ("\n\n");
2792252726Srpaulo
2793252726Srpaulo  process_tree (&recog_tree, RECOG);
2794281806Srpaulo  process_tree (&split_tree, SPLIT);
2795281806Srpaulo  process_tree (&peephole2_tree, PEEPHOLE2);
2796252726Srpaulo
2797252726Srpaulo  fflush (stdout);
2798252726Srpaulo  return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
2799252726Srpaulo}
2800189251Ssam
2801189251Ssamstatic void
2802189251Ssamdebug_decision_2 (struct decision_test *test)
2803189251Ssam{
2804189251Ssam  switch (test->type)
2805189251Ssam    {
2806189251Ssam    case DT_num_insns:
2807189251Ssam      fprintf (stderr, "num_insns=%d", test->u.num_insns);
2808189251Ssam      break;
2809189251Ssam    case DT_mode:
2810189251Ssam      fprintf (stderr, "mode=%s", GET_MODE_NAME (test->u.mode));
2811189251Ssam      break;
2812189251Ssam    case DT_code:
2813189251Ssam      fprintf (stderr, "code=%s", GET_RTX_NAME (test->u.code));
2814189251Ssam      break;
2815189251Ssam    case DT_veclen:
2816189251Ssam      fprintf (stderr, "veclen=%d", test->u.veclen);
2817189251Ssam      break;
2818189251Ssam    case DT_elt_zero_int:
2819189251Ssam      fprintf (stderr, "elt0_i=%d", (int) test->u.intval);
2820189251Ssam      break;
2821189251Ssam    case DT_elt_one_int:
2822189251Ssam      fprintf (stderr, "elt1_i=%d", (int) test->u.intval);
2823189251Ssam      break;
2824189251Ssam    case DT_elt_zero_wide:
2825189251Ssam      fprintf (stderr, "elt0_w=" HOST_WIDE_INT_PRINT_DEC, test->u.intval);
2826189251Ssam      break;
2827189251Ssam    case DT_elt_zero_wide_safe:
2828189251Ssam      fprintf (stderr, "elt0_ws=" HOST_WIDE_INT_PRINT_DEC, test->u.intval);
2829189251Ssam      break;
2830189251Ssam    case DT_veclen_ge:
2831189251Ssam      fprintf (stderr, "veclen>=%d", test->u.veclen);
2832189251Ssam      break;
2833189251Ssam    case DT_dup:
2834189251Ssam      fprintf (stderr, "dup=%d", test->u.dup);
2835189251Ssam      break;
2836189251Ssam    case DT_pred:
2837189251Ssam      fprintf (stderr, "pred=(%s,%s)",
2838189251Ssam	       test->u.pred.name, GET_MODE_NAME(test->u.pred.mode));
2839189251Ssam      break;
2840189251Ssam    case DT_c_test:
2841189251Ssam      {
2842189251Ssam	char sub[16+4];
2843189251Ssam	strncpy (sub, test->u.c_test, sizeof(sub));
2844189251Ssam	memcpy (sub+16, "...", 4);
2845189251Ssam	fprintf (stderr, "c_test=\"%s\"", sub);
2846189251Ssam      }
2847189251Ssam      break;
2848189251Ssam    case DT_accept_op:
2849189251Ssam      fprintf (stderr, "A_op=%d", test->u.opno);
2850189251Ssam      break;
2851189251Ssam    case DT_accept_insn:
2852189251Ssam      fprintf (stderr, "A_insn=(%d,%d)",
2853189251Ssam	       test->u.insn.code_number, test->u.insn.num_clobbers_to_add);
2854189251Ssam      break;
2855189251Ssam
2856189251Ssam    default:
2857189251Ssam      gcc_unreachable ();
2858189251Ssam    }
2859189251Ssam}
2860189251Ssam
2861189251Ssamstatic void
2862189251Ssamdebug_decision_1 (struct decision *d, int indent)
2863189251Ssam{
2864189251Ssam  int i;
2865189251Ssam  struct decision_test *test;
2866189251Ssam
2867189251Ssam  if (d == NULL)
2868189251Ssam    {
2869189251Ssam      for (i = 0; i < indent; ++i)
2870189251Ssam	putc (' ', stderr);
2871189251Ssam      fputs ("(nil)\n", stderr);
2872189251Ssam      return;
2873189251Ssam    }
2874189251Ssam
2875189251Ssam  for (i = 0; i < indent; ++i)
2876189251Ssam    putc (' ', stderr);
2877189251Ssam
2878189251Ssam  putc ('{', stderr);
2879189251Ssam  test = d->tests;
2880189251Ssam  if (test)
2881189251Ssam    {
2882189251Ssam      debug_decision_2 (test);
2883189251Ssam      while ((test = test->next) != NULL)
2884189251Ssam	{
2885189251Ssam	  fputs (" + ", stderr);
2886189251Ssam	  debug_decision_2 (test);
2887252726Srpaulo	}
2888252726Srpaulo    }
2889252726Srpaulo  fprintf (stderr, "} %d n %d a %d\n", d->number,
2890252726Srpaulo	   (d->next ? d->next->number : -1),
2891252726Srpaulo	   (d->afterward ? d->afterward->number : -1));
2892252726Srpaulo}
2893252726Srpaulo
2894252726Srpaulostatic void
2895252726Srpaulodebug_decision_0 (struct decision *d, int indent, int maxdepth)
2896189251Ssam{
2897189251Ssam  struct decision *n;
2898189251Ssam  int i;
2899189251Ssam
2900189251Ssam  if (maxdepth < 0)
2901189251Ssam    return;
2902189251Ssam  if (d == NULL)
2903189251Ssam    {
2904189251Ssam      for (i = 0; i < indent; ++i)
2905189251Ssam	putc (' ', stderr);
2906189251Ssam      fputs ("(nil)\n", stderr);
2907189251Ssam      return;
2908189251Ssam    }
2909189251Ssam
2910189251Ssam  debug_decision_1 (d, indent);
2911189251Ssam  for (n = d->success.first; n ; n = n->next)
2912189251Ssam    debug_decision_0 (n, indent + 2, maxdepth - 1);
2913189251Ssam}
2914189251Ssam
2915189251Ssamvoid
2916189251Ssamdebug_decision (struct decision *d)
2917189251Ssam{
2918189251Ssam  debug_decision_0 (d, 0, 1000000);
2919189251Ssam}
2920189251Ssam
2921189251Ssamvoid
2922189251Ssamdebug_decision_list (struct decision *d)
2923189251Ssam{
2924189251Ssam  while (d)
2925189251Ssam    {
2926189251Ssam      debug_decision_0 (d, 0, 0);
2927189251Ssam      d = d->next;
2928189251Ssam    }
2929189251Ssam}
2930189251Ssam