genrecog.c revision 96263
119370Spst/* Generate code from machine description to recognize rtl as insns.
2130809Smarcel   Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1997, 1998,
398948Sobrien   1999, 2000, 2001, 2002 Free Software Foundation, Inc.
4130809Smarcel
5130809Smarcel   This file is part of GCC.
619370Spst
798948Sobrien   GCC is free software; you can redistribute it and/or modify it
819370Spst   under the terms of the GNU General Public License as published by
998948Sobrien   the Free Software Foundation; either version 2, or (at your option)
1098948Sobrien   any later version.
1198948Sobrien
1298948Sobrien   GCC is distributed in the hope that it will be useful, but WITHOUT
1319370Spst   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
1498948Sobrien   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
1598948Sobrien   License for more details.
1698948Sobrien
1798948Sobrien   You should have received a copy of the GNU General Public License
1819370Spst   along with GCC; see the file COPYING.  If not, write to the Free
1998948Sobrien   Software Foundation, 59 Temple Place - Suite 330, Boston, MA
2098948Sobrien   02111-1307, USA.  */
2198948Sobrien
2298948Sobrien
2319370Spst/* This program is used to produce insn-recog.c, which contains a
2498948Sobrien   function called `recog' plus its subroutines.  These functions
2598948Sobrien   contain a decision tree that recognizes whether an rtx, the
2698948Sobrien   argument given to recog, is a valid instruction.
2798948Sobrien
2898948Sobrien   recog returns -1 if the rtx is not valid.  If the rtx is valid,
2998948Sobrien   recog returns a nonnegative number which is the insn code number
30130809Smarcel   for the pattern that matched.  This is the same as the order in the
31130809Smarcel   machine description of the entry that matched.  This number can be
32130809Smarcel   used as an index into various insn_* tables, such as insn_template,
33130809Smarcel   insn_outfun, and insn_n_operands (found in insn-output.c).
3498948Sobrien
3598948Sobrien   The third argument to recog is an optional pointer to an int.  If
3698948Sobrien   present, recog will accept a pattern if it matches except for
3798948Sobrien   missing CLOBBER expressions at the end.  In that case, the value
3846283Sdfr   pointed to by the optional pointer will be set to the number of
3946283Sdfr   CLOBBERs that need to be added (it should be initialized to zero by
4046283Sdfr   the caller).  If it is set nonzero, the caller should allocate a
4146283Sdfr   PARALLEL of the appropriate size, copy the initial entries, and
4246283Sdfr   call add_clobbers (found in insn-emit.c) to fill in the CLOBBERs.
4398948Sobrien
4419370Spst   This program also generates the function `split_insns', which
4519370Spst   returns 0 if the rtl could not be split, or it returns the split
4619370Spst   rtl in a SEQUENCE.
4719370Spst
4819370Spst   This program also generates the function `peephole2_insns', which
4919370Spst   returns 0 if the rtl could not be matched.  If there was a match,
5019370Spst   the new rtl is returned in a SEQUENCE, and LAST_INSN will point
51130809Smarcel   to the last recognized insn in the old sequence.  */
5219370Spst
53130809Smarcel#include "hconfig.h"
5419370Spst#include "system.h"
55130809Smarcel#include "rtl.h"
5698948Sobrien#include "errors.h"
5798948Sobrien#include "gensupport.h"
5898948Sobrien
59130809Smarcel
60130809Smarcel#define OUTPUT_LABEL(INDENT_STRING, LABEL_NUMBER) \
6198948Sobrien  printf("%sL%d: ATTRIBUTE_UNUSED_LABEL\n", (INDENT_STRING), (LABEL_NUMBER))
62130809Smarcel
63130809Smarcel/* Holds an array of names indexed by insn_code_number.  */
64130809Smarcelstatic char **insn_name_ptr = 0;
6598948Sobrienstatic int insn_name_ptr_size = 0;
66130809Smarcel
67130809Smarcel/* A listhead of decision trees.  The alternatives to a node are kept
6898948Sobrien   in a doublely-linked list so we can easily add nodes to the proper
69130809Smarcel   place when merging.  */
7098948Sobrien
7198948Sobrienstruct decision_head
72130809Smarcel{
7398948Sobrien  struct decision *first;
7498948Sobrien  struct decision *last;
7598948Sobrien};
7698948Sobrien
7798948Sobrien/* A single test.  The two accept types aren't tests per-se, but
7898948Sobrien   their equality (or lack thereof) does affect tree merging so
7998948Sobrien   it is convenient to keep them here.  */
8098948Sobrien
8198948Sobrienstruct decision_test
8298948Sobrien{
8319370Spst  /* A linked list through the tests attached to a node.  */
8419370Spst  struct decision_test *next;
8519370Spst
8698948Sobrien  /* These types are roughly in the order in which we'd like to test them.  */
8746283Sdfr  enum decision_type
8898948Sobrien    {
8998948Sobrien      DT_mode, DT_code, DT_veclen,
9098948Sobrien      DT_elt_zero_int, DT_elt_one_int, DT_elt_zero_wide, DT_elt_zero_wide_safe,
9198948Sobrien      DT_veclen_ge, DT_dup, DT_pred, DT_c_test,
9219370Spst      DT_accept_op, DT_accept_insn
9319370Spst    } type;
9498948Sobrien
9598948Sobrien  union
9619370Spst  {
9798948Sobrien    enum machine_mode mode;	/* Machine mode of node.  */
9819370Spst    RTX_CODE code;		/* Code to test.  */
99130809Smarcel
10019370Spst    struct
10198948Sobrien    {
10219370Spst      const char *name;		/* Predicate to call.  */
103130809Smarcel      int index;		/* Index into `preds' or -1.  */
10498948Sobrien      enum machine_mode mode;	/* Machine mode for node.  */
10519370Spst    } pred;
10619370Spst
10719370Spst    const char *c_test;		/* Additional test to perform.  */
10819370Spst    int veclen;			/* Length of vector.  */
10998948Sobrien    int dup;			/* Number of operand to compare against.  */
11098948Sobrien    HOST_WIDE_INT intval;	/* Value for XINT for XWINT.  */
11198948Sobrien    int opno;			/* Operand number matched.  */
11298948Sobrien
11398948Sobrien    struct {
114130809Smarcel      int code_number;		/* Insn number matched.  */
11519370Spst      int lineno;		/* Line number of the insn.  */
11698948Sobrien      int num_clobbers_to_add;	/* Number of CLOBBERs to be added.  */
11798948Sobrien    } insn;
11898948Sobrien  } u;
11998948Sobrien};
12098948Sobrien
12198948Sobrien/* Data structure for decision tree for recognizing legitimate insns.  */
12298948Sobrien
12319370Spststruct decision
12419370Spst{
12519370Spst  struct decision_head success;	/* Nodes to test on success.  */
12619370Spst  struct decision *next;	/* Node to test on failure.  */
12719370Spst  struct decision *prev;	/* Node whose failure tests us.  */
12819370Spst  struct decision *afterward;	/* Node to test on success,
12919370Spst				   but failure of successor nodes.  */
13019370Spst
13119370Spst  const char *position;		/* String denoting position in pattern.  */
13219370Spst
13319370Spst  struct decision_test *tests;	/* The tests for this node.  */
13419370Spst
13519370Spst  int number;			/* Node number, used for labels */
13619370Spst  int subroutine_number;	/* Number of subroutine this node starts */
13719370Spst  int need_label;		/* Label needs to be output.  */
13819370Spst};
13919370Spst
14019370Spst#define SUBROUTINE_THRESHOLD	100
14119370Spst
14219370Spststatic int next_subroutine_number;
14319370Spst
144130809Smarcel/* We can write three types of subroutines: One for insn recognition,
145130809Smarcel   one to split insns, and one for peephole-type optimizations.  This
14619370Spst   defines which type is being written.  */
14719370Spst
14819370Spstenum routine_type {
149130809Smarcel  RECOG, SPLIT, PEEPHOLE2
150130809Smarcel};
15119370Spst
15219370Spst#define IS_SPLIT(X) ((X) != RECOG)
15319370Spst
15419370Spst/* Next available node number for tree nodes.  */
15519370Spst
15619370Spststatic int next_number;
15719370Spst
15819370Spst/* Next number to use as an insn_code.  */
15919370Spst
16019370Spststatic int next_insn_code;
16119370Spst
16219370Spst/* Similar, but counts all expressions in the MD file; used for
16319370Spst   error messages.  */
16419370Spst
16519370Spststatic int next_index;
16619370Spst
16719370Spst/* Record the highest depth we ever have so we know how many variables to
16819370Spst   allocate in each subroutine we make.  */
16919370Spst
17019370Spststatic int max_depth;
17119370Spst
17246283Sdfr/* The line number of the start of the pattern currently being processed.  */
17346283Sdfrstatic int pattern_lineno;
17498948Sobrien
17546283Sdfr/* Count of errors.  */
17619370Spststatic int error_count;
17719370Spst
17819370Spst/* This table contains a list of the rtl codes that can possibly match a
17919370Spst   predicate defined in recog.c.  The function `maybe_both_true' uses it to
18019370Spst   deduce that there are no expressions that can be matches by certain pairs
18119370Spst   of tree nodes.  Also, if a predicate can match only one code, we can
18298948Sobrien   hardwire that code into the node testing the predicate.  */
18319370Spst
18498948Sobrienstatic const struct pred_table
18546283Sdfr{
18646283Sdfr  const char *const name;
18746283Sdfr  const RTX_CODE codes[NUM_RTX_CODE];
18898948Sobrien} preds[] = {
18946283Sdfr  {"general_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF,
19098948Sobrien		       LABEL_REF, SUBREG, REG, MEM}},
19146283Sdfr#ifdef PREDICATE_CODES
19298948Sobrien  PREDICATE_CODES
19346283Sdfr#endif
19498948Sobrien  {"address_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF,
19546283Sdfr		       LABEL_REF, SUBREG, REG, MEM, PLUS, MINUS, MULT}},
19698948Sobrien  {"register_operand", {SUBREG, REG}},
19746283Sdfr  {"pmode_register_operand", {SUBREG, REG}},
19898948Sobrien  {"scratch_operand", {SCRATCH, REG}},
19946283Sdfr  {"immediate_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF,
20098948Sobrien			 LABEL_REF}},
20146283Sdfr  {"const_int_operand", {CONST_INT}},
20298948Sobrien  {"const_double_operand", {CONST_INT, CONST_DOUBLE}},
20398948Sobrien  {"nonimmediate_operand", {SUBREG, REG, MEM}},
20498948Sobrien  {"nonmemory_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF,
20598948Sobrien			 LABEL_REF, SUBREG, REG}},
20698948Sobrien  {"push_operand", {MEM}},
20798948Sobrien  {"pop_operand", {MEM}},
20898948Sobrien  {"memory_operand", {SUBREG, MEM}},
20998948Sobrien  {"indirect_operand", {SUBREG, MEM}},
21098948Sobrien  {"comparison_operator", {EQ, NE, LE, LT, GE, GT, LEU, LTU, GEU, GTU,
21198948Sobrien			   UNORDERED, ORDERED, UNEQ, UNGE, UNGT, UNLE,
21298948Sobrien			   UNLT, LTGT}},
21398948Sobrien  {"mode_independent_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF,
21498948Sobrien				LABEL_REF, SUBREG, REG, MEM}}
21598948Sobrien};
21698948Sobrien
21798948Sobrien#define NUM_KNOWN_PREDS ARRAY_SIZE (preds)
21898948Sobrien
21998948Sobrienstatic const char *const special_mode_pred_table[] = {
22098948Sobrien#ifdef SPECIAL_MODE_PREDICATES
22198948Sobrien  SPECIAL_MODE_PREDICATES
22298948Sobrien#endif
22398948Sobrien  "pmode_register_operand"
22498948Sobrien};
22598948Sobrien
22698948Sobrien#define NUM_SPECIAL_MODE_PREDS ARRAY_SIZE (special_mode_pred_table)
22798948Sobrien
22898948Sobrienstatic struct decision *new_decision
22998948Sobrien  PARAMS ((const char *, struct decision_head *));
23098948Sobrienstatic struct decision_test *new_decision_test
23198948Sobrien  PARAMS ((enum decision_type, struct decision_test ***));
23298948Sobrienstatic rtx find_operand
23398948Sobrien  PARAMS ((rtx, int));
23498948Sobrienstatic rtx find_matching_operand
23598948Sobrien  PARAMS ((rtx, int));
23698948Sobrienstatic void validate_pattern
23798948Sobrien  PARAMS ((rtx, rtx, rtx, int));
23898948Sobrienstatic struct decision *add_to_sequence
23998948Sobrien  PARAMS ((rtx, struct decision_head *, const char *, enum routine_type, int));
24098948Sobrien
24198948Sobrienstatic int maybe_both_true_2
24298948Sobrien  PARAMS ((struct decision_test *, struct decision_test *));
24398948Sobrienstatic int maybe_both_true_1
24498948Sobrien  PARAMS ((struct decision_test *, struct decision_test *));
24598948Sobrienstatic int maybe_both_true
24698948Sobrien  PARAMS ((struct decision *, struct decision *, int));
24798948Sobrien
24898948Sobrienstatic int nodes_identical_1
24998948Sobrien  PARAMS ((struct decision_test *, struct decision_test *));
25098948Sobrienstatic int nodes_identical
25198948Sobrien  PARAMS ((struct decision *, struct decision *));
25298948Sobrienstatic void merge_accept_insn
25398948Sobrien  PARAMS ((struct decision *, struct decision *));
25498948Sobrienstatic void merge_trees
25598948Sobrien  PARAMS ((struct decision_head *, struct decision_head *));
25698948Sobrien
25798948Sobrienstatic void factor_tests
25898948Sobrien  PARAMS ((struct decision_head *));
25998948Sobrienstatic void simplify_tests
26098948Sobrien  PARAMS ((struct decision_head *));
26198948Sobrienstatic int break_out_subroutines
26298948Sobrien  PARAMS ((struct decision_head *, int));
26398948Sobrienstatic void find_afterward
26498948Sobrien  PARAMS ((struct decision_head *, struct decision *));
26598948Sobrien
26698948Sobrienstatic void change_state
267130809Smarcel  PARAMS ((const char *, const char *, struct decision *, const char *));
268130809Smarcelstatic void print_code
269130809Smarcel  PARAMS ((enum rtx_code));
27019370Spststatic void write_afterward
27146283Sdfr  PARAMS ((struct decision *, struct decision *, const char *));
27219370Spststatic struct decision *write_switch
27319370Spst  PARAMS ((struct decision *, int));
27446283Sdfrstatic void write_cond
27519370Spst  PARAMS ((struct decision_test *, int, enum routine_type));
27619370Spststatic void write_action
27719370Spst  PARAMS ((struct decision *, struct decision_test *, int, int,
27819370Spst	   struct decision *, enum routine_type));
27919370Spststatic int is_unconditional
28019370Spst  PARAMS ((struct decision_test *, enum routine_type));
28119370Spststatic int write_node
28219370Spst  PARAMS ((struct decision *, int, enum routine_type));
283130809Smarcelstatic void write_tree_1
28419370Spst  PARAMS ((struct decision_head *, int, enum routine_type));
28598948Sobrienstatic void write_tree
28646283Sdfr  PARAMS ((struct decision_head *, const char *, enum routine_type, int));
28746283Sdfrstatic void write_subroutine
28846283Sdfr  PARAMS ((struct decision_head *, enum routine_type));
289130809Smarcelstatic void write_subroutines
29046283Sdfr  PARAMS ((struct decision_head *, enum routine_type));
29198948Sobrienstatic void write_header
29246283Sdfr  PARAMS ((void));
29346283Sdfr
29446283Sdfrstatic struct decision_head make_insn_sequence
295130809Smarcel  PARAMS ((rtx, enum routine_type));
29646283Sdfrstatic void process_tree
29798948Sobrien  PARAMS ((struct decision_head *, enum routine_type));
29846283Sdfr
29946283Sdfrstatic void record_insn_name
30046283Sdfr  PARAMS ((int, const char *));
301130809Smarcel
30246283Sdfrstatic void debug_decision_0
30398948Sobrien  PARAMS ((struct decision *, int, int));
30498948Sobrienstatic void debug_decision_1
30598948Sobrien  PARAMS ((struct decision *, int));
30698948Sobrienstatic void debug_decision_2
307130809Smarcel  PARAMS ((struct decision_test *));
30898948Sobrienextern void debug_decision
30998948Sobrien  PARAMS ((struct decision *));
31098948Sobrienextern void debug_decision_list
31198948Sobrien  PARAMS ((struct decision *));
312130809Smarcel
313130809Smarcel/* Create a new node in sequence after LAST.  */
314130809Smarcel
31598948Sobrienstatic struct decision *
316130809Smarcelnew_decision (position, last)
31746283Sdfr     const char *position;
31819370Spst     struct decision_head *last;
31946283Sdfr{
32019370Spst  struct decision *new
32198948Sobrien    = (struct decision *) xmalloc (sizeof (struct decision));
32219370Spst
32319370Spst  memset (new, 0, sizeof (*new));
32419370Spst  new->success = *last;
32519370Spst  new->position = xstrdup (position);
32619370Spst  new->number = next_number++;
32719370Spst
32819370Spst  last->first = last->last = new;
329130809Smarcel  return new;
33019370Spst}
33198948Sobrien
33246283Sdfr/* Create a new test and link it in at PLACE.  */
33346283Sdfr
33446283Sdfrstatic struct decision_test *
335130809Smarcelnew_decision_test (type, pplace)
33646283Sdfr     enum decision_type type;
33798948Sobrien     struct decision_test ***pplace;
33846283Sdfr{
33946283Sdfr  struct decision_test **place = *pplace;
34046283Sdfr  struct decision_test *test;
341130809Smarcel
34246283Sdfr  test = (struct decision_test *) xmalloc (sizeof (*test));
34398948Sobrien  test->next = *place;
34498948Sobrien  test->type = type;
34598948Sobrien  *place = test;
34698948Sobrien
347130809Smarcel  place = &test->next;
348130809Smarcel  *pplace = place;
34998948Sobrien
350130809Smarcel  return test;
35146283Sdfr}
35219370Spst
35346283Sdfr/* Search for and return operand N.  */
35498948Sobrien
35519370Spststatic rtx
35619370Spstfind_operand (pattern, n)
35719370Spst     rtx pattern;
35819370Spst     int n;
35919370Spst{
36098948Sobrien  const char *fmt;
36119370Spst  RTX_CODE code;
36298948Sobrien  int i, j, len;
36346283Sdfr  rtx r;
36419370Spst
36546283Sdfr  code = GET_CODE (pattern);
36698948Sobrien  if ((code == MATCH_SCRATCH
36746283Sdfr       || code == MATCH_INSN
36898948Sobrien       || code == MATCH_OPERAND
36946283Sdfr       || code == MATCH_OPERATOR
37046283Sdfr       || code == MATCH_PARALLEL)
37146283Sdfr      && XINT (pattern, 0) == n)
37298948Sobrien    return pattern;
37346283Sdfr
37446283Sdfr  fmt = GET_RTX_FORMAT (code);
37546283Sdfr  len = GET_RTX_LENGTH (code);
37646283Sdfr  for (i = 0; i < len; i++)
37719370Spst    {
37819370Spst      switch (fmt[i])
37919370Spst	{
38019370Spst	case 'e': case 'u':
38119370Spst	  if ((r = find_operand (XEXP (pattern, i), n)) != NULL_RTX)
38298948Sobrien	    return r;
38319370Spst	  break;
38498948Sobrien
38519370Spst	case 'V':
38619370Spst	  if (! XVEC (pattern, i))
38746283Sdfr	    break;
38898948Sobrien	  /* FALLTHRU */
38946283Sdfr
39098948Sobrien	case 'E':
39146283Sdfr	  for (j = 0; j < XVECLEN (pattern, i); j++)
39246283Sdfr	    if ((r = find_operand (XVECEXP (pattern, i, j), n)) != NULL_RTX)
39346283Sdfr	      return r;
39498948Sobrien	  break;
39546283Sdfr
39646283Sdfr	case 'i': case 'w': case '0': case 's':
39746283Sdfr	  break;
39846283Sdfr
39919370Spst	default:
40019370Spst	  abort ();
40119370Spst	}
40298948Sobrien    }
40398948Sobrien
40419370Spst  return NULL;
40519370Spst}
40619370Spst
40719370Spst/* Search for and return operand M, such that it has a matching
40898948Sobrien   constraint for operand N.  */
40919370Spst
41098948Sobrienstatic rtx
41198948Sobrienfind_matching_operand (pattern, n)
41298948Sobrien     rtx pattern;
41398948Sobrien     int n;
41498948Sobrien{
41598948Sobrien  const char *fmt;
41698948Sobrien  RTX_CODE code;
41798948Sobrien  int i, j, len;
41898948Sobrien  rtx r;
41919370Spst
42019370Spst  code = GET_CODE (pattern);
42119370Spst  if (code == MATCH_OPERAND
42219370Spst      && (XSTR (pattern, 2)[0] == '0' + n
42319370Spst	  || (XSTR (pattern, 2)[0] == '%'
42419370Spst	      && XSTR (pattern, 2)[1] == '0' + n)))
42519370Spst    return pattern;
42619370Spst
42719370Spst  fmt = GET_RTX_FORMAT (code);
42819370Spst  len = GET_RTX_LENGTH (code);
42998948Sobrien  for (i = 0; i < len; i++)
43019370Spst    {
43119370Spst      switch (fmt[i])
43219370Spst	{
43398948Sobrien	case 'e': case 'u':
43498948Sobrien	  if ((r = find_matching_operand (XEXP (pattern, i), n)))
43598948Sobrien	    return r;
43698948Sobrien	  break;
43798948Sobrien
43898948Sobrien	case 'V':
43998948Sobrien	  if (! XVEC (pattern, i))
44019370Spst	    break;
441130809Smarcel	  /* FALLTHRU */
442130809Smarcel
44398948Sobrien	case 'E':
44498948Sobrien	  for (j = 0; j < XVECLEN (pattern, i); j++)
44598948Sobrien	    if ((r = find_matching_operand (XVECEXP (pattern, i, j), n)))
44698948Sobrien	      return r;
44798948Sobrien	  break;
44819370Spst
44998948Sobrien	case 'i': case 'w': case '0': case 's':
45098948Sobrien	  break;
45198948Sobrien
45298948Sobrien	default:
45398948Sobrien	  abort ();
45498948Sobrien	}
45598948Sobrien    }
45698948Sobrien
45719370Spst  return NULL;
45898948Sobrien}
45919370Spst
46098948Sobrien
46198948Sobrien/* Check for various errors in patterns.  SET is nonnull for a destination,
46298948Sobrien   and is the complete set pattern.  SET_CODE is '=' for normal sets, and
46398948Sobrien   '+' within a context that requires in-out constraints.  */
46498948Sobrien
46598948Sobrienstatic void
46698948Sobrienvalidate_pattern (pattern, insn, set, set_code)
46798948Sobrien     rtx pattern;
46898948Sobrien     rtx insn;
46998948Sobrien     rtx set;
47098948Sobrien     int set_code;
47198948Sobrien{
472130809Smarcel  const char *fmt;
473130809Smarcel  RTX_CODE code;
474130809Smarcel  size_t i, len;
475130809Smarcel  int j;
476130809Smarcel
477130809Smarcel  code = GET_CODE (pattern);
47819370Spst  switch (code)
47919370Spst    {
48098948Sobrien    case MATCH_SCRATCH:
48198948Sobrien      return;
48298948Sobrien
48398948Sobrien    case MATCH_INSN:
48498948Sobrien    case MATCH_OPERAND:
48598948Sobrien    case MATCH_OPERATOR:
48619370Spst      {
48798948Sobrien	const char *pred_name = XSTR (pattern, 1);
48898948Sobrien	int allows_non_lvalue = 1, allows_non_const = 1;
48998948Sobrien	int special_mode_pred = 0;
49098948Sobrien	const char *c_test;
49198948Sobrien
49298948Sobrien	if (GET_CODE (insn) == DEFINE_INSN)
49398948Sobrien	  c_test = XSTR (insn, 2);
49498948Sobrien	else
49598948Sobrien	  c_test = XSTR (insn, 1);
49698948Sobrien
49719370Spst	if (pred_name[0] != 0)
49898948Sobrien	  {
49998948Sobrien	    for (i = 0; i < NUM_KNOWN_PREDS; i++)
50098948Sobrien	      if (! strcmp (preds[i].name, pred_name))
50119370Spst		break;
50298948Sobrien
50319370Spst	    if (i < NUM_KNOWN_PREDS)
504130809Smarcel	      {
505130809Smarcel		int j;
50698948Sobrien
50798948Sobrien		allows_non_lvalue = allows_non_const = 0;
50898948Sobrien		for (j = 0; preds[i].codes[j] != 0; j++)
50998948Sobrien		  {
51019370Spst		    RTX_CODE c = preds[i].codes[j];
51119370Spst		    if (c != LABEL_REF
51298948Sobrien			&& c != SYMBOL_REF
51398948Sobrien			&& c != CONST_INT
51498948Sobrien			&& c != CONST_DOUBLE
51598948Sobrien			&& c != CONST
51698948Sobrien			&& c != HIGH
51798948Sobrien			&& c != CONSTANT_P_RTX)
51898948Sobrien		      allows_non_const = 1;
51998948Sobrien
52019370Spst		    if (c != REG
52198948Sobrien			&& c != SUBREG
52219370Spst			&& c != MEM
52398948Sobrien			&& c != CONCAT
52498948Sobrien			&& c != PARALLEL
52546283Sdfr			&& c != STRICT_LOW_PART)
52698948Sobrien		      allows_non_lvalue = 1;
52798948Sobrien		  }
52898948Sobrien	      }
52998948Sobrien	    else
53098948Sobrien	      {
53198948Sobrien#ifdef PREDICATE_CODES
53219370Spst		/* If the port has a list of the predicates it uses but
53398948Sobrien		   omits one, warn.  */
53498948Sobrien		message_with_line (pattern_lineno,
535130809Smarcel				   "warning: `%s' not in PREDICATE_CODES",
536130809Smarcel				   pred_name);
537130809Smarcel#endif
538130809Smarcel	      }
539130809Smarcel
540130809Smarcel	    for (i = 0; i < NUM_SPECIAL_MODE_PREDS; ++i)
54198948Sobrien	      if (strcmp (pred_name, special_mode_pred_table[i]) == 0)
54219370Spst		{
54398948Sobrien		  special_mode_pred = 1;
54498948Sobrien		  break;
54598948Sobrien		}
54698948Sobrien	  }
54798948Sobrien
54898948Sobrien	if (code == MATCH_OPERAND)
54998948Sobrien	  {
55098948Sobrien	    const char constraints0 = XSTR (pattern, 2)[0];
55198948Sobrien
55298948Sobrien	    /* In DEFINE_EXPAND, DEFINE_SPLIT, and DEFINE_PEEPHOLE2, we
55398948Sobrien	       don't use the MATCH_OPERAND constraint, only the predicate.
55498948Sobrien	       This is confusing to folks doing new ports, so help them
55598948Sobrien	       not make the mistake.  */
55619370Spst	    if (GET_CODE (insn) == DEFINE_EXPAND
55798948Sobrien		|| GET_CODE (insn) == DEFINE_SPLIT
55819370Spst		|| GET_CODE (insn) == DEFINE_PEEPHOLE2)
559130809Smarcel	      {
56098948Sobrien		if (constraints0)
56198948Sobrien		  message_with_line (pattern_lineno,
56298948Sobrien				     "warning: constraints not supported in %s",
56398948Sobrien				     rtx_name[GET_CODE (insn)]);
56498948Sobrien	      }
56598948Sobrien
56698948Sobrien	    /* A MATCH_OPERAND that is a SET should have an output reload.  */
56798948Sobrien	    else if (set && constraints0)
56819370Spst	      {
56998948Sobrien		if (set_code == '+')
57098948Sobrien		  {
57198948Sobrien		    if (constraints0 == '+')
57219370Spst		      ;
57398948Sobrien		    /* If we've only got an output reload for this operand,
57498948Sobrien		       we'd better have a matching input operand.  */
57598948Sobrien		    else if (constraints0 == '='
57698948Sobrien			     && find_matching_operand (insn, XINT (pattern, 0)))
577130809Smarcel		      ;
57898948Sobrien		    else
57998948Sobrien		      {
58019370Spst			message_with_line (pattern_lineno,
58119370Spst					   "operand %d missing in-out reload",
58219370Spst					   XINT (pattern, 0));
58319370Spst			error_count++;
58498948Sobrien		      }
58598948Sobrien		  }
58698948Sobrien		else if (constraints0 != '=' && constraints0 != '+')
58798948Sobrien		  {
58898948Sobrien		    message_with_line (pattern_lineno,
58919370Spst				       "operand %d missing output reload",
59098948Sobrien				       XINT (pattern, 0));
591130809Smarcel		    error_count++;
59298948Sobrien		  }
59398948Sobrien	      }
59498948Sobrien	  }
59598948Sobrien
59698948Sobrien	/* Allowing non-lvalues in destinations -- particularly CONST_INT --
59798948Sobrien	   while not likely to occur at runtime, results in less efficient
59819370Spst	   code from insn-recog.c.  */
59998948Sobrien	if (set
60098948Sobrien	    && pred_name[0] != '\0'
60198948Sobrien	    && allows_non_lvalue)
60219370Spst	  {
60319370Spst	    message_with_line (pattern_lineno,
60498948Sobrien			"warning: destination operand %d allows non-lvalue",
60519370Spst			XINT (pattern, 0));
60698948Sobrien	  }
60798948Sobrien
60898948Sobrien	/* A modeless MATCH_OPERAND can be handy when we can
60998948Sobrien	   check for multiple modes in the c_test.  In most other cases,
61098948Sobrien	   it is a mistake.  Only DEFINE_INSN is eligible, since SPLIT
61198948Sobrien	   and PEEP2 can FAIL within the output pattern.  Exclude
61298948Sobrien	   address_operand, since its mode is related to the mode of
613130809Smarcel	   the memory not the operand.  Exclude the SET_DEST of a call
61498948Sobrien	   instruction, as that is a common idiom.  */
61519370Spst
61619370Spst	if (GET_MODE (pattern) == VOIDmode
61798948Sobrien	    && code == MATCH_OPERAND
61819370Spst	    && GET_CODE (insn) == DEFINE_INSN
61919370Spst	    && allows_non_const
62019370Spst	    && ! special_mode_pred
62119370Spst	    && pred_name[0] != '\0'
62298948Sobrien	    && strcmp (pred_name, "address_operand") != 0
62319370Spst	    && strstr (c_test, "operands") == NULL
62498948Sobrien	    && ! (set
62598948Sobrien		  && GET_CODE (set) == SET
62619370Spst		  && GET_CODE (SET_SRC (set)) == CALL))
627130809Smarcel	  {
628130809Smarcel	    message_with_line (pattern_lineno,
62998948Sobrien			       "warning: operand %d missing mode?",
630130809Smarcel			       XINT (pattern, 0));
631130809Smarcel	  }
632130809Smarcel	return;
633130809Smarcel      }
634130809Smarcel
635130809Smarcel    case SET:
636130809Smarcel      {
637130809Smarcel	enum machine_mode dmode, smode;
638130809Smarcel	rtx dest, src;
639130809Smarcel
640130809Smarcel	dest = SET_DEST (pattern);
641130809Smarcel	src = SET_SRC (pattern);
642130809Smarcel
643130809Smarcel	/* STRICT_LOW_PART is a wrapper.  Its argument is the real
644130809Smarcel	   destination, and it's mode should match the source.  */
645130809Smarcel	if (GET_CODE (dest) == STRICT_LOW_PART)
646130809Smarcel	  dest = XEXP (dest, 0);
647130809Smarcel
648130809Smarcel	/* Find the referant for a DUP.  */
649130809Smarcel
650130809Smarcel	if (GET_CODE (dest) == MATCH_DUP
651130809Smarcel	    || GET_CODE (dest) == MATCH_OP_DUP
652130809Smarcel	    || GET_CODE (dest) == MATCH_PAR_DUP)
653130809Smarcel	  dest = find_operand (insn, XINT (dest, 0));
654130809Smarcel
655130809Smarcel	if (GET_CODE (src) == MATCH_DUP
656130809Smarcel	    || GET_CODE (src) == MATCH_OP_DUP
657130809Smarcel	    || GET_CODE (src) == MATCH_PAR_DUP)
658130809Smarcel	  src = find_operand (insn, XINT (src, 0));
659130809Smarcel
66098948Sobrien	dmode = GET_MODE (dest);
66198948Sobrien	smode = GET_MODE (src);
66298948Sobrien
66398948Sobrien	/* The mode of an ADDRESS_OPERAND is the mode of the memory
66419370Spst	   reference, not the mode of the address.  */
66598948Sobrien	if (GET_CODE (src) == MATCH_OPERAND
66698948Sobrien	    && ! strcmp (XSTR (src, 1), "address_operand"))
66798948Sobrien	  ;
66898948Sobrien
66998948Sobrien        /* The operands of a SET must have the same mode unless one
67098948Sobrien	   is VOIDmode.  */
67198948Sobrien        else if (dmode != VOIDmode && smode != VOIDmode && dmode != smode)
67298948Sobrien	  {
67398948Sobrien	    message_with_line (pattern_lineno,
67498948Sobrien			       "mode mismatch in set: %smode vs %smode",
675130809Smarcel			       GET_MODE_NAME (dmode), GET_MODE_NAME (smode));
67698948Sobrien	    error_count++;
67798948Sobrien	  }
67898948Sobrien
67998948Sobrien	/* If only one of the operands is VOIDmode, and PC or CC0 is
68019370Spst	   not involved, it's probably a mistake.  */
68119370Spst	else if (dmode != smode
68298948Sobrien		 && GET_CODE (dest) != PC
68319370Spst		 && GET_CODE (dest) != CC0
68419370Spst		 && GET_CODE (src) != PC
68598948Sobrien		 && GET_CODE (src) != CC0
68619370Spst		 && GET_CODE (src) != CONST_INT)
68798948Sobrien	  {
68898948Sobrien	    const char *which;
68998948Sobrien	    which = (dmode == VOIDmode ? "destination" : "source");
690130809Smarcel	    message_with_line (pattern_lineno,
69198948Sobrien			       "warning: %s missing a mode?", which);
69219370Spst	  }
69398948Sobrien
69498948Sobrien	if (dest != SET_DEST (pattern))
69598948Sobrien	  validate_pattern (dest, insn, pattern, '=');
69698948Sobrien	validate_pattern (SET_DEST (pattern), insn, pattern, '=');
69798948Sobrien        validate_pattern (SET_SRC (pattern), insn, NULL_RTX, 0);
69898948Sobrien        return;
699130809Smarcel      }
700130809Smarcel
701130809Smarcel    case CLOBBER:
70298948Sobrien      validate_pattern (SET_DEST (pattern), insn, pattern, '=');
703130809Smarcel      return;
70498948Sobrien
705130809Smarcel    case ZERO_EXTRACT:
706130809Smarcel      validate_pattern (XEXP (pattern, 0), insn, set, set ? '+' : 0);
707130809Smarcel      validate_pattern (XEXP (pattern, 1), insn, NULL_RTX, 0);
708130809Smarcel      validate_pattern (XEXP (pattern, 2), insn, NULL_RTX, 0);
709130809Smarcel      return;
710130809Smarcel
711130809Smarcel    case STRICT_LOW_PART:
712130809Smarcel      validate_pattern (XEXP (pattern, 0), insn, set, set ? '+' : 0);
713130809Smarcel      return;
714130809Smarcel
715130809Smarcel    case LABEL_REF:
716130809Smarcel      if (GET_MODE (XEXP (pattern, 0)) != VOIDmode)
717130809Smarcel	{
718130809Smarcel	  message_with_line (pattern_lineno,
719130809Smarcel			     "operand to label_ref %smode not VOIDmode",
720130809Smarcel			     GET_MODE_NAME (GET_MODE (XEXP (pattern, 0))));
72198948Sobrien	  error_count++;
72298948Sobrien	}
723130809Smarcel      break;
72498948Sobrien
725130809Smarcel    default:
726130809Smarcel      break;
727130809Smarcel    }
728130809Smarcel
729130809Smarcel  fmt = GET_RTX_FORMAT (code);
730130809Smarcel  len = GET_RTX_LENGTH (code);
731130809Smarcel  for (i = 0; i < len; i++)
732130809Smarcel    {
733130809Smarcel      switch (fmt[i])
734130809Smarcel	{
735130809Smarcel	case 'e': case 'u':
736130809Smarcel	  validate_pattern (XEXP (pattern, i), insn, NULL_RTX, 0);
737130809Smarcel	  break;
738130809Smarcel
739130809Smarcel	case 'E':
740130809Smarcel	  for (j = 0; j < XVECLEN (pattern, i); j++)
741130809Smarcel	    validate_pattern (XVECEXP (pattern, i, j), insn, NULL_RTX, 0);
742130809Smarcel	  break;
743130809Smarcel
744130809Smarcel	case 'i': case 'w': case '0': case 's':
745130809Smarcel	  break;
746130809Smarcel
747130809Smarcel	default:
748130809Smarcel	  abort ();
749130809Smarcel	}
750130809Smarcel    }
751130809Smarcel}
752130809Smarcel
753130809Smarcel/* Create a chain of nodes to verify that an rtl expression matches
754130809Smarcel   PATTERN.
755130809Smarcel
756130809Smarcel   LAST is a pointer to the listhead in the previous node in the chain (or
757130809Smarcel   in the calling function, for the first node).
758130809Smarcel
759130809Smarcel   POSITION is the string representing the current position in the insn.
760130809Smarcel
761130809Smarcel   INSN_TYPE is the type of insn for which we are emitting code.
762130809Smarcel
763130809Smarcel   A pointer to the final node in the chain is returned.  */
764130809Smarcel
76519370Spststatic struct decision *
766130809Smarceladd_to_sequence (pattern, last, position, insn_type, top)
767130809Smarcel     rtx pattern;
768130809Smarcel     struct decision_head *last;
769130809Smarcel     const char *position;
770130809Smarcel     enum routine_type insn_type;
77198948Sobrien     int top;
772130809Smarcel{
773130809Smarcel  RTX_CODE code;
774130809Smarcel  struct decision *this, *sub;
775130809Smarcel  struct decision_test *test;
776130809Smarcel  struct decision_test **place;
777130809Smarcel  char *subpos;
77898948Sobrien  size_t i;
779130809Smarcel  const char *fmt;
78019370Spst  int depth = strlen (position);
78198948Sobrien  int len;
782130809Smarcel  enum machine_mode mode;
783130809Smarcel
784130809Smarcel  if (depth > max_depth)
785130809Smarcel    max_depth = depth;
786130809Smarcel
787130809Smarcel  subpos = (char *) xmalloc (depth + 2);
788130809Smarcel  strcpy (subpos, position);
789130809Smarcel  subpos[depth + 1] = 0;
790130809Smarcel
791130809Smarcel  sub = this = new_decision (position, last);
792130809Smarcel  place = &this->tests;
793130809Smarcel
794130809Smarcel restart:
795130809Smarcel  mode = GET_MODE (pattern);
796130809Smarcel  code = GET_CODE (pattern);
797130809Smarcel
798130809Smarcel  switch (code)
799130809Smarcel    {
80098948Sobrien    case PARALLEL:
80198948Sobrien      /* Toplevel peephole pattern.  */
80298948Sobrien      if (insn_type == PEEPHOLE2 && top)
80398948Sobrien	{
804130809Smarcel	  /* We don't need the node we just created -- unlink it.  */
80598948Sobrien	  last->first = last->last = NULL;
80698948Sobrien
80798948Sobrien	  for (i = 0; i < (size_t) XVECLEN (pattern, 0); i++)
80898948Sobrien	    {
80998948Sobrien	      /* Which insn we're looking at is represented by A-Z. We don't
81098948Sobrien	         ever use 'A', however; it is always implied.  */
81198948Sobrien
81298948Sobrien	      subpos[depth] = (i > 0 ? 'A' + i : 0);
813130809Smarcel	      sub = add_to_sequence (XVECEXP (pattern, 0, i),
81498948Sobrien				     last, subpos, insn_type, 0);
81598948Sobrien	      last = &sub->success;
81698948Sobrien	    }
81798948Sobrien	  goto ret;
818130809Smarcel	}
819130809Smarcel
820130809Smarcel      /* Else nothing special.  */
821130809Smarcel      break;
822130809Smarcel
823130809Smarcel    case MATCH_PARALLEL:
824130809Smarcel      /* The explicit patterns within a match_parallel enforce a minimum
825130809Smarcel	 length on the vector.  The match_parallel predicate may allow
826130809Smarcel	 for more elements.  We do need to check for this minimum here
827130809Smarcel	 or the code generated to match the internals may reference data
82898948Sobrien	 beyond the end of the vector.  */
82919370Spst      test = new_decision_test (DT_veclen_ge, &place);
83019370Spst      test->u.veclen = XVECLEN (pattern, 2);
83198948Sobrien      /* FALLTHRU */
83298948Sobrien
83398948Sobrien    case MATCH_OPERAND:
83498948Sobrien    case MATCH_SCRATCH:
83598948Sobrien    case MATCH_OPERATOR:
83698948Sobrien    case MATCH_INSN:
83798948Sobrien      {
83898948Sobrien	const char *pred_name;
83998948Sobrien	RTX_CODE was_code = code;
840130809Smarcel	int allows_const_int = 1;
841130809Smarcel
842130809Smarcel	if (code == MATCH_SCRATCH)
843130809Smarcel	  {
844130809Smarcel	    pred_name = "scratch_operand";
845130809Smarcel	    code = UNKNOWN;
846130809Smarcel	  }
847130809Smarcel	else
848130809Smarcel	  {
849130809Smarcel	    pred_name = XSTR (pattern, 1);
850130809Smarcel	    if (code == MATCH_PARALLEL)
851130809Smarcel	      code = PARALLEL;
852130809Smarcel	    else
853130809Smarcel	      code = UNKNOWN;
854130809Smarcel	  }
855130809Smarcel
856130809Smarcel	if (pred_name[0] != 0)
857130809Smarcel	  {
858130809Smarcel	    test = new_decision_test (DT_pred, &place);
85998948Sobrien	    test->u.pred.name = pred_name;
86019370Spst	    test->u.pred.mode = mode;
86119370Spst
86219370Spst	    /* See if we know about this predicate and save its number.
86319370Spst	       If we do, and it only accepts one code, note that fact.
86498948Sobrien
86519370Spst	       If we know that the predicate does not allow CONST_INT,
86619370Spst	       we know that the only way the predicate can match is if
86719370Spst	       the modes match (here we use the kludge of relying on the
86819370Spst	       fact that "address_operand" accepts CONST_INT; otherwise,
869130809Smarcel	       it would have to be a special case), so we can test the
870130809Smarcel	       mode (but we need not).  This fact should considerably
87119370Spst	       simplify the generated code.  */
87298948Sobrien
87319370Spst	    for (i = 0; i < NUM_KNOWN_PREDS; i++)
87419370Spst	      if (! strcmp (preds[i].name, pred_name))
87519370Spst		break;
87619370Spst
87719370Spst	    if (i < NUM_KNOWN_PREDS)
87819370Spst	      {
87919370Spst		int j;
88019370Spst
88119370Spst		test->u.pred.index = i;
88246283Sdfr
88398948Sobrien		if (preds[i].codes[1] == 0 && code == UNKNOWN)
88419370Spst		  code = preds[i].codes[0];
88519370Spst
88619370Spst		allows_const_int = 0;
88719370Spst		for (j = 0; preds[i].codes[j] != 0; j++)
88819370Spst		  if (preds[i].codes[j] == CONST_INT)
88919370Spst		    {
89019370Spst		      allows_const_int = 1;
89119370Spst		      break;
89219370Spst		    }
89319370Spst	      }
89419370Spst	    else
89519370Spst	      test->u.pred.index = -1;
89619370Spst	  }
89719370Spst
89819370Spst	/* Can't enforce a mode if we allow const_int.  */
89919370Spst	if (allows_const_int)
90098948Sobrien	  mode = VOIDmode;
90119370Spst
90219370Spst	/* Accept the operand, ie. record it in `operands'.  */
90319370Spst	test = new_decision_test (DT_accept_op, &place);
90419370Spst	test->u.opno = XINT (pattern, 0);
90519370Spst
90619370Spst	if (was_code == MATCH_OPERATOR || was_code == MATCH_PARALLEL)
90798948Sobrien	  {
90819370Spst	    char base = (was_code == MATCH_OPERATOR ? '0' : 'a');
90919370Spst	    for (i = 0; i < (size_t) XVECLEN (pattern, 2); i++)
91019370Spst	      {
91119370Spst		subpos[depth] = i + base;
91219370Spst		sub = add_to_sequence (XVECEXP (pattern, 2, i),
91319370Spst				       &sub->success, subpos, insn_type, 0);
91419370Spst	      }
91519370Spst	  }
91619370Spst	goto fini;
91719370Spst      }
91819370Spst
91919370Spst    case MATCH_OP_DUP:
92019370Spst      code = UNKNOWN;
92119370Spst
92219370Spst      test = new_decision_test (DT_dup, &place);
92319370Spst      test->u.dup = XINT (pattern, 0);
92419370Spst
92519370Spst      test = new_decision_test (DT_accept_op, &place);
92619370Spst      test->u.opno = XINT (pattern, 0);
92798948Sobrien
92819370Spst      for (i = 0; i < (size_t) XVECLEN (pattern, 1); i++)
92998948Sobrien	{
93019370Spst	  subpos[depth] = i + '0';
93119370Spst	  sub = add_to_sequence (XVECEXP (pattern, 1, i),
93219370Spst				 &sub->success, subpos, insn_type, 0);
93319370Spst	}
93419370Spst      goto fini;
93519370Spst
93619370Spst    case MATCH_DUP:
93719370Spst    case MATCH_PAR_DUP:
93819370Spst      code = UNKNOWN;
93998948Sobrien
94019370Spst      test = new_decision_test (DT_dup, &place);
94119370Spst      test->u.dup = XINT (pattern, 0);
94219370Spst      goto fini;
94319370Spst
94419370Spst    case ADDRESS:
94519370Spst      pattern = XEXP (pattern, 0);
94698948Sobrien      goto restart;
94798948Sobrien
94819370Spst    default:
94919370Spst      break;
95019370Spst    }
95119370Spst
95219370Spst  fmt = GET_RTX_FORMAT (code);
953130809Smarcel  len = GET_RTX_LENGTH (code);
95419370Spst
95598948Sobrien  /* Do tests against the current node first.  */
95698948Sobrien  for (i = 0; i < (size_t) len; i++)
95798948Sobrien    {
95898948Sobrien      if (fmt[i] == 'i')
95998948Sobrien	{
96019370Spst	  if (i == 0)
961130809Smarcel	    {
962130809Smarcel	      test = new_decision_test (DT_elt_zero_int, &place);
96319370Spst	      test->u.intval = XINT (pattern, i);
96419370Spst	    }
96519370Spst	  else if (i == 1)
96619370Spst	    {
967130809Smarcel	      test = new_decision_test (DT_elt_one_int, &place);
96898948Sobrien	      test->u.intval = XINT (pattern, i);
96998948Sobrien	    }
97019370Spst	  else
97119370Spst	    abort ();
97219370Spst	}
97319370Spst      else if (fmt[i] == 'w')
97498948Sobrien	{
97519370Spst	  /* If this value actually fits in an int, we can use a switch
97619370Spst	     statement here, so indicate that.  */
97719370Spst	  enum decision_type type
97819370Spst	    = ((int) XWINT (pattern, i) == XWINT (pattern, i))
97919370Spst	      ? DT_elt_zero_wide_safe : DT_elt_zero_wide;
98019370Spst
98119370Spst	  if (i != 0)
98298948Sobrien	    abort ();
98319370Spst
98419370Spst	  test = new_decision_test (type, &place);
98519370Spst	  test->u.intval = XWINT (pattern, i);
98619370Spst	}
98719370Spst      else if (fmt[i] == 'E')
98898948Sobrien	{
98998948Sobrien	  if (i != 0)
99019370Spst	    abort ();
991130809Smarcel
99219370Spst	  test = new_decision_test (DT_veclen, &place);
99319370Spst	  test->u.veclen = XVECLEN (pattern, i);
99498948Sobrien	}
99598948Sobrien    }
99619370Spst
99798948Sobrien  /* Now test our sub-patterns.  */
99898948Sobrien  for (i = 0; i < (size_t) len; i++)
99919370Spst    {
1000130809Smarcel      switch (fmt[i])
100119370Spst	{
100219370Spst	case 'e': case 'u':
100398948Sobrien	  subpos[depth] = '0' + i;
100498948Sobrien	  sub = add_to_sequence (XEXP (pattern, i), &sub->success,
100519370Spst				 subpos, insn_type, 0);
1006130809Smarcel	  break;
100719370Spst
100819370Spst	case 'E':
100998948Sobrien	  {
101098948Sobrien	    int j;
101198948Sobrien	    for (j = 0; j < XVECLEN (pattern, i); j++)
1012130809Smarcel	      {
101398948Sobrien		subpos[depth] = 'a' + j;
101419370Spst		sub = add_to_sequence (XVECEXP (pattern, i, j),
1015130809Smarcel				       &sub->success, subpos, insn_type, 0);
1016130809Smarcel	      }
101719370Spst	    break;
101898948Sobrien	  }
101919370Spst
102019370Spst	case 'i': case 'w':
102119370Spst	  /* Handled above.  */
102219370Spst	  break;
102319370Spst	case '0':
102419370Spst	  break;
102519370Spst
102698948Sobrien	default:
102719370Spst	  abort ();
102819370Spst	}
102919370Spst    }
103098948Sobrien
1031130809Smarcel fini:
1032130809Smarcel  /* Insert nodes testing mode and code, if they're still relevant,
103319370Spst     before any of the nodes we may have added above.  */
103419370Spst  if (code != UNKNOWN)
103519370Spst    {
1036130809Smarcel      place = &this->tests;
103719370Spst      test = new_decision_test (DT_code, &place);
103819370Spst      test->u.code = code;
103919370Spst    }
104098948Sobrien
104119370Spst  if (mode != VOIDmode)
104298948Sobrien    {
104398948Sobrien      place = &this->tests;
104498948Sobrien      test = new_decision_test (DT_mode, &place);
104598948Sobrien      test->u.mode = mode;
104698948Sobrien    }
104798948Sobrien
104898948Sobrien  /* If we didn't insert any tests or accept nodes, hork.  */
104998948Sobrien  if (this->tests == NULL)
105098948Sobrien    abort ();
105198948Sobrien
105219370Spst ret:
105398948Sobrien  free (subpos);
105419370Spst  return sub;
1055130809Smarcel}
1056130809Smarcel
105719370Spst/* A subroutine of maybe_both_true; examines only one test.
1058130809Smarcel   Returns > 0 for "definitely both true" and < 0 for "maybe both true".  */
1059130809Smarcel
1060130809Smarcelstatic int
1061130809Smarcelmaybe_both_true_2 (d1, d2)
1062130809Smarcel     struct decision_test *d1, *d2;
1063130809Smarcel{
106419370Spst  if (d1->type == d2->type)
106519370Spst    {
106619370Spst      switch (d1->type)
106798948Sobrien	{
106898948Sobrien	case DT_mode:
106919370Spst	  return d1->u.mode == d2->u.mode;
107098948Sobrien
107119370Spst	case DT_code:
1072130809Smarcel	  return d1->u.code == d2->u.code;
1073130809Smarcel
107498948Sobrien	case DT_veclen:
1075130809Smarcel	  return d1->u.veclen == d2->u.veclen;
1076130809Smarcel
1077130809Smarcel	case DT_elt_zero_int:
1078130809Smarcel	case DT_elt_one_int:
107919370Spst	case DT_elt_zero_wide:
1080130809Smarcel	case DT_elt_zero_wide_safe:
1081130809Smarcel	  return d1->u.intval == d2->u.intval;
1082130809Smarcel
1083130809Smarcel	default:
108498948Sobrien	  break;
108598948Sobrien	}
108698948Sobrien    }
108798948Sobrien
108898948Sobrien  /* If either has a predicate that we know something about, set
108998948Sobrien     things up so that D1 is the one that always has a known
109098948Sobrien     predicate.  Then see if they have any codes in common.  */
1091130809Smarcel
1092130809Smarcel  if (d1->type == DT_pred || d2->type == DT_pred)
1093130809Smarcel    {
109498948Sobrien      if (d2->type == DT_pred)
109519370Spst	{
1096130809Smarcel	  struct decision_test *tmp;
1097130809Smarcel	  tmp = d1, d1 = d2, d2 = tmp;
109819370Spst	}
1099130809Smarcel
1100130809Smarcel      /* If D2 tests a mode, see if it matches D1.  */
1101130809Smarcel      if (d1->u.pred.mode != VOIDmode)
1102130809Smarcel	{
1103130809Smarcel	  if (d2->type == DT_mode)
110498948Sobrien	    {
110519370Spst	      if (d1->u.pred.mode != d2->u.mode
110619370Spst		  /* The mode of an address_operand predicate is the
110798948Sobrien		     mode of the memory, not the operand.  It can only
110898948Sobrien		     be used for testing the predicate, so we must
110998948Sobrien		     ignore it here.  */
111098948Sobrien		  && strcmp (d1->u.pred.name, "address_operand") != 0)
111198948Sobrien		return 0;
111298948Sobrien	    }
111319370Spst	  /* Don't check two predicate modes here, because if both predicates
111498948Sobrien	     accept CONST_INT, then both can still be true even if the modes
111598948Sobrien	     are different.  If they don't accept CONST_INT, there will be a
111698948Sobrien	     separate DT_mode that will make maybe_both_true_1 return 0.  */
111798948Sobrien	}
111898948Sobrien
111998948Sobrien      if (d1->u.pred.index >= 0)
112098948Sobrien	{
112198948Sobrien	  /* If D2 tests a code, see if it is in the list of valid
112298948Sobrien	     codes for D1's predicate.  */
112398948Sobrien	  if (d2->type == DT_code)
112498948Sobrien	    {
1125130809Smarcel	      const RTX_CODE *c = &preds[d1->u.pred.index].codes[0];
112698948Sobrien	      while (*c != 0)
112719370Spst		{
112898948Sobrien		  if (*c == d2->u.code)
112919370Spst		    break;
113019370Spst		  ++c;
1131130809Smarcel		}
1132130809Smarcel	      if (*c == 0)
113398948Sobrien		return 0;
113498948Sobrien	    }
113598948Sobrien
113619370Spst	  /* Otherwise see if the predicates have any codes in common.  */
1137130809Smarcel	  else if (d2->type == DT_pred && d2->u.pred.index >= 0)
113898948Sobrien	    {
113919370Spst	      const RTX_CODE *c1 = &preds[d1->u.pred.index].codes[0];
114098948Sobrien	      int common = 0;
114119370Spst
114219370Spst	      while (*c1 != 0 && !common)
114398948Sobrien		{
114498948Sobrien		  const RTX_CODE *c2 = &preds[d2->u.pred.index].codes[0];
114598948Sobrien		  while (*c2 != 0 && !common)
114698948Sobrien		    {
114798948Sobrien		      common = (*c1 == *c2);
114819370Spst		      ++c2;
114998948Sobrien		    }
115098948Sobrien		  ++c1;
115198948Sobrien		}
115298948Sobrien
1153130809Smarcel	      if (!common)
1154130809Smarcel		return 0;
1155130809Smarcel	    }
1156130809Smarcel	}
1157130809Smarcel    }
1158130809Smarcel
1159130809Smarcel  /* Tests vs veclen may be known when strict equality is involved.  */
1160130809Smarcel  if (d1->type == DT_veclen && d2->type == DT_veclen_ge)
1161130809Smarcel    return d1->u.veclen >= d2->u.veclen;
1162130809Smarcel  if (d1->type == DT_veclen_ge && d2->type == DT_veclen)
1163130809Smarcel    return d2->u.veclen >= d1->u.veclen;
116498948Sobrien
116598948Sobrien  return -1;
116698948Sobrien}
116798948Sobrien
116898948Sobrien/* A subroutine of maybe_both_true; examines all the tests for a given node.
116998948Sobrien   Returns > 0 for "definitely both true" and < 0 for "maybe both true".  */
117098948Sobrien
117198948Sobrienstatic int
117298948Sobrienmaybe_both_true_1 (d1, d2)
117398948Sobrien     struct decision_test *d1, *d2;
117498948Sobrien{
117598948Sobrien  struct decision_test *t1, *t2;
117698948Sobrien
117798948Sobrien  /* A match_operand with no predicate can match anything.  Recognize
117898948Sobrien     this by the existence of a lone DT_accept_op test.  */
117998948Sobrien  if (d1->type == DT_accept_op || d2->type == DT_accept_op)
118098948Sobrien    return 1;
1181130809Smarcel
118298948Sobrien  /* Eliminate pairs of tests while they can exactly match.  */
118398948Sobrien  while (d1 && d2 && d1->type == d2->type)
118498948Sobrien    {
118598948Sobrien      if (maybe_both_true_2 (d1, d2) == 0)
1186130809Smarcel	return 0;
118798948Sobrien      d1 = d1->next, d2 = d2->next;
118898948Sobrien    }
118998948Sobrien
119019370Spst  /* After that, consider all pairs.  */
119119370Spst  for (t1 = d1; t1 ; t1 = t1->next)
119219370Spst    for (t2 = d2; t2 ; t2 = t2->next)
119319370Spst      if (maybe_both_true_2 (t1, t2) == 0)
119498948Sobrien	return 0;
119519370Spst
1196130809Smarcel  return -1;
119719370Spst}
119819370Spst
119919370Spst/* Return 0 if we can prove that there is no RTL that can match both
120019370Spst   D1 and D2.  Otherwise, return 1 (it may be that there is an RTL that
120119370Spst   can match both or just that we couldn't prove there wasn't such an RTL).
120219370Spst
120319370Spst   TOPLEVEL is non-zero if we are to only look at the top level and not
120419370Spst   recursively descend.  */
120519370Spst
120619370Spststatic int
120719370Spstmaybe_both_true (d1, d2, toplevel)
120819370Spst     struct decision *d1, *d2;
120919370Spst     int toplevel;
121019370Spst{
121119370Spst  struct decision *p1, *p2;
121219370Spst  int cmp;
121319370Spst
121419370Spst  /* Don't compare strings on the different positions in insn.  Doing so
121519370Spst     is incorrect and results in false matches from constructs like
121619370Spst
121798948Sobrien	[(set (subreg:HI (match_operand:SI "register_operand" "r") 0)
121819370Spst	      (subreg:HI (match_operand:SI "register_operand" "r") 0))]
1219130809Smarcel     vs
122019370Spst	[(set (match_operand:HI "register_operand" "r")
122119370Spst	      (match_operand:HI "register_operand" "r"))]
122219370Spst
122319370Spst     If we are presented with such, we are recursing through the remainder
122419370Spst     of a node's success nodes (from the loop at the end of this function).
122519370Spst     Skip forward until we come to a position that matches.
122698948Sobrien
122719370Spst     Due to the way position strings are constructed, we know that iterating
1228130809Smarcel     forward from the lexically lower position (e.g. "00") will run into
122919370Spst     the lexically higher position (e.g. "1") and not the other way around.
123019370Spst     This saves a bit of effort.  */
123119370Spst
123219370Spst  cmp = strcmp (d1->position, d2->position);
123319370Spst  if (cmp != 0)
123419370Spst    {
123598948Sobrien      if (toplevel)
123619370Spst	abort ();
123719370Spst
123819370Spst      /* If the d2->position was lexically lower, swap.  */
123919370Spst      if (cmp > 0)
124019370Spst	p1 = d1, d1 = d2, d2 = p1;
1241130809Smarcel
124219370Spst      if (d1->success.first == 0)
124398948Sobrien	return 1;
124419370Spst      for (p1 = d1->success.first; p1; p1 = p1->next)
124519370Spst	if (maybe_both_true (p1, d2, 0))
124619370Spst	  return 1;
124719370Spst
124819370Spst      return 0;
1249130809Smarcel    }
125019370Spst
125119370Spst  /* Test the current level.  */
125219370Spst  cmp = maybe_both_true_1 (d1->tests, d2->tests);
125319370Spst  if (cmp >= 0)
125419370Spst    return cmp;
125519370Spst
125698948Sobrien  /* We can't prove that D1 and D2 cannot both be true.  If we are only
125719370Spst     to check the top level, return 1.  Otherwise, see if we can prove
125819370Spst     that all choices in both successors are mutually exclusive.  If
125919370Spst     either does not have any successors, we can't prove they can't both
126019370Spst     be true.  */
126119370Spst
126219370Spst  if (toplevel || d1->success.first == 0 || d2->success.first == 0)
126319370Spst    return 1;
126419370Spst
126519370Spst  for (p1 = d1->success.first; p1; p1 = p1->next)
1266130809Smarcel    for (p2 = d2->success.first; p2; p2 = p2->next)
126719370Spst      if (maybe_both_true (p1, p2, 0))
126819370Spst	return 1;
1269130809Smarcel
1270130809Smarcel  return 0;
127119370Spst}
127219370Spst
127319370Spst/* A subroutine of nodes_identical.  Examine two tests for equivalence.  */
127419370Spst
127519370Spststatic int
127619370Spstnodes_identical_1 (d1, d2)
127719370Spst     struct decision_test *d1, *d2;
127819370Spst{
127919370Spst  switch (d1->type)
128019370Spst    {
128119370Spst    case DT_mode:
128219370Spst      return d1->u.mode == d2->u.mode;
128319370Spst
128419370Spst    case DT_code:
128519370Spst      return d1->u.code == d2->u.code;
128619370Spst
128719370Spst    case DT_pred:
128819370Spst      return (d1->u.pred.mode == d2->u.pred.mode
128919370Spst	      && strcmp (d1->u.pred.name, d2->u.pred.name) == 0);
129019370Spst
129119370Spst    case DT_c_test:
129219370Spst      return strcmp (d1->u.c_test, d2->u.c_test) == 0;
129319370Spst
129419370Spst    case DT_veclen:
129519370Spst    case DT_veclen_ge:
129619370Spst      return d1->u.veclen == d2->u.veclen;
129719370Spst
129898948Sobrien    case DT_dup:
129919370Spst      return d1->u.dup == d2->u.dup;
130046283Sdfr
130198948Sobrien    case DT_elt_zero_int:
130219370Spst    case DT_elt_one_int:
130319370Spst    case DT_elt_zero_wide:
130498948Sobrien    case DT_elt_zero_wide_safe:
130519370Spst      return d1->u.intval == d2->u.intval;
130619370Spst
130719370Spst    case DT_accept_op:
130846283Sdfr      return d1->u.opno == d2->u.opno;
130998948Sobrien
131098948Sobrien    case DT_accept_insn:
131119370Spst      /* Differences will be handled in merge_accept_insn.  */
1312130809Smarcel      return 1;
131319370Spst
131419370Spst    default:
131598948Sobrien      abort ();
131646283Sdfr    }
131719370Spst}
131819370Spst
131919370Spst/* True iff the two nodes are identical (on one level only).  Due
132019370Spst   to the way these lists are constructed, we shouldn't have to
132119370Spst   consider different orderings on the tests.  */
132219370Spst
132319370Spststatic int
132419370Spstnodes_identical (d1, d2)
132519370Spst     struct decision *d1, *d2;
132619370Spst{
132719370Spst  struct decision_test *t1, *t2;
132819370Spst
132919370Spst  for (t1 = d1->tests, t2 = d2->tests; t1 && t2; t1 = t1->next, t2 = t2->next)
133019370Spst    {
133119370Spst      if (t1->type != t2->type)
133219370Spst	return 0;
133319370Spst      if (! nodes_identical_1 (t1, t2))
133419370Spst	return 0;
133519370Spst    }
133698948Sobrien
133719370Spst  /* For success, they should now both be null.  */
1338130809Smarcel  if (t1 != t2)
1339130809Smarcel    return 0;
1340130809Smarcel
1341130809Smarcel  /* Check that their subnodes are at the same position, as any one set
1342130809Smarcel     of sibling decisions must be at the same position.  Allowing this
1343130809Smarcel     requires complications to find_afterward and when change_state is
1344130809Smarcel     invoked.  */
1345130809Smarcel  if (d1->success.first
1346130809Smarcel      && d2->success.first
1347130809Smarcel      && strcmp (d1->success.first->position, d2->success.first->position))
1348130809Smarcel    return 0;
1349130809Smarcel
1350130809Smarcel  return 1;
1351130809Smarcel}
1352130809Smarcel
1353130809Smarcel/* A subroutine of merge_trees; given two nodes that have been declared
1354130809Smarcel   identical, cope with two insn accept states.  If they differ in the
1355130809Smarcel   number of clobbers, then the conflict was created by make_insn_sequence
1356130809Smarcel   and we can drop the with-clobbers version on the floor.  If both
1357130809Smarcel   nodes have no additional clobbers, we have found an ambiguity in the
1358130809Smarcel   source machine description.  */
1359130809Smarcel
1360130809Smarcelstatic void
1361130809Smarcelmerge_accept_insn (oldd, addd)
1362130809Smarcel     struct decision *oldd, *addd;
1363130809Smarcel{
1364130809Smarcel  struct decision_test *old, *add;
1365130809Smarcel
1366130809Smarcel  for (old = oldd->tests; old; old = old->next)
1367130809Smarcel    if (old->type == DT_accept_insn)
1368130809Smarcel      break;
1369130809Smarcel  if (old == NULL)
1370130809Smarcel    return;
1371130809Smarcel
1372130809Smarcel  for (add = addd->tests; add; add = add->next)
1373130809Smarcel    if (add->type == DT_accept_insn)
1374130809Smarcel      break;
1375130809Smarcel  if (add == NULL)
1376130809Smarcel    return;
1377130809Smarcel
1378130809Smarcel  /* If one node is for a normal insn and the second is for the base
1379130809Smarcel     insn with clobbers stripped off, the second node should be ignored.  */
1380130809Smarcel
1381130809Smarcel  if (old->u.insn.num_clobbers_to_add == 0
1382130809Smarcel      && add->u.insn.num_clobbers_to_add > 0)
1383130809Smarcel    {
1384130809Smarcel      /* Nothing to do here.  */
1385130809Smarcel    }
1386130809Smarcel  else if (old->u.insn.num_clobbers_to_add > 0
1387130809Smarcel	   && add->u.insn.num_clobbers_to_add == 0)
1388130809Smarcel    {
1389130809Smarcel      /* In this case, replace OLD with ADD.  */
1390130809Smarcel      old->u.insn = add->u.insn;
1391130809Smarcel    }
1392130809Smarcel  else
1393130809Smarcel    {
1394130809Smarcel      message_with_line (add->u.insn.lineno, "`%s' matches `%s'",
1395130809Smarcel			 get_insn_name (add->u.insn.code_number),
1396130809Smarcel			 get_insn_name (old->u.insn.code_number));
1397130809Smarcel      message_with_line (old->u.insn.lineno, "previous definition of `%s'",
1398130809Smarcel			 get_insn_name (old->u.insn.code_number));
1399130809Smarcel      error_count++;
1400130809Smarcel    }
1401130809Smarcel}
1402130809Smarcel
1403130809Smarcel/* Merge two decision trees OLDH and ADDH, modifying OLDH destructively.  */
1404130809Smarcel
1405130809Smarcelstatic void
1406130809Smarcelmerge_trees (oldh, addh)
1407130809Smarcel     struct decision_head *oldh, *addh;
1408130809Smarcel{
1409130809Smarcel  struct decision *next, *add;
1410130809Smarcel
1411130809Smarcel  if (addh->first == 0)
1412130809Smarcel    return;
1413130809Smarcel  if (oldh->first == 0)
1414130809Smarcel    {
1415130809Smarcel      *oldh = *addh;
1416130809Smarcel      return;
1417130809Smarcel    }
1418130809Smarcel
1419130809Smarcel  /* Trying to merge bits at different positions isn't possible.  */
1420130809Smarcel  if (strcmp (oldh->first->position, addh->first->position))
1421130809Smarcel    abort ();
1422130809Smarcel
1423130809Smarcel  for (add = addh->first; add ; add = next)
1424130809Smarcel    {
1425130809Smarcel      struct decision *old, *insert_before = NULL;
1426130809Smarcel
1427130809Smarcel      next = add->next;
1428130809Smarcel
1429130809Smarcel      /* The semantics of pattern matching state that the tests are
1430130809Smarcel	 done in the order given in the MD file so that if an insn
1431130809Smarcel	 matches two patterns, the first one will be used.  However,
1432130809Smarcel	 in practice, most, if not all, patterns are unambiguous so
1433130809Smarcel	 that their order is independent.  In that case, we can merge
1434130809Smarcel	 identical tests and group all similar modes and codes together.
1435130809Smarcel
1436130809Smarcel	 Scan starting from the end of OLDH until we reach a point
1437130809Smarcel	 where we reach the head of the list or where we pass a
1438130809Smarcel	 pattern that could also be true if NEW is true.  If we find
1439130809Smarcel	 an identical pattern, we can merge them.  Also, record the
1440130809Smarcel	 last node that tests the same code and mode and the last one
1441130809Smarcel	 that tests just the same mode.
1442130809Smarcel
1443130809Smarcel	 If we have no match, place NEW after the closest match we found.  */
1444130809Smarcel
1445130809Smarcel      for (old = oldh->last; old; old = old->prev)
1446130809Smarcel	{
1447130809Smarcel	  if (nodes_identical (old, add))
1448130809Smarcel	    {
1449130809Smarcel	      merge_accept_insn (old, add);
1450130809Smarcel	      merge_trees (&old->success, &add->success);
1451130809Smarcel	      goto merged_nodes;
1452130809Smarcel	    }
1453130809Smarcel
1454130809Smarcel	  if (maybe_both_true (old, add, 0))
1455130809Smarcel	    break;
1456130809Smarcel
1457130809Smarcel	  /* Insert the nodes in DT test type order, which is roughly
1458130809Smarcel	     how expensive/important the test is.  Given that the tests
1459130809Smarcel	     are also ordered within the list, examining the first is
1460130809Smarcel	     sufficient.  */
1461130809Smarcel	  if ((int) add->tests->type < (int) old->tests->type)
1462130809Smarcel	    insert_before = old;
1463130809Smarcel	}
1464130809Smarcel
1465130809Smarcel      if (insert_before == NULL)
1466130809Smarcel	{
1467130809Smarcel	  add->next = NULL;
1468130809Smarcel	  add->prev = oldh->last;
1469130809Smarcel	  oldh->last->next = add;
1470130809Smarcel	  oldh->last = add;
1471130809Smarcel	}
1472130809Smarcel      else
1473130809Smarcel	{
1474130809Smarcel	  if ((add->prev = insert_before->prev) != NULL)
1475130809Smarcel	    add->prev->next = add;
1476130809Smarcel	  else
1477130809Smarcel	    oldh->first = add;
1478130809Smarcel	  add->next = insert_before;
1479130809Smarcel	  insert_before->prev = add;
1480130809Smarcel	}
1481130809Smarcel
1482130809Smarcel    merged_nodes:;
1483130809Smarcel    }
1484130809Smarcel}
1485130809Smarcel
1486130809Smarcel/* Walk the tree looking for sub-nodes that perform common tests.
1487130809Smarcel   Factor out the common test into a new node.  This enables us
1488130809Smarcel   (depending on the test type) to emit switch statements later.  */
1489130809Smarcel
1490130809Smarcelstatic void
1491130809Smarcelfactor_tests (head)
1492130809Smarcel     struct decision_head *head;
1493130809Smarcel{
149419370Spst  struct decision *first, *next;
149519370Spst
149619370Spst  for (first = head->first; first && first->next; first = next)
149719370Spst    {
149819370Spst      enum decision_type type;
149919370Spst      struct decision *new, *old_last;
150019370Spst
150119370Spst      type = first->tests->type;
150219370Spst      next = first->next;
150319370Spst
150419370Spst      /* Want at least two compatible sequential nodes.  */
150519370Spst      if (next->tests->type != type)
150619370Spst	continue;
150719370Spst
150819370Spst      /* Don't want all node types, just those we can turn into
150919370Spst	 switch statements.  */
151098948Sobrien      if (type != DT_mode
151119370Spst	  && type != DT_code
1512130809Smarcel	  && type != DT_veclen
1513130809Smarcel	  && type != DT_elt_zero_int
1514130809Smarcel	  && type != DT_elt_one_int
1515130809Smarcel	  && type != DT_elt_zero_wide_safe)
1516130809Smarcel	continue;
1517130809Smarcel
1518130809Smarcel      /* If we'd been performing more than one test, create a new node
1519130809Smarcel         below our first test.  */
1520130809Smarcel      if (first->tests->next != NULL)
1521130809Smarcel	{
1522130809Smarcel	  new = new_decision (first->position, &first->success);
1523130809Smarcel	  new->tests = first->tests->next;
1524130809Smarcel	  first->tests->next = NULL;
1525130809Smarcel	}
1526130809Smarcel
1527130809Smarcel      /* Crop the node tree off after our first test.  */
1528130809Smarcel      first->next = NULL;
152998948Sobrien      old_last = head->last;
1530130809Smarcel      head->last = first;
1531130809Smarcel
1532130809Smarcel      /* For each compatible test, adjust to perform only one test in
1533130809Smarcel	 the top level node, then merge the node back into the tree.  */
1534130809Smarcel      do
1535130809Smarcel	{
1536130809Smarcel	  struct decision_head h;
1537130809Smarcel
1538130809Smarcel	  if (next->tests->next != NULL)
1539130809Smarcel	    {
1540130809Smarcel	      new = new_decision (next->position, &next->success);
1541130809Smarcel	      new->tests = next->tests->next;
1542130809Smarcel	      next->tests->next = NULL;
1543130809Smarcel	    }
1544130809Smarcel	  new = next;
1545130809Smarcel	  next = next->next;
1546130809Smarcel	  new->next = NULL;
1547130809Smarcel	  h.first = h.last = new;
1548130809Smarcel
1549130809Smarcel	  merge_trees (head, &h);
1550130809Smarcel	}
1551130809Smarcel      while (next && next->tests->type == type);
1552130809Smarcel
1553130809Smarcel      /* After we run out of compatible tests, graft the remaining nodes
1554130809Smarcel	 back onto the tree.  */
1555130809Smarcel      if (next)
1556130809Smarcel	{
1557130809Smarcel	  next->prev = head->last;
1558130809Smarcel	  head->last->next = next;
1559130809Smarcel	  head->last = old_last;
1560130809Smarcel	}
1561130809Smarcel    }
1562130809Smarcel
1563130809Smarcel  /* Recurse.  */
1564130809Smarcel  for (first = head->first; first; first = first->next)
1565130809Smarcel    factor_tests (&first->success);
1566130809Smarcel}
1567130809Smarcel
1568130809Smarcel/* After factoring, try to simplify the tests on any one node.
1569130809Smarcel   Tests that are useful for switch statements are recognizable
1570130809Smarcel   by having only a single test on a node -- we'll be manipulating
1571130809Smarcel   nodes with multiple tests:
1572130809Smarcel
1573130809Smarcel   If we have mode tests or code tests that are redundant with
1574130809Smarcel   predicates, remove them.  */
1575130809Smarcel
1576130809Smarcelstatic void
1577130809Smarcelsimplify_tests (head)
1578130809Smarcel     struct decision_head *head;
1579130809Smarcel{
1580130809Smarcel  struct decision *tree;
1581130809Smarcel
1582130809Smarcel  for (tree = head->first; tree; tree = tree->next)
1583130809Smarcel    {
1584130809Smarcel      struct decision_test *a, *b;
1585130809Smarcel
1586130809Smarcel      a = tree->tests;
1587130809Smarcel      b = a->next;
1588130809Smarcel      if (b == NULL)
1589130809Smarcel	continue;
1590130809Smarcel
1591130809Smarcel      /* Find a predicate node.  */
1592130809Smarcel      while (b && b->type != DT_pred)
1593130809Smarcel	b = b->next;
1594130809Smarcel      if (b)
1595130809Smarcel	{
159619370Spst	  /* Due to how these tests are constructed, we don't even need
159719370Spst	     to check that the mode and code are compatible -- they were
159819370Spst	     generated from the predicate in the first place.  */
159919370Spst	  while (a->type == DT_mode || a->type == DT_code)
160019370Spst	    a = a->next;
160119370Spst	  tree->tests = a;
160219370Spst	}
160319370Spst    }
160498948Sobrien
160598948Sobrien  /* Recurse.  */
160698948Sobrien  for (tree = head->first; tree; tree = tree->next)
160798948Sobrien    simplify_tests (&tree->success);
160819370Spst}
160919370Spst
161019370Spst/* Count the number of subnodes of HEAD.  If the number is high enough,
161119370Spst   make the first node in HEAD start a separate subroutine in the C code
161298948Sobrien   that is generated.  */
161398948Sobrien
161498948Sobrienstatic int
161598948Sobrienbreak_out_subroutines (head, initial)
161698948Sobrien     struct decision_head *head;
161798948Sobrien     int initial;
161898948Sobrien{
161998948Sobrien  int size = 0;
162098948Sobrien  struct decision *sub;
162198948Sobrien
162298948Sobrien  for (sub = head->first; sub; sub = sub->next)
162398948Sobrien    size += 1 + break_out_subroutines (&sub->success, 0);
162498948Sobrien
162598948Sobrien  if (size > SUBROUTINE_THRESHOLD && ! initial)
162698948Sobrien    {
162798948Sobrien      head->first->subroutine_number = ++next_subroutine_number;
162898948Sobrien      size = 1;
162998948Sobrien    }
163098948Sobrien  return size;
163198948Sobrien}
163298948Sobrien
163398948Sobrien/* For each node p, find the next alternative that might be true
163498948Sobrien   when p is true.  */
163598948Sobrien
163698948Sobrienstatic void
163798948Sobrienfind_afterward (head, real_afterward)
163898948Sobrien     struct decision_head *head;
163998948Sobrien     struct decision *real_afterward;
164098948Sobrien{
164198948Sobrien  struct decision *p, *q, *afterward;
164298948Sobrien
164398948Sobrien  /* We can't propagate alternatives across subroutine boundaries.
164498948Sobrien     This is not incorrect, merely a minor optimization loss.  */
164598948Sobrien
164698948Sobrien  p = head->first;
164798948Sobrien  afterward = (p->subroutine_number > 0 ? NULL : real_afterward);
164898948Sobrien
164998948Sobrien  for ( ; p ; p = p->next)
165019370Spst    {
165146283Sdfr      /* Find the next node that might be true if this one fails.  */
165298948Sobrien      for (q = p->next; q ; q = q->next)
165398948Sobrien	if (maybe_both_true (p, q, 1))
165498948Sobrien	  break;
165598948Sobrien
165646283Sdfr      /* If we reached the end of the list without finding one,
165798948Sobrien	 use the incoming afterward position.  */
165898948Sobrien      if (!q)
165998948Sobrien	q = afterward;
166098948Sobrien      p->afterward = q;
166198948Sobrien      if (q)
166298948Sobrien	q->need_label = 1;
166346283Sdfr    }
166498948Sobrien
166598948Sobrien  /* Recurse.  */
166698948Sobrien  for (p = head->first; p ; p = p->next)
166798948Sobrien    if (p->success.first)
166898948Sobrien      find_afterward (&p->success, p->afterward);
166998948Sobrien
167046283Sdfr  /* When we are generating a subroutine, record the real afterward
167198948Sobrien     position in the first node where write_tree can find it, and we
1672130809Smarcel     can do the right thing at the subroutine call site.  */
1673130809Smarcel  p = head->first;
167446283Sdfr  if (p->subroutine_number > 0)
167598948Sobrien    p->afterward = real_afterward;
167698948Sobrien}
167798948Sobrien
167846283Sdfr/* Assuming that the state of argument is denoted by OLDPOS, take whatever
167919370Spst   actions are necessary to move to NEWPOS.  If we fail to move to the
168098948Sobrien   new state, branch to node AFTERWARD if non-zero, otherwise return.
168119370Spst
168219370Spst   Failure to move to the new state can only occur if we are trying to
1683130809Smarcel   match multiple insns and we try to step past the end of the stream.  */
168498948Sobrien
168519370Spststatic void
1686130809Smarcelchange_state (oldpos, newpos, afterward, indent)
168719370Spst     const char *oldpos;
168819370Spst     const char *newpos;
168919370Spst     struct decision *afterward;
169019370Spst     const char *indent;
169119370Spst{
169219370Spst  int odepth = strlen (oldpos);
169319370Spst  int ndepth = strlen (newpos);
169419370Spst  int depth;
169519370Spst  int old_has_insn, new_has_insn;
169619370Spst
169719370Spst  /* Pop up as many levels as necessary.  */
169819370Spst  for (depth = odepth; strncmp (oldpos, newpos, depth) != 0; --depth)
169919370Spst    continue;
170019370Spst
170119370Spst  /* Hunt for the last [A-Z] in both strings.  */
170219370Spst  for (old_has_insn = odepth - 1; old_has_insn >= 0; --old_has_insn)
170319370Spst    if (ISUPPER (oldpos[old_has_insn]))
170419370Spst      break;
170519370Spst  for (new_has_insn = ndepth - 1; new_has_insn >= 0; --new_has_insn)
170619370Spst    if (ISUPPER (newpos[new_has_insn]))
170719370Spst      break;
170819370Spst
170919370Spst  /* Go down to desired level.  */
171019370Spst  while (depth < ndepth)
171119370Spst    {
171219370Spst      /* It's a different insn from the first one.  */
171398948Sobrien      if (ISUPPER (newpos[depth]))
171419370Spst	{
1715130809Smarcel	  /* We can only fail if we're moving down the tree.  */
1716130809Smarcel	  if (old_has_insn >= 0 && oldpos[old_has_insn] >= newpos[depth])
171746283Sdfr	    {
171898948Sobrien	      printf ("%stem = peep2_next_insn (%d);\n",
171919370Spst		      indent, newpos[depth] - 'A');
172046283Sdfr	    }
172198948Sobrien	  else
172246283Sdfr	    {
172346283Sdfr	      printf ("%stem = peep2_next_insn (%d);\n",
1724130809Smarcel		      indent, newpos[depth] - 'A');
1725130809Smarcel	      printf ("%sif (tem == NULL_RTX)\n", indent);
172646283Sdfr	      if (afterward)
1727130809Smarcel		printf ("%s  goto L%d;\n", indent, afterward->number);
1728130809Smarcel	      else
1729130809Smarcel		printf ("%s  goto ret0;\n", indent);
1730130809Smarcel	    }
173198948Sobrien	  printf ("%sx%d = PATTERN (tem);\n", indent, depth + 1);
1732130809Smarcel	}
1733130809Smarcel      else if (ISLOWER (newpos[depth]))
173446283Sdfr	printf ("%sx%d = XVECEXP (x%d, 0, %d);\n",
1735130809Smarcel		indent, depth + 1, depth, newpos[depth] - 'a');
1736130809Smarcel      else
1737130809Smarcel	printf ("%sx%d = XEXP (x%d, %c);\n",
1738130809Smarcel		indent, depth + 1, depth, newpos[depth]);
173946283Sdfr      ++depth;
1740130809Smarcel    }
1741130809Smarcel}
1742130809Smarcel
1743130809Smarcel/* Print the enumerator constant for CODE -- the upcase version of
1744130809Smarcel   the name.  */
1745130809Smarcel
1746130809Smarcelstatic void
1747130809Smarcelprint_code (code)
174846283Sdfr     enum rtx_code code;
1749130809Smarcel{
175046283Sdfr  const char *p;
175146283Sdfr  for (p = GET_RTX_NAME (code); *p; p++)
175246283Sdfr    putchar (TOUPPER (*p));
1753130809Smarcel}
175446283Sdfr
175598948Sobrien/* Emit code to cross an afterward link -- change state and branch.  */
175698948Sobrien
1757130809Smarcelstatic void
1758130809Smarcelwrite_afterward (start, afterward, indent)
1759130809Smarcel     struct decision *start;
1760130809Smarcel     struct decision *afterward;
176198948Sobrien     const char *indent;
176246283Sdfr{
176346283Sdfr  if (!afterward || start->subroutine_number > 0)
1764130809Smarcel    printf("%sgoto ret0;\n", indent);
1765130809Smarcel  else
176646283Sdfr    {
1767130809Smarcel      change_state (start->position, afterward->position, NULL, indent);
1768130809Smarcel      printf ("%sgoto L%d;\n", indent, afterward->number);
1769130809Smarcel    }
1770130809Smarcel}
1771130809Smarcel
1772130809Smarcel/* Emit a switch statement, if possible, for an initial sequence of
1773130809Smarcel   nodes at START.  Return the first node yet untested.  */
1774130809Smarcel
1775130809Smarcelstatic struct decision *
1776130809Smarcelwrite_switch (start, depth)
1777130809Smarcel     struct decision *start;
1778130809Smarcel     int depth;
1779130809Smarcel{
1780130809Smarcel  struct decision *p = start;
1781130809Smarcel  enum decision_type type = p->tests->type;
1782130809Smarcel  struct decision *needs_label = NULL;
1783130809Smarcel
1784130809Smarcel  /* If we have two or more nodes in sequence that test the same one
1785130809Smarcel     thing, we may be able to use a switch statement.  */
178698948Sobrien
178746283Sdfr  if (!p->next
178846283Sdfr      || p->tests->next
178998948Sobrien      || p->next->tests->type != type
179046283Sdfr      || p->next->tests->next
179119370Spst      || nodes_identical_1 (p->tests, p->next->tests))
179219370Spst    return p;
179319370Spst
179419370Spst  /* DT_code is special in that we can do interesting things with
179519370Spst     known predicates at the same time.  */
179619370Spst  if (type == DT_code)
179719370Spst    {
1798130809Smarcel      char codemap[NUM_RTX_CODE];
179919370Spst      struct decision *ret;
180019370Spst      RTX_CODE code;
180198948Sobrien
180298948Sobrien      memset (codemap, 0, sizeof(codemap));
180346283Sdfr
1804130809Smarcel      printf ("  switch (GET_CODE (x%d))\n    {\n", depth);
180546283Sdfr      code = p->tests->u.code;
180646283Sdfr      do
180746283Sdfr	{
1808130809Smarcel	  if (p != start && p->need_label && needs_label == NULL)
1809130809Smarcel	    needs_label = p;
1810130809Smarcel
1811130809Smarcel	  printf ("    case ");
1812130809Smarcel	  print_code (code);
1813130809Smarcel	  printf (":\n      goto L%d;\n", p->success.first->number);
181419370Spst	  p->success.first->need_label = 1;
181519370Spst
181619370Spst	  codemap[code] = 1;
181719370Spst	  p = p->next;
181898948Sobrien	}
181919370Spst      while (p
182019370Spst	     && ! p->tests->next
182119370Spst	     && p->tests->type == DT_code
182219370Spst	     && ! codemap[code = p->tests->u.code]);
182319370Spst
182419370Spst      /* If P is testing a predicate that we know about and we haven't
182519370Spst	 seen any of the codes that are valid for the predicate, we can
182619370Spst	 write a series of "case" statement, one for each possible code.
182719370Spst	 Since we are already in a switch, these redundant tests are very
182819370Spst	 cheap and will reduce the number of predicates called.  */
182919370Spst
183019370Spst      /* Note that while we write out cases for these predicates here,
183119370Spst	 we don't actually write the test here, as it gets kinda messy.
183219370Spst	 It is trivial to leave this to later by telling our caller that
183319370Spst	 we only processed the CODE tests.  */
183419370Spst      if (needs_label != NULL)
183519370Spst	ret = needs_label;
183619370Spst      else
183719370Spst	ret = p;
183819370Spst
183919370Spst      while (p && p->tests->type == DT_pred
184019370Spst	     && p->tests->u.pred.index >= 0)
184119370Spst	{
184219370Spst	  const RTX_CODE *c;
184319370Spst
184419370Spst	  for (c = &preds[p->tests->u.pred.index].codes[0]; *c ; ++c)
184519370Spst	    if (codemap[(int) *c] != 0)
184619370Spst	      goto pred_done;
1847130809Smarcel
184819370Spst	  for (c = &preds[p->tests->u.pred.index].codes[0]; *c ; ++c)
184919370Spst	    {
185019370Spst	      printf ("    case ");
185119370Spst	      print_code (*c);
185219370Spst	      printf (":\n");
185319370Spst	      codemap[(int) *c] = 1;
185419370Spst	    }
185519370Spst
185619370Spst	  printf ("      goto L%d;\n", p->number);
185719370Spst	  p->need_label = 1;
185898948Sobrien	  p = p->next;
185998948Sobrien	}
186098948Sobrien
186198948Sobrien    pred_done:
186298948Sobrien      /* Make the default case skip the predicates we managed to match.  */
186398948Sobrien
186498948Sobrien      printf ("    default:\n");
186519370Spst      if (p != ret)
186619370Spst	{
186719370Spst	  if (p)
186819370Spst	    {
186919370Spst	      printf ("      goto L%d;\n", p->number);
187019370Spst	      p->need_label = 1;
187119370Spst	    }
187219370Spst	  else
187319370Spst	    write_afterward (start, start->afterward, "      ");
187419370Spst	}
187519370Spst      else
187619370Spst	printf ("     break;\n");
187719370Spst      printf ("   }\n");
187898948Sobrien
187919370Spst      return ret;
188019370Spst    }
188119370Spst  else if (type == DT_mode
188219370Spst	   || type == DT_veclen
188319370Spst	   || type == DT_elt_zero_int
188419370Spst	   || type == DT_elt_one_int
188519370Spst	   || type == DT_elt_zero_wide_safe)
188619370Spst    {
188719370Spst      const char *indent = "";
188819370Spst
188919370Spst      /* We cast switch parameter to integer, so we must ensure that the value
189019370Spst	 fits.  */
189119370Spst      if (type == DT_elt_zero_wide_safe)
189219370Spst	{
189319370Spst	  indent = "  ";
189419370Spst	  printf("  if ((int) XWINT (x%d, 0) == XWINT (x%d, 0))\n", depth, depth);
189519370Spst	}
189619370Spst      printf ("%s  switch (", indent);
189719370Spst      switch (type)
189819370Spst	{
189919370Spst	case DT_mode:
190019370Spst	  printf ("GET_MODE (x%d)", depth);
190119370Spst	  break;
190219370Spst	case DT_veclen:
190319370Spst	  printf ("XVECLEN (x%d, 0)", depth);
190419370Spst	  break;
190519370Spst	case DT_elt_zero_int:
190698948Sobrien	  printf ("XINT (x%d, 0)", depth);
190719370Spst	  break;
190819370Spst	case DT_elt_one_int:
190919370Spst	  printf ("XINT (x%d, 1)", depth);
191098948Sobrien	  break;
191119370Spst	case DT_elt_zero_wide_safe:
191219370Spst	  /* Convert result of XWINT to int for portability since some C
191319370Spst	     compilers won't do it and some will.  */
191419370Spst	  printf ("(int) XWINT (x%d, 0)", depth);
191519370Spst	  break;
191619370Spst	default:
191719370Spst	  abort ();
191819370Spst	}
191998948Sobrien      printf (")\n%s    {\n", indent);
192019370Spst
192119370Spst      do
192219370Spst	{
192319370Spst	  /* Merge trees will not unify identical nodes if their
192419370Spst	     sub-nodes are at different levels.  Thus we must check
192519370Spst	     for duplicate cases.  */
192619370Spst	  struct decision *q;
192719370Spst	  for (q = start; q != p; q = q->next)
192819370Spst	    if (nodes_identical_1 (p->tests, q->tests))
192919370Spst	      goto case_done;
193019370Spst
193119370Spst	  if (p != start && p->need_label && needs_label == NULL)
193219370Spst	    needs_label = p;
193319370Spst
193419370Spst	  printf ("%s    case ", indent);
193519370Spst	  switch (type)
193619370Spst	    {
193719370Spst	    case DT_mode:
193819370Spst	      printf ("%smode", GET_MODE_NAME (p->tests->u.mode));
193919370Spst	      break;
1940130809Smarcel	    case DT_veclen:
1941130809Smarcel	      printf ("%d", p->tests->u.veclen);
1942130809Smarcel	      break;
1943130809Smarcel	    case DT_elt_zero_int:
1944130809Smarcel	    case DT_elt_one_int:
1945130809Smarcel	    case DT_elt_zero_wide:
1946130809Smarcel	    case DT_elt_zero_wide_safe:
1947130809Smarcel	      printf (HOST_WIDE_INT_PRINT_DEC, p->tests->u.intval);
1948130809Smarcel	      break;
1949130809Smarcel	    default:
1950130809Smarcel	      abort ();
1951130809Smarcel	    }
1952130809Smarcel	  printf (":\n%s      goto L%d;\n", indent, p->success.first->number);
1953130809Smarcel	  p->success.first->need_label = 1;
1954130809Smarcel
1955130809Smarcel	  p = p->next;
1956130809Smarcel	}
1957130809Smarcel      while (p && p->tests->type == type && !p->tests->next);
1958130809Smarcel
1959130809Smarcel    case_done:
1960130809Smarcel      printf ("%s    default:\n%s      break;\n%s    }\n",
1961130809Smarcel	      indent, indent, indent);
1962130809Smarcel
1963130809Smarcel      return needs_label != NULL ? needs_label : p;
1964130809Smarcel    }
1965130809Smarcel  else
1966130809Smarcel    {
1967130809Smarcel      /* None of the other tests are ameanable.  */
1968130809Smarcel      return p;
1969130809Smarcel    }
1970130809Smarcel}
1971130809Smarcel
1972130809Smarcel/* Emit code for one test.  */
1973130809Smarcel
1974130809Smarcelstatic void
1975130809Smarcelwrite_cond (p, depth, subroutine_type)
1976130809Smarcel     struct decision_test *p;
1977130809Smarcel     int depth;
1978130809Smarcel     enum routine_type subroutine_type;
1979130809Smarcel{
1980130809Smarcel  switch (p->type)
1981130809Smarcel    {
1982130809Smarcel    case DT_mode:
1983130809Smarcel      printf ("GET_MODE (x%d) == %smode", depth, GET_MODE_NAME (p->u.mode));
1984130809Smarcel      break;
198519370Spst
198619370Spst    case DT_code:
198719370Spst      printf ("GET_CODE (x%d) == ", depth);
198819370Spst      print_code (p->u.code);
198919370Spst      break;
199019370Spst
199198948Sobrien    case DT_veclen:
199219370Spst      printf ("XVECLEN (x%d, 0) == %d", depth, p->u.veclen);
199319370Spst      break;
199419370Spst
199519370Spst    case DT_elt_zero_int:
199619370Spst      printf ("XINT (x%d, 0) == %d", depth, (int) p->u.intval);
199719370Spst      break;
199819370Spst
199919370Spst    case DT_elt_one_int:
200019370Spst      printf ("XINT (x%d, 1) == %d", depth, (int) p->u.intval);
200119370Spst      break;
200219370Spst
200319370Spst    case DT_elt_zero_wide:
200419370Spst    case DT_elt_zero_wide_safe:
200519370Spst      printf ("XWINT (x%d, 0) == ", depth);
200619370Spst      printf (HOST_WIDE_INT_PRINT_DEC, p->u.intval);
200719370Spst      break;
200819370Spst
200919370Spst    case DT_veclen_ge:
201019370Spst      printf ("XVECLEN (x%d, 0) >= %d", depth, p->u.veclen);
201119370Spst      break;
201219370Spst
201319370Spst    case DT_dup:
201498948Sobrien      printf ("rtx_equal_p (x%d, operands[%d])", depth, p->u.dup);
201598948Sobrien      break;
201619370Spst
201719370Spst    case DT_pred:
201819370Spst      printf ("%s (x%d, %smode)", p->u.pred.name, depth,
201919370Spst	      GET_MODE_NAME (p->u.pred.mode));
202019370Spst      break;
202119370Spst
202219370Spst    case DT_c_test:
202398948Sobrien      printf ("(%s)", p->u.c_test);
202498948Sobrien      break;
202519370Spst
202619370Spst    case DT_accept_insn:
202719370Spst      switch (subroutine_type)
202819370Spst	{
202919370Spst	case RECOG:
203019370Spst	  if (p->u.insn.num_clobbers_to_add == 0)
203119370Spst	    abort ();
203219370Spst	  printf ("pnum_clobbers != NULL");
203398948Sobrien	  break;
203419370Spst
203519370Spst	default:
203619370Spst	  abort ();
203719370Spst	}
2038130809Smarcel      break;
203919370Spst
204019370Spst    default:
204119370Spst      abort ();
204219370Spst    }
204319370Spst}
204419370Spst
204519370Spst/* Emit code for one action.  The previous tests have succeeded;
204619370Spst   TEST is the last of the chain.  In the normal case we simply
204719370Spst   perform a state change.  For the `accept' tests we must do more work.  */
204819370Spst
204919370Spststatic void
205019370Spstwrite_action (p, test, depth, uncond, success, subroutine_type)
205119370Spst     struct decision *p;
205298948Sobrien     struct decision_test *test;
205319370Spst     int depth, uncond;
205419370Spst     struct decision *success;
205519370Spst     enum routine_type subroutine_type;
205619370Spst{
205719370Spst  const char *indent;
205819370Spst  int want_close = 0;
205919370Spst
206019370Spst  if (uncond)
206198948Sobrien    indent = "  ";
206219370Spst  else if (test->type == DT_accept_op || test->type == DT_accept_insn)
206319370Spst    {
206419370Spst      fputs ("    {\n", stdout);
206598948Sobrien      indent = "      ";
206619370Spst      want_close = 1;
206719370Spst    }
206819370Spst  else
206919370Spst    indent = "    ";
207019370Spst
207119370Spst  if (test->type == DT_accept_op)
207219370Spst    {
207398948Sobrien      printf("%soperands[%d] = x%d;\n", indent, test->u.opno, depth);
207498948Sobrien
207519370Spst      /* Only allow DT_accept_insn to follow.  */
207619370Spst      if (test->next)
207719370Spst	{
207819370Spst	  test = test->next;
207919370Spst	  if (test->type != DT_accept_insn)
208019370Spst	    abort ();
208119370Spst	}
208219370Spst    }
208319370Spst
208419370Spst  /* Sanity check that we're now at the end of the list of tests.  */
208519370Spst  if (test->next)
2086130809Smarcel    abort ();
208798948Sobrien
208819370Spst  if (test->type == DT_accept_insn)
208919370Spst    {
209019370Spst      switch (subroutine_type)
209119370Spst	{
209219370Spst	case RECOG:
209319370Spst	  if (test->u.insn.num_clobbers_to_add != 0)
209419370Spst	    printf ("%s*pnum_clobbers = %d;\n",
209598948Sobrien		    indent, test->u.insn.num_clobbers_to_add);
209619370Spst	  printf ("%sreturn %d;\n", indent, test->u.insn.code_number);
209719370Spst	  break;
209898948Sobrien
209998948Sobrien	case SPLIT:
210019370Spst	  printf ("%sreturn gen_split_%d (operands);\n",
210119370Spst		  indent, test->u.insn.code_number);
210219370Spst	  break;
210319370Spst
210419370Spst	case PEEPHOLE2:
210519370Spst	  {
210698948Sobrien	    int match_len = 0, i;
210719370Spst
210819370Spst	    for (i = strlen (p->position) - 1; i >= 0; --i)
210919370Spst	      if (ISUPPER (p->position[i]))
211019370Spst		{
211119370Spst		  match_len = p->position[i] - 'A';
211219370Spst		  break;
211319370Spst		}
211419370Spst	    printf ("%s*_pmatch_len = %d;\n", indent, match_len);
211598948Sobrien	    printf ("%stem = gen_peephole2_%d (insn, operands);\n",
211619370Spst		    indent, test->u.insn.code_number);
211719370Spst	    printf ("%sif (tem != 0)\n%s  return tem;\n", indent, indent);
211819370Spst	  }
211919370Spst	  break;
212019370Spst
212198948Sobrien	default:
212219370Spst	  abort ();
212398948Sobrien	}
212498948Sobrien    }
212519370Spst  else
212619370Spst    {
212719370Spst      printf("%sgoto L%d;\n", indent, success->number);
212898948Sobrien      success->need_label = 1;
212998948Sobrien    }
213098948Sobrien
213119370Spst  if (want_close)
213298948Sobrien    fputs ("    }\n", stdout);
213319370Spst}
213498948Sobrien
213598948Sobrien/* Return 1 if the test is always true and has no fallthru path.  Return -1
213619370Spst   if the test does have a fallthru path, but requires that the condition be
213798948Sobrien   terminated.  Otherwise return 0 for a normal test.  */
213898948Sobrien/* ??? is_unconditional is a stupid name for a tri-state function.  */
213998948Sobrien
214098948Sobrienstatic int
214198948Sobrienis_unconditional (t, subroutine_type)
214219370Spst     struct decision_test *t;
214319370Spst     enum routine_type subroutine_type;
214419370Spst{
214546283Sdfr  if (t->type == DT_accept_op)
214698948Sobrien    return 1;
214746283Sdfr
214846283Sdfr  if (t->type == DT_accept_insn)
214919370Spst    {
215046283Sdfr      switch (subroutine_type)
215146283Sdfr	{
215246283Sdfr	case RECOG:
215346283Sdfr	  return (t->u.insn.num_clobbers_to_add == 0);
215446283Sdfr	case SPLIT:
215546283Sdfr	  return 1;
215646283Sdfr	case PEEPHOLE2:
215746283Sdfr	  return -1;
215846283Sdfr	default:
215946283Sdfr	  abort ();
216098948Sobrien	}
216146283Sdfr    }
216246283Sdfr
216346283Sdfr  return 0;
216446283Sdfr}
216546283Sdfr
216646283Sdfr/* Emit code for one node -- the conditional and the accompanying action.
216746283Sdfr   Return true if there is no fallthru path.  */
216846283Sdfr
216946283Sdfrstatic int
217046283Sdfrwrite_node (p, depth, subroutine_type)
217146283Sdfr     struct decision *p;
217246283Sdfr     int depth;
217346283Sdfr     enum routine_type subroutine_type;
217446283Sdfr{
217598948Sobrien  struct decision_test *test, *last_test;
217646283Sdfr  int uncond;
217798948Sobrien
217898948Sobrien  last_test = test = p->tests;
217998948Sobrien  uncond = is_unconditional (test, subroutine_type);
218046283Sdfr  if (uncond == 0)
218146283Sdfr    {
218246283Sdfr      printf ("  if (");
218346283Sdfr      write_cond (test, depth, subroutine_type);
218446283Sdfr
218546283Sdfr      while ((test = test->next) != NULL)
218698948Sobrien	{
218746283Sdfr	  int uncond2;
218846283Sdfr
218946283Sdfr	  last_test = test;
219046283Sdfr	  uncond2 = is_unconditional (test, subroutine_type);
219146283Sdfr	  if (uncond2 != 0)
219246283Sdfr	    break;
219346283Sdfr
219446283Sdfr	  printf ("\n      && ");
219546283Sdfr	  write_cond (test, depth, subroutine_type);
219698948Sobrien	}
219746283Sdfr
219846283Sdfr      printf (")\n");
219998948Sobrien    }
220046283Sdfr
220146283Sdfr  write_action (p, last_test, depth, uncond, p->success.first, subroutine_type);
220298948Sobrien
220346283Sdfr  return uncond > 0;
220446283Sdfr}
220598948Sobrien
220698948Sobrien/* Emit code for all of the sibling nodes of HEAD.  */
220798948Sobrien
220898948Sobrienstatic void
220998948Sobrienwrite_tree_1 (head, depth, subroutine_type)
221098948Sobrien     struct decision_head *head;
221198948Sobrien     int depth;
221298948Sobrien     enum routine_type subroutine_type;
221398948Sobrien{
221498948Sobrien  struct decision *p, *next;
221598948Sobrien  int uncond = 0;
221698948Sobrien
221798948Sobrien  for (p = head->first; p ; p = next)
221898948Sobrien    {
221998948Sobrien      /* The label for the first element was printed in write_tree.  */
222098948Sobrien      if (p != head->first && p->need_label)
222198948Sobrien	OUTPUT_LABEL (" ", p->number);
222298948Sobrien
222398948Sobrien      /* Attempt to write a switch statement for a whole sequence.  */
222498948Sobrien      next = write_switch (p, depth);
222598948Sobrien      if (p != next)
222698948Sobrien	uncond = 0;
222798948Sobrien      else
222846283Sdfr	{
222946283Sdfr	  /* Failed -- fall back and write one node.  */
223046283Sdfr	  uncond = write_node (p, depth, subroutine_type);
223146283Sdfr	  next = p->next;
223246283Sdfr	}
223346283Sdfr    }
223446283Sdfr
223598948Sobrien  /* Finished with this chain.  Close a fallthru path by branching
223698948Sobrien     to the afterward node.  */
223746283Sdfr  if (! uncond)
223846283Sdfr    write_afterward (head->last, head->last->afterward, "  ");
223946283Sdfr}
224046283Sdfr
224119370Spst/* Write out the decision tree starting at HEAD.  PREVPOS is the
224219370Spst   position at the node that branched to this node.  */
224319370Spst
224419370Spststatic void
224519370Spstwrite_tree (head, prevpos, type, initial)
224619370Spst     struct decision_head *head;
224719370Spst     const char *prevpos;
224819370Spst     enum routine_type type;
224919370Spst     int initial;
225019370Spst{
225119370Spst  struct decision *p = head->first;
225219370Spst
225319370Spst  putchar ('\n');
225419370Spst  if (p->need_label)
225519370Spst    OUTPUT_LABEL (" ", p->number);
225698948Sobrien
225798948Sobrien  if (! initial && p->subroutine_number > 0)
225819370Spst    {
225919370Spst      static const char * const name_prefix[] = {
226019370Spst	  "recog", "split", "peephole2"
226119370Spst      };
226298948Sobrien
226398948Sobrien      static const char * const call_suffix[] = {
226419370Spst	  ", pnum_clobbers", "", ", _pmatch_len"
226519370Spst      };
226619370Spst
226719370Spst      /* This node has been broken out into a separate subroutine.
226819370Spst	 Call it, test the result, and branch accordingly.  */
226919370Spst
227098948Sobrien      if (p->afterward)
227119370Spst	{
227219370Spst	  printf ("  tem = %s_%d (x0, insn%s);\n",
227319370Spst		  name_prefix[type], p->subroutine_number, call_suffix[type]);
227419370Spst	  if (IS_SPLIT (type))
227519370Spst	    printf ("  if (tem != 0)\n    return tem;\n");
227698948Sobrien	  else
227719370Spst	    printf ("  if (tem >= 0)\n    return tem;\n");
227819370Spst
227919370Spst	  change_state (p->position, p->afterward->position, NULL, "  ");
228019370Spst	  printf ("  goto L%d;\n", p->afterward->number);
228198948Sobrien	}
228298948Sobrien      else
228319370Spst	{
228419370Spst	  printf ("  return %s_%d (x0, insn%s);\n",
228519370Spst		  name_prefix[type], p->subroutine_number, call_suffix[type]);
228619370Spst	}
228719370Spst    }
228898948Sobrien  else
228919370Spst    {
229019370Spst      int depth = strlen (p->position);
229119370Spst
229219370Spst      change_state (prevpos, p->position, head->last->afterward, "  ");
229319370Spst      write_tree_1 (head, depth, type);
229498948Sobrien
229519370Spst      for (p = head->first; p; p = p->next)
229619370Spst        if (p->success.first)
229719370Spst          write_tree (&p->success, p->position, type, 0);
229819370Spst    }
229919370Spst}
2300130809Smarcel
230119370Spst/* Write out a subroutine of type TYPE to do comparisons starting at
230219370Spst   node TREE.  */
230319370Spst
230419370Spststatic void
230519370Spstwrite_subroutine (head, type)
230619370Spst     struct decision_head *head;
230719370Spst     enum routine_type type;
230819370Spst{
2309130809Smarcel  int subfunction = head->first ? head->first->subroutine_number : 0;
231019370Spst  const char *s_or_e;
231119370Spst  char extension[32];
231219370Spst  int i;
231319370Spst
231419370Spst  s_or_e = subfunction ? "static " : "";
231519370Spst
231619370Spst  if (subfunction)
231719370Spst    sprintf (extension, "_%d", subfunction);
231819370Spst  else if (type == RECOG)
231919370Spst    extension[0] = '\0';
232019370Spst  else
2321130809Smarcel    strcpy (extension, "_insns");
2322130809Smarcel
232319370Spst  switch (type)
232419370Spst    {
232519370Spst    case RECOG:
232619370Spst      printf ("%sint recog%s PARAMS ((rtx, rtx, int *));\n", s_or_e, extension);
232719370Spst      printf ("%sint\n\
232819370Spstrecog%s (x0, insn, pnum_clobbers)\n\
232919370Spst     rtx x0 ATTRIBUTE_UNUSED;\n\
233019370Spst     rtx insn ATTRIBUTE_UNUSED;\n\
233119370Spst     int *pnum_clobbers ATTRIBUTE_UNUSED;\n", s_or_e, extension);
233219370Spst      break;
233319370Spst    case SPLIT:
2334130809Smarcel      printf ("%srtx split%s PARAMS ((rtx, rtx));\n", s_or_e, extension);
233519370Spst      printf ("%srtx\n\
233619370Spstsplit%s (x0, insn)\n\
233719370Spst     rtx x0 ATTRIBUTE_UNUSED;\n\
233819370Spst     rtx insn ATTRIBUTE_UNUSED;\n", s_or_e, extension);
233919370Spst      break;
234019370Spst    case PEEPHOLE2:
234119370Spst      printf ("%srtx peephole2%s PARAMS ((rtx, rtx, int *));\n",
234219370Spst	      s_or_e, extension);
234319370Spst      printf ("%srtx\n\
2344130809Smarcelpeephole2%s (x0, insn, _pmatch_len)\n\
234519370Spst     rtx x0 ATTRIBUTE_UNUSED;\n\
234619370Spst     rtx insn ATTRIBUTE_UNUSED;\n\
234719370Spst     int *_pmatch_len ATTRIBUTE_UNUSED;\n", s_or_e, extension);
234819370Spst      break;
234919370Spst    }
235019370Spst
235119370Spst  printf ("{\n  rtx * const operands ATTRIBUTE_UNUSED = &recog_data.operand[0];\n");
235219370Spst  for (i = 1; i <= max_depth; i++)
235319370Spst    printf ("  rtx x%d ATTRIBUTE_UNUSED;\n", i);
235419370Spst
235519370Spst  printf ("  %s tem ATTRIBUTE_UNUSED;\n", IS_SPLIT (type) ? "rtx" : "int");
2356130809Smarcel
235719370Spst  if (!subfunction)
235819370Spst    printf ("  recog_data.insn = NULL_RTX;\n");
235919370Spst
236019370Spst  if (head->first)
236119370Spst    write_tree (head, "", type, 1);
236219370Spst  else
236319370Spst    printf ("  goto ret0;\n");
236419370Spst
236519370Spst  printf (" ret0:\n  return %d;\n}\n\n", IS_SPLIT (type) ? 0 : -1);
236619370Spst}
236719370Spst
236819370Spst/* In break_out_subroutines, we discovered the boundaries for the
236919370Spst   subroutines, but did not write them out.  Do so now.  */
237019370Spst
237198948Sobrienstatic void
237219370Spstwrite_subroutines (head, type)
237319370Spst     struct decision_head *head;
237419370Spst     enum routine_type type;
237519370Spst{
237619370Spst  struct decision *p;
237798948Sobrien
237819370Spst  for (p = head->first; p ; p = p->next)
237919370Spst    if (p->success.first)
238019370Spst      write_subroutines (&p->success, type);
238119370Spst
238219370Spst  if (head->first->subroutine_number > 0)
238319370Spst    write_subroutine (head, type);
238419370Spst}
238598948Sobrien
238619370Spst/* Begin the output file.  */
238798948Sobrien
238898948Sobrienstatic void
238998948Sobrienwrite_header ()
239019370Spst{
239119370Spst  puts ("\
239219370Spst/* Generated automatically by the program `genrecog' from the target\n\
239319370Spst   machine description file.  */\n\
239498948Sobrien\n\
239598948Sobrien#include \"config.h\"\n\
239698948Sobrien#include \"system.h\"\n\
239719370Spst#include \"rtl.h\"\n\
239819370Spst#include \"tm_p.h\"\n\
239919370Spst#include \"function.h\"\n\
240019370Spst#include \"insn-config.h\"\n\
240119370Spst#include \"recog.h\"\n\
240219370Spst#include \"real.h\"\n\
240319370Spst#include \"output.h\"\n\
240419370Spst#include \"flags.h\"\n\
240519370Spst#include \"hard-reg-set.h\"\n\
240619370Spst#include \"resource.h\"\n\
240798948Sobrien#include \"toplev.h\"\n\
240819370Spst#include \"reload.h\"\n\
240919370Spst\n");
241019370Spst
241119370Spst  puts ("\n\
2412130809Smarcel/* `recog' contains a decision tree that recognizes whether the rtx\n\
241319370Spst   X0 is a valid instruction.\n\
241419370Spst\n\
241519370Spst   recog returns -1 if the rtx is not valid.  If the rtx is valid, recog\n\
241619370Spst   returns a nonnegative number which is the insn code number for the\n\
241719370Spst   pattern that matched.  This is the same as the order in the machine\n\
241819370Spst   description of the entry that matched.  This number can be used as an\n\
241919370Spst   index into `insn_data' and other tables.\n");
2420130809Smarcel  puts ("\
2421130809Smarcel   The third argument to recog is an optional pointer to an int.  If\n\
242219370Spst   present, recog will accept a pattern if it matches except for missing\n\
242319370Spst   CLOBBER expressions at the end.  In that case, the value pointed to by\n\
242419370Spst   the optional pointer will be set to the number of CLOBBERs that need\n\
242519370Spst   to be added (it should be initialized to zero by the caller).  If it");
242619370Spst  puts ("\
242719370Spst   is set nonzero, the caller should allocate a PARALLEL of the\n\
242819370Spst   appropriate size, copy the initial entries, and call add_clobbers\n\
242919370Spst   (found in insn-emit.c) to fill in the CLOBBERs.\n\
243019370Spst");
243119370Spst
243219370Spst  puts ("\n\
243319370Spst   The function split_insns returns 0 if the rtl could not\n\
2434130809Smarcel   be split or the split rtl in a SEQUENCE if it can be.\n\
243519370Spst\n\
243619370Spst   The function peephole2_insns returns 0 if the rtl could not\n\
243719370Spst   be matched. If there was a match, the new rtl is returned in a SEQUENCE,\n\
243898948Sobrien   and LAST_INSN will point to the last recognized insn in the old sequence.\n\
243919370Spst*/\n\n");
244019370Spst}
244119370Spst
244219370Spst
244319370Spst/* Construct and return a sequence of decisions
244419370Spst   that will recognize INSN.
244519370Spst
244619370Spst   TYPE says what type of routine we are recognizing (RECOG or SPLIT).  */
244798948Sobrien
244819370Spststatic struct decision_head
244919370Spstmake_insn_sequence (insn, type)
245019370Spst     rtx insn;
245119370Spst     enum routine_type type;
245219370Spst{
245319370Spst  rtx x;
245498948Sobrien  const char *c_test = XSTR (insn, type == RECOG ? 2 : 1);
245519370Spst  struct decision *last;
245619370Spst  struct decision_test *test, **place;
245719370Spst  struct decision_head head;
245819370Spst  char c_test_pos[2];
245919370Spst
246019370Spst  record_insn_name (next_insn_code, (type == RECOG ? XSTR (insn, 0) : NULL));
246119370Spst
246219370Spst  c_test_pos[0] = '\0';
246319370Spst  if (type == PEEPHOLE2)
246419370Spst    {
246519370Spst      int i, j;
246619370Spst
246719370Spst      /* peephole2 gets special treatment:
246819370Spst	 - X always gets an outer parallel even if it's only one entry
246919370Spst	 - we remove all traces of outer-level match_scratch and match_dup
247019370Spst           expressions here.  */
247119370Spst      x = rtx_alloc (PARALLEL);
247219370Spst      PUT_MODE (x, VOIDmode);
247319370Spst      XVEC (x, 0) = rtvec_alloc (XVECLEN (insn, 0));
247419370Spst      for (i = j = 0; i < XVECLEN (insn, 0); i++)
247519370Spst	{
247619370Spst	  rtx tmp = XVECEXP (insn, 0, i);
247719370Spst	  if (GET_CODE (tmp) != MATCH_SCRATCH && GET_CODE (tmp) != MATCH_DUP)
2478130809Smarcel	    {
2479130809Smarcel	      XVECEXP (x, 0, j) = tmp;
2480130809Smarcel	      j++;
2481130809Smarcel	    }
2482130809Smarcel	}
2483130809Smarcel      XVECLEN (x, 0) = j;
2484130809Smarcel
2485130809Smarcel      c_test_pos[0] = 'A' + j - 1;
2486130809Smarcel      c_test_pos[1] = '\0';
2487130809Smarcel    }
2488130809Smarcel  else if (XVECLEN (insn, type == RECOG) == 1)
2489130809Smarcel    x = XVECEXP (insn, type == RECOG, 0);
2490130809Smarcel  else
2491130809Smarcel    {
2492130809Smarcel      x = rtx_alloc (PARALLEL);
2493130809Smarcel      XVEC (x, 0) = XVEC (insn, type == RECOG);
2494130809Smarcel      PUT_MODE (x, VOIDmode);
2495130809Smarcel    }
2496130809Smarcel
2497130809Smarcel  validate_pattern (x, insn, NULL_RTX, 0);
2498130809Smarcel
2499130809Smarcel  memset(&head, 0, sizeof(head));
2500130809Smarcel  last = add_to_sequence (x, &head, "", type, 1);
2501130809Smarcel
2502130809Smarcel  /* Find the end of the test chain on the last node.  */
2503130809Smarcel  for (test = last->tests; test->next; test = test->next)
2504130809Smarcel    continue;
2505130809Smarcel  place = &test->next;
2506130809Smarcel
2507130809Smarcel  if (c_test[0])
2508130809Smarcel    {
2509130809Smarcel      /* Need a new node if we have another test to add.  */
2510130809Smarcel      if (test->type == DT_accept_op)
2511130809Smarcel	{
2512130809Smarcel	  last = new_decision (c_test_pos, &last->success);
2513130809Smarcel	  place = &last->tests;
2514130809Smarcel	}
2515130809Smarcel      test = new_decision_test (DT_c_test, &place);
2516130809Smarcel      test->u.c_test = c_test;
2517130809Smarcel    }
2518130809Smarcel
2519130809Smarcel  test = new_decision_test (DT_accept_insn, &place);
2520130809Smarcel  test->u.insn.code_number = next_insn_code;
2521130809Smarcel  test->u.insn.lineno = pattern_lineno;
2522130809Smarcel  test->u.insn.num_clobbers_to_add = 0;
2523130809Smarcel
2524130809Smarcel  switch (type)
2525130809Smarcel    {
2526130809Smarcel    case RECOG:
2527130809Smarcel      /* If this is an DEFINE_INSN and X is a PARALLEL, see if it ends
2528130809Smarcel	 with a group of CLOBBERs of (hard) registers or MATCH_SCRATCHes.
2529130809Smarcel	 If so, set up to recognize the pattern without these CLOBBERs.  */
2530130809Smarcel
2531130809Smarcel      if (GET_CODE (x) == PARALLEL)
2532130809Smarcel	{
2533130809Smarcel	  int i;
2534130809Smarcel
2535130809Smarcel	  /* Find the last non-clobber in the parallel.  */
2536130809Smarcel	  for (i = XVECLEN (x, 0); i > 0; i--)
2537130809Smarcel	    {
2538130809Smarcel	      rtx y = XVECEXP (x, 0, i - 1);
2539130809Smarcel	      if (GET_CODE (y) != CLOBBER
2540130809Smarcel		  || (GET_CODE (XEXP (y, 0)) != REG
2541130809Smarcel		      && GET_CODE (XEXP (y, 0)) != MATCH_SCRATCH))
2542130809Smarcel		break;
2543130809Smarcel	    }
2544130809Smarcel
2545130809Smarcel	  if (i != XVECLEN (x, 0))
2546130809Smarcel	    {
2547130809Smarcel	      rtx new;
2548130809Smarcel	      struct decision_head clobber_head;
2549130809Smarcel
2550130809Smarcel	      /* Build a similar insn without the clobbers.  */
2551130809Smarcel	      if (i == 1)
2552130809Smarcel		new = XVECEXP (x, 0, 0);
2553130809Smarcel	      else
2554130809Smarcel		{
2555130809Smarcel		  int j;
2556130809Smarcel
2557130809Smarcel		  new = rtx_alloc (PARALLEL);
2558130809Smarcel		  XVEC (new, 0) = rtvec_alloc (i);
2559130809Smarcel		  for (j = i - 1; j >= 0; j--)
2560130809Smarcel		    XVECEXP (new, 0, j) = XVECEXP (x, 0, j);
2561130809Smarcel		}
2562130809Smarcel
2563130809Smarcel	      /* Recognize it.  */
2564130809Smarcel	      memset (&clobber_head, 0, sizeof(clobber_head));
2565130809Smarcel	      last = add_to_sequence (new, &clobber_head, "", type, 1);
256698948Sobrien
256719370Spst	      /* Find the end of the test chain on the last node.  */
256846283Sdfr	      for (test = last->tests; test->next; test = test->next)
256998948Sobrien		continue;
257098948Sobrien
257198948Sobrien	      /* We definitely have a new test to add -- create a new
257298948Sobrien		 node if needed.  */
257398948Sobrien	      place = &test->next;
257446283Sdfr	      if (test->type == DT_accept_op)
257598948Sobrien		{
257646283Sdfr		  last = new_decision ("", &last->success);
257798948Sobrien		  place = &last->tests;
2578130809Smarcel		}
2579130809Smarcel
2580130809Smarcel	      if (c_test[0])
2581130809Smarcel		{
2582130809Smarcel		  test = new_decision_test (DT_c_test, &place);
258398948Sobrien		  test->u.c_test = c_test;
258498948Sobrien		}
258598948Sobrien
258698948Sobrien	      test = new_decision_test (DT_accept_insn, &place);
258746283Sdfr	      test->u.insn.code_number = next_insn_code;
258846283Sdfr	      test->u.insn.lineno = pattern_lineno;
258998948Sobrien	      test->u.insn.num_clobbers_to_add = XVECLEN (x, 0) - i;
259098948Sobrien
259198948Sobrien	      merge_trees (&head, &clobber_head);
259246283Sdfr	    }
259346283Sdfr	}
259446283Sdfr      break;
259546283Sdfr
259698948Sobrien    case SPLIT:
259798948Sobrien      /* Define the subroutine we will call below and emit in genemit.  */
259898948Sobrien      printf ("extern rtx gen_split_%d PARAMS ((rtx *));\n", next_insn_code);
259946283Sdfr      break;
260046283Sdfr
260146283Sdfr    case PEEPHOLE2:
260298948Sobrien      /* Define the subroutine we will call below and emit in genemit.  */
260346283Sdfr      printf ("extern rtx gen_peephole2_%d PARAMS ((rtx, rtx *));\n",
260419370Spst	      next_insn_code);
260598948Sobrien      break;
260619370Spst    }
260719370Spst
260819370Spst  return head;
2609130809Smarcel}
261098948Sobrien
261198948Sobrienstatic void
261219370Spstprocess_tree (head, subroutine_type)
261398948Sobrien     struct decision_head *head;
261419370Spst     enum routine_type subroutine_type;
2615130809Smarcel{
2616130809Smarcel  if (head->first == NULL)
2617130809Smarcel    {
2618130809Smarcel      /* We can elide peephole2_insns, but not recog or split_insns.  */
261998948Sobrien      if (subroutine_type == PEEPHOLE2)
262046283Sdfr	return;
262119370Spst    }
262219370Spst  else
262398948Sobrien    {
262498948Sobrien      factor_tests (head);
2625130809Smarcel
2626130809Smarcel      next_subroutine_number = 0;
262719370Spst      break_out_subroutines (head, 1);
262819370Spst      find_afterward (head, NULL);
262946283Sdfr
263098948Sobrien      /* We run this after find_afterward, because find_afterward needs
2631130809Smarcel	 the redundant DT_mode tests on predicates to determine whether
263298948Sobrien	 two tests can both be true or not.  */
263346283Sdfr      simplify_tests(head);
263446283Sdfr
263598948Sobrien      write_subroutines (head, subroutine_type);
263698948Sobrien    }
263798948Sobrien
263898948Sobrien  write_subroutine (head, subroutine_type);
263946283Sdfr}
264046283Sdfr
264146283Sdfrextern int main PARAMS ((int, char **));
264298948Sobrien
264398948Sobrienint
264498948Sobrienmain (argc, argv)
2645130809Smarcel     int argc;
264619370Spst     char **argv;
264719370Spst{
264898948Sobrien  rtx desc;
264998948Sobrien  struct decision_head recog_tree, split_tree, peephole2_tree, h;
2650130809Smarcel
2651130809Smarcel  progname = "genrecog";
265219370Spst
265319370Spst  memset (&recog_tree, 0, sizeof recog_tree);
265419370Spst  memset (&split_tree, 0, sizeof split_tree);
265519370Spst  memset (&peephole2_tree, 0, sizeof peephole2_tree);
265619370Spst
265798948Sobrien  if (argc <= 1)
265819370Spst    fatal ("no input file name");
265998948Sobrien
266098948Sobrien  if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
266198948Sobrien    return (FATAL_EXIT_CODE);
266298948Sobrien
266398948Sobrien  next_insn_code = 0;
266498948Sobrien  next_index = 0;
266598948Sobrien
266698948Sobrien  write_header ();
266798948Sobrien
266898948Sobrien  /* Read the machine description.  */
266998948Sobrien
267098948Sobrien  while (1)
267198948Sobrien    {
267246283Sdfr      desc = read_md_rtx (&pattern_lineno, &next_insn_code);
267398948Sobrien      if (desc == NULL)
267498948Sobrien	break;
267598948Sobrien
267698948Sobrien      if (GET_CODE (desc) == DEFINE_INSN)
267798948Sobrien	{
267846283Sdfr	  h = make_insn_sequence (desc, RECOG);
267998948Sobrien	  merge_trees (&recog_tree, &h);
268098948Sobrien	}
268198948Sobrien      else if (GET_CODE (desc) == DEFINE_SPLIT)
268298948Sobrien	{
268398948Sobrien	  h = make_insn_sequence (desc, SPLIT);
268446283Sdfr	  merge_trees (&split_tree, &h);
268598948Sobrien	}
268698948Sobrien      else if (GET_CODE (desc) == DEFINE_PEEPHOLE2)
268746283Sdfr	{
268898948Sobrien	  h = make_insn_sequence (desc, PEEPHOLE2);
268946283Sdfr	  merge_trees (&peephole2_tree, &h);
269046283Sdfr	}
269198948Sobrien
269298948Sobrien      next_index++;
269346283Sdfr    }
269498948Sobrien
269598948Sobrien  if (error_count)
269698948Sobrien    return FATAL_EXIT_CODE;
269798948Sobrien
269898948Sobrien  puts ("\n\n");
269946283Sdfr
270098948Sobrien  process_tree (&recog_tree, RECOG);
270198948Sobrien  process_tree (&split_tree, SPLIT);
270298948Sobrien  process_tree (&peephole2_tree, PEEPHOLE2);
270346283Sdfr
270498948Sobrien  fflush (stdout);
270598948Sobrien  return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
270646283Sdfr}
270798948Sobrien
2708130809Smarcel/* Define this so we can link with print-rtl.o to get debug_rtx function.  */
270998948Sobrienconst char *
271098948Sobrienget_insn_name (code)
2711130809Smarcel     int code;
271298948Sobrien{
271398948Sobrien  if (code < insn_name_ptr_size)
2714130809Smarcel    return insn_name_ptr[code];
271598948Sobrien  else
271698948Sobrien    return NULL;
2717130809Smarcel}
2718130809Smarcel
271946283Sdfrstatic void
272098948Sobrienrecord_insn_name (code, name)
272146283Sdfr     int code;
272298948Sobrien     const char *name;
272398948Sobrien{
272498948Sobrien  static const char *last_real_name = "insn";
272598948Sobrien  static int last_real_code = 0;
272698948Sobrien  char *new;
272798948Sobrien
272846283Sdfr  if (insn_name_ptr_size <= code)
272946283Sdfr    {
273098948Sobrien      int new_size;
273198948Sobrien      new_size = (insn_name_ptr_size ? insn_name_ptr_size * 2 : 512);
273246283Sdfr      insn_name_ptr =
273398948Sobrien	(char **) xrealloc (insn_name_ptr, sizeof(char *) * new_size);
273498948Sobrien      memset (insn_name_ptr + insn_name_ptr_size, 0,
273598948Sobrien	      sizeof(char *) * (new_size - insn_name_ptr_size));
273646283Sdfr      insn_name_ptr_size = new_size;
273798948Sobrien    }
273898948Sobrien
273998948Sobrien  if (!name || name[0] == '\0')
274046283Sdfr    {
274198948Sobrien      new = xmalloc (strlen (last_real_name) + 10);
274298948Sobrien      sprintf (new, "%s+%d", last_real_name, code - last_real_code);
274398948Sobrien    }
274498948Sobrien  else
274598948Sobrien    {
274698948Sobrien      last_real_name = new = xstrdup (name);
274798948Sobrien      last_real_code = code;
274898948Sobrien    }
274946283Sdfr
275098948Sobrien  insn_name_ptr[code] = new;
275198948Sobrien}
275298948Sobrien
275398948Sobrienstatic void
275498948Sobriendebug_decision_2 (test)
275598948Sobrien     struct decision_test *test;
275698948Sobrien{
275798948Sobrien  switch (test->type)
275898948Sobrien    {
275998948Sobrien    case DT_mode:
276098948Sobrien      fprintf (stderr, "mode=%s", GET_MODE_NAME (test->u.mode));
276198948Sobrien      break;
276298948Sobrien    case DT_code:
276398948Sobrien      fprintf (stderr, "code=%s", GET_RTX_NAME (test->u.code));
276498948Sobrien      break;
276598948Sobrien    case DT_veclen:
276698948Sobrien      fprintf (stderr, "veclen=%d", test->u.veclen);
276746283Sdfr      break;
276898948Sobrien    case DT_elt_zero_int:
276946283Sdfr      fprintf (stderr, "elt0_i=%d", (int) test->u.intval);
277046283Sdfr      break;
277198948Sobrien    case DT_elt_one_int:
277298948Sobrien      fprintf (stderr, "elt1_i=%d", (int) test->u.intval);
277346283Sdfr      break;
277498948Sobrien    case DT_elt_zero_wide:
277598948Sobrien      fprintf (stderr, "elt0_w=");
277698948Sobrien      fprintf (stderr, HOST_WIDE_INT_PRINT_DEC, test->u.intval);
277798948Sobrien      break;
277846283Sdfr    case DT_elt_zero_wide_safe:
277998948Sobrien      fprintf (stderr, "elt0_ws=");
278098948Sobrien      fprintf (stderr, HOST_WIDE_INT_PRINT_DEC, test->u.intval);
278198948Sobrien      break;
278298948Sobrien    case DT_veclen_ge:
278398948Sobrien      fprintf (stderr, "veclen>=%d", test->u.veclen);
2784130809Smarcel      break;
278598948Sobrien    case DT_dup:
278646283Sdfr      fprintf (stderr, "dup=%d", test->u.dup);
278798948Sobrien      break;
278898948Sobrien    case DT_pred:
278998948Sobrien      fprintf (stderr, "pred=(%s,%s)",
279098948Sobrien	       test->u.pred.name, GET_MODE_NAME(test->u.pred.mode));
279198948Sobrien      break;
279298948Sobrien    case DT_c_test:
279398948Sobrien      {
279498948Sobrien	char sub[16+4];
279598948Sobrien	strncpy (sub, test->u.c_test, sizeof(sub));
279698948Sobrien	memcpy (sub+16, "...", 4);
279798948Sobrien	fprintf (stderr, "c_test=\"%s\"", sub);
279846283Sdfr      }
279998948Sobrien      break;
280046283Sdfr    case DT_accept_op:
280146283Sdfr      fprintf (stderr, "A_op=%d", test->u.opno);
280246283Sdfr      break;
280398948Sobrien    case DT_accept_insn:
280498948Sobrien      fprintf (stderr, "A_insn=(%d,%d)",
280598948Sobrien	       test->u.insn.code_number, test->u.insn.num_clobbers_to_add);
280646283Sdfr      break;
280798948Sobrien
280898948Sobrien    default:
280998948Sobrien      abort ();
281098948Sobrien    }
281146283Sdfr}
281246283Sdfr
281398948Sobrienstatic void
281498948Sobriendebug_decision_1 (d, indent)
281546283Sdfr     struct decision *d;
281698948Sobrien     int indent;
281798948Sobrien{
281898948Sobrien  int i;
281998948Sobrien  struct decision_test *test;
282046283Sdfr
282146283Sdfr  if (d == NULL)
282298948Sobrien    {
282398948Sobrien      for (i = 0; i < indent; ++i)
282498948Sobrien	putc (' ', stderr);
282546283Sdfr      fputs ("(nil)\n", stderr);
282698948Sobrien      return;
282798948Sobrien    }
282846283Sdfr
282998948Sobrien  for (i = 0; i < indent; ++i)
283098948Sobrien    putc (' ', stderr);
283198948Sobrien
283246283Sdfr  putc ('{', stderr);
283398948Sobrien  test = d->tests;
283498948Sobrien  if (test)
2835130809Smarcel    {
283698948Sobrien      debug_decision_2 (test);
283746283Sdfr      while ((test = test->next) != NULL)
283898948Sobrien	{
283946283Sdfr	  fputs (" + ", stderr);
284046283Sdfr	  debug_decision_2 (test);
284198948Sobrien	}
284246283Sdfr    }
284398948Sobrien  fprintf (stderr, "} %d n %d a %d\n", d->number,
284498948Sobrien	   (d->next ? d->next->number : -1),
284598948Sobrien	   (d->afterward ? d->afterward->number : -1));
284646283Sdfr}
284798948Sobrien
284898948Sobrienstatic void
284946283Sdfrdebug_decision_0 (d, indent, maxdepth)
285098948Sobrien     struct decision *d;
285146283Sdfr     int indent, maxdepth;
285246283Sdfr{
285398948Sobrien  struct decision *n;
285446283Sdfr  int i;
285598948Sobrien
285698948Sobrien  if (maxdepth < 0)
285798948Sobrien    return;
285898948Sobrien  if (d == NULL)
2859130809Smarcel    {
2860130809Smarcel      for (i = 0; i < indent; ++i)
2861130809Smarcel	putc (' ', stderr);
2862130809Smarcel      fputs ("(nil)\n", stderr);
286398948Sobrien      return;
2864130809Smarcel    }
286598948Sobrien
2866130809Smarcel  debug_decision_1 (d, indent);
286798948Sobrien  for (n = d->success.first; n ; n = n->next)
286898948Sobrien    debug_decision_0 (n, indent + 2, maxdepth - 1);
2869130809Smarcel}
287098948Sobrien
287198948Sobrienvoid
2872130809Smarceldebug_decision (d)
2873130809Smarcel     struct decision *d;
2874130809Smarcel{
2875130809Smarcel  debug_decision_0 (d, 0, 1000000);
2876130809Smarcel}
2877130809Smarcel
2878130809Smarcelvoid
287998948Sobriendebug_decision_list (d)
288098948Sobrien     struct decision *d;
2881130809Smarcel{
2882130809Smarcel  while (d)
2883130809Smarcel    {
2884130809Smarcel      debug_decision_0 (d, 0, 0);
2885130809Smarcel      d = d->next;
2886130809Smarcel    }
2887130809Smarcel}
2888130809Smarcel