annotate gcc/gensupport.c @ 16:04ced10e8804

gcc 7
author kono
date Fri, 27 Oct 2017 22:46:09 +0900
parents f6334be47118
children 84e7813d76e9
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1 /* Support routines for the various generation passes.
16
kono
parents: 14
diff changeset
2 Copyright (C) 2000-2017 Free Software Foundation, Inc.
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
3
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
4 This file is part of GCC.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
5
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
6 GCC is free software; you can redistribute it and/or modify it
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
7 under the terms of the GNU General Public License as published by
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
8 the Free Software Foundation; either version 3, or (at your option)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
9 any later version.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
10
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
11 GCC is distributed in the hope that it will be useful, but WITHOUT
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
13 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
14 License for more details.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
15
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
16 You should have received a copy of the GNU General Public License
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
17 along with GCC; see the file COPYING3. If not see
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
18 <http://www.gnu.org/licenses/>. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
19
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
20 #include "bconfig.h"
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
21 #include "system.h"
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
22 #include "coretypes.h"
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
23 #include "tm.h"
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
24 #include "rtl.h"
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
25 #include "obstack.h"
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
26 #include "errors.h"
14
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 11
diff changeset
27 #include "read-md.h"
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
28 #include "gensupport.h"
16
kono
parents: 14
diff changeset
29 #include "vec.h"
kono
parents: 14
diff changeset
30
kono
parents: 14
diff changeset
31 #define MAX_OPERANDS 40
kono
parents: 14
diff changeset
32
kono
parents: 14
diff changeset
33 static rtx operand_data[MAX_OPERANDS];
kono
parents: 14
diff changeset
34 static rtx match_operand_entries_in_pattern[MAX_OPERANDS];
kono
parents: 14
diff changeset
35 static char used_operands_numbers[MAX_OPERANDS];
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
36
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
37
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
38 /* In case some macros used by files we include need it, define this here. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
39 int target_flags;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
40
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
41 int insn_elision = 1;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
42
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
43 static struct obstack obstack;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
44 struct obstack *rtl_obstack = &obstack;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
45
16
kono
parents: 14
diff changeset
46 /* Counter for named patterns and INSN_CODEs. */
kono
parents: 14
diff changeset
47 static int insn_sequence_num;
kono
parents: 14
diff changeset
48
kono
parents: 14
diff changeset
49 /* Counter for define_splits. */
kono
parents: 14
diff changeset
50 static int split_sequence_num;
kono
parents: 14
diff changeset
51
kono
parents: 14
diff changeset
52 /* Counter for define_peephole2s. */
kono
parents: 14
diff changeset
53 static int peephole2_sequence_num;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
54
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
55 static int predicable_default;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
56 static const char *predicable_true;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
57 static const char *predicable_false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
58
16
kono
parents: 14
diff changeset
59 static const char *subst_true = "yes";
kono
parents: 14
diff changeset
60 static const char *subst_false = "no";
kono
parents: 14
diff changeset
61
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
62 static htab_t condition_table;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
63
16
kono
parents: 14
diff changeset
64 /* We initially queue all patterns, process the define_insn,
kono
parents: 14
diff changeset
65 define_cond_exec and define_subst patterns, then return
kono
parents: 14
diff changeset
66 them one at a time. */
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
67
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
68 struct queue_elem
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
69 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
70 rtx data;
16
kono
parents: 14
diff changeset
71 file_location loc;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
72 struct queue_elem *next;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
73 /* In a DEFINE_INSN that came from a DEFINE_INSN_AND_SPLIT, SPLIT
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
74 points to the generated DEFINE_SPLIT. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
75 struct queue_elem *split;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
76 };
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
77
14
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 11
diff changeset
78 #define MNEMONIC_ATTR_NAME "mnemonic"
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 11
diff changeset
79 #define MNEMONIC_HTAB_SIZE 1024
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 11
diff changeset
80
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
81 static struct queue_elem *define_attr_queue;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
82 static struct queue_elem **define_attr_tail = &define_attr_queue;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
83 static struct queue_elem *define_pred_queue;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
84 static struct queue_elem **define_pred_tail = &define_pred_queue;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
85 static struct queue_elem *define_insn_queue;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
86 static struct queue_elem **define_insn_tail = &define_insn_queue;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
87 static struct queue_elem *define_cond_exec_queue;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
88 static struct queue_elem **define_cond_exec_tail = &define_cond_exec_queue;
16
kono
parents: 14
diff changeset
89 static struct queue_elem *define_subst_queue;
kono
parents: 14
diff changeset
90 static struct queue_elem **define_subst_tail = &define_subst_queue;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
91 static struct queue_elem *other_queue;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
92 static struct queue_elem **other_tail = &other_queue;
16
kono
parents: 14
diff changeset
93 static struct queue_elem *define_subst_attr_queue;
kono
parents: 14
diff changeset
94 static struct queue_elem **define_subst_attr_tail = &define_subst_attr_queue;
kono
parents: 14
diff changeset
95
kono
parents: 14
diff changeset
96 /* Mapping from DEFINE_* rtxes to their location in the source file. */
kono
parents: 14
diff changeset
97 static hash_map <rtx, file_location> *rtx_locs;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
98
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
99 static void remove_constraints (rtx);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
100
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
101 static int is_predicable (struct queue_elem *);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
102 static void identify_predicable_attribute (void);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
103 static int n_alternatives (const char *);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
104 static void collect_insn_data (rtx, int *, int *);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
105 static const char *alter_test_for_insn (struct queue_elem *,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
106 struct queue_elem *);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
107 static char *shift_output_template (char *, const char *, int);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
108 static const char *alter_output_for_insn (struct queue_elem *,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
109 struct queue_elem *,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
110 int, int);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
111 static void process_one_cond_exec (struct queue_elem *);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
112 static void process_define_cond_exec (void);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
113 static void init_predicate_table (void);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
114 static void record_insn_name (int, const char *);
16
kono
parents: 14
diff changeset
115
kono
parents: 14
diff changeset
116 static bool has_subst_attribute (struct queue_elem *, struct queue_elem *);
kono
parents: 14
diff changeset
117 static const char * alter_output_for_subst_insn (rtx, int);
kono
parents: 14
diff changeset
118 static void alter_attrs_for_subst_insn (struct queue_elem *, int);
kono
parents: 14
diff changeset
119 static void process_substs_on_one_elem (struct queue_elem *,
kono
parents: 14
diff changeset
120 struct queue_elem *);
kono
parents: 14
diff changeset
121 static rtx subst_dup (rtx, int, int);
kono
parents: 14
diff changeset
122 static void process_define_subst (void);
kono
parents: 14
diff changeset
123
kono
parents: 14
diff changeset
124 static const char * duplicate_alternatives (const char *, int);
kono
parents: 14
diff changeset
125 static const char * duplicate_each_alternative (const char * str, int n_dup);
kono
parents: 14
diff changeset
126
kono
parents: 14
diff changeset
127 typedef const char * (*constraints_handler_t) (const char *, int);
kono
parents: 14
diff changeset
128 static rtx alter_constraints (rtx, int, constraints_handler_t);
kono
parents: 14
diff changeset
129 static rtx adjust_operands_numbers (rtx);
kono
parents: 14
diff changeset
130 static rtx replace_duplicating_operands_in_pattern (rtx);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
131
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
132 /* Make a version of gen_rtx_CONST_INT so that GEN_INT can be used in
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
133 the gensupport programs. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
134
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
135 rtx
16
kono
parents: 14
diff changeset
136 gen_rtx_CONST_INT (machine_mode ARG_UNUSED (mode),
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
137 HOST_WIDE_INT arg)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
138 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
139 rtx rt = rtx_alloc (CONST_INT);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
140
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
141 XWINT (rt, 0) = arg;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
142 return rt;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
143 }
16
kono
parents: 14
diff changeset
144
kono
parents: 14
diff changeset
145 /* Return the rtx pattern specified by the list of rtxes in a
kono
parents: 14
diff changeset
146 define_insn or define_split. */
kono
parents: 14
diff changeset
147
kono
parents: 14
diff changeset
148 rtx
kono
parents: 14
diff changeset
149 add_implicit_parallel (rtvec vec)
kono
parents: 14
diff changeset
150 {
kono
parents: 14
diff changeset
151 if (GET_NUM_ELEM (vec) == 1)
kono
parents: 14
diff changeset
152 return RTVEC_ELT (vec, 0);
kono
parents: 14
diff changeset
153 else
kono
parents: 14
diff changeset
154 {
kono
parents: 14
diff changeset
155 rtx pattern = rtx_alloc (PARALLEL);
kono
parents: 14
diff changeset
156 XVEC (pattern, 0) = vec;
kono
parents: 14
diff changeset
157 return pattern;
kono
parents: 14
diff changeset
158 }
kono
parents: 14
diff changeset
159 }
kono
parents: 14
diff changeset
160
kono
parents: 14
diff changeset
161 /* Predicate handling.
kono
parents: 14
diff changeset
162
kono
parents: 14
diff changeset
163 We construct from the machine description a table mapping each
kono
parents: 14
diff changeset
164 predicate to a list of the rtl codes it can possibly match. The
kono
parents: 14
diff changeset
165 function 'maybe_both_true' uses it to deduce that there are no
kono
parents: 14
diff changeset
166 expressions that can be matches by certain pairs of tree nodes.
kono
parents: 14
diff changeset
167 Also, if a predicate can match only one code, we can hardwire that
kono
parents: 14
diff changeset
168 code into the node testing the predicate.
kono
parents: 14
diff changeset
169
kono
parents: 14
diff changeset
170 Some predicates are flagged as special. validate_pattern will not
kono
parents: 14
diff changeset
171 warn about modeless match_operand expressions if they have a
kono
parents: 14
diff changeset
172 special predicate. Predicates that allow only constants are also
kono
parents: 14
diff changeset
173 treated as special, for this purpose.
kono
parents: 14
diff changeset
174
kono
parents: 14
diff changeset
175 validate_pattern will warn about predicates that allow non-lvalues
kono
parents: 14
diff changeset
176 when they appear in destination operands.
kono
parents: 14
diff changeset
177
kono
parents: 14
diff changeset
178 Calculating the set of rtx codes that can possibly be accepted by a
kono
parents: 14
diff changeset
179 predicate expression EXP requires a three-state logic: any given
kono
parents: 14
diff changeset
180 subexpression may definitively accept a code C (Y), definitively
kono
parents: 14
diff changeset
181 reject a code C (N), or may have an indeterminate effect (I). N
kono
parents: 14
diff changeset
182 and I is N; Y or I is Y; Y and I, N or I are both I. Here are full
kono
parents: 14
diff changeset
183 truth tables.
kono
parents: 14
diff changeset
184
kono
parents: 14
diff changeset
185 a b a&b a|b
kono
parents: 14
diff changeset
186 Y Y Y Y
kono
parents: 14
diff changeset
187 N Y N Y
kono
parents: 14
diff changeset
188 N N N N
kono
parents: 14
diff changeset
189 I Y I Y
kono
parents: 14
diff changeset
190 I N N I
kono
parents: 14
diff changeset
191 I I I I
kono
parents: 14
diff changeset
192
kono
parents: 14
diff changeset
193 We represent Y with 1, N with 0, I with 2. If any code is left in
kono
parents: 14
diff changeset
194 an I state by the complete expression, we must assume that that
kono
parents: 14
diff changeset
195 code can be accepted. */
kono
parents: 14
diff changeset
196
kono
parents: 14
diff changeset
197 #define N 0
kono
parents: 14
diff changeset
198 #define Y 1
kono
parents: 14
diff changeset
199 #define I 2
kono
parents: 14
diff changeset
200
kono
parents: 14
diff changeset
201 #define TRISTATE_AND(a,b) \
kono
parents: 14
diff changeset
202 ((a) == I ? ((b) == N ? N : I) : \
kono
parents: 14
diff changeset
203 (b) == I ? ((a) == N ? N : I) : \
kono
parents: 14
diff changeset
204 (a) && (b))
kono
parents: 14
diff changeset
205
kono
parents: 14
diff changeset
206 #define TRISTATE_OR(a,b) \
kono
parents: 14
diff changeset
207 ((a) == I ? ((b) == Y ? Y : I) : \
kono
parents: 14
diff changeset
208 (b) == I ? ((a) == Y ? Y : I) : \
kono
parents: 14
diff changeset
209 (a) || (b))
kono
parents: 14
diff changeset
210
kono
parents: 14
diff changeset
211 #define TRISTATE_NOT(a) \
kono
parents: 14
diff changeset
212 ((a) == I ? I : !(a))
kono
parents: 14
diff changeset
213
kono
parents: 14
diff changeset
214 /* 0 means no warning about that code yet, 1 means warned. */
kono
parents: 14
diff changeset
215 static char did_you_mean_codes[NUM_RTX_CODE];
kono
parents: 14
diff changeset
216
kono
parents: 14
diff changeset
217 /* Recursively calculate the set of rtx codes accepted by the
kono
parents: 14
diff changeset
218 predicate expression EXP, writing the result to CODES. LOC is
kono
parents: 14
diff changeset
219 the .md file location of the directive containing EXP. */
kono
parents: 14
diff changeset
220
kono
parents: 14
diff changeset
221 void
kono
parents: 14
diff changeset
222 compute_test_codes (rtx exp, file_location loc, char *codes)
kono
parents: 14
diff changeset
223 {
kono
parents: 14
diff changeset
224 char op0_codes[NUM_RTX_CODE];
kono
parents: 14
diff changeset
225 char op1_codes[NUM_RTX_CODE];
kono
parents: 14
diff changeset
226 char op2_codes[NUM_RTX_CODE];
kono
parents: 14
diff changeset
227 int i;
kono
parents: 14
diff changeset
228
kono
parents: 14
diff changeset
229 switch (GET_CODE (exp))
kono
parents: 14
diff changeset
230 {
kono
parents: 14
diff changeset
231 case AND:
kono
parents: 14
diff changeset
232 compute_test_codes (XEXP (exp, 0), loc, op0_codes);
kono
parents: 14
diff changeset
233 compute_test_codes (XEXP (exp, 1), loc, op1_codes);
kono
parents: 14
diff changeset
234 for (i = 0; i < NUM_RTX_CODE; i++)
kono
parents: 14
diff changeset
235 codes[i] = TRISTATE_AND (op0_codes[i], op1_codes[i]);
kono
parents: 14
diff changeset
236 break;
kono
parents: 14
diff changeset
237
kono
parents: 14
diff changeset
238 case IOR:
kono
parents: 14
diff changeset
239 compute_test_codes (XEXP (exp, 0), loc, op0_codes);
kono
parents: 14
diff changeset
240 compute_test_codes (XEXP (exp, 1), loc, op1_codes);
kono
parents: 14
diff changeset
241 for (i = 0; i < NUM_RTX_CODE; i++)
kono
parents: 14
diff changeset
242 codes[i] = TRISTATE_OR (op0_codes[i], op1_codes[i]);
kono
parents: 14
diff changeset
243 break;
kono
parents: 14
diff changeset
244 case NOT:
kono
parents: 14
diff changeset
245 compute_test_codes (XEXP (exp, 0), loc, op0_codes);
kono
parents: 14
diff changeset
246 for (i = 0; i < NUM_RTX_CODE; i++)
kono
parents: 14
diff changeset
247 codes[i] = TRISTATE_NOT (op0_codes[i]);
kono
parents: 14
diff changeset
248 break;
kono
parents: 14
diff changeset
249
kono
parents: 14
diff changeset
250 case IF_THEN_ELSE:
kono
parents: 14
diff changeset
251 /* a ? b : c accepts the same codes as (a & b) | (!a & c). */
kono
parents: 14
diff changeset
252 compute_test_codes (XEXP (exp, 0), loc, op0_codes);
kono
parents: 14
diff changeset
253 compute_test_codes (XEXP (exp, 1), loc, op1_codes);
kono
parents: 14
diff changeset
254 compute_test_codes (XEXP (exp, 2), loc, op2_codes);
kono
parents: 14
diff changeset
255 for (i = 0; i < NUM_RTX_CODE; i++)
kono
parents: 14
diff changeset
256 codes[i] = TRISTATE_OR (TRISTATE_AND (op0_codes[i], op1_codes[i]),
kono
parents: 14
diff changeset
257 TRISTATE_AND (TRISTATE_NOT (op0_codes[i]),
kono
parents: 14
diff changeset
258 op2_codes[i]));
kono
parents: 14
diff changeset
259 break;
kono
parents: 14
diff changeset
260
kono
parents: 14
diff changeset
261 case MATCH_CODE:
kono
parents: 14
diff changeset
262 /* MATCH_CODE allows a specified list of codes. However, if it
kono
parents: 14
diff changeset
263 does not apply to the top level of the expression, it does not
kono
parents: 14
diff changeset
264 constrain the set of codes for the top level. */
kono
parents: 14
diff changeset
265 if (XSTR (exp, 1)[0] != '\0')
kono
parents: 14
diff changeset
266 {
kono
parents: 14
diff changeset
267 memset (codes, Y, NUM_RTX_CODE);
kono
parents: 14
diff changeset
268 break;
kono
parents: 14
diff changeset
269 }
kono
parents: 14
diff changeset
270
kono
parents: 14
diff changeset
271 memset (codes, N, NUM_RTX_CODE);
kono
parents: 14
diff changeset
272 {
kono
parents: 14
diff changeset
273 const char *next_code = XSTR (exp, 0);
kono
parents: 14
diff changeset
274 const char *code;
kono
parents: 14
diff changeset
275
kono
parents: 14
diff changeset
276 if (*next_code == '\0')
kono
parents: 14
diff changeset
277 {
kono
parents: 14
diff changeset
278 error_at (loc, "empty match_code expression");
kono
parents: 14
diff changeset
279 break;
kono
parents: 14
diff changeset
280 }
kono
parents: 14
diff changeset
281
kono
parents: 14
diff changeset
282 while ((code = scan_comma_elt (&next_code)) != 0)
kono
parents: 14
diff changeset
283 {
kono
parents: 14
diff changeset
284 size_t n = next_code - code;
kono
parents: 14
diff changeset
285 int found_it = 0;
kono
parents: 14
diff changeset
286
kono
parents: 14
diff changeset
287 for (i = 0; i < NUM_RTX_CODE; i++)
kono
parents: 14
diff changeset
288 if (!strncmp (code, GET_RTX_NAME (i), n)
kono
parents: 14
diff changeset
289 && GET_RTX_NAME (i)[n] == '\0')
kono
parents: 14
diff changeset
290 {
kono
parents: 14
diff changeset
291 codes[i] = Y;
kono
parents: 14
diff changeset
292 found_it = 1;
kono
parents: 14
diff changeset
293 break;
kono
parents: 14
diff changeset
294 }
kono
parents: 14
diff changeset
295 if (!found_it)
kono
parents: 14
diff changeset
296 {
kono
parents: 14
diff changeset
297 error_at (loc, "match_code \"%.*s\" matches nothing",
kono
parents: 14
diff changeset
298 (int) n, code);
kono
parents: 14
diff changeset
299 for (i = 0; i < NUM_RTX_CODE; i++)
kono
parents: 14
diff changeset
300 if (!strncasecmp (code, GET_RTX_NAME (i), n)
kono
parents: 14
diff changeset
301 && GET_RTX_NAME (i)[n] == '\0'
kono
parents: 14
diff changeset
302 && !did_you_mean_codes[i])
kono
parents: 14
diff changeset
303 {
kono
parents: 14
diff changeset
304 did_you_mean_codes[i] = 1;
kono
parents: 14
diff changeset
305 message_at (loc, "(did you mean \"%s\"?)",
kono
parents: 14
diff changeset
306 GET_RTX_NAME (i));
kono
parents: 14
diff changeset
307 }
kono
parents: 14
diff changeset
308 }
kono
parents: 14
diff changeset
309 }
kono
parents: 14
diff changeset
310 }
kono
parents: 14
diff changeset
311 break;
kono
parents: 14
diff changeset
312
kono
parents: 14
diff changeset
313 case MATCH_OPERAND:
kono
parents: 14
diff changeset
314 /* MATCH_OPERAND disallows the set of codes that the named predicate
kono
parents: 14
diff changeset
315 disallows, and is indeterminate for the codes that it does allow. */
kono
parents: 14
diff changeset
316 {
kono
parents: 14
diff changeset
317 struct pred_data *p = lookup_predicate (XSTR (exp, 1));
kono
parents: 14
diff changeset
318 if (!p)
kono
parents: 14
diff changeset
319 {
kono
parents: 14
diff changeset
320 error_at (loc, "reference to unknown predicate '%s'",
kono
parents: 14
diff changeset
321 XSTR (exp, 1));
kono
parents: 14
diff changeset
322 break;
kono
parents: 14
diff changeset
323 }
kono
parents: 14
diff changeset
324 for (i = 0; i < NUM_RTX_CODE; i++)
kono
parents: 14
diff changeset
325 codes[i] = p->codes[i] ? I : N;
kono
parents: 14
diff changeset
326 }
kono
parents: 14
diff changeset
327 break;
kono
parents: 14
diff changeset
328
kono
parents: 14
diff changeset
329
kono
parents: 14
diff changeset
330 case MATCH_TEST:
kono
parents: 14
diff changeset
331 /* (match_test WHATEVER) is completely indeterminate. */
kono
parents: 14
diff changeset
332 memset (codes, I, NUM_RTX_CODE);
kono
parents: 14
diff changeset
333 break;
kono
parents: 14
diff changeset
334
kono
parents: 14
diff changeset
335 default:
kono
parents: 14
diff changeset
336 error_at (loc, "'%s' cannot be used in predicates or constraints",
kono
parents: 14
diff changeset
337 GET_RTX_NAME (GET_CODE (exp)));
kono
parents: 14
diff changeset
338 memset (codes, I, NUM_RTX_CODE);
kono
parents: 14
diff changeset
339 break;
kono
parents: 14
diff changeset
340 }
kono
parents: 14
diff changeset
341 }
kono
parents: 14
diff changeset
342
kono
parents: 14
diff changeset
343 #undef TRISTATE_OR
kono
parents: 14
diff changeset
344 #undef TRISTATE_AND
kono
parents: 14
diff changeset
345 #undef TRISTATE_NOT
kono
parents: 14
diff changeset
346
kono
parents: 14
diff changeset
347 /* Return true if NAME is a valid predicate name. */
kono
parents: 14
diff changeset
348
kono
parents: 14
diff changeset
349 static bool
kono
parents: 14
diff changeset
350 valid_predicate_name_p (const char *name)
kono
parents: 14
diff changeset
351 {
kono
parents: 14
diff changeset
352 const char *p;
kono
parents: 14
diff changeset
353
kono
parents: 14
diff changeset
354 if (!ISALPHA (name[0]) && name[0] != '_')
kono
parents: 14
diff changeset
355 return false;
kono
parents: 14
diff changeset
356 for (p = name + 1; *p; p++)
kono
parents: 14
diff changeset
357 if (!ISALNUM (*p) && *p != '_')
kono
parents: 14
diff changeset
358 return false;
kono
parents: 14
diff changeset
359 return true;
kono
parents: 14
diff changeset
360 }
kono
parents: 14
diff changeset
361
kono
parents: 14
diff changeset
362 /* Process define_predicate directive DESC, which appears at location LOC.
kono
parents: 14
diff changeset
363 Compute the set of codes that can be matched, and record this as a known
kono
parents: 14
diff changeset
364 predicate. */
kono
parents: 14
diff changeset
365
kono
parents: 14
diff changeset
366 static void
kono
parents: 14
diff changeset
367 process_define_predicate (rtx desc, file_location loc)
kono
parents: 14
diff changeset
368 {
kono
parents: 14
diff changeset
369 struct pred_data *pred;
kono
parents: 14
diff changeset
370 char codes[NUM_RTX_CODE];
kono
parents: 14
diff changeset
371 int i;
kono
parents: 14
diff changeset
372
kono
parents: 14
diff changeset
373 if (!valid_predicate_name_p (XSTR (desc, 0)))
kono
parents: 14
diff changeset
374 {
kono
parents: 14
diff changeset
375 error_at (loc, "%s: predicate name must be a valid C function name",
kono
parents: 14
diff changeset
376 XSTR (desc, 0));
kono
parents: 14
diff changeset
377 return;
kono
parents: 14
diff changeset
378 }
kono
parents: 14
diff changeset
379
kono
parents: 14
diff changeset
380 pred = XCNEW (struct pred_data);
kono
parents: 14
diff changeset
381 pred->name = XSTR (desc, 0);
kono
parents: 14
diff changeset
382 pred->exp = XEXP (desc, 1);
kono
parents: 14
diff changeset
383 pred->c_block = XSTR (desc, 2);
kono
parents: 14
diff changeset
384 if (GET_CODE (desc) == DEFINE_SPECIAL_PREDICATE)
kono
parents: 14
diff changeset
385 pred->special = true;
kono
parents: 14
diff changeset
386
kono
parents: 14
diff changeset
387 compute_test_codes (XEXP (desc, 1), loc, codes);
kono
parents: 14
diff changeset
388
kono
parents: 14
diff changeset
389 for (i = 0; i < NUM_RTX_CODE; i++)
kono
parents: 14
diff changeset
390 if (codes[i] != N)
kono
parents: 14
diff changeset
391 add_predicate_code (pred, (enum rtx_code) i);
kono
parents: 14
diff changeset
392
kono
parents: 14
diff changeset
393 add_predicate (pred);
kono
parents: 14
diff changeset
394 }
kono
parents: 14
diff changeset
395 #undef I
kono
parents: 14
diff changeset
396 #undef N
kono
parents: 14
diff changeset
397 #undef Y
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
398
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
399 /* Queue PATTERN on LIST_TAIL. Return the address of the new queue
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
400 element. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
401
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
402 static struct queue_elem *
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
403 queue_pattern (rtx pattern, struct queue_elem ***list_tail,
16
kono
parents: 14
diff changeset
404 file_location loc)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
405 {
16
kono
parents: 14
diff changeset
406 struct queue_elem *e = XNEW (struct queue_elem);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
407 e->data = pattern;
16
kono
parents: 14
diff changeset
408 e->loc = loc;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
409 e->next = NULL;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
410 e->split = NULL;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
411 **list_tail = e;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
412 *list_tail = &e->next;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
413 return e;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
414 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
415
16
kono
parents: 14
diff changeset
416 /* Remove element ELEM from QUEUE. */
kono
parents: 14
diff changeset
417 static void
kono
parents: 14
diff changeset
418 remove_from_queue (struct queue_elem *elem, struct queue_elem **queue)
kono
parents: 14
diff changeset
419 {
kono
parents: 14
diff changeset
420 struct queue_elem *prev, *e;
kono
parents: 14
diff changeset
421 prev = NULL;
kono
parents: 14
diff changeset
422 for (e = *queue; e ; e = e->next)
kono
parents: 14
diff changeset
423 {
kono
parents: 14
diff changeset
424 if (e == elem)
kono
parents: 14
diff changeset
425 break;
kono
parents: 14
diff changeset
426 prev = e;
kono
parents: 14
diff changeset
427 }
kono
parents: 14
diff changeset
428 if (e == NULL)
kono
parents: 14
diff changeset
429 return;
kono
parents: 14
diff changeset
430
kono
parents: 14
diff changeset
431 if (prev)
kono
parents: 14
diff changeset
432 prev->next = elem->next;
kono
parents: 14
diff changeset
433 else
kono
parents: 14
diff changeset
434 *queue = elem->next;
kono
parents: 14
diff changeset
435 }
kono
parents: 14
diff changeset
436
kono
parents: 14
diff changeset
437 /* Build a define_attr for an binary attribute with name NAME and
kono
parents: 14
diff changeset
438 possible values "yes" and "no", and queue it. */
kono
parents: 14
diff changeset
439 static void
kono
parents: 14
diff changeset
440 add_define_attr (const char *name)
kono
parents: 14
diff changeset
441 {
kono
parents: 14
diff changeset
442 struct queue_elem *e = XNEW (struct queue_elem);
kono
parents: 14
diff changeset
443 rtx t1 = rtx_alloc (DEFINE_ATTR);
kono
parents: 14
diff changeset
444 XSTR (t1, 0) = name;
kono
parents: 14
diff changeset
445 XSTR (t1, 1) = "no,yes";
kono
parents: 14
diff changeset
446 XEXP (t1, 2) = rtx_alloc (CONST_STRING);
kono
parents: 14
diff changeset
447 XSTR (XEXP (t1, 2), 0) = "yes";
kono
parents: 14
diff changeset
448 e->data = t1;
kono
parents: 14
diff changeset
449 e->loc = file_location ("built-in", -1, -1);
kono
parents: 14
diff changeset
450 e->next = define_attr_queue;
kono
parents: 14
diff changeset
451 define_attr_queue = e;
kono
parents: 14
diff changeset
452
kono
parents: 14
diff changeset
453 }
kono
parents: 14
diff changeset
454
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
455 /* Recursively remove constraints from an rtx. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
456
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
457 static void
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
458 remove_constraints (rtx part)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
459 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
460 int i, j;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
461 const char *format_ptr;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
462
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
463 if (part == 0)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
464 return;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
465
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
466 if (GET_CODE (part) == MATCH_OPERAND)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
467 XSTR (part, 2) = "";
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
468 else if (GET_CODE (part) == MATCH_SCRATCH)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
469 XSTR (part, 1) = "";
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
470
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
471 format_ptr = GET_RTX_FORMAT (GET_CODE (part));
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
472
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
473 for (i = 0; i < GET_RTX_LENGTH (GET_CODE (part)); i++)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
474 switch (*format_ptr++)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
475 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
476 case 'e':
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
477 case 'u':
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
478 remove_constraints (XEXP (part, i));
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
479 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
480 case 'E':
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
481 if (XVEC (part, i) != NULL)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
482 for (j = 0; j < XVECLEN (part, i); j++)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
483 remove_constraints (XVECEXP (part, i, j));
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
484 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
485 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
486 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
487
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
488 /* Process a top level rtx in some way, queuing as appropriate. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
489
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
490 static void
16
kono
parents: 14
diff changeset
491 process_rtx (rtx desc, file_location loc)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
492 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
493 switch (GET_CODE (desc))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
494 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
495 case DEFINE_INSN:
16
kono
parents: 14
diff changeset
496 queue_pattern (desc, &define_insn_tail, loc);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
497 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
498
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
499 case DEFINE_COND_EXEC:
16
kono
parents: 14
diff changeset
500 queue_pattern (desc, &define_cond_exec_tail, loc);
kono
parents: 14
diff changeset
501 break;
kono
parents: 14
diff changeset
502
kono
parents: 14
diff changeset
503 case DEFINE_SUBST:
kono
parents: 14
diff changeset
504 queue_pattern (desc, &define_subst_tail, loc);
kono
parents: 14
diff changeset
505 break;
kono
parents: 14
diff changeset
506
kono
parents: 14
diff changeset
507 case DEFINE_SUBST_ATTR:
kono
parents: 14
diff changeset
508 queue_pattern (desc, &define_subst_attr_tail, loc);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
509 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
510
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
511 case DEFINE_ATTR:
14
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 11
diff changeset
512 case DEFINE_ENUM_ATTR:
16
kono
parents: 14
diff changeset
513 queue_pattern (desc, &define_attr_tail, loc);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
514 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
515
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
516 case DEFINE_PREDICATE:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
517 case DEFINE_SPECIAL_PREDICATE:
16
kono
parents: 14
diff changeset
518 process_define_predicate (desc, loc);
kono
parents: 14
diff changeset
519 /* Fall through. */
kono
parents: 14
diff changeset
520
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
521 case DEFINE_CONSTRAINT:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
522 case DEFINE_REGISTER_CONSTRAINT:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
523 case DEFINE_MEMORY_CONSTRAINT:
16
kono
parents: 14
diff changeset
524 case DEFINE_SPECIAL_MEMORY_CONSTRAINT:
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
525 case DEFINE_ADDRESS_CONSTRAINT:
16
kono
parents: 14
diff changeset
526 queue_pattern (desc, &define_pred_tail, loc);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
527 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
528
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
529 case DEFINE_INSN_AND_SPLIT:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
530 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
531 const char *split_cond;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
532 rtx split;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
533 rtvec attr;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
534 int i;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
535 struct queue_elem *insn_elem;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
536 struct queue_elem *split_elem;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
537
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
538 /* Create a split with values from the insn_and_split. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
539 split = rtx_alloc (DEFINE_SPLIT);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
540
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
541 i = XVECLEN (desc, 1);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
542 XVEC (split, 0) = rtvec_alloc (i);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
543 while (--i >= 0)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
544 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
545 XVECEXP (split, 0, i) = copy_rtx (XVECEXP (desc, 1, i));
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
546 remove_constraints (XVECEXP (split, 0, i));
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
547 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
548
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
549 /* If the split condition starts with "&&", append it to the
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
550 insn condition to create the new split condition. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
551 split_cond = XSTR (desc, 4);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
552 if (split_cond[0] == '&' && split_cond[1] == '&')
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
553 {
16
kono
parents: 14
diff changeset
554 rtx_reader_ptr->copy_md_ptr_loc (split_cond + 2, split_cond);
kono
parents: 14
diff changeset
555 split_cond = rtx_reader_ptr->join_c_conditions (XSTR (desc, 2),
kono
parents: 14
diff changeset
556 split_cond + 2);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
557 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
558 XSTR (split, 1) = split_cond;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
559 XVEC (split, 2) = XVEC (desc, 5);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
560 XSTR (split, 3) = XSTR (desc, 6);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
561
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
562 /* Fix up the DEFINE_INSN. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
563 attr = XVEC (desc, 7);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
564 PUT_CODE (desc, DEFINE_INSN);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
565 XVEC (desc, 4) = attr;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
566
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
567 /* Queue them. */
16
kono
parents: 14
diff changeset
568 insn_elem = queue_pattern (desc, &define_insn_tail, loc);
kono
parents: 14
diff changeset
569 split_elem = queue_pattern (split, &other_tail, loc);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
570 insn_elem->split = split_elem;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
571 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
572 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
573
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
574 default:
16
kono
parents: 14
diff changeset
575 queue_pattern (desc, &other_tail, loc);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
576 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
577 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
578 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
579
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
580 /* Return true if attribute PREDICABLE is true for ELEM, which holds
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
581 a DEFINE_INSN. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
582
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
583 static int
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
584 is_predicable (struct queue_elem *elem)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
585 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
586 rtvec vec = XVEC (elem->data, 4);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
587 const char *value;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
588 int i;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
589
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
590 if (! vec)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
591 return predicable_default;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
592
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
593 for (i = GET_NUM_ELEM (vec) - 1; i >= 0; --i)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
594 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
595 rtx sub = RTVEC_ELT (vec, i);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
596 switch (GET_CODE (sub))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
597 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
598 case SET_ATTR:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
599 if (strcmp (XSTR (sub, 0), "predicable") == 0)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
600 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
601 value = XSTR (sub, 1);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
602 goto found;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
603 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
604 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
605
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
606 case SET_ATTR_ALTERNATIVE:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
607 if (strcmp (XSTR (sub, 0), "predicable") == 0)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
608 {
16
kono
parents: 14
diff changeset
609 error_at (elem->loc, "multiple alternatives for `predicable'");
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
610 return 0;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
611 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
612 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
613
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
614 case SET:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
615 if (GET_CODE (SET_DEST (sub)) != ATTR
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
616 || strcmp (XSTR (SET_DEST (sub), 0), "predicable") != 0)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
617 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
618 sub = SET_SRC (sub);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
619 if (GET_CODE (sub) == CONST_STRING)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
620 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
621 value = XSTR (sub, 0);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
622 goto found;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
623 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
624
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
625 /* ??? It would be possible to handle this if we really tried.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
626 It's not easy though, and I'm not going to bother until it
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
627 really proves necessary. */
16
kono
parents: 14
diff changeset
628 error_at (elem->loc, "non-constant value for `predicable'");
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
629 return 0;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
630
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
631 default:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
632 gcc_unreachable ();
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
633 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
634 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
635
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
636 return predicable_default;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
637
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
638 found:
16
kono
parents: 14
diff changeset
639 /* Find out which value we're looking at. Multiple alternatives means at
kono
parents: 14
diff changeset
640 least one is predicable. */
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
641 if (strchr (value, ',') != NULL)
16
kono
parents: 14
diff changeset
642 return 1;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
643 if (strcmp (value, predicable_true) == 0)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
644 return 1;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
645 if (strcmp (value, predicable_false) == 0)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
646 return 0;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
647
16
kono
parents: 14
diff changeset
648 error_at (elem->loc, "unknown value `%s' for `predicable' attribute", value);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
649 return 0;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
650 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
651
16
kono
parents: 14
diff changeset
652 /* Find attribute SUBST in ELEM and assign NEW_VALUE to it. */
kono
parents: 14
diff changeset
653 static void
kono
parents: 14
diff changeset
654 change_subst_attribute (struct queue_elem *elem,
kono
parents: 14
diff changeset
655 struct queue_elem *subst_elem,
kono
parents: 14
diff changeset
656 const char *new_value)
kono
parents: 14
diff changeset
657 {
kono
parents: 14
diff changeset
658 rtvec attrs_vec = XVEC (elem->data, 4);
kono
parents: 14
diff changeset
659 const char *subst_name = XSTR (subst_elem->data, 0);
kono
parents: 14
diff changeset
660 int i;
kono
parents: 14
diff changeset
661
kono
parents: 14
diff changeset
662 if (! attrs_vec)
kono
parents: 14
diff changeset
663 return;
kono
parents: 14
diff changeset
664
kono
parents: 14
diff changeset
665 for (i = GET_NUM_ELEM (attrs_vec) - 1; i >= 0; --i)
kono
parents: 14
diff changeset
666 {
kono
parents: 14
diff changeset
667 rtx cur_attr = RTVEC_ELT (attrs_vec, i);
kono
parents: 14
diff changeset
668 if (GET_CODE (cur_attr) != SET_ATTR)
kono
parents: 14
diff changeset
669 continue;
kono
parents: 14
diff changeset
670 if (strcmp (XSTR (cur_attr, 0), subst_name) == 0)
kono
parents: 14
diff changeset
671 {
kono
parents: 14
diff changeset
672 XSTR (cur_attr, 1) = new_value;
kono
parents: 14
diff changeset
673 return;
kono
parents: 14
diff changeset
674 }
kono
parents: 14
diff changeset
675 }
kono
parents: 14
diff changeset
676 }
kono
parents: 14
diff changeset
677
kono
parents: 14
diff changeset
678 /* Return true if ELEM has the attribute with the name of DEFINE_SUBST
kono
parents: 14
diff changeset
679 represented by SUBST_ELEM and this attribute has value SUBST_TRUE.
kono
parents: 14
diff changeset
680 DEFINE_SUBST isn't applied to patterns without such attribute. In other
kono
parents: 14
diff changeset
681 words, we suppose the default value of the attribute to be 'no' since it is
kono
parents: 14
diff changeset
682 always generated automatically in read-rtl.c. */
kono
parents: 14
diff changeset
683 static bool
kono
parents: 14
diff changeset
684 has_subst_attribute (struct queue_elem *elem, struct queue_elem *subst_elem)
kono
parents: 14
diff changeset
685 {
kono
parents: 14
diff changeset
686 rtvec attrs_vec = XVEC (elem->data, 4);
kono
parents: 14
diff changeset
687 const char *value, *subst_name = XSTR (subst_elem->data, 0);
kono
parents: 14
diff changeset
688 int i;
kono
parents: 14
diff changeset
689
kono
parents: 14
diff changeset
690 if (! attrs_vec)
kono
parents: 14
diff changeset
691 return false;
kono
parents: 14
diff changeset
692
kono
parents: 14
diff changeset
693 for (i = GET_NUM_ELEM (attrs_vec) - 1; i >= 0; --i)
kono
parents: 14
diff changeset
694 {
kono
parents: 14
diff changeset
695 rtx cur_attr = RTVEC_ELT (attrs_vec, i);
kono
parents: 14
diff changeset
696 switch (GET_CODE (cur_attr))
kono
parents: 14
diff changeset
697 {
kono
parents: 14
diff changeset
698 case SET_ATTR:
kono
parents: 14
diff changeset
699 if (strcmp (XSTR (cur_attr, 0), subst_name) == 0)
kono
parents: 14
diff changeset
700 {
kono
parents: 14
diff changeset
701 value = XSTR (cur_attr, 1);
kono
parents: 14
diff changeset
702 goto found;
kono
parents: 14
diff changeset
703 }
kono
parents: 14
diff changeset
704 break;
kono
parents: 14
diff changeset
705
kono
parents: 14
diff changeset
706 case SET:
kono
parents: 14
diff changeset
707 if (GET_CODE (SET_DEST (cur_attr)) != ATTR
kono
parents: 14
diff changeset
708 || strcmp (XSTR (SET_DEST (cur_attr), 0), subst_name) != 0)
kono
parents: 14
diff changeset
709 break;
kono
parents: 14
diff changeset
710 cur_attr = SET_SRC (cur_attr);
kono
parents: 14
diff changeset
711 if (GET_CODE (cur_attr) == CONST_STRING)
kono
parents: 14
diff changeset
712 {
kono
parents: 14
diff changeset
713 value = XSTR (cur_attr, 0);
kono
parents: 14
diff changeset
714 goto found;
kono
parents: 14
diff changeset
715 }
kono
parents: 14
diff changeset
716
kono
parents: 14
diff changeset
717 /* Only (set_attr "subst" "yes/no") and
kono
parents: 14
diff changeset
718 (set (attr "subst" (const_string "yes/no")))
kono
parents: 14
diff changeset
719 are currently allowed. */
kono
parents: 14
diff changeset
720 error_at (elem->loc, "unsupported value for `%s'", subst_name);
kono
parents: 14
diff changeset
721 return false;
kono
parents: 14
diff changeset
722
kono
parents: 14
diff changeset
723 case SET_ATTR_ALTERNATIVE:
kono
parents: 14
diff changeset
724 error_at (elem->loc,
kono
parents: 14
diff changeset
725 "%s: `set_attr_alternative' is unsupported by "
kono
parents: 14
diff changeset
726 "`define_subst'", XSTR (elem->data, 0));
kono
parents: 14
diff changeset
727 return false;
kono
parents: 14
diff changeset
728
kono
parents: 14
diff changeset
729
kono
parents: 14
diff changeset
730 default:
kono
parents: 14
diff changeset
731 gcc_unreachable ();
kono
parents: 14
diff changeset
732 }
kono
parents: 14
diff changeset
733 }
kono
parents: 14
diff changeset
734
kono
parents: 14
diff changeset
735 return false;
kono
parents: 14
diff changeset
736
kono
parents: 14
diff changeset
737 found:
kono
parents: 14
diff changeset
738 if (strcmp (value, subst_true) == 0)
kono
parents: 14
diff changeset
739 return true;
kono
parents: 14
diff changeset
740 if (strcmp (value, subst_false) == 0)
kono
parents: 14
diff changeset
741 return false;
kono
parents: 14
diff changeset
742
kono
parents: 14
diff changeset
743 error_at (elem->loc, "unknown value `%s' for `%s' attribute",
kono
parents: 14
diff changeset
744 value, subst_name);
kono
parents: 14
diff changeset
745 return false;
kono
parents: 14
diff changeset
746 }
kono
parents: 14
diff changeset
747
kono
parents: 14
diff changeset
748 /* Compare RTL-template of original define_insn X to input RTL-template of
kono
parents: 14
diff changeset
749 define_subst PT. Return 1 if the templates match, 0 otherwise.
kono
parents: 14
diff changeset
750 During the comparison, the routine also fills global_array OPERAND_DATA. */
kono
parents: 14
diff changeset
751 static bool
kono
parents: 14
diff changeset
752 subst_pattern_match (rtx x, rtx pt, file_location loc)
kono
parents: 14
diff changeset
753 {
kono
parents: 14
diff changeset
754 RTX_CODE code, code_pt;
kono
parents: 14
diff changeset
755 int i, j, len;
kono
parents: 14
diff changeset
756 const char *fmt, *pred_name;
kono
parents: 14
diff changeset
757
kono
parents: 14
diff changeset
758 code = GET_CODE (x);
kono
parents: 14
diff changeset
759 code_pt = GET_CODE (pt);
kono
parents: 14
diff changeset
760
kono
parents: 14
diff changeset
761 if (code_pt == MATCH_OPERAND)
kono
parents: 14
diff changeset
762 {
kono
parents: 14
diff changeset
763 /* MATCH_DUP, and MATCH_OP_DUP don't have a specified mode, so we
kono
parents: 14
diff changeset
764 always accept them. */
kono
parents: 14
diff changeset
765 if (GET_MODE (pt) != VOIDmode && GET_MODE (x) != GET_MODE (pt)
kono
parents: 14
diff changeset
766 && (code != MATCH_DUP && code != MATCH_OP_DUP))
kono
parents: 14
diff changeset
767 return false; /* Modes don't match. */
kono
parents: 14
diff changeset
768
kono
parents: 14
diff changeset
769 if (code == MATCH_OPERAND)
kono
parents: 14
diff changeset
770 {
kono
parents: 14
diff changeset
771 pred_name = XSTR (pt, 1);
kono
parents: 14
diff changeset
772 if (pred_name[0] != 0)
kono
parents: 14
diff changeset
773 {
kono
parents: 14
diff changeset
774 const struct pred_data *pred_pt = lookup_predicate (pred_name);
kono
parents: 14
diff changeset
775 if (!pred_pt || pred_pt != lookup_predicate (XSTR (x, 1)))
kono
parents: 14
diff changeset
776 return false; /* Predicates don't match. */
kono
parents: 14
diff changeset
777 }
kono
parents: 14
diff changeset
778 }
kono
parents: 14
diff changeset
779
kono
parents: 14
diff changeset
780 gcc_assert (XINT (pt, 0) >= 0 && XINT (pt, 0) < MAX_OPERANDS);
kono
parents: 14
diff changeset
781 operand_data[XINT (pt, 0)] = x;
kono
parents: 14
diff changeset
782 return true;
kono
parents: 14
diff changeset
783 }
kono
parents: 14
diff changeset
784
kono
parents: 14
diff changeset
785 if (code_pt == MATCH_OPERATOR)
kono
parents: 14
diff changeset
786 {
kono
parents: 14
diff changeset
787 int x_vecexp_pos = -1;
kono
parents: 14
diff changeset
788
kono
parents: 14
diff changeset
789 /* Compare modes. */
kono
parents: 14
diff changeset
790 if (GET_MODE (pt) != VOIDmode && GET_MODE (x) != GET_MODE (pt))
kono
parents: 14
diff changeset
791 return false;
kono
parents: 14
diff changeset
792
kono
parents: 14
diff changeset
793 /* In case X is also match_operator, compare predicates. */
kono
parents: 14
diff changeset
794 if (code == MATCH_OPERATOR)
kono
parents: 14
diff changeset
795 {
kono
parents: 14
diff changeset
796 pred_name = XSTR (pt, 1);
kono
parents: 14
diff changeset
797 if (pred_name[0] != 0)
kono
parents: 14
diff changeset
798 {
kono
parents: 14
diff changeset
799 const struct pred_data *pred_pt = lookup_predicate (pred_name);
kono
parents: 14
diff changeset
800 if (!pred_pt || pred_pt != lookup_predicate (XSTR (x, 1)))
kono
parents: 14
diff changeset
801 return false;
kono
parents: 14
diff changeset
802 }
kono
parents: 14
diff changeset
803 }
kono
parents: 14
diff changeset
804
kono
parents: 14
diff changeset
805 /* Compare operands.
kono
parents: 14
diff changeset
806 MATCH_OPERATOR in input template could match in original template
kono
parents: 14
diff changeset
807 either 1) MATCH_OPERAND, 2) UNSPEC, 3) ordinary operation (like PLUS).
kono
parents: 14
diff changeset
808 In the first case operands are at (XVECEXP (x, 2, j)), in the second
kono
parents: 14
diff changeset
809 - at (XVECEXP (x, 0, j)), in the last one - (XEXP (x, j)).
kono
parents: 14
diff changeset
810 X_VECEXP_POS variable shows, where to look for these operands. */
kono
parents: 14
diff changeset
811 if (code == UNSPEC
kono
parents: 14
diff changeset
812 || code == UNSPEC_VOLATILE)
kono
parents: 14
diff changeset
813 x_vecexp_pos = 0;
kono
parents: 14
diff changeset
814 else if (code == MATCH_OPERATOR)
kono
parents: 14
diff changeset
815 x_vecexp_pos = 2;
kono
parents: 14
diff changeset
816 else
kono
parents: 14
diff changeset
817 x_vecexp_pos = -1;
kono
parents: 14
diff changeset
818
kono
parents: 14
diff changeset
819 /* MATCH_OPERATOR or UNSPEC case. */
kono
parents: 14
diff changeset
820 if (x_vecexp_pos >= 0)
kono
parents: 14
diff changeset
821 {
kono
parents: 14
diff changeset
822 /* Compare operands number in X and PT. */
kono
parents: 14
diff changeset
823 if (XVECLEN (x, x_vecexp_pos) != XVECLEN (pt, 2))
kono
parents: 14
diff changeset
824 return false;
kono
parents: 14
diff changeset
825 for (j = 0; j < XVECLEN (pt, 2); j++)
kono
parents: 14
diff changeset
826 if (!subst_pattern_match (XVECEXP (x, x_vecexp_pos, j),
kono
parents: 14
diff changeset
827 XVECEXP (pt, 2, j), loc))
kono
parents: 14
diff changeset
828 return false;
kono
parents: 14
diff changeset
829 }
kono
parents: 14
diff changeset
830
kono
parents: 14
diff changeset
831 /* Ordinary operator. */
kono
parents: 14
diff changeset
832 else
kono
parents: 14
diff changeset
833 {
kono
parents: 14
diff changeset
834 /* Compare operands number in X and PT.
kono
parents: 14
diff changeset
835 We count operands differently for X and PT since we compare
kono
parents: 14
diff changeset
836 an operator (with operands directly in RTX) and MATCH_OPERATOR
kono
parents: 14
diff changeset
837 (that has a vector with operands). */
kono
parents: 14
diff changeset
838 if (GET_RTX_LENGTH (code) != XVECLEN (pt, 2))
kono
parents: 14
diff changeset
839 return false;
kono
parents: 14
diff changeset
840 for (j = 0; j < XVECLEN (pt, 2); j++)
kono
parents: 14
diff changeset
841 if (!subst_pattern_match (XEXP (x, j), XVECEXP (pt, 2, j), loc))
kono
parents: 14
diff changeset
842 return false;
kono
parents: 14
diff changeset
843 }
kono
parents: 14
diff changeset
844
kono
parents: 14
diff changeset
845 /* Store the operand to OPERAND_DATA array. */
kono
parents: 14
diff changeset
846 gcc_assert (XINT (pt, 0) >= 0 && XINT (pt, 0) < MAX_OPERANDS);
kono
parents: 14
diff changeset
847 operand_data[XINT (pt, 0)] = x;
kono
parents: 14
diff changeset
848 return true;
kono
parents: 14
diff changeset
849 }
kono
parents: 14
diff changeset
850
kono
parents: 14
diff changeset
851 if (code_pt == MATCH_PAR_DUP
kono
parents: 14
diff changeset
852 || code_pt == MATCH_DUP
kono
parents: 14
diff changeset
853 || code_pt == MATCH_OP_DUP
kono
parents: 14
diff changeset
854 || code_pt == MATCH_SCRATCH
kono
parents: 14
diff changeset
855 || code_pt == MATCH_PARALLEL)
kono
parents: 14
diff changeset
856 {
kono
parents: 14
diff changeset
857 /* Currently interface for these constructions isn't defined -
kono
parents: 14
diff changeset
858 probably they aren't needed in input template of define_subst at all.
kono
parents: 14
diff changeset
859 So, for now their usage in define_subst is forbidden. */
kono
parents: 14
diff changeset
860 error_at (loc, "%s cannot be used in define_subst",
kono
parents: 14
diff changeset
861 GET_RTX_NAME (code_pt));
kono
parents: 14
diff changeset
862 }
kono
parents: 14
diff changeset
863
kono
parents: 14
diff changeset
864 gcc_assert (code != MATCH_PAR_DUP
kono
parents: 14
diff changeset
865 && code_pt != MATCH_DUP
kono
parents: 14
diff changeset
866 && code_pt != MATCH_OP_DUP
kono
parents: 14
diff changeset
867 && code_pt != MATCH_SCRATCH
kono
parents: 14
diff changeset
868 && code_pt != MATCH_PARALLEL
kono
parents: 14
diff changeset
869 && code_pt != MATCH_OPERAND
kono
parents: 14
diff changeset
870 && code_pt != MATCH_OPERATOR);
kono
parents: 14
diff changeset
871 /* If PT is none of the handled above, then we match only expressions with
kono
parents: 14
diff changeset
872 the same code in X. */
kono
parents: 14
diff changeset
873 if (code != code_pt)
kono
parents: 14
diff changeset
874 return false;
kono
parents: 14
diff changeset
875
kono
parents: 14
diff changeset
876 fmt = GET_RTX_FORMAT (code_pt);
kono
parents: 14
diff changeset
877 len = GET_RTX_LENGTH (code_pt);
kono
parents: 14
diff changeset
878
kono
parents: 14
diff changeset
879 for (i = 0; i < len; i++)
kono
parents: 14
diff changeset
880 {
kono
parents: 14
diff changeset
881 if (fmt[i] == '0')
kono
parents: 14
diff changeset
882 break;
kono
parents: 14
diff changeset
883
kono
parents: 14
diff changeset
884 switch (fmt[i])
kono
parents: 14
diff changeset
885 {
kono
parents: 14
diff changeset
886 case 'i': case 'r': case 'w': case 's':
kono
parents: 14
diff changeset
887 continue;
kono
parents: 14
diff changeset
888
kono
parents: 14
diff changeset
889 case 'e': case 'u':
kono
parents: 14
diff changeset
890 if (!subst_pattern_match (XEXP (x, i), XEXP (pt, i), loc))
kono
parents: 14
diff changeset
891 return false;
kono
parents: 14
diff changeset
892 break;
kono
parents: 14
diff changeset
893 case 'E':
kono
parents: 14
diff changeset
894 {
kono
parents: 14
diff changeset
895 if (XVECLEN (x, i) != XVECLEN (pt, i))
kono
parents: 14
diff changeset
896 return false;
kono
parents: 14
diff changeset
897 for (j = 0; j < XVECLEN (pt, i); j++)
kono
parents: 14
diff changeset
898 if (!subst_pattern_match (XVECEXP (x, i, j),
kono
parents: 14
diff changeset
899 XVECEXP (pt, i, j), loc))
kono
parents: 14
diff changeset
900 return false;
kono
parents: 14
diff changeset
901 break;
kono
parents: 14
diff changeset
902 }
kono
parents: 14
diff changeset
903 default:
kono
parents: 14
diff changeset
904 gcc_unreachable ();
kono
parents: 14
diff changeset
905 }
kono
parents: 14
diff changeset
906 }
kono
parents: 14
diff changeset
907
kono
parents: 14
diff changeset
908 return true;
kono
parents: 14
diff changeset
909 }
kono
parents: 14
diff changeset
910
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
911 /* Examine the attribute "predicable"; discover its boolean values
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
912 and its default. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
913
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
914 static void
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
915 identify_predicable_attribute (void)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
916 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
917 struct queue_elem *elem;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
918 char *p_true, *p_false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
919 const char *value;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
920
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
921 /* Look for the DEFINE_ATTR for `predicable', which must exist. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
922 for (elem = define_attr_queue; elem ; elem = elem->next)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
923 if (strcmp (XSTR (elem->data, 0), "predicable") == 0)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
924 goto found;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
925
16
kono
parents: 14
diff changeset
926 error_at (define_cond_exec_queue->loc,
kono
parents: 14
diff changeset
927 "attribute `predicable' not defined");
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
928 return;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
929
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
930 found:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
931 value = XSTR (elem->data, 1);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
932 p_false = xstrdup (value);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
933 p_true = strchr (p_false, ',');
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
934 if (p_true == NULL || strchr (++p_true, ',') != NULL)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
935 {
16
kono
parents: 14
diff changeset
936 error_at (elem->loc, "attribute `predicable' is not a boolean");
kono
parents: 14
diff changeset
937 free (p_false);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
938 return;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
939 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
940 p_true[-1] = '\0';
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
941
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
942 predicable_true = p_true;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
943 predicable_false = p_false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
944
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
945 switch (GET_CODE (XEXP (elem->data, 2)))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
946 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
947 case CONST_STRING:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
948 value = XSTR (XEXP (elem->data, 2), 0);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
949 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
950
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
951 case CONST:
16
kono
parents: 14
diff changeset
952 error_at (elem->loc, "attribute `predicable' cannot be const");
kono
parents: 14
diff changeset
953 free (p_false);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
954 return;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
955
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
956 default:
16
kono
parents: 14
diff changeset
957 error_at (elem->loc,
kono
parents: 14
diff changeset
958 "attribute `predicable' must have a constant default");
kono
parents: 14
diff changeset
959 free (p_false);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
960 return;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
961 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
962
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
963 if (strcmp (value, p_true) == 0)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
964 predicable_default = 1;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
965 else if (strcmp (value, p_false) == 0)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
966 predicable_default = 0;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
967 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
968 {
16
kono
parents: 14
diff changeset
969 error_at (elem->loc, "unknown value `%s' for `predicable' attribute",
kono
parents: 14
diff changeset
970 value);
kono
parents: 14
diff changeset
971 free (p_false);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
972 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
973 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
974
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
975 /* Return the number of alternatives in constraint S. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
976
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
977 static int
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
978 n_alternatives (const char *s)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
979 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
980 int n = 1;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
981
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
982 if (s)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
983 while (*s)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
984 n += (*s++ == ',');
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
985
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
986 return n;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
987 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
988
16
kono
parents: 14
diff changeset
989 /* The routine scans rtl PATTERN, find match_operand in it and counts
kono
parents: 14
diff changeset
990 number of alternatives. If PATTERN contains several match_operands
kono
parents: 14
diff changeset
991 with different number of alternatives, error is emitted, and the
kono
parents: 14
diff changeset
992 routine returns 0. If all match_operands in PATTERN have the same
kono
parents: 14
diff changeset
993 number of alternatives, it's stored in N_ALT, and the routine returns 1.
kono
parents: 14
diff changeset
994 LOC is the location of PATTERN, for error reporting. */
kono
parents: 14
diff changeset
995 static int
kono
parents: 14
diff changeset
996 get_alternatives_number (rtx pattern, int *n_alt, file_location loc)
kono
parents: 14
diff changeset
997 {
kono
parents: 14
diff changeset
998 const char *fmt;
kono
parents: 14
diff changeset
999 enum rtx_code code;
kono
parents: 14
diff changeset
1000 int i, j, len;
kono
parents: 14
diff changeset
1001
kono
parents: 14
diff changeset
1002 if (!n_alt)
kono
parents: 14
diff changeset
1003 return 0;
kono
parents: 14
diff changeset
1004
kono
parents: 14
diff changeset
1005 code = GET_CODE (pattern);
kono
parents: 14
diff changeset
1006 switch (code)
kono
parents: 14
diff changeset
1007 {
kono
parents: 14
diff changeset
1008 case MATCH_OPERAND:
kono
parents: 14
diff changeset
1009 i = n_alternatives (XSTR (pattern, 2));
kono
parents: 14
diff changeset
1010 /* n_alternatives returns 1 if constraint string is empty -
kono
parents: 14
diff changeset
1011 here we fix it up. */
kono
parents: 14
diff changeset
1012 if (!*(XSTR (pattern, 2)))
kono
parents: 14
diff changeset
1013 i = 0;
kono
parents: 14
diff changeset
1014 if (*n_alt <= 0)
kono
parents: 14
diff changeset
1015 *n_alt = i;
kono
parents: 14
diff changeset
1016
kono
parents: 14
diff changeset
1017 else if (i && i != *n_alt)
kono
parents: 14
diff changeset
1018 {
kono
parents: 14
diff changeset
1019 error_at (loc, "wrong number of alternatives in operand %d",
kono
parents: 14
diff changeset
1020 XINT (pattern, 0));
kono
parents: 14
diff changeset
1021 return 0;
kono
parents: 14
diff changeset
1022 }
kono
parents: 14
diff changeset
1023
kono
parents: 14
diff changeset
1024 default:
kono
parents: 14
diff changeset
1025 break;
kono
parents: 14
diff changeset
1026 }
kono
parents: 14
diff changeset
1027
kono
parents: 14
diff changeset
1028 fmt = GET_RTX_FORMAT (code);
kono
parents: 14
diff changeset
1029 len = GET_RTX_LENGTH (code);
kono
parents: 14
diff changeset
1030 for (i = 0; i < len; i++)
kono
parents: 14
diff changeset
1031 {
kono
parents: 14
diff changeset
1032 switch (fmt[i])
kono
parents: 14
diff changeset
1033 {
kono
parents: 14
diff changeset
1034 case 'e': case 'u':
kono
parents: 14
diff changeset
1035 if (!get_alternatives_number (XEXP (pattern, i), n_alt, loc))
kono
parents: 14
diff changeset
1036 return 0;
kono
parents: 14
diff changeset
1037 break;
kono
parents: 14
diff changeset
1038
kono
parents: 14
diff changeset
1039 case 'V':
kono
parents: 14
diff changeset
1040 if (XVEC (pattern, i) == NULL)
kono
parents: 14
diff changeset
1041 break;
kono
parents: 14
diff changeset
1042 /* FALLTHRU */
kono
parents: 14
diff changeset
1043
kono
parents: 14
diff changeset
1044 case 'E':
kono
parents: 14
diff changeset
1045 for (j = XVECLEN (pattern, i) - 1; j >= 0; --j)
kono
parents: 14
diff changeset
1046 if (!get_alternatives_number (XVECEXP (pattern, i, j), n_alt, loc))
kono
parents: 14
diff changeset
1047 return 0;
kono
parents: 14
diff changeset
1048 break;
kono
parents: 14
diff changeset
1049
kono
parents: 14
diff changeset
1050 case 'i': case 'r': case 'w': case '0': case 's': case 'S': case 'T':
kono
parents: 14
diff changeset
1051 break;
kono
parents: 14
diff changeset
1052
kono
parents: 14
diff changeset
1053 default:
kono
parents: 14
diff changeset
1054 gcc_unreachable ();
kono
parents: 14
diff changeset
1055 }
kono
parents: 14
diff changeset
1056 }
kono
parents: 14
diff changeset
1057 return 1;
kono
parents: 14
diff changeset
1058 }
kono
parents: 14
diff changeset
1059
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1060 /* Determine how many alternatives there are in INSN, and how many
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1061 operands. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1062
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1063 static void
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1064 collect_insn_data (rtx pattern, int *palt, int *pmax)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1065 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1066 const char *fmt;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1067 enum rtx_code code;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1068 int i, j, len;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1069
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1070 code = GET_CODE (pattern);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1071 switch (code)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1072 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1073 case MATCH_OPERAND:
16
kono
parents: 14
diff changeset
1074 case MATCH_SCRATCH:
kono
parents: 14
diff changeset
1075 i = n_alternatives (XSTR (pattern, code == MATCH_SCRATCH ? 1 : 2));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1076 *palt = (i > *palt ? i : *palt);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1077 /* Fall through. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1078
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1079 case MATCH_OPERATOR:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1080 case MATCH_PARALLEL:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1081 i = XINT (pattern, 0);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1082 if (i > *pmax)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1083 *pmax = i;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1084 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1085
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1086 default:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1087 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1088 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1089
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1090 fmt = GET_RTX_FORMAT (code);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1091 len = GET_RTX_LENGTH (code);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1092 for (i = 0; i < len; i++)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1093 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1094 switch (fmt[i])
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1095 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1096 case 'e': case 'u':
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1097 collect_insn_data (XEXP (pattern, i), palt, pmax);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1098 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1099
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1100 case 'V':
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1101 if (XVEC (pattern, i) == NULL)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1102 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1103 /* Fall through. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1104 case 'E':
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1105 for (j = XVECLEN (pattern, i) - 1; j >= 0; --j)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1106 collect_insn_data (XVECEXP (pattern, i, j), palt, pmax);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1107 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1108
16
kono
parents: 14
diff changeset
1109 case 'i': case 'r': case 'w': case '0': case 's': case 'S': case 'T':
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1110 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1111
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1112 default:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1113 gcc_unreachable ();
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1114 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1115 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1116 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1117
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1118 static rtx
16
kono
parents: 14
diff changeset
1119 alter_predicate_for_insn (rtx pattern, int alt, int max_op,
kono
parents: 14
diff changeset
1120 file_location loc)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1121 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1122 const char *fmt;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1123 enum rtx_code code;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1124 int i, j, len;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1125
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1126 code = GET_CODE (pattern);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1127 switch (code)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1128 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1129 case MATCH_OPERAND:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1130 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1131 const char *c = XSTR (pattern, 2);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1132
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1133 if (n_alternatives (c) != 1)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1134 {
16
kono
parents: 14
diff changeset
1135 error_at (loc, "too many alternatives for operand %d",
kono
parents: 14
diff changeset
1136 XINT (pattern, 0));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1137 return NULL;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1138 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1139
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1140 /* Replicate C as needed to fill out ALT alternatives. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1141 if (c && *c && alt > 1)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1142 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1143 size_t c_len = strlen (c);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1144 size_t len = alt * (c_len + 1);
16
kono
parents: 14
diff changeset
1145 char *new_c = XNEWVEC (char, len);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1146
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1147 memcpy (new_c, c, c_len);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1148 for (i = 1; i < alt; ++i)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1149 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1150 new_c[i * (c_len + 1) - 1] = ',';
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1151 memcpy (&new_c[i * (c_len + 1)], c, c_len);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1152 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1153 new_c[len - 1] = '\0';
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1154 XSTR (pattern, 2) = new_c;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1155 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1156 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1157 /* Fall through. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1158
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1159 case MATCH_OPERATOR:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1160 case MATCH_SCRATCH:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1161 case MATCH_PARALLEL:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1162 XINT (pattern, 0) += max_op;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1163 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1164
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1165 default:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1166 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1167 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1168
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1169 fmt = GET_RTX_FORMAT (code);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1170 len = GET_RTX_LENGTH (code);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1171 for (i = 0; i < len; i++)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1172 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1173 rtx r;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1174
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1175 switch (fmt[i])
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1176 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1177 case 'e': case 'u':
16
kono
parents: 14
diff changeset
1178 r = alter_predicate_for_insn (XEXP (pattern, i), alt, max_op, loc);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1179 if (r == NULL)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1180 return r;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1181 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1182
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1183 case 'E':
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1184 for (j = XVECLEN (pattern, i) - 1; j >= 0; --j)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1185 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1186 r = alter_predicate_for_insn (XVECEXP (pattern, i, j),
16
kono
parents: 14
diff changeset
1187 alt, max_op, loc);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1188 if (r == NULL)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1189 return r;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1190 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1191 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1192
16
kono
parents: 14
diff changeset
1193 case 'i': case 'r': case 'w': case '0': case 's':
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1194 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1195
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1196 default:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1197 gcc_unreachable ();
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1198 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1199 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1200
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1201 return pattern;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1202 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1203
16
kono
parents: 14
diff changeset
1204 /* Duplicate constraints in PATTERN. If pattern is from original
kono
parents: 14
diff changeset
1205 rtl-template, we need to duplicate each alternative - for that we
kono
parents: 14
diff changeset
1206 need to use duplicate_each_alternative () as a functor ALTER.
kono
parents: 14
diff changeset
1207 If pattern is from output-pattern of define_subst, we need to
kono
parents: 14
diff changeset
1208 duplicate constraints in another way - with duplicate_alternatives ().
kono
parents: 14
diff changeset
1209 N_DUP is multiplication factor. */
kono
parents: 14
diff changeset
1210 static rtx
kono
parents: 14
diff changeset
1211 alter_constraints (rtx pattern, int n_dup, constraints_handler_t alter)
kono
parents: 14
diff changeset
1212 {
kono
parents: 14
diff changeset
1213 const char *fmt;
kono
parents: 14
diff changeset
1214 enum rtx_code code;
kono
parents: 14
diff changeset
1215 int i, j, len;
kono
parents: 14
diff changeset
1216
kono
parents: 14
diff changeset
1217 code = GET_CODE (pattern);
kono
parents: 14
diff changeset
1218 switch (code)
kono
parents: 14
diff changeset
1219 {
kono
parents: 14
diff changeset
1220 case MATCH_OPERAND:
kono
parents: 14
diff changeset
1221 XSTR (pattern, 2) = alter (XSTR (pattern, 2), n_dup);
kono
parents: 14
diff changeset
1222 break;
kono
parents: 14
diff changeset
1223
kono
parents: 14
diff changeset
1224 default:
kono
parents: 14
diff changeset
1225 break;
kono
parents: 14
diff changeset
1226 }
kono
parents: 14
diff changeset
1227
kono
parents: 14
diff changeset
1228 fmt = GET_RTX_FORMAT (code);
kono
parents: 14
diff changeset
1229 len = GET_RTX_LENGTH (code);
kono
parents: 14
diff changeset
1230 for (i = 0; i < len; i++)
kono
parents: 14
diff changeset
1231 {
kono
parents: 14
diff changeset
1232 rtx r;
kono
parents: 14
diff changeset
1233
kono
parents: 14
diff changeset
1234 switch (fmt[i])
kono
parents: 14
diff changeset
1235 {
kono
parents: 14
diff changeset
1236 case 'e': case 'u':
kono
parents: 14
diff changeset
1237 r = alter_constraints (XEXP (pattern, i), n_dup, alter);
kono
parents: 14
diff changeset
1238 if (r == NULL)
kono
parents: 14
diff changeset
1239 return r;
kono
parents: 14
diff changeset
1240 break;
kono
parents: 14
diff changeset
1241
kono
parents: 14
diff changeset
1242 case 'E':
kono
parents: 14
diff changeset
1243 for (j = XVECLEN (pattern, i) - 1; j >= 0; --j)
kono
parents: 14
diff changeset
1244 {
kono
parents: 14
diff changeset
1245 r = alter_constraints (XVECEXP (pattern, i, j), n_dup, alter);
kono
parents: 14
diff changeset
1246 if (r == NULL)
kono
parents: 14
diff changeset
1247 return r;
kono
parents: 14
diff changeset
1248 }
kono
parents: 14
diff changeset
1249 break;
kono
parents: 14
diff changeset
1250
kono
parents: 14
diff changeset
1251 case 'i': case 'r': case 'w': case '0': case 's':
kono
parents: 14
diff changeset
1252 break;
kono
parents: 14
diff changeset
1253
kono
parents: 14
diff changeset
1254 default:
kono
parents: 14
diff changeset
1255 break;
kono
parents: 14
diff changeset
1256 }
kono
parents: 14
diff changeset
1257 }
kono
parents: 14
diff changeset
1258
kono
parents: 14
diff changeset
1259 return pattern;
kono
parents: 14
diff changeset
1260 }
kono
parents: 14
diff changeset
1261
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1262 static const char *
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1263 alter_test_for_insn (struct queue_elem *ce_elem,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1264 struct queue_elem *insn_elem)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1265 {
16
kono
parents: 14
diff changeset
1266 return rtx_reader_ptr->join_c_conditions (XSTR (ce_elem->data, 1),
kono
parents: 14
diff changeset
1267 XSTR (insn_elem->data, 2));
kono
parents: 14
diff changeset
1268 }
kono
parents: 14
diff changeset
1269
kono
parents: 14
diff changeset
1270 /* Modify VAL, which is an attribute expression for the "enabled" attribute,
kono
parents: 14
diff changeset
1271 to take "ce_enabled" into account. Return the new expression. */
kono
parents: 14
diff changeset
1272 static rtx
kono
parents: 14
diff changeset
1273 modify_attr_enabled_ce (rtx val)
kono
parents: 14
diff changeset
1274 {
kono
parents: 14
diff changeset
1275 rtx eq_attr, str;
kono
parents: 14
diff changeset
1276 rtx ite;
kono
parents: 14
diff changeset
1277 eq_attr = rtx_alloc (EQ_ATTR);
kono
parents: 14
diff changeset
1278 ite = rtx_alloc (IF_THEN_ELSE);
kono
parents: 14
diff changeset
1279 str = rtx_alloc (CONST_STRING);
kono
parents: 14
diff changeset
1280
kono
parents: 14
diff changeset
1281 XSTR (eq_attr, 0) = "ce_enabled";
kono
parents: 14
diff changeset
1282 XSTR (eq_attr, 1) = "yes";
kono
parents: 14
diff changeset
1283 XSTR (str, 0) = "no";
kono
parents: 14
diff changeset
1284 XEXP (ite, 0) = eq_attr;
kono
parents: 14
diff changeset
1285 XEXP (ite, 1) = val;
kono
parents: 14
diff changeset
1286 XEXP (ite, 2) = str;
kono
parents: 14
diff changeset
1287
kono
parents: 14
diff changeset
1288 return ite;
kono
parents: 14
diff changeset
1289 }
kono
parents: 14
diff changeset
1290
kono
parents: 14
diff changeset
1291 /* Alter the attribute vector of INSN, which is a COND_EXEC variant created
kono
parents: 14
diff changeset
1292 from a define_insn pattern. We must modify the "predicable" attribute
kono
parents: 14
diff changeset
1293 to be named "ce_enabled", and also change any "enabled" attribute that's
kono
parents: 14
diff changeset
1294 present so that it takes ce_enabled into account.
kono
parents: 14
diff changeset
1295 We rely on the fact that INSN was created with copy_rtx, and modify data
kono
parents: 14
diff changeset
1296 in-place. */
kono
parents: 14
diff changeset
1297
kono
parents: 14
diff changeset
1298 static void
kono
parents: 14
diff changeset
1299 alter_attrs_for_insn (rtx insn)
kono
parents: 14
diff changeset
1300 {
kono
parents: 14
diff changeset
1301 static bool global_changes_made = false;
kono
parents: 14
diff changeset
1302 rtvec vec = XVEC (insn, 4);
kono
parents: 14
diff changeset
1303 rtvec new_vec;
kono
parents: 14
diff changeset
1304 rtx val, set;
kono
parents: 14
diff changeset
1305 int num_elem;
kono
parents: 14
diff changeset
1306 int predicable_idx = -1;
kono
parents: 14
diff changeset
1307 int enabled_idx = -1;
kono
parents: 14
diff changeset
1308 int i;
kono
parents: 14
diff changeset
1309
kono
parents: 14
diff changeset
1310 if (! vec)
kono
parents: 14
diff changeset
1311 return;
kono
parents: 14
diff changeset
1312
kono
parents: 14
diff changeset
1313 num_elem = GET_NUM_ELEM (vec);
kono
parents: 14
diff changeset
1314 for (i = num_elem - 1; i >= 0; --i)
kono
parents: 14
diff changeset
1315 {
kono
parents: 14
diff changeset
1316 rtx sub = RTVEC_ELT (vec, i);
kono
parents: 14
diff changeset
1317 switch (GET_CODE (sub))
kono
parents: 14
diff changeset
1318 {
kono
parents: 14
diff changeset
1319 case SET_ATTR:
kono
parents: 14
diff changeset
1320 if (strcmp (XSTR (sub, 0), "predicable") == 0)
kono
parents: 14
diff changeset
1321 {
kono
parents: 14
diff changeset
1322 predicable_idx = i;
kono
parents: 14
diff changeset
1323 XSTR (sub, 0) = "ce_enabled";
kono
parents: 14
diff changeset
1324 }
kono
parents: 14
diff changeset
1325 else if (strcmp (XSTR (sub, 0), "enabled") == 0)
kono
parents: 14
diff changeset
1326 {
kono
parents: 14
diff changeset
1327 enabled_idx = i;
kono
parents: 14
diff changeset
1328 XSTR (sub, 0) = "nonce_enabled";
kono
parents: 14
diff changeset
1329 }
kono
parents: 14
diff changeset
1330 break;
kono
parents: 14
diff changeset
1331
kono
parents: 14
diff changeset
1332 case SET_ATTR_ALTERNATIVE:
kono
parents: 14
diff changeset
1333 if (strcmp (XSTR (sub, 0), "predicable") == 0)
kono
parents: 14
diff changeset
1334 /* We already give an error elsewhere. */
kono
parents: 14
diff changeset
1335 return;
kono
parents: 14
diff changeset
1336 else if (strcmp (XSTR (sub, 0), "enabled") == 0)
kono
parents: 14
diff changeset
1337 {
kono
parents: 14
diff changeset
1338 enabled_idx = i;
kono
parents: 14
diff changeset
1339 XSTR (sub, 0) = "nonce_enabled";
kono
parents: 14
diff changeset
1340 }
kono
parents: 14
diff changeset
1341 break;
kono
parents: 14
diff changeset
1342
kono
parents: 14
diff changeset
1343 case SET:
kono
parents: 14
diff changeset
1344 if (GET_CODE (SET_DEST (sub)) != ATTR)
kono
parents: 14
diff changeset
1345 break;
kono
parents: 14
diff changeset
1346 if (strcmp (XSTR (SET_DEST (sub), 0), "predicable") == 0)
kono
parents: 14
diff changeset
1347 {
kono
parents: 14
diff changeset
1348 sub = SET_SRC (sub);
kono
parents: 14
diff changeset
1349 if (GET_CODE (sub) == CONST_STRING)
kono
parents: 14
diff changeset
1350 {
kono
parents: 14
diff changeset
1351 predicable_idx = i;
kono
parents: 14
diff changeset
1352 XSTR (sub, 0) = "ce_enabled";
kono
parents: 14
diff changeset
1353 }
kono
parents: 14
diff changeset
1354 else
kono
parents: 14
diff changeset
1355 /* We already give an error elsewhere. */
kono
parents: 14
diff changeset
1356 return;
kono
parents: 14
diff changeset
1357 break;
kono
parents: 14
diff changeset
1358 }
kono
parents: 14
diff changeset
1359 if (strcmp (XSTR (SET_DEST (sub), 0), "enabled") == 0)
kono
parents: 14
diff changeset
1360 {
kono
parents: 14
diff changeset
1361 enabled_idx = i;
kono
parents: 14
diff changeset
1362 XSTR (SET_DEST (sub), 0) = "nonce_enabled";
kono
parents: 14
diff changeset
1363 }
kono
parents: 14
diff changeset
1364 break;
kono
parents: 14
diff changeset
1365
kono
parents: 14
diff changeset
1366 default:
kono
parents: 14
diff changeset
1367 gcc_unreachable ();
kono
parents: 14
diff changeset
1368 }
kono
parents: 14
diff changeset
1369 }
kono
parents: 14
diff changeset
1370 if (predicable_idx == -1)
kono
parents: 14
diff changeset
1371 return;
kono
parents: 14
diff changeset
1372
kono
parents: 14
diff changeset
1373 if (!global_changes_made)
kono
parents: 14
diff changeset
1374 {
kono
parents: 14
diff changeset
1375 struct queue_elem *elem;
kono
parents: 14
diff changeset
1376
kono
parents: 14
diff changeset
1377 global_changes_made = true;
kono
parents: 14
diff changeset
1378 add_define_attr ("ce_enabled");
kono
parents: 14
diff changeset
1379 add_define_attr ("nonce_enabled");
kono
parents: 14
diff changeset
1380
kono
parents: 14
diff changeset
1381 for (elem = define_attr_queue; elem ; elem = elem->next)
kono
parents: 14
diff changeset
1382 if (strcmp (XSTR (elem->data, 0), "enabled") == 0)
kono
parents: 14
diff changeset
1383 {
kono
parents: 14
diff changeset
1384 XEXP (elem->data, 2)
kono
parents: 14
diff changeset
1385 = modify_attr_enabled_ce (XEXP (elem->data, 2));
kono
parents: 14
diff changeset
1386 }
kono
parents: 14
diff changeset
1387 }
kono
parents: 14
diff changeset
1388 if (enabled_idx == -1)
kono
parents: 14
diff changeset
1389 return;
kono
parents: 14
diff changeset
1390
kono
parents: 14
diff changeset
1391 new_vec = rtvec_alloc (num_elem + 1);
kono
parents: 14
diff changeset
1392 for (i = 0; i < num_elem; i++)
kono
parents: 14
diff changeset
1393 RTVEC_ELT (new_vec, i) = RTVEC_ELT (vec, i);
kono
parents: 14
diff changeset
1394 val = rtx_alloc (IF_THEN_ELSE);
kono
parents: 14
diff changeset
1395 XEXP (val, 0) = rtx_alloc (EQ_ATTR);
kono
parents: 14
diff changeset
1396 XEXP (val, 1) = rtx_alloc (CONST_STRING);
kono
parents: 14
diff changeset
1397 XEXP (val, 2) = rtx_alloc (CONST_STRING);
kono
parents: 14
diff changeset
1398 XSTR (XEXP (val, 0), 0) = "nonce_enabled";
kono
parents: 14
diff changeset
1399 XSTR (XEXP (val, 0), 1) = "yes";
kono
parents: 14
diff changeset
1400 XSTR (XEXP (val, 1), 0) = "yes";
kono
parents: 14
diff changeset
1401 XSTR (XEXP (val, 2), 0) = "no";
kono
parents: 14
diff changeset
1402 set = rtx_alloc (SET);
kono
parents: 14
diff changeset
1403 SET_DEST (set) = rtx_alloc (ATTR);
kono
parents: 14
diff changeset
1404 XSTR (SET_DEST (set), 0) = "enabled";
kono
parents: 14
diff changeset
1405 SET_SRC (set) = modify_attr_enabled_ce (val);
kono
parents: 14
diff changeset
1406 RTVEC_ELT (new_vec, i) = set;
kono
parents: 14
diff changeset
1407 XVEC (insn, 4) = new_vec;
kono
parents: 14
diff changeset
1408 }
kono
parents: 14
diff changeset
1409
kono
parents: 14
diff changeset
1410 /* As number of constraints is changed after define_subst, we need to
kono
parents: 14
diff changeset
1411 process attributes as well - we need to duplicate them the same way
kono
parents: 14
diff changeset
1412 that we duplicated constraints in original pattern
kono
parents: 14
diff changeset
1413 ELEM is a queue element, containing our rtl-template,
kono
parents: 14
diff changeset
1414 N_DUP - multiplication factor. */
kono
parents: 14
diff changeset
1415 static void
kono
parents: 14
diff changeset
1416 alter_attrs_for_subst_insn (struct queue_elem * elem, int n_dup)
kono
parents: 14
diff changeset
1417 {
kono
parents: 14
diff changeset
1418 rtvec vec = XVEC (elem->data, 4);
kono
parents: 14
diff changeset
1419 int num_elem;
kono
parents: 14
diff changeset
1420 int i;
kono
parents: 14
diff changeset
1421
kono
parents: 14
diff changeset
1422 if (n_dup < 2 || ! vec)
kono
parents: 14
diff changeset
1423 return;
kono
parents: 14
diff changeset
1424
kono
parents: 14
diff changeset
1425 num_elem = GET_NUM_ELEM (vec);
kono
parents: 14
diff changeset
1426 for (i = num_elem - 1; i >= 0; --i)
kono
parents: 14
diff changeset
1427 {
kono
parents: 14
diff changeset
1428 rtx sub = RTVEC_ELT (vec, i);
kono
parents: 14
diff changeset
1429 switch (GET_CODE (sub))
kono
parents: 14
diff changeset
1430 {
kono
parents: 14
diff changeset
1431 case SET_ATTR:
kono
parents: 14
diff changeset
1432 if (strchr (XSTR (sub, 1), ',') != NULL)
kono
parents: 14
diff changeset
1433 XSTR (sub, 1) = duplicate_alternatives (XSTR (sub, 1), n_dup);
kono
parents: 14
diff changeset
1434 break;
kono
parents: 14
diff changeset
1435
kono
parents: 14
diff changeset
1436 case SET_ATTR_ALTERNATIVE:
kono
parents: 14
diff changeset
1437 case SET:
kono
parents: 14
diff changeset
1438 error_at (elem->loc,
kono
parents: 14
diff changeset
1439 "%s: `define_subst' does not support attributes "
kono
parents: 14
diff changeset
1440 "assigned by `set' and `set_attr_alternative'",
kono
parents: 14
diff changeset
1441 XSTR (elem->data, 0));
kono
parents: 14
diff changeset
1442 return;
kono
parents: 14
diff changeset
1443
kono
parents: 14
diff changeset
1444 default:
kono
parents: 14
diff changeset
1445 gcc_unreachable ();
kono
parents: 14
diff changeset
1446 }
kono
parents: 14
diff changeset
1447 }
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1448 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1449
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1450 /* Adjust all of the operand numbers in SRC to match the shift they'll
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1451 get from an operand displacement of DISP. Return a pointer after the
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1452 adjusted string. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1453
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1454 static char *
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1455 shift_output_template (char *dest, const char *src, int disp)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1456 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1457 while (*src)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1458 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1459 char c = *src++;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1460 *dest++ = c;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1461 if (c == '%')
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1462 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1463 c = *src++;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1464 if (ISDIGIT ((unsigned char) c))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1465 c += disp;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1466 else if (ISALPHA (c))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1467 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1468 *dest++ = c;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1469 c = *src++ + disp;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1470 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1471 *dest++ = c;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1472 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1473 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1474
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1475 return dest;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1476 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1477
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1478 static const char *
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1479 alter_output_for_insn (struct queue_elem *ce_elem,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1480 struct queue_elem *insn_elem,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1481 int alt, int max_op)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1482 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1483 const char *ce_out, *insn_out;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1484 char *result, *p;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1485 size_t len, ce_len, insn_len;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1486
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1487 /* ??? Could coordinate with genoutput to not duplicate code here. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1488
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1489 ce_out = XSTR (ce_elem->data, 2);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1490 insn_out = XTMPL (insn_elem->data, 3);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1491 if (!ce_out || *ce_out == '\0')
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1492 return insn_out;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1493
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1494 ce_len = strlen (ce_out);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1495 insn_len = strlen (insn_out);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1496
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1497 if (*insn_out == '*')
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1498 /* You must take care of the predicate yourself. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1499 return insn_out;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1500
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1501 if (*insn_out == '@')
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1502 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1503 len = (ce_len + 1) * alt + insn_len + 1;
16
kono
parents: 14
diff changeset
1504 p = result = XNEWVEC (char, len);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1505
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1506 do
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1507 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1508 do
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1509 *p++ = *insn_out++;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1510 while (ISSPACE ((unsigned char) *insn_out));
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1511
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1512 if (*insn_out != '#')
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1513 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1514 p = shift_output_template (p, ce_out, max_op);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1515 *p++ = ' ';
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1516 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1517
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1518 do
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1519 *p++ = *insn_out++;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1520 while (*insn_out && *insn_out != '\n');
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1521 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1522 while (*insn_out);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1523 *p = '\0';
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1524 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1525 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1526 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1527 len = ce_len + 1 + insn_len + 1;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1528 result = XNEWVEC (char, len);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1529
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1530 p = shift_output_template (result, ce_out, max_op);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1531 *p++ = ' ';
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1532 memcpy (p, insn_out, insn_len + 1);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1533 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1534
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1535 return result;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1536 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1537
16
kono
parents: 14
diff changeset
1538 /* From string STR "a,b,c" produce "a,b,c,a,b,c,a,b,c", i.e. original
kono
parents: 14
diff changeset
1539 string, duplicated N_DUP times. */
kono
parents: 14
diff changeset
1540
kono
parents: 14
diff changeset
1541 static const char *
kono
parents: 14
diff changeset
1542 duplicate_alternatives (const char * str, int n_dup)
kono
parents: 14
diff changeset
1543 {
kono
parents: 14
diff changeset
1544 int i, len, new_len;
kono
parents: 14
diff changeset
1545 char *result, *sp;
kono
parents: 14
diff changeset
1546 const char *cp;
kono
parents: 14
diff changeset
1547
kono
parents: 14
diff changeset
1548 if (n_dup < 2)
kono
parents: 14
diff changeset
1549 return str;
kono
parents: 14
diff changeset
1550
kono
parents: 14
diff changeset
1551 while (ISSPACE (*str))
kono
parents: 14
diff changeset
1552 str++;
kono
parents: 14
diff changeset
1553
kono
parents: 14
diff changeset
1554 if (*str == '\0')
kono
parents: 14
diff changeset
1555 return str;
kono
parents: 14
diff changeset
1556
kono
parents: 14
diff changeset
1557 cp = str;
kono
parents: 14
diff changeset
1558 len = strlen (str);
kono
parents: 14
diff changeset
1559 new_len = (len + 1) * n_dup;
kono
parents: 14
diff changeset
1560
kono
parents: 14
diff changeset
1561 sp = result = XNEWVEC (char, new_len);
kono
parents: 14
diff changeset
1562
kono
parents: 14
diff changeset
1563 /* Global modifier characters mustn't be duplicated: skip if found. */
kono
parents: 14
diff changeset
1564 if (*cp == '=' || *cp == '+' || *cp == '%')
kono
parents: 14
diff changeset
1565 {
kono
parents: 14
diff changeset
1566 *sp++ = *cp++;
kono
parents: 14
diff changeset
1567 len--;
kono
parents: 14
diff changeset
1568 }
kono
parents: 14
diff changeset
1569
kono
parents: 14
diff changeset
1570 /* Copy original constraints N_DUP times. */
kono
parents: 14
diff changeset
1571 for (i = 0; i < n_dup; i++, sp += len+1)
kono
parents: 14
diff changeset
1572 {
kono
parents: 14
diff changeset
1573 memcpy (sp, cp, len);
kono
parents: 14
diff changeset
1574 *(sp+len) = (i == n_dup - 1) ? '\0' : ',';
kono
parents: 14
diff changeset
1575 }
kono
parents: 14
diff changeset
1576
kono
parents: 14
diff changeset
1577 return result;
kono
parents: 14
diff changeset
1578 }
kono
parents: 14
diff changeset
1579
kono
parents: 14
diff changeset
1580 /* From string STR "a,b,c" produce "a,a,a,b,b,b,c,c,c", i.e. string where
kono
parents: 14
diff changeset
1581 each alternative from the original string is duplicated N_DUP times. */
kono
parents: 14
diff changeset
1582 static const char *
kono
parents: 14
diff changeset
1583 duplicate_each_alternative (const char * str, int n_dup)
kono
parents: 14
diff changeset
1584 {
kono
parents: 14
diff changeset
1585 int i, len, new_len;
kono
parents: 14
diff changeset
1586 char *result, *sp, *ep, *cp;
kono
parents: 14
diff changeset
1587
kono
parents: 14
diff changeset
1588 if (n_dup < 2)
kono
parents: 14
diff changeset
1589 return str;
kono
parents: 14
diff changeset
1590
kono
parents: 14
diff changeset
1591 while (ISSPACE (*str))
kono
parents: 14
diff changeset
1592 str++;
kono
parents: 14
diff changeset
1593
kono
parents: 14
diff changeset
1594 if (*str == '\0')
kono
parents: 14
diff changeset
1595 return str;
kono
parents: 14
diff changeset
1596
kono
parents: 14
diff changeset
1597 cp = xstrdup (str);
kono
parents: 14
diff changeset
1598
kono
parents: 14
diff changeset
1599 new_len = (strlen (cp) + 1) * n_dup;
kono
parents: 14
diff changeset
1600
kono
parents: 14
diff changeset
1601 sp = result = XNEWVEC (char, new_len);
kono
parents: 14
diff changeset
1602
kono
parents: 14
diff changeset
1603 /* Global modifier characters mustn't be duplicated: skip if found. */
kono
parents: 14
diff changeset
1604 if (*cp == '=' || *cp == '+' || *cp == '%')
kono
parents: 14
diff changeset
1605 *sp++ = *cp++;
kono
parents: 14
diff changeset
1606
kono
parents: 14
diff changeset
1607 do
kono
parents: 14
diff changeset
1608 {
kono
parents: 14
diff changeset
1609 if ((ep = strchr (cp, ',')) != NULL)
kono
parents: 14
diff changeset
1610 *ep++ = '\0';
kono
parents: 14
diff changeset
1611 len = strlen (cp);
kono
parents: 14
diff changeset
1612
kono
parents: 14
diff changeset
1613 /* Copy a constraint N_DUP times. */
kono
parents: 14
diff changeset
1614 for (i = 0; i < n_dup; i++, sp += len + 1)
kono
parents: 14
diff changeset
1615 {
kono
parents: 14
diff changeset
1616 memcpy (sp, cp, len);
kono
parents: 14
diff changeset
1617 *(sp+len) = (ep == NULL && i == n_dup - 1) ? '\0' : ',';
kono
parents: 14
diff changeset
1618 }
kono
parents: 14
diff changeset
1619
kono
parents: 14
diff changeset
1620 cp = ep;
kono
parents: 14
diff changeset
1621 }
kono
parents: 14
diff changeset
1622 while (cp != NULL);
kono
parents: 14
diff changeset
1623
kono
parents: 14
diff changeset
1624 return result;
kono
parents: 14
diff changeset
1625 }
kono
parents: 14
diff changeset
1626
kono
parents: 14
diff changeset
1627 /* Alter the output of INSN whose pattern was modified by
kono
parents: 14
diff changeset
1628 DEFINE_SUBST. We must replicate output strings according
kono
parents: 14
diff changeset
1629 to the new number of alternatives ALT in substituted pattern.
kono
parents: 14
diff changeset
1630 If ALT equals 1, output has one alternative or defined by C
kono
parents: 14
diff changeset
1631 code, then output is returned without any changes. */
kono
parents: 14
diff changeset
1632
kono
parents: 14
diff changeset
1633 static const char *
kono
parents: 14
diff changeset
1634 alter_output_for_subst_insn (rtx insn, int alt)
kono
parents: 14
diff changeset
1635 {
kono
parents: 14
diff changeset
1636 const char *insn_out, *old_out;
kono
parents: 14
diff changeset
1637 char *new_out, *cp;
kono
parents: 14
diff changeset
1638 size_t old_len, new_len;
kono
parents: 14
diff changeset
1639 int j;
kono
parents: 14
diff changeset
1640
kono
parents: 14
diff changeset
1641 insn_out = XTMPL (insn, 3);
kono
parents: 14
diff changeset
1642
kono
parents: 14
diff changeset
1643 if (alt < 2 || *insn_out != '@')
kono
parents: 14
diff changeset
1644 return insn_out;
kono
parents: 14
diff changeset
1645
kono
parents: 14
diff changeset
1646 old_out = insn_out + 1;
kono
parents: 14
diff changeset
1647 while (ISSPACE (*old_out))
kono
parents: 14
diff changeset
1648 old_out++;
kono
parents: 14
diff changeset
1649 old_len = strlen (old_out);
kono
parents: 14
diff changeset
1650
kono
parents: 14
diff changeset
1651 new_len = alt * (old_len + 1) + 1;