1e4b17023SJohn Marino /* Subroutines used by or related to instruction recognition.
2e4b17023SJohn Marino Copyright (C) 1987, 1988, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998
3e4b17023SJohn Marino 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
4e4b17023SJohn Marino Free Software Foundation, Inc.
5e4b17023SJohn Marino
6e4b17023SJohn Marino This file is part of GCC.
7e4b17023SJohn Marino
8e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify it under
9e4b17023SJohn Marino the terms of the GNU General Public License as published by the Free
10e4b17023SJohn Marino Software Foundation; either version 3, or (at your option) any later
11e4b17023SJohn Marino version.
12e4b17023SJohn Marino
13e4b17023SJohn Marino GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14e4b17023SJohn Marino WARRANTY; without even the implied warranty of MERCHANTABILITY or
15e4b17023SJohn Marino FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16e4b17023SJohn Marino for more details.
17e4b17023SJohn Marino
18e4b17023SJohn Marino You should have received a copy of the GNU General Public License
19e4b17023SJohn Marino along with GCC; see the file COPYING3. If not see
20e4b17023SJohn Marino <http://www.gnu.org/licenses/>. */
21e4b17023SJohn Marino
22e4b17023SJohn Marino
23e4b17023SJohn Marino #include "config.h"
24e4b17023SJohn Marino #include "system.h"
25e4b17023SJohn Marino #include "coretypes.h"
26e4b17023SJohn Marino #include "tm.h"
27e4b17023SJohn Marino #include "rtl-error.h"
28e4b17023SJohn Marino #include "tm_p.h"
29e4b17023SJohn Marino #include "insn-config.h"
30e4b17023SJohn Marino #include "insn-attr.h"
31e4b17023SJohn Marino #include "hard-reg-set.h"
32e4b17023SJohn Marino #include "recog.h"
33e4b17023SJohn Marino #include "regs.h"
34e4b17023SJohn Marino #include "addresses.h"
35e4b17023SJohn Marino #include "expr.h"
36e4b17023SJohn Marino #include "function.h"
37e4b17023SJohn Marino #include "flags.h"
38e4b17023SJohn Marino #include "basic-block.h"
39e4b17023SJohn Marino #include "output.h"
40e4b17023SJohn Marino #include "reload.h"
41e4b17023SJohn Marino #include "target.h"
42e4b17023SJohn Marino #include "timevar.h"
43e4b17023SJohn Marino #include "tree-pass.h"
44e4b17023SJohn Marino #include "df.h"
45e4b17023SJohn Marino
46e4b17023SJohn Marino #ifndef STACK_PUSH_CODE
47e4b17023SJohn Marino #ifdef STACK_GROWS_DOWNWARD
48e4b17023SJohn Marino #define STACK_PUSH_CODE PRE_DEC
49e4b17023SJohn Marino #else
50e4b17023SJohn Marino #define STACK_PUSH_CODE PRE_INC
51e4b17023SJohn Marino #endif
52e4b17023SJohn Marino #endif
53e4b17023SJohn Marino
54e4b17023SJohn Marino #ifndef STACK_POP_CODE
55e4b17023SJohn Marino #ifdef STACK_GROWS_DOWNWARD
56e4b17023SJohn Marino #define STACK_POP_CODE POST_INC
57e4b17023SJohn Marino #else
58e4b17023SJohn Marino #define STACK_POP_CODE POST_DEC
59e4b17023SJohn Marino #endif
60e4b17023SJohn Marino #endif
61e4b17023SJohn Marino
62e4b17023SJohn Marino #ifndef HAVE_ATTR_enabled
63e4b17023SJohn Marino static inline bool
get_attr_enabled(rtx insn ATTRIBUTE_UNUSED)64e4b17023SJohn Marino get_attr_enabled (rtx insn ATTRIBUTE_UNUSED)
65e4b17023SJohn Marino {
66e4b17023SJohn Marino return true;
67e4b17023SJohn Marino }
68e4b17023SJohn Marino #endif
69e4b17023SJohn Marino
70e4b17023SJohn Marino static void validate_replace_rtx_1 (rtx *, rtx, rtx, rtx, bool);
71e4b17023SJohn Marino static void validate_replace_src_1 (rtx *, void *);
72e4b17023SJohn Marino static rtx split_insn (rtx);
73e4b17023SJohn Marino
74e4b17023SJohn Marino /* Nonzero means allow operands to be volatile.
75e4b17023SJohn Marino This should be 0 if you are generating rtl, such as if you are calling
76e4b17023SJohn Marino the functions in optabs.c and expmed.c (most of the time).
77e4b17023SJohn Marino This should be 1 if all valid insns need to be recognized,
78e4b17023SJohn Marino such as in reginfo.c and final.c and reload.c.
79e4b17023SJohn Marino
80e4b17023SJohn Marino init_recog and init_recog_no_volatile are responsible for setting this. */
81e4b17023SJohn Marino
82e4b17023SJohn Marino int volatile_ok;
83e4b17023SJohn Marino
84e4b17023SJohn Marino struct recog_data recog_data;
85e4b17023SJohn Marino
86e4b17023SJohn Marino /* Contains a vector of operand_alternative structures for every operand.
87e4b17023SJohn Marino Set up by preprocess_constraints. */
88e4b17023SJohn Marino struct operand_alternative recog_op_alt[MAX_RECOG_OPERANDS][MAX_RECOG_ALTERNATIVES];
89e4b17023SJohn Marino
90e4b17023SJohn Marino /* On return from `constrain_operands', indicate which alternative
91e4b17023SJohn Marino was satisfied. */
92e4b17023SJohn Marino
93e4b17023SJohn Marino int which_alternative;
94e4b17023SJohn Marino
95e4b17023SJohn Marino /* Nonzero after end of reload pass.
96e4b17023SJohn Marino Set to 1 or 0 by toplev.c.
97e4b17023SJohn Marino Controls the significance of (SUBREG (MEM)). */
98e4b17023SJohn Marino
99e4b17023SJohn Marino int reload_completed;
100e4b17023SJohn Marino
101e4b17023SJohn Marino /* Nonzero after thread_prologue_and_epilogue_insns has run. */
102e4b17023SJohn Marino int epilogue_completed;
103e4b17023SJohn Marino
104e4b17023SJohn Marino /* Initialize data used by the function `recog'.
105e4b17023SJohn Marino This must be called once in the compilation of a function
106e4b17023SJohn Marino before any insn recognition may be done in the function. */
107e4b17023SJohn Marino
108e4b17023SJohn Marino void
init_recog_no_volatile(void)109e4b17023SJohn Marino init_recog_no_volatile (void)
110e4b17023SJohn Marino {
111e4b17023SJohn Marino volatile_ok = 0;
112e4b17023SJohn Marino }
113e4b17023SJohn Marino
114e4b17023SJohn Marino void
init_recog(void)115e4b17023SJohn Marino init_recog (void)
116e4b17023SJohn Marino {
117e4b17023SJohn Marino volatile_ok = 1;
118e4b17023SJohn Marino }
119e4b17023SJohn Marino
120e4b17023SJohn Marino
121e4b17023SJohn Marino /* Return true if labels in asm operands BODY are LABEL_REFs. */
122e4b17023SJohn Marino
123e4b17023SJohn Marino static bool
asm_labels_ok(rtx body)124e4b17023SJohn Marino asm_labels_ok (rtx body)
125e4b17023SJohn Marino {
126e4b17023SJohn Marino rtx asmop;
127e4b17023SJohn Marino int i;
128e4b17023SJohn Marino
129e4b17023SJohn Marino asmop = extract_asm_operands (body);
130e4b17023SJohn Marino if (asmop == NULL_RTX)
131e4b17023SJohn Marino return true;
132e4b17023SJohn Marino
133e4b17023SJohn Marino for (i = 0; i < ASM_OPERANDS_LABEL_LENGTH (asmop); i++)
134e4b17023SJohn Marino if (GET_CODE (ASM_OPERANDS_LABEL (asmop, i)) != LABEL_REF)
135e4b17023SJohn Marino return false;
136e4b17023SJohn Marino
137e4b17023SJohn Marino return true;
138e4b17023SJohn Marino }
139e4b17023SJohn Marino
140e4b17023SJohn Marino /* Check that X is an insn-body for an `asm' with operands
141e4b17023SJohn Marino and that the operands mentioned in it are legitimate. */
142e4b17023SJohn Marino
143e4b17023SJohn Marino int
check_asm_operands(rtx x)144e4b17023SJohn Marino check_asm_operands (rtx x)
145e4b17023SJohn Marino {
146e4b17023SJohn Marino int noperands;
147e4b17023SJohn Marino rtx *operands;
148e4b17023SJohn Marino const char **constraints;
149e4b17023SJohn Marino int i;
150e4b17023SJohn Marino
151e4b17023SJohn Marino if (!asm_labels_ok (x))
152e4b17023SJohn Marino return 0;
153e4b17023SJohn Marino
154e4b17023SJohn Marino /* Post-reload, be more strict with things. */
155e4b17023SJohn Marino if (reload_completed)
156e4b17023SJohn Marino {
157e4b17023SJohn Marino /* ??? Doh! We've not got the wrapping insn. Cook one up. */
158e4b17023SJohn Marino extract_insn (make_insn_raw (x));
159e4b17023SJohn Marino constrain_operands (1);
160e4b17023SJohn Marino return which_alternative >= 0;
161e4b17023SJohn Marino }
162e4b17023SJohn Marino
163e4b17023SJohn Marino noperands = asm_noperands (x);
164e4b17023SJohn Marino if (noperands < 0)
165e4b17023SJohn Marino return 0;
166e4b17023SJohn Marino if (noperands == 0)
167e4b17023SJohn Marino return 1;
168e4b17023SJohn Marino
169e4b17023SJohn Marino operands = XALLOCAVEC (rtx, noperands);
170e4b17023SJohn Marino constraints = XALLOCAVEC (const char *, noperands);
171e4b17023SJohn Marino
172e4b17023SJohn Marino decode_asm_operands (x, operands, NULL, constraints, NULL, NULL);
173e4b17023SJohn Marino
174e4b17023SJohn Marino for (i = 0; i < noperands; i++)
175e4b17023SJohn Marino {
176e4b17023SJohn Marino const char *c = constraints[i];
177e4b17023SJohn Marino if (c[0] == '%')
178e4b17023SJohn Marino c++;
179e4b17023SJohn Marino if (! asm_operand_ok (operands[i], c, constraints))
180e4b17023SJohn Marino return 0;
181e4b17023SJohn Marino }
182e4b17023SJohn Marino
183e4b17023SJohn Marino return 1;
184e4b17023SJohn Marino }
185e4b17023SJohn Marino
186e4b17023SJohn Marino /* Static data for the next two routines. */
187e4b17023SJohn Marino
188e4b17023SJohn Marino typedef struct change_t
189e4b17023SJohn Marino {
190e4b17023SJohn Marino rtx object;
191e4b17023SJohn Marino int old_code;
192e4b17023SJohn Marino rtx *loc;
193e4b17023SJohn Marino rtx old;
194e4b17023SJohn Marino bool unshare;
195e4b17023SJohn Marino } change_t;
196e4b17023SJohn Marino
197e4b17023SJohn Marino static change_t *changes;
198e4b17023SJohn Marino static int changes_allocated;
199e4b17023SJohn Marino
200e4b17023SJohn Marino static int num_changes = 0;
201e4b17023SJohn Marino
202e4b17023SJohn Marino /* Validate a proposed change to OBJECT. LOC is the location in the rtl
203e4b17023SJohn Marino at which NEW_RTX will be placed. If OBJECT is zero, no validation is done,
204e4b17023SJohn Marino the change is simply made.
205e4b17023SJohn Marino
206e4b17023SJohn Marino Two types of objects are supported: If OBJECT is a MEM, memory_address_p
207e4b17023SJohn Marino will be called with the address and mode as parameters. If OBJECT is
208e4b17023SJohn Marino an INSN, CALL_INSN, or JUMP_INSN, the insn will be re-recognized with
209e4b17023SJohn Marino the change in place.
210e4b17023SJohn Marino
211e4b17023SJohn Marino IN_GROUP is nonzero if this is part of a group of changes that must be
212e4b17023SJohn Marino performed as a group. In that case, the changes will be stored. The
213e4b17023SJohn Marino function `apply_change_group' will validate and apply the changes.
214e4b17023SJohn Marino
215e4b17023SJohn Marino If IN_GROUP is zero, this is a single change. Try to recognize the insn
216e4b17023SJohn Marino or validate the memory reference with the change applied. If the result
217e4b17023SJohn Marino is not valid for the machine, suppress the change and return zero.
218e4b17023SJohn Marino Otherwise, perform the change and return 1. */
219e4b17023SJohn Marino
220e4b17023SJohn Marino static bool
validate_change_1(rtx object,rtx * loc,rtx new_rtx,bool in_group,bool unshare)221e4b17023SJohn Marino validate_change_1 (rtx object, rtx *loc, rtx new_rtx, bool in_group, bool unshare)
222e4b17023SJohn Marino {
223e4b17023SJohn Marino rtx old = *loc;
224e4b17023SJohn Marino
225e4b17023SJohn Marino if (old == new_rtx || rtx_equal_p (old, new_rtx))
226e4b17023SJohn Marino return 1;
227e4b17023SJohn Marino
228e4b17023SJohn Marino gcc_assert (in_group != 0 || num_changes == 0);
229e4b17023SJohn Marino
230e4b17023SJohn Marino *loc = new_rtx;
231e4b17023SJohn Marino
232e4b17023SJohn Marino /* Save the information describing this change. */
233e4b17023SJohn Marino if (num_changes >= changes_allocated)
234e4b17023SJohn Marino {
235e4b17023SJohn Marino if (changes_allocated == 0)
236e4b17023SJohn Marino /* This value allows for repeated substitutions inside complex
237e4b17023SJohn Marino indexed addresses, or changes in up to 5 insns. */
238e4b17023SJohn Marino changes_allocated = MAX_RECOG_OPERANDS * 5;
239e4b17023SJohn Marino else
240e4b17023SJohn Marino changes_allocated *= 2;
241e4b17023SJohn Marino
242e4b17023SJohn Marino changes = XRESIZEVEC (change_t, changes, changes_allocated);
243e4b17023SJohn Marino }
244e4b17023SJohn Marino
245e4b17023SJohn Marino changes[num_changes].object = object;
246e4b17023SJohn Marino changes[num_changes].loc = loc;
247e4b17023SJohn Marino changes[num_changes].old = old;
248e4b17023SJohn Marino changes[num_changes].unshare = unshare;
249e4b17023SJohn Marino
250e4b17023SJohn Marino if (object && !MEM_P (object))
251e4b17023SJohn Marino {
252e4b17023SJohn Marino /* Set INSN_CODE to force rerecognition of insn. Save old code in
253e4b17023SJohn Marino case invalid. */
254e4b17023SJohn Marino changes[num_changes].old_code = INSN_CODE (object);
255e4b17023SJohn Marino INSN_CODE (object) = -1;
256e4b17023SJohn Marino }
257e4b17023SJohn Marino
258e4b17023SJohn Marino num_changes++;
259e4b17023SJohn Marino
260e4b17023SJohn Marino /* If we are making a group of changes, return 1. Otherwise, validate the
261e4b17023SJohn Marino change group we made. */
262e4b17023SJohn Marino
263e4b17023SJohn Marino if (in_group)
264e4b17023SJohn Marino return 1;
265e4b17023SJohn Marino else
266e4b17023SJohn Marino return apply_change_group ();
267e4b17023SJohn Marino }
268e4b17023SJohn Marino
269e4b17023SJohn Marino /* Wrapper for validate_change_1 without the UNSHARE argument defaulting
270e4b17023SJohn Marino UNSHARE to false. */
271e4b17023SJohn Marino
272e4b17023SJohn Marino bool
validate_change(rtx object,rtx * loc,rtx new_rtx,bool in_group)273e4b17023SJohn Marino validate_change (rtx object, rtx *loc, rtx new_rtx, bool in_group)
274e4b17023SJohn Marino {
275e4b17023SJohn Marino return validate_change_1 (object, loc, new_rtx, in_group, false);
276e4b17023SJohn Marino }
277e4b17023SJohn Marino
278e4b17023SJohn Marino /* Wrapper for validate_change_1 without the UNSHARE argument defaulting
279e4b17023SJohn Marino UNSHARE to true. */
280e4b17023SJohn Marino
281e4b17023SJohn Marino bool
validate_unshare_change(rtx object,rtx * loc,rtx new_rtx,bool in_group)282e4b17023SJohn Marino validate_unshare_change (rtx object, rtx *loc, rtx new_rtx, bool in_group)
283e4b17023SJohn Marino {
284e4b17023SJohn Marino return validate_change_1 (object, loc, new_rtx, in_group, true);
285e4b17023SJohn Marino }
286e4b17023SJohn Marino
287e4b17023SJohn Marino
288e4b17023SJohn Marino /* Keep X canonicalized if some changes have made it non-canonical; only
289e4b17023SJohn Marino modifies the operands of X, not (for example) its code. Simplifications
290e4b17023SJohn Marino are not the job of this routine.
291e4b17023SJohn Marino
292e4b17023SJohn Marino Return true if anything was changed. */
293e4b17023SJohn Marino bool
canonicalize_change_group(rtx insn,rtx x)294e4b17023SJohn Marino canonicalize_change_group (rtx insn, rtx x)
295e4b17023SJohn Marino {
296e4b17023SJohn Marino if (COMMUTATIVE_P (x)
297e4b17023SJohn Marino && swap_commutative_operands_p (XEXP (x, 0), XEXP (x, 1)))
298e4b17023SJohn Marino {
299e4b17023SJohn Marino /* Oops, the caller has made X no longer canonical.
300e4b17023SJohn Marino Let's redo the changes in the correct order. */
301e4b17023SJohn Marino rtx tem = XEXP (x, 0);
302e4b17023SJohn Marino validate_unshare_change (insn, &XEXP (x, 0), XEXP (x, 1), 1);
303e4b17023SJohn Marino validate_unshare_change (insn, &XEXP (x, 1), tem, 1);
304e4b17023SJohn Marino return true;
305e4b17023SJohn Marino }
306e4b17023SJohn Marino else
307e4b17023SJohn Marino return false;
308e4b17023SJohn Marino }
309e4b17023SJohn Marino
310e4b17023SJohn Marino
311e4b17023SJohn Marino /* This subroutine of apply_change_group verifies whether the changes to INSN
312e4b17023SJohn Marino were valid; i.e. whether INSN can still be recognized. */
313e4b17023SJohn Marino
314e4b17023SJohn Marino int
insn_invalid_p(rtx insn)315e4b17023SJohn Marino insn_invalid_p (rtx insn)
316e4b17023SJohn Marino {
317e4b17023SJohn Marino rtx pat = PATTERN (insn);
318e4b17023SJohn Marino int num_clobbers = 0;
319e4b17023SJohn Marino /* If we are before reload and the pattern is a SET, see if we can add
320e4b17023SJohn Marino clobbers. */
321e4b17023SJohn Marino int icode = recog (pat, insn,
322e4b17023SJohn Marino (GET_CODE (pat) == SET
323e4b17023SJohn Marino && ! reload_completed && ! reload_in_progress)
324e4b17023SJohn Marino ? &num_clobbers : 0);
325e4b17023SJohn Marino int is_asm = icode < 0 && asm_noperands (PATTERN (insn)) >= 0;
326e4b17023SJohn Marino
327e4b17023SJohn Marino
328e4b17023SJohn Marino /* If this is an asm and the operand aren't legal, then fail. Likewise if
329e4b17023SJohn Marino this is not an asm and the insn wasn't recognized. */
330e4b17023SJohn Marino if ((is_asm && ! check_asm_operands (PATTERN (insn)))
331e4b17023SJohn Marino || (!is_asm && icode < 0))
332e4b17023SJohn Marino return 1;
333e4b17023SJohn Marino
334e4b17023SJohn Marino /* If we have to add CLOBBERs, fail if we have to add ones that reference
335e4b17023SJohn Marino hard registers since our callers can't know if they are live or not.
336e4b17023SJohn Marino Otherwise, add them. */
337e4b17023SJohn Marino if (num_clobbers > 0)
338e4b17023SJohn Marino {
339e4b17023SJohn Marino rtx newpat;
340e4b17023SJohn Marino
341e4b17023SJohn Marino if (added_clobbers_hard_reg_p (icode))
342e4b17023SJohn Marino return 1;
343e4b17023SJohn Marino
344e4b17023SJohn Marino newpat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (num_clobbers + 1));
345e4b17023SJohn Marino XVECEXP (newpat, 0, 0) = pat;
346e4b17023SJohn Marino add_clobbers (newpat, icode);
347e4b17023SJohn Marino PATTERN (insn) = pat = newpat;
348e4b17023SJohn Marino }
349e4b17023SJohn Marino
350e4b17023SJohn Marino /* After reload, verify that all constraints are satisfied. */
351e4b17023SJohn Marino if (reload_completed)
352e4b17023SJohn Marino {
353e4b17023SJohn Marino extract_insn (insn);
354e4b17023SJohn Marino
355e4b17023SJohn Marino if (! constrain_operands (1))
356e4b17023SJohn Marino return 1;
357e4b17023SJohn Marino }
358e4b17023SJohn Marino
359e4b17023SJohn Marino INSN_CODE (insn) = icode;
360e4b17023SJohn Marino return 0;
361e4b17023SJohn Marino }
362e4b17023SJohn Marino
363e4b17023SJohn Marino /* Return number of changes made and not validated yet. */
364e4b17023SJohn Marino int
num_changes_pending(void)365e4b17023SJohn Marino num_changes_pending (void)
366e4b17023SJohn Marino {
367e4b17023SJohn Marino return num_changes;
368e4b17023SJohn Marino }
369e4b17023SJohn Marino
370e4b17023SJohn Marino /* Tentatively apply the changes numbered NUM and up.
371e4b17023SJohn Marino Return 1 if all changes are valid, zero otherwise. */
372e4b17023SJohn Marino
373e4b17023SJohn Marino int
verify_changes(int num)374e4b17023SJohn Marino verify_changes (int num)
375e4b17023SJohn Marino {
376e4b17023SJohn Marino int i;
377e4b17023SJohn Marino rtx last_validated = NULL_RTX;
378e4b17023SJohn Marino
379e4b17023SJohn Marino /* The changes have been applied and all INSN_CODEs have been reset to force
380e4b17023SJohn Marino rerecognition.
381e4b17023SJohn Marino
382e4b17023SJohn Marino The changes are valid if we aren't given an object, or if we are
383e4b17023SJohn Marino given a MEM and it still is a valid address, or if this is in insn
384e4b17023SJohn Marino and it is recognized. In the latter case, if reload has completed,
385e4b17023SJohn Marino we also require that the operands meet the constraints for
386e4b17023SJohn Marino the insn. */
387e4b17023SJohn Marino
388e4b17023SJohn Marino for (i = num; i < num_changes; i++)
389e4b17023SJohn Marino {
390e4b17023SJohn Marino rtx object = changes[i].object;
391e4b17023SJohn Marino
392e4b17023SJohn Marino /* If there is no object to test or if it is the same as the one we
393e4b17023SJohn Marino already tested, ignore it. */
394e4b17023SJohn Marino if (object == 0 || object == last_validated)
395e4b17023SJohn Marino continue;
396e4b17023SJohn Marino
397e4b17023SJohn Marino if (MEM_P (object))
398e4b17023SJohn Marino {
399e4b17023SJohn Marino if (! memory_address_addr_space_p (GET_MODE (object),
400e4b17023SJohn Marino XEXP (object, 0),
401e4b17023SJohn Marino MEM_ADDR_SPACE (object)))
402e4b17023SJohn Marino break;
403e4b17023SJohn Marino }
404e4b17023SJohn Marino else if (REG_P (changes[i].old)
405e4b17023SJohn Marino && asm_noperands (PATTERN (object)) > 0
406e4b17023SJohn Marino && REG_EXPR (changes[i].old) != NULL_TREE
407e4b17023SJohn Marino && DECL_ASSEMBLER_NAME_SET_P (REG_EXPR (changes[i].old))
408e4b17023SJohn Marino && DECL_REGISTER (REG_EXPR (changes[i].old)))
409e4b17023SJohn Marino {
410e4b17023SJohn Marino /* Don't allow changes of hard register operands to inline
411e4b17023SJohn Marino assemblies if they have been defined as register asm ("x"). */
412e4b17023SJohn Marino break;
413e4b17023SJohn Marino }
414e4b17023SJohn Marino else if (DEBUG_INSN_P (object))
415e4b17023SJohn Marino continue;
416e4b17023SJohn Marino else if (insn_invalid_p (object))
417e4b17023SJohn Marino {
418e4b17023SJohn Marino rtx pat = PATTERN (object);
419e4b17023SJohn Marino
420e4b17023SJohn Marino /* Perhaps we couldn't recognize the insn because there were
421e4b17023SJohn Marino extra CLOBBERs at the end. If so, try to re-recognize
422e4b17023SJohn Marino without the last CLOBBER (later iterations will cause each of
423e4b17023SJohn Marino them to be eliminated, in turn). But don't do this if we
424e4b17023SJohn Marino have an ASM_OPERAND. */
425e4b17023SJohn Marino if (GET_CODE (pat) == PARALLEL
426e4b17023SJohn Marino && GET_CODE (XVECEXP (pat, 0, XVECLEN (pat, 0) - 1)) == CLOBBER
427e4b17023SJohn Marino && asm_noperands (PATTERN (object)) < 0)
428e4b17023SJohn Marino {
429e4b17023SJohn Marino rtx newpat;
430e4b17023SJohn Marino
431e4b17023SJohn Marino if (XVECLEN (pat, 0) == 2)
432e4b17023SJohn Marino newpat = XVECEXP (pat, 0, 0);
433e4b17023SJohn Marino else
434e4b17023SJohn Marino {
435e4b17023SJohn Marino int j;
436e4b17023SJohn Marino
437e4b17023SJohn Marino newpat
438e4b17023SJohn Marino = gen_rtx_PARALLEL (VOIDmode,
439e4b17023SJohn Marino rtvec_alloc (XVECLEN (pat, 0) - 1));
440e4b17023SJohn Marino for (j = 0; j < XVECLEN (newpat, 0); j++)
441e4b17023SJohn Marino XVECEXP (newpat, 0, j) = XVECEXP (pat, 0, j);
442e4b17023SJohn Marino }
443e4b17023SJohn Marino
444e4b17023SJohn Marino /* Add a new change to this group to replace the pattern
445e4b17023SJohn Marino with this new pattern. Then consider this change
446e4b17023SJohn Marino as having succeeded. The change we added will
447e4b17023SJohn Marino cause the entire call to fail if things remain invalid.
448e4b17023SJohn Marino
449e4b17023SJohn Marino Note that this can lose if a later change than the one
450e4b17023SJohn Marino we are processing specified &XVECEXP (PATTERN (object), 0, X)
451e4b17023SJohn Marino but this shouldn't occur. */
452e4b17023SJohn Marino
453e4b17023SJohn Marino validate_change (object, &PATTERN (object), newpat, 1);
454e4b17023SJohn Marino continue;
455e4b17023SJohn Marino }
456e4b17023SJohn Marino else if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
457e4b17023SJohn Marino || GET_CODE (pat) == VAR_LOCATION)
458e4b17023SJohn Marino /* If this insn is a CLOBBER or USE, it is always valid, but is
459e4b17023SJohn Marino never recognized. */
460e4b17023SJohn Marino continue;
461e4b17023SJohn Marino else
462e4b17023SJohn Marino break;
463e4b17023SJohn Marino }
464e4b17023SJohn Marino last_validated = object;
465e4b17023SJohn Marino }
466e4b17023SJohn Marino
467e4b17023SJohn Marino return (i == num_changes);
468e4b17023SJohn Marino }
469e4b17023SJohn Marino
470e4b17023SJohn Marino /* A group of changes has previously been issued with validate_change
471e4b17023SJohn Marino and verified with verify_changes. Call df_insn_rescan for each of
472e4b17023SJohn Marino the insn changed and clear num_changes. */
473e4b17023SJohn Marino
474e4b17023SJohn Marino void
confirm_change_group(void)475e4b17023SJohn Marino confirm_change_group (void)
476e4b17023SJohn Marino {
477e4b17023SJohn Marino int i;
478e4b17023SJohn Marino rtx last_object = NULL;
479e4b17023SJohn Marino
480e4b17023SJohn Marino for (i = 0; i < num_changes; i++)
481e4b17023SJohn Marino {
482e4b17023SJohn Marino rtx object = changes[i].object;
483e4b17023SJohn Marino
484e4b17023SJohn Marino if (changes[i].unshare)
485e4b17023SJohn Marino *changes[i].loc = copy_rtx (*changes[i].loc);
486e4b17023SJohn Marino
487e4b17023SJohn Marino /* Avoid unnecessary rescanning when multiple changes to same instruction
488e4b17023SJohn Marino are made. */
489e4b17023SJohn Marino if (object)
490e4b17023SJohn Marino {
491e4b17023SJohn Marino if (object != last_object && last_object && INSN_P (last_object))
492e4b17023SJohn Marino df_insn_rescan (last_object);
493e4b17023SJohn Marino last_object = object;
494e4b17023SJohn Marino }
495e4b17023SJohn Marino }
496e4b17023SJohn Marino
497e4b17023SJohn Marino if (last_object && INSN_P (last_object))
498e4b17023SJohn Marino df_insn_rescan (last_object);
499e4b17023SJohn Marino num_changes = 0;
500e4b17023SJohn Marino }
501e4b17023SJohn Marino
502e4b17023SJohn Marino /* Apply a group of changes previously issued with `validate_change'.
503e4b17023SJohn Marino If all changes are valid, call confirm_change_group and return 1,
504e4b17023SJohn Marino otherwise, call cancel_changes and return 0. */
505e4b17023SJohn Marino
506e4b17023SJohn Marino int
apply_change_group(void)507e4b17023SJohn Marino apply_change_group (void)
508e4b17023SJohn Marino {
509e4b17023SJohn Marino if (verify_changes (0))
510e4b17023SJohn Marino {
511e4b17023SJohn Marino confirm_change_group ();
512e4b17023SJohn Marino return 1;
513e4b17023SJohn Marino }
514e4b17023SJohn Marino else
515e4b17023SJohn Marino {
516e4b17023SJohn Marino cancel_changes (0);
517e4b17023SJohn Marino return 0;
518e4b17023SJohn Marino }
519e4b17023SJohn Marino }
520e4b17023SJohn Marino
521e4b17023SJohn Marino
522e4b17023SJohn Marino /* Return the number of changes so far in the current group. */
523e4b17023SJohn Marino
524e4b17023SJohn Marino int
num_validated_changes(void)525e4b17023SJohn Marino num_validated_changes (void)
526e4b17023SJohn Marino {
527e4b17023SJohn Marino return num_changes;
528e4b17023SJohn Marino }
529e4b17023SJohn Marino
530e4b17023SJohn Marino /* Retract the changes numbered NUM and up. */
531e4b17023SJohn Marino
532e4b17023SJohn Marino void
cancel_changes(int num)533e4b17023SJohn Marino cancel_changes (int num)
534e4b17023SJohn Marino {
535e4b17023SJohn Marino int i;
536e4b17023SJohn Marino
537e4b17023SJohn Marino /* Back out all the changes. Do this in the opposite order in which
538e4b17023SJohn Marino they were made. */
539e4b17023SJohn Marino for (i = num_changes - 1; i >= num; i--)
540e4b17023SJohn Marino {
541e4b17023SJohn Marino *changes[i].loc = changes[i].old;
542e4b17023SJohn Marino if (changes[i].object && !MEM_P (changes[i].object))
543e4b17023SJohn Marino INSN_CODE (changes[i].object) = changes[i].old_code;
544e4b17023SJohn Marino }
545e4b17023SJohn Marino num_changes = num;
546e4b17023SJohn Marino }
547e4b17023SJohn Marino
548e4b17023SJohn Marino /* A subroutine of validate_replace_rtx_1 that tries to simplify the resulting
549e4b17023SJohn Marino rtx. */
550e4b17023SJohn Marino
551e4b17023SJohn Marino static void
simplify_while_replacing(rtx * loc,rtx to,rtx object,enum machine_mode op0_mode)552e4b17023SJohn Marino simplify_while_replacing (rtx *loc, rtx to, rtx object,
553e4b17023SJohn Marino enum machine_mode op0_mode)
554e4b17023SJohn Marino {
555e4b17023SJohn Marino rtx x = *loc;
556e4b17023SJohn Marino enum rtx_code code = GET_CODE (x);
557e4b17023SJohn Marino rtx new_rtx;
558e4b17023SJohn Marino
559e4b17023SJohn Marino if (SWAPPABLE_OPERANDS_P (x)
560e4b17023SJohn Marino && swap_commutative_operands_p (XEXP (x, 0), XEXP (x, 1)))
561e4b17023SJohn Marino {
562e4b17023SJohn Marino validate_unshare_change (object, loc,
563e4b17023SJohn Marino gen_rtx_fmt_ee (COMMUTATIVE_ARITH_P (x) ? code
564e4b17023SJohn Marino : swap_condition (code),
565e4b17023SJohn Marino GET_MODE (x), XEXP (x, 1),
566e4b17023SJohn Marino XEXP (x, 0)), 1);
567e4b17023SJohn Marino x = *loc;
568e4b17023SJohn Marino code = GET_CODE (x);
569e4b17023SJohn Marino }
570e4b17023SJohn Marino
571e4b17023SJohn Marino switch (code)
572e4b17023SJohn Marino {
573e4b17023SJohn Marino case PLUS:
574e4b17023SJohn Marino /* If we have a PLUS whose second operand is now a CONST_INT, use
575e4b17023SJohn Marino simplify_gen_binary to try to simplify it.
576e4b17023SJohn Marino ??? We may want later to remove this, once simplification is
577e4b17023SJohn Marino separated from this function. */
578e4b17023SJohn Marino if (CONST_INT_P (XEXP (x, 1)) && XEXP (x, 1) == to)
579e4b17023SJohn Marino validate_change (object, loc,
580e4b17023SJohn Marino simplify_gen_binary
581e4b17023SJohn Marino (PLUS, GET_MODE (x), XEXP (x, 0), XEXP (x, 1)), 1);
582e4b17023SJohn Marino break;
583e4b17023SJohn Marino case MINUS:
584e4b17023SJohn Marino if (CONST_INT_P (XEXP (x, 1))
585e4b17023SJohn Marino || GET_CODE (XEXP (x, 1)) == CONST_DOUBLE)
586e4b17023SJohn Marino validate_change (object, loc,
587e4b17023SJohn Marino simplify_gen_binary
588e4b17023SJohn Marino (PLUS, GET_MODE (x), XEXP (x, 0),
589e4b17023SJohn Marino simplify_gen_unary (NEG,
590e4b17023SJohn Marino GET_MODE (x), XEXP (x, 1),
591e4b17023SJohn Marino GET_MODE (x))), 1);
592e4b17023SJohn Marino break;
593e4b17023SJohn Marino case ZERO_EXTEND:
594e4b17023SJohn Marino case SIGN_EXTEND:
595e4b17023SJohn Marino if (GET_MODE (XEXP (x, 0)) == VOIDmode)
596e4b17023SJohn Marino {
597e4b17023SJohn Marino new_rtx = simplify_gen_unary (code, GET_MODE (x), XEXP (x, 0),
598e4b17023SJohn Marino op0_mode);
599e4b17023SJohn Marino /* If any of the above failed, substitute in something that
600e4b17023SJohn Marino we know won't be recognized. */
601e4b17023SJohn Marino if (!new_rtx)
602e4b17023SJohn Marino new_rtx = gen_rtx_CLOBBER (GET_MODE (x), const0_rtx);
603e4b17023SJohn Marino validate_change (object, loc, new_rtx, 1);
604e4b17023SJohn Marino }
605e4b17023SJohn Marino break;
606e4b17023SJohn Marino case SUBREG:
607e4b17023SJohn Marino /* All subregs possible to simplify should be simplified. */
608e4b17023SJohn Marino new_rtx = simplify_subreg (GET_MODE (x), SUBREG_REG (x), op0_mode,
609e4b17023SJohn Marino SUBREG_BYTE (x));
610e4b17023SJohn Marino
611e4b17023SJohn Marino /* Subregs of VOIDmode operands are incorrect. */
612e4b17023SJohn Marino if (!new_rtx && GET_MODE (SUBREG_REG (x)) == VOIDmode)
613e4b17023SJohn Marino new_rtx = gen_rtx_CLOBBER (GET_MODE (x), const0_rtx);
614e4b17023SJohn Marino if (new_rtx)
615e4b17023SJohn Marino validate_change (object, loc, new_rtx, 1);
616e4b17023SJohn Marino break;
617e4b17023SJohn Marino case ZERO_EXTRACT:
618e4b17023SJohn Marino case SIGN_EXTRACT:
619e4b17023SJohn Marino /* If we are replacing a register with memory, try to change the memory
620e4b17023SJohn Marino to be the mode required for memory in extract operations (this isn't
621e4b17023SJohn Marino likely to be an insertion operation; if it was, nothing bad will
622e4b17023SJohn Marino happen, we might just fail in some cases). */
623e4b17023SJohn Marino
624e4b17023SJohn Marino if (MEM_P (XEXP (x, 0))
625e4b17023SJohn Marino && CONST_INT_P (XEXP (x, 1))
626e4b17023SJohn Marino && CONST_INT_P (XEXP (x, 2))
627e4b17023SJohn Marino && !mode_dependent_address_p (XEXP (XEXP (x, 0), 0))
628e4b17023SJohn Marino && !MEM_VOLATILE_P (XEXP (x, 0)))
629e4b17023SJohn Marino {
630e4b17023SJohn Marino enum machine_mode wanted_mode = VOIDmode;
631e4b17023SJohn Marino enum machine_mode is_mode = GET_MODE (XEXP (x, 0));
632e4b17023SJohn Marino int pos = INTVAL (XEXP (x, 2));
633e4b17023SJohn Marino
634e4b17023SJohn Marino if (GET_CODE (x) == ZERO_EXTRACT)
635e4b17023SJohn Marino {
636e4b17023SJohn Marino enum machine_mode new_mode
637e4b17023SJohn Marino = mode_for_extraction (EP_extzv, 1);
638e4b17023SJohn Marino if (new_mode != MAX_MACHINE_MODE)
639e4b17023SJohn Marino wanted_mode = new_mode;
640e4b17023SJohn Marino }
641e4b17023SJohn Marino else if (GET_CODE (x) == SIGN_EXTRACT)
642e4b17023SJohn Marino {
643e4b17023SJohn Marino enum machine_mode new_mode
644e4b17023SJohn Marino = mode_for_extraction (EP_extv, 1);
645e4b17023SJohn Marino if (new_mode != MAX_MACHINE_MODE)
646e4b17023SJohn Marino wanted_mode = new_mode;
647e4b17023SJohn Marino }
648e4b17023SJohn Marino
649e4b17023SJohn Marino /* If we have a narrower mode, we can do something. */
650e4b17023SJohn Marino if (wanted_mode != VOIDmode
651e4b17023SJohn Marino && GET_MODE_SIZE (wanted_mode) < GET_MODE_SIZE (is_mode))
652e4b17023SJohn Marino {
653e4b17023SJohn Marino int offset = pos / BITS_PER_UNIT;
654e4b17023SJohn Marino rtx newmem;
655e4b17023SJohn Marino
656e4b17023SJohn Marino /* If the bytes and bits are counted differently, we
657e4b17023SJohn Marino must adjust the offset. */
658e4b17023SJohn Marino if (BYTES_BIG_ENDIAN != BITS_BIG_ENDIAN)
659e4b17023SJohn Marino offset =
660e4b17023SJohn Marino (GET_MODE_SIZE (is_mode) - GET_MODE_SIZE (wanted_mode) -
661e4b17023SJohn Marino offset);
662e4b17023SJohn Marino
663e4b17023SJohn Marino gcc_assert (GET_MODE_PRECISION (wanted_mode)
664e4b17023SJohn Marino == GET_MODE_BITSIZE (wanted_mode));
665e4b17023SJohn Marino pos %= GET_MODE_BITSIZE (wanted_mode);
666e4b17023SJohn Marino
667e4b17023SJohn Marino newmem = adjust_address_nv (XEXP (x, 0), wanted_mode, offset);
668e4b17023SJohn Marino
669e4b17023SJohn Marino validate_change (object, &XEXP (x, 2), GEN_INT (pos), 1);
670e4b17023SJohn Marino validate_change (object, &XEXP (x, 0), newmem, 1);
671e4b17023SJohn Marino }
672e4b17023SJohn Marino }
673e4b17023SJohn Marino
674e4b17023SJohn Marino break;
675e4b17023SJohn Marino
676e4b17023SJohn Marino default:
677e4b17023SJohn Marino break;
678e4b17023SJohn Marino }
679e4b17023SJohn Marino }
680e4b17023SJohn Marino
681e4b17023SJohn Marino /* Replace every occurrence of FROM in X with TO. Mark each change with
682e4b17023SJohn Marino validate_change passing OBJECT. */
683e4b17023SJohn Marino
684e4b17023SJohn Marino static void
validate_replace_rtx_1(rtx * loc,rtx from,rtx to,rtx object,bool simplify)685e4b17023SJohn Marino validate_replace_rtx_1 (rtx *loc, rtx from, rtx to, rtx object,
686e4b17023SJohn Marino bool simplify)
687e4b17023SJohn Marino {
688e4b17023SJohn Marino int i, j;
689e4b17023SJohn Marino const char *fmt;
690e4b17023SJohn Marino rtx x = *loc;
691e4b17023SJohn Marino enum rtx_code code;
692e4b17023SJohn Marino enum machine_mode op0_mode = VOIDmode;
693e4b17023SJohn Marino int prev_changes = num_changes;
694e4b17023SJohn Marino
695e4b17023SJohn Marino if (!x)
696e4b17023SJohn Marino return;
697e4b17023SJohn Marino
698e4b17023SJohn Marino code = GET_CODE (x);
699e4b17023SJohn Marino fmt = GET_RTX_FORMAT (code);
700e4b17023SJohn Marino if (fmt[0] == 'e')
701e4b17023SJohn Marino op0_mode = GET_MODE (XEXP (x, 0));
702e4b17023SJohn Marino
703e4b17023SJohn Marino /* X matches FROM if it is the same rtx or they are both referring to the
704e4b17023SJohn Marino same register in the same mode. Avoid calling rtx_equal_p unless the
705e4b17023SJohn Marino operands look similar. */
706e4b17023SJohn Marino
707e4b17023SJohn Marino if (x == from
708e4b17023SJohn Marino || (REG_P (x) && REG_P (from)
709e4b17023SJohn Marino && GET_MODE (x) == GET_MODE (from)
710e4b17023SJohn Marino && REGNO (x) == REGNO (from))
711e4b17023SJohn Marino || (GET_CODE (x) == GET_CODE (from) && GET_MODE (x) == GET_MODE (from)
712e4b17023SJohn Marino && rtx_equal_p (x, from)))
713e4b17023SJohn Marino {
714e4b17023SJohn Marino validate_unshare_change (object, loc, to, 1);
715e4b17023SJohn Marino return;
716e4b17023SJohn Marino }
717e4b17023SJohn Marino
718e4b17023SJohn Marino /* Call ourself recursively to perform the replacements.
719e4b17023SJohn Marino We must not replace inside already replaced expression, otherwise we
720e4b17023SJohn Marino get infinite recursion for replacements like (reg X)->(subreg (reg X))
721e4b17023SJohn Marino done by regmove, so we must special case shared ASM_OPERANDS. */
722e4b17023SJohn Marino
723e4b17023SJohn Marino if (GET_CODE (x) == PARALLEL)
724e4b17023SJohn Marino {
725e4b17023SJohn Marino for (j = XVECLEN (x, 0) - 1; j >= 0; j--)
726e4b17023SJohn Marino {
727e4b17023SJohn Marino if (j && GET_CODE (XVECEXP (x, 0, j)) == SET
728e4b17023SJohn Marino && GET_CODE (SET_SRC (XVECEXP (x, 0, j))) == ASM_OPERANDS)
729e4b17023SJohn Marino {
730e4b17023SJohn Marino /* Verify that operands are really shared. */
731e4b17023SJohn Marino gcc_assert (ASM_OPERANDS_INPUT_VEC (SET_SRC (XVECEXP (x, 0, 0)))
732e4b17023SJohn Marino == ASM_OPERANDS_INPUT_VEC (SET_SRC (XVECEXP
733e4b17023SJohn Marino (x, 0, j))));
734e4b17023SJohn Marino validate_replace_rtx_1 (&SET_DEST (XVECEXP (x, 0, j)),
735e4b17023SJohn Marino from, to, object, simplify);
736e4b17023SJohn Marino }
737e4b17023SJohn Marino else
738e4b17023SJohn Marino validate_replace_rtx_1 (&XVECEXP (x, 0, j), from, to, object,
739e4b17023SJohn Marino simplify);
740e4b17023SJohn Marino }
741e4b17023SJohn Marino }
742e4b17023SJohn Marino else
743e4b17023SJohn Marino for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
744e4b17023SJohn Marino {
745e4b17023SJohn Marino if (fmt[i] == 'e')
746e4b17023SJohn Marino validate_replace_rtx_1 (&XEXP (x, i), from, to, object, simplify);
747e4b17023SJohn Marino else if (fmt[i] == 'E')
748e4b17023SJohn Marino for (j = XVECLEN (x, i) - 1; j >= 0; j--)
749e4b17023SJohn Marino validate_replace_rtx_1 (&XVECEXP (x, i, j), from, to, object,
750e4b17023SJohn Marino simplify);
751e4b17023SJohn Marino }
752e4b17023SJohn Marino
753e4b17023SJohn Marino /* If we didn't substitute, there is nothing more to do. */
754e4b17023SJohn Marino if (num_changes == prev_changes)
755e4b17023SJohn Marino return;
756e4b17023SJohn Marino
757e4b17023SJohn Marino /* Allow substituted expression to have different mode. This is used by
758e4b17023SJohn Marino regmove to change mode of pseudo register. */
759e4b17023SJohn Marino if (fmt[0] == 'e' && GET_MODE (XEXP (x, 0)) != VOIDmode)
760e4b17023SJohn Marino op0_mode = GET_MODE (XEXP (x, 0));
761e4b17023SJohn Marino
762e4b17023SJohn Marino /* Do changes needed to keep rtx consistent. Don't do any other
763e4b17023SJohn Marino simplifications, as it is not our job. */
764e4b17023SJohn Marino if (simplify)
765e4b17023SJohn Marino simplify_while_replacing (loc, to, object, op0_mode);
766e4b17023SJohn Marino }
767e4b17023SJohn Marino
768e4b17023SJohn Marino /* Try replacing every occurrence of FROM in subexpression LOC of INSN
769e4b17023SJohn Marino with TO. After all changes have been made, validate by seeing
770e4b17023SJohn Marino if INSN is still valid. */
771e4b17023SJohn Marino
772e4b17023SJohn Marino int
validate_replace_rtx_subexp(rtx from,rtx to,rtx insn,rtx * loc)773e4b17023SJohn Marino validate_replace_rtx_subexp (rtx from, rtx to, rtx insn, rtx *loc)
774e4b17023SJohn Marino {
775e4b17023SJohn Marino validate_replace_rtx_1 (loc, from, to, insn, true);
776e4b17023SJohn Marino return apply_change_group ();
777e4b17023SJohn Marino }
778e4b17023SJohn Marino
779e4b17023SJohn Marino /* Try replacing every occurrence of FROM in INSN with TO. After all
780e4b17023SJohn Marino changes have been made, validate by seeing if INSN is still valid. */
781e4b17023SJohn Marino
782e4b17023SJohn Marino int
validate_replace_rtx(rtx from,rtx to,rtx insn)783e4b17023SJohn Marino validate_replace_rtx (rtx from, rtx to, rtx insn)
784e4b17023SJohn Marino {
785e4b17023SJohn Marino validate_replace_rtx_1 (&PATTERN (insn), from, to, insn, true);
786e4b17023SJohn Marino return apply_change_group ();
787e4b17023SJohn Marino }
788e4b17023SJohn Marino
789e4b17023SJohn Marino /* Try replacing every occurrence of FROM in WHERE with TO. Assume that WHERE
790e4b17023SJohn Marino is a part of INSN. After all changes have been made, validate by seeing if
791e4b17023SJohn Marino INSN is still valid.
792e4b17023SJohn Marino validate_replace_rtx (from, to, insn) is equivalent to
793e4b17023SJohn Marino validate_replace_rtx_part (from, to, &PATTERN (insn), insn). */
794e4b17023SJohn Marino
795e4b17023SJohn Marino int
validate_replace_rtx_part(rtx from,rtx to,rtx * where,rtx insn)796e4b17023SJohn Marino validate_replace_rtx_part (rtx from, rtx to, rtx *where, rtx insn)
797e4b17023SJohn Marino {
798e4b17023SJohn Marino validate_replace_rtx_1 (where, from, to, insn, true);
799e4b17023SJohn Marino return apply_change_group ();
800e4b17023SJohn Marino }
801e4b17023SJohn Marino
802e4b17023SJohn Marino /* Same as above, but do not simplify rtx afterwards. */
803e4b17023SJohn Marino int
validate_replace_rtx_part_nosimplify(rtx from,rtx to,rtx * where,rtx insn)804e4b17023SJohn Marino validate_replace_rtx_part_nosimplify (rtx from, rtx to, rtx *where,
805e4b17023SJohn Marino rtx insn)
806e4b17023SJohn Marino {
807e4b17023SJohn Marino validate_replace_rtx_1 (where, from, to, insn, false);
808e4b17023SJohn Marino return apply_change_group ();
809e4b17023SJohn Marino
810e4b17023SJohn Marino }
811e4b17023SJohn Marino
812e4b17023SJohn Marino /* Try replacing every occurrence of FROM in INSN with TO. This also
813e4b17023SJohn Marino will replace in REG_EQUAL and REG_EQUIV notes. */
814e4b17023SJohn Marino
815e4b17023SJohn Marino void
validate_replace_rtx_group(rtx from,rtx to,rtx insn)816e4b17023SJohn Marino validate_replace_rtx_group (rtx from, rtx to, rtx insn)
817e4b17023SJohn Marino {
818e4b17023SJohn Marino rtx note;
819e4b17023SJohn Marino validate_replace_rtx_1 (&PATTERN (insn), from, to, insn, true);
820e4b17023SJohn Marino for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
821e4b17023SJohn Marino if (REG_NOTE_KIND (note) == REG_EQUAL
822e4b17023SJohn Marino || REG_NOTE_KIND (note) == REG_EQUIV)
823e4b17023SJohn Marino validate_replace_rtx_1 (&XEXP (note, 0), from, to, insn, true);
824e4b17023SJohn Marino }
825e4b17023SJohn Marino
826e4b17023SJohn Marino /* Function called by note_uses to replace used subexpressions. */
827e4b17023SJohn Marino struct validate_replace_src_data
828e4b17023SJohn Marino {
829e4b17023SJohn Marino rtx from; /* Old RTX */
830e4b17023SJohn Marino rtx to; /* New RTX */
831e4b17023SJohn Marino rtx insn; /* Insn in which substitution is occurring. */
832e4b17023SJohn Marino };
833e4b17023SJohn Marino
834e4b17023SJohn Marino static void
validate_replace_src_1(rtx * x,void * data)835e4b17023SJohn Marino validate_replace_src_1 (rtx *x, void *data)
836e4b17023SJohn Marino {
837e4b17023SJohn Marino struct validate_replace_src_data *d
838e4b17023SJohn Marino = (struct validate_replace_src_data *) data;
839e4b17023SJohn Marino
840e4b17023SJohn Marino validate_replace_rtx_1 (x, d->from, d->to, d->insn, true);
841e4b17023SJohn Marino }
842e4b17023SJohn Marino
843e4b17023SJohn Marino /* Try replacing every occurrence of FROM in INSN with TO, avoiding
844e4b17023SJohn Marino SET_DESTs. */
845e4b17023SJohn Marino
846e4b17023SJohn Marino void
validate_replace_src_group(rtx from,rtx to,rtx insn)847e4b17023SJohn Marino validate_replace_src_group (rtx from, rtx to, rtx insn)
848e4b17023SJohn Marino {
849e4b17023SJohn Marino struct validate_replace_src_data d;
850e4b17023SJohn Marino
851e4b17023SJohn Marino d.from = from;
852e4b17023SJohn Marino d.to = to;
853e4b17023SJohn Marino d.insn = insn;
854e4b17023SJohn Marino note_uses (&PATTERN (insn), validate_replace_src_1, &d);
855e4b17023SJohn Marino }
856e4b17023SJohn Marino
857e4b17023SJohn Marino /* Try simplify INSN.
858e4b17023SJohn Marino Invoke simplify_rtx () on every SET_SRC and SET_DEST inside the INSN's
859e4b17023SJohn Marino pattern and return true if something was simplified. */
860e4b17023SJohn Marino
861e4b17023SJohn Marino bool
validate_simplify_insn(rtx insn)862e4b17023SJohn Marino validate_simplify_insn (rtx insn)
863e4b17023SJohn Marino {
864e4b17023SJohn Marino int i;
865e4b17023SJohn Marino rtx pat = NULL;
866e4b17023SJohn Marino rtx newpat = NULL;
867e4b17023SJohn Marino
868e4b17023SJohn Marino pat = PATTERN (insn);
869e4b17023SJohn Marino
870e4b17023SJohn Marino if (GET_CODE (pat) == SET)
871e4b17023SJohn Marino {
872e4b17023SJohn Marino newpat = simplify_rtx (SET_SRC (pat));
873e4b17023SJohn Marino if (newpat && !rtx_equal_p (SET_SRC (pat), newpat))
874e4b17023SJohn Marino validate_change (insn, &SET_SRC (pat), newpat, 1);
875e4b17023SJohn Marino newpat = simplify_rtx (SET_DEST (pat));
876e4b17023SJohn Marino if (newpat && !rtx_equal_p (SET_DEST (pat), newpat))
877e4b17023SJohn Marino validate_change (insn, &SET_DEST (pat), newpat, 1);
878e4b17023SJohn Marino }
879e4b17023SJohn Marino else if (GET_CODE (pat) == PARALLEL)
880e4b17023SJohn Marino for (i = 0; i < XVECLEN (pat, 0); i++)
881e4b17023SJohn Marino {
882e4b17023SJohn Marino rtx s = XVECEXP (pat, 0, i);
883e4b17023SJohn Marino
884e4b17023SJohn Marino if (GET_CODE (XVECEXP (pat, 0, i)) == SET)
885e4b17023SJohn Marino {
886e4b17023SJohn Marino newpat = simplify_rtx (SET_SRC (s));
887e4b17023SJohn Marino if (newpat && !rtx_equal_p (SET_SRC (s), newpat))
888e4b17023SJohn Marino validate_change (insn, &SET_SRC (s), newpat, 1);
889e4b17023SJohn Marino newpat = simplify_rtx (SET_DEST (s));
890e4b17023SJohn Marino if (newpat && !rtx_equal_p (SET_DEST (s), newpat))
891e4b17023SJohn Marino validate_change (insn, &SET_DEST (s), newpat, 1);
892e4b17023SJohn Marino }
893e4b17023SJohn Marino }
894e4b17023SJohn Marino return ((num_changes_pending () > 0) && (apply_change_group () > 0));
895e4b17023SJohn Marino }
896e4b17023SJohn Marino
897e4b17023SJohn Marino #ifdef HAVE_cc0
898e4b17023SJohn Marino /* Return 1 if the insn using CC0 set by INSN does not contain
899e4b17023SJohn Marino any ordered tests applied to the condition codes.
900e4b17023SJohn Marino EQ and NE tests do not count. */
901e4b17023SJohn Marino
902e4b17023SJohn Marino int
next_insn_tests_no_inequality(rtx insn)903e4b17023SJohn Marino next_insn_tests_no_inequality (rtx insn)
904e4b17023SJohn Marino {
905e4b17023SJohn Marino rtx next = next_cc0_user (insn);
906e4b17023SJohn Marino
907e4b17023SJohn Marino /* If there is no next insn, we have to take the conservative choice. */
908e4b17023SJohn Marino if (next == 0)
909e4b17023SJohn Marino return 0;
910e4b17023SJohn Marino
911e4b17023SJohn Marino return (INSN_P (next)
912e4b17023SJohn Marino && ! inequality_comparisons_p (PATTERN (next)));
913e4b17023SJohn Marino }
914e4b17023SJohn Marino #endif
915e4b17023SJohn Marino
916e4b17023SJohn Marino /* Return 1 if OP is a valid general operand for machine mode MODE.
917e4b17023SJohn Marino This is either a register reference, a memory reference,
918e4b17023SJohn Marino or a constant. In the case of a memory reference, the address
919e4b17023SJohn Marino is checked for general validity for the target machine.
920e4b17023SJohn Marino
921e4b17023SJohn Marino Register and memory references must have mode MODE in order to be valid,
922e4b17023SJohn Marino but some constants have no machine mode and are valid for any mode.
923e4b17023SJohn Marino
924e4b17023SJohn Marino If MODE is VOIDmode, OP is checked for validity for whatever mode
925e4b17023SJohn Marino it has.
926e4b17023SJohn Marino
927e4b17023SJohn Marino The main use of this function is as a predicate in match_operand
928e4b17023SJohn Marino expressions in the machine description. */
929e4b17023SJohn Marino
930e4b17023SJohn Marino int
general_operand(rtx op,enum machine_mode mode)931e4b17023SJohn Marino general_operand (rtx op, enum machine_mode mode)
932e4b17023SJohn Marino {
933e4b17023SJohn Marino enum rtx_code code = GET_CODE (op);
934e4b17023SJohn Marino
935e4b17023SJohn Marino if (mode == VOIDmode)
936e4b17023SJohn Marino mode = GET_MODE (op);
937e4b17023SJohn Marino
938e4b17023SJohn Marino /* Don't accept CONST_INT or anything similar
939e4b17023SJohn Marino if the caller wants something floating. */
940e4b17023SJohn Marino if (GET_MODE (op) == VOIDmode && mode != VOIDmode
941e4b17023SJohn Marino && GET_MODE_CLASS (mode) != MODE_INT
942e4b17023SJohn Marino && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT)
943e4b17023SJohn Marino return 0;
944e4b17023SJohn Marino
945e4b17023SJohn Marino if (CONST_INT_P (op)
946e4b17023SJohn Marino && mode != VOIDmode
947e4b17023SJohn Marino && trunc_int_for_mode (INTVAL (op), mode) != INTVAL (op))
948e4b17023SJohn Marino return 0;
949e4b17023SJohn Marino
950e4b17023SJohn Marino if (CONSTANT_P (op))
951e4b17023SJohn Marino return ((GET_MODE (op) == VOIDmode || GET_MODE (op) == mode
952e4b17023SJohn Marino || mode == VOIDmode)
953e4b17023SJohn Marino && (! flag_pic || LEGITIMATE_PIC_OPERAND_P (op))
954e4b17023SJohn Marino && targetm.legitimate_constant_p (mode == VOIDmode
955e4b17023SJohn Marino ? GET_MODE (op)
956e4b17023SJohn Marino : mode, op));
957e4b17023SJohn Marino
958e4b17023SJohn Marino /* Except for certain constants with VOIDmode, already checked for,
959e4b17023SJohn Marino OP's mode must match MODE if MODE specifies a mode. */
960e4b17023SJohn Marino
961e4b17023SJohn Marino if (GET_MODE (op) != mode)
962e4b17023SJohn Marino return 0;
963e4b17023SJohn Marino
964e4b17023SJohn Marino if (code == SUBREG)
965e4b17023SJohn Marino {
966e4b17023SJohn Marino rtx sub = SUBREG_REG (op);
967e4b17023SJohn Marino
968e4b17023SJohn Marino #ifdef INSN_SCHEDULING
969e4b17023SJohn Marino /* On machines that have insn scheduling, we want all memory
970e4b17023SJohn Marino reference to be explicit, so outlaw paradoxical SUBREGs.
971e4b17023SJohn Marino However, we must allow them after reload so that they can
972e4b17023SJohn Marino get cleaned up by cleanup_subreg_operands. */
973e4b17023SJohn Marino if (!reload_completed && MEM_P (sub)
974e4b17023SJohn Marino && GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (sub)))
975e4b17023SJohn Marino return 0;
976e4b17023SJohn Marino #endif
977e4b17023SJohn Marino /* Avoid memories with nonzero SUBREG_BYTE, as offsetting the memory
978e4b17023SJohn Marino may result in incorrect reference. We should simplify all valid
979e4b17023SJohn Marino subregs of MEM anyway. But allow this after reload because we
980e4b17023SJohn Marino might be called from cleanup_subreg_operands.
981e4b17023SJohn Marino
982e4b17023SJohn Marino ??? This is a kludge. */
983e4b17023SJohn Marino if (!reload_completed && SUBREG_BYTE (op) != 0
984e4b17023SJohn Marino && MEM_P (sub))
985e4b17023SJohn Marino return 0;
986e4b17023SJohn Marino
987e4b17023SJohn Marino /* FLOAT_MODE subregs can't be paradoxical. Combine will occasionally
988e4b17023SJohn Marino create such rtl, and we must reject it. */
989e4b17023SJohn Marino if (SCALAR_FLOAT_MODE_P (GET_MODE (op))
990e4b17023SJohn Marino && GET_MODE_SIZE (GET_MODE (op)) > GET_MODE_SIZE (GET_MODE (sub)))
991e4b17023SJohn Marino return 0;
992e4b17023SJohn Marino
993e4b17023SJohn Marino op = sub;
994e4b17023SJohn Marino code = GET_CODE (op);
995e4b17023SJohn Marino }
996e4b17023SJohn Marino
997e4b17023SJohn Marino if (code == REG)
998e4b17023SJohn Marino return (REGNO (op) >= FIRST_PSEUDO_REGISTER
999e4b17023SJohn Marino || in_hard_reg_set_p (operand_reg_set, GET_MODE (op), REGNO (op)));
1000e4b17023SJohn Marino
1001e4b17023SJohn Marino if (code == MEM)
1002e4b17023SJohn Marino {
1003e4b17023SJohn Marino rtx y = XEXP (op, 0);
1004e4b17023SJohn Marino
1005e4b17023SJohn Marino if (! volatile_ok && MEM_VOLATILE_P (op))
1006e4b17023SJohn Marino return 0;
1007e4b17023SJohn Marino
1008e4b17023SJohn Marino /* Use the mem's mode, since it will be reloaded thus. */
1009e4b17023SJohn Marino if (memory_address_addr_space_p (GET_MODE (op), y, MEM_ADDR_SPACE (op)))
1010e4b17023SJohn Marino return 1;
1011e4b17023SJohn Marino }
1012e4b17023SJohn Marino
1013e4b17023SJohn Marino return 0;
1014e4b17023SJohn Marino }
1015e4b17023SJohn Marino
1016e4b17023SJohn Marino /* Return 1 if OP is a valid memory address for a memory reference
1017e4b17023SJohn Marino of mode MODE.
1018e4b17023SJohn Marino
1019e4b17023SJohn Marino The main use of this function is as a predicate in match_operand
1020e4b17023SJohn Marino expressions in the machine description. */
1021e4b17023SJohn Marino
1022e4b17023SJohn Marino int
address_operand(rtx op,enum machine_mode mode)1023e4b17023SJohn Marino address_operand (rtx op, enum machine_mode mode)
1024e4b17023SJohn Marino {
1025e4b17023SJohn Marino return memory_address_p (mode, op);
1026e4b17023SJohn Marino }
1027e4b17023SJohn Marino
1028e4b17023SJohn Marino /* Return 1 if OP is a register reference of mode MODE.
1029e4b17023SJohn Marino If MODE is VOIDmode, accept a register in any mode.
1030e4b17023SJohn Marino
1031e4b17023SJohn Marino The main use of this function is as a predicate in match_operand
1032e4b17023SJohn Marino expressions in the machine description. */
1033e4b17023SJohn Marino
1034e4b17023SJohn Marino int
register_operand(rtx op,enum machine_mode mode)1035e4b17023SJohn Marino register_operand (rtx op, enum machine_mode mode)
1036e4b17023SJohn Marino {
1037e4b17023SJohn Marino if (GET_MODE (op) != mode && mode != VOIDmode)
1038e4b17023SJohn Marino return 0;
1039e4b17023SJohn Marino
1040e4b17023SJohn Marino if (GET_CODE (op) == SUBREG)
1041e4b17023SJohn Marino {
1042e4b17023SJohn Marino rtx sub = SUBREG_REG (op);
1043e4b17023SJohn Marino
1044e4b17023SJohn Marino /* Before reload, we can allow (SUBREG (MEM...)) as a register operand
1045e4b17023SJohn Marino because it is guaranteed to be reloaded into one.
1046e4b17023SJohn Marino Just make sure the MEM is valid in itself.
1047e4b17023SJohn Marino (Ideally, (SUBREG (MEM)...) should not exist after reload,
1048e4b17023SJohn Marino but currently it does result from (SUBREG (REG)...) where the
1049e4b17023SJohn Marino reg went on the stack.) */
1050e4b17023SJohn Marino if (! reload_completed && MEM_P (sub))
1051e4b17023SJohn Marino return general_operand (op, mode);
1052e4b17023SJohn Marino
1053e4b17023SJohn Marino #ifdef CANNOT_CHANGE_MODE_CLASS
1054e4b17023SJohn Marino if (REG_P (sub)
1055e4b17023SJohn Marino && REGNO (sub) < FIRST_PSEUDO_REGISTER
1056e4b17023SJohn Marino && REG_CANNOT_CHANGE_MODE_P (REGNO (sub), GET_MODE (sub), mode)
1057e4b17023SJohn Marino && GET_MODE_CLASS (GET_MODE (sub)) != MODE_COMPLEX_INT
1058e4b17023SJohn Marino && GET_MODE_CLASS (GET_MODE (sub)) != MODE_COMPLEX_FLOAT)
1059e4b17023SJohn Marino return 0;
1060e4b17023SJohn Marino #endif
1061e4b17023SJohn Marino
1062e4b17023SJohn Marino /* FLOAT_MODE subregs can't be paradoxical. Combine will occasionally
1063e4b17023SJohn Marino create such rtl, and we must reject it. */
1064e4b17023SJohn Marino if (SCALAR_FLOAT_MODE_P (GET_MODE (op))
1065e4b17023SJohn Marino && GET_MODE_SIZE (GET_MODE (op)) > GET_MODE_SIZE (GET_MODE (sub)))
1066e4b17023SJohn Marino return 0;
1067e4b17023SJohn Marino
1068e4b17023SJohn Marino op = sub;
1069e4b17023SJohn Marino }
1070e4b17023SJohn Marino
1071e4b17023SJohn Marino return (REG_P (op)
1072e4b17023SJohn Marino && (REGNO (op) >= FIRST_PSEUDO_REGISTER
1073e4b17023SJohn Marino || in_hard_reg_set_p (operand_reg_set,
1074e4b17023SJohn Marino GET_MODE (op), REGNO (op))));
1075e4b17023SJohn Marino }
1076e4b17023SJohn Marino
1077e4b17023SJohn Marino /* Return 1 for a register in Pmode; ignore the tested mode. */
1078e4b17023SJohn Marino
1079e4b17023SJohn Marino int
pmode_register_operand(rtx op,enum machine_mode mode ATTRIBUTE_UNUSED)1080e4b17023SJohn Marino pmode_register_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
1081e4b17023SJohn Marino {
1082e4b17023SJohn Marino return register_operand (op, Pmode);
1083e4b17023SJohn Marino }
1084e4b17023SJohn Marino
1085e4b17023SJohn Marino /* Return 1 if OP should match a MATCH_SCRATCH, i.e., if it is a SCRATCH
1086e4b17023SJohn Marino or a hard register. */
1087e4b17023SJohn Marino
1088e4b17023SJohn Marino int
scratch_operand(rtx op,enum machine_mode mode)1089e4b17023SJohn Marino scratch_operand (rtx op, enum machine_mode mode)
1090e4b17023SJohn Marino {
1091e4b17023SJohn Marino if (GET_MODE (op) != mode && mode != VOIDmode)
1092e4b17023SJohn Marino return 0;
1093e4b17023SJohn Marino
1094e4b17023SJohn Marino return (GET_CODE (op) == SCRATCH
1095e4b17023SJohn Marino || (REG_P (op)
1096e4b17023SJohn Marino && REGNO (op) < FIRST_PSEUDO_REGISTER));
1097e4b17023SJohn Marino }
1098e4b17023SJohn Marino
1099e4b17023SJohn Marino /* Return 1 if OP is a valid immediate operand for mode MODE.
1100e4b17023SJohn Marino
1101e4b17023SJohn Marino The main use of this function is as a predicate in match_operand
1102e4b17023SJohn Marino expressions in the machine description. */
1103e4b17023SJohn Marino
1104e4b17023SJohn Marino int
immediate_operand(rtx op,enum machine_mode mode)1105e4b17023SJohn Marino immediate_operand (rtx op, enum machine_mode mode)
1106e4b17023SJohn Marino {
1107e4b17023SJohn Marino /* Don't accept CONST_INT or anything similar
1108e4b17023SJohn Marino if the caller wants something floating. */
1109e4b17023SJohn Marino if (GET_MODE (op) == VOIDmode && mode != VOIDmode
1110e4b17023SJohn Marino && GET_MODE_CLASS (mode) != MODE_INT
1111e4b17023SJohn Marino && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT)
1112e4b17023SJohn Marino return 0;
1113e4b17023SJohn Marino
1114e4b17023SJohn Marino if (CONST_INT_P (op)
1115e4b17023SJohn Marino && mode != VOIDmode
1116e4b17023SJohn Marino && trunc_int_for_mode (INTVAL (op), mode) != INTVAL (op))
1117e4b17023SJohn Marino return 0;
1118e4b17023SJohn Marino
1119e4b17023SJohn Marino return (CONSTANT_P (op)
1120e4b17023SJohn Marino && (GET_MODE (op) == mode || mode == VOIDmode
1121e4b17023SJohn Marino || GET_MODE (op) == VOIDmode)
1122e4b17023SJohn Marino && (! flag_pic || LEGITIMATE_PIC_OPERAND_P (op))
1123e4b17023SJohn Marino && targetm.legitimate_constant_p (mode == VOIDmode
1124e4b17023SJohn Marino ? GET_MODE (op)
1125e4b17023SJohn Marino : mode, op));
1126e4b17023SJohn Marino }
1127e4b17023SJohn Marino
1128e4b17023SJohn Marino /* Returns 1 if OP is an operand that is a CONST_INT. */
1129e4b17023SJohn Marino
1130e4b17023SJohn Marino int
const_int_operand(rtx op,enum machine_mode mode)1131e4b17023SJohn Marino const_int_operand (rtx op, enum machine_mode mode)
1132e4b17023SJohn Marino {
1133e4b17023SJohn Marino if (!CONST_INT_P (op))
1134e4b17023SJohn Marino return 0;
1135e4b17023SJohn Marino
1136e4b17023SJohn Marino if (mode != VOIDmode
1137e4b17023SJohn Marino && trunc_int_for_mode (INTVAL (op), mode) != INTVAL (op))
1138e4b17023SJohn Marino return 0;
1139e4b17023SJohn Marino
1140e4b17023SJohn Marino return 1;
1141e4b17023SJohn Marino }
1142e4b17023SJohn Marino
1143e4b17023SJohn Marino /* Returns 1 if OP is an operand that is a constant integer or constant
1144e4b17023SJohn Marino floating-point number. */
1145e4b17023SJohn Marino
1146e4b17023SJohn Marino int
const_double_operand(rtx op,enum machine_mode mode)1147e4b17023SJohn Marino const_double_operand (rtx op, enum machine_mode mode)
1148e4b17023SJohn Marino {
1149e4b17023SJohn Marino /* Don't accept CONST_INT or anything similar
1150e4b17023SJohn Marino if the caller wants something floating. */
1151e4b17023SJohn Marino if (GET_MODE (op) == VOIDmode && mode != VOIDmode
1152e4b17023SJohn Marino && GET_MODE_CLASS (mode) != MODE_INT
1153e4b17023SJohn Marino && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT)
1154e4b17023SJohn Marino return 0;
1155e4b17023SJohn Marino
1156e4b17023SJohn Marino return ((GET_CODE (op) == CONST_DOUBLE || CONST_INT_P (op))
1157e4b17023SJohn Marino && (mode == VOIDmode || GET_MODE (op) == mode
1158e4b17023SJohn Marino || GET_MODE (op) == VOIDmode));
1159e4b17023SJohn Marino }
1160e4b17023SJohn Marino
1161e4b17023SJohn Marino /* Return 1 if OP is a general operand that is not an immediate operand. */
1162e4b17023SJohn Marino
1163e4b17023SJohn Marino int
nonimmediate_operand(rtx op,enum machine_mode mode)1164e4b17023SJohn Marino nonimmediate_operand (rtx op, enum machine_mode mode)
1165e4b17023SJohn Marino {
1166e4b17023SJohn Marino return (general_operand (op, mode) && ! CONSTANT_P (op));
1167e4b17023SJohn Marino }
1168e4b17023SJohn Marino
1169e4b17023SJohn Marino /* Return 1 if OP is a register reference or immediate value of mode MODE. */
1170e4b17023SJohn Marino
1171e4b17023SJohn Marino int
nonmemory_operand(rtx op,enum machine_mode mode)1172e4b17023SJohn Marino nonmemory_operand (rtx op, enum machine_mode mode)
1173e4b17023SJohn Marino {
1174e4b17023SJohn Marino if (CONSTANT_P (op))
1175e4b17023SJohn Marino return immediate_operand (op, mode);
1176e4b17023SJohn Marino
1177e4b17023SJohn Marino if (GET_MODE (op) != mode && mode != VOIDmode)
1178e4b17023SJohn Marino return 0;
1179e4b17023SJohn Marino
1180e4b17023SJohn Marino if (GET_CODE (op) == SUBREG)
1181e4b17023SJohn Marino {
1182e4b17023SJohn Marino /* Before reload, we can allow (SUBREG (MEM...)) as a register operand
1183e4b17023SJohn Marino because it is guaranteed to be reloaded into one.
1184e4b17023SJohn Marino Just make sure the MEM is valid in itself.
1185e4b17023SJohn Marino (Ideally, (SUBREG (MEM)...) should not exist after reload,
1186e4b17023SJohn Marino but currently it does result from (SUBREG (REG)...) where the
1187e4b17023SJohn Marino reg went on the stack.) */
1188e4b17023SJohn Marino if (! reload_completed && MEM_P (SUBREG_REG (op)))
1189e4b17023SJohn Marino return general_operand (op, mode);
1190e4b17023SJohn Marino op = SUBREG_REG (op);
1191e4b17023SJohn Marino }
1192e4b17023SJohn Marino
1193e4b17023SJohn Marino return (REG_P (op)
1194e4b17023SJohn Marino && (REGNO (op) >= FIRST_PSEUDO_REGISTER
1195e4b17023SJohn Marino || in_hard_reg_set_p (operand_reg_set,
1196e4b17023SJohn Marino GET_MODE (op), REGNO (op))));
1197e4b17023SJohn Marino }
1198e4b17023SJohn Marino
1199e4b17023SJohn Marino /* Return 1 if OP is a valid operand that stands for pushing a
1200e4b17023SJohn Marino value of mode MODE onto the stack.
1201e4b17023SJohn Marino
1202e4b17023SJohn Marino The main use of this function is as a predicate in match_operand
1203e4b17023SJohn Marino expressions in the machine description. */
1204e4b17023SJohn Marino
1205e4b17023SJohn Marino int
push_operand(rtx op,enum machine_mode mode)1206e4b17023SJohn Marino push_operand (rtx op, enum machine_mode mode)
1207e4b17023SJohn Marino {
1208e4b17023SJohn Marino unsigned int rounded_size = GET_MODE_SIZE (mode);
1209e4b17023SJohn Marino
1210e4b17023SJohn Marino #ifdef PUSH_ROUNDING
1211e4b17023SJohn Marino rounded_size = PUSH_ROUNDING (rounded_size);
1212e4b17023SJohn Marino #endif
1213e4b17023SJohn Marino
1214e4b17023SJohn Marino if (!MEM_P (op))
1215e4b17023SJohn Marino return 0;
1216e4b17023SJohn Marino
1217e4b17023SJohn Marino if (mode != VOIDmode && GET_MODE (op) != mode)
1218e4b17023SJohn Marino return 0;
1219e4b17023SJohn Marino
1220e4b17023SJohn Marino op = XEXP (op, 0);
1221e4b17023SJohn Marino
1222e4b17023SJohn Marino if (rounded_size == GET_MODE_SIZE (mode))
1223e4b17023SJohn Marino {
1224e4b17023SJohn Marino if (GET_CODE (op) != STACK_PUSH_CODE)
1225e4b17023SJohn Marino return 0;
1226e4b17023SJohn Marino }
1227e4b17023SJohn Marino else
1228e4b17023SJohn Marino {
1229e4b17023SJohn Marino if (GET_CODE (op) != PRE_MODIFY
1230e4b17023SJohn Marino || GET_CODE (XEXP (op, 1)) != PLUS
1231e4b17023SJohn Marino || XEXP (XEXP (op, 1), 0) != XEXP (op, 0)
1232e4b17023SJohn Marino || !CONST_INT_P (XEXP (XEXP (op, 1), 1))
1233e4b17023SJohn Marino #ifdef STACK_GROWS_DOWNWARD
1234e4b17023SJohn Marino || INTVAL (XEXP (XEXP (op, 1), 1)) != - (int) rounded_size
1235e4b17023SJohn Marino #else
1236e4b17023SJohn Marino || INTVAL (XEXP (XEXP (op, 1), 1)) != (int) rounded_size
1237e4b17023SJohn Marino #endif
1238e4b17023SJohn Marino )
1239e4b17023SJohn Marino return 0;
1240e4b17023SJohn Marino }
1241e4b17023SJohn Marino
1242e4b17023SJohn Marino return XEXP (op, 0) == stack_pointer_rtx;
1243e4b17023SJohn Marino }
1244e4b17023SJohn Marino
1245e4b17023SJohn Marino /* Return 1 if OP is a valid operand that stands for popping a
1246e4b17023SJohn Marino value of mode MODE off the stack.
1247e4b17023SJohn Marino
1248e4b17023SJohn Marino The main use of this function is as a predicate in match_operand
1249e4b17023SJohn Marino expressions in the machine description. */
1250e4b17023SJohn Marino
1251e4b17023SJohn Marino int
pop_operand(rtx op,enum machine_mode mode)1252e4b17023SJohn Marino pop_operand (rtx op, enum machine_mode mode)
1253e4b17023SJohn Marino {
1254e4b17023SJohn Marino if (!MEM_P (op))
1255e4b17023SJohn Marino return 0;
1256e4b17023SJohn Marino
1257e4b17023SJohn Marino if (mode != VOIDmode && GET_MODE (op) != mode)
1258e4b17023SJohn Marino return 0;
1259e4b17023SJohn Marino
1260e4b17023SJohn Marino op = XEXP (op, 0);
1261e4b17023SJohn Marino
1262e4b17023SJohn Marino if (GET_CODE (op) != STACK_POP_CODE)
1263e4b17023SJohn Marino return 0;
1264e4b17023SJohn Marino
1265e4b17023SJohn Marino return XEXP (op, 0) == stack_pointer_rtx;
1266e4b17023SJohn Marino }
1267e4b17023SJohn Marino
1268e4b17023SJohn Marino /* Return 1 if ADDR is a valid memory address
1269e4b17023SJohn Marino for mode MODE in address space AS. */
1270e4b17023SJohn Marino
1271e4b17023SJohn Marino int
memory_address_addr_space_p(enum machine_mode mode ATTRIBUTE_UNUSED,rtx addr,addr_space_t as)1272e4b17023SJohn Marino memory_address_addr_space_p (enum machine_mode mode ATTRIBUTE_UNUSED,
1273e4b17023SJohn Marino rtx addr, addr_space_t as)
1274e4b17023SJohn Marino {
1275e4b17023SJohn Marino #ifdef GO_IF_LEGITIMATE_ADDRESS
1276e4b17023SJohn Marino gcc_assert (ADDR_SPACE_GENERIC_P (as));
1277e4b17023SJohn Marino GO_IF_LEGITIMATE_ADDRESS (mode, addr, win);
1278e4b17023SJohn Marino return 0;
1279e4b17023SJohn Marino
1280e4b17023SJohn Marino win:
1281e4b17023SJohn Marino return 1;
1282e4b17023SJohn Marino #else
1283e4b17023SJohn Marino return targetm.addr_space.legitimate_address_p (mode, addr, 0, as);
1284e4b17023SJohn Marino #endif
1285e4b17023SJohn Marino }
1286e4b17023SJohn Marino
1287e4b17023SJohn Marino /* Return 1 if OP is a valid memory reference with mode MODE,
1288e4b17023SJohn Marino including a valid address.
1289e4b17023SJohn Marino
1290e4b17023SJohn Marino The main use of this function is as a predicate in match_operand
1291e4b17023SJohn Marino expressions in the machine description. */
1292e4b17023SJohn Marino
1293e4b17023SJohn Marino int
memory_operand(rtx op,enum machine_mode mode)1294e4b17023SJohn Marino memory_operand (rtx op, enum machine_mode mode)
1295e4b17023SJohn Marino {
1296e4b17023SJohn Marino rtx inner;
1297e4b17023SJohn Marino
1298e4b17023SJohn Marino if (! reload_completed)
1299e4b17023SJohn Marino /* Note that no SUBREG is a memory operand before end of reload pass,
1300e4b17023SJohn Marino because (SUBREG (MEM...)) forces reloading into a register. */
1301e4b17023SJohn Marino return MEM_P (op) && general_operand (op, mode);
1302e4b17023SJohn Marino
1303e4b17023SJohn Marino if (mode != VOIDmode && GET_MODE (op) != mode)
1304e4b17023SJohn Marino return 0;
1305e4b17023SJohn Marino
1306e4b17023SJohn Marino inner = op;
1307e4b17023SJohn Marino if (GET_CODE (inner) == SUBREG)
1308e4b17023SJohn Marino inner = SUBREG_REG (inner);
1309e4b17023SJohn Marino
1310e4b17023SJohn Marino return (MEM_P (inner) && general_operand (op, mode));
1311e4b17023SJohn Marino }
1312e4b17023SJohn Marino
1313e4b17023SJohn Marino /* Return 1 if OP is a valid indirect memory reference with mode MODE;
1314e4b17023SJohn Marino that is, a memory reference whose address is a general_operand. */
1315e4b17023SJohn Marino
1316e4b17023SJohn Marino int
indirect_operand(rtx op,enum machine_mode mode)1317e4b17023SJohn Marino indirect_operand (rtx op, enum machine_mode mode)
1318e4b17023SJohn Marino {
1319e4b17023SJohn Marino /* Before reload, a SUBREG isn't in memory (see memory_operand, above). */
1320e4b17023SJohn Marino if (! reload_completed
1321e4b17023SJohn Marino && GET_CODE (op) == SUBREG && MEM_P (SUBREG_REG (op)))
1322e4b17023SJohn Marino {
1323e4b17023SJohn Marino int offset = SUBREG_BYTE (op);
1324e4b17023SJohn Marino rtx inner = SUBREG_REG (op);
1325e4b17023SJohn Marino
1326e4b17023SJohn Marino if (mode != VOIDmode && GET_MODE (op) != mode)
1327e4b17023SJohn Marino return 0;
1328e4b17023SJohn Marino
1329e4b17023SJohn Marino /* The only way that we can have a general_operand as the resulting
1330e4b17023SJohn Marino address is if OFFSET is zero and the address already is an operand
1331e4b17023SJohn Marino or if the address is (plus Y (const_int -OFFSET)) and Y is an
1332e4b17023SJohn Marino operand. */
1333e4b17023SJohn Marino
1334e4b17023SJohn Marino return ((offset == 0 && general_operand (XEXP (inner, 0), Pmode))
1335e4b17023SJohn Marino || (GET_CODE (XEXP (inner, 0)) == PLUS
1336e4b17023SJohn Marino && CONST_INT_P (XEXP (XEXP (inner, 0), 1))
1337e4b17023SJohn Marino && INTVAL (XEXP (XEXP (inner, 0), 1)) == -offset
1338e4b17023SJohn Marino && general_operand (XEXP (XEXP (inner, 0), 0), Pmode)));
1339e4b17023SJohn Marino }
1340e4b17023SJohn Marino
1341e4b17023SJohn Marino return (MEM_P (op)
1342e4b17023SJohn Marino && memory_operand (op, mode)
1343e4b17023SJohn Marino && general_operand (XEXP (op, 0), Pmode));
1344e4b17023SJohn Marino }
1345e4b17023SJohn Marino
1346e4b17023SJohn Marino /* Return 1 if this is an ordered comparison operator (not including
1347e4b17023SJohn Marino ORDERED and UNORDERED). */
1348e4b17023SJohn Marino
1349e4b17023SJohn Marino int
ordered_comparison_operator(rtx op,enum machine_mode mode)1350e4b17023SJohn Marino ordered_comparison_operator (rtx op, enum machine_mode mode)
1351e4b17023SJohn Marino {
1352e4b17023SJohn Marino if (mode != VOIDmode && GET_MODE (op) != mode)
1353e4b17023SJohn Marino return false;
1354e4b17023SJohn Marino switch (GET_CODE (op))
1355e4b17023SJohn Marino {
1356e4b17023SJohn Marino case EQ:
1357e4b17023SJohn Marino case NE:
1358e4b17023SJohn Marino case LT:
1359e4b17023SJohn Marino case LTU:
1360e4b17023SJohn Marino case LE:
1361e4b17023SJohn Marino case LEU:
1362e4b17023SJohn Marino case GT:
1363e4b17023SJohn Marino case GTU:
1364e4b17023SJohn Marino case GE:
1365e4b17023SJohn Marino case GEU:
1366e4b17023SJohn Marino return true;
1367e4b17023SJohn Marino default:
1368e4b17023SJohn Marino return false;
1369e4b17023SJohn Marino }
1370e4b17023SJohn Marino }
1371e4b17023SJohn Marino
1372e4b17023SJohn Marino /* Return 1 if this is a comparison operator. This allows the use of
1373e4b17023SJohn Marino MATCH_OPERATOR to recognize all the branch insns. */
1374e4b17023SJohn Marino
1375e4b17023SJohn Marino int
comparison_operator(rtx op,enum machine_mode mode)1376e4b17023SJohn Marino comparison_operator (rtx op, enum machine_mode mode)
1377e4b17023SJohn Marino {
1378e4b17023SJohn Marino return ((mode == VOIDmode || GET_MODE (op) == mode)
1379e4b17023SJohn Marino && COMPARISON_P (op));
1380e4b17023SJohn Marino }
1381e4b17023SJohn Marino
1382e4b17023SJohn Marino /* If BODY is an insn body that uses ASM_OPERANDS, return it. */
1383e4b17023SJohn Marino
1384e4b17023SJohn Marino rtx
extract_asm_operands(rtx body)1385e4b17023SJohn Marino extract_asm_operands (rtx body)
1386e4b17023SJohn Marino {
1387e4b17023SJohn Marino rtx tmp;
1388e4b17023SJohn Marino switch (GET_CODE (body))
1389e4b17023SJohn Marino {
1390e4b17023SJohn Marino case ASM_OPERANDS:
1391e4b17023SJohn Marino return body;
1392e4b17023SJohn Marino
1393e4b17023SJohn Marino case SET:
1394e4b17023SJohn Marino /* Single output operand: BODY is (set OUTPUT (asm_operands ...)). */
1395e4b17023SJohn Marino tmp = SET_SRC (body);
1396e4b17023SJohn Marino if (GET_CODE (tmp) == ASM_OPERANDS)
1397e4b17023SJohn Marino return tmp;
1398e4b17023SJohn Marino break;
1399e4b17023SJohn Marino
1400e4b17023SJohn Marino case PARALLEL:
1401e4b17023SJohn Marino tmp = XVECEXP (body, 0, 0);
1402e4b17023SJohn Marino if (GET_CODE (tmp) == ASM_OPERANDS)
1403e4b17023SJohn Marino return tmp;
1404e4b17023SJohn Marino if (GET_CODE (tmp) == SET)
1405e4b17023SJohn Marino {
1406e4b17023SJohn Marino tmp = SET_SRC (tmp);
1407e4b17023SJohn Marino if (GET_CODE (tmp) == ASM_OPERANDS)
1408e4b17023SJohn Marino return tmp;
1409e4b17023SJohn Marino }
1410e4b17023SJohn Marino break;
1411e4b17023SJohn Marino
1412e4b17023SJohn Marino default:
1413e4b17023SJohn Marino break;
1414e4b17023SJohn Marino }
1415e4b17023SJohn Marino return NULL;
1416e4b17023SJohn Marino }
1417e4b17023SJohn Marino
1418e4b17023SJohn Marino /* If BODY is an insn body that uses ASM_OPERANDS,
1419e4b17023SJohn Marino return the number of operands (both input and output) in the insn.
1420e4b17023SJohn Marino Otherwise return -1. */
1421e4b17023SJohn Marino
1422e4b17023SJohn Marino int
asm_noperands(const_rtx body)1423e4b17023SJohn Marino asm_noperands (const_rtx body)
1424e4b17023SJohn Marino {
1425e4b17023SJohn Marino rtx asm_op = extract_asm_operands (CONST_CAST_RTX (body));
1426e4b17023SJohn Marino int n_sets = 0;
1427e4b17023SJohn Marino
1428e4b17023SJohn Marino if (asm_op == NULL)
1429e4b17023SJohn Marino return -1;
1430e4b17023SJohn Marino
1431e4b17023SJohn Marino if (GET_CODE (body) == SET)
1432e4b17023SJohn Marino n_sets = 1;
1433e4b17023SJohn Marino else if (GET_CODE (body) == PARALLEL)
1434e4b17023SJohn Marino {
1435e4b17023SJohn Marino int i;
1436e4b17023SJohn Marino if (GET_CODE (XVECEXP (body, 0, 0)) == SET)
1437e4b17023SJohn Marino {
1438e4b17023SJohn Marino /* Multiple output operands, or 1 output plus some clobbers:
1439e4b17023SJohn Marino body is
1440e4b17023SJohn Marino [(set OUTPUT (asm_operands ...))... (clobber (reg ...))...]. */
1441e4b17023SJohn Marino /* Count backwards through CLOBBERs to determine number of SETs. */
1442e4b17023SJohn Marino for (i = XVECLEN (body, 0); i > 0; i--)
1443e4b17023SJohn Marino {
1444e4b17023SJohn Marino if (GET_CODE (XVECEXP (body, 0, i - 1)) == SET)
1445e4b17023SJohn Marino break;
1446e4b17023SJohn Marino if (GET_CODE (XVECEXP (body, 0, i - 1)) != CLOBBER)
1447e4b17023SJohn Marino return -1;
1448e4b17023SJohn Marino }
1449e4b17023SJohn Marino
1450e4b17023SJohn Marino /* N_SETS is now number of output operands. */
1451e4b17023SJohn Marino n_sets = i;
1452e4b17023SJohn Marino
1453e4b17023SJohn Marino /* Verify that all the SETs we have
1454e4b17023SJohn Marino came from a single original asm_operands insn
1455e4b17023SJohn Marino (so that invalid combinations are blocked). */
1456e4b17023SJohn Marino for (i = 0; i < n_sets; i++)
1457e4b17023SJohn Marino {
1458e4b17023SJohn Marino rtx elt = XVECEXP (body, 0, i);
1459e4b17023SJohn Marino if (GET_CODE (elt) != SET)
1460e4b17023SJohn Marino return -1;
1461e4b17023SJohn Marino if (GET_CODE (SET_SRC (elt)) != ASM_OPERANDS)
1462e4b17023SJohn Marino return -1;
1463e4b17023SJohn Marino /* If these ASM_OPERANDS rtx's came from different original insns
1464e4b17023SJohn Marino then they aren't allowed together. */
1465e4b17023SJohn Marino if (ASM_OPERANDS_INPUT_VEC (SET_SRC (elt))
1466e4b17023SJohn Marino != ASM_OPERANDS_INPUT_VEC (asm_op))
1467e4b17023SJohn Marino return -1;
1468e4b17023SJohn Marino }
1469e4b17023SJohn Marino }
1470e4b17023SJohn Marino else
1471e4b17023SJohn Marino {
1472e4b17023SJohn Marino /* 0 outputs, but some clobbers:
1473e4b17023SJohn Marino body is [(asm_operands ...) (clobber (reg ...))...]. */
1474e4b17023SJohn Marino /* Make sure all the other parallel things really are clobbers. */
1475e4b17023SJohn Marino for (i = XVECLEN (body, 0) - 1; i > 0; i--)
1476e4b17023SJohn Marino if (GET_CODE (XVECEXP (body, 0, i)) != CLOBBER)
1477e4b17023SJohn Marino return -1;
1478e4b17023SJohn Marino }
1479e4b17023SJohn Marino }
1480e4b17023SJohn Marino
1481e4b17023SJohn Marino return (ASM_OPERANDS_INPUT_LENGTH (asm_op)
1482e4b17023SJohn Marino + ASM_OPERANDS_LABEL_LENGTH (asm_op) + n_sets);
1483e4b17023SJohn Marino }
1484e4b17023SJohn Marino
1485e4b17023SJohn Marino /* Assuming BODY is an insn body that uses ASM_OPERANDS,
1486e4b17023SJohn Marino copy its operands (both input and output) into the vector OPERANDS,
1487e4b17023SJohn Marino the locations of the operands within the insn into the vector OPERAND_LOCS,
1488e4b17023SJohn Marino and the constraints for the operands into CONSTRAINTS.
1489e4b17023SJohn Marino Write the modes of the operands into MODES.
1490e4b17023SJohn Marino Return the assembler-template.
1491e4b17023SJohn Marino
1492e4b17023SJohn Marino If MODES, OPERAND_LOCS, CONSTRAINTS or OPERANDS is 0,
1493e4b17023SJohn Marino we don't store that info. */
1494e4b17023SJohn Marino
1495e4b17023SJohn Marino const char *
decode_asm_operands(rtx body,rtx * operands,rtx ** operand_locs,const char ** constraints,enum machine_mode * modes,location_t * loc)1496e4b17023SJohn Marino decode_asm_operands (rtx body, rtx *operands, rtx **operand_locs,
1497e4b17023SJohn Marino const char **constraints, enum machine_mode *modes,
1498e4b17023SJohn Marino location_t *loc)
1499e4b17023SJohn Marino {
1500e4b17023SJohn Marino int nbase = 0, n, i;
1501e4b17023SJohn Marino rtx asmop;
1502e4b17023SJohn Marino
1503e4b17023SJohn Marino switch (GET_CODE (body))
1504e4b17023SJohn Marino {
1505e4b17023SJohn Marino case ASM_OPERANDS:
1506e4b17023SJohn Marino /* Zero output asm: BODY is (asm_operands ...). */
1507e4b17023SJohn Marino asmop = body;
1508e4b17023SJohn Marino break;
1509e4b17023SJohn Marino
1510e4b17023SJohn Marino case SET:
1511e4b17023SJohn Marino /* Single output asm: BODY is (set OUTPUT (asm_operands ...)). */
1512e4b17023SJohn Marino asmop = SET_SRC (body);
1513e4b17023SJohn Marino
1514e4b17023SJohn Marino /* The output is in the SET.
1515e4b17023SJohn Marino Its constraint is in the ASM_OPERANDS itself. */
1516e4b17023SJohn Marino if (operands)
1517e4b17023SJohn Marino operands[0] = SET_DEST (body);
1518e4b17023SJohn Marino if (operand_locs)
1519e4b17023SJohn Marino operand_locs[0] = &SET_DEST (body);
1520e4b17023SJohn Marino if (constraints)
1521e4b17023SJohn Marino constraints[0] = ASM_OPERANDS_OUTPUT_CONSTRAINT (asmop);
1522e4b17023SJohn Marino if (modes)
1523e4b17023SJohn Marino modes[0] = GET_MODE (SET_DEST (body));
1524e4b17023SJohn Marino nbase = 1;
1525e4b17023SJohn Marino break;
1526e4b17023SJohn Marino
1527e4b17023SJohn Marino case PARALLEL:
1528e4b17023SJohn Marino {
1529e4b17023SJohn Marino int nparallel = XVECLEN (body, 0); /* Includes CLOBBERs. */
1530e4b17023SJohn Marino
1531e4b17023SJohn Marino asmop = XVECEXP (body, 0, 0);
1532e4b17023SJohn Marino if (GET_CODE (asmop) == SET)
1533e4b17023SJohn Marino {
1534e4b17023SJohn Marino asmop = SET_SRC (asmop);
1535e4b17023SJohn Marino
1536e4b17023SJohn Marino /* At least one output, plus some CLOBBERs. The outputs are in
1537e4b17023SJohn Marino the SETs. Their constraints are in the ASM_OPERANDS itself. */
1538e4b17023SJohn Marino for (i = 0; i < nparallel; i++)
1539e4b17023SJohn Marino {
1540e4b17023SJohn Marino if (GET_CODE (XVECEXP (body, 0, i)) == CLOBBER)
1541e4b17023SJohn Marino break; /* Past last SET */
1542e4b17023SJohn Marino if (operands)
1543e4b17023SJohn Marino operands[i] = SET_DEST (XVECEXP (body, 0, i));
1544e4b17023SJohn Marino if (operand_locs)
1545e4b17023SJohn Marino operand_locs[i] = &SET_DEST (XVECEXP (body, 0, i));
1546e4b17023SJohn Marino if (constraints)
1547e4b17023SJohn Marino constraints[i] = XSTR (SET_SRC (XVECEXP (body, 0, i)), 1);
1548e4b17023SJohn Marino if (modes)
1549e4b17023SJohn Marino modes[i] = GET_MODE (SET_DEST (XVECEXP (body, 0, i)));
1550e4b17023SJohn Marino }
1551e4b17023SJohn Marino nbase = i;
1552e4b17023SJohn Marino }
1553e4b17023SJohn Marino break;
1554e4b17023SJohn Marino }
1555e4b17023SJohn Marino
1556e4b17023SJohn Marino default:
1557e4b17023SJohn Marino gcc_unreachable ();
1558e4b17023SJohn Marino }
1559e4b17023SJohn Marino
1560e4b17023SJohn Marino n = ASM_OPERANDS_INPUT_LENGTH (asmop);
1561e4b17023SJohn Marino for (i = 0; i < n; i++)
1562e4b17023SJohn Marino {
1563e4b17023SJohn Marino if (operand_locs)
1564e4b17023SJohn Marino operand_locs[nbase + i] = &ASM_OPERANDS_INPUT (asmop, i);
1565e4b17023SJohn Marino if (operands)
1566e4b17023SJohn Marino operands[nbase + i] = ASM_OPERANDS_INPUT (asmop, i);
1567e4b17023SJohn Marino if (constraints)
1568e4b17023SJohn Marino constraints[nbase + i] = ASM_OPERANDS_INPUT_CONSTRAINT (asmop, i);
1569e4b17023SJohn Marino if (modes)
1570e4b17023SJohn Marino modes[nbase + i] = ASM_OPERANDS_INPUT_MODE (asmop, i);
1571e4b17023SJohn Marino }
1572e4b17023SJohn Marino nbase += n;
1573e4b17023SJohn Marino
1574e4b17023SJohn Marino n = ASM_OPERANDS_LABEL_LENGTH (asmop);
1575e4b17023SJohn Marino for (i = 0; i < n; i++)
1576e4b17023SJohn Marino {
1577e4b17023SJohn Marino if (operand_locs)
1578e4b17023SJohn Marino operand_locs[nbase + i] = &ASM_OPERANDS_LABEL (asmop, i);
1579e4b17023SJohn Marino if (operands)
1580e4b17023SJohn Marino operands[nbase + i] = ASM_OPERANDS_LABEL (asmop, i);
1581e4b17023SJohn Marino if (constraints)
1582e4b17023SJohn Marino constraints[nbase + i] = "";
1583e4b17023SJohn Marino if (modes)
1584e4b17023SJohn Marino modes[nbase + i] = Pmode;
1585e4b17023SJohn Marino }
1586e4b17023SJohn Marino
1587e4b17023SJohn Marino if (loc)
1588e4b17023SJohn Marino *loc = ASM_OPERANDS_SOURCE_LOCATION (asmop);
1589e4b17023SJohn Marino
1590e4b17023SJohn Marino return ASM_OPERANDS_TEMPLATE (asmop);
1591e4b17023SJohn Marino }
1592e4b17023SJohn Marino
1593e4b17023SJohn Marino /* Check if an asm_operand matches its constraints.
1594e4b17023SJohn Marino Return > 0 if ok, = 0 if bad, < 0 if inconclusive. */
1595e4b17023SJohn Marino
1596e4b17023SJohn Marino int
asm_operand_ok(rtx op,const char * constraint,const char ** constraints)1597e4b17023SJohn Marino asm_operand_ok (rtx op, const char *constraint, const char **constraints)
1598e4b17023SJohn Marino {
1599e4b17023SJohn Marino int result = 0;
1600e4b17023SJohn Marino #ifdef AUTO_INC_DEC
1601e4b17023SJohn Marino bool incdec_ok = false;
1602e4b17023SJohn Marino #endif
1603e4b17023SJohn Marino
1604e4b17023SJohn Marino /* Use constrain_operands after reload. */
1605e4b17023SJohn Marino gcc_assert (!reload_completed);
1606e4b17023SJohn Marino
1607e4b17023SJohn Marino /* Empty constraint string is the same as "X,...,X", i.e. X for as
1608e4b17023SJohn Marino many alternatives as required to match the other operands. */
1609e4b17023SJohn Marino if (*constraint == '\0')
1610e4b17023SJohn Marino result = 1;
1611e4b17023SJohn Marino
1612e4b17023SJohn Marino while (*constraint)
1613e4b17023SJohn Marino {
1614e4b17023SJohn Marino char c = *constraint;
1615e4b17023SJohn Marino int len;
1616e4b17023SJohn Marino switch (c)
1617e4b17023SJohn Marino {
1618e4b17023SJohn Marino case ',':
1619e4b17023SJohn Marino constraint++;
1620e4b17023SJohn Marino continue;
1621e4b17023SJohn Marino case '=':
1622e4b17023SJohn Marino case '+':
1623e4b17023SJohn Marino case '*':
1624e4b17023SJohn Marino case '%':
1625e4b17023SJohn Marino case '!':
1626e4b17023SJohn Marino case '#':
1627e4b17023SJohn Marino case '&':
1628e4b17023SJohn Marino case '?':
1629e4b17023SJohn Marino break;
1630e4b17023SJohn Marino
1631e4b17023SJohn Marino case '0': case '1': case '2': case '3': case '4':
1632e4b17023SJohn Marino case '5': case '6': case '7': case '8': case '9':
1633e4b17023SJohn Marino /* If caller provided constraints pointer, look up
1634e4b17023SJohn Marino the maching constraint. Otherwise, our caller should have
1635e4b17023SJohn Marino given us the proper matching constraint, but we can't
1636e4b17023SJohn Marino actually fail the check if they didn't. Indicate that
1637e4b17023SJohn Marino results are inconclusive. */
1638e4b17023SJohn Marino if (constraints)
1639e4b17023SJohn Marino {
1640e4b17023SJohn Marino char *end;
1641e4b17023SJohn Marino unsigned long match;
1642e4b17023SJohn Marino
1643e4b17023SJohn Marino match = strtoul (constraint, &end, 10);
1644e4b17023SJohn Marino if (!result)
1645e4b17023SJohn Marino result = asm_operand_ok (op, constraints[match], NULL);
1646e4b17023SJohn Marino constraint = (const char *) end;
1647e4b17023SJohn Marino }
1648e4b17023SJohn Marino else
1649e4b17023SJohn Marino {
1650e4b17023SJohn Marino do
1651e4b17023SJohn Marino constraint++;
1652e4b17023SJohn Marino while (ISDIGIT (*constraint));
1653e4b17023SJohn Marino if (! result)
1654e4b17023SJohn Marino result = -1;
1655e4b17023SJohn Marino }
1656e4b17023SJohn Marino continue;
1657e4b17023SJohn Marino
1658e4b17023SJohn Marino case 'p':
1659e4b17023SJohn Marino if (address_operand (op, VOIDmode))
1660e4b17023SJohn Marino result = 1;
1661e4b17023SJohn Marino break;
1662e4b17023SJohn Marino
1663e4b17023SJohn Marino case TARGET_MEM_CONSTRAINT:
1664e4b17023SJohn Marino case 'V': /* non-offsettable */
1665e4b17023SJohn Marino if (memory_operand (op, VOIDmode))
1666e4b17023SJohn Marino result = 1;
1667e4b17023SJohn Marino break;
1668e4b17023SJohn Marino
1669e4b17023SJohn Marino case 'o': /* offsettable */
1670e4b17023SJohn Marino if (offsettable_nonstrict_memref_p (op))
1671e4b17023SJohn Marino result = 1;
1672e4b17023SJohn Marino break;
1673e4b17023SJohn Marino
1674e4b17023SJohn Marino case '<':
1675e4b17023SJohn Marino /* ??? Before auto-inc-dec, auto inc/dec insns are not supposed to exist,
1676e4b17023SJohn Marino excepting those that expand_call created. Further, on some
1677e4b17023SJohn Marino machines which do not have generalized auto inc/dec, an inc/dec
1678e4b17023SJohn Marino is not a memory_operand.
1679e4b17023SJohn Marino
1680e4b17023SJohn Marino Match any memory and hope things are resolved after reload. */
1681e4b17023SJohn Marino
1682e4b17023SJohn Marino if (MEM_P (op)
1683e4b17023SJohn Marino && (1
1684e4b17023SJohn Marino || GET_CODE (XEXP (op, 0)) == PRE_DEC
1685e4b17023SJohn Marino || GET_CODE (XEXP (op, 0)) == POST_DEC))
1686e4b17023SJohn Marino result = 1;
1687e4b17023SJohn Marino #ifdef AUTO_INC_DEC
1688e4b17023SJohn Marino incdec_ok = true;
1689e4b17023SJohn Marino #endif
1690e4b17023SJohn Marino break;
1691e4b17023SJohn Marino
1692e4b17023SJohn Marino case '>':
1693e4b17023SJohn Marino if (MEM_P (op)
1694e4b17023SJohn Marino && (1
1695e4b17023SJohn Marino || GET_CODE (XEXP (op, 0)) == PRE_INC
1696e4b17023SJohn Marino || GET_CODE (XEXP (op, 0)) == POST_INC))
1697e4b17023SJohn Marino result = 1;
1698e4b17023SJohn Marino #ifdef AUTO_INC_DEC
1699e4b17023SJohn Marino incdec_ok = true;
1700e4b17023SJohn Marino #endif
1701e4b17023SJohn Marino break;
1702e4b17023SJohn Marino
1703e4b17023SJohn Marino case 'E':
1704e4b17023SJohn Marino case 'F':
1705e4b17023SJohn Marino if (GET_CODE (op) == CONST_DOUBLE
1706e4b17023SJohn Marino || (GET_CODE (op) == CONST_VECTOR
1707e4b17023SJohn Marino && GET_MODE_CLASS (GET_MODE (op)) == MODE_VECTOR_FLOAT))
1708e4b17023SJohn Marino result = 1;
1709e4b17023SJohn Marino break;
1710e4b17023SJohn Marino
1711e4b17023SJohn Marino case 'G':
1712e4b17023SJohn Marino if (GET_CODE (op) == CONST_DOUBLE
1713e4b17023SJohn Marino && CONST_DOUBLE_OK_FOR_CONSTRAINT_P (op, 'G', constraint))
1714e4b17023SJohn Marino result = 1;
1715e4b17023SJohn Marino break;
1716e4b17023SJohn Marino case 'H':
1717e4b17023SJohn Marino if (GET_CODE (op) == CONST_DOUBLE
1718e4b17023SJohn Marino && CONST_DOUBLE_OK_FOR_CONSTRAINT_P (op, 'H', constraint))
1719e4b17023SJohn Marino result = 1;
1720e4b17023SJohn Marino break;
1721e4b17023SJohn Marino
1722e4b17023SJohn Marino case 's':
1723e4b17023SJohn Marino if (CONST_INT_P (op)
1724e4b17023SJohn Marino || (GET_CODE (op) == CONST_DOUBLE
1725e4b17023SJohn Marino && GET_MODE (op) == VOIDmode))
1726e4b17023SJohn Marino break;
1727e4b17023SJohn Marino /* Fall through. */
1728e4b17023SJohn Marino
1729e4b17023SJohn Marino case 'i':
1730e4b17023SJohn Marino if (CONSTANT_P (op) && (! flag_pic || LEGITIMATE_PIC_OPERAND_P (op)))
1731e4b17023SJohn Marino result = 1;
1732e4b17023SJohn Marino break;
1733e4b17023SJohn Marino
1734e4b17023SJohn Marino case 'n':
1735e4b17023SJohn Marino if (CONST_INT_P (op)
1736e4b17023SJohn Marino || (GET_CODE (op) == CONST_DOUBLE
1737e4b17023SJohn Marino && GET_MODE (op) == VOIDmode))
1738e4b17023SJohn Marino result = 1;
1739e4b17023SJohn Marino break;
1740e4b17023SJohn Marino
1741e4b17023SJohn Marino case 'I':
1742e4b17023SJohn Marino if (CONST_INT_P (op)
1743e4b17023SJohn Marino && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'I', constraint))
1744e4b17023SJohn Marino result = 1;
1745e4b17023SJohn Marino break;
1746e4b17023SJohn Marino case 'J':
1747e4b17023SJohn Marino if (CONST_INT_P (op)
1748e4b17023SJohn Marino && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'J', constraint))
1749e4b17023SJohn Marino result = 1;
1750e4b17023SJohn Marino break;
1751e4b17023SJohn Marino case 'K':
1752e4b17023SJohn Marino if (CONST_INT_P (op)
1753e4b17023SJohn Marino && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'K', constraint))
1754e4b17023SJohn Marino result = 1;
1755e4b17023SJohn Marino break;
1756e4b17023SJohn Marino case 'L':
1757e4b17023SJohn Marino if (CONST_INT_P (op)
1758e4b17023SJohn Marino && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'L', constraint))
1759e4b17023SJohn Marino result = 1;
1760e4b17023SJohn Marino break;
1761e4b17023SJohn Marino case 'M':
1762e4b17023SJohn Marino if (CONST_INT_P (op)
1763e4b17023SJohn Marino && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'M', constraint))
1764e4b17023SJohn Marino result = 1;
1765e4b17023SJohn Marino break;
1766e4b17023SJohn Marino case 'N':
1767e4b17023SJohn Marino if (CONST_INT_P (op)
1768e4b17023SJohn Marino && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'N', constraint))
1769e4b17023SJohn Marino result = 1;
1770e4b17023SJohn Marino break;
1771e4b17023SJohn Marino case 'O':
1772e4b17023SJohn Marino if (CONST_INT_P (op)
1773e4b17023SJohn Marino && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'O', constraint))
1774e4b17023SJohn Marino result = 1;
1775e4b17023SJohn Marino break;
1776e4b17023SJohn Marino case 'P':
1777e4b17023SJohn Marino if (CONST_INT_P (op)
1778e4b17023SJohn Marino && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'P', constraint))
1779e4b17023SJohn Marino result = 1;
1780e4b17023SJohn Marino break;
1781e4b17023SJohn Marino
1782e4b17023SJohn Marino case 'X':
1783e4b17023SJohn Marino result = 1;
1784e4b17023SJohn Marino break;
1785e4b17023SJohn Marino
1786e4b17023SJohn Marino case 'g':
1787e4b17023SJohn Marino if (general_operand (op, VOIDmode))
1788e4b17023SJohn Marino result = 1;
1789e4b17023SJohn Marino break;
1790e4b17023SJohn Marino
1791e4b17023SJohn Marino default:
1792e4b17023SJohn Marino /* For all other letters, we first check for a register class,
1793e4b17023SJohn Marino otherwise it is an EXTRA_CONSTRAINT. */
1794e4b17023SJohn Marino if (REG_CLASS_FROM_CONSTRAINT (c, constraint) != NO_REGS)
1795e4b17023SJohn Marino {
1796e4b17023SJohn Marino case 'r':
1797e4b17023SJohn Marino if (GET_MODE (op) == BLKmode)
1798e4b17023SJohn Marino break;
1799e4b17023SJohn Marino if (register_operand (op, VOIDmode))
1800e4b17023SJohn Marino result = 1;
1801e4b17023SJohn Marino }
1802e4b17023SJohn Marino #ifdef EXTRA_CONSTRAINT_STR
1803e4b17023SJohn Marino else if (EXTRA_MEMORY_CONSTRAINT (c, constraint))
1804e4b17023SJohn Marino /* Every memory operand can be reloaded to fit. */
1805e4b17023SJohn Marino result = result || memory_operand (op, VOIDmode);
1806e4b17023SJohn Marino else if (EXTRA_ADDRESS_CONSTRAINT (c, constraint))
1807e4b17023SJohn Marino /* Every address operand can be reloaded to fit. */
1808e4b17023SJohn Marino result = result || address_operand (op, VOIDmode);
1809e4b17023SJohn Marino else if (EXTRA_CONSTRAINT_STR (op, c, constraint))
1810e4b17023SJohn Marino result = 1;
1811e4b17023SJohn Marino #endif
1812e4b17023SJohn Marino break;
1813e4b17023SJohn Marino }
1814e4b17023SJohn Marino len = CONSTRAINT_LEN (c, constraint);
1815e4b17023SJohn Marino do
1816e4b17023SJohn Marino constraint++;
1817e4b17023SJohn Marino while (--len && *constraint);
1818e4b17023SJohn Marino if (len)
1819e4b17023SJohn Marino return 0;
1820e4b17023SJohn Marino }
1821e4b17023SJohn Marino
1822e4b17023SJohn Marino #ifdef AUTO_INC_DEC
1823e4b17023SJohn Marino /* For operands without < or > constraints reject side-effects. */
1824e4b17023SJohn Marino if (!incdec_ok && result && MEM_P (op))
1825e4b17023SJohn Marino switch (GET_CODE (XEXP (op, 0)))
1826e4b17023SJohn Marino {
1827e4b17023SJohn Marino case PRE_INC:
1828e4b17023SJohn Marino case POST_INC:
1829e4b17023SJohn Marino case PRE_DEC:
1830e4b17023SJohn Marino case POST_DEC:
1831e4b17023SJohn Marino case PRE_MODIFY:
1832e4b17023SJohn Marino case POST_MODIFY:
1833e4b17023SJohn Marino return 0;
1834e4b17023SJohn Marino default:
1835e4b17023SJohn Marino break;
1836e4b17023SJohn Marino }
1837e4b17023SJohn Marino #endif
1838e4b17023SJohn Marino
1839e4b17023SJohn Marino return result;
1840e4b17023SJohn Marino }
1841e4b17023SJohn Marino
1842e4b17023SJohn Marino /* Given an rtx *P, if it is a sum containing an integer constant term,
1843e4b17023SJohn Marino return the location (type rtx *) of the pointer to that constant term.
1844e4b17023SJohn Marino Otherwise, return a null pointer. */
1845e4b17023SJohn Marino
1846e4b17023SJohn Marino rtx *
find_constant_term_loc(rtx * p)1847e4b17023SJohn Marino find_constant_term_loc (rtx *p)
1848e4b17023SJohn Marino {
1849e4b17023SJohn Marino rtx *tem;
1850e4b17023SJohn Marino enum rtx_code code = GET_CODE (*p);
1851e4b17023SJohn Marino
1852e4b17023SJohn Marino /* If *P IS such a constant term, P is its location. */
1853e4b17023SJohn Marino
1854e4b17023SJohn Marino if (code == CONST_INT || code == SYMBOL_REF || code == LABEL_REF
1855e4b17023SJohn Marino || code == CONST)
1856e4b17023SJohn Marino return p;
1857e4b17023SJohn Marino
1858e4b17023SJohn Marino /* Otherwise, if not a sum, it has no constant term. */
1859e4b17023SJohn Marino
1860e4b17023SJohn Marino if (GET_CODE (*p) != PLUS)
1861e4b17023SJohn Marino return 0;
1862e4b17023SJohn Marino
1863e4b17023SJohn Marino /* If one of the summands is constant, return its location. */
1864e4b17023SJohn Marino
1865e4b17023SJohn Marino if (XEXP (*p, 0) && CONSTANT_P (XEXP (*p, 0))
1866e4b17023SJohn Marino && XEXP (*p, 1) && CONSTANT_P (XEXP (*p, 1)))
1867e4b17023SJohn Marino return p;
1868e4b17023SJohn Marino
1869e4b17023SJohn Marino /* Otherwise, check each summand for containing a constant term. */
1870e4b17023SJohn Marino
1871e4b17023SJohn Marino if (XEXP (*p, 0) != 0)
1872e4b17023SJohn Marino {
1873e4b17023SJohn Marino tem = find_constant_term_loc (&XEXP (*p, 0));
1874e4b17023SJohn Marino if (tem != 0)
1875e4b17023SJohn Marino return tem;
1876e4b17023SJohn Marino }
1877e4b17023SJohn Marino
1878e4b17023SJohn Marino if (XEXP (*p, 1) != 0)
1879e4b17023SJohn Marino {
1880e4b17023SJohn Marino tem = find_constant_term_loc (&XEXP (*p, 1));
1881e4b17023SJohn Marino if (tem != 0)
1882e4b17023SJohn Marino return tem;
1883e4b17023SJohn Marino }
1884e4b17023SJohn Marino
1885e4b17023SJohn Marino return 0;
1886e4b17023SJohn Marino }
1887e4b17023SJohn Marino
1888e4b17023SJohn Marino /* Return 1 if OP is a memory reference
1889e4b17023SJohn Marino whose address contains no side effects
1890e4b17023SJohn Marino and remains valid after the addition
1891e4b17023SJohn Marino of a positive integer less than the
1892e4b17023SJohn Marino size of the object being referenced.
1893e4b17023SJohn Marino
1894e4b17023SJohn Marino We assume that the original address is valid and do not check it.
1895e4b17023SJohn Marino
1896e4b17023SJohn Marino This uses strict_memory_address_p as a subroutine, so
1897e4b17023SJohn Marino don't use it before reload. */
1898e4b17023SJohn Marino
1899e4b17023SJohn Marino int
offsettable_memref_p(rtx op)1900e4b17023SJohn Marino offsettable_memref_p (rtx op)
1901e4b17023SJohn Marino {
1902e4b17023SJohn Marino return ((MEM_P (op))
1903e4b17023SJohn Marino && offsettable_address_addr_space_p (1, GET_MODE (op), XEXP (op, 0),
1904e4b17023SJohn Marino MEM_ADDR_SPACE (op)));
1905e4b17023SJohn Marino }
1906e4b17023SJohn Marino
1907e4b17023SJohn Marino /* Similar, but don't require a strictly valid mem ref:
1908e4b17023SJohn Marino consider pseudo-regs valid as index or base regs. */
1909e4b17023SJohn Marino
1910e4b17023SJohn Marino int
offsettable_nonstrict_memref_p(rtx op)1911e4b17023SJohn Marino offsettable_nonstrict_memref_p (rtx op)
1912e4b17023SJohn Marino {
1913e4b17023SJohn Marino return ((MEM_P (op))
1914e4b17023SJohn Marino && offsettable_address_addr_space_p (0, GET_MODE (op), XEXP (op, 0),
1915e4b17023SJohn Marino MEM_ADDR_SPACE (op)));
1916e4b17023SJohn Marino }
1917e4b17023SJohn Marino
1918e4b17023SJohn Marino /* Return 1 if Y is a memory address which contains no side effects
1919e4b17023SJohn Marino and would remain valid for address space AS after the addition of
1920e4b17023SJohn Marino a positive integer less than the size of that mode.
1921e4b17023SJohn Marino
1922e4b17023SJohn Marino We assume that the original address is valid and do not check it.
1923e4b17023SJohn Marino We do check that it is valid for narrower modes.
1924e4b17023SJohn Marino
1925e4b17023SJohn Marino If STRICTP is nonzero, we require a strictly valid address,
1926e4b17023SJohn Marino for the sake of use in reload.c. */
1927e4b17023SJohn Marino
1928e4b17023SJohn Marino int
offsettable_address_addr_space_p(int strictp,enum machine_mode mode,rtx y,addr_space_t as)1929e4b17023SJohn Marino offsettable_address_addr_space_p (int strictp, enum machine_mode mode, rtx y,
1930e4b17023SJohn Marino addr_space_t as)
1931e4b17023SJohn Marino {
1932e4b17023SJohn Marino enum rtx_code ycode = GET_CODE (y);
1933e4b17023SJohn Marino rtx z;
1934e4b17023SJohn Marino rtx y1 = y;
1935e4b17023SJohn Marino rtx *y2;
1936e4b17023SJohn Marino int (*addressp) (enum machine_mode, rtx, addr_space_t) =
1937e4b17023SJohn Marino (strictp ? strict_memory_address_addr_space_p
1938e4b17023SJohn Marino : memory_address_addr_space_p);
1939e4b17023SJohn Marino unsigned int mode_sz = GET_MODE_SIZE (mode);
1940e4b17023SJohn Marino
1941e4b17023SJohn Marino if (CONSTANT_ADDRESS_P (y))
1942e4b17023SJohn Marino return 1;
1943e4b17023SJohn Marino
1944e4b17023SJohn Marino /* Adjusting an offsettable address involves changing to a narrower mode.
1945e4b17023SJohn Marino Make sure that's OK. */
1946e4b17023SJohn Marino
1947e4b17023SJohn Marino if (mode_dependent_address_p (y))
1948e4b17023SJohn Marino return 0;
1949e4b17023SJohn Marino
1950e4b17023SJohn Marino /* ??? How much offset does an offsettable BLKmode reference need?
1951e4b17023SJohn Marino Clearly that depends on the situation in which it's being used.
1952e4b17023SJohn Marino However, the current situation in which we test 0xffffffff is
1953e4b17023SJohn Marino less than ideal. Caveat user. */
1954e4b17023SJohn Marino if (mode_sz == 0)
1955e4b17023SJohn Marino mode_sz = BIGGEST_ALIGNMENT / BITS_PER_UNIT;
1956e4b17023SJohn Marino
1957e4b17023SJohn Marino /* If the expression contains a constant term,
1958e4b17023SJohn Marino see if it remains valid when max possible offset is added. */
1959e4b17023SJohn Marino
1960e4b17023SJohn Marino if ((ycode == PLUS) && (y2 = find_constant_term_loc (&y1)))
1961e4b17023SJohn Marino {
1962e4b17023SJohn Marino int good;
1963e4b17023SJohn Marino
1964e4b17023SJohn Marino y1 = *y2;
1965e4b17023SJohn Marino *y2 = plus_constant (*y2, mode_sz - 1);
1966e4b17023SJohn Marino /* Use QImode because an odd displacement may be automatically invalid
1967e4b17023SJohn Marino for any wider mode. But it should be valid for a single byte. */
1968e4b17023SJohn Marino good = (*addressp) (QImode, y, as);
1969e4b17023SJohn Marino
1970e4b17023SJohn Marino /* In any case, restore old contents of memory. */
1971e4b17023SJohn Marino *y2 = y1;
1972e4b17023SJohn Marino return good;
1973e4b17023SJohn Marino }
1974e4b17023SJohn Marino
1975e4b17023SJohn Marino if (GET_RTX_CLASS (ycode) == RTX_AUTOINC)
1976e4b17023SJohn Marino return 0;
1977e4b17023SJohn Marino
1978e4b17023SJohn Marino /* The offset added here is chosen as the maximum offset that
1979e4b17023SJohn Marino any instruction could need to add when operating on something
1980e4b17023SJohn Marino of the specified mode. We assume that if Y and Y+c are
1981e4b17023SJohn Marino valid addresses then so is Y+d for all 0<d<c. adjust_address will
1982e4b17023SJohn Marino go inside a LO_SUM here, so we do so as well. */
1983e4b17023SJohn Marino if (GET_CODE (y) == LO_SUM
1984e4b17023SJohn Marino && mode != BLKmode
1985e4b17023SJohn Marino && mode_sz <= GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT)
1986e4b17023SJohn Marino z = gen_rtx_LO_SUM (GET_MODE (y), XEXP (y, 0),
1987e4b17023SJohn Marino plus_constant (XEXP (y, 1), mode_sz - 1));
1988e4b17023SJohn Marino else
1989e4b17023SJohn Marino z = plus_constant (y, mode_sz - 1);
1990e4b17023SJohn Marino
1991e4b17023SJohn Marino /* Use QImode because an odd displacement may be automatically invalid
1992e4b17023SJohn Marino for any wider mode. But it should be valid for a single byte. */
1993e4b17023SJohn Marino return (*addressp) (QImode, z, as);
1994e4b17023SJohn Marino }
1995e4b17023SJohn Marino
1996e4b17023SJohn Marino /* Return 1 if ADDR is an address-expression whose effect depends
1997e4b17023SJohn Marino on the mode of the memory reference it is used in.
1998e4b17023SJohn Marino
1999e4b17023SJohn Marino Autoincrement addressing is a typical example of mode-dependence
2000e4b17023SJohn Marino because the amount of the increment depends on the mode. */
2001e4b17023SJohn Marino
2002e4b17023SJohn Marino bool
mode_dependent_address_p(rtx addr)2003e4b17023SJohn Marino mode_dependent_address_p (rtx addr)
2004e4b17023SJohn Marino {
2005e4b17023SJohn Marino /* Auto-increment addressing with anything other than post_modify
2006e4b17023SJohn Marino or pre_modify always introduces a mode dependency. Catch such
2007e4b17023SJohn Marino cases now instead of deferring to the target. */
2008e4b17023SJohn Marino if (GET_CODE (addr) == PRE_INC
2009e4b17023SJohn Marino || GET_CODE (addr) == POST_INC
2010e4b17023SJohn Marino || GET_CODE (addr) == PRE_DEC
2011e4b17023SJohn Marino || GET_CODE (addr) == POST_DEC)
2012e4b17023SJohn Marino return true;
2013e4b17023SJohn Marino
2014e4b17023SJohn Marino return targetm.mode_dependent_address_p (addr);
2015e4b17023SJohn Marino }
2016e4b17023SJohn Marino
2017e4b17023SJohn Marino /* Like extract_insn, but save insn extracted and don't extract again, when
2018e4b17023SJohn Marino called again for the same insn expecting that recog_data still contain the
2019e4b17023SJohn Marino valid information. This is used primary by gen_attr infrastructure that
2020e4b17023SJohn Marino often does extract insn again and again. */
2021e4b17023SJohn Marino void
extract_insn_cached(rtx insn)2022e4b17023SJohn Marino extract_insn_cached (rtx insn)
2023e4b17023SJohn Marino {
2024e4b17023SJohn Marino if (recog_data.insn == insn && INSN_CODE (insn) >= 0)
2025e4b17023SJohn Marino return;
2026e4b17023SJohn Marino extract_insn (insn);
2027e4b17023SJohn Marino recog_data.insn = insn;
2028e4b17023SJohn Marino }
2029e4b17023SJohn Marino
2030e4b17023SJohn Marino /* Do cached extract_insn, constrain_operands and complain about failures.
2031e4b17023SJohn Marino Used by insn_attrtab. */
2032e4b17023SJohn Marino void
extract_constrain_insn_cached(rtx insn)2033e4b17023SJohn Marino extract_constrain_insn_cached (rtx insn)
2034e4b17023SJohn Marino {
2035e4b17023SJohn Marino extract_insn_cached (insn);
2036e4b17023SJohn Marino if (which_alternative == -1
2037e4b17023SJohn Marino && !constrain_operands (reload_completed))
2038e4b17023SJohn Marino fatal_insn_not_found (insn);
2039e4b17023SJohn Marino }
2040e4b17023SJohn Marino
2041e4b17023SJohn Marino /* Do cached constrain_operands and complain about failures. */
2042e4b17023SJohn Marino int
constrain_operands_cached(int strict)2043e4b17023SJohn Marino constrain_operands_cached (int strict)
2044e4b17023SJohn Marino {
2045e4b17023SJohn Marino if (which_alternative == -1)
2046e4b17023SJohn Marino return constrain_operands (strict);
2047e4b17023SJohn Marino else
2048e4b17023SJohn Marino return 1;
2049e4b17023SJohn Marino }
2050e4b17023SJohn Marino
2051e4b17023SJohn Marino /* Analyze INSN and fill in recog_data. */
2052e4b17023SJohn Marino
2053e4b17023SJohn Marino void
extract_insn(rtx insn)2054e4b17023SJohn Marino extract_insn (rtx insn)
2055e4b17023SJohn Marino {
2056e4b17023SJohn Marino int i;
2057e4b17023SJohn Marino int icode;
2058e4b17023SJohn Marino int noperands;
2059e4b17023SJohn Marino rtx body = PATTERN (insn);
2060e4b17023SJohn Marino
2061e4b17023SJohn Marino recog_data.n_operands = 0;
2062e4b17023SJohn Marino recog_data.n_alternatives = 0;
2063e4b17023SJohn Marino recog_data.n_dups = 0;
2064e4b17023SJohn Marino recog_data.is_asm = false;
2065e4b17023SJohn Marino
2066e4b17023SJohn Marino switch (GET_CODE (body))
2067e4b17023SJohn Marino {
2068e4b17023SJohn Marino case USE:
2069e4b17023SJohn Marino case CLOBBER:
2070e4b17023SJohn Marino case ASM_INPUT:
2071e4b17023SJohn Marino case ADDR_VEC:
2072e4b17023SJohn Marino case ADDR_DIFF_VEC:
2073e4b17023SJohn Marino case VAR_LOCATION:
2074e4b17023SJohn Marino return;
2075e4b17023SJohn Marino
2076e4b17023SJohn Marino case SET:
2077e4b17023SJohn Marino if (GET_CODE (SET_SRC (body)) == ASM_OPERANDS)
2078e4b17023SJohn Marino goto asm_insn;
2079e4b17023SJohn Marino else
2080e4b17023SJohn Marino goto normal_insn;
2081e4b17023SJohn Marino case PARALLEL:
2082e4b17023SJohn Marino if ((GET_CODE (XVECEXP (body, 0, 0)) == SET
2083e4b17023SJohn Marino && GET_CODE (SET_SRC (XVECEXP (body, 0, 0))) == ASM_OPERANDS)
2084e4b17023SJohn Marino || GET_CODE (XVECEXP (body, 0, 0)) == ASM_OPERANDS)
2085e4b17023SJohn Marino goto asm_insn;
2086e4b17023SJohn Marino else
2087e4b17023SJohn Marino goto normal_insn;
2088e4b17023SJohn Marino case ASM_OPERANDS:
2089e4b17023SJohn Marino asm_insn:
2090e4b17023SJohn Marino recog_data.n_operands = noperands = asm_noperands (body);
2091e4b17023SJohn Marino if (noperands >= 0)
2092e4b17023SJohn Marino {
2093e4b17023SJohn Marino /* This insn is an `asm' with operands. */
2094e4b17023SJohn Marino
2095e4b17023SJohn Marino /* expand_asm_operands makes sure there aren't too many operands. */
2096e4b17023SJohn Marino gcc_assert (noperands <= MAX_RECOG_OPERANDS);
2097e4b17023SJohn Marino
2098e4b17023SJohn Marino /* Now get the operand values and constraints out of the insn. */
2099e4b17023SJohn Marino decode_asm_operands (body, recog_data.operand,
2100e4b17023SJohn Marino recog_data.operand_loc,
2101e4b17023SJohn Marino recog_data.constraints,
2102e4b17023SJohn Marino recog_data.operand_mode, NULL);
2103e4b17023SJohn Marino memset (recog_data.is_operator, 0, sizeof recog_data.is_operator);
2104e4b17023SJohn Marino if (noperands > 0)
2105e4b17023SJohn Marino {
2106e4b17023SJohn Marino const char *p = recog_data.constraints[0];
2107e4b17023SJohn Marino recog_data.n_alternatives = 1;
2108e4b17023SJohn Marino while (*p)
2109e4b17023SJohn Marino recog_data.n_alternatives += (*p++ == ',');
2110e4b17023SJohn Marino }
2111e4b17023SJohn Marino recog_data.is_asm = true;
2112e4b17023SJohn Marino break;
2113e4b17023SJohn Marino }
2114e4b17023SJohn Marino fatal_insn_not_found (insn);
2115e4b17023SJohn Marino
2116e4b17023SJohn Marino default:
2117e4b17023SJohn Marino normal_insn:
2118e4b17023SJohn Marino /* Ordinary insn: recognize it, get the operands via insn_extract
2119e4b17023SJohn Marino and get the constraints. */
2120e4b17023SJohn Marino
2121e4b17023SJohn Marino icode = recog_memoized (insn);
2122e4b17023SJohn Marino if (icode < 0)
2123e4b17023SJohn Marino fatal_insn_not_found (insn);
2124e4b17023SJohn Marino
2125e4b17023SJohn Marino recog_data.n_operands = noperands = insn_data[icode].n_operands;
2126e4b17023SJohn Marino recog_data.n_alternatives = insn_data[icode].n_alternatives;
2127e4b17023SJohn Marino recog_data.n_dups = insn_data[icode].n_dups;
2128e4b17023SJohn Marino
2129e4b17023SJohn Marino insn_extract (insn);
2130e4b17023SJohn Marino
2131e4b17023SJohn Marino for (i = 0; i < noperands; i++)
2132e4b17023SJohn Marino {
2133e4b17023SJohn Marino recog_data.constraints[i] = insn_data[icode].operand[i].constraint;
2134e4b17023SJohn Marino recog_data.is_operator[i] = insn_data[icode].operand[i].is_operator;
2135e4b17023SJohn Marino recog_data.operand_mode[i] = insn_data[icode].operand[i].mode;
2136e4b17023SJohn Marino /* VOIDmode match_operands gets mode from their real operand. */
2137e4b17023SJohn Marino if (recog_data.operand_mode[i] == VOIDmode)
2138e4b17023SJohn Marino recog_data.operand_mode[i] = GET_MODE (recog_data.operand[i]);
2139e4b17023SJohn Marino }
2140e4b17023SJohn Marino }
2141e4b17023SJohn Marino for (i = 0; i < noperands; i++)
2142e4b17023SJohn Marino recog_data.operand_type[i]
2143e4b17023SJohn Marino = (recog_data.constraints[i][0] == '=' ? OP_OUT
2144e4b17023SJohn Marino : recog_data.constraints[i][0] == '+' ? OP_INOUT
2145e4b17023SJohn Marino : OP_IN);
2146e4b17023SJohn Marino
2147e4b17023SJohn Marino gcc_assert (recog_data.n_alternatives <= MAX_RECOG_ALTERNATIVES);
2148e4b17023SJohn Marino
2149e4b17023SJohn Marino if (INSN_CODE (insn) < 0)
2150e4b17023SJohn Marino for (i = 0; i < recog_data.n_alternatives; i++)
2151e4b17023SJohn Marino recog_data.alternative_enabled_p[i] = true;
2152e4b17023SJohn Marino else
2153e4b17023SJohn Marino {
2154e4b17023SJohn Marino recog_data.insn = insn;
2155e4b17023SJohn Marino for (i = 0; i < recog_data.n_alternatives; i++)
2156e4b17023SJohn Marino {
2157e4b17023SJohn Marino which_alternative = i;
2158e4b17023SJohn Marino recog_data.alternative_enabled_p[i] = get_attr_enabled (insn);
2159e4b17023SJohn Marino }
2160e4b17023SJohn Marino }
2161e4b17023SJohn Marino
2162e4b17023SJohn Marino recog_data.insn = NULL;
2163e4b17023SJohn Marino which_alternative = -1;
2164e4b17023SJohn Marino }
2165e4b17023SJohn Marino
2166e4b17023SJohn Marino /* After calling extract_insn, you can use this function to extract some
2167e4b17023SJohn Marino information from the constraint strings into a more usable form.
2168e4b17023SJohn Marino The collected data is stored in recog_op_alt. */
2169e4b17023SJohn Marino void
preprocess_constraints(void)2170e4b17023SJohn Marino preprocess_constraints (void)
2171e4b17023SJohn Marino {
2172e4b17023SJohn Marino int i;
2173e4b17023SJohn Marino
2174e4b17023SJohn Marino for (i = 0; i < recog_data.n_operands; i++)
2175e4b17023SJohn Marino memset (recog_op_alt[i], 0, (recog_data.n_alternatives
2176e4b17023SJohn Marino * sizeof (struct operand_alternative)));
2177e4b17023SJohn Marino
2178e4b17023SJohn Marino for (i = 0; i < recog_data.n_operands; i++)
2179e4b17023SJohn Marino {
2180e4b17023SJohn Marino int j;
2181e4b17023SJohn Marino struct operand_alternative *op_alt;
2182e4b17023SJohn Marino const char *p = recog_data.constraints[i];
2183e4b17023SJohn Marino
2184e4b17023SJohn Marino op_alt = recog_op_alt[i];
2185e4b17023SJohn Marino
2186e4b17023SJohn Marino for (j = 0; j < recog_data.n_alternatives; j++)
2187e4b17023SJohn Marino {
2188e4b17023SJohn Marino op_alt[j].cl = NO_REGS;
2189e4b17023SJohn Marino op_alt[j].constraint = p;
2190e4b17023SJohn Marino op_alt[j].matches = -1;
2191e4b17023SJohn Marino op_alt[j].matched = -1;
2192e4b17023SJohn Marino
2193e4b17023SJohn Marino if (!recog_data.alternative_enabled_p[j])
2194e4b17023SJohn Marino {
2195e4b17023SJohn Marino p = skip_alternative (p);
2196e4b17023SJohn Marino continue;
2197e4b17023SJohn Marino }
2198e4b17023SJohn Marino
2199e4b17023SJohn Marino if (*p == '\0' || *p == ',')
2200e4b17023SJohn Marino {
2201e4b17023SJohn Marino op_alt[j].anything_ok = 1;
2202e4b17023SJohn Marino continue;
2203e4b17023SJohn Marino }
2204e4b17023SJohn Marino
2205e4b17023SJohn Marino for (;;)
2206e4b17023SJohn Marino {
2207e4b17023SJohn Marino char c = *p;
2208e4b17023SJohn Marino if (c == '#')
2209e4b17023SJohn Marino do
2210e4b17023SJohn Marino c = *++p;
2211e4b17023SJohn Marino while (c != ',' && c != '\0');
2212e4b17023SJohn Marino if (c == ',' || c == '\0')
2213e4b17023SJohn Marino {
2214e4b17023SJohn Marino p++;
2215e4b17023SJohn Marino break;
2216e4b17023SJohn Marino }
2217e4b17023SJohn Marino
2218e4b17023SJohn Marino switch (c)
2219e4b17023SJohn Marino {
2220e4b17023SJohn Marino case '=': case '+': case '*': case '%':
2221e4b17023SJohn Marino case 'E': case 'F': case 'G': case 'H':
2222e4b17023SJohn Marino case 's': case 'i': case 'n':
2223e4b17023SJohn Marino case 'I': case 'J': case 'K': case 'L':
2224e4b17023SJohn Marino case 'M': case 'N': case 'O': case 'P':
2225e4b17023SJohn Marino /* These don't say anything we care about. */
2226e4b17023SJohn Marino break;
2227e4b17023SJohn Marino
2228e4b17023SJohn Marino case '?':
2229e4b17023SJohn Marino op_alt[j].reject += 6;
2230e4b17023SJohn Marino break;
2231e4b17023SJohn Marino case '!':
2232e4b17023SJohn Marino op_alt[j].reject += 600;
2233e4b17023SJohn Marino break;
2234e4b17023SJohn Marino case '&':
2235e4b17023SJohn Marino op_alt[j].earlyclobber = 1;
2236e4b17023SJohn Marino break;
2237e4b17023SJohn Marino
2238e4b17023SJohn Marino case '0': case '1': case '2': case '3': case '4':
2239e4b17023SJohn Marino case '5': case '6': case '7': case '8': case '9':
2240e4b17023SJohn Marino {
2241e4b17023SJohn Marino char *end;
2242e4b17023SJohn Marino op_alt[j].matches = strtoul (p, &end, 10);
2243e4b17023SJohn Marino recog_op_alt[op_alt[j].matches][j].matched = i;
2244e4b17023SJohn Marino p = end;
2245e4b17023SJohn Marino }
2246e4b17023SJohn Marino continue;
2247e4b17023SJohn Marino
2248e4b17023SJohn Marino case TARGET_MEM_CONSTRAINT:
2249e4b17023SJohn Marino op_alt[j].memory_ok = 1;
2250e4b17023SJohn Marino break;
2251e4b17023SJohn Marino case '<':
2252e4b17023SJohn Marino op_alt[j].decmem_ok = 1;
2253e4b17023SJohn Marino break;
2254e4b17023SJohn Marino case '>':
2255e4b17023SJohn Marino op_alt[j].incmem_ok = 1;
2256e4b17023SJohn Marino break;
2257e4b17023SJohn Marino case 'V':
2258e4b17023SJohn Marino op_alt[j].nonoffmem_ok = 1;
2259e4b17023SJohn Marino break;
2260e4b17023SJohn Marino case 'o':
2261e4b17023SJohn Marino op_alt[j].offmem_ok = 1;
2262e4b17023SJohn Marino break;
2263e4b17023SJohn Marino case 'X':
2264e4b17023SJohn Marino op_alt[j].anything_ok = 1;
2265e4b17023SJohn Marino break;
2266e4b17023SJohn Marino
2267e4b17023SJohn Marino case 'p':
2268e4b17023SJohn Marino op_alt[j].is_address = 1;
2269e4b17023SJohn Marino op_alt[j].cl = reg_class_subunion[(int) op_alt[j].cl]
2270e4b17023SJohn Marino [(int) base_reg_class (VOIDmode, ADDR_SPACE_GENERIC,
2271e4b17023SJohn Marino ADDRESS, SCRATCH)];
2272e4b17023SJohn Marino break;
2273e4b17023SJohn Marino
2274e4b17023SJohn Marino case 'g':
2275e4b17023SJohn Marino case 'r':
2276e4b17023SJohn Marino op_alt[j].cl =
2277e4b17023SJohn Marino reg_class_subunion[(int) op_alt[j].cl][(int) GENERAL_REGS];
2278e4b17023SJohn Marino break;
2279e4b17023SJohn Marino
2280e4b17023SJohn Marino default:
2281e4b17023SJohn Marino if (EXTRA_MEMORY_CONSTRAINT (c, p))
2282e4b17023SJohn Marino {
2283e4b17023SJohn Marino op_alt[j].memory_ok = 1;
2284e4b17023SJohn Marino break;
2285e4b17023SJohn Marino }
2286e4b17023SJohn Marino if (EXTRA_ADDRESS_CONSTRAINT (c, p))
2287e4b17023SJohn Marino {
2288e4b17023SJohn Marino op_alt[j].is_address = 1;
2289e4b17023SJohn Marino op_alt[j].cl
2290e4b17023SJohn Marino = (reg_class_subunion
2291e4b17023SJohn Marino [(int) op_alt[j].cl]
2292e4b17023SJohn Marino [(int) base_reg_class (VOIDmode, ADDR_SPACE_GENERIC,
2293e4b17023SJohn Marino ADDRESS, SCRATCH)]);
2294e4b17023SJohn Marino break;
2295e4b17023SJohn Marino }
2296e4b17023SJohn Marino
2297e4b17023SJohn Marino op_alt[j].cl
2298e4b17023SJohn Marino = (reg_class_subunion
2299e4b17023SJohn Marino [(int) op_alt[j].cl]
2300e4b17023SJohn Marino [(int) REG_CLASS_FROM_CONSTRAINT ((unsigned char) c, p)]);
2301e4b17023SJohn Marino break;
2302e4b17023SJohn Marino }
2303e4b17023SJohn Marino p += CONSTRAINT_LEN (c, p);
2304e4b17023SJohn Marino }
2305e4b17023SJohn Marino }
2306e4b17023SJohn Marino }
2307e4b17023SJohn Marino }
2308e4b17023SJohn Marino
2309e4b17023SJohn Marino /* Check the operands of an insn against the insn's operand constraints
2310e4b17023SJohn Marino and return 1 if they are valid.
2311e4b17023SJohn Marino The information about the insn's operands, constraints, operand modes
2312e4b17023SJohn Marino etc. is obtained from the global variables set up by extract_insn.
2313e4b17023SJohn Marino
2314e4b17023SJohn Marino WHICH_ALTERNATIVE is set to a number which indicates which
2315e4b17023SJohn Marino alternative of constraints was matched: 0 for the first alternative,
2316e4b17023SJohn Marino 1 for the next, etc.
2317e4b17023SJohn Marino
2318e4b17023SJohn Marino In addition, when two operands are required to match
2319e4b17023SJohn Marino and it happens that the output operand is (reg) while the
2320e4b17023SJohn Marino input operand is --(reg) or ++(reg) (a pre-inc or pre-dec),
2321e4b17023SJohn Marino make the output operand look like the input.
2322e4b17023SJohn Marino This is because the output operand is the one the template will print.
2323e4b17023SJohn Marino
2324e4b17023SJohn Marino This is used in final, just before printing the assembler code and by
2325e4b17023SJohn Marino the routines that determine an insn's attribute.
2326e4b17023SJohn Marino
2327e4b17023SJohn Marino If STRICT is a positive nonzero value, it means that we have been
2328e4b17023SJohn Marino called after reload has been completed. In that case, we must
2329e4b17023SJohn Marino do all checks strictly. If it is zero, it means that we have been called
2330e4b17023SJohn Marino before reload has completed. In that case, we first try to see if we can
2331e4b17023SJohn Marino find an alternative that matches strictly. If not, we try again, this
2332e4b17023SJohn Marino time assuming that reload will fix up the insn. This provides a "best
2333e4b17023SJohn Marino guess" for the alternative and is used to compute attributes of insns prior
2334e4b17023SJohn Marino to reload. A negative value of STRICT is used for this internal call. */
2335e4b17023SJohn Marino
2336e4b17023SJohn Marino struct funny_match
2337e4b17023SJohn Marino {
2338e4b17023SJohn Marino int this_op, other;
2339e4b17023SJohn Marino };
2340e4b17023SJohn Marino
2341e4b17023SJohn Marino int
constrain_operands(int strict)2342e4b17023SJohn Marino constrain_operands (int strict)
2343e4b17023SJohn Marino {
2344e4b17023SJohn Marino const char *constraints[MAX_RECOG_OPERANDS];
2345e4b17023SJohn Marino int matching_operands[MAX_RECOG_OPERANDS];
2346e4b17023SJohn Marino int earlyclobber[MAX_RECOG_OPERANDS];
2347e4b17023SJohn Marino int c;
2348e4b17023SJohn Marino
2349e4b17023SJohn Marino struct funny_match funny_match[MAX_RECOG_OPERANDS];
2350e4b17023SJohn Marino int funny_match_index;
2351e4b17023SJohn Marino
2352e4b17023SJohn Marino which_alternative = 0;
2353e4b17023SJohn Marino if (recog_data.n_operands == 0 || recog_data.n_alternatives == 0)
2354e4b17023SJohn Marino return 1;
2355e4b17023SJohn Marino
2356e4b17023SJohn Marino for (c = 0; c < recog_data.n_operands; c++)
2357e4b17023SJohn Marino {
2358e4b17023SJohn Marino constraints[c] = recog_data.constraints[c];
2359e4b17023SJohn Marino matching_operands[c] = -1;
2360e4b17023SJohn Marino }
2361e4b17023SJohn Marino
2362e4b17023SJohn Marino do
2363e4b17023SJohn Marino {
2364e4b17023SJohn Marino int seen_earlyclobber_at = -1;
2365e4b17023SJohn Marino int opno;
2366e4b17023SJohn Marino int lose = 0;
2367e4b17023SJohn Marino funny_match_index = 0;
2368e4b17023SJohn Marino
2369e4b17023SJohn Marino if (!recog_data.alternative_enabled_p[which_alternative])
2370e4b17023SJohn Marino {
2371e4b17023SJohn Marino int i;
2372e4b17023SJohn Marino
2373e4b17023SJohn Marino for (i = 0; i < recog_data.n_operands; i++)
2374e4b17023SJohn Marino constraints[i] = skip_alternative (constraints[i]);
2375e4b17023SJohn Marino
2376e4b17023SJohn Marino which_alternative++;
2377e4b17023SJohn Marino continue;
2378e4b17023SJohn Marino }
2379e4b17023SJohn Marino
2380e4b17023SJohn Marino for (opno = 0; opno < recog_data.n_operands; opno++)
2381e4b17023SJohn Marino {
2382e4b17023SJohn Marino rtx op = recog_data.operand[opno];
2383e4b17023SJohn Marino enum machine_mode mode = GET_MODE (op);
2384e4b17023SJohn Marino const char *p = constraints[opno];
2385e4b17023SJohn Marino int offset = 0;
2386e4b17023SJohn Marino int win = 0;
2387e4b17023SJohn Marino int val;
2388e4b17023SJohn Marino int len;
2389e4b17023SJohn Marino
2390e4b17023SJohn Marino earlyclobber[opno] = 0;
2391e4b17023SJohn Marino
2392e4b17023SJohn Marino /* A unary operator may be accepted by the predicate, but it
2393e4b17023SJohn Marino is irrelevant for matching constraints. */
2394e4b17023SJohn Marino if (UNARY_P (op))
2395e4b17023SJohn Marino op = XEXP (op, 0);
2396e4b17023SJohn Marino
2397e4b17023SJohn Marino if (GET_CODE (op) == SUBREG)
2398e4b17023SJohn Marino {
2399e4b17023SJohn Marino if (REG_P (SUBREG_REG (op))
2400e4b17023SJohn Marino && REGNO (SUBREG_REG (op)) < FIRST_PSEUDO_REGISTER)
2401e4b17023SJohn Marino offset = subreg_regno_offset (REGNO (SUBREG_REG (op)),
2402e4b17023SJohn Marino GET_MODE (SUBREG_REG (op)),
2403e4b17023SJohn Marino SUBREG_BYTE (op),
2404e4b17023SJohn Marino GET_MODE (op));
2405e4b17023SJohn Marino op = SUBREG_REG (op);
2406e4b17023SJohn Marino }
2407e4b17023SJohn Marino
2408e4b17023SJohn Marino /* An empty constraint or empty alternative
2409e4b17023SJohn Marino allows anything which matched the pattern. */
2410e4b17023SJohn Marino if (*p == 0 || *p == ',')
2411e4b17023SJohn Marino win = 1;
2412e4b17023SJohn Marino
2413e4b17023SJohn Marino do
2414e4b17023SJohn Marino switch (c = *p, len = CONSTRAINT_LEN (c, p), c)
2415e4b17023SJohn Marino {
2416e4b17023SJohn Marino case '\0':
2417e4b17023SJohn Marino len = 0;
2418e4b17023SJohn Marino break;
2419e4b17023SJohn Marino case ',':
2420e4b17023SJohn Marino c = '\0';
2421e4b17023SJohn Marino break;
2422e4b17023SJohn Marino
2423e4b17023SJohn Marino case '?': case '!': case '*': case '%':
2424e4b17023SJohn Marino case '=': case '+':
2425e4b17023SJohn Marino break;
2426e4b17023SJohn Marino
2427e4b17023SJohn Marino case '#':
2428e4b17023SJohn Marino /* Ignore rest of this alternative as far as
2429e4b17023SJohn Marino constraint checking is concerned. */
2430e4b17023SJohn Marino do
2431e4b17023SJohn Marino p++;
2432e4b17023SJohn Marino while (*p && *p != ',');
2433e4b17023SJohn Marino len = 0;
2434e4b17023SJohn Marino break;
2435e4b17023SJohn Marino
2436e4b17023SJohn Marino case '&':
2437e4b17023SJohn Marino earlyclobber[opno] = 1;
2438e4b17023SJohn Marino if (seen_earlyclobber_at < 0)
2439e4b17023SJohn Marino seen_earlyclobber_at = opno;
2440e4b17023SJohn Marino break;
2441e4b17023SJohn Marino
2442e4b17023SJohn Marino case '0': case '1': case '2': case '3': case '4':
2443e4b17023SJohn Marino case '5': case '6': case '7': case '8': case '9':
2444e4b17023SJohn Marino {
2445e4b17023SJohn Marino /* This operand must be the same as a previous one.
2446e4b17023SJohn Marino This kind of constraint is used for instructions such
2447e4b17023SJohn Marino as add when they take only two operands.
2448e4b17023SJohn Marino
2449e4b17023SJohn Marino Note that the lower-numbered operand is passed first.
2450e4b17023SJohn Marino
2451e4b17023SJohn Marino If we are not testing strictly, assume that this
2452e4b17023SJohn Marino constraint will be satisfied. */
2453e4b17023SJohn Marino
2454e4b17023SJohn Marino char *end;
2455e4b17023SJohn Marino int match;
2456e4b17023SJohn Marino
2457e4b17023SJohn Marino match = strtoul (p, &end, 10);
2458e4b17023SJohn Marino p = end;
2459e4b17023SJohn Marino
2460e4b17023SJohn Marino if (strict < 0)
2461e4b17023SJohn Marino val = 1;
2462e4b17023SJohn Marino else
2463e4b17023SJohn Marino {
2464e4b17023SJohn Marino rtx op1 = recog_data.operand[match];
2465e4b17023SJohn Marino rtx op2 = recog_data.operand[opno];
2466e4b17023SJohn Marino
2467e4b17023SJohn Marino /* A unary operator may be accepted by the predicate,
2468e4b17023SJohn Marino but it is irrelevant for matching constraints. */
2469e4b17023SJohn Marino if (UNARY_P (op1))
2470e4b17023SJohn Marino op1 = XEXP (op1, 0);
2471e4b17023SJohn Marino if (UNARY_P (op2))
2472e4b17023SJohn Marino op2 = XEXP (op2, 0);
2473e4b17023SJohn Marino
2474e4b17023SJohn Marino val = operands_match_p (op1, op2);
2475e4b17023SJohn Marino }
2476e4b17023SJohn Marino
2477e4b17023SJohn Marino matching_operands[opno] = match;
2478e4b17023SJohn Marino matching_operands[match] = opno;
2479e4b17023SJohn Marino
2480e4b17023SJohn Marino if (val != 0)
2481e4b17023SJohn Marino win = 1;
2482e4b17023SJohn Marino
2483e4b17023SJohn Marino /* If output is *x and input is *--x, arrange later
2484e4b17023SJohn Marino to change the output to *--x as well, since the
2485e4b17023SJohn Marino output op is the one that will be printed. */
2486e4b17023SJohn Marino if (val == 2 && strict > 0)
2487e4b17023SJohn Marino {
2488e4b17023SJohn Marino funny_match[funny_match_index].this_op = opno;
2489e4b17023SJohn Marino funny_match[funny_match_index++].other = match;
2490e4b17023SJohn Marino }
2491e4b17023SJohn Marino }
2492e4b17023SJohn Marino len = 0;
2493e4b17023SJohn Marino break;
2494e4b17023SJohn Marino
2495e4b17023SJohn Marino case 'p':
2496e4b17023SJohn Marino /* p is used for address_operands. When we are called by
2497e4b17023SJohn Marino gen_reload, no one will have checked that the address is
2498e4b17023SJohn Marino strictly valid, i.e., that all pseudos requiring hard regs
2499e4b17023SJohn Marino have gotten them. */
2500e4b17023SJohn Marino if (strict <= 0
2501e4b17023SJohn Marino || (strict_memory_address_p (recog_data.operand_mode[opno],
2502e4b17023SJohn Marino op)))
2503e4b17023SJohn Marino win = 1;
2504e4b17023SJohn Marino break;
2505e4b17023SJohn Marino
2506e4b17023SJohn Marino /* No need to check general_operand again;
2507e4b17023SJohn Marino it was done in insn-recog.c. Well, except that reload
2508e4b17023SJohn Marino doesn't check the validity of its replacements, but
2509e4b17023SJohn Marino that should only matter when there's a bug. */
2510e4b17023SJohn Marino case 'g':
2511e4b17023SJohn Marino /* Anything goes unless it is a REG and really has a hard reg
2512e4b17023SJohn Marino but the hard reg is not in the class GENERAL_REGS. */
2513e4b17023SJohn Marino if (REG_P (op))
2514e4b17023SJohn Marino {
2515e4b17023SJohn Marino if (strict < 0
2516e4b17023SJohn Marino || GENERAL_REGS == ALL_REGS
2517e4b17023SJohn Marino || (reload_in_progress
2518e4b17023SJohn Marino && REGNO (op) >= FIRST_PSEUDO_REGISTER)
2519e4b17023SJohn Marino || reg_fits_class_p (op, GENERAL_REGS, offset, mode))
2520e4b17023SJohn Marino win = 1;
2521e4b17023SJohn Marino }
2522e4b17023SJohn Marino else if (strict < 0 || general_operand (op, mode))
2523e4b17023SJohn Marino win = 1;
2524e4b17023SJohn Marino break;
2525e4b17023SJohn Marino
2526e4b17023SJohn Marino case 'X':
2527e4b17023SJohn Marino /* This is used for a MATCH_SCRATCH in the cases when
2528e4b17023SJohn Marino we don't actually need anything. So anything goes
2529e4b17023SJohn Marino any time. */
2530e4b17023SJohn Marino win = 1;
2531e4b17023SJohn Marino break;
2532e4b17023SJohn Marino
2533e4b17023SJohn Marino case TARGET_MEM_CONSTRAINT:
2534e4b17023SJohn Marino /* Memory operands must be valid, to the extent
2535e4b17023SJohn Marino required by STRICT. */
2536e4b17023SJohn Marino if (MEM_P (op))
2537e4b17023SJohn Marino {
2538e4b17023SJohn Marino if (strict > 0
2539e4b17023SJohn Marino && !strict_memory_address_addr_space_p
2540e4b17023SJohn Marino (GET_MODE (op), XEXP (op, 0),
2541e4b17023SJohn Marino MEM_ADDR_SPACE (op)))
2542e4b17023SJohn Marino break;
2543e4b17023SJohn Marino if (strict == 0
2544e4b17023SJohn Marino && !memory_address_addr_space_p
2545e4b17023SJohn Marino (GET_MODE (op), XEXP (op, 0),
2546e4b17023SJohn Marino MEM_ADDR_SPACE (op)))
2547e4b17023SJohn Marino break;
2548e4b17023SJohn Marino win = 1;
2549e4b17023SJohn Marino }
2550e4b17023SJohn Marino /* Before reload, accept what reload can turn into mem. */
2551e4b17023SJohn Marino else if (strict < 0 && CONSTANT_P (op))
2552e4b17023SJohn Marino win = 1;
2553e4b17023SJohn Marino /* During reload, accept a pseudo */
2554e4b17023SJohn Marino else if (reload_in_progress && REG_P (op)
2555e4b17023SJohn Marino && REGNO (op) >= FIRST_PSEUDO_REGISTER)
2556e4b17023SJohn Marino win = 1;
2557e4b17023SJohn Marino break;
2558e4b17023SJohn Marino
2559e4b17023SJohn Marino case '<':
2560e4b17023SJohn Marino if (MEM_P (op)
2561e4b17023SJohn Marino && (GET_CODE (XEXP (op, 0)) == PRE_DEC
2562e4b17023SJohn Marino || GET_CODE (XEXP (op, 0)) == POST_DEC))
2563e4b17023SJohn Marino win = 1;
2564e4b17023SJohn Marino break;
2565e4b17023SJohn Marino
2566e4b17023SJohn Marino case '>':
2567e4b17023SJohn Marino if (MEM_P (op)
2568e4b17023SJohn Marino && (GET_CODE (XEXP (op, 0)) == PRE_INC
2569e4b17023SJohn Marino || GET_CODE (XEXP (op, 0)) == POST_INC))
2570e4b17023SJohn Marino win = 1;
2571e4b17023SJohn Marino break;
2572e4b17023SJohn Marino
2573e4b17023SJohn Marino case 'E':
2574e4b17023SJohn Marino case 'F':
2575e4b17023SJohn Marino if (GET_CODE (op) == CONST_DOUBLE
2576e4b17023SJohn Marino || (GET_CODE (op) == CONST_VECTOR
2577e4b17023SJohn Marino && GET_MODE_CLASS (GET_MODE (op)) == MODE_VECTOR_FLOAT))
2578e4b17023SJohn Marino win = 1;
2579e4b17023SJohn Marino break;
2580e4b17023SJohn Marino
2581e4b17023SJohn Marino case 'G':
2582e4b17023SJohn Marino case 'H':
2583e4b17023SJohn Marino if (GET_CODE (op) == CONST_DOUBLE
2584e4b17023SJohn Marino && CONST_DOUBLE_OK_FOR_CONSTRAINT_P (op, c, p))
2585e4b17023SJohn Marino win = 1;
2586e4b17023SJohn Marino break;
2587e4b17023SJohn Marino
2588e4b17023SJohn Marino case 's':
2589e4b17023SJohn Marino if (CONST_INT_P (op)
2590e4b17023SJohn Marino || (GET_CODE (op) == CONST_DOUBLE
2591e4b17023SJohn Marino && GET_MODE (op) == VOIDmode))
2592e4b17023SJohn Marino break;
2593e4b17023SJohn Marino case 'i':
2594e4b17023SJohn Marino if (CONSTANT_P (op))
2595e4b17023SJohn Marino win = 1;
2596e4b17023SJohn Marino break;
2597e4b17023SJohn Marino
2598e4b17023SJohn Marino case 'n':
2599e4b17023SJohn Marino if (CONST_INT_P (op)
2600e4b17023SJohn Marino || (GET_CODE (op) == CONST_DOUBLE
2601e4b17023SJohn Marino && GET_MODE (op) == VOIDmode))
2602e4b17023SJohn Marino win = 1;
2603e4b17023SJohn Marino break;
2604e4b17023SJohn Marino
2605e4b17023SJohn Marino case 'I':
2606e4b17023SJohn Marino case 'J':
2607e4b17023SJohn Marino case 'K':
2608e4b17023SJohn Marino case 'L':
2609e4b17023SJohn Marino case 'M':
2610e4b17023SJohn Marino case 'N':
2611e4b17023SJohn Marino case 'O':
2612e4b17023SJohn Marino case 'P':
2613e4b17023SJohn Marino if (CONST_INT_P (op)
2614e4b17023SJohn Marino && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), c, p))
2615e4b17023SJohn Marino win = 1;
2616e4b17023SJohn Marino break;
2617e4b17023SJohn Marino
2618e4b17023SJohn Marino case 'V':
2619e4b17023SJohn Marino if (MEM_P (op)
2620e4b17023SJohn Marino && ((strict > 0 && ! offsettable_memref_p (op))
2621e4b17023SJohn Marino || (strict < 0
2622e4b17023SJohn Marino && !(CONSTANT_P (op) || MEM_P (op)))
2623e4b17023SJohn Marino || (reload_in_progress
2624e4b17023SJohn Marino && !(REG_P (op)
2625e4b17023SJohn Marino && REGNO (op) >= FIRST_PSEUDO_REGISTER))))
2626e4b17023SJohn Marino win = 1;
2627e4b17023SJohn Marino break;
2628e4b17023SJohn Marino
2629e4b17023SJohn Marino case 'o':
2630e4b17023SJohn Marino if ((strict > 0 && offsettable_memref_p (op))
2631e4b17023SJohn Marino || (strict == 0 && offsettable_nonstrict_memref_p (op))
2632e4b17023SJohn Marino /* Before reload, accept what reload can handle. */
2633e4b17023SJohn Marino || (strict < 0
2634e4b17023SJohn Marino && (CONSTANT_P (op) || MEM_P (op)))
2635e4b17023SJohn Marino /* During reload, accept a pseudo */
2636e4b17023SJohn Marino || (reload_in_progress && REG_P (op)
2637e4b17023SJohn Marino && REGNO (op) >= FIRST_PSEUDO_REGISTER))
2638e4b17023SJohn Marino win = 1;
2639e4b17023SJohn Marino break;
2640e4b17023SJohn Marino
2641e4b17023SJohn Marino default:
2642e4b17023SJohn Marino {
2643e4b17023SJohn Marino enum reg_class cl;
2644e4b17023SJohn Marino
2645e4b17023SJohn Marino cl = (c == 'r'
2646e4b17023SJohn Marino ? GENERAL_REGS : REG_CLASS_FROM_CONSTRAINT (c, p));
2647e4b17023SJohn Marino if (cl != NO_REGS)
2648e4b17023SJohn Marino {
2649e4b17023SJohn Marino if (strict < 0
2650e4b17023SJohn Marino || (strict == 0
2651e4b17023SJohn Marino && REG_P (op)
2652e4b17023SJohn Marino && REGNO (op) >= FIRST_PSEUDO_REGISTER)
2653e4b17023SJohn Marino || (strict == 0 && GET_CODE (op) == SCRATCH)
2654e4b17023SJohn Marino || (REG_P (op)
2655e4b17023SJohn Marino && reg_fits_class_p (op, cl, offset, mode)))
2656e4b17023SJohn Marino win = 1;
2657e4b17023SJohn Marino }
2658e4b17023SJohn Marino #ifdef EXTRA_CONSTRAINT_STR
2659e4b17023SJohn Marino else if (EXTRA_CONSTRAINT_STR (op, c, p))
2660e4b17023SJohn Marino win = 1;
2661e4b17023SJohn Marino
2662e4b17023SJohn Marino else if (EXTRA_MEMORY_CONSTRAINT (c, p)
2663e4b17023SJohn Marino /* Every memory operand can be reloaded to fit. */
2664e4b17023SJohn Marino && ((strict < 0 && MEM_P (op))
2665e4b17023SJohn Marino /* Before reload, accept what reload can turn
2666e4b17023SJohn Marino into mem. */
2667e4b17023SJohn Marino || (strict < 0 && CONSTANT_P (op))
2668e4b17023SJohn Marino /* During reload, accept a pseudo */
2669e4b17023SJohn Marino || (reload_in_progress && REG_P (op)
2670e4b17023SJohn Marino && REGNO (op) >= FIRST_PSEUDO_REGISTER)))
2671e4b17023SJohn Marino win = 1;
2672e4b17023SJohn Marino else if (EXTRA_ADDRESS_CONSTRAINT (c, p)
2673e4b17023SJohn Marino /* Every address operand can be reloaded to fit. */
2674e4b17023SJohn Marino && strict < 0)
2675e4b17023SJohn Marino win = 1;
2676e4b17023SJohn Marino /* Cater to architectures like IA-64 that define extra memory
2677e4b17023SJohn Marino constraints without using define_memory_constraint. */
2678e4b17023SJohn Marino else if (reload_in_progress
2679e4b17023SJohn Marino && REG_P (op)
2680e4b17023SJohn Marino && REGNO (op) >= FIRST_PSEUDO_REGISTER
2681e4b17023SJohn Marino && reg_renumber[REGNO (op)] < 0
2682e4b17023SJohn Marino && reg_equiv_mem (REGNO (op)) != 0
2683e4b17023SJohn Marino && EXTRA_CONSTRAINT_STR
2684e4b17023SJohn Marino (reg_equiv_mem (REGNO (op)), c, p))
2685e4b17023SJohn Marino win = 1;
2686e4b17023SJohn Marino #endif
2687e4b17023SJohn Marino break;
2688e4b17023SJohn Marino }
2689e4b17023SJohn Marino }
2690e4b17023SJohn Marino while (p += len, c);
2691e4b17023SJohn Marino
2692e4b17023SJohn Marino constraints[opno] = p;
2693e4b17023SJohn Marino /* If this operand did not win somehow,
2694e4b17023SJohn Marino this alternative loses. */
2695e4b17023SJohn Marino if (! win)
2696e4b17023SJohn Marino lose = 1;
2697e4b17023SJohn Marino }
2698e4b17023SJohn Marino /* This alternative won; the operands are ok.
2699e4b17023SJohn Marino Change whichever operands this alternative says to change. */
2700e4b17023SJohn Marino if (! lose)
2701e4b17023SJohn Marino {
2702e4b17023SJohn Marino int opno, eopno;
2703e4b17023SJohn Marino
2704e4b17023SJohn Marino /* See if any earlyclobber operand conflicts with some other
2705e4b17023SJohn Marino operand. */
2706e4b17023SJohn Marino
2707e4b17023SJohn Marino if (strict > 0 && seen_earlyclobber_at >= 0)
2708e4b17023SJohn Marino for (eopno = seen_earlyclobber_at;
2709e4b17023SJohn Marino eopno < recog_data.n_operands;
2710e4b17023SJohn Marino eopno++)
2711e4b17023SJohn Marino /* Ignore earlyclobber operands now in memory,
2712e4b17023SJohn Marino because we would often report failure when we have
2713e4b17023SJohn Marino two memory operands, one of which was formerly a REG. */
2714e4b17023SJohn Marino if (earlyclobber[eopno]
2715e4b17023SJohn Marino && REG_P (recog_data.operand[eopno]))
2716e4b17023SJohn Marino for (opno = 0; opno < recog_data.n_operands; opno++)
2717e4b17023SJohn Marino if ((MEM_P (recog_data.operand[opno])
2718e4b17023SJohn Marino || recog_data.operand_type[opno] != OP_OUT)
2719e4b17023SJohn Marino && opno != eopno
2720e4b17023SJohn Marino /* Ignore things like match_operator operands. */
2721e4b17023SJohn Marino && *recog_data.constraints[opno] != 0
2722e4b17023SJohn Marino && ! (matching_operands[opno] == eopno
2723e4b17023SJohn Marino && operands_match_p (recog_data.operand[opno],
2724e4b17023SJohn Marino recog_data.operand[eopno]))
2725e4b17023SJohn Marino && ! safe_from_earlyclobber (recog_data.operand[opno],
2726e4b17023SJohn Marino recog_data.operand[eopno]))
2727e4b17023SJohn Marino lose = 1;
2728e4b17023SJohn Marino
2729e4b17023SJohn Marino if (! lose)
2730e4b17023SJohn Marino {
2731e4b17023SJohn Marino while (--funny_match_index >= 0)
2732e4b17023SJohn Marino {
2733e4b17023SJohn Marino recog_data.operand[funny_match[funny_match_index].other]
2734e4b17023SJohn Marino = recog_data.operand[funny_match[funny_match_index].this_op];
2735e4b17023SJohn Marino }
2736e4b17023SJohn Marino
2737e4b17023SJohn Marino #ifdef AUTO_INC_DEC
2738e4b17023SJohn Marino /* For operands without < or > constraints reject side-effects. */
2739e4b17023SJohn Marino if (recog_data.is_asm)
2740e4b17023SJohn Marino {
2741e4b17023SJohn Marino for (opno = 0; opno < recog_data.n_operands; opno++)
2742e4b17023SJohn Marino if (MEM_P (recog_data.operand[opno]))
2743e4b17023SJohn Marino switch (GET_CODE (XEXP (recog_data.operand[opno], 0)))
2744e4b17023SJohn Marino {
2745e4b17023SJohn Marino case PRE_INC:
2746e4b17023SJohn Marino case POST_INC:
2747e4b17023SJohn Marino case PRE_DEC:
2748e4b17023SJohn Marino case POST_DEC:
2749e4b17023SJohn Marino case PRE_MODIFY:
2750e4b17023SJohn Marino case POST_MODIFY:
2751e4b17023SJohn Marino if (strchr (recog_data.constraints[opno], '<') == NULL
2752e4b17023SJohn Marino && strchr (recog_data.constraints[opno], '>')
2753e4b17023SJohn Marino == NULL)
2754e4b17023SJohn Marino return 0;
2755e4b17023SJohn Marino break;
2756e4b17023SJohn Marino default:
2757e4b17023SJohn Marino break;
2758e4b17023SJohn Marino }
2759e4b17023SJohn Marino }
2760e4b17023SJohn Marino #endif
2761e4b17023SJohn Marino return 1;
2762e4b17023SJohn Marino }
2763e4b17023SJohn Marino }
2764e4b17023SJohn Marino
2765e4b17023SJohn Marino which_alternative++;
2766e4b17023SJohn Marino }
2767e4b17023SJohn Marino while (which_alternative < recog_data.n_alternatives);
2768e4b17023SJohn Marino
2769e4b17023SJohn Marino which_alternative = -1;
2770e4b17023SJohn Marino /* If we are about to reject this, but we are not to test strictly,
2771e4b17023SJohn Marino try a very loose test. Only return failure if it fails also. */
2772e4b17023SJohn Marino if (strict == 0)
2773e4b17023SJohn Marino return constrain_operands (-1);
2774e4b17023SJohn Marino else
2775e4b17023SJohn Marino return 0;
2776e4b17023SJohn Marino }
2777e4b17023SJohn Marino
2778e4b17023SJohn Marino /* Return true iff OPERAND (assumed to be a REG rtx)
2779e4b17023SJohn Marino is a hard reg in class CLASS when its regno is offset by OFFSET
2780e4b17023SJohn Marino and changed to mode MODE.
2781e4b17023SJohn Marino If REG occupies multiple hard regs, all of them must be in CLASS. */
2782e4b17023SJohn Marino
2783e4b17023SJohn Marino bool
reg_fits_class_p(const_rtx operand,reg_class_t cl,int offset,enum machine_mode mode)2784e4b17023SJohn Marino reg_fits_class_p (const_rtx operand, reg_class_t cl, int offset,
2785e4b17023SJohn Marino enum machine_mode mode)
2786e4b17023SJohn Marino {
2787e4b17023SJohn Marino int regno = REGNO (operand);
2788e4b17023SJohn Marino
2789e4b17023SJohn Marino if (cl == NO_REGS)
2790e4b17023SJohn Marino return false;
2791e4b17023SJohn Marino
2792e4b17023SJohn Marino return (HARD_REGISTER_NUM_P (regno)
2793e4b17023SJohn Marino && in_hard_reg_set_p (reg_class_contents[(int) cl],
2794e4b17023SJohn Marino mode, regno + offset));
2795e4b17023SJohn Marino }
2796e4b17023SJohn Marino
2797e4b17023SJohn Marino /* Split single instruction. Helper function for split_all_insns and
2798e4b17023SJohn Marino split_all_insns_noflow. Return last insn in the sequence if successful,
2799e4b17023SJohn Marino or NULL if unsuccessful. */
2800e4b17023SJohn Marino
2801e4b17023SJohn Marino static rtx
split_insn(rtx insn)2802e4b17023SJohn Marino split_insn (rtx insn)
2803e4b17023SJohn Marino {
2804e4b17023SJohn Marino /* Split insns here to get max fine-grain parallelism. */
2805e4b17023SJohn Marino rtx first = PREV_INSN (insn);
2806e4b17023SJohn Marino rtx last = try_split (PATTERN (insn), insn, 1);
2807e4b17023SJohn Marino rtx insn_set, last_set, note;
2808e4b17023SJohn Marino
2809e4b17023SJohn Marino if (last == insn)
2810e4b17023SJohn Marino return NULL_RTX;
2811e4b17023SJohn Marino
2812e4b17023SJohn Marino /* If the original instruction was a single set that was known to be
2813e4b17023SJohn Marino equivalent to a constant, see if we can say the same about the last
2814e4b17023SJohn Marino instruction in the split sequence. The two instructions must set
2815e4b17023SJohn Marino the same destination. */
2816e4b17023SJohn Marino insn_set = single_set (insn);
2817e4b17023SJohn Marino if (insn_set)
2818e4b17023SJohn Marino {
2819e4b17023SJohn Marino last_set = single_set (last);
2820e4b17023SJohn Marino if (last_set && rtx_equal_p (SET_DEST (last_set), SET_DEST (insn_set)))
2821e4b17023SJohn Marino {
2822e4b17023SJohn Marino note = find_reg_equal_equiv_note (insn);
2823e4b17023SJohn Marino if (note && CONSTANT_P (XEXP (note, 0)))
2824e4b17023SJohn Marino set_unique_reg_note (last, REG_EQUAL, XEXP (note, 0));
2825e4b17023SJohn Marino else if (CONSTANT_P (SET_SRC (insn_set)))
2826e4b17023SJohn Marino set_unique_reg_note (last, REG_EQUAL, SET_SRC (insn_set));
2827e4b17023SJohn Marino }
2828e4b17023SJohn Marino }
2829e4b17023SJohn Marino
2830e4b17023SJohn Marino /* try_split returns the NOTE that INSN became. */
2831e4b17023SJohn Marino SET_INSN_DELETED (insn);
2832e4b17023SJohn Marino
2833e4b17023SJohn Marino /* ??? Coddle to md files that generate subregs in post-reload
2834e4b17023SJohn Marino splitters instead of computing the proper hard register. */
2835e4b17023SJohn Marino if (reload_completed && first != last)
2836e4b17023SJohn Marino {
2837e4b17023SJohn Marino first = NEXT_INSN (first);
2838e4b17023SJohn Marino for (;;)
2839e4b17023SJohn Marino {
2840e4b17023SJohn Marino if (INSN_P (first))
2841e4b17023SJohn Marino cleanup_subreg_operands (first);
2842e4b17023SJohn Marino if (first == last)
2843e4b17023SJohn Marino break;
2844e4b17023SJohn Marino first = NEXT_INSN (first);
2845e4b17023SJohn Marino }
2846e4b17023SJohn Marino }
2847e4b17023SJohn Marino
2848e4b17023SJohn Marino return last;
2849e4b17023SJohn Marino }
2850e4b17023SJohn Marino
2851e4b17023SJohn Marino /* Split all insns in the function. If UPD_LIFE, update life info after. */
2852e4b17023SJohn Marino
2853e4b17023SJohn Marino void
split_all_insns(void)2854e4b17023SJohn Marino split_all_insns (void)
2855e4b17023SJohn Marino {
2856e4b17023SJohn Marino sbitmap blocks;
2857e4b17023SJohn Marino bool changed;
2858e4b17023SJohn Marino basic_block bb;
2859e4b17023SJohn Marino
2860e4b17023SJohn Marino blocks = sbitmap_alloc (last_basic_block);
2861e4b17023SJohn Marino sbitmap_zero (blocks);
2862e4b17023SJohn Marino changed = false;
2863e4b17023SJohn Marino
2864e4b17023SJohn Marino FOR_EACH_BB_REVERSE (bb)
2865e4b17023SJohn Marino {
2866e4b17023SJohn Marino rtx insn, next;
2867e4b17023SJohn Marino bool finish = false;
2868e4b17023SJohn Marino
2869e4b17023SJohn Marino rtl_profile_for_bb (bb);
2870e4b17023SJohn Marino for (insn = BB_HEAD (bb); !finish ; insn = next)
2871e4b17023SJohn Marino {
2872e4b17023SJohn Marino /* Can't use `next_real_insn' because that might go across
2873e4b17023SJohn Marino CODE_LABELS and short-out basic blocks. */
2874e4b17023SJohn Marino next = NEXT_INSN (insn);
2875e4b17023SJohn Marino finish = (insn == BB_END (bb));
2876e4b17023SJohn Marino if (INSN_P (insn))
2877e4b17023SJohn Marino {
2878e4b17023SJohn Marino rtx set = single_set (insn);
2879e4b17023SJohn Marino
2880e4b17023SJohn Marino /* Don't split no-op move insns. These should silently
2881e4b17023SJohn Marino disappear later in final. Splitting such insns would
2882e4b17023SJohn Marino break the code that handles LIBCALL blocks. */
2883e4b17023SJohn Marino if (set && set_noop_p (set))
2884e4b17023SJohn Marino {
2885e4b17023SJohn Marino /* Nops get in the way while scheduling, so delete them
2886e4b17023SJohn Marino now if register allocation has already been done. It
2887e4b17023SJohn Marino is too risky to try to do this before register
2888e4b17023SJohn Marino allocation, and there are unlikely to be very many
2889e4b17023SJohn Marino nops then anyways. */
2890e4b17023SJohn Marino if (reload_completed)
2891e4b17023SJohn Marino delete_insn_and_edges (insn);
2892e4b17023SJohn Marino }
2893e4b17023SJohn Marino else
2894e4b17023SJohn Marino {
2895e4b17023SJohn Marino if (split_insn (insn))
2896e4b17023SJohn Marino {
2897e4b17023SJohn Marino SET_BIT (blocks, bb->index);
2898e4b17023SJohn Marino changed = true;
2899e4b17023SJohn Marino }
2900e4b17023SJohn Marino }
2901e4b17023SJohn Marino }
2902e4b17023SJohn Marino }
2903e4b17023SJohn Marino }
2904e4b17023SJohn Marino
2905e4b17023SJohn Marino default_rtl_profile ();
2906e4b17023SJohn Marino if (changed)
2907e4b17023SJohn Marino find_many_sub_basic_blocks (blocks);
2908e4b17023SJohn Marino
2909e4b17023SJohn Marino #ifdef ENABLE_CHECKING
2910e4b17023SJohn Marino verify_flow_info ();
2911e4b17023SJohn Marino #endif
2912e4b17023SJohn Marino
2913e4b17023SJohn Marino sbitmap_free (blocks);
2914e4b17023SJohn Marino }
2915e4b17023SJohn Marino
2916e4b17023SJohn Marino /* Same as split_all_insns, but do not expect CFG to be available.
2917e4b17023SJohn Marino Used by machine dependent reorg passes. */
2918e4b17023SJohn Marino
2919e4b17023SJohn Marino unsigned int
split_all_insns_noflow(void)2920e4b17023SJohn Marino split_all_insns_noflow (void)
2921e4b17023SJohn Marino {
2922e4b17023SJohn Marino rtx next, insn;
2923e4b17023SJohn Marino
2924e4b17023SJohn Marino for (insn = get_insns (); insn; insn = next)
2925e4b17023SJohn Marino {
2926e4b17023SJohn Marino next = NEXT_INSN (insn);
2927e4b17023SJohn Marino if (INSN_P (insn))
2928e4b17023SJohn Marino {
2929e4b17023SJohn Marino /* Don't split no-op move insns. These should silently
2930e4b17023SJohn Marino disappear later in final. Splitting such insns would
2931e4b17023SJohn Marino break the code that handles LIBCALL blocks. */
2932e4b17023SJohn Marino rtx set = single_set (insn);
2933e4b17023SJohn Marino if (set && set_noop_p (set))
2934e4b17023SJohn Marino {
2935e4b17023SJohn Marino /* Nops get in the way while scheduling, so delete them
2936e4b17023SJohn Marino now if register allocation has already been done. It
2937e4b17023SJohn Marino is too risky to try to do this before register
2938e4b17023SJohn Marino allocation, and there are unlikely to be very many
2939e4b17023SJohn Marino nops then anyways.
2940e4b17023SJohn Marino
2941e4b17023SJohn Marino ??? Should we use delete_insn when the CFG isn't valid? */
2942e4b17023SJohn Marino if (reload_completed)
2943e4b17023SJohn Marino delete_insn_and_edges (insn);
2944e4b17023SJohn Marino }
2945e4b17023SJohn Marino else
2946e4b17023SJohn Marino split_insn (insn);
2947e4b17023SJohn Marino }
2948e4b17023SJohn Marino }
2949e4b17023SJohn Marino return 0;
2950e4b17023SJohn Marino }
2951e4b17023SJohn Marino
2952e4b17023SJohn Marino #ifdef HAVE_peephole2
2953e4b17023SJohn Marino struct peep2_insn_data
2954e4b17023SJohn Marino {
2955e4b17023SJohn Marino rtx insn;
2956e4b17023SJohn Marino regset live_before;
2957e4b17023SJohn Marino };
2958e4b17023SJohn Marino
2959e4b17023SJohn Marino static struct peep2_insn_data peep2_insn_data[MAX_INSNS_PER_PEEP2 + 1];
2960e4b17023SJohn Marino static int peep2_current;
2961e4b17023SJohn Marino
2962e4b17023SJohn Marino static bool peep2_do_rebuild_jump_labels;
2963e4b17023SJohn Marino static bool peep2_do_cleanup_cfg;
2964e4b17023SJohn Marino
2965e4b17023SJohn Marino /* The number of instructions available to match a peep2. */
2966e4b17023SJohn Marino int peep2_current_count;
2967e4b17023SJohn Marino
2968e4b17023SJohn Marino /* A non-insn marker indicating the last insn of the block.
2969e4b17023SJohn Marino The live_before regset for this element is correct, indicating
2970e4b17023SJohn Marino DF_LIVE_OUT for the block. */
2971e4b17023SJohn Marino #define PEEP2_EOB pc_rtx
2972e4b17023SJohn Marino
2973e4b17023SJohn Marino /* Wrap N to fit into the peep2_insn_data buffer. */
2974e4b17023SJohn Marino
2975e4b17023SJohn Marino static int
peep2_buf_position(int n)2976e4b17023SJohn Marino peep2_buf_position (int n)
2977e4b17023SJohn Marino {
2978e4b17023SJohn Marino if (n >= MAX_INSNS_PER_PEEP2 + 1)
2979e4b17023SJohn Marino n -= MAX_INSNS_PER_PEEP2 + 1;
2980e4b17023SJohn Marino return n;
2981e4b17023SJohn Marino }
2982e4b17023SJohn Marino
2983e4b17023SJohn Marino /* Return the Nth non-note insn after `current', or return NULL_RTX if it
2984e4b17023SJohn Marino does not exist. Used by the recognizer to find the next insn to match
2985e4b17023SJohn Marino in a multi-insn pattern. */
2986e4b17023SJohn Marino
2987e4b17023SJohn Marino rtx
peep2_next_insn(int n)2988e4b17023SJohn Marino peep2_next_insn (int n)
2989e4b17023SJohn Marino {
2990e4b17023SJohn Marino gcc_assert (n <= peep2_current_count);
2991e4b17023SJohn Marino
2992e4b17023SJohn Marino n = peep2_buf_position (peep2_current + n);
2993e4b17023SJohn Marino
2994e4b17023SJohn Marino return peep2_insn_data[n].insn;
2995e4b17023SJohn Marino }
2996e4b17023SJohn Marino
2997e4b17023SJohn Marino /* Return true if REGNO is dead before the Nth non-note insn
2998e4b17023SJohn Marino after `current'. */
2999e4b17023SJohn Marino
3000e4b17023SJohn Marino int
peep2_regno_dead_p(int ofs,int regno)3001e4b17023SJohn Marino peep2_regno_dead_p (int ofs, int regno)
3002e4b17023SJohn Marino {
3003e4b17023SJohn Marino gcc_assert (ofs < MAX_INSNS_PER_PEEP2 + 1);
3004e4b17023SJohn Marino
3005e4b17023SJohn Marino ofs = peep2_buf_position (peep2_current + ofs);
3006e4b17023SJohn Marino
3007e4b17023SJohn Marino gcc_assert (peep2_insn_data[ofs].insn != NULL_RTX);
3008e4b17023SJohn Marino
3009e4b17023SJohn Marino return ! REGNO_REG_SET_P (peep2_insn_data[ofs].live_before, regno);
3010e4b17023SJohn Marino }
3011e4b17023SJohn Marino
3012e4b17023SJohn Marino /* Similarly for a REG. */
3013e4b17023SJohn Marino
3014e4b17023SJohn Marino int
peep2_reg_dead_p(int ofs,rtx reg)3015e4b17023SJohn Marino peep2_reg_dead_p (int ofs, rtx reg)
3016e4b17023SJohn Marino {
3017e4b17023SJohn Marino int regno, n;
3018e4b17023SJohn Marino
3019e4b17023SJohn Marino gcc_assert (ofs < MAX_INSNS_PER_PEEP2 + 1);
3020e4b17023SJohn Marino
3021e4b17023SJohn Marino ofs = peep2_buf_position (peep2_current + ofs);
3022e4b17023SJohn Marino
3023e4b17023SJohn Marino gcc_assert (peep2_insn_data[ofs].insn != NULL_RTX);
3024e4b17023SJohn Marino
3025e4b17023SJohn Marino regno = REGNO (reg);
3026e4b17023SJohn Marino n = hard_regno_nregs[regno][GET_MODE (reg)];
3027e4b17023SJohn Marino while (--n >= 0)
3028e4b17023SJohn Marino if (REGNO_REG_SET_P (peep2_insn_data[ofs].live_before, regno + n))
3029e4b17023SJohn Marino return 0;
3030e4b17023SJohn Marino return 1;
3031e4b17023SJohn Marino }
3032e4b17023SJohn Marino
3033*95d28233SJohn Marino /* Regno offset to be used in the register search. */
3034*95d28233SJohn Marino static int search_ofs;
3035*95d28233SJohn Marino
3036e4b17023SJohn Marino /* Try to find a hard register of mode MODE, matching the register class in
3037e4b17023SJohn Marino CLASS_STR, which is available at the beginning of insn CURRENT_INSN and
3038e4b17023SJohn Marino remains available until the end of LAST_INSN. LAST_INSN may be NULL_RTX,
3039e4b17023SJohn Marino in which case the only condition is that the register must be available
3040e4b17023SJohn Marino before CURRENT_INSN.
3041e4b17023SJohn Marino Registers that already have bits set in REG_SET will not be considered.
3042e4b17023SJohn Marino
3043e4b17023SJohn Marino If an appropriate register is available, it will be returned and the
3044e4b17023SJohn Marino corresponding bit(s) in REG_SET will be set; otherwise, NULL_RTX is
3045e4b17023SJohn Marino returned. */
3046e4b17023SJohn Marino
3047e4b17023SJohn Marino rtx
peep2_find_free_register(int from,int to,const char * class_str,enum machine_mode mode,HARD_REG_SET * reg_set)3048e4b17023SJohn Marino peep2_find_free_register (int from, int to, const char *class_str,
3049e4b17023SJohn Marino enum machine_mode mode, HARD_REG_SET *reg_set)
3050e4b17023SJohn Marino {
3051e4b17023SJohn Marino enum reg_class cl;
3052e4b17023SJohn Marino HARD_REG_SET live;
3053e4b17023SJohn Marino df_ref *def_rec;
3054e4b17023SJohn Marino int i;
3055e4b17023SJohn Marino
3056e4b17023SJohn Marino gcc_assert (from < MAX_INSNS_PER_PEEP2 + 1);
3057e4b17023SJohn Marino gcc_assert (to < MAX_INSNS_PER_PEEP2 + 1);
3058e4b17023SJohn Marino
3059e4b17023SJohn Marino from = peep2_buf_position (peep2_current + from);
3060e4b17023SJohn Marino to = peep2_buf_position (peep2_current + to);
3061e4b17023SJohn Marino
3062e4b17023SJohn Marino gcc_assert (peep2_insn_data[from].insn != NULL_RTX);
3063e4b17023SJohn Marino REG_SET_TO_HARD_REG_SET (live, peep2_insn_data[from].live_before);
3064e4b17023SJohn Marino
3065e4b17023SJohn Marino while (from != to)
3066e4b17023SJohn Marino {
3067e4b17023SJohn Marino gcc_assert (peep2_insn_data[from].insn != NULL_RTX);
3068e4b17023SJohn Marino
3069e4b17023SJohn Marino /* Don't use registers set or clobbered by the insn. */
3070e4b17023SJohn Marino for (def_rec = DF_INSN_DEFS (peep2_insn_data[from].insn);
3071e4b17023SJohn Marino *def_rec; def_rec++)
3072e4b17023SJohn Marino SET_HARD_REG_BIT (live, DF_REF_REGNO (*def_rec));
3073e4b17023SJohn Marino
3074e4b17023SJohn Marino from = peep2_buf_position (from + 1);
3075e4b17023SJohn Marino }
3076e4b17023SJohn Marino
3077e4b17023SJohn Marino cl = (class_str[0] == 'r' ? GENERAL_REGS
3078e4b17023SJohn Marino : REG_CLASS_FROM_CONSTRAINT (class_str[0], class_str));
3079e4b17023SJohn Marino
3080e4b17023SJohn Marino for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
3081e4b17023SJohn Marino {
3082e4b17023SJohn Marino int raw_regno, regno, success, j;
3083e4b17023SJohn Marino
3084e4b17023SJohn Marino /* Distribute the free registers as much as possible. */
3085e4b17023SJohn Marino raw_regno = search_ofs + i;
3086e4b17023SJohn Marino if (raw_regno >= FIRST_PSEUDO_REGISTER)
3087e4b17023SJohn Marino raw_regno -= FIRST_PSEUDO_REGISTER;
3088e4b17023SJohn Marino #ifdef REG_ALLOC_ORDER
3089e4b17023SJohn Marino regno = reg_alloc_order[raw_regno];
3090e4b17023SJohn Marino #else
3091e4b17023SJohn Marino regno = raw_regno;
3092e4b17023SJohn Marino #endif
3093e4b17023SJohn Marino
3094e4b17023SJohn Marino /* Don't allocate fixed registers. */
3095e4b17023SJohn Marino if (fixed_regs[regno])
3096e4b17023SJohn Marino continue;
3097e4b17023SJohn Marino /* Don't allocate global registers. */
3098e4b17023SJohn Marino if (global_regs[regno])
3099e4b17023SJohn Marino continue;
3100e4b17023SJohn Marino /* Make sure the register is of the right class. */
3101e4b17023SJohn Marino if (! TEST_HARD_REG_BIT (reg_class_contents[cl], regno))
3102e4b17023SJohn Marino continue;
3103e4b17023SJohn Marino /* And can support the mode we need. */
3104e4b17023SJohn Marino if (! HARD_REGNO_MODE_OK (regno, mode))
3105e4b17023SJohn Marino continue;
3106e4b17023SJohn Marino /* And that we don't create an extra save/restore. */
3107e4b17023SJohn Marino if (! call_used_regs[regno] && ! df_regs_ever_live_p (regno))
3108e4b17023SJohn Marino continue;
3109e4b17023SJohn Marino if (! targetm.hard_regno_scratch_ok (regno))
3110e4b17023SJohn Marino continue;
3111e4b17023SJohn Marino
3112e4b17023SJohn Marino /* And we don't clobber traceback for noreturn functions. */
3113e4b17023SJohn Marino if ((regno == FRAME_POINTER_REGNUM || regno == HARD_FRAME_POINTER_REGNUM)
3114e4b17023SJohn Marino && (! reload_completed || frame_pointer_needed))
3115e4b17023SJohn Marino continue;
3116e4b17023SJohn Marino
3117e4b17023SJohn Marino success = 1;
3118e4b17023SJohn Marino for (j = hard_regno_nregs[regno][mode] - 1; j >= 0; j--)
3119e4b17023SJohn Marino {
3120e4b17023SJohn Marino if (TEST_HARD_REG_BIT (*reg_set, regno + j)
3121e4b17023SJohn Marino || TEST_HARD_REG_BIT (live, regno + j))
3122e4b17023SJohn Marino {
3123e4b17023SJohn Marino success = 0;
3124e4b17023SJohn Marino break;
3125e4b17023SJohn Marino }
3126e4b17023SJohn Marino }
3127e4b17023SJohn Marino if (success)
3128e4b17023SJohn Marino {
3129e4b17023SJohn Marino add_to_hard_reg_set (reg_set, mode, regno);
3130e4b17023SJohn Marino
3131e4b17023SJohn Marino /* Start the next search with the next register. */
3132e4b17023SJohn Marino if (++raw_regno >= FIRST_PSEUDO_REGISTER)
3133e4b17023SJohn Marino raw_regno = 0;
3134e4b17023SJohn Marino search_ofs = raw_regno;
3135e4b17023SJohn Marino
3136e4b17023SJohn Marino return gen_rtx_REG (mode, regno);
3137e4b17023SJohn Marino }
3138e4b17023SJohn Marino }
3139e4b17023SJohn Marino
3140e4b17023SJohn Marino search_ofs = 0;
3141e4b17023SJohn Marino return NULL_RTX;
3142e4b17023SJohn Marino }
3143e4b17023SJohn Marino
3144e4b17023SJohn Marino /* Forget all currently tracked instructions, only remember current
3145e4b17023SJohn Marino LIVE regset. */
3146e4b17023SJohn Marino
3147e4b17023SJohn Marino static void
peep2_reinit_state(regset live)3148e4b17023SJohn Marino peep2_reinit_state (regset live)
3149e4b17023SJohn Marino {
3150e4b17023SJohn Marino int i;
3151e4b17023SJohn Marino
3152e4b17023SJohn Marino /* Indicate that all slots except the last holds invalid data. */
3153e4b17023SJohn Marino for (i = 0; i < MAX_INSNS_PER_PEEP2; ++i)
3154e4b17023SJohn Marino peep2_insn_data[i].insn = NULL_RTX;
3155e4b17023SJohn Marino peep2_current_count = 0;
3156e4b17023SJohn Marino
3157e4b17023SJohn Marino /* Indicate that the last slot contains live_after data. */
3158e4b17023SJohn Marino peep2_insn_data[MAX_INSNS_PER_PEEP2].insn = PEEP2_EOB;
3159e4b17023SJohn Marino peep2_current = MAX_INSNS_PER_PEEP2;
3160e4b17023SJohn Marino
3161e4b17023SJohn Marino COPY_REG_SET (peep2_insn_data[MAX_INSNS_PER_PEEP2].live_before, live);
3162e4b17023SJohn Marino }
3163e4b17023SJohn Marino
3164e4b17023SJohn Marino /* While scanning basic block BB, we found a match of length MATCH_LEN,
3165e4b17023SJohn Marino starting at INSN. Perform the replacement, removing the old insns and
3166e4b17023SJohn Marino replacing them with ATTEMPT. Returns the last insn emitted, or NULL
3167e4b17023SJohn Marino if the replacement is rejected. */
3168e4b17023SJohn Marino
3169e4b17023SJohn Marino static rtx
peep2_attempt(basic_block bb,rtx insn,int match_len,rtx attempt)3170e4b17023SJohn Marino peep2_attempt (basic_block bb, rtx insn, int match_len, rtx attempt)
3171e4b17023SJohn Marino {
3172e4b17023SJohn Marino int i;
3173e4b17023SJohn Marino rtx last, eh_note, as_note, before_try, x;
3174e4b17023SJohn Marino rtx old_insn, new_insn;
3175e4b17023SJohn Marino bool was_call = false;
3176e4b17023SJohn Marino
3177e4b17023SJohn Marino /* If we are splitting an RTX_FRAME_RELATED_P insn, do not allow it to
3178e4b17023SJohn Marino match more than one insn, or to be split into more than one insn. */
3179e4b17023SJohn Marino old_insn = peep2_insn_data[peep2_current].insn;
3180e4b17023SJohn Marino if (RTX_FRAME_RELATED_P (old_insn))
3181e4b17023SJohn Marino {
3182e4b17023SJohn Marino bool any_note = false;
3183e4b17023SJohn Marino rtx note;
3184e4b17023SJohn Marino
3185e4b17023SJohn Marino if (match_len != 0)
3186e4b17023SJohn Marino return NULL;
3187e4b17023SJohn Marino
3188e4b17023SJohn Marino /* Look for one "active" insn. I.e. ignore any "clobber" insns that
3189e4b17023SJohn Marino may be in the stream for the purpose of register allocation. */
3190e4b17023SJohn Marino if (active_insn_p (attempt))
3191e4b17023SJohn Marino new_insn = attempt;
3192e4b17023SJohn Marino else
3193e4b17023SJohn Marino new_insn = next_active_insn (attempt);
3194e4b17023SJohn Marino if (next_active_insn (new_insn))
3195e4b17023SJohn Marino return NULL;
3196e4b17023SJohn Marino
3197e4b17023SJohn Marino /* We have a 1-1 replacement. Copy over any frame-related info. */
3198e4b17023SJohn Marino RTX_FRAME_RELATED_P (new_insn) = 1;
3199e4b17023SJohn Marino
3200e4b17023SJohn Marino /* Allow the backend to fill in a note during the split. */
3201e4b17023SJohn Marino for (note = REG_NOTES (new_insn); note ; note = XEXP (note, 1))
3202e4b17023SJohn Marino switch (REG_NOTE_KIND (note))
3203e4b17023SJohn Marino {
3204e4b17023SJohn Marino case REG_FRAME_RELATED_EXPR:
3205e4b17023SJohn Marino case REG_CFA_DEF_CFA:
3206e4b17023SJohn Marino case REG_CFA_ADJUST_CFA:
3207e4b17023SJohn Marino case REG_CFA_OFFSET:
3208e4b17023SJohn Marino case REG_CFA_REGISTER:
3209e4b17023SJohn Marino case REG_CFA_EXPRESSION:
3210e4b17023SJohn Marino case REG_CFA_RESTORE:
3211e4b17023SJohn Marino case REG_CFA_SET_VDRAP:
3212e4b17023SJohn Marino any_note = true;
3213e4b17023SJohn Marino break;
3214e4b17023SJohn Marino default:
3215e4b17023SJohn Marino break;
3216e4b17023SJohn Marino }
3217e4b17023SJohn Marino
3218e4b17023SJohn Marino /* If the backend didn't supply a note, copy one over. */
3219e4b17023SJohn Marino if (!any_note)
3220e4b17023SJohn Marino for (note = REG_NOTES (old_insn); note ; note = XEXP (note, 1))
3221e4b17023SJohn Marino switch (REG_NOTE_KIND (note))
3222e4b17023SJohn Marino {
3223e4b17023SJohn Marino case REG_FRAME_RELATED_EXPR:
3224e4b17023SJohn Marino case REG_CFA_DEF_CFA:
3225e4b17023SJohn Marino case REG_CFA_ADJUST_CFA:
3226e4b17023SJohn Marino case REG_CFA_OFFSET:
3227e4b17023SJohn Marino case REG_CFA_REGISTER:
3228e4b17023SJohn Marino case REG_CFA_EXPRESSION:
3229e4b17023SJohn Marino case REG_CFA_RESTORE:
3230e4b17023SJohn Marino case REG_CFA_SET_VDRAP:
3231e4b17023SJohn Marino add_reg_note (new_insn, REG_NOTE_KIND (note), XEXP (note, 0));
3232e4b17023SJohn Marino any_note = true;
3233e4b17023SJohn Marino break;
3234e4b17023SJohn Marino default:
3235e4b17023SJohn Marino break;
3236e4b17023SJohn Marino }
3237e4b17023SJohn Marino
3238e4b17023SJohn Marino /* If there still isn't a note, make sure the unwind info sees the
3239e4b17023SJohn Marino same expression as before the split. */
3240e4b17023SJohn Marino if (!any_note)
3241e4b17023SJohn Marino {
3242e4b17023SJohn Marino rtx old_set, new_set;
3243e4b17023SJohn Marino
3244e4b17023SJohn Marino /* The old insn had better have been simple, or annotated. */
3245e4b17023SJohn Marino old_set = single_set (old_insn);
3246e4b17023SJohn Marino gcc_assert (old_set != NULL);
3247e4b17023SJohn Marino
3248e4b17023SJohn Marino new_set = single_set (new_insn);
3249e4b17023SJohn Marino if (!new_set || !rtx_equal_p (new_set, old_set))
3250e4b17023SJohn Marino add_reg_note (new_insn, REG_FRAME_RELATED_EXPR, old_set);
3251e4b17023SJohn Marino }
3252e4b17023SJohn Marino
3253e4b17023SJohn Marino /* Copy prologue/epilogue status. This is required in order to keep
3254e4b17023SJohn Marino proper placement of EPILOGUE_BEG and the DW_CFA_remember_state. */
3255e4b17023SJohn Marino maybe_copy_prologue_epilogue_insn (old_insn, new_insn);
3256e4b17023SJohn Marino }
3257e4b17023SJohn Marino
3258e4b17023SJohn Marino /* If we are splitting a CALL_INSN, look for the CALL_INSN
3259e4b17023SJohn Marino in SEQ and copy our CALL_INSN_FUNCTION_USAGE and other
3260e4b17023SJohn Marino cfg-related call notes. */
3261e4b17023SJohn Marino for (i = 0; i <= match_len; ++i)
3262e4b17023SJohn Marino {
3263e4b17023SJohn Marino int j;
3264e4b17023SJohn Marino rtx note;
3265e4b17023SJohn Marino
3266e4b17023SJohn Marino j = peep2_buf_position (peep2_current + i);
3267e4b17023SJohn Marino old_insn = peep2_insn_data[j].insn;
3268e4b17023SJohn Marino if (!CALL_P (old_insn))
3269e4b17023SJohn Marino continue;
3270e4b17023SJohn Marino was_call = true;
3271e4b17023SJohn Marino
3272e4b17023SJohn Marino new_insn = attempt;
3273e4b17023SJohn Marino while (new_insn != NULL_RTX)
3274e4b17023SJohn Marino {
3275e4b17023SJohn Marino if (CALL_P (new_insn))
3276e4b17023SJohn Marino break;
3277e4b17023SJohn Marino new_insn = NEXT_INSN (new_insn);
3278e4b17023SJohn Marino }
3279e4b17023SJohn Marino
3280e4b17023SJohn Marino gcc_assert (new_insn != NULL_RTX);
3281e4b17023SJohn Marino
3282e4b17023SJohn Marino CALL_INSN_FUNCTION_USAGE (new_insn)
3283e4b17023SJohn Marino = CALL_INSN_FUNCTION_USAGE (old_insn);
3284e4b17023SJohn Marino
3285e4b17023SJohn Marino for (note = REG_NOTES (old_insn);
3286e4b17023SJohn Marino note;
3287e4b17023SJohn Marino note = XEXP (note, 1))
3288e4b17023SJohn Marino switch (REG_NOTE_KIND (note))
3289e4b17023SJohn Marino {
3290e4b17023SJohn Marino case REG_NORETURN:
3291e4b17023SJohn Marino case REG_SETJMP:
3292e4b17023SJohn Marino case REG_TM:
3293e4b17023SJohn Marino add_reg_note (new_insn, REG_NOTE_KIND (note),
3294e4b17023SJohn Marino XEXP (note, 0));
3295e4b17023SJohn Marino break;
3296e4b17023SJohn Marino default:
3297e4b17023SJohn Marino /* Discard all other reg notes. */
3298e4b17023SJohn Marino break;
3299e4b17023SJohn Marino }
3300e4b17023SJohn Marino
3301e4b17023SJohn Marino /* Croak if there is another call in the sequence. */
3302e4b17023SJohn Marino while (++i <= match_len)
3303e4b17023SJohn Marino {
3304e4b17023SJohn Marino j = peep2_buf_position (peep2_current + i);
3305e4b17023SJohn Marino old_insn = peep2_insn_data[j].insn;
3306e4b17023SJohn Marino gcc_assert (!CALL_P (old_insn));
3307e4b17023SJohn Marino }
3308e4b17023SJohn Marino break;
3309e4b17023SJohn Marino }
3310e4b17023SJohn Marino
3311e4b17023SJohn Marino /* If we matched any instruction that had a REG_ARGS_SIZE, then
3312e4b17023SJohn Marino move those notes over to the new sequence. */
3313e4b17023SJohn Marino as_note = NULL;
3314e4b17023SJohn Marino for (i = match_len; i >= 0; --i)
3315e4b17023SJohn Marino {
3316e4b17023SJohn Marino int j = peep2_buf_position (peep2_current + i);
3317e4b17023SJohn Marino old_insn = peep2_insn_data[j].insn;
3318e4b17023SJohn Marino
3319e4b17023SJohn Marino as_note = find_reg_note (old_insn, REG_ARGS_SIZE, NULL);
3320e4b17023SJohn Marino if (as_note)
3321e4b17023SJohn Marino break;
3322e4b17023SJohn Marino }
3323e4b17023SJohn Marino
3324e4b17023SJohn Marino i = peep2_buf_position (peep2_current + match_len);
3325e4b17023SJohn Marino eh_note = find_reg_note (peep2_insn_data[i].insn, REG_EH_REGION, NULL_RTX);
3326e4b17023SJohn Marino
3327e4b17023SJohn Marino /* Replace the old sequence with the new. */
3328e4b17023SJohn Marino last = emit_insn_after_setloc (attempt,
3329e4b17023SJohn Marino peep2_insn_data[i].insn,
3330e4b17023SJohn Marino INSN_LOCATOR (peep2_insn_data[i].insn));
3331e4b17023SJohn Marino before_try = PREV_INSN (insn);
3332e4b17023SJohn Marino delete_insn_chain (insn, peep2_insn_data[i].insn, false);
3333e4b17023SJohn Marino
3334e4b17023SJohn Marino /* Re-insert the EH_REGION notes. */
3335e4b17023SJohn Marino if (eh_note || (was_call && nonlocal_goto_handler_labels))
3336e4b17023SJohn Marino {
3337e4b17023SJohn Marino edge eh_edge;
3338e4b17023SJohn Marino edge_iterator ei;
3339e4b17023SJohn Marino
3340e4b17023SJohn Marino FOR_EACH_EDGE (eh_edge, ei, bb->succs)
3341e4b17023SJohn Marino if (eh_edge->flags & (EDGE_EH | EDGE_ABNORMAL_CALL))
3342e4b17023SJohn Marino break;
3343e4b17023SJohn Marino
3344e4b17023SJohn Marino if (eh_note)
3345e4b17023SJohn Marino copy_reg_eh_region_note_backward (eh_note, last, before_try);
3346e4b17023SJohn Marino
3347e4b17023SJohn Marino if (eh_edge)
3348e4b17023SJohn Marino for (x = last; x != before_try; x = PREV_INSN (x))
3349e4b17023SJohn Marino if (x != BB_END (bb)
3350e4b17023SJohn Marino && (can_throw_internal (x)
3351e4b17023SJohn Marino || can_nonlocal_goto (x)))
3352e4b17023SJohn Marino {
3353e4b17023SJohn Marino edge nfte, nehe;
3354e4b17023SJohn Marino int flags;
3355e4b17023SJohn Marino
3356e4b17023SJohn Marino nfte = split_block (bb, x);
3357e4b17023SJohn Marino flags = (eh_edge->flags
3358e4b17023SJohn Marino & (EDGE_EH | EDGE_ABNORMAL));
3359e4b17023SJohn Marino if (CALL_P (x))
3360e4b17023SJohn Marino flags |= EDGE_ABNORMAL_CALL;
3361e4b17023SJohn Marino nehe = make_edge (nfte->src, eh_edge->dest,
3362e4b17023SJohn Marino flags);
3363e4b17023SJohn Marino
3364e4b17023SJohn Marino nehe->probability = eh_edge->probability;
3365e4b17023SJohn Marino nfte->probability
3366e4b17023SJohn Marino = REG_BR_PROB_BASE - nehe->probability;
3367e4b17023SJohn Marino
3368e4b17023SJohn Marino peep2_do_cleanup_cfg |= purge_dead_edges (nfte->dest);
3369e4b17023SJohn Marino bb = nfte->src;
3370e4b17023SJohn Marino eh_edge = nehe;
3371e4b17023SJohn Marino }
3372e4b17023SJohn Marino
3373e4b17023SJohn Marino /* Converting possibly trapping insn to non-trapping is
3374e4b17023SJohn Marino possible. Zap dummy outgoing edges. */
3375e4b17023SJohn Marino peep2_do_cleanup_cfg |= purge_dead_edges (bb);
3376e4b17023SJohn Marino }
3377e4b17023SJohn Marino
3378e4b17023SJohn Marino /* Re-insert the ARGS_SIZE notes. */
3379e4b17023SJohn Marino if (as_note)
3380e4b17023SJohn Marino fixup_args_size_notes (before_try, last, INTVAL (XEXP (as_note, 0)));
3381e4b17023SJohn Marino
3382e4b17023SJohn Marino /* If we generated a jump instruction, it won't have
3383e4b17023SJohn Marino JUMP_LABEL set. Recompute after we're done. */
3384e4b17023SJohn Marino for (x = last; x != before_try; x = PREV_INSN (x))
3385e4b17023SJohn Marino if (JUMP_P (x))
3386e4b17023SJohn Marino {
3387e4b17023SJohn Marino peep2_do_rebuild_jump_labels = true;
3388e4b17023SJohn Marino break;
3389e4b17023SJohn Marino }
3390e4b17023SJohn Marino
3391e4b17023SJohn Marino return last;
3392e4b17023SJohn Marino }
3393e4b17023SJohn Marino
3394e4b17023SJohn Marino /* After performing a replacement in basic block BB, fix up the life
3395e4b17023SJohn Marino information in our buffer. LAST is the last of the insns that we
3396e4b17023SJohn Marino emitted as a replacement. PREV is the insn before the start of
3397e4b17023SJohn Marino the replacement. MATCH_LEN is the number of instructions that were
3398e4b17023SJohn Marino matched, and which now need to be replaced in the buffer. */
3399e4b17023SJohn Marino
3400e4b17023SJohn Marino static void
peep2_update_life(basic_block bb,int match_len,rtx last,rtx prev)3401e4b17023SJohn Marino peep2_update_life (basic_block bb, int match_len, rtx last, rtx prev)
3402e4b17023SJohn Marino {
3403e4b17023SJohn Marino int i = peep2_buf_position (peep2_current + match_len + 1);
3404e4b17023SJohn Marino rtx x;
3405e4b17023SJohn Marino regset_head live;
3406e4b17023SJohn Marino
3407e4b17023SJohn Marino INIT_REG_SET (&live);
3408e4b17023SJohn Marino COPY_REG_SET (&live, peep2_insn_data[i].live_before);
3409e4b17023SJohn Marino
3410e4b17023SJohn Marino gcc_assert (peep2_current_count >= match_len + 1);
3411e4b17023SJohn Marino peep2_current_count -= match_len + 1;
3412e4b17023SJohn Marino
3413e4b17023SJohn Marino x = last;
3414e4b17023SJohn Marino do
3415e4b17023SJohn Marino {
3416e4b17023SJohn Marino if (INSN_P (x))
3417e4b17023SJohn Marino {
3418e4b17023SJohn Marino df_insn_rescan (x);
3419e4b17023SJohn Marino if (peep2_current_count < MAX_INSNS_PER_PEEP2)
3420e4b17023SJohn Marino {
3421e4b17023SJohn Marino peep2_current_count++;
3422e4b17023SJohn Marino if (--i < 0)
3423e4b17023SJohn Marino i = MAX_INSNS_PER_PEEP2;
3424e4b17023SJohn Marino peep2_insn_data[i].insn = x;
3425e4b17023SJohn Marino df_simulate_one_insn_backwards (bb, x, &live);
3426e4b17023SJohn Marino COPY_REG_SET (peep2_insn_data[i].live_before, &live);
3427e4b17023SJohn Marino }
3428e4b17023SJohn Marino }
3429e4b17023SJohn Marino x = PREV_INSN (x);
3430e4b17023SJohn Marino }
3431e4b17023SJohn Marino while (x != prev);
3432e4b17023SJohn Marino CLEAR_REG_SET (&live);
3433e4b17023SJohn Marino
3434e4b17023SJohn Marino peep2_current = i;
3435e4b17023SJohn Marino }
3436e4b17023SJohn Marino
3437e4b17023SJohn Marino /* Add INSN, which is in BB, at the end of the peep2 insn buffer if possible.
3438e4b17023SJohn Marino Return true if we added it, false otherwise. The caller will try to match
3439e4b17023SJohn Marino peepholes against the buffer if we return false; otherwise it will try to
3440e4b17023SJohn Marino add more instructions to the buffer. */
3441e4b17023SJohn Marino
3442e4b17023SJohn Marino static bool
peep2_fill_buffer(basic_block bb,rtx insn,regset live)3443e4b17023SJohn Marino peep2_fill_buffer (basic_block bb, rtx insn, regset live)
3444e4b17023SJohn Marino {
3445e4b17023SJohn Marino int pos;
3446e4b17023SJohn Marino
3447e4b17023SJohn Marino /* Once we have filled the maximum number of insns the buffer can hold,
3448e4b17023SJohn Marino allow the caller to match the insns against peepholes. We wait until
3449e4b17023SJohn Marino the buffer is full in case the target has similar peepholes of different
3450e4b17023SJohn Marino length; we always want to match the longest if possible. */
3451e4b17023SJohn Marino if (peep2_current_count == MAX_INSNS_PER_PEEP2)
3452e4b17023SJohn Marino return false;
3453e4b17023SJohn Marino
3454e4b17023SJohn Marino /* If an insn has RTX_FRAME_RELATED_P set, do not allow it to be matched with
3455e4b17023SJohn Marino any other pattern, lest it change the semantics of the frame info. */
3456e4b17023SJohn Marino if (RTX_FRAME_RELATED_P (insn))
3457e4b17023SJohn Marino {
3458e4b17023SJohn Marino /* Let the buffer drain first. */
3459e4b17023SJohn Marino if (peep2_current_count > 0)
3460e4b17023SJohn Marino return false;
3461e4b17023SJohn Marino /* Now the insn will be the only thing in the buffer. */
3462e4b17023SJohn Marino }
3463e4b17023SJohn Marino
3464e4b17023SJohn Marino pos = peep2_buf_position (peep2_current + peep2_current_count);
3465e4b17023SJohn Marino peep2_insn_data[pos].insn = insn;
3466e4b17023SJohn Marino COPY_REG_SET (peep2_insn_data[pos].live_before, live);
3467e4b17023SJohn Marino peep2_current_count++;
3468e4b17023SJohn Marino
3469e4b17023SJohn Marino df_simulate_one_insn_forwards (bb, insn, live);
3470e4b17023SJohn Marino return true;
3471e4b17023SJohn Marino }
3472e4b17023SJohn Marino
3473e4b17023SJohn Marino /* Perform the peephole2 optimization pass. */
3474e4b17023SJohn Marino
3475e4b17023SJohn Marino static void
peephole2_optimize(void)3476e4b17023SJohn Marino peephole2_optimize (void)
3477e4b17023SJohn Marino {
3478e4b17023SJohn Marino rtx insn;
3479e4b17023SJohn Marino bitmap live;
3480e4b17023SJohn Marino int i;
3481e4b17023SJohn Marino basic_block bb;
3482e4b17023SJohn Marino
3483e4b17023SJohn Marino peep2_do_cleanup_cfg = false;
3484e4b17023SJohn Marino peep2_do_rebuild_jump_labels = false;
3485e4b17023SJohn Marino
3486e4b17023SJohn Marino df_set_flags (DF_LR_RUN_DCE);
3487e4b17023SJohn Marino df_note_add_problem ();
3488e4b17023SJohn Marino df_analyze ();
3489e4b17023SJohn Marino
3490e4b17023SJohn Marino /* Initialize the regsets we're going to use. */
3491e4b17023SJohn Marino for (i = 0; i < MAX_INSNS_PER_PEEP2 + 1; ++i)
3492e4b17023SJohn Marino peep2_insn_data[i].live_before = BITMAP_ALLOC (®_obstack);
3493*95d28233SJohn Marino search_ofs = 0;
3494e4b17023SJohn Marino live = BITMAP_ALLOC (®_obstack);
3495e4b17023SJohn Marino
3496e4b17023SJohn Marino FOR_EACH_BB_REVERSE (bb)
3497e4b17023SJohn Marino {
3498e4b17023SJohn Marino bool past_end = false;
3499e4b17023SJohn Marino int pos;
3500e4b17023SJohn Marino
3501e4b17023SJohn Marino rtl_profile_for_bb (bb);
3502e4b17023SJohn Marino
3503e4b17023SJohn Marino /* Start up propagation. */
3504e4b17023SJohn Marino bitmap_copy (live, DF_LR_IN (bb));
3505e4b17023SJohn Marino df_simulate_initialize_forwards (bb, live);
3506e4b17023SJohn Marino peep2_reinit_state (live);
3507e4b17023SJohn Marino
3508e4b17023SJohn Marino insn = BB_HEAD (bb);
3509e4b17023SJohn Marino for (;;)
3510e4b17023SJohn Marino {
3511e4b17023SJohn Marino rtx attempt, head;
3512e4b17023SJohn Marino int match_len;
3513e4b17023SJohn Marino
3514e4b17023SJohn Marino if (!past_end && !NONDEBUG_INSN_P (insn))
3515e4b17023SJohn Marino {
3516e4b17023SJohn Marino next_insn:
3517e4b17023SJohn Marino insn = NEXT_INSN (insn);
3518e4b17023SJohn Marino if (insn == NEXT_INSN (BB_END (bb)))
3519e4b17023SJohn Marino past_end = true;
3520e4b17023SJohn Marino continue;
3521e4b17023SJohn Marino }
3522e4b17023SJohn Marino if (!past_end && peep2_fill_buffer (bb, insn, live))
3523e4b17023SJohn Marino goto next_insn;
3524e4b17023SJohn Marino
3525e4b17023SJohn Marino /* If we did not fill an empty buffer, it signals the end of the
3526e4b17023SJohn Marino block. */
3527e4b17023SJohn Marino if (peep2_current_count == 0)
3528e4b17023SJohn Marino break;
3529e4b17023SJohn Marino
3530e4b17023SJohn Marino /* The buffer filled to the current maximum, so try to match. */
3531e4b17023SJohn Marino
3532e4b17023SJohn Marino pos = peep2_buf_position (peep2_current + peep2_current_count);
3533e4b17023SJohn Marino peep2_insn_data[pos].insn = PEEP2_EOB;
3534e4b17023SJohn Marino COPY_REG_SET (peep2_insn_data[pos].live_before, live);
3535e4b17023SJohn Marino
3536e4b17023SJohn Marino /* Match the peephole. */
3537e4b17023SJohn Marino head = peep2_insn_data[peep2_current].insn;
3538e4b17023SJohn Marino attempt = peephole2_insns (PATTERN (head), head, &match_len);
3539e4b17023SJohn Marino if (attempt != NULL)
3540e4b17023SJohn Marino {
3541e4b17023SJohn Marino rtx last = peep2_attempt (bb, head, match_len, attempt);
3542e4b17023SJohn Marino if (last)
3543e4b17023SJohn Marino {
3544e4b17023SJohn Marino peep2_update_life (bb, match_len, last, PREV_INSN (attempt));
3545e4b17023SJohn Marino continue;
3546e4b17023SJohn Marino }
3547e4b17023SJohn Marino }
3548e4b17023SJohn Marino
3549e4b17023SJohn Marino /* No match: advance the buffer by one insn. */
3550e4b17023SJohn Marino peep2_current = peep2_buf_position (peep2_current + 1);
3551e4b17023SJohn Marino peep2_current_count--;
3552e4b17023SJohn Marino }
3553e4b17023SJohn Marino }
3554e4b17023SJohn Marino
3555e4b17023SJohn Marino default_rtl_profile ();
3556e4b17023SJohn Marino for (i = 0; i < MAX_INSNS_PER_PEEP2 + 1; ++i)
3557e4b17023SJohn Marino BITMAP_FREE (peep2_insn_data[i].live_before);
3558e4b17023SJohn Marino BITMAP_FREE (live);
3559e4b17023SJohn Marino if (peep2_do_rebuild_jump_labels)
3560e4b17023SJohn Marino rebuild_jump_labels (get_insns ());
3561e4b17023SJohn Marino }
3562e4b17023SJohn Marino #endif /* HAVE_peephole2 */
3563e4b17023SJohn Marino
3564e4b17023SJohn Marino /* Common predicates for use with define_bypass. */
3565e4b17023SJohn Marino
3566e4b17023SJohn Marino /* True if the dependency between OUT_INSN and IN_INSN is on the store
3567e4b17023SJohn Marino data not the address operand(s) of the store. IN_INSN and OUT_INSN
3568e4b17023SJohn Marino must be either a single_set or a PARALLEL with SETs inside. */
3569e4b17023SJohn Marino
3570e4b17023SJohn Marino int
store_data_bypass_p(rtx out_insn,rtx in_insn)3571e4b17023SJohn Marino store_data_bypass_p (rtx out_insn, rtx in_insn)
3572e4b17023SJohn Marino {
3573e4b17023SJohn Marino rtx out_set, in_set;
3574e4b17023SJohn Marino rtx out_pat, in_pat;
3575e4b17023SJohn Marino rtx out_exp, in_exp;
3576e4b17023SJohn Marino int i, j;
3577e4b17023SJohn Marino
3578e4b17023SJohn Marino in_set = single_set (in_insn);
3579e4b17023SJohn Marino if (in_set)
3580e4b17023SJohn Marino {
3581e4b17023SJohn Marino if (!MEM_P (SET_DEST (in_set)))
3582e4b17023SJohn Marino return false;
3583e4b17023SJohn Marino
3584e4b17023SJohn Marino out_set = single_set (out_insn);
3585e4b17023SJohn Marino if (out_set)
3586e4b17023SJohn Marino {
3587e4b17023SJohn Marino if (reg_mentioned_p (SET_DEST (out_set), SET_DEST (in_set)))
3588e4b17023SJohn Marino return false;
3589e4b17023SJohn Marino }
3590e4b17023SJohn Marino else
3591e4b17023SJohn Marino {
3592e4b17023SJohn Marino out_pat = PATTERN (out_insn);
3593e4b17023SJohn Marino
3594e4b17023SJohn Marino if (GET_CODE (out_pat) != PARALLEL)
3595e4b17023SJohn Marino return false;
3596e4b17023SJohn Marino
3597e4b17023SJohn Marino for (i = 0; i < XVECLEN (out_pat, 0); i++)
3598e4b17023SJohn Marino {
3599e4b17023SJohn Marino out_exp = XVECEXP (out_pat, 0, i);
3600e4b17023SJohn Marino
3601e4b17023SJohn Marino if (GET_CODE (out_exp) == CLOBBER)
3602e4b17023SJohn Marino continue;
3603e4b17023SJohn Marino
3604e4b17023SJohn Marino gcc_assert (GET_CODE (out_exp) == SET);
3605e4b17023SJohn Marino
3606e4b17023SJohn Marino if (reg_mentioned_p (SET_DEST (out_exp), SET_DEST (in_set)))
3607e4b17023SJohn Marino return false;
3608e4b17023SJohn Marino }
3609e4b17023SJohn Marino }
3610e4b17023SJohn Marino }
3611e4b17023SJohn Marino else
3612e4b17023SJohn Marino {
3613e4b17023SJohn Marino in_pat = PATTERN (in_insn);
3614e4b17023SJohn Marino gcc_assert (GET_CODE (in_pat) == PARALLEL);
3615e4b17023SJohn Marino
3616e4b17023SJohn Marino for (i = 0; i < XVECLEN (in_pat, 0); i++)
3617e4b17023SJohn Marino {
3618e4b17023SJohn Marino in_exp = XVECEXP (in_pat, 0, i);
3619e4b17023SJohn Marino
3620e4b17023SJohn Marino if (GET_CODE (in_exp) == CLOBBER)
3621e4b17023SJohn Marino continue;
3622e4b17023SJohn Marino
3623e4b17023SJohn Marino gcc_assert (GET_CODE (in_exp) == SET);
3624e4b17023SJohn Marino
3625e4b17023SJohn Marino if (!MEM_P (SET_DEST (in_exp)))
3626e4b17023SJohn Marino return false;
3627e4b17023SJohn Marino
3628e4b17023SJohn Marino out_set = single_set (out_insn);
3629e4b17023SJohn Marino if (out_set)
3630e4b17023SJohn Marino {
3631e4b17023SJohn Marino if (reg_mentioned_p (SET_DEST (out_set), SET_DEST (in_exp)))
3632e4b17023SJohn Marino return false;
3633e4b17023SJohn Marino }
3634e4b17023SJohn Marino else
3635e4b17023SJohn Marino {
3636e4b17023SJohn Marino out_pat = PATTERN (out_insn);
3637e4b17023SJohn Marino gcc_assert (GET_CODE (out_pat) == PARALLEL);
3638e4b17023SJohn Marino
3639e4b17023SJohn Marino for (j = 0; j < XVECLEN (out_pat, 0); j++)
3640e4b17023SJohn Marino {
3641e4b17023SJohn Marino out_exp = XVECEXP (out_pat, 0, j);
3642e4b17023SJohn Marino
3643e4b17023SJohn Marino if (GET_CODE (out_exp) == CLOBBER)
3644e4b17023SJohn Marino continue;
3645e4b17023SJohn Marino
3646e4b17023SJohn Marino gcc_assert (GET_CODE (out_exp) == SET);
3647e4b17023SJohn Marino
3648e4b17023SJohn Marino if (reg_mentioned_p (SET_DEST (out_exp), SET_DEST (in_exp)))
3649e4b17023SJohn Marino return false;
3650e4b17023SJohn Marino }
3651e4b17023SJohn Marino }
3652e4b17023SJohn Marino }
3653e4b17023SJohn Marino }
3654e4b17023SJohn Marino
3655e4b17023SJohn Marino return true;
3656e4b17023SJohn Marino }
3657e4b17023SJohn Marino
3658e4b17023SJohn Marino /* True if the dependency between OUT_INSN and IN_INSN is in the IF_THEN_ELSE
3659e4b17023SJohn Marino condition, and not the THEN or ELSE branch. OUT_INSN may be either a single
3660e4b17023SJohn Marino or multiple set; IN_INSN should be single_set for truth, but for convenience
3661e4b17023SJohn Marino of insn categorization may be any JUMP or CALL insn. */
3662e4b17023SJohn Marino
3663e4b17023SJohn Marino int
if_test_bypass_p(rtx out_insn,rtx in_insn)3664e4b17023SJohn Marino if_test_bypass_p (rtx out_insn, rtx in_insn)
3665e4b17023SJohn Marino {
3666e4b17023SJohn Marino rtx out_set, in_set;
3667e4b17023SJohn Marino
3668e4b17023SJohn Marino in_set = single_set (in_insn);
3669e4b17023SJohn Marino if (! in_set)
3670e4b17023SJohn Marino {
3671e4b17023SJohn Marino gcc_assert (JUMP_P (in_insn) || CALL_P (in_insn));
3672e4b17023SJohn Marino return false;
3673e4b17023SJohn Marino }
3674e4b17023SJohn Marino
3675e4b17023SJohn Marino if (GET_CODE (SET_SRC (in_set)) != IF_THEN_ELSE)
3676e4b17023SJohn Marino return false;
3677e4b17023SJohn Marino in_set = SET_SRC (in_set);
3678e4b17023SJohn Marino
3679e4b17023SJohn Marino out_set = single_set (out_insn);
3680e4b17023SJohn Marino if (out_set)
3681e4b17023SJohn Marino {
3682e4b17023SJohn Marino if (reg_mentioned_p (SET_DEST (out_set), XEXP (in_set, 1))
3683e4b17023SJohn Marino || reg_mentioned_p (SET_DEST (out_set), XEXP (in_set, 2)))
3684e4b17023SJohn Marino return false;
3685e4b17023SJohn Marino }
3686e4b17023SJohn Marino else
3687e4b17023SJohn Marino {
3688e4b17023SJohn Marino rtx out_pat;
3689e4b17023SJohn Marino int i;
3690e4b17023SJohn Marino
3691e4b17023SJohn Marino out_pat = PATTERN (out_insn);
3692e4b17023SJohn Marino gcc_assert (GET_CODE (out_pat) == PARALLEL);
3693e4b17023SJohn Marino
3694e4b17023SJohn Marino for (i = 0; i < XVECLEN (out_pat, 0); i++)
3695e4b17023SJohn Marino {
3696e4b17023SJohn Marino rtx exp = XVECEXP (out_pat, 0, i);
3697e4b17023SJohn Marino
3698e4b17023SJohn Marino if (GET_CODE (exp) == CLOBBER)
3699e4b17023SJohn Marino continue;
3700e4b17023SJohn Marino
3701e4b17023SJohn Marino gcc_assert (GET_CODE (exp) == SET);
3702e4b17023SJohn Marino
3703e4b17023SJohn Marino if (reg_mentioned_p (SET_DEST (out_set), XEXP (in_set, 1))
3704e4b17023SJohn Marino || reg_mentioned_p (SET_DEST (out_set), XEXP (in_set, 2)))
3705e4b17023SJohn Marino return false;
3706e4b17023SJohn Marino }
3707e4b17023SJohn Marino }
3708e4b17023SJohn Marino
3709e4b17023SJohn Marino return true;
3710e4b17023SJohn Marino }
3711e4b17023SJohn Marino
3712e4b17023SJohn Marino static bool
gate_handle_peephole2(void)3713e4b17023SJohn Marino gate_handle_peephole2 (void)
3714e4b17023SJohn Marino {
3715e4b17023SJohn Marino return (optimize > 0 && flag_peephole2);
3716e4b17023SJohn Marino }
3717e4b17023SJohn Marino
3718e4b17023SJohn Marino static unsigned int
rest_of_handle_peephole2(void)3719e4b17023SJohn Marino rest_of_handle_peephole2 (void)
3720e4b17023SJohn Marino {
3721e4b17023SJohn Marino #ifdef HAVE_peephole2
3722e4b17023SJohn Marino peephole2_optimize ();
3723e4b17023SJohn Marino #endif
3724e4b17023SJohn Marino return 0;
3725e4b17023SJohn Marino }
3726e4b17023SJohn Marino
3727e4b17023SJohn Marino struct rtl_opt_pass pass_peephole2 =
3728e4b17023SJohn Marino {
3729e4b17023SJohn Marino {
3730e4b17023SJohn Marino RTL_PASS,
3731e4b17023SJohn Marino "peephole2", /* name */
3732e4b17023SJohn Marino gate_handle_peephole2, /* gate */
3733e4b17023SJohn Marino rest_of_handle_peephole2, /* execute */
3734e4b17023SJohn Marino NULL, /* sub */
3735e4b17023SJohn Marino NULL, /* next */
3736e4b17023SJohn Marino 0, /* static_pass_number */
3737e4b17023SJohn Marino TV_PEEPHOLE2, /* tv_id */
3738e4b17023SJohn Marino 0, /* properties_required */
3739e4b17023SJohn Marino 0, /* properties_provided */
3740e4b17023SJohn Marino 0, /* properties_destroyed */
3741e4b17023SJohn Marino 0, /* todo_flags_start */
3742e4b17023SJohn Marino TODO_df_finish | TODO_verify_rtl_sharing |
3743e4b17023SJohn Marino 0 /* todo_flags_finish */
3744e4b17023SJohn Marino }
3745e4b17023SJohn Marino };
3746e4b17023SJohn Marino
3747e4b17023SJohn Marino static unsigned int
rest_of_handle_split_all_insns(void)3748e4b17023SJohn Marino rest_of_handle_split_all_insns (void)
3749e4b17023SJohn Marino {
3750e4b17023SJohn Marino split_all_insns ();
3751e4b17023SJohn Marino return 0;
3752e4b17023SJohn Marino }
3753e4b17023SJohn Marino
3754e4b17023SJohn Marino struct rtl_opt_pass pass_split_all_insns =
3755e4b17023SJohn Marino {
3756e4b17023SJohn Marino {
3757e4b17023SJohn Marino RTL_PASS,
3758e4b17023SJohn Marino "split1", /* name */
3759e4b17023SJohn Marino NULL, /* gate */
3760e4b17023SJohn Marino rest_of_handle_split_all_insns, /* execute */
3761e4b17023SJohn Marino NULL, /* sub */
3762e4b17023SJohn Marino NULL, /* next */
3763e4b17023SJohn Marino 0, /* static_pass_number */
3764e4b17023SJohn Marino TV_NONE, /* tv_id */
3765e4b17023SJohn Marino 0, /* properties_required */
3766e4b17023SJohn Marino 0, /* properties_provided */
3767e4b17023SJohn Marino 0, /* properties_destroyed */
3768e4b17023SJohn Marino 0, /* todo_flags_start */
3769e4b17023SJohn Marino 0 /* todo_flags_finish */
3770e4b17023SJohn Marino }
3771e4b17023SJohn Marino };
3772e4b17023SJohn Marino
3773e4b17023SJohn Marino static unsigned int
rest_of_handle_split_after_reload(void)3774e4b17023SJohn Marino rest_of_handle_split_after_reload (void)
3775e4b17023SJohn Marino {
3776e4b17023SJohn Marino /* If optimizing, then go ahead and split insns now. */
3777e4b17023SJohn Marino #ifndef STACK_REGS
3778e4b17023SJohn Marino if (optimize > 0)
3779e4b17023SJohn Marino #endif
3780e4b17023SJohn Marino split_all_insns ();
3781e4b17023SJohn Marino return 0;
3782e4b17023SJohn Marino }
3783e4b17023SJohn Marino
3784e4b17023SJohn Marino struct rtl_opt_pass pass_split_after_reload =
3785e4b17023SJohn Marino {
3786e4b17023SJohn Marino {
3787e4b17023SJohn Marino RTL_PASS,
3788e4b17023SJohn Marino "split2", /* name */
3789e4b17023SJohn Marino NULL, /* gate */
3790e4b17023SJohn Marino rest_of_handle_split_after_reload, /* execute */
3791e4b17023SJohn Marino NULL, /* sub */
3792e4b17023SJohn Marino NULL, /* next */
3793e4b17023SJohn Marino 0, /* static_pass_number */
3794e4b17023SJohn Marino TV_NONE, /* tv_id */
3795e4b17023SJohn Marino 0, /* properties_required */
3796e4b17023SJohn Marino 0, /* properties_provided */
3797e4b17023SJohn Marino 0, /* properties_destroyed */
3798e4b17023SJohn Marino 0, /* todo_flags_start */
3799e4b17023SJohn Marino 0 /* todo_flags_finish */
3800e4b17023SJohn Marino }
3801e4b17023SJohn Marino };
3802e4b17023SJohn Marino
3803e4b17023SJohn Marino static bool
gate_handle_split_before_regstack(void)3804e4b17023SJohn Marino gate_handle_split_before_regstack (void)
3805e4b17023SJohn Marino {
3806e4b17023SJohn Marino #if defined (HAVE_ATTR_length) && defined (STACK_REGS)
3807e4b17023SJohn Marino /* If flow2 creates new instructions which need splitting
3808e4b17023SJohn Marino and scheduling after reload is not done, they might not be
3809e4b17023SJohn Marino split until final which doesn't allow splitting
3810e4b17023SJohn Marino if HAVE_ATTR_length. */
3811e4b17023SJohn Marino # ifdef INSN_SCHEDULING
3812e4b17023SJohn Marino return (optimize && !flag_schedule_insns_after_reload);
3813e4b17023SJohn Marino # else
3814e4b17023SJohn Marino return (optimize);
3815e4b17023SJohn Marino # endif
3816e4b17023SJohn Marino #else
3817e4b17023SJohn Marino return 0;
3818e4b17023SJohn Marino #endif
3819e4b17023SJohn Marino }
3820e4b17023SJohn Marino
3821e4b17023SJohn Marino static unsigned int
rest_of_handle_split_before_regstack(void)3822e4b17023SJohn Marino rest_of_handle_split_before_regstack (void)
3823e4b17023SJohn Marino {
3824e4b17023SJohn Marino split_all_insns ();
3825e4b17023SJohn Marino return 0;
3826e4b17023SJohn Marino }
3827e4b17023SJohn Marino
3828e4b17023SJohn Marino struct rtl_opt_pass pass_split_before_regstack =
3829e4b17023SJohn Marino {
3830e4b17023SJohn Marino {
3831e4b17023SJohn Marino RTL_PASS,
3832e4b17023SJohn Marino "split3", /* name */
3833e4b17023SJohn Marino gate_handle_split_before_regstack, /* gate */
3834e4b17023SJohn Marino rest_of_handle_split_before_regstack, /* execute */
3835e4b17023SJohn Marino NULL, /* sub */
3836e4b17023SJohn Marino NULL, /* next */
3837e4b17023SJohn Marino 0, /* static_pass_number */
3838e4b17023SJohn Marino TV_NONE, /* tv_id */
3839e4b17023SJohn Marino 0, /* properties_required */
3840e4b17023SJohn Marino 0, /* properties_provided */
3841e4b17023SJohn Marino 0, /* properties_destroyed */
3842e4b17023SJohn Marino 0, /* todo_flags_start */
3843e4b17023SJohn Marino 0 /* todo_flags_finish */
3844e4b17023SJohn Marino }
3845e4b17023SJohn Marino };
3846e4b17023SJohn Marino
3847e4b17023SJohn Marino static bool
gate_handle_split_before_sched2(void)3848e4b17023SJohn Marino gate_handle_split_before_sched2 (void)
3849e4b17023SJohn Marino {
3850e4b17023SJohn Marino #ifdef INSN_SCHEDULING
3851e4b17023SJohn Marino return optimize > 0 && flag_schedule_insns_after_reload;
3852e4b17023SJohn Marino #else
3853e4b17023SJohn Marino return 0;
3854e4b17023SJohn Marino #endif
3855e4b17023SJohn Marino }
3856e4b17023SJohn Marino
3857e4b17023SJohn Marino static unsigned int
rest_of_handle_split_before_sched2(void)3858e4b17023SJohn Marino rest_of_handle_split_before_sched2 (void)
3859e4b17023SJohn Marino {
3860e4b17023SJohn Marino #ifdef INSN_SCHEDULING
3861e4b17023SJohn Marino split_all_insns ();
3862e4b17023SJohn Marino #endif
3863e4b17023SJohn Marino return 0;
3864e4b17023SJohn Marino }
3865e4b17023SJohn Marino
3866e4b17023SJohn Marino struct rtl_opt_pass pass_split_before_sched2 =
3867e4b17023SJohn Marino {
3868e4b17023SJohn Marino {
3869e4b17023SJohn Marino RTL_PASS,
3870e4b17023SJohn Marino "split4", /* name */
3871e4b17023SJohn Marino gate_handle_split_before_sched2, /* gate */
3872e4b17023SJohn Marino rest_of_handle_split_before_sched2, /* execute */
3873e4b17023SJohn Marino NULL, /* sub */
3874e4b17023SJohn Marino NULL, /* next */
3875e4b17023SJohn Marino 0, /* static_pass_number */
3876e4b17023SJohn Marino TV_NONE, /* tv_id */
3877e4b17023SJohn Marino 0, /* properties_required */
3878e4b17023SJohn Marino 0, /* properties_provided */
3879e4b17023SJohn Marino 0, /* properties_destroyed */
3880e4b17023SJohn Marino 0, /* todo_flags_start */
3881e4b17023SJohn Marino TODO_verify_flow /* todo_flags_finish */
3882e4b17023SJohn Marino }
3883e4b17023SJohn Marino };
3884e4b17023SJohn Marino
3885e4b17023SJohn Marino /* The placement of the splitting that we do for shorten_branches
3886e4b17023SJohn Marino depends on whether regstack is used by the target or not. */
3887e4b17023SJohn Marino static bool
gate_do_final_split(void)3888e4b17023SJohn Marino gate_do_final_split (void)
3889e4b17023SJohn Marino {
3890e4b17023SJohn Marino #if defined (HAVE_ATTR_length) && !defined (STACK_REGS)
3891e4b17023SJohn Marino return 1;
3892e4b17023SJohn Marino #else
3893e4b17023SJohn Marino return 0;
3894e4b17023SJohn Marino #endif
3895e4b17023SJohn Marino }
3896e4b17023SJohn Marino
3897e4b17023SJohn Marino struct rtl_opt_pass pass_split_for_shorten_branches =
3898e4b17023SJohn Marino {
3899e4b17023SJohn Marino {
3900e4b17023SJohn Marino RTL_PASS,
3901e4b17023SJohn Marino "split5", /* name */
3902e4b17023SJohn Marino gate_do_final_split, /* gate */
3903e4b17023SJohn Marino split_all_insns_noflow, /* execute */
3904e4b17023SJohn Marino NULL, /* sub */
3905e4b17023SJohn Marino NULL, /* next */
3906e4b17023SJohn Marino 0, /* static_pass_number */
3907e4b17023SJohn Marino TV_NONE, /* tv_id */
3908e4b17023SJohn Marino 0, /* properties_required */
3909e4b17023SJohn Marino 0, /* properties_provided */
3910e4b17023SJohn Marino 0, /* properties_destroyed */
3911e4b17023SJohn Marino 0, /* todo_flags_start */
3912e4b17023SJohn Marino TODO_verify_rtl_sharing /* todo_flags_finish */
3913e4b17023SJohn Marino }
3914e4b17023SJohn Marino };
3915