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