118334Speter/* Subroutines used by or related to instruction recognition.
290075Sobrien   Copyright (C) 1987, 1988, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998
3169699Skan   1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
418334Speter
590075SobrienThis file is part of GCC.
618334Speter
790075SobrienGCC is free software; you can redistribute it and/or modify it under
890075Sobrienthe terms of the GNU General Public License as published by the Free
990075SobrienSoftware Foundation; either version 2, or (at your option) any later
1090075Sobrienversion.
1118334Speter
1290075SobrienGCC is distributed in the hope that it will be useful, but WITHOUT ANY
1390075SobrienWARRANTY; without even the implied warranty of MERCHANTABILITY or
1490075SobrienFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1590075Sobrienfor more details.
1618334Speter
1718334SpeterYou should have received a copy of the GNU General Public License
1890075Sobrienalong with GCC; see the file COPYING.  If not, write to the Free
19169699SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
20169699Skan02110-1301, USA.  */
2118334Speter
2218334Speter
2318334Speter#include "config.h"
2450397Sobrien#include "system.h"
25132727Skan#include "coretypes.h"
26132727Skan#include "tm.h"
2718334Speter#include "rtl.h"
2890075Sobrien#include "tm_p.h"
2918334Speter#include "insn-config.h"
3018334Speter#include "insn-attr.h"
3190075Sobrien#include "hard-reg-set.h"
3218334Speter#include "recog.h"
3318334Speter#include "regs.h"
34169699Skan#include "addresses.h"
3590075Sobrien#include "expr.h"
3690075Sobrien#include "function.h"
3718334Speter#include "flags.h"
3818334Speter#include "real.h"
3952284Sobrien#include "toplev.h"
4052284Sobrien#include "basic-block.h"
4190075Sobrien#include "output.h"
4290075Sobrien#include "reload.h"
43169699Skan#include "timevar.h"
44169699Skan#include "tree-pass.h"
4518334Speter
4618334Speter#ifndef STACK_PUSH_CODE
4718334Speter#ifdef STACK_GROWS_DOWNWARD
4818334Speter#define STACK_PUSH_CODE PRE_DEC
4918334Speter#else
5018334Speter#define STACK_PUSH_CODE PRE_INC
5118334Speter#endif
5218334Speter#endif
5318334Speter
5452284Sobrien#ifndef STACK_POP_CODE
5552284Sobrien#ifdef STACK_GROWS_DOWNWARD
5652284Sobrien#define STACK_POP_CODE POST_INC
5752284Sobrien#else
5852284Sobrien#define STACK_POP_CODE POST_DEC
5952284Sobrien#endif
6052284Sobrien#endif
6118334Speter
62132727Skanstatic void validate_replace_rtx_1 (rtx *, rtx, rtx, rtx);
63132727Skanstatic rtx *find_single_use_1 (rtx, rtx *);
64132727Skanstatic void validate_replace_src_1 (rtx *, void *);
65132727Skanstatic rtx split_insn (rtx);
6618334Speter
6718334Speter/* Nonzero means allow operands to be volatile.
6818334Speter   This should be 0 if you are generating rtl, such as if you are calling
6918334Speter   the functions in optabs.c and expmed.c (most of the time).
7018334Speter   This should be 1 if all valid insns need to be recognized,
7118334Speter   such as in regclass.c and final.c and reload.c.
7218334Speter
7318334Speter   init_recog and init_recog_no_volatile are responsible for setting this.  */
7418334Speter
7518334Speterint volatile_ok;
7618334Speter
7790075Sobrienstruct recog_data recog_data;
7852284Sobrien
7952284Sobrien/* Contains a vector of operand_alternative structures for every operand.
8052284Sobrien   Set up by preprocess_constraints.  */
8152284Sobrienstruct operand_alternative recog_op_alt[MAX_RECOG_OPERANDS][MAX_RECOG_ALTERNATIVES];
8252284Sobrien
8318334Speter/* On return from `constrain_operands', indicate which alternative
8418334Speter   was satisfied.  */
8518334Speter
8618334Speterint which_alternative;
8718334Speter
8818334Speter/* Nonzero after end of reload pass.
8918334Speter   Set to 1 or 0 by toplev.c.
9018334Speter   Controls the significance of (SUBREG (MEM)).  */
9118334Speter
9218334Speterint reload_completed;
9318334Speter
94132727Skan/* Nonzero after thread_prologue_and_epilogue_insns has run.  */
95132727Skanint epilogue_completed;
96132727Skan
9718334Speter/* Initialize data used by the function `recog'.
9818334Speter   This must be called once in the compilation of a function
9918334Speter   before any insn recognition may be done in the function.  */
10018334Speter
10118334Spetervoid
102132727Skaninit_recog_no_volatile (void)
10318334Speter{
10418334Speter  volatile_ok = 0;
10518334Speter}
10618334Speter
10718334Spetervoid
108132727Skaninit_recog (void)
10918334Speter{
11018334Speter  volatile_ok = 1;
11118334Speter}
11218334Speter
11318334Speter
11418334Speter/* Check that X is an insn-body for an `asm' with operands
11518334Speter   and that the operands mentioned in it are legitimate.  */
11618334Speter
11718334Speterint
118132727Skancheck_asm_operands (rtx x)
11918334Speter{
12052284Sobrien  int noperands;
12118334Speter  rtx *operands;
12252284Sobrien  const char **constraints;
12318334Speter  int i;
12418334Speter
12552284Sobrien  /* Post-reload, be more strict with things.  */
12652284Sobrien  if (reload_completed)
12752284Sobrien    {
12852284Sobrien      /* ??? Doh!  We've not got the wrapping insn.  Cook one up.  */
12952284Sobrien      extract_insn (make_insn_raw (x));
13052284Sobrien      constrain_operands (1);
13152284Sobrien      return which_alternative >= 0;
13252284Sobrien    }
13352284Sobrien
13452284Sobrien  noperands = asm_noperands (x);
13518334Speter  if (noperands < 0)
13618334Speter    return 0;
13718334Speter  if (noperands == 0)
13818334Speter    return 1;
13918334Speter
140132727Skan  operands = alloca (noperands * sizeof (rtx));
141132727Skan  constraints = alloca (noperands * sizeof (char *));
14218334Speter
14390075Sobrien  decode_asm_operands (x, operands, NULL, constraints, NULL);
14452284Sobrien
14518334Speter  for (i = 0; i < noperands; i++)
14652284Sobrien    {
14752284Sobrien      const char *c = constraints[i];
14852284Sobrien      if (c[0] == '%')
14952284Sobrien	c++;
15090075Sobrien      if (ISDIGIT ((unsigned char) c[0]) && c[1] == '\0')
15152284Sobrien	c = constraints[c[0] - '0'];
15218334Speter
15352284Sobrien      if (! asm_operand_ok (operands[i], c))
154117404Skan	return 0;
15552284Sobrien    }
15652284Sobrien
15718334Speter  return 1;
15818334Speter}
15918334Speter
16052284Sobrien/* Static data for the next two routines.  */
16118334Speter
16252284Sobrientypedef struct change_t
16352284Sobrien{
16452284Sobrien  rtx object;
16552284Sobrien  int old_code;
16652284Sobrien  rtx *loc;
16752284Sobrien  rtx old;
16852284Sobrien} change_t;
16918334Speter
17052284Sobrienstatic change_t *changes;
17152284Sobrienstatic int changes_allocated;
17218334Speter
17318334Speterstatic int num_changes = 0;
17418334Speter
17590075Sobrien/* Validate a proposed change to OBJECT.  LOC is the location in the rtl
17618334Speter   at which NEW will be placed.  If OBJECT is zero, no validation is done,
17718334Speter   the change is simply made.
17818334Speter
17918334Speter   Two types of objects are supported:  If OBJECT is a MEM, memory_address_p
18018334Speter   will be called with the address and mode as parameters.  If OBJECT is
18118334Speter   an INSN, CALL_INSN, or JUMP_INSN, the insn will be re-recognized with
18218334Speter   the change in place.
18318334Speter
184117404Skan   IN_GROUP is nonzero if this is part of a group of changes that must be
18518334Speter   performed as a group.  In that case, the changes will be stored.  The
18618334Speter   function `apply_change_group' will validate and apply the changes.
18718334Speter
18818334Speter   If IN_GROUP is zero, this is a single change.  Try to recognize the insn
18918334Speter   or validate the memory reference with the change applied.  If the result
19018334Speter   is not valid for the machine, suppress the change and return zero.
19118334Speter   Otherwise, perform the change and return 1.  */
19218334Speter
19318334Speterint
194132727Skanvalidate_change (rtx object, rtx *loc, rtx new, int in_group)
19518334Speter{
19618334Speter  rtx old = *loc;
19718334Speter
19818334Speter  if (old == new || rtx_equal_p (old, new))
19918334Speter    return 1;
20018334Speter
201169699Skan  gcc_assert (in_group != 0 || num_changes == 0);
20218334Speter
20318334Speter  *loc = new;
20418334Speter
20518334Speter  /* Save the information describing this change.  */
20652284Sobrien  if (num_changes >= changes_allocated)
20752284Sobrien    {
20852284Sobrien      if (changes_allocated == 0)
20952284Sobrien	/* This value allows for repeated substitutions inside complex
21052284Sobrien	   indexed addresses, or changes in up to 5 insns.  */
21152284Sobrien	changes_allocated = MAX_RECOG_OPERANDS * 5;
21252284Sobrien      else
21352284Sobrien	changes_allocated *= 2;
21418334Speter
215132727Skan      changes = xrealloc (changes, sizeof (change_t) * changes_allocated);
21652284Sobrien    }
217117404Skan
21852284Sobrien  changes[num_changes].object = object;
21952284Sobrien  changes[num_changes].loc = loc;
22052284Sobrien  changes[num_changes].old = old;
22152284Sobrien
222169699Skan  if (object && !MEM_P (object))
22318334Speter    {
22418334Speter      /* Set INSN_CODE to force rerecognition of insn.  Save old code in
22518334Speter	 case invalid.  */
22652284Sobrien      changes[num_changes].old_code = INSN_CODE (object);
22718334Speter      INSN_CODE (object) = -1;
22818334Speter    }
22918334Speter
23018334Speter  num_changes++;
23118334Speter
23218334Speter  /* If we are making a group of changes, return 1.  Otherwise, validate the
23318334Speter     change group we made.  */
23418334Speter
23518334Speter  if (in_group)
23618334Speter    return 1;
23718334Speter  else
23818334Speter    return apply_change_group ();
23918334Speter}
24018334Speter
241169699Skan
24252284Sobrien/* This subroutine of apply_change_group verifies whether the changes to INSN
24352284Sobrien   were valid; i.e. whether INSN can still be recognized.  */
24452284Sobrien
24590075Sobrienint
246132727Skaninsn_invalid_p (rtx insn)
24752284Sobrien{
24890075Sobrien  rtx pat = PATTERN (insn);
24990075Sobrien  int num_clobbers = 0;
25090075Sobrien  /* If we are before reload and the pattern is a SET, see if we can add
25190075Sobrien     clobbers.  */
25290075Sobrien  int icode = recog (pat, insn,
25390075Sobrien		     (GET_CODE (pat) == SET
25490075Sobrien		      && ! reload_completed && ! reload_in_progress)
25590075Sobrien		     ? &num_clobbers : 0);
25652284Sobrien  int is_asm = icode < 0 && asm_noperands (PATTERN (insn)) >= 0;
25752284Sobrien
258117404Skan
25990075Sobrien  /* If this is an asm and the operand aren't legal, then fail.  Likewise if
26090075Sobrien     this is not an asm and the insn wasn't recognized.  */
26190075Sobrien  if ((is_asm && ! check_asm_operands (PATTERN (insn)))
26290075Sobrien      || (!is_asm && icode < 0))
26352284Sobrien    return 1;
26452284Sobrien
26590075Sobrien  /* If we have to add CLOBBERs, fail if we have to add ones that reference
26690075Sobrien     hard registers since our callers can't know if they are live or not.
26790075Sobrien     Otherwise, add them.  */
26890075Sobrien  if (num_clobbers > 0)
26990075Sobrien    {
27090075Sobrien      rtx newpat;
27190075Sobrien
27290075Sobrien      if (added_clobbers_hard_reg_p (icode))
27390075Sobrien	return 1;
27490075Sobrien
27590075Sobrien      newpat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (num_clobbers + 1));
27690075Sobrien      XVECEXP (newpat, 0, 0) = pat;
27790075Sobrien      add_clobbers (newpat, icode);
27890075Sobrien      PATTERN (insn) = pat = newpat;
27990075Sobrien    }
28090075Sobrien
28152284Sobrien  /* After reload, verify that all constraints are satisfied.  */
28252284Sobrien  if (reload_completed)
28352284Sobrien    {
28452284Sobrien      extract_insn (insn);
28552284Sobrien
28652284Sobrien      if (! constrain_operands (1))
28752284Sobrien	return 1;
28852284Sobrien    }
28952284Sobrien
29090075Sobrien  INSN_CODE (insn) = icode;
29152284Sobrien  return 0;
29252284Sobrien}
29352284Sobrien
294117404Skan/* Return number of changes made and not validated yet.  */
295117404Skanint
296132727Skannum_changes_pending (void)
297117404Skan{
298117404Skan  return num_changes;
299117404Skan}
300117404Skan
301169699Skan/* Tentatively apply the changes numbered NUM and up.
30218334Speter   Return 1 if all changes are valid, zero otherwise.  */
30318334Speter
30418334Speterint
305169699Skanverify_changes (int num)
30618334Speter{
30718334Speter  int i;
30890075Sobrien  rtx last_validated = NULL_RTX;
30918334Speter
31018334Speter  /* The changes have been applied and all INSN_CODEs have been reset to force
31118334Speter     rerecognition.
31218334Speter
31318334Speter     The changes are valid if we aren't given an object, or if we are
31418334Speter     given a MEM and it still is a valid address, or if this is in insn
31518334Speter     and it is recognized.  In the latter case, if reload has completed,
31618334Speter     we also require that the operands meet the constraints for
31752284Sobrien     the insn.  */
31818334Speter
319169699Skan  for (i = num; i < num_changes; i++)
32018334Speter    {
32152284Sobrien      rtx object = changes[i].object;
32218334Speter
323132727Skan      /* If there is no object to test or if it is the same as the one we
32490075Sobrien         already tested, ignore it.  */
32590075Sobrien      if (object == 0 || object == last_validated)
32618334Speter	continue;
32718334Speter
328169699Skan      if (MEM_P (object))
32918334Speter	{
33018334Speter	  if (! memory_address_p (GET_MODE (object), XEXP (object, 0)))
33118334Speter	    break;
33218334Speter	}
33352284Sobrien      else if (insn_invalid_p (object))
33418334Speter	{
33518334Speter	  rtx pat = PATTERN (object);
33618334Speter
33718334Speter	  /* Perhaps we couldn't recognize the insn because there were
33818334Speter	     extra CLOBBERs at the end.  If so, try to re-recognize
33918334Speter	     without the last CLOBBER (later iterations will cause each of
34018334Speter	     them to be eliminated, in turn).  But don't do this if we
34118334Speter	     have an ASM_OPERAND.  */
34218334Speter	  if (GET_CODE (pat) == PARALLEL
34318334Speter	      && GET_CODE (XVECEXP (pat, 0, XVECLEN (pat, 0) - 1)) == CLOBBER
34418334Speter	      && asm_noperands (PATTERN (object)) < 0)
34518334Speter	    {
34690075Sobrien	      rtx newpat;
34718334Speter
34890075Sobrien	      if (XVECLEN (pat, 0) == 2)
34990075Sobrien		newpat = XVECEXP (pat, 0, 0);
35090075Sobrien	      else
35190075Sobrien		{
35290075Sobrien		  int j;
35318334Speter
35490075Sobrien		  newpat
355117404Skan		    = gen_rtx_PARALLEL (VOIDmode,
35690075Sobrien					rtvec_alloc (XVECLEN (pat, 0) - 1));
35790075Sobrien		  for (j = 0; j < XVECLEN (newpat, 0); j++)
35890075Sobrien		    XVECEXP (newpat, 0, j) = XVECEXP (pat, 0, j);
35990075Sobrien		}
36018334Speter
36190075Sobrien	      /* Add a new change to this group to replace the pattern
36290075Sobrien		 with this new pattern.  Then consider this change
36390075Sobrien		 as having succeeded.  The change we added will
36490075Sobrien		 cause the entire call to fail if things remain invalid.
36518334Speter
36690075Sobrien		 Note that this can lose if a later change than the one
36790075Sobrien		 we are processing specified &XVECEXP (PATTERN (object), 0, X)
36890075Sobrien		 but this shouldn't occur.  */
36918334Speter
37090075Sobrien	      validate_change (object, &PATTERN (object), newpat, 1);
37190075Sobrien	      continue;
37290075Sobrien	    }
37318334Speter	  else if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER)
37418334Speter	    /* If this insn is a CLOBBER or USE, it is always valid, but is
37518334Speter	       never recognized.  */
37618334Speter	    continue;
37718334Speter	  else
37818334Speter	    break;
37918334Speter	}
38090075Sobrien      last_validated = object;
38118334Speter    }
38218334Speter
383169699Skan  return (i == num_changes);
384169699Skan}
385117404Skan
386169699Skan/* A group of changes has previously been issued with validate_change and
387169699Skan   verified with verify_changes.  Update the BB_DIRTY flags of the affected
388169699Skan   blocks, and clear num_changes.  */
389117404Skan
390169699Skanvoid
391169699Skanconfirm_change_group (void)
392169699Skan{
393169699Skan  int i;
394169699Skan  basic_block bb;
395169699Skan
396169699Skan  for (i = 0; i < num_changes; i++)
397169699Skan    if (changes[i].object
398169699Skan	&& INSN_P (changes[i].object)
399169699Skan	&& (bb = BLOCK_FOR_INSN (changes[i].object)))
400169699Skan      bb->flags |= BB_DIRTY;
401169699Skan
402169699Skan  num_changes = 0;
403169699Skan}
404169699Skan
405169699Skan/* Apply a group of changes previously issued with `validate_change'.
406169699Skan   If all changes are valid, call confirm_change_group and return 1,
407169699Skan   otherwise, call cancel_changes and return 0.  */
408169699Skan
409169699Skanint
410169699Skanapply_change_group (void)
411169699Skan{
412169699Skan  if (verify_changes (0))
413169699Skan    {
414169699Skan      confirm_change_group ();
41518334Speter      return 1;
41618334Speter    }
41718334Speter  else
41818334Speter    {
41918334Speter      cancel_changes (0);
42018334Speter      return 0;
42118334Speter    }
42218334Speter}
42318334Speter
424169699Skan
42590075Sobrien/* Return the number of changes so far in the current group.  */
42618334Speter
42718334Speterint
428132727Skannum_validated_changes (void)
42918334Speter{
43018334Speter  return num_changes;
43118334Speter}
43218334Speter
43318334Speter/* Retract the changes numbered NUM and up.  */
43418334Speter
43518334Spetervoid
436132727Skancancel_changes (int num)
43718334Speter{
43818334Speter  int i;
43918334Speter
44018334Speter  /* Back out all the changes.  Do this in the opposite order in which
44118334Speter     they were made.  */
44218334Speter  for (i = num_changes - 1; i >= num; i--)
44318334Speter    {
44452284Sobrien      *changes[i].loc = changes[i].old;
445169699Skan      if (changes[i].object && !MEM_P (changes[i].object))
44652284Sobrien	INSN_CODE (changes[i].object) = changes[i].old_code;
44718334Speter    }
44818334Speter  num_changes = num;
44918334Speter}
45018334Speter
45118334Speter/* Replace every occurrence of FROM in X with TO.  Mark each change with
45218334Speter   validate_change passing OBJECT.  */
45318334Speter
45418334Speterstatic void
455132727Skanvalidate_replace_rtx_1 (rtx *loc, rtx from, rtx to, rtx object)
45618334Speter{
45790075Sobrien  int i, j;
45890075Sobrien  const char *fmt;
45990075Sobrien  rtx x = *loc;
46090075Sobrien  enum rtx_code code;
46190075Sobrien  enum machine_mode op0_mode = VOIDmode;
46290075Sobrien  int prev_changes = num_changes;
46390075Sobrien  rtx new;
46418334Speter
46590075Sobrien  if (!x)
46690075Sobrien    return;
46790075Sobrien
46890075Sobrien  code = GET_CODE (x);
46990075Sobrien  fmt = GET_RTX_FORMAT (code);
47090075Sobrien  if (fmt[0] == 'e')
47190075Sobrien    op0_mode = GET_MODE (XEXP (x, 0));
47290075Sobrien
47318334Speter  /* X matches FROM if it is the same rtx or they are both referring to the
47418334Speter     same register in the same mode.  Avoid calling rtx_equal_p unless the
47518334Speter     operands look similar.  */
47618334Speter
47718334Speter  if (x == from
478169699Skan      || (REG_P (x) && REG_P (from)
47918334Speter	  && GET_MODE (x) == GET_MODE (from)
48018334Speter	  && REGNO (x) == REGNO (from))
48118334Speter      || (GET_CODE (x) == GET_CODE (from) && GET_MODE (x) == GET_MODE (from)
48218334Speter	  && rtx_equal_p (x, from)))
48318334Speter    {
48418334Speter      validate_change (object, loc, to, 1);
48518334Speter      return;
48618334Speter    }
48718334Speter
488132727Skan  /* Call ourself recursively to perform the replacements.
489132727Skan     We must not replace inside already replaced expression, otherwise we
490132727Skan     get infinite recursion for replacements like (reg X)->(subreg (reg X))
491132727Skan     done by regmove, so we must special case shared ASM_OPERANDS.  */
49290075Sobrien
493132727Skan  if (GET_CODE (x) == PARALLEL)
49418334Speter    {
495132727Skan      for (j = XVECLEN (x, 0) - 1; j >= 0; j--)
496132727Skan	{
497132727Skan	  if (j && GET_CODE (XVECEXP (x, 0, j)) == SET
498132727Skan	      && GET_CODE (SET_SRC (XVECEXP (x, 0, j))) == ASM_OPERANDS)
499132727Skan	    {
500132727Skan	      /* Verify that operands are really shared.  */
501169699Skan	      gcc_assert (ASM_OPERANDS_INPUT_VEC (SET_SRC (XVECEXP (x, 0, 0)))
502169699Skan			  == ASM_OPERANDS_INPUT_VEC (SET_SRC (XVECEXP
503169699Skan							      (x, 0, j))));
504132727Skan	      validate_replace_rtx_1 (&SET_DEST (XVECEXP (x, 0, j)),
505132727Skan				      from, to, object);
506132727Skan	    }
507132727Skan	  else
508132727Skan	    validate_replace_rtx_1 (&XVECEXP (x, 0, j), from, to, object);
509132727Skan	}
51090075Sobrien    }
511132727Skan  else
512132727Skan    for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
513132727Skan      {
514132727Skan	if (fmt[i] == 'e')
515132727Skan	  validate_replace_rtx_1 (&XEXP (x, i), from, to, object);
516132727Skan	else if (fmt[i] == 'E')
517132727Skan	  for (j = XVECLEN (x, i) - 1; j >= 0; j--)
518132727Skan	    validate_replace_rtx_1 (&XVECEXP (x, i, j), from, to, object);
519132727Skan      }
52018334Speter
52190075Sobrien  /* If we didn't substitute, there is nothing more to do.  */
52290075Sobrien  if (num_changes == prev_changes)
52390075Sobrien    return;
52490075Sobrien
52590075Sobrien  /* Allow substituted expression to have different mode.  This is used by
52690075Sobrien     regmove to change mode of pseudo register.  */
52790075Sobrien  if (fmt[0] == 'e' && GET_MODE (XEXP (x, 0)) != VOIDmode)
52890075Sobrien    op0_mode = GET_MODE (XEXP (x, 0));
52990075Sobrien
53090075Sobrien  /* Do changes needed to keep rtx consistent.  Don't do any other
53190075Sobrien     simplifications, as it is not our job.  */
53290075Sobrien
533169699Skan  if (SWAPPABLE_OPERANDS_P (x)
53490075Sobrien      && swap_commutative_operands_p (XEXP (x, 0), XEXP (x, 1)))
53590075Sobrien    {
53690075Sobrien      validate_change (object, loc,
537169699Skan		       gen_rtx_fmt_ee (COMMUTATIVE_ARITH_P (x) ? code
53890075Sobrien				       : swap_condition (code),
53990075Sobrien				       GET_MODE (x), XEXP (x, 1),
54090075Sobrien				       XEXP (x, 0)), 1);
54190075Sobrien      x = *loc;
54290075Sobrien      code = GET_CODE (x);
54318334Speter    }
54418334Speter
54518334Speter  switch (code)
54618334Speter    {
54718334Speter    case PLUS:
54850397Sobrien      /* If we have a PLUS whose second operand is now a CONST_INT, use
549110621Skan         simplify_gen_binary to try to simplify it.
55090075Sobrien         ??? We may want later to remove this, once simplification is
55190075Sobrien         separated from this function.  */
552110621Skan      if (GET_CODE (XEXP (x, 1)) == CONST_INT && XEXP (x, 1) == to)
55390075Sobrien	validate_change (object, loc,
55490075Sobrien			 simplify_gen_binary
55590075Sobrien			 (PLUS, GET_MODE (x), XEXP (x, 0), XEXP (x, 1)), 1);
55690075Sobrien      break;
55750397Sobrien    case MINUS:
55890075Sobrien      if (GET_CODE (XEXP (x, 1)) == CONST_INT
55990075Sobrien	  || GET_CODE (XEXP (x, 1)) == CONST_DOUBLE)
56090075Sobrien	validate_change (object, loc,
56190075Sobrien			 simplify_gen_binary
56290075Sobrien			 (PLUS, GET_MODE (x), XEXP (x, 0),
56390075Sobrien			  simplify_gen_unary (NEG,
56490075Sobrien					      GET_MODE (x), XEXP (x, 1),
56590075Sobrien					      GET_MODE (x))), 1);
56650397Sobrien      break;
56718334Speter    case ZERO_EXTEND:
56818334Speter    case SIGN_EXTEND:
56990075Sobrien      if (GET_MODE (XEXP (x, 0)) == VOIDmode)
57018334Speter	{
57190075Sobrien	  new = simplify_gen_unary (code, GET_MODE (x), XEXP (x, 0),
57290075Sobrien				    op0_mode);
57390075Sobrien	  /* If any of the above failed, substitute in something that
57490075Sobrien	     we know won't be recognized.  */
57590075Sobrien	  if (!new)
57650397Sobrien	    new = gen_rtx_CLOBBER (GET_MODE (x), const0_rtx);
57718334Speter	  validate_change (object, loc, new, 1);
57818334Speter	}
57918334Speter      break;
58018334Speter    case SUBREG:
58190075Sobrien      /* All subregs possible to simplify should be simplified.  */
58290075Sobrien      new = simplify_subreg (GET_MODE (x), SUBREG_REG (x), op0_mode,
58390075Sobrien			     SUBREG_BYTE (x));
58418334Speter
58590075Sobrien      /* Subregs of VOIDmode operands are incorrect.  */
58690075Sobrien      if (!new && GET_MODE (SUBREG_REG (x)) == VOIDmode)
58790075Sobrien	new = gen_rtx_CLOBBER (GET_MODE (x), const0_rtx);
58890075Sobrien      if (new)
58990075Sobrien	validate_change (object, loc, new, 1);
59018334Speter      break;
59118334Speter    case ZERO_EXTRACT:
59218334Speter    case SIGN_EXTRACT:
59318334Speter      /* If we are replacing a register with memory, try to change the memory
59490075Sobrien         to be the mode required for memory in extract operations (this isn't
59590075Sobrien         likely to be an insertion operation; if it was, nothing bad will
59690075Sobrien         happen, we might just fail in some cases).  */
59718334Speter
598169699Skan      if (MEM_P (XEXP (x, 0))
59918334Speter	  && GET_CODE (XEXP (x, 1)) == CONST_INT
60018334Speter	  && GET_CODE (XEXP (x, 2)) == CONST_INT
60190075Sobrien	  && !mode_dependent_address_p (XEXP (XEXP (x, 0), 0))
60290075Sobrien	  && !MEM_VOLATILE_P (XEXP (x, 0)))
60318334Speter	{
60418334Speter	  enum machine_mode wanted_mode = VOIDmode;
60590075Sobrien	  enum machine_mode is_mode = GET_MODE (XEXP (x, 0));
60618334Speter	  int pos = INTVAL (XEXP (x, 2));
60718334Speter
60890075Sobrien	  if (GET_CODE (x) == ZERO_EXTRACT)
60952284Sobrien	    {
61090075Sobrien	      enum machine_mode new_mode
61190075Sobrien		= mode_for_extraction (EP_extzv, 1);
61290075Sobrien	      if (new_mode != MAX_MACHINE_MODE)
61390075Sobrien		wanted_mode = new_mode;
61452284Sobrien	    }
61590075Sobrien	  else if (GET_CODE (x) == SIGN_EXTRACT)
61652284Sobrien	    {
61790075Sobrien	      enum machine_mode new_mode
61890075Sobrien		= mode_for_extraction (EP_extv, 1);
61990075Sobrien	      if (new_mode != MAX_MACHINE_MODE)
62090075Sobrien		wanted_mode = new_mode;
62152284Sobrien	    }
62218334Speter
62318334Speter	  /* If we have a narrower mode, we can do something.  */
62418334Speter	  if (wanted_mode != VOIDmode
62518334Speter	      && GET_MODE_SIZE (wanted_mode) < GET_MODE_SIZE (is_mode))
62618334Speter	    {
62718334Speter	      int offset = pos / BITS_PER_UNIT;
62818334Speter	      rtx newmem;
62918334Speter
63090075Sobrien	      /* If the bytes and bits are counted differently, we
63190075Sobrien	         must adjust the offset.  */
63218334Speter	      if (BYTES_BIG_ENDIAN != BITS_BIG_ENDIAN)
63390075Sobrien		offset =
63490075Sobrien		  (GET_MODE_SIZE (is_mode) - GET_MODE_SIZE (wanted_mode) -
63590075Sobrien		   offset);
63618334Speter
63718334Speter	      pos %= GET_MODE_BITSIZE (wanted_mode);
63818334Speter
63990075Sobrien	      newmem = adjust_address_nv (XEXP (x, 0), wanted_mode, offset);
64018334Speter
64118334Speter	      validate_change (object, &XEXP (x, 2), GEN_INT (pos), 1);
64218334Speter	      validate_change (object, &XEXP (x, 0), newmem, 1);
64318334Speter	    }
64418334Speter	}
64518334Speter
64618334Speter      break;
64790075Sobrien
64850397Sobrien    default:
64950397Sobrien      break;
65018334Speter    }
65118334Speter}
65218334Speter
65318334Speter/* Try replacing every occurrence of FROM in INSN with TO.  After all
65418334Speter   changes have been made, validate by seeing if INSN is still valid.  */
65518334Speter
65618334Speterint
657132727Skanvalidate_replace_rtx (rtx from, rtx to, rtx insn)
65818334Speter{
65918334Speter  validate_replace_rtx_1 (&PATTERN (insn), from, to, insn);
66018334Speter  return apply_change_group ();
66118334Speter}
66250397Sobrien
66390075Sobrien/* Try replacing every occurrence of FROM in INSN with TO.  */
66452284Sobrien
66552284Sobrienvoid
666132727Skanvalidate_replace_rtx_group (rtx from, rtx to, rtx insn)
66752284Sobrien{
66852284Sobrien  validate_replace_rtx_1 (&PATTERN (insn), from, to, insn);
66952284Sobrien}
67052284Sobrien
67190075Sobrien/* Function called by note_uses to replace used subexpressions.  */
67290075Sobrienstruct validate_replace_src_data
67390075Sobrien{
67490075Sobrien  rtx from;			/* Old RTX */
67590075Sobrien  rtx to;			/* New RTX */
67690075Sobrien  rtx insn;			/* Insn in which substitution is occurring.  */
67790075Sobrien};
67890075Sobrien
67990075Sobrienstatic void
680132727Skanvalidate_replace_src_1 (rtx *x, void *data)
68190075Sobrien{
68290075Sobrien  struct validate_replace_src_data *d
68390075Sobrien    = (struct validate_replace_src_data *) data;
68490075Sobrien
68590075Sobrien  validate_replace_rtx_1 (x, d->from, d->to, d->insn);
68690075Sobrien}
68790075Sobrien
68850397Sobrien/* Try replacing every occurrence of FROM in INSN with TO, avoiding
689117404Skan   SET_DESTs.  */
69050397Sobrien
691117404Skanvoid
692132727Skanvalidate_replace_src_group (rtx from, rtx to, rtx insn)
69350397Sobrien{
69490075Sobrien  struct validate_replace_src_data d;
69550397Sobrien
69690075Sobrien  d.from = from;
69790075Sobrien  d.to = to;
69890075Sobrien  d.insn = insn;
69990075Sobrien  note_uses (&PATTERN (insn), validate_replace_src_1, &d);
700117404Skan}
701117404Skan
702169699Skan/* Try simplify INSN.
703169699Skan   Invoke simplify_rtx () on every SET_SRC and SET_DEST inside the INSN's
704169699Skan   pattern and return true if something was simplified.  */
705169699Skan
706169699Skanbool
707169699Skanvalidate_simplify_insn (rtx insn)
708117404Skan{
709169699Skan  int i;
710169699Skan  rtx pat = NULL;
711169699Skan  rtx newpat = NULL;
712169699Skan
713169699Skan  pat = PATTERN (insn);
714169699Skan
715169699Skan  if (GET_CODE (pat) == SET)
716169699Skan    {
717169699Skan      newpat = simplify_rtx (SET_SRC (pat));
718169699Skan      if (newpat && !rtx_equal_p (SET_SRC (pat), newpat))
719169699Skan	validate_change (insn, &SET_SRC (pat), newpat, 1);
720169699Skan      newpat = simplify_rtx (SET_DEST (pat));
721169699Skan      if (newpat && !rtx_equal_p (SET_DEST (pat), newpat))
722169699Skan	validate_change (insn, &SET_DEST (pat), newpat, 1);
723169699Skan    }
724169699Skan  else if (GET_CODE (pat) == PARALLEL)
725169699Skan    for (i = 0; i < XVECLEN (pat, 0); i++)
726169699Skan      {
727169699Skan	rtx s = XVECEXP (pat, 0, i);
728169699Skan
729169699Skan	if (GET_CODE (XVECEXP (pat, 0, i)) == SET)
730169699Skan	  {
731169699Skan	    newpat = simplify_rtx (SET_SRC (s));
732169699Skan	    if (newpat && !rtx_equal_p (SET_SRC (s), newpat))
733169699Skan	      validate_change (insn, &SET_SRC (s), newpat, 1);
734169699Skan	    newpat = simplify_rtx (SET_DEST (s));
735169699Skan	    if (newpat && !rtx_equal_p (SET_DEST (s), newpat))
736169699Skan	      validate_change (insn, &SET_DEST (s), newpat, 1);
737169699Skan	  }
738169699Skan      }
739169699Skan  return ((num_changes_pending () > 0) && (apply_change_group () > 0));
74050397Sobrien}
74118334Speter
74218334Speter#ifdef HAVE_cc0
74318334Speter/* Return 1 if the insn using CC0 set by INSN does not contain
74418334Speter   any ordered tests applied to the condition codes.
74518334Speter   EQ and NE tests do not count.  */
74618334Speter
74718334Speterint
748132727Skannext_insn_tests_no_inequality (rtx insn)
74918334Speter{
75090075Sobrien  rtx next = next_cc0_user (insn);
75118334Speter
75218334Speter  /* If there is no next insn, we have to take the conservative choice.  */
75318334Speter  if (next == 0)
75418334Speter    return 0;
75518334Speter
756169699Skan  return (INSN_P (next)
75718334Speter	  && ! inequality_comparisons_p (PATTERN (next)));
75818334Speter}
75918334Speter#endif
76018334Speter
76118334Speter/* This is used by find_single_use to locate an rtx that contains exactly one
76218334Speter   use of DEST, which is typically either a REG or CC0.  It returns a
76318334Speter   pointer to the innermost rtx expression containing DEST.  Appearances of
76418334Speter   DEST that are being used to totally replace it are not counted.  */
76518334Speter
76618334Speterstatic rtx *
767132727Skanfind_single_use_1 (rtx dest, rtx *loc)
76818334Speter{
76918334Speter  rtx x = *loc;
77018334Speter  enum rtx_code code = GET_CODE (x);
77118334Speter  rtx *result = 0;
77218334Speter  rtx *this_result;
77318334Speter  int i;
77490075Sobrien  const char *fmt;
77518334Speter
77618334Speter  switch (code)
77718334Speter    {
77818334Speter    case CONST_INT:
77918334Speter    case CONST:
78018334Speter    case LABEL_REF:
78118334Speter    case SYMBOL_REF:
78218334Speter    case CONST_DOUBLE:
78396263Sobrien    case CONST_VECTOR:
78418334Speter    case CLOBBER:
78518334Speter      return 0;
78618334Speter
78718334Speter    case SET:
78818334Speter      /* If the destination is anything other than CC0, PC, a REG or a SUBREG
78918334Speter	 of a REG that occupies all of the REG, the insn uses DEST if
79018334Speter	 it is mentioned in the destination or the source.  Otherwise, we
79118334Speter	 need just check the source.  */
79218334Speter      if (GET_CODE (SET_DEST (x)) != CC0
79318334Speter	  && GET_CODE (SET_DEST (x)) != PC
794169699Skan	  && !REG_P (SET_DEST (x))
79518334Speter	  && ! (GET_CODE (SET_DEST (x)) == SUBREG
796169699Skan		&& REG_P (SUBREG_REG (SET_DEST (x)))
79718334Speter		&& (((GET_MODE_SIZE (GET_MODE (SUBREG_REG (SET_DEST (x))))
79818334Speter		      + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD)
79918334Speter		    == ((GET_MODE_SIZE (GET_MODE (SET_DEST (x)))
80018334Speter			 + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD))))
80118334Speter	break;
80218334Speter
80318334Speter      return find_single_use_1 (dest, &SET_SRC (x));
80418334Speter
80518334Speter    case MEM:
80618334Speter    case SUBREG:
80718334Speter      return find_single_use_1 (dest, &XEXP (x, 0));
808117404Skan
80950397Sobrien    default:
81050397Sobrien      break;
81118334Speter    }
81218334Speter
81318334Speter  /* If it wasn't one of the common cases above, check each expression and
81418334Speter     vector of this code.  Look for a unique usage of DEST.  */
81518334Speter
81618334Speter  fmt = GET_RTX_FORMAT (code);
81718334Speter  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
81818334Speter    {
81918334Speter      if (fmt[i] == 'e')
82018334Speter	{
82118334Speter	  if (dest == XEXP (x, i)
822169699Skan	      || (REG_P (dest) && REG_P (XEXP (x, i))
82318334Speter		  && REGNO (dest) == REGNO (XEXP (x, i))))
82418334Speter	    this_result = loc;
82518334Speter	  else
82618334Speter	    this_result = find_single_use_1 (dest, &XEXP (x, i));
82718334Speter
82818334Speter	  if (result == 0)
82918334Speter	    result = this_result;
83018334Speter	  else if (this_result)
83118334Speter	    /* Duplicate usage.  */
83218334Speter	    return 0;
83318334Speter	}
83418334Speter      else if (fmt[i] == 'E')
83518334Speter	{
83618334Speter	  int j;
83718334Speter
83818334Speter	  for (j = XVECLEN (x, i) - 1; j >= 0; j--)
83918334Speter	    {
84018334Speter	      if (XVECEXP (x, i, j) == dest
841169699Skan		  || (REG_P (dest)
842169699Skan		      && REG_P (XVECEXP (x, i, j))
84318334Speter		      && REGNO (XVECEXP (x, i, j)) == REGNO (dest)))
84418334Speter		this_result = loc;
84518334Speter	      else
84618334Speter		this_result = find_single_use_1 (dest, &XVECEXP (x, i, j));
84718334Speter
84818334Speter	      if (result == 0)
84918334Speter		result = this_result;
85018334Speter	      else if (this_result)
85118334Speter		return 0;
85218334Speter	    }
85318334Speter	}
85418334Speter    }
85518334Speter
85618334Speter  return result;
85718334Speter}
85818334Speter
85918334Speter/* See if DEST, produced in INSN, is used only a single time in the
86018334Speter   sequel.  If so, return a pointer to the innermost rtx expression in which
86118334Speter   it is used.
86218334Speter
863117404Skan   If PLOC is nonzero, *PLOC is set to the insn containing the single use.
86418334Speter
86518334Speter   This routine will return usually zero either before flow is called (because
86618334Speter   there will be no LOG_LINKS notes) or after reload (because the REG_DEAD
86718334Speter   note can't be trusted).
86818334Speter
86918334Speter   If DEST is cc0_rtx, we look only at the next insn.  In that case, we don't
87018334Speter   care about REG_DEAD notes or LOG_LINKS.
87118334Speter
87218334Speter   Otherwise, we find the single use by finding an insn that has a
87318334Speter   LOG_LINKS pointing at INSN and has a REG_DEAD note for DEST.  If DEST is
87418334Speter   only referenced once in that insn, we know that it must be the first
87518334Speter   and last insn referencing DEST.  */
87618334Speter
87718334Speterrtx *
878132727Skanfind_single_use (rtx dest, rtx insn, rtx *ploc)
87918334Speter{
88018334Speter  rtx next;
88118334Speter  rtx *result;
88218334Speter  rtx link;
88318334Speter
88418334Speter#ifdef HAVE_cc0
88518334Speter  if (dest == cc0_rtx)
88618334Speter    {
88718334Speter      next = NEXT_INSN (insn);
88818334Speter      if (next == 0
889169699Skan	  || (!NONJUMP_INSN_P (next) && !JUMP_P (next)))
89018334Speter	return 0;
89118334Speter
89218334Speter      result = find_single_use_1 (dest, &PATTERN (next));
89318334Speter      if (result && ploc)
89418334Speter	*ploc = next;
89518334Speter      return result;
89618334Speter    }
89718334Speter#endif
89818334Speter
899169699Skan  if (reload_completed || reload_in_progress || !REG_P (dest))
90018334Speter    return 0;
90118334Speter
90218334Speter  for (next = next_nonnote_insn (insn);
903169699Skan       next != 0 && !LABEL_P (next);
90418334Speter       next = next_nonnote_insn (next))
90590075Sobrien    if (INSN_P (next) && dead_or_set_p (next, dest))
90618334Speter      {
90718334Speter	for (link = LOG_LINKS (next); link; link = XEXP (link, 1))
90818334Speter	  if (XEXP (link, 0) == insn)
90918334Speter	    break;
91018334Speter
91118334Speter	if (link)
91218334Speter	  {
91318334Speter	    result = find_single_use_1 (dest, &PATTERN (next));
91418334Speter	    if (ploc)
91518334Speter	      *ploc = next;
91618334Speter	    return result;
91718334Speter	  }
91818334Speter      }
91918334Speter
92018334Speter  return 0;
92118334Speter}
92218334Speter
92318334Speter/* Return 1 if OP is a valid general operand for machine mode MODE.
92418334Speter   This is either a register reference, a memory reference,
92518334Speter   or a constant.  In the case of a memory reference, the address
92618334Speter   is checked for general validity for the target machine.
92718334Speter
92818334Speter   Register and memory references must have mode MODE in order to be valid,
92918334Speter   but some constants have no machine mode and are valid for any mode.
93018334Speter
93118334Speter   If MODE is VOIDmode, OP is checked for validity for whatever mode
93218334Speter   it has.
93318334Speter
93418334Speter   The main use of this function is as a predicate in match_operand
93518334Speter   expressions in the machine description.
93618334Speter
93718334Speter   For an explanation of this function's behavior for registers of
93818334Speter   class NO_REGS, see the comment for `register_operand'.  */
93918334Speter
94018334Speterint
941132727Skangeneral_operand (rtx op, enum machine_mode mode)
94218334Speter{
94390075Sobrien  enum rtx_code code = GET_CODE (op);
94418334Speter
94518334Speter  if (mode == VOIDmode)
94618334Speter    mode = GET_MODE (op);
94718334Speter
94818334Speter  /* Don't accept CONST_INT or anything similar
94918334Speter     if the caller wants something floating.  */
95018334Speter  if (GET_MODE (op) == VOIDmode && mode != VOIDmode
95118334Speter      && GET_MODE_CLASS (mode) != MODE_INT
95218334Speter      && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT)
95318334Speter    return 0;
95418334Speter
95590075Sobrien  if (GET_CODE (op) == CONST_INT
956117404Skan      && mode != VOIDmode
95790075Sobrien      && trunc_int_for_mode (INTVAL (op), mode) != INTVAL (op))
95890075Sobrien    return 0;
95990075Sobrien
96018334Speter  if (CONSTANT_P (op))
96190075Sobrien    return ((GET_MODE (op) == VOIDmode || GET_MODE (op) == mode
96290075Sobrien	     || mode == VOIDmode)
96318334Speter	    && (! flag_pic || LEGITIMATE_PIC_OPERAND_P (op))
96418334Speter	    && LEGITIMATE_CONSTANT_P (op));
96518334Speter
96618334Speter  /* Except for certain constants with VOIDmode, already checked for,
96718334Speter     OP's mode must match MODE if MODE specifies a mode.  */
96818334Speter
96918334Speter  if (GET_MODE (op) != mode)
97018334Speter    return 0;
97118334Speter
97218334Speter  if (code == SUBREG)
97318334Speter    {
97499396Sobrien      rtx sub = SUBREG_REG (op);
97599396Sobrien
97618334Speter#ifdef INSN_SCHEDULING
97718334Speter      /* On machines that have insn scheduling, we want all memory
978169699Skan	 reference to be explicit, so outlaw paradoxical SUBREGs.
979169699Skan	 However, we must allow them after reload so that they can
980169699Skan	 get cleaned up by cleanup_subreg_operands.  */
981169699Skan      if (!reload_completed && MEM_P (sub)
98299396Sobrien	  && GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (sub)))
98318334Speter	return 0;
98418334Speter#endif
98590075Sobrien      /* Avoid memories with nonzero SUBREG_BYTE, as offsetting the memory
98690075Sobrien         may result in incorrect reference.  We should simplify all valid
98790075Sobrien         subregs of MEM anyway.  But allow this after reload because we
988117404Skan	 might be called from cleanup_subreg_operands.
98918334Speter
99090075Sobrien	 ??? This is a kludge.  */
99190075Sobrien      if (!reload_completed && SUBREG_BYTE (op) != 0
992169699Skan	  && MEM_P (sub))
993117404Skan	return 0;
99490075Sobrien
99599396Sobrien      /* FLOAT_MODE subregs can't be paradoxical.  Combine will occasionally
996132727Skan	 create such rtl, and we must reject it.  */
997169699Skan      if (SCALAR_FLOAT_MODE_P (GET_MODE (op))
99899396Sobrien	  && GET_MODE_SIZE (GET_MODE (op)) > GET_MODE_SIZE (GET_MODE (sub)))
99999396Sobrien	return 0;
100099396Sobrien
100199396Sobrien      op = sub;
100218334Speter      code = GET_CODE (op);
100318334Speter    }
100418334Speter
100518334Speter  if (code == REG)
100618334Speter    /* A register whose class is NO_REGS is not a general operand.  */
100718334Speter    return (REGNO (op) >= FIRST_PSEUDO_REGISTER
100818334Speter	    || REGNO_REG_CLASS (REGNO (op)) != NO_REGS);
100918334Speter
101018334Speter  if (code == MEM)
101118334Speter    {
101290075Sobrien      rtx y = XEXP (op, 0);
101390075Sobrien
101418334Speter      if (! volatile_ok && MEM_VOLATILE_P (op))
101518334Speter	return 0;
101690075Sobrien
1017169699Skan      /* Use the mem's mode, since it will be reloaded thus.  */
1018169699Skan      if (memory_address_p (GET_MODE (op), y))
101950397Sobrien	return 1;
102018334Speter    }
102150397Sobrien
102218334Speter  return 0;
102318334Speter}
102418334Speter
102518334Speter/* Return 1 if OP is a valid memory address for a memory reference
102618334Speter   of mode MODE.
102718334Speter
102818334Speter   The main use of this function is as a predicate in match_operand
102918334Speter   expressions in the machine description.  */
103018334Speter
103118334Speterint
1032132727Skanaddress_operand (rtx op, enum machine_mode mode)
103318334Speter{
103418334Speter  return memory_address_p (mode, op);
103518334Speter}
103618334Speter
103718334Speter/* Return 1 if OP is a register reference of mode MODE.
103818334Speter   If MODE is VOIDmode, accept a register in any mode.
103918334Speter
104018334Speter   The main use of this function is as a predicate in match_operand
104118334Speter   expressions in the machine description.
104218334Speter
104318334Speter   As a special exception, registers whose class is NO_REGS are
104418334Speter   not accepted by `register_operand'.  The reason for this change
104518334Speter   is to allow the representation of special architecture artifacts
104618334Speter   (such as a condition code register) without extending the rtl
104718334Speter   definitions.  Since registers of class NO_REGS cannot be used
104818334Speter   as registers in any case where register classes are examined,
104918334Speter   it is most consistent to keep this function from accepting them.  */
105018334Speter
105118334Speterint
1052132727Skanregister_operand (rtx op, enum machine_mode mode)
105318334Speter{
105418334Speter  if (GET_MODE (op) != mode && mode != VOIDmode)
105518334Speter    return 0;
105618334Speter
105718334Speter  if (GET_CODE (op) == SUBREG)
105818334Speter    {
105999396Sobrien      rtx sub = SUBREG_REG (op);
106099396Sobrien
106118334Speter      /* Before reload, we can allow (SUBREG (MEM...)) as a register operand
106218334Speter	 because it is guaranteed to be reloaded into one.
106318334Speter	 Just make sure the MEM is valid in itself.
106418334Speter	 (Ideally, (SUBREG (MEM)...) should not exist after reload,
106518334Speter	 but currently it does result from (SUBREG (REG)...) where the
106618334Speter	 reg went on the stack.)  */
1067169699Skan      if (! reload_completed && MEM_P (sub))
106818334Speter	return general_operand (op, mode);
106918334Speter
1070117404Skan#ifdef CANNOT_CHANGE_MODE_CLASS
1071169699Skan      if (REG_P (sub)
107299396Sobrien	  && REGNO (sub) < FIRST_PSEUDO_REGISTER
1073117404Skan	  && REG_CANNOT_CHANGE_MODE_P (REGNO (sub), GET_MODE (sub), mode)
107499396Sobrien	  && GET_MODE_CLASS (GET_MODE (sub)) != MODE_COMPLEX_INT
107599396Sobrien	  && GET_MODE_CLASS (GET_MODE (sub)) != MODE_COMPLEX_FLOAT)
107618334Speter	return 0;
107718334Speter#endif
107818334Speter
107999396Sobrien      /* FLOAT_MODE subregs can't be paradoxical.  Combine will occasionally
108099396Sobrien	 create such rtl, and we must reject it.  */
1081169699Skan      if (SCALAR_FLOAT_MODE_P (GET_MODE (op))
108299396Sobrien	  && GET_MODE_SIZE (GET_MODE (op)) > GET_MODE_SIZE (GET_MODE (sub)))
108399396Sobrien	return 0;
108499396Sobrien
108599396Sobrien      op = sub;
108618334Speter    }
108718334Speter
108818334Speter  /* We don't consider registers whose class is NO_REGS
108918334Speter     to be a register operand.  */
1090169699Skan  return (REG_P (op)
109118334Speter	  && (REGNO (op) >= FIRST_PSEUDO_REGISTER
109218334Speter	      || REGNO_REG_CLASS (REGNO (op)) != NO_REGS));
109318334Speter}
109418334Speter
109590075Sobrien/* Return 1 for a register in Pmode; ignore the tested mode.  */
109690075Sobrien
109790075Sobrienint
1098132727Skanpmode_register_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
109990075Sobrien{
110090075Sobrien  return register_operand (op, Pmode);
110190075Sobrien}
110290075Sobrien
110318334Speter/* Return 1 if OP should match a MATCH_SCRATCH, i.e., if it is a SCRATCH
110418334Speter   or a hard register.  */
110518334Speter
110618334Speterint
1107132727Skanscratch_operand (rtx op, enum machine_mode mode)
110818334Speter{
110990075Sobrien  if (GET_MODE (op) != mode && mode != VOIDmode)
111090075Sobrien    return 0;
111190075Sobrien
111290075Sobrien  return (GET_CODE (op) == SCRATCH
1113169699Skan	  || (REG_P (op)
111490075Sobrien	      && REGNO (op) < FIRST_PSEUDO_REGISTER));
111518334Speter}
111618334Speter
111718334Speter/* Return 1 if OP is a valid immediate operand for mode MODE.
111818334Speter
111918334Speter   The main use of this function is as a predicate in match_operand
112018334Speter   expressions in the machine description.  */
112118334Speter
112218334Speterint
1123132727Skanimmediate_operand (rtx op, enum machine_mode mode)
112418334Speter{
112518334Speter  /* Don't accept CONST_INT or anything similar
112618334Speter     if the caller wants something floating.  */
112718334Speter  if (GET_MODE (op) == VOIDmode && mode != VOIDmode
112818334Speter      && GET_MODE_CLASS (mode) != MODE_INT
112918334Speter      && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT)
113018334Speter    return 0;
113118334Speter
113290075Sobrien  if (GET_CODE (op) == CONST_INT
1133117404Skan      && mode != VOIDmode
113490075Sobrien      && trunc_int_for_mode (INTVAL (op), mode) != INTVAL (op))
113590075Sobrien    return 0;
113690075Sobrien
113718334Speter  return (CONSTANT_P (op)
113818334Speter	  && (GET_MODE (op) == mode || mode == VOIDmode
113918334Speter	      || GET_MODE (op) == VOIDmode)
114018334Speter	  && (! flag_pic || LEGITIMATE_PIC_OPERAND_P (op))
114118334Speter	  && LEGITIMATE_CONSTANT_P (op));
114218334Speter}
114318334Speter
114418334Speter/* Returns 1 if OP is an operand that is a CONST_INT.  */
114518334Speter
114618334Speterint
1147132727Skanconst_int_operand (rtx op, enum machine_mode mode)
114818334Speter{
114990075Sobrien  if (GET_CODE (op) != CONST_INT)
115090075Sobrien    return 0;
115190075Sobrien
115290075Sobrien  if (mode != VOIDmode
115390075Sobrien      && trunc_int_for_mode (INTVAL (op), mode) != INTVAL (op))
115490075Sobrien    return 0;
115590075Sobrien
115690075Sobrien  return 1;
115718334Speter}
115818334Speter
115918334Speter/* Returns 1 if OP is an operand that is a constant integer or constant
116018334Speter   floating-point number.  */
116118334Speter
116218334Speterint
1163132727Skanconst_double_operand (rtx op, enum machine_mode mode)
116418334Speter{
116518334Speter  /* Don't accept CONST_INT or anything similar
116618334Speter     if the caller wants something floating.  */
116718334Speter  if (GET_MODE (op) == VOIDmode && mode != VOIDmode
116818334Speter      && GET_MODE_CLASS (mode) != MODE_INT
116918334Speter      && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT)
117018334Speter    return 0;
117118334Speter
117218334Speter  return ((GET_CODE (op) == CONST_DOUBLE || GET_CODE (op) == CONST_INT)
117318334Speter	  && (mode == VOIDmode || GET_MODE (op) == mode
117418334Speter	      || GET_MODE (op) == VOIDmode));
117518334Speter}
117618334Speter
117718334Speter/* Return 1 if OP is a general operand that is not an immediate operand.  */
117818334Speter
117918334Speterint
1180132727Skannonimmediate_operand (rtx op, enum machine_mode mode)
118118334Speter{
118218334Speter  return (general_operand (op, mode) && ! CONSTANT_P (op));
118318334Speter}
118418334Speter
118518334Speter/* Return 1 if OP is a register reference or immediate value of mode MODE.  */
118618334Speter
118718334Speterint
1188132727Skannonmemory_operand (rtx op, enum machine_mode mode)
118918334Speter{
119018334Speter  if (CONSTANT_P (op))
119118334Speter    {
119218334Speter      /* Don't accept CONST_INT or anything similar
119318334Speter	 if the caller wants something floating.  */
119418334Speter      if (GET_MODE (op) == VOIDmode && mode != VOIDmode
119518334Speter	  && GET_MODE_CLASS (mode) != MODE_INT
119618334Speter	  && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT)
119718334Speter	return 0;
119818334Speter
119990075Sobrien      if (GET_CODE (op) == CONST_INT
1200117404Skan	  && mode != VOIDmode
120190075Sobrien	  && trunc_int_for_mode (INTVAL (op), mode) != INTVAL (op))
120290075Sobrien	return 0;
120390075Sobrien
120490075Sobrien      return ((GET_MODE (op) == VOIDmode || GET_MODE (op) == mode
120590075Sobrien	       || mode == VOIDmode)
120618334Speter	      && (! flag_pic || LEGITIMATE_PIC_OPERAND_P (op))
120718334Speter	      && LEGITIMATE_CONSTANT_P (op));
120818334Speter    }
120918334Speter
121018334Speter  if (GET_MODE (op) != mode && mode != VOIDmode)
121118334Speter    return 0;
121218334Speter
121318334Speter  if (GET_CODE (op) == SUBREG)
121418334Speter    {
121518334Speter      /* Before reload, we can allow (SUBREG (MEM...)) as a register operand
121618334Speter	 because it is guaranteed to be reloaded into one.
121718334Speter	 Just make sure the MEM is valid in itself.
121818334Speter	 (Ideally, (SUBREG (MEM)...) should not exist after reload,
121918334Speter	 but currently it does result from (SUBREG (REG)...) where the
122018334Speter	 reg went on the stack.)  */
1221169699Skan      if (! reload_completed && MEM_P (SUBREG_REG (op)))
122218334Speter	return general_operand (op, mode);
122318334Speter      op = SUBREG_REG (op);
122418334Speter    }
122518334Speter
122618334Speter  /* We don't consider registers whose class is NO_REGS
122718334Speter     to be a register operand.  */
1228169699Skan  return (REG_P (op)
122918334Speter	  && (REGNO (op) >= FIRST_PSEUDO_REGISTER
123018334Speter	      || REGNO_REG_CLASS (REGNO (op)) != NO_REGS));
123118334Speter}
123218334Speter
123318334Speter/* Return 1 if OP is a valid operand that stands for pushing a
123418334Speter   value of mode MODE onto the stack.
123518334Speter
123618334Speter   The main use of this function is as a predicate in match_operand
123718334Speter   expressions in the machine description.  */
123818334Speter
123918334Speterint
1240132727Skanpush_operand (rtx op, enum machine_mode mode)
124118334Speter{
124290075Sobrien  unsigned int rounded_size = GET_MODE_SIZE (mode);
124390075Sobrien
124490075Sobrien#ifdef PUSH_ROUNDING
124590075Sobrien  rounded_size = PUSH_ROUNDING (rounded_size);
124690075Sobrien#endif
124790075Sobrien
1248169699Skan  if (!MEM_P (op))
124918334Speter    return 0;
125018334Speter
125152284Sobrien  if (mode != VOIDmode && GET_MODE (op) != mode)
125218334Speter    return 0;
125318334Speter
125418334Speter  op = XEXP (op, 0);
125518334Speter
125690075Sobrien  if (rounded_size == GET_MODE_SIZE (mode))
125790075Sobrien    {
125890075Sobrien      if (GET_CODE (op) != STACK_PUSH_CODE)
125990075Sobrien	return 0;
126090075Sobrien    }
126190075Sobrien  else
126290075Sobrien    {
126390075Sobrien      if (GET_CODE (op) != PRE_MODIFY
126490075Sobrien	  || GET_CODE (XEXP (op, 1)) != PLUS
126590075Sobrien	  || XEXP (XEXP (op, 1), 0) != XEXP (op, 0)
126690075Sobrien	  || GET_CODE (XEXP (XEXP (op, 1), 1)) != CONST_INT
126790075Sobrien#ifdef STACK_GROWS_DOWNWARD
126890075Sobrien	  || INTVAL (XEXP (XEXP (op, 1), 1)) != - (int) rounded_size
126990075Sobrien#else
1270132727Skan	  || INTVAL (XEXP (XEXP (op, 1), 1)) != (int) rounded_size
127190075Sobrien#endif
127290075Sobrien	  )
127390075Sobrien	return 0;
127490075Sobrien    }
127518334Speter
127618334Speter  return XEXP (op, 0) == stack_pointer_rtx;
127718334Speter}
127818334Speter
127952284Sobrien/* Return 1 if OP is a valid operand that stands for popping a
128052284Sobrien   value of mode MODE off the stack.
128152284Sobrien
128252284Sobrien   The main use of this function is as a predicate in match_operand
128352284Sobrien   expressions in the machine description.  */
128452284Sobrien
128552284Sobrienint
1286132727Skanpop_operand (rtx op, enum machine_mode mode)
128752284Sobrien{
1288169699Skan  if (!MEM_P (op))
128952284Sobrien    return 0;
129052284Sobrien
129152284Sobrien  if (mode != VOIDmode && GET_MODE (op) != mode)
129252284Sobrien    return 0;
129352284Sobrien
129452284Sobrien  op = XEXP (op, 0);
129552284Sobrien
129652284Sobrien  if (GET_CODE (op) != STACK_POP_CODE)
129752284Sobrien    return 0;
129852284Sobrien
129952284Sobrien  return XEXP (op, 0) == stack_pointer_rtx;
130052284Sobrien}
130152284Sobrien
130218334Speter/* Return 1 if ADDR is a valid memory address for mode MODE.  */
130318334Speter
130418334Speterint
1305132727Skanmemory_address_p (enum machine_mode mode ATTRIBUTE_UNUSED, rtx addr)
130618334Speter{
130718334Speter  GO_IF_LEGITIMATE_ADDRESS (mode, addr, win);
130818334Speter  return 0;
130918334Speter
131018334Speter win:
131118334Speter  return 1;
131218334Speter}
131318334Speter
131418334Speter/* Return 1 if OP is a valid memory reference with mode MODE,
131518334Speter   including a valid address.
131618334Speter
131718334Speter   The main use of this function is as a predicate in match_operand
131818334Speter   expressions in the machine description.  */
131918334Speter
132018334Speterint
1321132727Skanmemory_operand (rtx op, enum machine_mode mode)
132218334Speter{
132318334Speter  rtx inner;
132418334Speter
132518334Speter  if (! reload_completed)
132618334Speter    /* Note that no SUBREG is a memory operand before end of reload pass,
132718334Speter       because (SUBREG (MEM...)) forces reloading into a register.  */
1328169699Skan    return MEM_P (op) && general_operand (op, mode);
132918334Speter
133018334Speter  if (mode != VOIDmode && GET_MODE (op) != mode)
133118334Speter    return 0;
133218334Speter
133318334Speter  inner = op;
133418334Speter  if (GET_CODE (inner) == SUBREG)
133518334Speter    inner = SUBREG_REG (inner);
133618334Speter
1337169699Skan  return (MEM_P (inner) && general_operand (op, mode));
133818334Speter}
133918334Speter
134018334Speter/* Return 1 if OP is a valid indirect memory reference with mode MODE;
134118334Speter   that is, a memory reference whose address is a general_operand.  */
134218334Speter
134318334Speterint
1344132727Skanindirect_operand (rtx op, enum machine_mode mode)
134518334Speter{
134618334Speter  /* Before reload, a SUBREG isn't in memory (see memory_operand, above).  */
134718334Speter  if (! reload_completed
1348169699Skan      && GET_CODE (op) == SUBREG && MEM_P (SUBREG_REG (op)))
134918334Speter    {
135090075Sobrien      int offset = SUBREG_BYTE (op);
135118334Speter      rtx inner = SUBREG_REG (op);
135218334Speter
135318334Speter      if (mode != VOIDmode && GET_MODE (op) != mode)
135418334Speter	return 0;
135518334Speter
135618334Speter      /* The only way that we can have a general_operand as the resulting
135718334Speter	 address is if OFFSET is zero and the address already is an operand
135818334Speter	 or if the address is (plus Y (const_int -OFFSET)) and Y is an
135918334Speter	 operand.  */
136018334Speter
136118334Speter      return ((offset == 0 && general_operand (XEXP (inner, 0), Pmode))
136218334Speter	      || (GET_CODE (XEXP (inner, 0)) == PLUS
136318334Speter		  && GET_CODE (XEXP (XEXP (inner, 0), 1)) == CONST_INT
136418334Speter		  && INTVAL (XEXP (XEXP (inner, 0), 1)) == -offset
136518334Speter		  && general_operand (XEXP (XEXP (inner, 0), 0), Pmode)));
136618334Speter    }
136718334Speter
1368169699Skan  return (MEM_P (op)
136918334Speter	  && memory_operand (op, mode)
137018334Speter	  && general_operand (XEXP (op, 0), Pmode));
137118334Speter}
137218334Speter
137318334Speter/* Return 1 if this is a comparison operator.  This allows the use of
137418334Speter   MATCH_OPERATOR to recognize all the branch insns.  */
137518334Speter
137618334Speterint
1377132727Skancomparison_operator (rtx op, enum machine_mode mode)
137818334Speter{
137918334Speter  return ((mode == VOIDmode || GET_MODE (op) == mode)
1380169699Skan	  && COMPARISON_P (op));
138118334Speter}
138218334Speter
138318334Speter/* If BODY is an insn body that uses ASM_OPERANDS,
138418334Speter   return the number of operands (both input and output) in the insn.
138518334Speter   Otherwise return -1.  */
138618334Speter
138718334Speterint
1388132727Skanasm_noperands (rtx body)
138918334Speter{
139090075Sobrien  switch (GET_CODE (body))
139118334Speter    {
139290075Sobrien    case ASM_OPERANDS:
139390075Sobrien      /* No output operands: return number of input operands.  */
139490075Sobrien      return ASM_OPERANDS_INPUT_LENGTH (body);
139590075Sobrien    case SET:
139690075Sobrien      if (GET_CODE (SET_SRC (body)) == ASM_OPERANDS)
139790075Sobrien	/* Single output operand: BODY is (set OUTPUT (asm_operands ...)).  */
139890075Sobrien	return ASM_OPERANDS_INPUT_LENGTH (SET_SRC (body)) + 1;
139990075Sobrien      else
140090075Sobrien	return -1;
140190075Sobrien    case PARALLEL:
140290075Sobrien      if (GET_CODE (XVECEXP (body, 0, 0)) == SET
140390075Sobrien	  && GET_CODE (SET_SRC (XVECEXP (body, 0, 0))) == ASM_OPERANDS)
140418334Speter	{
140590075Sobrien	  /* Multiple output operands, or 1 output plus some clobbers:
140690075Sobrien	     body is [(set OUTPUT (asm_operands ...))... (clobber (reg ...))...].  */
140790075Sobrien	  int i;
140890075Sobrien	  int n_sets;
140918334Speter
141090075Sobrien	  /* Count backwards through CLOBBERs to determine number of SETs.  */
141190075Sobrien	  for (i = XVECLEN (body, 0); i > 0; i--)
141290075Sobrien	    {
141390075Sobrien	      if (GET_CODE (XVECEXP (body, 0, i - 1)) == SET)
141490075Sobrien		break;
141590075Sobrien	      if (GET_CODE (XVECEXP (body, 0, i - 1)) != CLOBBER)
141690075Sobrien		return -1;
141790075Sobrien	    }
141818334Speter
141990075Sobrien	  /* N_SETS is now number of output operands.  */
142090075Sobrien	  n_sets = i;
142190075Sobrien
142290075Sobrien	  /* Verify that all the SETs we have
142390075Sobrien	     came from a single original asm_operands insn
142490075Sobrien	     (so that invalid combinations are blocked).  */
142590075Sobrien	  for (i = 0; i < n_sets; i++)
142690075Sobrien	    {
142790075Sobrien	      rtx elt = XVECEXP (body, 0, i);
142890075Sobrien	      if (GET_CODE (elt) != SET)
142990075Sobrien		return -1;
143090075Sobrien	      if (GET_CODE (SET_SRC (elt)) != ASM_OPERANDS)
143190075Sobrien		return -1;
143290075Sobrien	      /* If these ASM_OPERANDS rtx's came from different original insns
143390075Sobrien	         then they aren't allowed together.  */
143490075Sobrien	      if (ASM_OPERANDS_INPUT_VEC (SET_SRC (elt))
143590075Sobrien		  != ASM_OPERANDS_INPUT_VEC (SET_SRC (XVECEXP (body, 0, 0))))
143690075Sobrien		return -1;
143790075Sobrien	    }
143890075Sobrien	  return (ASM_OPERANDS_INPUT_LENGTH (SET_SRC (XVECEXP (body, 0, 0)))
143990075Sobrien		  + n_sets);
144090075Sobrien	}
144190075Sobrien      else if (GET_CODE (XVECEXP (body, 0, 0)) == ASM_OPERANDS)
144218334Speter	{
144390075Sobrien	  /* 0 outputs, but some clobbers:
144490075Sobrien	     body is [(asm_operands ...) (clobber (reg ...))...].  */
144590075Sobrien	  int i;
144618334Speter
144790075Sobrien	  /* Make sure all the other parallel things really are clobbers.  */
144890075Sobrien	  for (i = XVECLEN (body, 0) - 1; i > 0; i--)
144990075Sobrien	    if (GET_CODE (XVECEXP (body, 0, i)) != CLOBBER)
145090075Sobrien	      return -1;
145118334Speter
145290075Sobrien	  return ASM_OPERANDS_INPUT_LENGTH (XVECEXP (body, 0, 0));
145390075Sobrien	}
145490075Sobrien      else
145590075Sobrien	return -1;
145690075Sobrien    default:
145790075Sobrien      return -1;
145818334Speter    }
145918334Speter}
146018334Speter
146118334Speter/* Assuming BODY is an insn body that uses ASM_OPERANDS,
146218334Speter   copy its operands (both input and output) into the vector OPERANDS,
146318334Speter   the locations of the operands within the insn into the vector OPERAND_LOCS,
146418334Speter   and the constraints for the operands into CONSTRAINTS.
146518334Speter   Write the modes of the operands into MODES.
146618334Speter   Return the assembler-template.
146718334Speter
146818334Speter   If MODES, OPERAND_LOCS, CONSTRAINTS or OPERANDS is 0,
146918334Speter   we don't store that info.  */
147018334Speter
147190075Sobrienconst char *
1472132727Skandecode_asm_operands (rtx body, rtx *operands, rtx **operand_locs,
1473132727Skan		     const char **constraints, enum machine_mode *modes)
147418334Speter{
147590075Sobrien  int i;
147618334Speter  int noperands;
147790075Sobrien  const char *template = 0;
147818334Speter
147918334Speter  if (GET_CODE (body) == SET && GET_CODE (SET_SRC (body)) == ASM_OPERANDS)
148018334Speter    {
148118334Speter      rtx asmop = SET_SRC (body);
148218334Speter      /* Single output operand: BODY is (set OUTPUT (asm_operands ....)).  */
148318334Speter
148418334Speter      noperands = ASM_OPERANDS_INPUT_LENGTH (asmop) + 1;
148518334Speter
148618334Speter      for (i = 1; i < noperands; i++)
148718334Speter	{
148818334Speter	  if (operand_locs)
148918334Speter	    operand_locs[i] = &ASM_OPERANDS_INPUT (asmop, i - 1);
149018334Speter	  if (operands)
149118334Speter	    operands[i] = ASM_OPERANDS_INPUT (asmop, i - 1);
149218334Speter	  if (constraints)
149318334Speter	    constraints[i] = ASM_OPERANDS_INPUT_CONSTRAINT (asmop, i - 1);
149418334Speter	  if (modes)
149518334Speter	    modes[i] = ASM_OPERANDS_INPUT_MODE (asmop, i - 1);
149618334Speter	}
149718334Speter
149818334Speter      /* The output is in the SET.
149918334Speter	 Its constraint is in the ASM_OPERANDS itself.  */
150018334Speter      if (operands)
150118334Speter	operands[0] = SET_DEST (body);
150218334Speter      if (operand_locs)
150318334Speter	operand_locs[0] = &SET_DEST (body);
150418334Speter      if (constraints)
150518334Speter	constraints[0] = ASM_OPERANDS_OUTPUT_CONSTRAINT (asmop);
150618334Speter      if (modes)
150718334Speter	modes[0] = GET_MODE (SET_DEST (body));
150818334Speter      template = ASM_OPERANDS_TEMPLATE (asmop);
150918334Speter    }
151018334Speter  else if (GET_CODE (body) == ASM_OPERANDS)
151118334Speter    {
151218334Speter      rtx asmop = body;
151318334Speter      /* No output operands: BODY is (asm_operands ....).  */
151418334Speter
151518334Speter      noperands = ASM_OPERANDS_INPUT_LENGTH (asmop);
151618334Speter
151718334Speter      /* The input operands are found in the 1st element vector.  */
151818334Speter      /* Constraints for inputs are in the 2nd element vector.  */
151918334Speter      for (i = 0; i < noperands; i++)
152018334Speter	{
152118334Speter	  if (operand_locs)
152218334Speter	    operand_locs[i] = &ASM_OPERANDS_INPUT (asmop, i);
152318334Speter	  if (operands)
152418334Speter	    operands[i] = ASM_OPERANDS_INPUT (asmop, i);
152518334Speter	  if (constraints)
152618334Speter	    constraints[i] = ASM_OPERANDS_INPUT_CONSTRAINT (asmop, i);
152718334Speter	  if (modes)
152818334Speter	    modes[i] = ASM_OPERANDS_INPUT_MODE (asmop, i);
152918334Speter	}
153018334Speter      template = ASM_OPERANDS_TEMPLATE (asmop);
153118334Speter    }
153218334Speter  else if (GET_CODE (body) == PARALLEL
153390075Sobrien	   && GET_CODE (XVECEXP (body, 0, 0)) == SET
153490075Sobrien	   && GET_CODE (SET_SRC (XVECEXP (body, 0, 0))) == ASM_OPERANDS)
153518334Speter    {
153618334Speter      rtx asmop = SET_SRC (XVECEXP (body, 0, 0));
153718334Speter      int nparallel = XVECLEN (body, 0); /* Includes CLOBBERs.  */
153818334Speter      int nin = ASM_OPERANDS_INPUT_LENGTH (asmop);
153918334Speter      int nout = 0;		/* Does not include CLOBBERs.  */
154018334Speter
154118334Speter      /* At least one output, plus some CLOBBERs.  */
154218334Speter
154318334Speter      /* The outputs are in the SETs.
154418334Speter	 Their constraints are in the ASM_OPERANDS itself.  */
154518334Speter      for (i = 0; i < nparallel; i++)
154618334Speter	{
154718334Speter	  if (GET_CODE (XVECEXP (body, 0, i)) == CLOBBER)
154818334Speter	    break;		/* Past last SET */
1549117404Skan
155018334Speter	  if (operands)
155118334Speter	    operands[i] = SET_DEST (XVECEXP (body, 0, i));
155218334Speter	  if (operand_locs)
155318334Speter	    operand_locs[i] = &SET_DEST (XVECEXP (body, 0, i));
155418334Speter	  if (constraints)
155518334Speter	    constraints[i] = XSTR (SET_SRC (XVECEXP (body, 0, i)), 1);
155618334Speter	  if (modes)
155718334Speter	    modes[i] = GET_MODE (SET_DEST (XVECEXP (body, 0, i)));
155818334Speter	  nout++;
155918334Speter	}
156018334Speter
156118334Speter      for (i = 0; i < nin; i++)
156218334Speter	{
156318334Speter	  if (operand_locs)
156418334Speter	    operand_locs[i + nout] = &ASM_OPERANDS_INPUT (asmop, i);
156518334Speter	  if (operands)
156618334Speter	    operands[i + nout] = ASM_OPERANDS_INPUT (asmop, i);
156718334Speter	  if (constraints)
156818334Speter	    constraints[i + nout] = ASM_OPERANDS_INPUT_CONSTRAINT (asmop, i);
156918334Speter	  if (modes)
157018334Speter	    modes[i + nout] = ASM_OPERANDS_INPUT_MODE (asmop, i);
157118334Speter	}
157218334Speter
157318334Speter      template = ASM_OPERANDS_TEMPLATE (asmop);
157418334Speter    }
157518334Speter  else if (GET_CODE (body) == PARALLEL
157618334Speter	   && GET_CODE (XVECEXP (body, 0, 0)) == ASM_OPERANDS)
157718334Speter    {
157818334Speter      /* No outputs, but some CLOBBERs.  */
157918334Speter
158018334Speter      rtx asmop = XVECEXP (body, 0, 0);
158118334Speter      int nin = ASM_OPERANDS_INPUT_LENGTH (asmop);
158218334Speter
158318334Speter      for (i = 0; i < nin; i++)
158418334Speter	{
158518334Speter	  if (operand_locs)
158618334Speter	    operand_locs[i] = &ASM_OPERANDS_INPUT (asmop, i);
158718334Speter	  if (operands)
158818334Speter	    operands[i] = ASM_OPERANDS_INPUT (asmop, i);
158918334Speter	  if (constraints)
159018334Speter	    constraints[i] = ASM_OPERANDS_INPUT_CONSTRAINT (asmop, i);
159118334Speter	  if (modes)
159218334Speter	    modes[i] = ASM_OPERANDS_INPUT_MODE (asmop, i);
159318334Speter	}
159418334Speter
159518334Speter      template = ASM_OPERANDS_TEMPLATE (asmop);
159618334Speter    }
159718334Speter
159818334Speter  return template;
159918334Speter}
160052284Sobrien
1601169699Skan/* Check if an asm_operand matches its constraints.
160252284Sobrien   Return > 0 if ok, = 0 if bad, < 0 if inconclusive.  */
160352284Sobrien
160452284Sobrienint
1605132727Skanasm_operand_ok (rtx op, const char *constraint)
160652284Sobrien{
160752284Sobrien  int result = 0;
160852284Sobrien
160952284Sobrien  /* Use constrain_operands after reload.  */
1610169699Skan  gcc_assert (!reload_completed);
161152284Sobrien
161252284Sobrien  while (*constraint)
161352284Sobrien    {
1614132727Skan      char c = *constraint;
1615132727Skan      int len;
161690075Sobrien      switch (c)
161752284Sobrien	{
1618132727Skan	case ',':
1619132727Skan	  constraint++;
1620132727Skan	  continue;
162152284Sobrien	case '=':
162252284Sobrien	case '+':
162352284Sobrien	case '*':
162452284Sobrien	case '%':
162552284Sobrien	case '!':
162652284Sobrien	case '#':
162752284Sobrien	case '&':
1628132727Skan	case '?':
162952284Sobrien	  break;
163052284Sobrien
163152284Sobrien	case '0': case '1': case '2': case '3': case '4':
163252284Sobrien	case '5': case '6': case '7': case '8': case '9':
163352284Sobrien	  /* For best results, our caller should have given us the
163452284Sobrien	     proper matching constraint, but we can't actually fail
163552284Sobrien	     the check if they didn't.  Indicate that results are
163652284Sobrien	     inconclusive.  */
1637132727Skan	  do
163890075Sobrien	    constraint++;
1639132727Skan	  while (ISDIGIT (*constraint));
1640132727Skan	  if (! result)
1641132727Skan	    result = -1;
1642132727Skan	  continue;
164352284Sobrien
164452284Sobrien	case 'p':
164552284Sobrien	  if (address_operand (op, VOIDmode))
1646132727Skan	    result = 1;
164752284Sobrien	  break;
164852284Sobrien
164952284Sobrien	case 'm':
165052284Sobrien	case 'V': /* non-offsettable */
165152284Sobrien	  if (memory_operand (op, VOIDmode))
1652132727Skan	    result = 1;
165352284Sobrien	  break;
165452284Sobrien
165552284Sobrien	case 'o': /* offsettable */
165652284Sobrien	  if (offsettable_nonstrict_memref_p (op))
1657132727Skan	    result = 1;
165852284Sobrien	  break;
165952284Sobrien
166052284Sobrien	case '<':
166152284Sobrien	  /* ??? Before flow, auto inc/dec insns are not supposed to exist,
166252284Sobrien	     excepting those that expand_call created.  Further, on some
166352284Sobrien	     machines which do not have generalized auto inc/dec, an inc/dec
166452284Sobrien	     is not a memory_operand.
166552284Sobrien
166652284Sobrien	     Match any memory and hope things are resolved after reload.  */
166752284Sobrien
1668169699Skan	  if (MEM_P (op)
166952284Sobrien	      && (1
167052284Sobrien		  || GET_CODE (XEXP (op, 0)) == PRE_DEC
1671117404Skan		  || GET_CODE (XEXP (op, 0)) == POST_DEC))
1672132727Skan	    result = 1;
167352284Sobrien	  break;
167452284Sobrien
167552284Sobrien	case '>':
1676169699Skan	  if (MEM_P (op)
167752284Sobrien	      && (1
167852284Sobrien		  || GET_CODE (XEXP (op, 0)) == PRE_INC
1679117404Skan		  || GET_CODE (XEXP (op, 0)) == POST_INC))
1680132727Skan	    result = 1;
168152284Sobrien	  break;
168252284Sobrien
168352284Sobrien	case 'E':
168452284Sobrien	case 'F':
1685117404Skan	  if (GET_CODE (op) == CONST_DOUBLE
1686117404Skan	      || (GET_CODE (op) == CONST_VECTOR
1687117404Skan		  && GET_MODE_CLASS (GET_MODE (op)) == MODE_VECTOR_FLOAT))
1688132727Skan	    result = 1;
168952284Sobrien	  break;
169052284Sobrien
169152284Sobrien	case 'G':
169252284Sobrien	  if (GET_CODE (op) == CONST_DOUBLE
1693132727Skan	      && CONST_DOUBLE_OK_FOR_CONSTRAINT_P (op, 'G', constraint))
1694132727Skan	    result = 1;
169552284Sobrien	  break;
169652284Sobrien	case 'H':
169752284Sobrien	  if (GET_CODE (op) == CONST_DOUBLE
1698132727Skan	      && CONST_DOUBLE_OK_FOR_CONSTRAINT_P (op, 'H', constraint))
1699132727Skan	    result = 1;
170052284Sobrien	  break;
170152284Sobrien
170252284Sobrien	case 's':
170352284Sobrien	  if (GET_CODE (op) == CONST_INT
170452284Sobrien	      || (GET_CODE (op) == CONST_DOUBLE
170552284Sobrien		  && GET_MODE (op) == VOIDmode))
170652284Sobrien	    break;
1707132727Skan	  /* Fall through.  */
170852284Sobrien
170952284Sobrien	case 'i':
1710169699Skan	  if (CONSTANT_P (op) && (! flag_pic || LEGITIMATE_PIC_OPERAND_P (op)))
1711132727Skan	    result = 1;
171252284Sobrien	  break;
171352284Sobrien
171452284Sobrien	case 'n':
171552284Sobrien	  if (GET_CODE (op) == CONST_INT
171652284Sobrien	      || (GET_CODE (op) == CONST_DOUBLE
171752284Sobrien		  && GET_MODE (op) == VOIDmode))
1718132727Skan	    result = 1;
171952284Sobrien	  break;
172052284Sobrien
172152284Sobrien	case 'I':
172252284Sobrien	  if (GET_CODE (op) == CONST_INT
1723132727Skan	      && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'I', constraint))
1724132727Skan	    result = 1;
172552284Sobrien	  break;
172652284Sobrien	case 'J':
172752284Sobrien	  if (GET_CODE (op) == CONST_INT
1728132727Skan	      && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'J', constraint))
1729132727Skan	    result = 1;
173052284Sobrien	  break;
173152284Sobrien	case 'K':
173252284Sobrien	  if (GET_CODE (op) == CONST_INT
1733132727Skan	      && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'K', constraint))
1734132727Skan	    result = 1;
173552284Sobrien	  break;
173652284Sobrien	case 'L':
173752284Sobrien	  if (GET_CODE (op) == CONST_INT
1738132727Skan	      && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'L', constraint))
1739132727Skan	    result = 1;
174052284Sobrien	  break;
174152284Sobrien	case 'M':
174252284Sobrien	  if (GET_CODE (op) == CONST_INT
1743132727Skan	      && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'M', constraint))
1744132727Skan	    result = 1;
174552284Sobrien	  break;
174652284Sobrien	case 'N':
174752284Sobrien	  if (GET_CODE (op) == CONST_INT
1748132727Skan	      && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'N', constraint))
1749132727Skan	    result = 1;
175052284Sobrien	  break;
175152284Sobrien	case 'O':
175252284Sobrien	  if (GET_CODE (op) == CONST_INT
1753132727Skan	      && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'O', constraint))
1754132727Skan	    result = 1;
175552284Sobrien	  break;
175652284Sobrien	case 'P':
175752284Sobrien	  if (GET_CODE (op) == CONST_INT
1758132727Skan	      && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'P', constraint))
1759132727Skan	    result = 1;
176052284Sobrien	  break;
176152284Sobrien
176252284Sobrien	case 'X':
1763132727Skan	  result = 1;
1764132727Skan	  break;
176552284Sobrien
176652284Sobrien	case 'g':
176752284Sobrien	  if (general_operand (op, VOIDmode))
1768132727Skan	    result = 1;
176952284Sobrien	  break;
177052284Sobrien
177190075Sobrien	default:
177290075Sobrien	  /* For all other letters, we first check for a register class,
177390075Sobrien	     otherwise it is an EXTRA_CONSTRAINT.  */
1774132727Skan	  if (REG_CLASS_FROM_CONSTRAINT (c, constraint) != NO_REGS)
177590075Sobrien	    {
177690075Sobrien	    case 'r':
177790075Sobrien	      if (GET_MODE (op) == BLKmode)
177890075Sobrien		break;
177990075Sobrien	      if (register_operand (op, VOIDmode))
1780132727Skan		result = 1;
178190075Sobrien	    }
1782132727Skan#ifdef EXTRA_CONSTRAINT_STR
1783132727Skan	  else if (EXTRA_CONSTRAINT_STR (op, c, constraint))
1784132727Skan	    result = 1;
1785132727Skan	  else if (EXTRA_MEMORY_CONSTRAINT (c, constraint)
1786132727Skan		   /* Every memory operand can be reloaded to fit.  */
1787132727Skan		   && memory_operand (op, VOIDmode))
1788132727Skan	    result = 1;
1789132727Skan	  else if (EXTRA_ADDRESS_CONSTRAINT (c, constraint)
1790132727Skan		   /* Every address operand can be reloaded to fit.  */
1791132727Skan		   && address_operand (op, VOIDmode))
1792132727Skan	    result = 1;
179352284Sobrien#endif
179452284Sobrien	  break;
179552284Sobrien	}
1796132727Skan      len = CONSTRAINT_LEN (c, constraint);
1797132727Skan      do
1798132727Skan	constraint++;
1799132727Skan      while (--len && *constraint);
1800132727Skan      if (len)
1801132727Skan	return 0;
180252284Sobrien    }
180352284Sobrien
180452284Sobrien  return result;
180552284Sobrien}
180618334Speter
180718334Speter/* Given an rtx *P, if it is a sum containing an integer constant term,
180818334Speter   return the location (type rtx *) of the pointer to that constant term.
180918334Speter   Otherwise, return a null pointer.  */
181018334Speter
181190075Sobrienrtx *
1812132727Skanfind_constant_term_loc (rtx *p)
181318334Speter{
181490075Sobrien  rtx *tem;
181590075Sobrien  enum rtx_code code = GET_CODE (*p);
181618334Speter
181718334Speter  /* If *P IS such a constant term, P is its location.  */
181818334Speter
181918334Speter  if (code == CONST_INT || code == SYMBOL_REF || code == LABEL_REF
182018334Speter      || code == CONST)
182118334Speter    return p;
182218334Speter
182318334Speter  /* Otherwise, if not a sum, it has no constant term.  */
182418334Speter
182518334Speter  if (GET_CODE (*p) != PLUS)
182618334Speter    return 0;
182718334Speter
182818334Speter  /* If one of the summands is constant, return its location.  */
182918334Speter
183018334Speter  if (XEXP (*p, 0) && CONSTANT_P (XEXP (*p, 0))
183118334Speter      && XEXP (*p, 1) && CONSTANT_P (XEXP (*p, 1)))
183218334Speter    return p;
183318334Speter
183418334Speter  /* Otherwise, check each summand for containing a constant term.  */
183518334Speter
183618334Speter  if (XEXP (*p, 0) != 0)
183718334Speter    {
183818334Speter      tem = find_constant_term_loc (&XEXP (*p, 0));
183918334Speter      if (tem != 0)
184018334Speter	return tem;
184118334Speter    }
184218334Speter
184318334Speter  if (XEXP (*p, 1) != 0)
184418334Speter    {
184518334Speter      tem = find_constant_term_loc (&XEXP (*p, 1));
184618334Speter      if (tem != 0)
184718334Speter	return tem;
184818334Speter    }
184918334Speter
185018334Speter  return 0;
185118334Speter}
185218334Speter
185318334Speter/* Return 1 if OP is a memory reference
185418334Speter   whose address contains no side effects
185518334Speter   and remains valid after the addition
185618334Speter   of a positive integer less than the
185718334Speter   size of the object being referenced.
185818334Speter
185918334Speter   We assume that the original address is valid and do not check it.
186018334Speter
186118334Speter   This uses strict_memory_address_p as a subroutine, so
186218334Speter   don't use it before reload.  */
186318334Speter
186418334Speterint
1865132727Skanoffsettable_memref_p (rtx op)
186618334Speter{
1867169699Skan  return ((MEM_P (op))
186818334Speter	  && offsettable_address_p (1, GET_MODE (op), XEXP (op, 0)));
186918334Speter}
187018334Speter
187118334Speter/* Similar, but don't require a strictly valid mem ref:
187218334Speter   consider pseudo-regs valid as index or base regs.  */
187318334Speter
187418334Speterint
1875132727Skanoffsettable_nonstrict_memref_p (rtx op)
187618334Speter{
1877169699Skan  return ((MEM_P (op))
187818334Speter	  && offsettable_address_p (0, GET_MODE (op), XEXP (op, 0)));
187918334Speter}
188018334Speter
188118334Speter/* Return 1 if Y is a memory address which contains no side effects
188218334Speter   and would remain valid after the addition of a positive integer
188318334Speter   less than the size of that mode.
188418334Speter
188518334Speter   We assume that the original address is valid and do not check it.
188618334Speter   We do check that it is valid for narrower modes.
188718334Speter
188818334Speter   If STRICTP is nonzero, we require a strictly valid address,
188918334Speter   for the sake of use in reload.c.  */
189018334Speter
189118334Speterint
1892132727Skanoffsettable_address_p (int strictp, enum machine_mode mode, rtx y)
189318334Speter{
189490075Sobrien  enum rtx_code ycode = GET_CODE (y);
189590075Sobrien  rtx z;
189618334Speter  rtx y1 = y;
189718334Speter  rtx *y2;
1898132727Skan  int (*addressp) (enum machine_mode, rtx) =
189990075Sobrien    (strictp ? strict_memory_address_p : memory_address_p);
190090075Sobrien  unsigned int mode_sz = GET_MODE_SIZE (mode);
190118334Speter
190218334Speter  if (CONSTANT_ADDRESS_P (y))
190318334Speter    return 1;
190418334Speter
190518334Speter  /* Adjusting an offsettable address involves changing to a narrower mode.
190618334Speter     Make sure that's OK.  */
190718334Speter
190818334Speter  if (mode_dependent_address_p (y))
190918334Speter    return 0;
191018334Speter
191190075Sobrien  /* ??? How much offset does an offsettable BLKmode reference need?
191290075Sobrien     Clearly that depends on the situation in which it's being used.
191390075Sobrien     However, the current situation in which we test 0xffffffff is
191490075Sobrien     less than ideal.  Caveat user.  */
191590075Sobrien  if (mode_sz == 0)
191690075Sobrien    mode_sz = BIGGEST_ALIGNMENT / BITS_PER_UNIT;
191790075Sobrien
191818334Speter  /* If the expression contains a constant term,
191918334Speter     see if it remains valid when max possible offset is added.  */
192018334Speter
192118334Speter  if ((ycode == PLUS) && (y2 = find_constant_term_loc (&y1)))
192218334Speter    {
192318334Speter      int good;
192418334Speter
192518334Speter      y1 = *y2;
192690075Sobrien      *y2 = plus_constant (*y2, mode_sz - 1);
192718334Speter      /* Use QImode because an odd displacement may be automatically invalid
192818334Speter	 for any wider mode.  But it should be valid for a single byte.  */
192918334Speter      good = (*addressp) (QImode, y);
193018334Speter
193118334Speter      /* In any case, restore old contents of memory.  */
193218334Speter      *y2 = y1;
193318334Speter      return good;
193418334Speter    }
193518334Speter
1936169699Skan  if (GET_RTX_CLASS (ycode) == RTX_AUTOINC)
193718334Speter    return 0;
193818334Speter
193918334Speter  /* The offset added here is chosen as the maximum offset that
194018334Speter     any instruction could need to add when operating on something
194118334Speter     of the specified mode.  We assume that if Y and Y+c are
194290075Sobrien     valid addresses then so is Y+d for all 0<d<c.  adjust_address will
194390075Sobrien     go inside a LO_SUM here, so we do so as well.  */
194496263Sobrien  if (GET_CODE (y) == LO_SUM
194596263Sobrien      && mode != BLKmode
194696263Sobrien      && mode_sz <= GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT)
194790075Sobrien    z = gen_rtx_LO_SUM (GET_MODE (y), XEXP (y, 0),
194890075Sobrien			plus_constant (XEXP (y, 1), mode_sz - 1));
194990075Sobrien  else
195090075Sobrien    z = plus_constant (y, mode_sz - 1);
195118334Speter
195218334Speter  /* Use QImode because an odd displacement may be automatically invalid
195318334Speter     for any wider mode.  But it should be valid for a single byte.  */
195418334Speter  return (*addressp) (QImode, z);
195518334Speter}
195618334Speter
195718334Speter/* Return 1 if ADDR is an address-expression whose effect depends
195818334Speter   on the mode of the memory reference it is used in.
195918334Speter
196018334Speter   Autoincrement addressing is a typical example of mode-dependence
196118334Speter   because the amount of the increment depends on the mode.  */
196218334Speter
196318334Speterint
1964132727Skanmode_dependent_address_p (rtx addr ATTRIBUTE_UNUSED /* Maybe used in GO_IF_MODE_DEPENDENT_ADDRESS.  */)
196518334Speter{
196618334Speter  GO_IF_MODE_DEPENDENT_ADDRESS (addr, win);
196718334Speter  return 0;
196890075Sobrien  /* Label `win' might (not) be used via GO_IF_MODE_DEPENDENT_ADDRESS.  */
196952284Sobrien win: ATTRIBUTE_UNUSED_LABEL
197018334Speter  return 1;
197118334Speter}
197290075Sobrien
197390075Sobrien/* Like extract_insn, but save insn extracted and don't extract again, when
197490075Sobrien   called again for the same insn expecting that recog_data still contain the
197590075Sobrien   valid information.  This is used primary by gen_attr infrastructure that
197690075Sobrien   often does extract insn again and again.  */
197790075Sobrienvoid
1978132727Skanextract_insn_cached (rtx insn)
197918334Speter{
198090075Sobrien  if (recog_data.insn == insn && INSN_CODE (insn) >= 0)
198190075Sobrien    return;
198290075Sobrien  extract_insn (insn);
198390075Sobrien  recog_data.insn = insn;
198418334Speter}
1985169699Skan
1986132727Skan/* Do cached extract_insn, constrain_operands and complain about failures.
198790075Sobrien   Used by insn_attrtab.  */
198890075Sobrienvoid
1989132727Skanextract_constrain_insn_cached (rtx insn)
199090075Sobrien{
199190075Sobrien  extract_insn_cached (insn);
199290075Sobrien  if (which_alternative == -1
199390075Sobrien      && !constrain_operands (reload_completed))
199490075Sobrien    fatal_insn_not_found (insn);
199590075Sobrien}
1996169699Skan
1997132727Skan/* Do cached constrain_operands and complain about failures.  */
199890075Sobrienint
1999132727Skanconstrain_operands_cached (int strict)
200090075Sobrien{
200190075Sobrien  if (which_alternative == -1)
200290075Sobrien    return constrain_operands (strict);
200390075Sobrien  else
200490075Sobrien    return 1;
200590075Sobrien}
200618334Speter
200790075Sobrien/* Analyze INSN and fill in recog_data.  */
200890075Sobrien
200952284Sobrienvoid
2010132727Skanextract_insn (rtx insn)
201152284Sobrien{
201252284Sobrien  int i;
201352284Sobrien  int icode;
201452284Sobrien  int noperands;
201552284Sobrien  rtx body = PATTERN (insn);
201652284Sobrien
201790075Sobrien  recog_data.insn = NULL;
201890075Sobrien  recog_data.n_operands = 0;
201990075Sobrien  recog_data.n_alternatives = 0;
202090075Sobrien  recog_data.n_dups = 0;
202190075Sobrien  which_alternative = -1;
202252284Sobrien
202352284Sobrien  switch (GET_CODE (body))
202452284Sobrien    {
202552284Sobrien    case USE:
202652284Sobrien    case CLOBBER:
202752284Sobrien    case ASM_INPUT:
202852284Sobrien    case ADDR_VEC:
202952284Sobrien    case ADDR_DIFF_VEC:
203052284Sobrien      return;
203152284Sobrien
203252284Sobrien    case SET:
203390075Sobrien      if (GET_CODE (SET_SRC (body)) == ASM_OPERANDS)
203490075Sobrien	goto asm_insn;
203590075Sobrien      else
203690075Sobrien	goto normal_insn;
203752284Sobrien    case PARALLEL:
203890075Sobrien      if ((GET_CODE (XVECEXP (body, 0, 0)) == SET
203990075Sobrien	   && GET_CODE (SET_SRC (XVECEXP (body, 0, 0))) == ASM_OPERANDS)
204090075Sobrien	  || GET_CODE (XVECEXP (body, 0, 0)) == ASM_OPERANDS)
204190075Sobrien	goto asm_insn;
204290075Sobrien      else
204390075Sobrien	goto normal_insn;
204452284Sobrien    case ASM_OPERANDS:
204590075Sobrien    asm_insn:
204690075Sobrien      recog_data.n_operands = noperands = asm_noperands (body);
204752284Sobrien      if (noperands >= 0)
204852284Sobrien	{
204952284Sobrien	  /* This insn is an `asm' with operands.  */
205052284Sobrien
205152284Sobrien	  /* expand_asm_operands makes sure there aren't too many operands.  */
2052169699Skan	  gcc_assert (noperands <= MAX_RECOG_OPERANDS);
205352284Sobrien
205452284Sobrien	  /* Now get the operand values and constraints out of the insn.  */
205590075Sobrien	  decode_asm_operands (body, recog_data.operand,
205690075Sobrien			       recog_data.operand_loc,
205790075Sobrien			       recog_data.constraints,
205890075Sobrien			       recog_data.operand_mode);
205952284Sobrien	  if (noperands > 0)
206052284Sobrien	    {
206190075Sobrien	      const char *p =  recog_data.constraints[0];
206290075Sobrien	      recog_data.n_alternatives = 1;
206352284Sobrien	      while (*p)
206490075Sobrien		recog_data.n_alternatives += (*p++ == ',');
206552284Sobrien	    }
206652284Sobrien	  break;
206752284Sobrien	}
206890075Sobrien      fatal_insn_not_found (insn);
206952284Sobrien
207052284Sobrien    default:
207190075Sobrien    normal_insn:
207252284Sobrien      /* Ordinary insn: recognize it, get the operands via insn_extract
207352284Sobrien	 and get the constraints.  */
207452284Sobrien
207552284Sobrien      icode = recog_memoized (insn);
207652284Sobrien      if (icode < 0)
207752284Sobrien	fatal_insn_not_found (insn);
207852284Sobrien
207990075Sobrien      recog_data.n_operands = noperands = insn_data[icode].n_operands;
208090075Sobrien      recog_data.n_alternatives = insn_data[icode].n_alternatives;
208190075Sobrien      recog_data.n_dups = insn_data[icode].n_dups;
208252284Sobrien
208352284Sobrien      insn_extract (insn);
208452284Sobrien
208552284Sobrien      for (i = 0; i < noperands; i++)
208652284Sobrien	{
208790075Sobrien	  recog_data.constraints[i] = insn_data[icode].operand[i].constraint;
208890075Sobrien	  recog_data.operand_mode[i] = insn_data[icode].operand[i].mode;
208990075Sobrien	  /* VOIDmode match_operands gets mode from their real operand.  */
209090075Sobrien	  if (recog_data.operand_mode[i] == VOIDmode)
209190075Sobrien	    recog_data.operand_mode[i] = GET_MODE (recog_data.operand[i]);
209252284Sobrien	}
209352284Sobrien    }
209452284Sobrien  for (i = 0; i < noperands; i++)
209590075Sobrien    recog_data.operand_type[i]
209690075Sobrien      = (recog_data.constraints[i][0] == '=' ? OP_OUT
209790075Sobrien	 : recog_data.constraints[i][0] == '+' ? OP_INOUT
209890075Sobrien	 : OP_IN);
209918334Speter
2100169699Skan  gcc_assert (recog_data.n_alternatives <= MAX_RECOG_ALTERNATIVES);
210152284Sobrien}
210252284Sobrien
210352284Sobrien/* After calling extract_insn, you can use this function to extract some
210452284Sobrien   information from the constraint strings into a more usable form.
210552284Sobrien   The collected data is stored in recog_op_alt.  */
210652284Sobrienvoid
2107132727Skanpreprocess_constraints (void)
210852284Sobrien{
210952284Sobrien  int i;
211052284Sobrien
211190075Sobrien  for (i = 0; i < recog_data.n_operands; i++)
2112132727Skan    memset (recog_op_alt[i], 0, (recog_data.n_alternatives
2113132727Skan				 * sizeof (struct operand_alternative)));
2114132727Skan
2115132727Skan  for (i = 0; i < recog_data.n_operands; i++)
211652284Sobrien    {
211752284Sobrien      int j;
211852284Sobrien      struct operand_alternative *op_alt;
211990075Sobrien      const char *p = recog_data.constraints[i];
212052284Sobrien
212152284Sobrien      op_alt = recog_op_alt[i];
212252284Sobrien
212390075Sobrien      for (j = 0; j < recog_data.n_alternatives; j++)
212452284Sobrien	{
2125169699Skan	  op_alt[j].cl = NO_REGS;
212652284Sobrien	  op_alt[j].constraint = p;
212752284Sobrien	  op_alt[j].matches = -1;
212852284Sobrien	  op_alt[j].matched = -1;
212952284Sobrien
213052284Sobrien	  if (*p == '\0' || *p == ',')
213152284Sobrien	    {
213252284Sobrien	      op_alt[j].anything_ok = 1;
213352284Sobrien	      continue;
213452284Sobrien	    }
213552284Sobrien
213652284Sobrien	  for (;;)
213752284Sobrien	    {
2138132727Skan	      char c = *p;
213952284Sobrien	      if (c == '#')
214052284Sobrien		do
2141132727Skan		  c = *++p;
214252284Sobrien		while (c != ',' && c != '\0');
214352284Sobrien	      if (c == ',' || c == '\0')
2144132727Skan		{
2145132727Skan		  p++;
2146132727Skan		  break;
2147132727Skan		}
214852284Sobrien
214952284Sobrien	      switch (c)
215052284Sobrien		{
215152284Sobrien		case '=': case '+': case '*': case '%':
215252284Sobrien		case 'E': case 'F': case 'G': case 'H':
215352284Sobrien		case 's': case 'i': case 'n':
215452284Sobrien		case 'I': case 'J': case 'K': case 'L':
215552284Sobrien		case 'M': case 'N': case 'O': case 'P':
215652284Sobrien		  /* These don't say anything we care about.  */
215752284Sobrien		  break;
215852284Sobrien
215952284Sobrien		case '?':
216052284Sobrien		  op_alt[j].reject += 6;
216152284Sobrien		  break;
216252284Sobrien		case '!':
216352284Sobrien		  op_alt[j].reject += 600;
216452284Sobrien		  break;
216552284Sobrien		case '&':
216652284Sobrien		  op_alt[j].earlyclobber = 1;
2167117404Skan		  break;
216852284Sobrien
216952284Sobrien		case '0': case '1': case '2': case '3': case '4':
217052284Sobrien		case '5': case '6': case '7': case '8': case '9':
217190075Sobrien		  {
217290075Sobrien		    char *end;
2173132727Skan		    op_alt[j].matches = strtoul (p, &end, 10);
217490075Sobrien		    recog_op_alt[op_alt[j].matches][j].matched = i;
217590075Sobrien		    p = end;
217690075Sobrien		  }
2177132727Skan		  continue;
217852284Sobrien
217952284Sobrien		case 'm':
218052284Sobrien		  op_alt[j].memory_ok = 1;
218152284Sobrien		  break;
218252284Sobrien		case '<':
218352284Sobrien		  op_alt[j].decmem_ok = 1;
218452284Sobrien		  break;
218552284Sobrien		case '>':
218652284Sobrien		  op_alt[j].incmem_ok = 1;
218752284Sobrien		  break;
218852284Sobrien		case 'V':
218952284Sobrien		  op_alt[j].nonoffmem_ok = 1;
219052284Sobrien		  break;
219152284Sobrien		case 'o':
219252284Sobrien		  op_alt[j].offmem_ok = 1;
219352284Sobrien		  break;
219452284Sobrien		case 'X':
219552284Sobrien		  op_alt[j].anything_ok = 1;
219652284Sobrien		  break;
219752284Sobrien
219852284Sobrien		case 'p':
219990075Sobrien		  op_alt[j].is_address = 1;
2200169699Skan		  op_alt[j].cl = reg_class_subunion[(int) op_alt[j].cl]
2201169699Skan		      [(int) base_reg_class (VOIDmode, ADDRESS, SCRATCH)];
220252284Sobrien		  break;
220352284Sobrien
2204169699Skan		case 'g':
2205169699Skan		case 'r':
2206169699Skan		  op_alt[j].cl =
2207169699Skan		   reg_class_subunion[(int) op_alt[j].cl][(int) GENERAL_REGS];
220852284Sobrien		  break;
220952284Sobrien
221052284Sobrien		default:
2211132727Skan		  if (EXTRA_MEMORY_CONSTRAINT (c, p))
2212117404Skan		    {
2213117404Skan		      op_alt[j].memory_ok = 1;
2214117404Skan		      break;
2215117404Skan		    }
2216132727Skan		  if (EXTRA_ADDRESS_CONSTRAINT (c, p))
2217117404Skan		    {
2218117404Skan		      op_alt[j].is_address = 1;
2219169699Skan		      op_alt[j].cl
2220132727Skan			= (reg_class_subunion
2221169699Skan			   [(int) op_alt[j].cl]
2222169699Skan			   [(int) base_reg_class (VOIDmode, ADDRESS,
2223169699Skan						  SCRATCH)]);
2224117404Skan		      break;
2225117404Skan		    }
2226117404Skan
2227169699Skan		  op_alt[j].cl
2228132727Skan		    = (reg_class_subunion
2229169699Skan		       [(int) op_alt[j].cl]
2230132727Skan		       [(int) REG_CLASS_FROM_CONSTRAINT ((unsigned char) c, p)]);
223152284Sobrien		  break;
223252284Sobrien		}
2233132727Skan	      p += CONSTRAINT_LEN (c, p);
223452284Sobrien	    }
223552284Sobrien	}
223652284Sobrien    }
223752284Sobrien}
2238117404Skan
223952284Sobrien/* Check the operands of an insn against the insn's operand constraints
224018334Speter   and return 1 if they are valid.
224152284Sobrien   The information about the insn's operands, constraints, operand modes
224252284Sobrien   etc. is obtained from the global variables set up by extract_insn.
224318334Speter
224418334Speter   WHICH_ALTERNATIVE is set to a number which indicates which
224518334Speter   alternative of constraints was matched: 0 for the first alternative,
224618334Speter   1 for the next, etc.
224718334Speter
2248132727Skan   In addition, when two operands are required to match
224918334Speter   and it happens that the output operand is (reg) while the
225018334Speter   input operand is --(reg) or ++(reg) (a pre-inc or pre-dec),
225118334Speter   make the output operand look like the input.
225218334Speter   This is because the output operand is the one the template will print.
225318334Speter
225418334Speter   This is used in final, just before printing the assembler code and by
225518334Speter   the routines that determine an insn's attribute.
225618334Speter
2257117404Skan   If STRICT is a positive nonzero value, it means that we have been
225818334Speter   called after reload has been completed.  In that case, we must
225918334Speter   do all checks strictly.  If it is zero, it means that we have been called
226018334Speter   before reload has completed.  In that case, we first try to see if we can
226118334Speter   find an alternative that matches strictly.  If not, we try again, this
226218334Speter   time assuming that reload will fix up the insn.  This provides a "best
226318334Speter   guess" for the alternative and is used to compute attributes of insns prior
226418334Speter   to reload.  A negative value of STRICT is used for this internal call.  */
226518334Speter
226618334Speterstruct funny_match
226718334Speter{
226818334Speter  int this, other;
226918334Speter};
227018334Speter
227118334Speterint
2272132727Skanconstrain_operands (int strict)
227318334Speter{
227452284Sobrien  const char *constraints[MAX_RECOG_OPERANDS];
227518334Speter  int matching_operands[MAX_RECOG_OPERANDS];
227618334Speter  int earlyclobber[MAX_RECOG_OPERANDS];
227790075Sobrien  int c;
227818334Speter
227918334Speter  struct funny_match funny_match[MAX_RECOG_OPERANDS];
228018334Speter  int funny_match_index;
228118334Speter
228290075Sobrien  which_alternative = 0;
228390075Sobrien  if (recog_data.n_operands == 0 || recog_data.n_alternatives == 0)
228418334Speter    return 1;
228518334Speter
228690075Sobrien  for (c = 0; c < recog_data.n_operands; c++)
228718334Speter    {
228890075Sobrien      constraints[c] = recog_data.constraints[c];
228918334Speter      matching_operands[c] = -1;
229018334Speter    }
229118334Speter
229290075Sobrien  do
229318334Speter    {
2294169699Skan      int seen_earlyclobber_at = -1;
229590075Sobrien      int opno;
229618334Speter      int lose = 0;
229718334Speter      funny_match_index = 0;
229818334Speter
229990075Sobrien      for (opno = 0; opno < recog_data.n_operands; opno++)
230018334Speter	{
230190075Sobrien	  rtx op = recog_data.operand[opno];
230218334Speter	  enum machine_mode mode = GET_MODE (op);
230390075Sobrien	  const char *p = constraints[opno];
230418334Speter	  int offset = 0;
230518334Speter	  int win = 0;
230618334Speter	  int val;
2307132727Skan	  int len;
230818334Speter
230918334Speter	  earlyclobber[opno] = 0;
231018334Speter
231150397Sobrien	  /* A unary operator may be accepted by the predicate, but it
231250397Sobrien	     is irrelevant for matching constraints.  */
2313169699Skan	  if (UNARY_P (op))
231450397Sobrien	    op = XEXP (op, 0);
231550397Sobrien
231618334Speter	  if (GET_CODE (op) == SUBREG)
231718334Speter	    {
2318169699Skan	      if (REG_P (SUBREG_REG (op))
231918334Speter		  && REGNO (SUBREG_REG (op)) < FIRST_PSEUDO_REGISTER)
232090075Sobrien		offset = subreg_regno_offset (REGNO (SUBREG_REG (op)),
232190075Sobrien					      GET_MODE (SUBREG_REG (op)),
232290075Sobrien					      SUBREG_BYTE (op),
232390075Sobrien					      GET_MODE (op));
232418334Speter	      op = SUBREG_REG (op);
232518334Speter	    }
232618334Speter
232718334Speter	  /* An empty constraint or empty alternative
232818334Speter	     allows anything which matched the pattern.  */
232918334Speter	  if (*p == 0 || *p == ',')
233018334Speter	    win = 1;
233118334Speter
2332132727Skan	  do
2333132727Skan	    switch (c = *p, len = CONSTRAINT_LEN (c, p), c)
233418334Speter	      {
2335132727Skan	      case '\0':
2336132727Skan		len = 0;
2337132727Skan		break;
2338132727Skan	      case ',':
2339132727Skan		c = '\0';
2340132727Skan		break;
2341132727Skan
234290075Sobrien	      case '?':  case '!': case '*':  case '%':
234390075Sobrien	      case '=':  case '+':
234418334Speter		break;
234518334Speter
234618334Speter	      case '#':
234718334Speter		/* Ignore rest of this alternative as far as
234818334Speter		   constraint checking is concerned.  */
2349132727Skan		do
235018334Speter		  p++;
2351132727Skan		while (*p && *p != ',');
2352132727Skan		len = 0;
235318334Speter		break;
235418334Speter
235518334Speter	      case '&':
235618334Speter		earlyclobber[opno] = 1;
2357169699Skan		if (seen_earlyclobber_at < 0)
2358169699Skan		  seen_earlyclobber_at = opno;
235918334Speter		break;
236018334Speter
236190075Sobrien	      case '0':  case '1':  case '2':  case '3':  case '4':
236290075Sobrien	      case '5':  case '6':  case '7':  case '8':  case '9':
236390075Sobrien		{
236490075Sobrien		  /* This operand must be the same as a previous one.
236590075Sobrien		     This kind of constraint is used for instructions such
236690075Sobrien		     as add when they take only two operands.
236718334Speter
236890075Sobrien		     Note that the lower-numbered operand is passed first.
236918334Speter
237090075Sobrien		     If we are not testing strictly, assume that this
237190075Sobrien		     constraint will be satisfied.  */
237218334Speter
237390075Sobrien		  char *end;
237490075Sobrien		  int match;
237552284Sobrien
2376132727Skan		  match = strtoul (p, &end, 10);
237790075Sobrien		  p = end;
237852284Sobrien
237990075Sobrien		  if (strict < 0)
238090075Sobrien		    val = 1;
238190075Sobrien		  else
238290075Sobrien		    {
238390075Sobrien		      rtx op1 = recog_data.operand[match];
238490075Sobrien		      rtx op2 = recog_data.operand[opno];
238518334Speter
238690075Sobrien		      /* A unary operator may be accepted by the predicate,
238790075Sobrien			 but it is irrelevant for matching constraints.  */
2388169699Skan		      if (UNARY_P (op1))
238990075Sobrien			op1 = XEXP (op1, 0);
2390169699Skan		      if (UNARY_P (op2))
239190075Sobrien			op2 = XEXP (op2, 0);
239290075Sobrien
239390075Sobrien		      val = operands_match_p (op1, op2);
239490075Sobrien		    }
239590075Sobrien
239690075Sobrien		  matching_operands[opno] = match;
239790075Sobrien		  matching_operands[match] = opno;
239890075Sobrien
239990075Sobrien		  if (val != 0)
240090075Sobrien		    win = 1;
240190075Sobrien
240290075Sobrien		  /* If output is *x and input is *--x, arrange later
240390075Sobrien		     to change the output to *--x as well, since the
240490075Sobrien		     output op is the one that will be printed.  */
240590075Sobrien		  if (val == 2 && strict > 0)
240690075Sobrien		    {
240790075Sobrien		      funny_match[funny_match_index].this = opno;
240890075Sobrien		      funny_match[funny_match_index++].other = match;
240990075Sobrien		    }
241090075Sobrien		}
2411132727Skan		len = 0;
241218334Speter		break;
241318334Speter
241418334Speter	      case 'p':
241518334Speter		/* p is used for address_operands.  When we are called by
241618334Speter		   gen_reload, no one will have checked that the address is
241718334Speter		   strictly valid, i.e., that all pseudos requiring hard regs
241818334Speter		   have gotten them.  */
241918334Speter		if (strict <= 0
242090075Sobrien		    || (strict_memory_address_p (recog_data.operand_mode[opno],
242152284Sobrien						 op)))
242218334Speter		  win = 1;
242318334Speter		break;
242418334Speter
242518334Speter		/* No need to check general_operand again;
2426169699Skan		   it was done in insn-recog.c.  Well, except that reload
2427169699Skan		   doesn't check the validity of its replacements, but
2428169699Skan		   that should only matter when there's a bug.  */
242918334Speter	      case 'g':
243018334Speter		/* Anything goes unless it is a REG and really has a hard reg
243118334Speter		   but the hard reg is not in the class GENERAL_REGS.  */
2432169699Skan		if (REG_P (op))
2433169699Skan		  {
2434169699Skan		    if (strict < 0
2435169699Skan			|| GENERAL_REGS == ALL_REGS
2436169699Skan			|| (reload_in_progress
2437169699Skan			    && REGNO (op) >= FIRST_PSEUDO_REGISTER)
2438169699Skan			|| reg_fits_class_p (op, GENERAL_REGS, offset, mode))
2439169699Skan		      win = 1;
2440169699Skan		  }
2441169699Skan		else if (strict < 0 || general_operand (op, mode))
244218334Speter		  win = 1;
244318334Speter		break;
244418334Speter
244518334Speter	      case 'X':
244650397Sobrien		/* This is used for a MATCH_SCRATCH in the cases when
244750397Sobrien		   we don't actually need anything.  So anything goes
244850397Sobrien		   any time.  */
244918334Speter		win = 1;
245018334Speter		break;
245118334Speter
245218334Speter	      case 'm':
2453132727Skan		/* Memory operands must be valid, to the extent
2454132727Skan		   required by STRICT.  */
2455169699Skan		if (MEM_P (op))
2456132727Skan		  {
2457132727Skan		    if (strict > 0
2458132727Skan			&& !strict_memory_address_p (GET_MODE (op),
2459132727Skan						     XEXP (op, 0)))
2460132727Skan		      break;
2461132727Skan		    if (strict == 0
2462132727Skan			&& !memory_address_p (GET_MODE (op), XEXP (op, 0)))
2463132727Skan		      break;
2464132727Skan		    win = 1;
2465132727Skan		  }
2466132727Skan		/* Before reload, accept what reload can turn into mem.  */
2467132727Skan		else if (strict < 0 && CONSTANT_P (op))
246818334Speter		  win = 1;
2469132727Skan		/* During reload, accept a pseudo  */
2470169699Skan		else if (reload_in_progress && REG_P (op)
2471132727Skan			 && REGNO (op) >= FIRST_PSEUDO_REGISTER)
2472132727Skan		  win = 1;
247318334Speter		break;
247418334Speter
247518334Speter	      case '<':
2476169699Skan		if (MEM_P (op)
247718334Speter		    && (GET_CODE (XEXP (op, 0)) == PRE_DEC
247818334Speter			|| GET_CODE (XEXP (op, 0)) == POST_DEC))
247918334Speter		  win = 1;
248018334Speter		break;
248118334Speter
248218334Speter	      case '>':
2483169699Skan		if (MEM_P (op)
248418334Speter		    && (GET_CODE (XEXP (op, 0)) == PRE_INC
248518334Speter			|| GET_CODE (XEXP (op, 0)) == POST_INC))
248618334Speter		  win = 1;
248718334Speter		break;
248818334Speter
248918334Speter	      case 'E':
249018334Speter	      case 'F':
2491117404Skan		if (GET_CODE (op) == CONST_DOUBLE
2492117404Skan		    || (GET_CODE (op) == CONST_VECTOR
2493117404Skan			&& GET_MODE_CLASS (GET_MODE (op)) == MODE_VECTOR_FLOAT))
249418334Speter		  win = 1;
249518334Speter		break;
249618334Speter
249718334Speter	      case 'G':
249818334Speter	      case 'H':
249918334Speter		if (GET_CODE (op) == CONST_DOUBLE
2500132727Skan		    && CONST_DOUBLE_OK_FOR_CONSTRAINT_P (op, c, p))
250118334Speter		  win = 1;
250218334Speter		break;
250318334Speter
250418334Speter	      case 's':
250518334Speter		if (GET_CODE (op) == CONST_INT
250618334Speter		    || (GET_CODE (op) == CONST_DOUBLE
250718334Speter			&& GET_MODE (op) == VOIDmode))
250818334Speter		  break;
250918334Speter	      case 'i':
251018334Speter		if (CONSTANT_P (op))
251118334Speter		  win = 1;
251218334Speter		break;
251318334Speter
251418334Speter	      case 'n':
251518334Speter		if (GET_CODE (op) == CONST_INT
251618334Speter		    || (GET_CODE (op) == CONST_DOUBLE
251718334Speter			&& GET_MODE (op) == VOIDmode))
251818334Speter		  win = 1;
251918334Speter		break;
252018334Speter
252118334Speter	      case 'I':
252218334Speter	      case 'J':
252318334Speter	      case 'K':
252418334Speter	      case 'L':
252518334Speter	      case 'M':
252618334Speter	      case 'N':
252718334Speter	      case 'O':
252818334Speter	      case 'P':
252918334Speter		if (GET_CODE (op) == CONST_INT
2530132727Skan		    && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), c, p))
253118334Speter		  win = 1;
253218334Speter		break;
253318334Speter
253418334Speter	      case 'V':
2535169699Skan		if (MEM_P (op)
253650397Sobrien		    && ((strict > 0 && ! offsettable_memref_p (op))
253750397Sobrien			|| (strict < 0
2538169699Skan			    && !(CONSTANT_P (op) || MEM_P (op)))
253950397Sobrien			|| (reload_in_progress
2540169699Skan			    && !(REG_P (op)
254150397Sobrien				 && REGNO (op) >= FIRST_PSEUDO_REGISTER))))
254218334Speter		  win = 1;
254318334Speter		break;
254418334Speter
254518334Speter	      case 'o':
254618334Speter		if ((strict > 0 && offsettable_memref_p (op))
254718334Speter		    || (strict == 0 && offsettable_nonstrict_memref_p (op))
254818334Speter		    /* Before reload, accept what reload can handle.  */
254918334Speter		    || (strict < 0
2550169699Skan			&& (CONSTANT_P (op) || MEM_P (op)))
255118334Speter		    /* During reload, accept a pseudo  */
2552169699Skan		    || (reload_in_progress && REG_P (op)
255318334Speter			&& REGNO (op) >= FIRST_PSEUDO_REGISTER))
255418334Speter		  win = 1;
255518334Speter		break;
255618334Speter
255718334Speter	      default:
255890075Sobrien		{
2559169699Skan		  enum reg_class cl;
256090075Sobrien
2561169699Skan		  cl = (c == 'r'
2562132727Skan			   ? GENERAL_REGS : REG_CLASS_FROM_CONSTRAINT (c, p));
2563169699Skan		  if (cl != NO_REGS)
256490075Sobrien		    {
256590075Sobrien		      if (strict < 0
256690075Sobrien			  || (strict == 0
2567169699Skan			      && REG_P (op)
256890075Sobrien			      && REGNO (op) >= FIRST_PSEUDO_REGISTER)
256990075Sobrien			  || (strict == 0 && GET_CODE (op) == SCRATCH)
2570169699Skan			  || (REG_P (op)
2571169699Skan			      && reg_fits_class_p (op, cl, offset, mode)))
257290075Sobrien		        win = 1;
257390075Sobrien		    }
2574132727Skan#ifdef EXTRA_CONSTRAINT_STR
2575132727Skan		  else if (EXTRA_CONSTRAINT_STR (op, c, p))
257690075Sobrien		    win = 1;
2577117404Skan
2578132727Skan		  else if (EXTRA_MEMORY_CONSTRAINT (c, p)
2579132727Skan			   /* Every memory operand can be reloaded to fit.  */
2580169699Skan			   && ((strict < 0 && MEM_P (op))
2581132727Skan			       /* Before reload, accept what reload can turn
2582132727Skan				  into mem.  */
2583132727Skan			       || (strict < 0 && CONSTANT_P (op))
2584132727Skan			       /* During reload, accept a pseudo  */
2585169699Skan			       || (reload_in_progress && REG_P (op)
2586132727Skan				   && REGNO (op) >= FIRST_PSEUDO_REGISTER)))
2587132727Skan		    win = 1;
2588132727Skan		  else if (EXTRA_ADDRESS_CONSTRAINT (c, p)
2589132727Skan			   /* Every address operand can be reloaded to fit.  */
2590132727Skan			   && strict < 0)
2591132727Skan		    win = 1;
259290075Sobrien#endif
259390075Sobrien		  break;
259490075Sobrien		}
259518334Speter	      }
2596132727Skan	  while (p += len, c);
259718334Speter
259818334Speter	  constraints[opno] = p;
259918334Speter	  /* If this operand did not win somehow,
260018334Speter	     this alternative loses.  */
260118334Speter	  if (! win)
260218334Speter	    lose = 1;
260318334Speter	}
260418334Speter      /* This alternative won; the operands are ok.
260518334Speter	 Change whichever operands this alternative says to change.  */
260618334Speter      if (! lose)
260718334Speter	{
260818334Speter	  int opno, eopno;
260918334Speter
261018334Speter	  /* See if any earlyclobber operand conflicts with some other
261118334Speter	     operand.  */
261218334Speter
2613169699Skan	  if (strict > 0  && seen_earlyclobber_at >= 0)
2614169699Skan	    for (eopno = seen_earlyclobber_at;
2615169699Skan		 eopno < recog_data.n_operands;
2616169699Skan		 eopno++)
261718334Speter	      /* Ignore earlyclobber operands now in memory,
261818334Speter		 because we would often report failure when we have
261918334Speter		 two memory operands, one of which was formerly a REG.  */
262018334Speter	      if (earlyclobber[eopno]
2621169699Skan		  && REG_P (recog_data.operand[eopno]))
262290075Sobrien		for (opno = 0; opno < recog_data.n_operands; opno++)
2623169699Skan		  if ((MEM_P (recog_data.operand[opno])
262490075Sobrien		       || recog_data.operand_type[opno] != OP_OUT)
262518334Speter		      && opno != eopno
262650397Sobrien		      /* Ignore things like match_operator operands.  */
262790075Sobrien		      && *recog_data.constraints[opno] != 0
262818334Speter		      && ! (matching_operands[opno] == eopno
262990075Sobrien			    && operands_match_p (recog_data.operand[opno],
263090075Sobrien						 recog_data.operand[eopno]))
263190075Sobrien		      && ! safe_from_earlyclobber (recog_data.operand[opno],
263290075Sobrien						   recog_data.operand[eopno]))
263318334Speter		    lose = 1;
263418334Speter
263518334Speter	  if (! lose)
263618334Speter	    {
263718334Speter	      while (--funny_match_index >= 0)
263818334Speter		{
263990075Sobrien		  recog_data.operand[funny_match[funny_match_index].other]
264090075Sobrien		    = recog_data.operand[funny_match[funny_match_index].this];
264118334Speter		}
264218334Speter
264318334Speter	      return 1;
264418334Speter	    }
264518334Speter	}
264618334Speter
264718334Speter      which_alternative++;
264818334Speter    }
264990075Sobrien  while (which_alternative < recog_data.n_alternatives);
265018334Speter
265190075Sobrien  which_alternative = -1;
265218334Speter  /* If we are about to reject this, but we are not to test strictly,
265318334Speter     try a very loose test.  Only return failure if it fails also.  */
265418334Speter  if (strict == 0)
265552284Sobrien    return constrain_operands (-1);
265618334Speter  else
265718334Speter    return 0;
265818334Speter}
265918334Speter
266018334Speter/* Return 1 iff OPERAND (assumed to be a REG rtx)
266150397Sobrien   is a hard reg in class CLASS when its regno is offset by OFFSET
266218334Speter   and changed to mode MODE.
266318334Speter   If REG occupies multiple hard regs, all of them must be in CLASS.  */
266418334Speter
266518334Speterint
2666169699Skanreg_fits_class_p (rtx operand, enum reg_class cl, int offset,
2667132727Skan		  enum machine_mode mode)
266818334Speter{
266990075Sobrien  int regno = REGNO (operand);
2670169699Skan
2671169699Skan  if (cl == NO_REGS)
2672169699Skan    return 0;
2673169699Skan
267418334Speter  if (regno < FIRST_PSEUDO_REGISTER
2675169699Skan      && TEST_HARD_REG_BIT (reg_class_contents[(int) cl],
267618334Speter			    regno + offset))
267718334Speter    {
267890075Sobrien      int sr;
267918334Speter      regno += offset;
2680169699Skan      for (sr = hard_regno_nregs[regno][mode] - 1;
268118334Speter	   sr > 0; sr--)
2682169699Skan	if (! TEST_HARD_REG_BIT (reg_class_contents[(int) cl],
268318334Speter				 regno + sr))
268418334Speter	  break;
268518334Speter      return sr == 0;
268618334Speter    }
268718334Speter
268818334Speter  return 0;
268918334Speter}
269052284Sobrien
2691132727Skan/* Split single instruction.  Helper function for split_all_insns and
2692132727Skan   split_all_insns_noflow.  Return last insn in the sequence if successful,
2693132727Skan   or NULL if unsuccessful.  */
2694132727Skan
269590075Sobrienstatic rtx
2696132727Skansplit_insn (rtx insn)
269752284Sobrien{
2698132727Skan  /* Split insns here to get max fine-grain parallelism.  */
2699132727Skan  rtx first = PREV_INSN (insn);
2700132727Skan  rtx last = try_split (PATTERN (insn), insn, 1);
270152284Sobrien
2702132727Skan  if (last == insn)
2703132727Skan    return NULL_RTX;
2704132727Skan
2705132727Skan  /* try_split returns the NOTE that INSN became.  */
2706169699Skan  SET_INSN_DELETED (insn);
2707132727Skan
2708132727Skan  /* ??? Coddle to md files that generate subregs in post-reload
2709132727Skan     splitters instead of computing the proper hard register.  */
2710132727Skan  if (reload_completed && first != last)
271152284Sobrien    {
2712132727Skan      first = NEXT_INSN (first);
2713132727Skan      for (;;)
271452284Sobrien	{
2715132727Skan	  if (INSN_P (first))
2716132727Skan	    cleanup_subreg_operands (first);
2717132727Skan	  if (first == last)
2718132727Skan	    break;
2719132727Skan	  first = NEXT_INSN (first);
272052284Sobrien	}
272190075Sobrien    }
2722132727Skan  return last;
272390075Sobrien}
2724132727Skan
272590075Sobrien/* Split all insns in the function.  If UPD_LIFE, update life info after.  */
272652284Sobrien
272790075Sobrienvoid
2728132727Skansplit_all_insns (int upd_life)
272990075Sobrien{
273090075Sobrien  sbitmap blocks;
2731117404Skan  bool changed;
2732117404Skan  basic_block bb;
273390075Sobrien
2734117404Skan  blocks = sbitmap_alloc (last_basic_block);
273590075Sobrien  sbitmap_zero (blocks);
2736117404Skan  changed = false;
273790075Sobrien
2738117404Skan  FOR_EACH_BB_REVERSE (bb)
273990075Sobrien    {
274090075Sobrien      rtx insn, next;
2741117404Skan      bool finish = false;
274290075Sobrien
2743132727Skan      for (insn = BB_HEAD (bb); !finish ; insn = next)
274452284Sobrien	{
274590075Sobrien	  /* Can't use `next_real_insn' because that might go across
274690075Sobrien	     CODE_LABELS and short-out basic blocks.  */
274790075Sobrien	  next = NEXT_INSN (insn);
2748132727Skan	  finish = (insn == BB_END (bb));
2749132727Skan	  if (INSN_P (insn))
275052284Sobrien	    {
2751132727Skan	      rtx set = single_set (insn);
275252284Sobrien
2753132727Skan	      /* Don't split no-op move insns.  These should silently
2754132727Skan		 disappear later in final.  Splitting such insns would
2755132727Skan		 break the code that handles REG_NO_CONFLICT blocks.  */
2756132727Skan	      if (set && set_noop_p (set))
2757132727Skan		{
2758132727Skan		  /* Nops get in the way while scheduling, so delete them
2759132727Skan		     now if register allocation has already been done.  It
2760132727Skan		     is too risky to try to do this before register
2761132727Skan		     allocation, and there are unlikely to be very many
2762132727Skan		     nops then anyways.  */
2763132727Skan		  if (reload_completed)
2764132727Skan		    {
2765132727Skan		      /* If the no-op set has a REG_UNUSED note, we need
2766132727Skan			 to update liveness information.  */
2767132727Skan		      if (find_reg_note (insn, REG_UNUSED, NULL_RTX))
2768132727Skan			{
2769132727Skan			  SET_BIT (blocks, bb->index);
2770132727Skan			  changed = true;
2771132727Skan			}
2772132727Skan		      /* ??? Is life info affected by deleting edges?  */
2773132727Skan		      delete_insn_and_edges (insn);
2774132727Skan		    }
2775132727Skan		}
2776132727Skan	      else
2777132727Skan		{
2778132727Skan		  rtx last = split_insn (insn);
2779132727Skan		  if (last)
2780132727Skan		    {
2781132727Skan		      /* The split sequence may include barrier, but the
2782132727Skan			 BB boundary we are interested in will be set to
2783132727Skan			 previous one.  */
2784132727Skan
2785169699Skan		      while (BARRIER_P (last))
2786132727Skan			last = PREV_INSN (last);
2787132727Skan		      SET_BIT (blocks, bb->index);
2788132727Skan		      changed = true;
2789132727Skan		    }
2790132727Skan		}
279152284Sobrien	    }
279252284Sobrien	}
279390075Sobrien    }
279490075Sobrien
279590075Sobrien  if (changed)
279690075Sobrien    {
2797117404Skan      int old_last_basic_block = last_basic_block;
2798117404Skan
279990075Sobrien      find_many_sub_basic_blocks (blocks);
2800117404Skan
2801117404Skan      if (old_last_basic_block != last_basic_block && upd_life)
2802117404Skan	blocks = sbitmap_resize (blocks, last_basic_block, 1);
280390075Sobrien    }
280490075Sobrien
280590075Sobrien  if (changed && upd_life)
2806117404Skan    update_life_info (blocks, UPDATE_LIFE_GLOBAL_RM_NOTES,
2807169699Skan		      PROP_DEATH_NOTES);
2808117404Skan
280990075Sobrien#ifdef ENABLE_CHECKING
281090075Sobrien  verify_flow_info ();
281190075Sobrien#endif
281290075Sobrien
281390075Sobrien  sbitmap_free (blocks);
281490075Sobrien}
281590075Sobrien
2816117404Skan/* Same as split_all_insns, but do not expect CFG to be available.
2817132727Skan   Used by machine dependent reorg passes.  */
281890075Sobrien
2819169699Skanunsigned int
2820132727Skansplit_all_insns_noflow (void)
282190075Sobrien{
282290075Sobrien  rtx next, insn;
282390075Sobrien
282490075Sobrien  for (insn = get_insns (); insn; insn = next)
282590075Sobrien    {
282690075Sobrien      next = NEXT_INSN (insn);
2827132727Skan      if (INSN_P (insn))
2828132727Skan	{
2829132727Skan	  /* Don't split no-op move insns.  These should silently
2830132727Skan	     disappear later in final.  Splitting such insns would
2831132727Skan	     break the code that handles REG_NO_CONFLICT blocks.  */
2832132727Skan	  rtx set = single_set (insn);
2833132727Skan	  if (set && set_noop_p (set))
2834132727Skan	    {
2835132727Skan	      /* Nops get in the way while scheduling, so delete them
2836132727Skan		 now if register allocation has already been done.  It
2837132727Skan		 is too risky to try to do this before register
2838132727Skan		 allocation, and there are unlikely to be very many
2839132727Skan		 nops then anyways.
2840132727Skan
2841132727Skan		 ??? Should we use delete_insn when the CFG isn't valid?  */
2842132727Skan	      if (reload_completed)
2843132727Skan		delete_insn_and_edges (insn);
2844132727Skan	    }
2845132727Skan	  else
2846132727Skan	    split_insn (insn);
2847132727Skan	}
284890075Sobrien    }
2849169699Skan  return 0;
285090075Sobrien}
285190075Sobrien
285290075Sobrien#ifdef HAVE_peephole2
285390075Sobrienstruct peep2_insn_data
285490075Sobrien{
285590075Sobrien  rtx insn;
285690075Sobrien  regset live_before;
285790075Sobrien};
285890075Sobrien
285990075Sobrienstatic struct peep2_insn_data peep2_insn_data[MAX_INSNS_PER_PEEP2 + 1];
286090075Sobrienstatic int peep2_current;
2861169699Skan/* The number of instructions available to match a peep2.  */
2862169699Skanint peep2_current_count;
286390075Sobrien
286490075Sobrien/* A non-insn marker indicating the last insn of the block.
286590075Sobrien   The live_before regset for this element is correct, indicating
286690075Sobrien   global_live_at_end for the block.  */
286790075Sobrien#define PEEP2_EOB	pc_rtx
286890075Sobrien
286990075Sobrien/* Return the Nth non-note insn after `current', or return NULL_RTX if it
287090075Sobrien   does not exist.  Used by the recognizer to find the next insn to match
287190075Sobrien   in a multi-insn pattern.  */
287290075Sobrien
287390075Sobrienrtx
2874132727Skanpeep2_next_insn (int n)
287590075Sobrien{
2876169699Skan  gcc_assert (n <= peep2_current_count);
287790075Sobrien
287890075Sobrien  n += peep2_current;
287990075Sobrien  if (n >= MAX_INSNS_PER_PEEP2 + 1)
288090075Sobrien    n -= MAX_INSNS_PER_PEEP2 + 1;
288190075Sobrien
288290075Sobrien  return peep2_insn_data[n].insn;
288390075Sobrien}
288490075Sobrien
288590075Sobrien/* Return true if REGNO is dead before the Nth non-note insn
288690075Sobrien   after `current'.  */
288790075Sobrien
288890075Sobrienint
2889132727Skanpeep2_regno_dead_p (int ofs, int regno)
289090075Sobrien{
2891169699Skan  gcc_assert (ofs < MAX_INSNS_PER_PEEP2 + 1);
289290075Sobrien
289390075Sobrien  ofs += peep2_current;
289490075Sobrien  if (ofs >= MAX_INSNS_PER_PEEP2 + 1)
289590075Sobrien    ofs -= MAX_INSNS_PER_PEEP2 + 1;
289690075Sobrien
2897169699Skan  gcc_assert (peep2_insn_data[ofs].insn != NULL_RTX);
289890075Sobrien
289990075Sobrien  return ! REGNO_REG_SET_P (peep2_insn_data[ofs].live_before, regno);
290090075Sobrien}
290190075Sobrien
290290075Sobrien/* Similarly for a REG.  */
290390075Sobrien
290490075Sobrienint
2905132727Skanpeep2_reg_dead_p (int ofs, rtx reg)
290690075Sobrien{
290790075Sobrien  int regno, n;
290890075Sobrien
2909169699Skan  gcc_assert (ofs < MAX_INSNS_PER_PEEP2 + 1);
291090075Sobrien
291190075Sobrien  ofs += peep2_current;
291290075Sobrien  if (ofs >= MAX_INSNS_PER_PEEP2 + 1)
291390075Sobrien    ofs -= MAX_INSNS_PER_PEEP2 + 1;
291490075Sobrien
2915169699Skan  gcc_assert (peep2_insn_data[ofs].insn != NULL_RTX);
291690075Sobrien
291790075Sobrien  regno = REGNO (reg);
2918169699Skan  n = hard_regno_nregs[regno][GET_MODE (reg)];
291990075Sobrien  while (--n >= 0)
292090075Sobrien    if (REGNO_REG_SET_P (peep2_insn_data[ofs].live_before, regno + n))
292190075Sobrien      return 0;
292290075Sobrien  return 1;
292390075Sobrien}
292490075Sobrien
292590075Sobrien/* Try to find a hard register of mode MODE, matching the register class in
292690075Sobrien   CLASS_STR, which is available at the beginning of insn CURRENT_INSN and
292790075Sobrien   remains available until the end of LAST_INSN.  LAST_INSN may be NULL_RTX,
292890075Sobrien   in which case the only condition is that the register must be available
292990075Sobrien   before CURRENT_INSN.
293090075Sobrien   Registers that already have bits set in REG_SET will not be considered.
293190075Sobrien
293290075Sobrien   If an appropriate register is available, it will be returned and the
293390075Sobrien   corresponding bit(s) in REG_SET will be set; otherwise, NULL_RTX is
293490075Sobrien   returned.  */
293590075Sobrien
293690075Sobrienrtx
2937132727Skanpeep2_find_free_register (int from, int to, const char *class_str,
2938132727Skan			  enum machine_mode mode, HARD_REG_SET *reg_set)
293990075Sobrien{
294090075Sobrien  static int search_ofs;
2941169699Skan  enum reg_class cl;
294290075Sobrien  HARD_REG_SET live;
294390075Sobrien  int i;
294490075Sobrien
2945169699Skan  gcc_assert (from < MAX_INSNS_PER_PEEP2 + 1);
2946169699Skan  gcc_assert (to < MAX_INSNS_PER_PEEP2 + 1);
294790075Sobrien
294890075Sobrien  from += peep2_current;
294990075Sobrien  if (from >= MAX_INSNS_PER_PEEP2 + 1)
295090075Sobrien    from -= MAX_INSNS_PER_PEEP2 + 1;
295190075Sobrien  to += peep2_current;
295290075Sobrien  if (to >= MAX_INSNS_PER_PEEP2 + 1)
295390075Sobrien    to -= MAX_INSNS_PER_PEEP2 + 1;
295490075Sobrien
2955169699Skan  gcc_assert (peep2_insn_data[from].insn != NULL_RTX);
295690075Sobrien  REG_SET_TO_HARD_REG_SET (live, peep2_insn_data[from].live_before);
295790075Sobrien
295890075Sobrien  while (from != to)
295990075Sobrien    {
296090075Sobrien      HARD_REG_SET this_live;
296190075Sobrien
296290075Sobrien      if (++from >= MAX_INSNS_PER_PEEP2 + 1)
296390075Sobrien	from = 0;
2964169699Skan      gcc_assert (peep2_insn_data[from].insn != NULL_RTX);
296590075Sobrien      REG_SET_TO_HARD_REG_SET (this_live, peep2_insn_data[from].live_before);
296690075Sobrien      IOR_HARD_REG_SET (live, this_live);
296790075Sobrien    }
296890075Sobrien
2969169699Skan  cl = (class_str[0] == 'r' ? GENERAL_REGS
2970132727Skan	   : REG_CLASS_FROM_CONSTRAINT (class_str[0], class_str));
297190075Sobrien
297290075Sobrien  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
297390075Sobrien    {
297490075Sobrien      int raw_regno, regno, success, j;
297590075Sobrien
297690075Sobrien      /* Distribute the free registers as much as possible.  */
297790075Sobrien      raw_regno = search_ofs + i;
297890075Sobrien      if (raw_regno >= FIRST_PSEUDO_REGISTER)
297990075Sobrien	raw_regno -= FIRST_PSEUDO_REGISTER;
298090075Sobrien#ifdef REG_ALLOC_ORDER
298190075Sobrien      regno = reg_alloc_order[raw_regno];
298290075Sobrien#else
298390075Sobrien      regno = raw_regno;
298490075Sobrien#endif
298590075Sobrien
298690075Sobrien      /* Don't allocate fixed registers.  */
298790075Sobrien      if (fixed_regs[regno])
298890075Sobrien	continue;
298990075Sobrien      /* Make sure the register is of the right class.  */
2990169699Skan      if (! TEST_HARD_REG_BIT (reg_class_contents[cl], regno))
299190075Sobrien	continue;
299290075Sobrien      /* And can support the mode we need.  */
299390075Sobrien      if (! HARD_REGNO_MODE_OK (regno, mode))
299490075Sobrien	continue;
299590075Sobrien      /* And that we don't create an extra save/restore.  */
299690075Sobrien      if (! call_used_regs[regno] && ! regs_ever_live[regno])
299790075Sobrien	continue;
299890075Sobrien      /* And we don't clobber traceback for noreturn functions.  */
299990075Sobrien      if ((regno == FRAME_POINTER_REGNUM || regno == HARD_FRAME_POINTER_REGNUM)
300090075Sobrien	  && (! reload_completed || frame_pointer_needed))
300190075Sobrien	continue;
300290075Sobrien
300390075Sobrien      success = 1;
3004169699Skan      for (j = hard_regno_nregs[regno][mode] - 1; j >= 0; j--)
300552284Sobrien	{
300690075Sobrien	  if (TEST_HARD_REG_BIT (*reg_set, regno + j)
300790075Sobrien	      || TEST_HARD_REG_BIT (live, regno + j))
300890075Sobrien	    {
300990075Sobrien	      success = 0;
301090075Sobrien	      break;
301190075Sobrien	    }
301290075Sobrien	}
301390075Sobrien      if (success)
301490075Sobrien	{
3015169699Skan	  for (j = hard_regno_nregs[regno][mode] - 1; j >= 0; j--)
301690075Sobrien	    SET_HARD_REG_BIT (*reg_set, regno + j);
301752284Sobrien
301890075Sobrien	  /* Start the next search with the next register.  */
301990075Sobrien	  if (++raw_regno >= FIRST_PSEUDO_REGISTER)
302090075Sobrien	    raw_regno = 0;
302190075Sobrien	  search_ofs = raw_regno;
302290075Sobrien
302390075Sobrien	  return gen_rtx_REG (mode, regno);
302490075Sobrien	}
302590075Sobrien    }
302690075Sobrien
302790075Sobrien  search_ofs = 0;
302890075Sobrien  return NULL_RTX;
302990075Sobrien}
303090075Sobrien
303190075Sobrien/* Perform the peephole2 optimization pass.  */
303290075Sobrien
3033169699Skanstatic void
3034169699Skanpeephole2_optimize (void)
303590075Sobrien{
303690075Sobrien  rtx insn, prev;
303790075Sobrien  regset live;
3038117404Skan  int i;
3039117404Skan  basic_block bb;
304090075Sobrien#ifdef HAVE_conditional_execution
304190075Sobrien  sbitmap blocks;
304296263Sobrien  bool changed;
304390075Sobrien#endif
304496263Sobrien  bool do_cleanup_cfg = false;
3045169699Skan  bool do_global_life_update = false;
304696263Sobrien  bool do_rebuild_jump_labels = false;
304790075Sobrien
304890075Sobrien  /* Initialize the regsets we're going to use.  */
304990075Sobrien  for (i = 0; i < MAX_INSNS_PER_PEEP2 + 1; ++i)
3050169699Skan    peep2_insn_data[i].live_before = ALLOC_REG_SET (&reg_obstack);
3051169699Skan  live = ALLOC_REG_SET (&reg_obstack);
305290075Sobrien
305390075Sobrien#ifdef HAVE_conditional_execution
3054117404Skan  blocks = sbitmap_alloc (last_basic_block);
305590075Sobrien  sbitmap_zero (blocks);
305696263Sobrien  changed = false;
305790075Sobrien#else
305890075Sobrien  count_or_remove_death_notes (NULL, 1);
305990075Sobrien#endif
306090075Sobrien
3061117404Skan  FOR_EACH_BB_REVERSE (bb)
306290075Sobrien    {
306390075Sobrien      struct propagate_block_info *pbi;
3064169699Skan      reg_set_iterator rsi;
3065169699Skan      unsigned int j;
306690075Sobrien
306790075Sobrien      /* Indicate that all slots except the last holds invalid data.  */
306890075Sobrien      for (i = 0; i < MAX_INSNS_PER_PEEP2; ++i)
306990075Sobrien	peep2_insn_data[i].insn = NULL_RTX;
3070169699Skan      peep2_current_count = 0;
307190075Sobrien
307290075Sobrien      /* Indicate that the last slot contains live_after data.  */
307390075Sobrien      peep2_insn_data[MAX_INSNS_PER_PEEP2].insn = PEEP2_EOB;
307490075Sobrien      peep2_current = MAX_INSNS_PER_PEEP2;
307590075Sobrien
307690075Sobrien      /* Start up propagation.  */
3077169699Skan      COPY_REG_SET (live, bb->il.rtl->global_live_at_end);
307890075Sobrien      COPY_REG_SET (peep2_insn_data[MAX_INSNS_PER_PEEP2].live_before, live);
307990075Sobrien
308090075Sobrien#ifdef HAVE_conditional_execution
308190075Sobrien      pbi = init_propagate_block_info (bb, live, NULL, NULL, 0);
308290075Sobrien#else
308390075Sobrien      pbi = init_propagate_block_info (bb, live, NULL, NULL, PROP_DEATH_NOTES);
308490075Sobrien#endif
308590075Sobrien
3086132727Skan      for (insn = BB_END (bb); ; insn = prev)
308790075Sobrien	{
308890075Sobrien	  prev = PREV_INSN (insn);
308990075Sobrien	  if (INSN_P (insn))
309052284Sobrien	    {
309196263Sobrien	      rtx try, before_try, x;
309290075Sobrien	      int match_len;
309396263Sobrien	      rtx note;
3094117404Skan	      bool was_call = false;
309590075Sobrien
309690075Sobrien	      /* Record this insn.  */
309790075Sobrien	      if (--peep2_current < 0)
309890075Sobrien		peep2_current = MAX_INSNS_PER_PEEP2;
3099169699Skan	      if (peep2_current_count < MAX_INSNS_PER_PEEP2
3100169699Skan		  && peep2_insn_data[peep2_current].insn == NULL_RTX)
3101169699Skan		peep2_current_count++;
310290075Sobrien	      peep2_insn_data[peep2_current].insn = insn;
310390075Sobrien	      propagate_one_insn (pbi, insn);
310490075Sobrien	      COPY_REG_SET (peep2_insn_data[peep2_current].live_before, live);
310590075Sobrien
3106169699Skan	      if (RTX_FRAME_RELATED_P (insn))
3107169699Skan		{
3108169699Skan		  /* If an insn has RTX_FRAME_RELATED_P set, peephole
3109169699Skan		     substitution would lose the
3110169699Skan		     REG_FRAME_RELATED_EXPR that is attached.  */
3111169699Skan		  peep2_current_count = 0;
3112169699Skan		  try = NULL;
3113169699Skan		}
3114169699Skan	      else
3115169699Skan		/* Match the peephole.  */
3116169699Skan		try = peephole2_insns (PATTERN (insn), insn, &match_len);
3117169699Skan
311890075Sobrien	      if (try != NULL)
311990075Sobrien		{
312090075Sobrien		  /* If we are splitting a CALL_INSN, look for the CALL_INSN
312190075Sobrien		     in SEQ and copy our CALL_INSN_FUNCTION_USAGE and other
312290075Sobrien		     cfg-related call notes.  */
312390075Sobrien		  for (i = 0; i <= match_len; ++i)
312490075Sobrien		    {
3125117404Skan		      int j;
312690075Sobrien		      rtx old_insn, new_insn, note;
312790075Sobrien
312890075Sobrien		      j = i + peep2_current;
312990075Sobrien		      if (j >= MAX_INSNS_PER_PEEP2 + 1)
313090075Sobrien			j -= MAX_INSNS_PER_PEEP2 + 1;
313190075Sobrien		      old_insn = peep2_insn_data[j].insn;
3132169699Skan		      if (!CALL_P (old_insn))
313390075Sobrien			continue;
3134117404Skan		      was_call = true;
313590075Sobrien
3136117404Skan		      new_insn = try;
3137117404Skan		      while (new_insn != NULL_RTX)
3138117404Skan			{
3139169699Skan			  if (CALL_P (new_insn))
3140117404Skan			    break;
3141117404Skan			  new_insn = NEXT_INSN (new_insn);
3142117404Skan			}
3143117404Skan
3144169699Skan		      gcc_assert (new_insn != NULL_RTX);
314590075Sobrien
314690075Sobrien		      CALL_INSN_FUNCTION_USAGE (new_insn)
314790075Sobrien			= CALL_INSN_FUNCTION_USAGE (old_insn);
314890075Sobrien
314990075Sobrien		      for (note = REG_NOTES (old_insn);
315090075Sobrien			   note;
315190075Sobrien			   note = XEXP (note, 1))
315290075Sobrien			switch (REG_NOTE_KIND (note))
315390075Sobrien			  {
315490075Sobrien			  case REG_NORETURN:
315590075Sobrien			  case REG_SETJMP:
315690075Sobrien			    REG_NOTES (new_insn)
315790075Sobrien			      = gen_rtx_EXPR_LIST (REG_NOTE_KIND (note),
315890075Sobrien						   XEXP (note, 0),
315990075Sobrien						   REG_NOTES (new_insn));
316090075Sobrien			  default:
316190075Sobrien			    /* Discard all other reg notes.  */
316290075Sobrien			    break;
316390075Sobrien			  }
316490075Sobrien
316590075Sobrien		      /* Croak if there is another call in the sequence.  */
316690075Sobrien		      while (++i <= match_len)
316790075Sobrien			{
316890075Sobrien			  j = i + peep2_current;
316990075Sobrien			  if (j >= MAX_INSNS_PER_PEEP2 + 1)
317090075Sobrien			    j -= MAX_INSNS_PER_PEEP2 + 1;
317190075Sobrien			  old_insn = peep2_insn_data[j].insn;
3172169699Skan			  gcc_assert (!CALL_P (old_insn));
317390075Sobrien			}
317490075Sobrien		      break;
317590075Sobrien		    }
317690075Sobrien
317790075Sobrien		  i = match_len + peep2_current;
317890075Sobrien		  if (i >= MAX_INSNS_PER_PEEP2 + 1)
317990075Sobrien		    i -= MAX_INSNS_PER_PEEP2 + 1;
318090075Sobrien
3181117404Skan		  note = find_reg_note (peep2_insn_data[i].insn,
318296263Sobrien					REG_EH_REGION, NULL_RTX);
318396263Sobrien
318490075Sobrien		  /* Replace the old sequence with the new.  */
3185132727Skan		  try = emit_insn_after_setloc (try, peep2_insn_data[i].insn,
3186132727Skan					        INSN_LOCATOR (peep2_insn_data[i].insn));
318796263Sobrien		  before_try = PREV_INSN (insn);
318890075Sobrien		  delete_insn_chain (insn, peep2_insn_data[i].insn);
318990075Sobrien
319096263Sobrien		  /* Re-insert the EH_REGION notes.  */
3191117404Skan		  if (note || (was_call && nonlocal_goto_handler_labels))
319296263Sobrien		    {
319396263Sobrien		      edge eh_edge;
3194169699Skan		      edge_iterator ei;
319596263Sobrien
3196169699Skan		      FOR_EACH_EDGE (eh_edge, ei, bb->succs)
3197117404Skan			if (eh_edge->flags & (EDGE_EH | EDGE_ABNORMAL_CALL))
319896263Sobrien			  break;
319996263Sobrien
320096263Sobrien		      for (x = try ; x != before_try ; x = PREV_INSN (x))
3201169699Skan			if (CALL_P (x)
320296263Sobrien			    || (flag_non_call_exceptions
320396263Sobrien				&& may_trap_p (PATTERN (x))
320496263Sobrien				&& !find_reg_note (x, REG_EH_REGION, NULL)))
320596263Sobrien			  {
3206117404Skan			    if (note)
3207117404Skan			      REG_NOTES (x)
3208117404Skan			        = gen_rtx_EXPR_LIST (REG_EH_REGION,
3209117404Skan						     XEXP (note, 0),
3210117404Skan						     REG_NOTES (x));
321196263Sobrien
3212132727Skan			    if (x != BB_END (bb) && eh_edge)
321396263Sobrien			      {
321496263Sobrien				edge nfte, nehe;
321596263Sobrien				int flags;
321696263Sobrien
321796263Sobrien				nfte = split_block (bb, x);
3218117404Skan				flags = (eh_edge->flags
3219117404Skan					 & (EDGE_EH | EDGE_ABNORMAL));
3220169699Skan				if (CALL_P (x))
322196263Sobrien				  flags |= EDGE_ABNORMAL_CALL;
322296263Sobrien				nehe = make_edge (nfte->src, eh_edge->dest,
322396263Sobrien						  flags);
322496263Sobrien
322596263Sobrien				nehe->probability = eh_edge->probability;
322696263Sobrien				nfte->probability
322796263Sobrien				  = REG_BR_PROB_BASE - nehe->probability;
322896263Sobrien
322996263Sobrien			        do_cleanup_cfg |= purge_dead_edges (nfte->dest);
323090075Sobrien#ifdef HAVE_conditional_execution
323196263Sobrien				SET_BIT (blocks, nfte->dest->index);
323296263Sobrien				changed = true;
323396263Sobrien#endif
323496263Sobrien				bb = nfte->src;
323596263Sobrien				eh_edge = nehe;
323696263Sobrien			      }
323796263Sobrien			  }
323896263Sobrien
323996263Sobrien		      /* Converting possibly trapping insn to non-trapping is
324096263Sobrien			 possible.  Zap dummy outgoing edges.  */
324196263Sobrien		      do_cleanup_cfg |= purge_dead_edges (bb);
324296263Sobrien		    }
324396263Sobrien
324496263Sobrien#ifdef HAVE_conditional_execution
324590075Sobrien		  /* With conditional execution, we cannot back up the
324690075Sobrien		     live information so easily, since the conditional
324790075Sobrien		     death data structures are not so self-contained.
324890075Sobrien		     So record that we've made a modification to this
324990075Sobrien		     block and update life information at the end.  */
3250117404Skan		  SET_BIT (blocks, bb->index);
325196263Sobrien		  changed = true;
325290075Sobrien
325390075Sobrien		  for (i = 0; i < MAX_INSNS_PER_PEEP2 + 1; ++i)
325490075Sobrien		    peep2_insn_data[i].insn = NULL_RTX;
325590075Sobrien		  peep2_insn_data[peep2_current].insn = PEEP2_EOB;
3256169699Skan		  peep2_current_count = 0;
325790075Sobrien#else
325890075Sobrien		  /* Back up lifetime information past the end of the
325990075Sobrien		     newly created sequence.  */
326090075Sobrien		  if (++i >= MAX_INSNS_PER_PEEP2 + 1)
326190075Sobrien		    i = 0;
326290075Sobrien		  COPY_REG_SET (live, peep2_insn_data[i].live_before);
326390075Sobrien
326490075Sobrien		  /* Update life information for the new sequence.  */
326596263Sobrien		  x = try;
326690075Sobrien		  do
326790075Sobrien		    {
326896263Sobrien		      if (INSN_P (x))
326990075Sobrien			{
327090075Sobrien			  if (--i < 0)
327190075Sobrien			    i = MAX_INSNS_PER_PEEP2;
3272169699Skan			  if (peep2_current_count < MAX_INSNS_PER_PEEP2
3273169699Skan			      && peep2_insn_data[i].insn == NULL_RTX)
3274169699Skan			    peep2_current_count++;
327596263Sobrien			  peep2_insn_data[i].insn = x;
327696263Sobrien			  propagate_one_insn (pbi, x);
327790075Sobrien			  COPY_REG_SET (peep2_insn_data[i].live_before, live);
327890075Sobrien			}
327996263Sobrien		      x = PREV_INSN (x);
328090075Sobrien		    }
328196263Sobrien		  while (x != prev);
328290075Sobrien
328390075Sobrien		  /* ??? Should verify that LIVE now matches what we
328490075Sobrien		     had before the new sequence.  */
328590075Sobrien
328690075Sobrien		  peep2_current = i;
328752284Sobrien#endif
328896263Sobrien
328996263Sobrien		  /* If we generated a jump instruction, it won't have
329096263Sobrien		     JUMP_LABEL set.  Recompute after we're done.  */
329196263Sobrien		  for (x = try; x != before_try; x = PREV_INSN (x))
3292169699Skan		    if (JUMP_P (x))
329396263Sobrien		      {
329496263Sobrien		        do_rebuild_jump_labels = true;
329596263Sobrien			break;
329696263Sobrien		      }
329752284Sobrien		}
329852284Sobrien	    }
329990075Sobrien
3300132727Skan	  if (insn == BB_HEAD (bb))
330190075Sobrien	    break;
330252284Sobrien	}
330352284Sobrien
3304169699Skan      /* Some peepholes can decide the don't need one or more of their
3305169699Skan	 inputs.  If this happens, local life update is not enough.  */
3306169699Skan      EXECUTE_IF_AND_COMPL_IN_BITMAP (bb->il.rtl->global_live_at_start, live,
3307169699Skan				      0, j, rsi)
3308169699Skan	{
3309169699Skan	  do_global_life_update = true;
3310169699Skan	  break;
3311169699Skan	}
3312169699Skan
331390075Sobrien      free_propagate_block_info (pbi);
331452284Sobrien    }
331590075Sobrien
331690075Sobrien  for (i = 0; i < MAX_INSNS_PER_PEEP2 + 1; ++i)
331790075Sobrien    FREE_REG_SET (peep2_insn_data[i].live_before);
331890075Sobrien  FREE_REG_SET (live);
331990075Sobrien
332096263Sobrien  if (do_rebuild_jump_labels)
332196263Sobrien    rebuild_jump_labels (get_insns ());
332296263Sobrien
332396263Sobrien  /* If we eliminated EH edges, we may be able to merge blocks.  Further,
332496263Sobrien     we've changed global life since exception handlers are no longer
332596263Sobrien     reachable.  */
332696263Sobrien  if (do_cleanup_cfg)
332796263Sobrien    {
332896263Sobrien      cleanup_cfg (0);
3329169699Skan      do_global_life_update = true;
333096263Sobrien    }
3331169699Skan  if (do_global_life_update)
3332169699Skan    update_life_info (0, UPDATE_LIFE_GLOBAL_RM_NOTES, PROP_DEATH_NOTES);
333390075Sobrien#ifdef HAVE_conditional_execution
333496263Sobrien  else
333596263Sobrien    {
333696263Sobrien      count_or_remove_death_notes (blocks, 1);
333796263Sobrien      update_life_info (blocks, UPDATE_LIFE_LOCAL, PROP_DEATH_NOTES);
333896263Sobrien    }
333990075Sobrien  sbitmap_free (blocks);
334090075Sobrien#endif
334152284Sobrien}
334290075Sobrien#endif /* HAVE_peephole2 */
3343117404Skan
3344117404Skan/* Common predicates for use with define_bypass.  */
3345117404Skan
3346117404Skan/* True if the dependency between OUT_INSN and IN_INSN is on the store
3347117404Skan   data not the address operand(s) of the store.  IN_INSN must be
3348117404Skan   single_set.  OUT_INSN must be either a single_set or a PARALLEL with
3349117404Skan   SETs inside.  */
3350117404Skan
3351117404Skanint
3352132727Skanstore_data_bypass_p (rtx out_insn, rtx in_insn)
3353117404Skan{
3354117404Skan  rtx out_set, in_set;
3355117404Skan
3356117404Skan  in_set = single_set (in_insn);
3357169699Skan  gcc_assert (in_set);
3358117404Skan
3359169699Skan  if (!MEM_P (SET_DEST (in_set)))
3360117404Skan    return false;
3361117404Skan
3362117404Skan  out_set = single_set (out_insn);
3363117404Skan  if (out_set)
3364117404Skan    {
3365117404Skan      if (reg_mentioned_p (SET_DEST (out_set), SET_DEST (in_set)))
3366117404Skan	return false;
3367117404Skan    }
3368117404Skan  else
3369117404Skan    {
3370117404Skan      rtx out_pat;
3371117404Skan      int i;
3372117404Skan
3373117404Skan      out_pat = PATTERN (out_insn);
3374169699Skan      gcc_assert (GET_CODE (out_pat) == PARALLEL);
3375117404Skan
3376117404Skan      for (i = 0; i < XVECLEN (out_pat, 0); i++)
3377117404Skan	{
3378117404Skan	  rtx exp = XVECEXP (out_pat, 0, i);
3379117404Skan
3380117404Skan	  if (GET_CODE (exp) == CLOBBER)
3381117404Skan	    continue;
3382117404Skan
3383169699Skan	  gcc_assert (GET_CODE (exp) == SET);
3384117404Skan
3385117404Skan	  if (reg_mentioned_p (SET_DEST (exp), SET_DEST (in_set)))
3386117404Skan	    return false;
3387117404Skan	}
3388117404Skan    }
3389117404Skan
3390117404Skan  return true;
3391117404Skan}
3392117404Skan
3393117404Skan/* True if the dependency between OUT_INSN and IN_INSN is in the IF_THEN_ELSE
3394117404Skan   condition, and not the THEN or ELSE branch.  OUT_INSN may be either a single
3395117404Skan   or multiple set; IN_INSN should be single_set for truth, but for convenience
3396117404Skan   of insn categorization may be any JUMP or CALL insn.  */
3397117404Skan
3398117404Skanint
3399132727Skanif_test_bypass_p (rtx out_insn, rtx in_insn)
3400117404Skan{
3401117404Skan  rtx out_set, in_set;
3402117404Skan
3403117404Skan  in_set = single_set (in_insn);
3404117404Skan  if (! in_set)
3405117404Skan    {
3406169699Skan      gcc_assert (JUMP_P (in_insn) || CALL_P (in_insn));
3407169699Skan      return false;
3408117404Skan    }
3409117404Skan
3410117404Skan  if (GET_CODE (SET_SRC (in_set)) != IF_THEN_ELSE)
3411117404Skan    return false;
3412117404Skan  in_set = SET_SRC (in_set);
3413117404Skan
3414117404Skan  out_set = single_set (out_insn);
3415117404Skan  if (out_set)
3416117404Skan    {
3417117404Skan      if (reg_mentioned_p (SET_DEST (out_set), XEXP (in_set, 1))
3418117404Skan	  || reg_mentioned_p (SET_DEST (out_set), XEXP (in_set, 2)))
3419117404Skan	return false;
3420117404Skan    }
3421117404Skan  else
3422117404Skan    {
3423117404Skan      rtx out_pat;
3424117404Skan      int i;
3425117404Skan
3426117404Skan      out_pat = PATTERN (out_insn);
3427169699Skan      gcc_assert (GET_CODE (out_pat) == PARALLEL);
3428117404Skan
3429117404Skan      for (i = 0; i < XVECLEN (out_pat, 0); i++)
3430117404Skan	{
3431117404Skan	  rtx exp = XVECEXP (out_pat, 0, i);
3432117404Skan
3433117404Skan	  if (GET_CODE (exp) == CLOBBER)
3434117404Skan	    continue;
3435117404Skan
3436169699Skan	  gcc_assert (GET_CODE (exp) == SET);
3437117404Skan
3438117404Skan	  if (reg_mentioned_p (SET_DEST (out_set), XEXP (in_set, 1))
3439117404Skan	      || reg_mentioned_p (SET_DEST (out_set), XEXP (in_set, 2)))
3440117404Skan	    return false;
3441117404Skan	}
3442117404Skan    }
3443117404Skan
3444117404Skan  return true;
3445117404Skan}
3446169699Skan
3447169699Skanstatic bool
3448169699Skangate_handle_peephole2 (void)
3449169699Skan{
3450169699Skan  return (optimize > 0 && flag_peephole2);
3451169699Skan}
3452169699Skan
3453169699Skanstatic unsigned int
3454169699Skanrest_of_handle_peephole2 (void)
3455169699Skan{
3456169699Skan#ifdef HAVE_peephole2
3457169699Skan  peephole2_optimize ();
3458169699Skan#endif
3459169699Skan  return 0;
3460169699Skan}
3461169699Skan
3462169699Skanstruct tree_opt_pass pass_peephole2 =
3463169699Skan{
3464169699Skan  "peephole2",                          /* name */
3465169699Skan  gate_handle_peephole2,                /* gate */
3466169699Skan  rest_of_handle_peephole2,             /* execute */
3467169699Skan  NULL,                                 /* sub */
3468169699Skan  NULL,                                 /* next */
3469169699Skan  0,                                    /* static_pass_number */
3470169699Skan  TV_PEEPHOLE2,                         /* tv_id */
3471169699Skan  0,                                    /* properties_required */
3472169699Skan  0,                                    /* properties_provided */
3473169699Skan  0,                                    /* properties_destroyed */
3474169699Skan  0,                                    /* todo_flags_start */
3475169699Skan  TODO_dump_func,                       /* todo_flags_finish */
3476169699Skan  'z'                                   /* letter */
3477169699Skan};
3478169699Skan
3479169699Skanstatic unsigned int
3480169699Skanrest_of_handle_split_all_insns (void)
3481169699Skan{
3482169699Skan  split_all_insns (1);
3483169699Skan  return 0;
3484169699Skan}
3485169699Skan
3486169699Skanstruct tree_opt_pass pass_split_all_insns =
3487169699Skan{
3488169699Skan  "split1",                             /* name */
3489169699Skan  NULL,                                 /* gate */
3490169699Skan  rest_of_handle_split_all_insns,       /* execute */
3491169699Skan  NULL,                                 /* sub */
3492169699Skan  NULL,                                 /* next */
3493169699Skan  0,                                    /* static_pass_number */
3494169699Skan  0,                                    /* tv_id */
3495169699Skan  0,                                    /* properties_required */
3496169699Skan  0,                                    /* properties_provided */
3497169699Skan  0,                                    /* properties_destroyed */
3498169699Skan  0,                                    /* todo_flags_start */
3499169699Skan  TODO_dump_func,                       /* todo_flags_finish */
3500169699Skan  0                                     /* letter */
3501169699Skan};
3502169699Skan
3503169699Skan/* The placement of the splitting that we do for shorten_branches
3504169699Skan   depends on whether regstack is used by the target or not.  */
3505169699Skanstatic bool
3506169699Skangate_do_final_split (void)
3507169699Skan{
3508169699Skan#if defined (HAVE_ATTR_length) && !defined (STACK_REGS)
3509169699Skan  return 1;
3510169699Skan#else
3511169699Skan  return 0;
3512169699Skan#endif
3513169699Skan}
3514169699Skan
3515169699Skanstruct tree_opt_pass pass_split_for_shorten_branches =
3516169699Skan{
3517169699Skan  "split3",                             /* name */
3518169699Skan  gate_do_final_split,                  /* gate */
3519169699Skan  split_all_insns_noflow,               /* execute */
3520169699Skan  NULL,                                 /* sub */
3521169699Skan  NULL,                                 /* next */
3522169699Skan  0,                                    /* static_pass_number */
3523169699Skan  TV_SHORTEN_BRANCH,                    /* tv_id */
3524169699Skan  0,                                    /* properties_required */
3525169699Skan  0,                                    /* properties_provided */
3526169699Skan  0,                                    /* properties_destroyed */
3527169699Skan  0,                                    /* todo_flags_start */
3528169699Skan  TODO_dump_func,                       /* todo_flags_finish */
3529169699Skan  0                                     /* letter */
3530169699Skan};
3531169699Skan
3532169699Skan
3533169699Skanstatic bool
3534169699Skangate_handle_split_before_regstack (void)
3535169699Skan{
3536169699Skan#if defined (HAVE_ATTR_length) && defined (STACK_REGS)
3537169699Skan  /* If flow2 creates new instructions which need splitting
3538169699Skan     and scheduling after reload is not done, they might not be
3539169699Skan     split until final which doesn't allow splitting
3540169699Skan     if HAVE_ATTR_length.  */
3541169699Skan# ifdef INSN_SCHEDULING
3542169699Skan  return (optimize && !flag_schedule_insns_after_reload);
3543169699Skan# else
3544169699Skan  return (optimize);
3545169699Skan# endif
3546169699Skan#else
3547169699Skan  return 0;
3548169699Skan#endif
3549169699Skan}
3550169699Skan
3551169699Skanstruct tree_opt_pass pass_split_before_regstack =
3552169699Skan{
3553169699Skan  "split2",                             /* name */
3554169699Skan  gate_handle_split_before_regstack,    /* gate */
3555169699Skan  rest_of_handle_split_all_insns,       /* execute */
3556169699Skan  NULL,                                 /* sub */
3557169699Skan  NULL,                                 /* next */
3558169699Skan  0,                                    /* static_pass_number */
3559169699Skan  TV_SHORTEN_BRANCH,                    /* tv_id */
3560169699Skan  0,                                    /* properties_required */
3561169699Skan  0,                                    /* properties_provided */
3562169699Skan  0,                                    /* properties_destroyed */
3563169699Skan  0,                                    /* todo_flags_start */
3564169699Skan  TODO_dump_func,                       /* todo_flags_finish */
3565169699Skan  0                                     /* letter */
3566169699Skan};
3567