118334Speter/* Optimize jump instructions, for GNU compiler.
290075Sobrien   Copyright (C) 1987, 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997
3169689Skan   1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
4169689Skan   Free Software Foundation, Inc.
518334Speter
690075SobrienThis file is part of GCC.
718334Speter
890075SobrienGCC is free software; you can redistribute it and/or modify it under
990075Sobrienthe terms of the GNU General Public License as published by the Free
1090075SobrienSoftware Foundation; either version 2, or (at your option) any later
1190075Sobrienversion.
1218334Speter
1390075SobrienGCC is distributed in the hope that it will be useful, but WITHOUT ANY
1490075SobrienWARRANTY; without even the implied warranty of MERCHANTABILITY or
1590075SobrienFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1690075Sobrienfor more details.
1718334Speter
1818334SpeterYou should have received a copy of the GNU General Public License
1990075Sobrienalong with GCC; see the file COPYING.  If not, write to the Free
20169689SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
21169689Skan02110-1301, USA.  */
2218334Speter
2390075Sobrien/* This is the pathetic reminder of old fame of the jump-optimization pass
24169689Skan   of the compiler.  Now it contains basically a set of utility functions to
2590075Sobrien   operate with jumps.
2618334Speter
2718334Speter   Each CODE_LABEL has a count of the times it is used
2818334Speter   stored in the LABEL_NUSES internal field, and each JUMP_INSN
2918334Speter   has one label that it refers to stored in the
3018334Speter   JUMP_LABEL internal field.  With this we can detect labels that
3118334Speter   become unused because of the deletion of all the jumps that
3218334Speter   formerly used them.  The JUMP_LABEL info is sometimes looked
3318334Speter   at by later passes.
3418334Speter
35169689Skan   The subroutines redirect_jump and invert_jump are used
3618334Speter   from other passes as well.  */
3718334Speter
3818334Speter#include "config.h"
3950397Sobrien#include "system.h"
40132718Skan#include "coretypes.h"
41132718Skan#include "tm.h"
4218334Speter#include "rtl.h"
4390075Sobrien#include "tm_p.h"
4418334Speter#include "flags.h"
4518334Speter#include "hard-reg-set.h"
4618334Speter#include "regs.h"
4718334Speter#include "insn-config.h"
4850397Sobrien#include "insn-attr.h"
4950397Sobrien#include "recog.h"
5090075Sobrien#include "function.h"
5118334Speter#include "expr.h"
5218334Speter#include "real.h"
5350397Sobrien#include "except.h"
54132718Skan#include "diagnostic.h"
5550397Sobrien#include "toplev.h"
5690075Sobrien#include "reload.h"
5790075Sobrien#include "predict.h"
58132718Skan#include "timevar.h"
59169689Skan#include "tree-pass.h"
60169689Skan#include "target.h"
6118334Speter
6218334Speter/* Optimize jump y; x: ... y: jumpif... x?
6318334Speter   Don't know if it is worth bothering with.  */
6418334Speter/* Optimize two cases of conditional jump to conditional jump?
6518334Speter   This can never delete any instruction or make anything dead,
6618334Speter   or even change what is live at any point.
6718334Speter   So perhaps let combiner do it.  */
6818334Speter
69132718Skanstatic void init_label_info (rtx);
70132718Skanstatic void mark_all_labels (rtx);
71132718Skanstatic void delete_computation (rtx);
72132718Skanstatic void redirect_exp_1 (rtx *, rtx, rtx, rtx);
73169689Skanstatic int invert_exp_1 (rtx, rtx);
74132718Skanstatic int returnjump_p_1 (rtx *, void *);
75132718Skanstatic void delete_prior_computation (rtx, rtx);
7690075Sobrien
7752284Sobrien/* Alternate entry into the jump optimizer.  This entry point only rebuilds
7852284Sobrien   the JUMP_LABEL field in jumping insns and REG_LABEL notes in non-jumping
7952284Sobrien   instructions.  */
8052284Sobrienvoid
81132718Skanrebuild_jump_labels (rtx f)
8252284Sobrien{
8390075Sobrien  rtx insn;
8418334Speter
85132718Skan  timevar_push (TV_REBUILD_JUMP);
86132718Skan  init_label_info (f);
8790075Sobrien  mark_all_labels (f);
8850397Sobrien
8990075Sobrien  /* Keep track of labels used from static data; we don't track them
9090075Sobrien     closely enough to delete them here, so make sure their reference
9190075Sobrien     count doesn't drop to zero.  */
9218334Speter
9318334Speter  for (insn = forced_labels; insn; insn = XEXP (insn, 1))
94169689Skan    if (LABEL_P (XEXP (insn, 0)))
9590075Sobrien      LABEL_NUSES (XEXP (insn, 0))++;
96132718Skan  timevar_pop (TV_REBUILD_JUMP);
9790075Sobrien}
9890075Sobrien
9990075Sobrien/* Some old code expects exactly one BARRIER as the NEXT_INSN of a
10090075Sobrien   non-fallthru insn.  This is not generally true, as multiple barriers
10190075Sobrien   may have crept in, or the BARRIER may be separated from the last
10290075Sobrien   real insn by one or more NOTEs.
10350397Sobrien
10490075Sobrien   This simple pass moves barriers and removes duplicates so that the
10590075Sobrien   old code is happy.
10690075Sobrien */
107169689Skanunsigned int
108132718Skancleanup_barriers (void)
10990075Sobrien{
11090075Sobrien  rtx insn, next, prev;
11190075Sobrien  for (insn = get_insns (); insn; insn = next)
11218334Speter    {
11390075Sobrien      next = NEXT_INSN (insn);
114169689Skan      if (BARRIER_P (insn))
11518334Speter	{
11690075Sobrien	  prev = prev_nonnote_insn (insn);
117169689Skan	  if (BARRIER_P (prev))
118169689Skan	    delete_insn (insn);
11990075Sobrien	  else if (prev != PREV_INSN (insn))
12090075Sobrien	    reorder_insns (insn, insn, prev);
12118334Speter	}
12218334Speter    }
123169689Skan  return 0;
12490075Sobrien}
125110611Skan
126169689Skanstruct tree_opt_pass pass_cleanup_barriers =
127110611Skan{
128169689Skan  "barriers",                           /* name */
129169689Skan  NULL,                                 /* gate */
130169689Skan  cleanup_barriers,                     /* execute */
131169689Skan  NULL,                                 /* sub */
132169689Skan  NULL,                                 /* next */
133169689Skan  0,                                    /* static_pass_number */
134169689Skan  0,                                    /* tv_id */
135169689Skan  0,                                    /* properties_required */
136169689Skan  0,                                    /* properties_provided */
137169689Skan  0,                                    /* properties_destroyed */
138169689Skan  0,                                    /* todo_flags_start */
139169689Skan  TODO_dump_func,                       /* todo_flags_finish */
140169689Skan  0                                     /* letter */
141169689Skan};
142110611Skan
143169689Skanunsigned int
144169689Skanpurge_line_number_notes (void)
14590075Sobrien{
14690075Sobrien  rtx last_note = 0;
14790075Sobrien  rtx insn;
14818334Speter  /* Delete extraneous line number notes.
14918334Speter     Note that two consecutive notes for different lines are not really
15018334Speter     extraneous.  There should be some indication where that line belonged,
15118334Speter     even if it became empty.  */
15218334Speter
153169689Skan  for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
154169689Skan    if (NOTE_P (insn))
15590075Sobrien      {
15690075Sobrien	if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_FUNCTION_BEG)
15790075Sobrien	  /* Any previous line note was for the prologue; gdb wants a new
15890075Sobrien	     note after the prologue even if it is for the same line.  */
15990075Sobrien	  last_note = NULL_RTX;
16090075Sobrien	else if (NOTE_LINE_NUMBER (insn) >= 0)
16190075Sobrien	  {
16290075Sobrien	    /* Delete this note if it is identical to previous note.  */
16390075Sobrien	    if (last_note
164169689Skan#ifdef USE_MAPPED_LOCATION
165169689Skan		&& NOTE_SOURCE_LOCATION (insn) == NOTE_SOURCE_LOCATION (last_note)
166169689Skan#else
16790075Sobrien		&& NOTE_SOURCE_FILE (insn) == NOTE_SOURCE_FILE (last_note)
168169689Skan		&& NOTE_LINE_NUMBER (insn) == NOTE_LINE_NUMBER (last_note)
169169689Skan#endif
170169689Skan)
17190075Sobrien	      {
17290075Sobrien		delete_related_insns (insn);
17390075Sobrien		continue;
17490075Sobrien	      }
17518334Speter
17690075Sobrien	    last_note = insn;
17790075Sobrien	  }
17890075Sobrien      }
179169689Skan  return 0;
18052284Sobrien}
181169689Skan
182169689Skanstruct tree_opt_pass pass_purge_lineno_notes =
183169689Skan{
184169689Skan  "elnotes",                            /* name */
185169689Skan  NULL,                                 /* gate */
186169689Skan  purge_line_number_notes,              /* execute */
187169689Skan  NULL,                                 /* sub */
188169689Skan  NULL,                                 /* next */
189169689Skan  0,                                    /* static_pass_number */
190169689Skan  0,                                    /* tv_id */
191169689Skan  0,                                    /* properties_required */
192169689Skan  0,                                    /* properties_provided */
193169689Skan  0,                                    /* properties_destroyed */
194169689Skan  0,                                    /* todo_flags_start */
195169689Skan  TODO_dump_func,                       /* todo_flags_finish */
196169689Skan  0                                     /* letter */
197169689Skan};
198169689Skan
19952284Sobrien
20052284Sobrien/* Initialize LABEL_NUSES and JUMP_LABEL fields.  Delete any REG_LABEL
20152284Sobrien   notes whose labels don't occur in the insn any more.  Returns the
20252284Sobrien   largest INSN_UID found.  */
203132718Skanstatic void
204132718Skaninit_label_info (rtx f)
20552284Sobrien{
20652284Sobrien  rtx insn;
20752284Sobrien
20852284Sobrien  for (insn = f; insn; insn = NEXT_INSN (insn))
209169689Skan    if (LABEL_P (insn))
210132718Skan      LABEL_NUSES (insn) = (LABEL_PRESERVE_P (insn) != 0);
211169689Skan    else if (JUMP_P (insn))
212132718Skan      JUMP_LABEL (insn) = 0;
213169689Skan    else if (NONJUMP_INSN_P (insn) || CALL_P (insn))
214132718Skan      {
215132718Skan	rtx note, next;
21652284Sobrien
217132718Skan	for (note = REG_NOTES (insn); note; note = next)
218132718Skan	  {
219132718Skan	    next = XEXP (note, 1);
220132718Skan	    if (REG_NOTE_KIND (note) == REG_LABEL
221132718Skan		&& ! reg_mentioned_p (XEXP (note, 0), PATTERN (insn)))
222132718Skan	      remove_note (insn, note);
223132718Skan	  }
224132718Skan      }
22552284Sobrien}
22652284Sobrien
22752284Sobrien/* Mark the label each jump jumps to.
22890075Sobrien   Combine consecutive labels, and count uses of labels.  */
22952284Sobrien
23052284Sobrienstatic void
231132718Skanmark_all_labels (rtx f)
23252284Sobrien{
23352284Sobrien  rtx insn;
23452284Sobrien
23552284Sobrien  for (insn = f; insn; insn = NEXT_INSN (insn))
23690075Sobrien    if (INSN_P (insn))
23752284Sobrien      {
23890075Sobrien	mark_jump_label (PATTERN (insn), insn, 0);
239169689Skan	if (! INSN_DELETED_P (insn) && JUMP_P (insn))
24090075Sobrien	  {
24190075Sobrien	    /* When we know the LABEL_REF contained in a REG used in
24290075Sobrien	       an indirect jump, we'll have a REG_LABEL note so that
24390075Sobrien	       flow can tell where it's going.  */
24490075Sobrien	    if (JUMP_LABEL (insn) == 0)
24552284Sobrien	      {
24690075Sobrien		rtx label_note = find_reg_note (insn, REG_LABEL, NULL_RTX);
24790075Sobrien		if (label_note)
24890075Sobrien		  {
24990075Sobrien		    /* But a LABEL_REF around the REG_LABEL note, so
25090075Sobrien		       that we can canonicalize it.  */
251169689Skan		    rtx label_ref = gen_rtx_LABEL_REF (Pmode,
25290075Sobrien						       XEXP (label_note, 0));
25390075Sobrien
25490075Sobrien		    mark_jump_label (label_ref, insn, 0);
25590075Sobrien		    XEXP (label_note, 0) = XEXP (label_ref, 0);
25690075Sobrien		    JUMP_LABEL (insn) = XEXP (label_note, 0);
25790075Sobrien		  }
25852284Sobrien	      }
25952284Sobrien	  }
26052284Sobrien      }
26152284Sobrien}
26218334Speter
263169689Skan/* Move all block-beg, block-end and loop-beg notes between START and END out
264169689Skan   before START.  START and END may be such notes.  Returns the values of the
265169689Skan   new starting and ending insns, which may be different if the original ones
266169689Skan   were such notes.  Return true if there were only such notes and no real
267169689Skan   instructions.  */
26818334Speter
26990075Sobrienbool
270132718Skansqueeze_notes (rtx* startp, rtx* endp)
27118334Speter{
27290075Sobrien  rtx start = *startp;
27390075Sobrien  rtx end = *endp;
27490075Sobrien
27518334Speter  rtx insn;
27618334Speter  rtx next;
27790075Sobrien  rtx last = NULL;
27890075Sobrien  rtx past_end = NEXT_INSN (end);
27918334Speter
28090075Sobrien  for (insn = start; insn != past_end; insn = next)
28118334Speter    {
28218334Speter      next = NEXT_INSN (insn);
283169689Skan      if (NOTE_P (insn)
28418334Speter	  && (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END
285169689Skan	      || NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG))
28618334Speter	{
287169689Skan	  /* BLOCK_BEG or BLOCK_END notes only exist in the `final' pass.  */
288169689Skan	  gcc_assert (NOTE_LINE_NUMBER (insn) != NOTE_INSN_BLOCK_BEG
289169689Skan		      && NOTE_LINE_NUMBER (insn) != NOTE_INSN_BLOCK_END);
290169689Skan
29118334Speter	  if (insn == start)
29218334Speter	    start = next;
29318334Speter	  else
29418334Speter	    {
29518334Speter	      rtx prev = PREV_INSN (insn);
29618334Speter	      PREV_INSN (insn) = PREV_INSN (start);
29718334Speter	      NEXT_INSN (insn) = start;
29818334Speter	      NEXT_INSN (PREV_INSN (insn)) = insn;
29918334Speter	      PREV_INSN (NEXT_INSN (insn)) = insn;
30018334Speter	      NEXT_INSN (prev) = next;
30118334Speter	      PREV_INSN (next) = prev;
30218334Speter	    }
30318334Speter	}
30490075Sobrien      else
30590075Sobrien	last = insn;
30618334Speter    }
30718334Speter
30890075Sobrien  /* There were no real instructions.  */
30990075Sobrien  if (start == past_end)
31090075Sobrien    return true;
31118334Speter
31290075Sobrien  end = last;
31318334Speter
31490075Sobrien  *startp = start;
31590075Sobrien  *endp = end;
31690075Sobrien  return false;
31718334Speter}
31818334Speter
31918334Speter/* Return the label before INSN, or put a new label there.  */
32018334Speter
32118334Speterrtx
322132718Skanget_label_before (rtx insn)
32318334Speter{
32418334Speter  rtx label;
32518334Speter
32618334Speter  /* Find an existing label at this point
32718334Speter     or make a new one if there is none.  */
32818334Speter  label = prev_nonnote_insn (insn);
32918334Speter
330169689Skan  if (label == 0 || !LABEL_P (label))
33118334Speter    {
33218334Speter      rtx prev = PREV_INSN (insn);
33318334Speter
33418334Speter      label = gen_label_rtx ();
33518334Speter      emit_label_after (label, prev);
33618334Speter      LABEL_NUSES (label) = 0;
33718334Speter    }
33818334Speter  return label;
33918334Speter}
34018334Speter
34118334Speter/* Return the label after INSN, or put a new label there.  */
34218334Speter
34318334Speterrtx
344132718Skanget_label_after (rtx insn)
34518334Speter{
34618334Speter  rtx label;
34718334Speter
34818334Speter  /* Find an existing label at this point
34918334Speter     or make a new one if there is none.  */
35018334Speter  label = next_nonnote_insn (insn);
35118334Speter
352169689Skan  if (label == 0 || !LABEL_P (label))
35318334Speter    {
35418334Speter      label = gen_label_rtx ();
35518334Speter      emit_label_after (label, insn);
35618334Speter      LABEL_NUSES (label) = 0;
35718334Speter    }
35818334Speter  return label;
35918334Speter}
36018334Speter
36190075Sobrien/* Given a comparison (CODE ARG0 ARG1), inside an insn, INSN, return a code
36290075Sobrien   of reversed comparison if it is possible to do so.  Otherwise return UNKNOWN.
36390075Sobrien   UNKNOWN may be returned in case we are having CC_MODE compare and we don't
36490075Sobrien   know whether it's source is floating point or integer comparison.  Machine
36590075Sobrien   description should define REVERSIBLE_CC_MODE and REVERSE_CONDITION macros
36690075Sobrien   to help this function avoid overhead in these cases.  */
36790075Sobrienenum rtx_code
368132718Skanreversed_comparison_code_parts (enum rtx_code code, rtx arg0, rtx arg1, rtx insn)
36918334Speter{
37090075Sobrien  enum machine_mode mode;
37118334Speter
37290075Sobrien  /* If this is not actually a comparison, we can't reverse it.  */
373169689Skan  if (GET_RTX_CLASS (code) != RTX_COMPARE
374169689Skan      && GET_RTX_CLASS (code) != RTX_COMM_COMPARE)
37590075Sobrien    return UNKNOWN;
37618334Speter
37790075Sobrien  mode = GET_MODE (arg0);
37890075Sobrien  if (mode == VOIDmode)
37990075Sobrien    mode = GET_MODE (arg1);
38018334Speter
381169689Skan  /* First see if machine description supplies us way to reverse the
382169689Skan     comparison.  Give it priority over everything else to allow
383169689Skan     machine description to do tricks.  */
38490075Sobrien  if (GET_MODE_CLASS (mode) == MODE_CC
38590075Sobrien      && REVERSIBLE_CC_MODE (mode))
38618334Speter    {
38790075Sobrien#ifdef REVERSE_CONDITION
38890075Sobrien      return REVERSE_CONDITION (code, mode);
38990075Sobrien#endif
39090075Sobrien      return reverse_condition (code);
39118334Speter    }
39218334Speter
39390075Sobrien  /* Try a few special cases based on the comparison code.  */
39490075Sobrien  switch (code)
39518334Speter    {
39690075Sobrien    case GEU:
39790075Sobrien    case GTU:
39890075Sobrien    case LEU:
39990075Sobrien    case LTU:
40090075Sobrien    case NE:
40190075Sobrien    case EQ:
40290075Sobrien      /* It is always safe to reverse EQ and NE, even for the floating
403132718Skan	 point.  Similarly the unsigned comparisons are never used for
40490075Sobrien	 floating point so we can reverse them in the default way.  */
40590075Sobrien      return reverse_condition (code);
40690075Sobrien    case ORDERED:
40790075Sobrien    case UNORDERED:
40890075Sobrien    case LTGT:
40990075Sobrien    case UNEQ:
41090075Sobrien      /* In case we already see unordered comparison, we can be sure to
41190075Sobrien	 be dealing with floating point so we don't need any more tests.  */
41290075Sobrien      return reverse_condition_maybe_unordered (code);
41390075Sobrien    case UNLT:
41490075Sobrien    case UNLE:
41590075Sobrien    case UNGT:
41690075Sobrien    case UNGE:
41790075Sobrien      /* We don't have safe way to reverse these yet.  */
41890075Sobrien      return UNKNOWN;
41990075Sobrien    default:
42090075Sobrien      break;
42118334Speter    }
42218334Speter
423132718Skan  if (GET_MODE_CLASS (mode) == MODE_CC || CC0_P (arg0))
42418334Speter    {
42590075Sobrien      rtx prev;
42690075Sobrien      /* Try to search for the comparison to determine the real mode.
42790075Sobrien         This code is expensive, but with sane machine description it
42890075Sobrien         will be never used, since REVERSIBLE_CC_MODE will return true
42990075Sobrien         in all cases.  */
43090075Sobrien      if (! insn)
43190075Sobrien	return UNKNOWN;
43218334Speter
43390075Sobrien      for (prev = prev_nonnote_insn (insn);
434169689Skan	   prev != 0 && !LABEL_P (prev);
43590075Sobrien	   prev = prev_nonnote_insn (prev))
43690075Sobrien	{
43790075Sobrien	  rtx set = set_of (arg0, prev);
43890075Sobrien	  if (set && GET_CODE (set) == SET
43990075Sobrien	      && rtx_equal_p (SET_DEST (set), arg0))
44090075Sobrien	    {
44190075Sobrien	      rtx src = SET_SRC (set);
44252284Sobrien
44390075Sobrien	      if (GET_CODE (src) == COMPARE)
44490075Sobrien		{
44590075Sobrien		  rtx comparison = src;
44690075Sobrien		  arg0 = XEXP (src, 0);
44790075Sobrien		  mode = GET_MODE (arg0);
44890075Sobrien		  if (mode == VOIDmode)
44990075Sobrien		    mode = GET_MODE (XEXP (comparison, 1));
45090075Sobrien		  break;
45190075Sobrien		}
45290075Sobrien	      /* We can get past reg-reg moves.  This may be useful for model
45390075Sobrien	         of i387 comparisons that first move flag registers around.  */
45490075Sobrien	      if (REG_P (src))
45590075Sobrien		{
45690075Sobrien		  arg0 = src;
45790075Sobrien		  continue;
45890075Sobrien		}
45990075Sobrien	    }
46090075Sobrien	  /* If register is clobbered in some ununderstandable way,
46190075Sobrien	     give up.  */
46290075Sobrien	  if (set)
46390075Sobrien	    return UNKNOWN;
46490075Sobrien	}
46590075Sobrien    }
46652284Sobrien
467117395Skan  /* Test for an integer condition, or a floating-point comparison
468117395Skan     in which NaNs can be ignored.  */
46990075Sobrien  if (GET_CODE (arg0) == CONST_INT
47090075Sobrien      || (GET_MODE (arg0) != VOIDmode
47190075Sobrien	  && GET_MODE_CLASS (mode) != MODE_CC
472117395Skan	  && !HONOR_NANS (mode)))
47390075Sobrien    return reverse_condition (code);
47418334Speter
47590075Sobrien  return UNKNOWN;
47690075Sobrien}
47718334Speter
478132718Skan/* A wrapper around the previous function to take COMPARISON as rtx
47990075Sobrien   expression.  This simplifies many callers.  */
48090075Sobrienenum rtx_code
481132718Skanreversed_comparison_code (rtx comparison, rtx insn)
48290075Sobrien{
483169689Skan  if (!COMPARISON_P (comparison))
48490075Sobrien    return UNKNOWN;
48590075Sobrien  return reversed_comparison_code_parts (GET_CODE (comparison),
48690075Sobrien					 XEXP (comparison, 0),
48790075Sobrien					 XEXP (comparison, 1), insn);
48818334Speter}
489169689Skan
490169689Skan/* Return comparison with reversed code of EXP.
491169689Skan   Return NULL_RTX in case we fail to do the reversal.  */
492169689Skanrtx
493169689Skanreversed_comparison (rtx exp, enum machine_mode mode)
494169689Skan{
495169689Skan  enum rtx_code reversed_code = reversed_comparison_code (exp, NULL_RTX);
496169689Skan  if (reversed_code == UNKNOWN)
497169689Skan    return NULL_RTX;
498169689Skan  else
499169689Skan    return simplify_gen_relational (reversed_code, mode, VOIDmode,
500169689Skan                                    XEXP (exp, 0), XEXP (exp, 1));
501169689Skan}
502169689Skan
50390075Sobrien
50490075Sobrien/* Given an rtx-code for a comparison, return the code for the negated
50590075Sobrien   comparison.  If no such code exists, return UNKNOWN.
50618334Speter
50790075Sobrien   WATCH OUT!  reverse_condition is not safe to use on a jump that might
50890075Sobrien   be acting on the results of an IEEE floating point comparison, because
50990075Sobrien   of the special treatment of non-signaling nans in comparisons.
51090075Sobrien   Use reversed_comparison_code instead.  */
51118334Speter
51218334Speterenum rtx_code
513132718Skanreverse_condition (enum rtx_code code)
51418334Speter{
51518334Speter  switch (code)
51618334Speter    {
51718334Speter    case EQ:
51818334Speter      return NE;
51918334Speter    case NE:
52018334Speter      return EQ;
52118334Speter    case GT:
52218334Speter      return LE;
52318334Speter    case GE:
52418334Speter      return LT;
52518334Speter    case LT:
52618334Speter      return GE;
52718334Speter    case LE:
52818334Speter      return GT;
52918334Speter    case GTU:
53018334Speter      return LEU;
53118334Speter    case GEU:
53218334Speter      return LTU;
53318334Speter    case LTU:
53418334Speter      return GEU;
53518334Speter    case LEU:
53618334Speter      return GTU;
53790075Sobrien    case UNORDERED:
53890075Sobrien      return ORDERED;
53990075Sobrien    case ORDERED:
54090075Sobrien      return UNORDERED;
54118334Speter
54290075Sobrien    case UNLT:
54390075Sobrien    case UNLE:
54490075Sobrien    case UNGT:
54590075Sobrien    case UNGE:
54690075Sobrien    case UNEQ:
54790075Sobrien    case LTGT:
54890075Sobrien      return UNKNOWN;
54990075Sobrien
55018334Speter    default:
551169689Skan      gcc_unreachable ();
55218334Speter    }
55318334Speter}
55418334Speter
55590075Sobrien/* Similar, but we're allowed to generate unordered comparisons, which
55690075Sobrien   makes it safe for IEEE floating-point.  Of course, we have to recognize
55790075Sobrien   that the target will support them too...  */
55890075Sobrien
55990075Sobrienenum rtx_code
560132718Skanreverse_condition_maybe_unordered (enum rtx_code code)
56190075Sobrien{
56290075Sobrien  switch (code)
56390075Sobrien    {
56490075Sobrien    case EQ:
56590075Sobrien      return NE;
56690075Sobrien    case NE:
56790075Sobrien      return EQ;
56890075Sobrien    case GT:
56990075Sobrien      return UNLE;
57090075Sobrien    case GE:
57190075Sobrien      return UNLT;
57290075Sobrien    case LT:
57390075Sobrien      return UNGE;
57490075Sobrien    case LE:
57590075Sobrien      return UNGT;
57690075Sobrien    case LTGT:
57790075Sobrien      return UNEQ;
57890075Sobrien    case UNORDERED:
57990075Sobrien      return ORDERED;
58090075Sobrien    case ORDERED:
58190075Sobrien      return UNORDERED;
58290075Sobrien    case UNLT:
58390075Sobrien      return GE;
58490075Sobrien    case UNLE:
58590075Sobrien      return GT;
58690075Sobrien    case UNGT:
58790075Sobrien      return LE;
58890075Sobrien    case UNGE:
58990075Sobrien      return LT;
59090075Sobrien    case UNEQ:
59190075Sobrien      return LTGT;
59290075Sobrien
59390075Sobrien    default:
594169689Skan      gcc_unreachable ();
59590075Sobrien    }
59690075Sobrien}
59790075Sobrien
59818334Speter/* Similar, but return the code when two operands of a comparison are swapped.
59918334Speter   This IS safe for IEEE floating-point.  */
60018334Speter
60118334Speterenum rtx_code
602132718Skanswap_condition (enum rtx_code code)
60318334Speter{
60418334Speter  switch (code)
60518334Speter    {
60618334Speter    case EQ:
60718334Speter    case NE:
60890075Sobrien    case UNORDERED:
60990075Sobrien    case ORDERED:
61090075Sobrien    case UNEQ:
61190075Sobrien    case LTGT:
61218334Speter      return code;
61318334Speter
61418334Speter    case GT:
61518334Speter      return LT;
61618334Speter    case GE:
61718334Speter      return LE;
61818334Speter    case LT:
61918334Speter      return GT;
62018334Speter    case LE:
62118334Speter      return GE;
62218334Speter    case GTU:
62318334Speter      return LTU;
62418334Speter    case GEU:
62518334Speter      return LEU;
62618334Speter    case LTU:
62718334Speter      return GTU;
62818334Speter    case LEU:
62918334Speter      return GEU;
63090075Sobrien    case UNLT:
63190075Sobrien      return UNGT;
63290075Sobrien    case UNLE:
63390075Sobrien      return UNGE;
63490075Sobrien    case UNGT:
63590075Sobrien      return UNLT;
63690075Sobrien    case UNGE:
63790075Sobrien      return UNLE;
63818334Speter
63918334Speter    default:
640169689Skan      gcc_unreachable ();
64118334Speter    }
64218334Speter}
64318334Speter
64418334Speter/* Given a comparison CODE, return the corresponding unsigned comparison.
64518334Speter   If CODE is an equality comparison or already an unsigned comparison,
64618334Speter   CODE is returned.  */
64718334Speter
64818334Speterenum rtx_code
649132718Skanunsigned_condition (enum rtx_code code)
65018334Speter{
65118334Speter  switch (code)
65218334Speter    {
65318334Speter    case EQ:
65418334Speter    case NE:
65518334Speter    case GTU:
65618334Speter    case GEU:
65718334Speter    case LTU:
65818334Speter    case LEU:
65918334Speter      return code;
66018334Speter
66118334Speter    case GT:
66218334Speter      return GTU;
66318334Speter    case GE:
66418334Speter      return GEU;
66518334Speter    case LT:
66618334Speter      return LTU;
66718334Speter    case LE:
66818334Speter      return LEU;
66918334Speter
67018334Speter    default:
671169689Skan      gcc_unreachable ();
67218334Speter    }
67318334Speter}
67418334Speter
67518334Speter/* Similarly, return the signed version of a comparison.  */
67618334Speter
67718334Speterenum rtx_code
678132718Skansigned_condition (enum rtx_code code)
67918334Speter{
68018334Speter  switch (code)
68118334Speter    {
68218334Speter    case EQ:
68318334Speter    case NE:
68418334Speter    case GT:
68518334Speter    case GE:
68618334Speter    case LT:
68718334Speter    case LE:
68818334Speter      return code;
68918334Speter
69018334Speter    case GTU:
69118334Speter      return GT;
69218334Speter    case GEU:
69318334Speter      return GE;
69418334Speter    case LTU:
69518334Speter      return LT;
69618334Speter    case LEU:
69718334Speter      return LE;
69818334Speter
69918334Speter    default:
700169689Skan      gcc_unreachable ();
70118334Speter    }
70218334Speter}
70318334Speter
704117395Skan/* Return nonzero if CODE1 is more strict than CODE2, i.e., if the
70518334Speter   truth of CODE1 implies the truth of CODE2.  */
70618334Speter
70718334Speterint
708132718Skancomparison_dominates_p (enum rtx_code code1, enum rtx_code code2)
70918334Speter{
71090075Sobrien  /* UNKNOWN comparison codes can happen as a result of trying to revert
71190075Sobrien     comparison codes.
71290075Sobrien     They can't match anything, so we have to reject them here.  */
71390075Sobrien  if (code1 == UNKNOWN || code2 == UNKNOWN)
71490075Sobrien    return 0;
71590075Sobrien
71618334Speter  if (code1 == code2)
71718334Speter    return 1;
71818334Speter
71918334Speter  switch (code1)
72018334Speter    {
72190075Sobrien    case UNEQ:
72290075Sobrien      if (code2 == UNLE || code2 == UNGE)
72390075Sobrien	return 1;
72490075Sobrien      break;
72590075Sobrien
72618334Speter    case EQ:
72790075Sobrien      if (code2 == LE || code2 == LEU || code2 == GE || code2 == GEU
72890075Sobrien	  || code2 == ORDERED)
72918334Speter	return 1;
73018334Speter      break;
73118334Speter
73290075Sobrien    case UNLT:
73390075Sobrien      if (code2 == UNLE || code2 == NE)
73490075Sobrien	return 1;
73590075Sobrien      break;
73690075Sobrien
73718334Speter    case LT:
73890075Sobrien      if (code2 == LE || code2 == NE || code2 == ORDERED || code2 == LTGT)
73918334Speter	return 1;
74018334Speter      break;
74118334Speter
74290075Sobrien    case UNGT:
74390075Sobrien      if (code2 == UNGE || code2 == NE)
74490075Sobrien	return 1;
74590075Sobrien      break;
74690075Sobrien
74718334Speter    case GT:
74890075Sobrien      if (code2 == GE || code2 == NE || code2 == ORDERED || code2 == LTGT)
74918334Speter	return 1;
75018334Speter      break;
75118334Speter
75290075Sobrien    case GE:
75390075Sobrien    case LE:
75490075Sobrien      if (code2 == ORDERED)
75590075Sobrien	return 1;
75690075Sobrien      break;
75790075Sobrien
75890075Sobrien    case LTGT:
75990075Sobrien      if (code2 == NE || code2 == ORDERED)
76090075Sobrien	return 1;
76190075Sobrien      break;
76290075Sobrien
76318334Speter    case LTU:
76418334Speter      if (code2 == LEU || code2 == NE)
76518334Speter	return 1;
76618334Speter      break;
76718334Speter
76818334Speter    case GTU:
76918334Speter      if (code2 == GEU || code2 == NE)
77018334Speter	return 1;
77118334Speter      break;
77290075Sobrien
77390075Sobrien    case UNORDERED:
77490075Sobrien      if (code2 == NE || code2 == UNEQ || code2 == UNLE || code2 == UNLT
77590075Sobrien	  || code2 == UNGE || code2 == UNGT)
77690075Sobrien	return 1;
77790075Sobrien      break;
77890075Sobrien
77950397Sobrien    default:
78050397Sobrien      break;
78118334Speter    }
78218334Speter
78318334Speter  return 0;
78418334Speter}
78518334Speter
78618334Speter/* Return 1 if INSN is an unconditional jump and nothing else.  */
78718334Speter
78818334Speterint
789132718Skansimplejump_p (rtx insn)
79018334Speter{
791169689Skan  return (JUMP_P (insn)
79218334Speter	  && GET_CODE (PATTERN (insn)) == SET
79318334Speter	  && GET_CODE (SET_DEST (PATTERN (insn))) == PC
79418334Speter	  && GET_CODE (SET_SRC (PATTERN (insn))) == LABEL_REF);
79518334Speter}
796117395Skan
79718334Speter/* Return nonzero if INSN is a (possibly) conditional jump
79890075Sobrien   and nothing more.
79918334Speter
800169689Skan   Use of this function is deprecated, since we need to support combined
80190075Sobrien   branch and compare insns.  Use any_condjump_p instead whenever possible.  */
80290075Sobrien
80318334Speterint
804132718Skancondjump_p (rtx insn)
80518334Speter{
80690075Sobrien  rtx x = PATTERN (insn);
80790075Sobrien
80890075Sobrien  if (GET_CODE (x) != SET
80990075Sobrien      || GET_CODE (SET_DEST (x)) != PC)
81018334Speter    return 0;
81190075Sobrien
81290075Sobrien  x = SET_SRC (x);
81390075Sobrien  if (GET_CODE (x) == LABEL_REF)
81418334Speter    return 1;
81590075Sobrien  else
81690075Sobrien    return (GET_CODE (x) == IF_THEN_ELSE
81790075Sobrien	    && ((GET_CODE (XEXP (x, 2)) == PC
81890075Sobrien		 && (GET_CODE (XEXP (x, 1)) == LABEL_REF
81990075Sobrien		     || GET_CODE (XEXP (x, 1)) == RETURN))
82090075Sobrien		|| (GET_CODE (XEXP (x, 1)) == PC
82190075Sobrien		    && (GET_CODE (XEXP (x, 2)) == LABEL_REF
82290075Sobrien			|| GET_CODE (XEXP (x, 2)) == RETURN))));
82318334Speter}
82418334Speter
82590075Sobrien/* Return nonzero if INSN is a (possibly) conditional jump inside a
82690075Sobrien   PARALLEL.
82718334Speter
82890075Sobrien   Use this function is deprecated, since we need to support combined
82990075Sobrien   branch and compare insns.  Use any_condjump_p instead whenever possible.  */
83090075Sobrien
83118334Speterint
832132718Skancondjump_in_parallel_p (rtx insn)
83318334Speter{
83490075Sobrien  rtx x = PATTERN (insn);
83518334Speter
83618334Speter  if (GET_CODE (x) != PARALLEL)
83718334Speter    return 0;
83818334Speter  else
83918334Speter    x = XVECEXP (x, 0, 0);
84018334Speter
84118334Speter  if (GET_CODE (x) != SET)
84218334Speter    return 0;
84318334Speter  if (GET_CODE (SET_DEST (x)) != PC)
84418334Speter    return 0;
84518334Speter  if (GET_CODE (SET_SRC (x)) == LABEL_REF)
84618334Speter    return 1;
84718334Speter  if (GET_CODE (SET_SRC (x)) != IF_THEN_ELSE)
84818334Speter    return 0;
84918334Speter  if (XEXP (SET_SRC (x), 2) == pc_rtx
85018334Speter      && (GET_CODE (XEXP (SET_SRC (x), 1)) == LABEL_REF
85118334Speter	  || GET_CODE (XEXP (SET_SRC (x), 1)) == RETURN))
85218334Speter    return 1;
85318334Speter  if (XEXP (SET_SRC (x), 1) == pc_rtx
85418334Speter      && (GET_CODE (XEXP (SET_SRC (x), 2)) == LABEL_REF
85518334Speter	  || GET_CODE (XEXP (SET_SRC (x), 2)) == RETURN))
85618334Speter    return 1;
85718334Speter  return 0;
85818334Speter}
85918334Speter
86090075Sobrien/* Return set of PC, otherwise NULL.  */
86190075Sobrien
86290075Sobrienrtx
863132718Skanpc_set (rtx insn)
86490075Sobrien{
86590075Sobrien  rtx pat;
866169689Skan  if (!JUMP_P (insn))
86790075Sobrien    return NULL_RTX;
86890075Sobrien  pat = PATTERN (insn);
86990075Sobrien
87090075Sobrien  /* The set is allowed to appear either as the insn pattern or
87190075Sobrien     the first set in a PARALLEL.  */
87290075Sobrien  if (GET_CODE (pat) == PARALLEL)
87390075Sobrien    pat = XVECEXP (pat, 0, 0);
87490075Sobrien  if (GET_CODE (pat) == SET && GET_CODE (SET_DEST (pat)) == PC)
87590075Sobrien    return pat;
87690075Sobrien
87790075Sobrien  return NULL_RTX;
87890075Sobrien}
87990075Sobrien
88090075Sobrien/* Return true when insn is an unconditional direct jump,
88190075Sobrien   possibly bundled inside a PARALLEL.  */
88290075Sobrien
88390075Sobrienint
884132718Skanany_uncondjump_p (rtx insn)
88590075Sobrien{
88690075Sobrien  rtx x = pc_set (insn);
88790075Sobrien  if (!x)
88890075Sobrien    return 0;
88990075Sobrien  if (GET_CODE (SET_SRC (x)) != LABEL_REF)
89090075Sobrien    return 0;
891169689Skan  if (find_reg_note (insn, REG_NON_LOCAL_GOTO, NULL_RTX))
892169689Skan    return 0;
89390075Sobrien  return 1;
89490075Sobrien}
89590075Sobrien
89690075Sobrien/* Return true when insn is a conditional jump.  This function works for
89790075Sobrien   instructions containing PC sets in PARALLELs.  The instruction may have
89890075Sobrien   various other effects so before removing the jump you must verify
89990075Sobrien   onlyjump_p.
90090075Sobrien
90190075Sobrien   Note that unlike condjump_p it returns false for unconditional jumps.  */
90290075Sobrien
90390075Sobrienint
904132718Skanany_condjump_p (rtx insn)
90590075Sobrien{
90690075Sobrien  rtx x = pc_set (insn);
90790075Sobrien  enum rtx_code a, b;
90890075Sobrien
90990075Sobrien  if (!x)
91090075Sobrien    return 0;
91190075Sobrien  if (GET_CODE (SET_SRC (x)) != IF_THEN_ELSE)
91290075Sobrien    return 0;
91390075Sobrien
91490075Sobrien  a = GET_CODE (XEXP (SET_SRC (x), 1));
91590075Sobrien  b = GET_CODE (XEXP (SET_SRC (x), 2));
91690075Sobrien
91790075Sobrien  return ((b == PC && (a == LABEL_REF || a == RETURN))
91890075Sobrien	  || (a == PC && (b == LABEL_REF || b == RETURN)));
91990075Sobrien}
92090075Sobrien
92152284Sobrien/* Return the label of a conditional jump.  */
92252284Sobrien
92352284Sobrienrtx
924132718Skancondjump_label (rtx insn)
92552284Sobrien{
92690075Sobrien  rtx x = pc_set (insn);
92752284Sobrien
92890075Sobrien  if (!x)
92952284Sobrien    return NULL_RTX;
93052284Sobrien  x = SET_SRC (x);
93152284Sobrien  if (GET_CODE (x) == LABEL_REF)
93252284Sobrien    return x;
93352284Sobrien  if (GET_CODE (x) != IF_THEN_ELSE)
93452284Sobrien    return NULL_RTX;
93552284Sobrien  if (XEXP (x, 2) == pc_rtx && GET_CODE (XEXP (x, 1)) == LABEL_REF)
93652284Sobrien    return XEXP (x, 1);
93752284Sobrien  if (XEXP (x, 1) == pc_rtx && GET_CODE (XEXP (x, 2)) == LABEL_REF)
93852284Sobrien    return XEXP (x, 2);
93952284Sobrien  return NULL_RTX;
94052284Sobrien}
94152284Sobrien
94252284Sobrien/* Return true if INSN is a (possibly conditional) return insn.  */
94352284Sobrien
94452284Sobrienstatic int
945132718Skanreturnjump_p_1 (rtx *loc, void *data ATTRIBUTE_UNUSED)
94652284Sobrien{
94752284Sobrien  rtx x = *loc;
94890075Sobrien
94990075Sobrien  return x && (GET_CODE (x) == RETURN
95090075Sobrien	       || (GET_CODE (x) == SET && SET_IS_RETURN_P (x)));
95152284Sobrien}
95252284Sobrien
95352284Sobrienint
954132718Skanreturnjump_p (rtx insn)
95552284Sobrien{
956169689Skan  if (!JUMP_P (insn))
95790075Sobrien    return 0;
95852284Sobrien  return for_each_rtx (&PATTERN (insn), returnjump_p_1, NULL);
95952284Sobrien}
96052284Sobrien
96190075Sobrien/* Return true if INSN is a jump that only transfers control and
96290075Sobrien   nothing more.  */
96390075Sobrien
96490075Sobrienint
965132718Skanonlyjump_p (rtx insn)
96690075Sobrien{
96790075Sobrien  rtx set;
96890075Sobrien
969169689Skan  if (!JUMP_P (insn))
97090075Sobrien    return 0;
97190075Sobrien
97290075Sobrien  set = single_set (insn);
97390075Sobrien  if (set == NULL)
97490075Sobrien    return 0;
97590075Sobrien  if (GET_CODE (SET_DEST (set)) != PC)
97690075Sobrien    return 0;
97790075Sobrien  if (side_effects_p (SET_SRC (set)))
97890075Sobrien    return 0;
97990075Sobrien
98090075Sobrien  return 1;
98190075Sobrien}
98290075Sobrien
98352284Sobrien#ifdef HAVE_cc0
98452284Sobrien
985117395Skan/* Return nonzero if X is an RTX that only sets the condition codes
98690075Sobrien   and has no side effects.  */
98790075Sobrien
98890075Sobrienint
989132718Skanonly_sets_cc0_p (rtx x)
99090075Sobrien{
99190075Sobrien  if (! x)
99290075Sobrien    return 0;
99390075Sobrien
99490075Sobrien  if (INSN_P (x))
99590075Sobrien    x = PATTERN (x);
99690075Sobrien
99790075Sobrien  return sets_cc0_p (x) == 1 && ! side_effects_p (x);
99890075Sobrien}
99990075Sobrien
100018334Speter/* Return 1 if X is an RTX that does nothing but set the condition codes
100118334Speter   and CLOBBER or USE registers.
100218334Speter   Return -1 if X does explicitly set the condition codes,
100318334Speter   but also does other things.  */
100418334Speter
100518334Speterint
1006132718Skansets_cc0_p (rtx x)
100718334Speter{
100890075Sobrien  if (! x)
100990075Sobrien    return 0;
101090075Sobrien
101190075Sobrien  if (INSN_P (x))
101290075Sobrien    x = PATTERN (x);
101390075Sobrien
101418334Speter  if (GET_CODE (x) == SET && SET_DEST (x) == cc0_rtx)
101518334Speter    return 1;
101618334Speter  if (GET_CODE (x) == PARALLEL)
101718334Speter    {
101818334Speter      int i;
101918334Speter      int sets_cc0 = 0;
102018334Speter      int other_things = 0;
102118334Speter      for (i = XVECLEN (x, 0) - 1; i >= 0; i--)
102218334Speter	{
102318334Speter	  if (GET_CODE (XVECEXP (x, 0, i)) == SET
102418334Speter	      && SET_DEST (XVECEXP (x, 0, i)) == cc0_rtx)
102518334Speter	    sets_cc0 = 1;
102618334Speter	  else if (GET_CODE (XVECEXP (x, 0, i)) == SET)
102718334Speter	    other_things = 1;
102818334Speter	}
102918334Speter      return ! sets_cc0 ? 0 : other_things ? -1 : 1;
103018334Speter    }
103118334Speter  return 0;
103252284Sobrien}
103318334Speter#endif
103418334Speter
103518334Speter/* Follow any unconditional jump at LABEL;
103618334Speter   return the ultimate label reached by any such chain of jumps.
1037169689Skan   Return null if the chain ultimately leads to a return instruction.
103818334Speter   If LABEL is not followed by a jump, return LABEL.
103918334Speter   If the chain loops or we can't find end, return LABEL,
104018334Speter   since that tells caller to avoid changing the insn.
104118334Speter
1042169689Skan   If RELOAD_COMPLETED is 0, we do not chain across a USE or CLOBBER.  */
104318334Speter
104418334Speterrtx
1045132718Skanfollow_jumps (rtx label)
104618334Speter{
104790075Sobrien  rtx insn;
104890075Sobrien  rtx next;
104990075Sobrien  rtx value = label;
105090075Sobrien  int depth;
105118334Speter
105218334Speter  for (depth = 0;
105318334Speter       (depth < 10
105418334Speter	&& (insn = next_active_insn (value)) != 0
1055169689Skan	&& JUMP_P (insn)
105690075Sobrien	&& ((JUMP_LABEL (insn) != 0 && any_uncondjump_p (insn)
105790075Sobrien	     && onlyjump_p (insn))
105850397Sobrien	    || GET_CODE (PATTERN (insn)) == RETURN)
105918334Speter	&& (next = NEXT_INSN (insn))
1060169689Skan	&& BARRIER_P (next));
106118334Speter       depth++)
106218334Speter    {
106318334Speter      rtx tem;
1064169689Skan      if (!reload_completed && flag_test_coverage)
1065169689Skan	{
1066169689Skan	  /* ??? Optional.  Disables some optimizations, but makes
1067169689Skan	     gcov output more accurate with -O.  */
1068169689Skan	  for (tem = value; tem != insn; tem = NEXT_INSN (tem))
1069169689Skan	    if (NOTE_P (tem) && NOTE_LINE_NUMBER (tem) > 0)
1070169689Skan	      return value;
1071169689Skan	}
107218334Speter
107318334Speter      /* If we have found a cycle, make the insn jump to itself.  */
107418334Speter      if (JUMP_LABEL (insn) == label)
107518334Speter	return label;
107618334Speter
107718334Speter      tem = next_active_insn (JUMP_LABEL (insn));
107818334Speter      if (tem && (GET_CODE (PATTERN (tem)) == ADDR_VEC
107918334Speter		  || GET_CODE (PATTERN (tem)) == ADDR_DIFF_VEC))
108018334Speter	break;
108118334Speter
108218334Speter      value = JUMP_LABEL (insn);
108318334Speter    }
108418334Speter  if (depth == 10)
108518334Speter    return label;
108618334Speter  return value;
108718334Speter}
108818334Speter
108918334Speter
109018334Speter/* Find all CODE_LABELs referred to in X, and increment their use counts.
109118334Speter   If INSN is a JUMP_INSN and there is at least one CODE_LABEL referenced
109218334Speter   in INSN, then store one of them in JUMP_LABEL (INSN).
109318334Speter   If INSN is an INSN or a CALL_INSN and there is at least one CODE_LABEL
109418334Speter   referenced in INSN, add a REG_LABEL note containing that label to INSN.
109518334Speter   Also, when there are consecutive labels, canonicalize on the last of them.
109618334Speter
109718334Speter   Note that two labels separated by a loop-beginning note
109818334Speter   must be kept distinct if we have not yet done loop-optimization,
109918334Speter   because the gap between them is where loop-optimize
110018334Speter   will want to move invariant code to.  CROSS_JUMP tells us
110190075Sobrien   that loop-optimization is done with.  */
110218334Speter
110390075Sobrienvoid
1104132718Skanmark_jump_label (rtx x, rtx insn, int in_mem)
110518334Speter{
110690075Sobrien  RTX_CODE code = GET_CODE (x);
110790075Sobrien  int i;
110890075Sobrien  const char *fmt;
110918334Speter
111018334Speter  switch (code)
111118334Speter    {
111218334Speter    case PC:
111318334Speter    case CC0:
111418334Speter    case REG:
111518334Speter    case CONST_INT:
111618334Speter    case CONST_DOUBLE:
111718334Speter    case CLOBBER:
111818334Speter    case CALL:
111918334Speter      return;
112018334Speter
112118334Speter    case MEM:
112290075Sobrien      in_mem = 1;
112390075Sobrien      break;
112490075Sobrien
112590075Sobrien    case SYMBOL_REF:
112690075Sobrien      if (!in_mem)
112790075Sobrien	return;
112890075Sobrien
112918334Speter      /* If this is a constant-pool reference, see if it is a label.  */
113090075Sobrien      if (CONSTANT_POOL_ADDRESS_P (x))
113190075Sobrien	mark_jump_label (get_pool_constant (x), insn, in_mem);
113218334Speter      break;
113318334Speter
113418334Speter    case LABEL_REF:
113518334Speter      {
113618334Speter	rtx label = XEXP (x, 0);
113718334Speter
113890075Sobrien	/* Ignore remaining references to unreachable labels that
113990075Sobrien	   have been deleted.  */
1140169689Skan	if (NOTE_P (label)
114190075Sobrien	    && NOTE_LINE_NUMBER (label) == NOTE_INSN_DELETED_LABEL)
114290075Sobrien	  break;
114390075Sobrien
1144169689Skan	gcc_assert (LABEL_P (label));
114518334Speter
114618334Speter	/* Ignore references to labels of containing functions.  */
114718334Speter	if (LABEL_REF_NONLOCAL_P (x))
114818334Speter	  break;
114918334Speter
115018334Speter	XEXP (x, 0) = label;
115150397Sobrien	if (! insn || ! INSN_DELETED_P (insn))
115250397Sobrien	  ++LABEL_NUSES (label);
115318334Speter
115418334Speter	if (insn)
115518334Speter	  {
1156169689Skan	    if (JUMP_P (insn))
115718334Speter	      JUMP_LABEL (insn) = label;
115890075Sobrien	    else
115918334Speter	      {
116090075Sobrien		/* Add a REG_LABEL note for LABEL unless there already
116190075Sobrien		   is one.  All uses of a label, except for labels
116290075Sobrien		   that are the targets of jumps, must have a
116390075Sobrien		   REG_LABEL note.  */
116490075Sobrien		if (! find_reg_note (insn, REG_LABEL, label))
116590075Sobrien		  REG_NOTES (insn) = gen_rtx_INSN_LIST (REG_LABEL, label,
116690075Sobrien							REG_NOTES (insn));
116718334Speter	      }
116818334Speter	  }
116918334Speter	return;
117018334Speter      }
117118334Speter
117218334Speter  /* Do walk the labels in a vector, but not the first operand of an
117318334Speter     ADDR_DIFF_VEC.  Don't set the JUMP_LABEL of a vector.  */
117418334Speter    case ADDR_VEC:
117518334Speter    case ADDR_DIFF_VEC:
117650397Sobrien      if (! INSN_DELETED_P (insn))
117750397Sobrien	{
117850397Sobrien	  int eltnum = code == ADDR_DIFF_VEC ? 1 : 0;
117918334Speter
118050397Sobrien	  for (i = 0; i < XVECLEN (x, eltnum); i++)
118190075Sobrien	    mark_jump_label (XVECEXP (x, eltnum, i), NULL_RTX, in_mem);
118250397Sobrien	}
118350397Sobrien      return;
118490075Sobrien
118550397Sobrien    default:
118650397Sobrien      break;
118718334Speter    }
118818334Speter
118918334Speter  fmt = GET_RTX_FORMAT (code);
119018334Speter  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
119118334Speter    {
119218334Speter      if (fmt[i] == 'e')
119390075Sobrien	mark_jump_label (XEXP (x, i), insn, in_mem);
119418334Speter      else if (fmt[i] == 'E')
119518334Speter	{
119690075Sobrien	  int j;
119718334Speter	  for (j = 0; j < XVECLEN (x, i); j++)
119890075Sobrien	    mark_jump_label (XVECEXP (x, i, j), insn, in_mem);
119918334Speter	}
120018334Speter    }
120118334Speter}
120218334Speter
120318334Speter/* If all INSN does is set the pc, delete it,
120418334Speter   and delete the insn that set the condition codes for it
120518334Speter   if that's what the previous thing was.  */
120618334Speter
120718334Spetervoid
1208132718Skandelete_jump (rtx insn)
120918334Speter{
121090075Sobrien  rtx set = single_set (insn);
121118334Speter
121218334Speter  if (set && GET_CODE (SET_DEST (set)) == PC)
121318334Speter    delete_computation (insn);
121418334Speter}
121518334Speter
121690075Sobrien/* Recursively delete prior insns that compute the value (used only by INSN
121790075Sobrien   which the caller is deleting) stored in the register mentioned by NOTE
121890075Sobrien   which is a REG_DEAD note associated with INSN.  */
121990075Sobrien
122090075Sobrienstatic void
1221132718Skandelete_prior_computation (rtx note, rtx insn)
122290075Sobrien{
122390075Sobrien  rtx our_prev;
122490075Sobrien  rtx reg = XEXP (note, 0);
122590075Sobrien
122690075Sobrien  for (our_prev = prev_nonnote_insn (insn);
1227169689Skan       our_prev && (NONJUMP_INSN_P (our_prev)
1228169689Skan		    || CALL_P (our_prev));
122990075Sobrien       our_prev = prev_nonnote_insn (our_prev))
123090075Sobrien    {
123190075Sobrien      rtx pat = PATTERN (our_prev);
123290075Sobrien
123390075Sobrien      /* If we reach a CALL which is not calling a const function
123490075Sobrien	 or the callee pops the arguments, then give up.  */
1235169689Skan      if (CALL_P (our_prev)
123690075Sobrien	  && (! CONST_OR_PURE_CALL_P (our_prev)
123790075Sobrien	      || GET_CODE (pat) != SET || GET_CODE (SET_SRC (pat)) != CALL))
123890075Sobrien	break;
123990075Sobrien
124090075Sobrien      /* If we reach a SEQUENCE, it is too complex to try to
1241117395Skan	 do anything with it, so give up.  We can be run during
1242117395Skan	 and after reorg, so SEQUENCE rtl can legitimately show
1243117395Skan	 up here.  */
124490075Sobrien      if (GET_CODE (pat) == SEQUENCE)
124590075Sobrien	break;
124690075Sobrien
124790075Sobrien      if (GET_CODE (pat) == USE
1248169689Skan	  && NONJUMP_INSN_P (XEXP (pat, 0)))
124990075Sobrien	/* reorg creates USEs that look like this.  We leave them
125090075Sobrien	   alone because reorg needs them for its own purposes.  */
125190075Sobrien	break;
125290075Sobrien
125390075Sobrien      if (reg_set_p (reg, pat))
125490075Sobrien	{
1255169689Skan	  if (side_effects_p (pat) && !CALL_P (our_prev))
125690075Sobrien	    break;
125790075Sobrien
125890075Sobrien	  if (GET_CODE (pat) == PARALLEL)
125990075Sobrien	    {
126090075Sobrien	      /* If we find a SET of something else, we can't
126190075Sobrien		 delete the insn.  */
126290075Sobrien
126390075Sobrien	      int i;
126490075Sobrien
126590075Sobrien	      for (i = 0; i < XVECLEN (pat, 0); i++)
126690075Sobrien		{
126790075Sobrien		  rtx part = XVECEXP (pat, 0, i);
126890075Sobrien
126990075Sobrien		  if (GET_CODE (part) == SET
127090075Sobrien		      && SET_DEST (part) != reg)
127190075Sobrien		    break;
127290075Sobrien		}
127390075Sobrien
127490075Sobrien	      if (i == XVECLEN (pat, 0))
127590075Sobrien		delete_computation (our_prev);
127690075Sobrien	    }
127790075Sobrien	  else if (GET_CODE (pat) == SET
1278169689Skan		   && REG_P (SET_DEST (pat)))
127990075Sobrien	    {
128090075Sobrien	      int dest_regno = REGNO (SET_DEST (pat));
128190075Sobrien	      int dest_endregno
128290075Sobrien		= (dest_regno
128390075Sobrien		   + (dest_regno < FIRST_PSEUDO_REGISTER
1284169689Skan		      ? hard_regno_nregs[dest_regno]
1285169689Skan					[GET_MODE (SET_DEST (pat))] : 1));
128690075Sobrien	      int regno = REGNO (reg);
128790075Sobrien	      int endregno
128890075Sobrien		= (regno
128990075Sobrien		   + (regno < FIRST_PSEUDO_REGISTER
1290169689Skan		      ? hard_regno_nregs[regno][GET_MODE (reg)] : 1));
129190075Sobrien
129290075Sobrien	      if (dest_regno >= regno
129390075Sobrien		  && dest_endregno <= endregno)
129490075Sobrien		delete_computation (our_prev);
129590075Sobrien
129690075Sobrien	      /* We may have a multi-word hard register and some, but not
129790075Sobrien		 all, of the words of the register are needed in subsequent
129890075Sobrien		 insns.  Write REG_UNUSED notes for those parts that were not
129990075Sobrien		 needed.  */
130090075Sobrien	      else if (dest_regno <= regno
130190075Sobrien		       && dest_endregno >= endregno)
130290075Sobrien		{
130390075Sobrien		  int i;
130490075Sobrien
130590075Sobrien		  REG_NOTES (our_prev)
130690075Sobrien		    = gen_rtx_EXPR_LIST (REG_UNUSED, reg,
130790075Sobrien					 REG_NOTES (our_prev));
130890075Sobrien
130990075Sobrien		  for (i = dest_regno; i < dest_endregno; i++)
131090075Sobrien		    if (! find_regno_note (our_prev, REG_UNUSED, i))
131190075Sobrien		      break;
131290075Sobrien
131390075Sobrien		  if (i == dest_endregno)
131490075Sobrien		    delete_computation (our_prev);
131590075Sobrien		}
131690075Sobrien	    }
131790075Sobrien
131890075Sobrien	  break;
131990075Sobrien	}
132090075Sobrien
132190075Sobrien      /* If PAT references the register that dies here, it is an
132290075Sobrien	 additional use.  Hence any prior SET isn't dead.  However, this
132390075Sobrien	 insn becomes the new place for the REG_DEAD note.  */
132490075Sobrien      if (reg_overlap_mentioned_p (reg, pat))
132590075Sobrien	{
132690075Sobrien	  XEXP (note, 1) = REG_NOTES (our_prev);
132790075Sobrien	  REG_NOTES (our_prev) = note;
132890075Sobrien	  break;
132990075Sobrien	}
133090075Sobrien    }
133190075Sobrien}
133290075Sobrien
133318334Speter/* Delete INSN and recursively delete insns that compute values used only
133418334Speter   by INSN.  This uses the REG_DEAD notes computed during flow analysis.
133518334Speter   If we are running before flow.c, we need do nothing since flow.c will
133618334Speter   delete dead code.  We also can't know if the registers being used are
133718334Speter   dead or not at this point.
133818334Speter
133918334Speter   Otherwise, look at all our REG_DEAD notes.  If a previous insn does
134018334Speter   nothing other than set a register that dies in this insn, we can delete
134118334Speter   that insn as well.
134218334Speter
134318334Speter   On machines with CC0, if CC0 is used in this insn, we may be able to
134418334Speter   delete the insn that set it.  */
134518334Speter
134618334Speterstatic void
1347132718Skandelete_computation (rtx insn)
134818334Speter{
134918334Speter  rtx note, next;
135018334Speter
135118334Speter#ifdef HAVE_cc0
135218334Speter  if (reg_referenced_p (cc0_rtx, PATTERN (insn)))
135318334Speter    {
135418334Speter      rtx prev = prev_nonnote_insn (insn);
135518334Speter      /* We assume that at this stage
135618334Speter	 CC's are always set explicitly
135718334Speter	 and always immediately before the jump that
135818334Speter	 will use them.  So if the previous insn
135918334Speter	 exists to set the CC's, delete it
136018334Speter	 (unless it performs auto-increments, etc.).  */
1361169689Skan      if (prev && NONJUMP_INSN_P (prev)
136218334Speter	  && sets_cc0_p (PATTERN (prev)))
136318334Speter	{
136418334Speter	  if (sets_cc0_p (PATTERN (prev)) > 0
136590075Sobrien	      && ! side_effects_p (PATTERN (prev)))
136618334Speter	    delete_computation (prev);
136718334Speter	  else
136818334Speter	    /* Otherwise, show that cc0 won't be used.  */
136950397Sobrien	    REG_NOTES (prev) = gen_rtx_EXPR_LIST (REG_UNUSED,
137050397Sobrien						  cc0_rtx, REG_NOTES (prev));
137118334Speter	}
137218334Speter    }
137318334Speter#endif
137418334Speter
137518334Speter  for (note = REG_NOTES (insn); note; note = next)
137618334Speter    {
137718334Speter      next = XEXP (note, 1);
137818334Speter
137918334Speter      if (REG_NOTE_KIND (note) != REG_DEAD
138018334Speter	  /* Verify that the REG_NOTE is legitimate.  */
1381169689Skan	  || !REG_P (XEXP (note, 0)))
138218334Speter	continue;
138318334Speter
138490075Sobrien      delete_prior_computation (note, insn);
138518334Speter    }
138618334Speter
138790075Sobrien  delete_related_insns (insn);
138818334Speter}
138918334Speter
139090075Sobrien/* Delete insn INSN from the chain of insns and update label ref counts
1391132718Skan   and delete insns now unreachable.
139218334Speter
1393132718Skan   Returns the first insn after INSN that was not deleted.
139418334Speter
139590075Sobrien   Usage of this instruction is deprecated.  Use delete_insn instead and
139690075Sobrien   subsequent cfg_cleanup pass to delete unreachable code if needed.  */
139790075Sobrien
139818334Speterrtx
1399132718Skandelete_related_insns (rtx insn)
140018334Speter{
1401169689Skan  int was_code_label = (LABEL_P (insn));
140290075Sobrien  rtx note;
140390075Sobrien  rtx next = NEXT_INSN (insn), prev = PREV_INSN (insn);
140418334Speter
140518334Speter  while (next && INSN_DELETED_P (next))
140618334Speter    next = NEXT_INSN (next);
140718334Speter
140818334Speter  /* This insn is already deleted => return first following nondeleted.  */
140918334Speter  if (INSN_DELETED_P (insn))
141018334Speter    return next;
141118334Speter
141290075Sobrien  delete_insn (insn);
141352284Sobrien
141418334Speter  /* If instruction is followed by a barrier,
141518334Speter     delete the barrier too.  */
141618334Speter
1417169689Skan  if (next != 0 && BARRIER_P (next))
141890075Sobrien    delete_insn (next);
141918334Speter
142018334Speter  /* If deleting a jump, decrement the count of the label,
142118334Speter     and delete the label if it is now unused.  */
142218334Speter
1423169689Skan  if (JUMP_P (insn) && JUMP_LABEL (insn))
142452284Sobrien    {
142552284Sobrien      rtx lab = JUMP_LABEL (insn), lab_next;
142618334Speter
142790075Sobrien      if (LABEL_NUSES (lab) == 0)
142852284Sobrien	{
142952284Sobrien	  /* This can delete NEXT or PREV,
143052284Sobrien	     either directly if NEXT is JUMP_LABEL (INSN),
143152284Sobrien	     or indirectly through more levels of jumps.  */
143290075Sobrien	  delete_related_insns (lab);
143352284Sobrien
143452284Sobrien	  /* I feel a little doubtful about this loop,
143552284Sobrien	     but I see no clean and sure alternative way
143652284Sobrien	     to find the first insn after INSN that is not now deleted.
143752284Sobrien	     I hope this works.  */
143852284Sobrien	  while (next && INSN_DELETED_P (next))
143952284Sobrien	    next = NEXT_INSN (next);
144052284Sobrien	  return next;
144152284Sobrien	}
1442132718Skan      else if (tablejump_p (insn, NULL, &lab_next))
144352284Sobrien	{
144452284Sobrien	  /* If we're deleting the tablejump, delete the dispatch table.
144590075Sobrien	     We may not be able to kill the label immediately preceding
144652284Sobrien	     just yet, as it might be referenced in code leading up to
144752284Sobrien	     the tablejump.  */
144890075Sobrien	  delete_related_insns (lab_next);
144952284Sobrien	}
145052284Sobrien    }
145152284Sobrien
145218334Speter  /* Likewise if we're deleting a dispatch table.  */
145318334Speter
1454169689Skan  if (JUMP_P (insn)
145518334Speter      && (GET_CODE (PATTERN (insn)) == ADDR_VEC
145618334Speter	  || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC))
145718334Speter    {
145818334Speter      rtx pat = PATTERN (insn);
145918334Speter      int i, diff_vec_p = GET_CODE (pat) == ADDR_DIFF_VEC;
146018334Speter      int len = XVECLEN (pat, diff_vec_p);
146118334Speter
146218334Speter      for (i = 0; i < len; i++)
146390075Sobrien	if (LABEL_NUSES (XEXP (XVECEXP (pat, diff_vec_p, i), 0)) == 0)
146490075Sobrien	  delete_related_insns (XEXP (XVECEXP (pat, diff_vec_p, i), 0));
146518334Speter      while (next && INSN_DELETED_P (next))
146618334Speter	next = NEXT_INSN (next);
146718334Speter      return next;
146818334Speter    }
146918334Speter
147090075Sobrien  /* Likewise for an ordinary INSN / CALL_INSN with a REG_LABEL note.  */
1471169689Skan  if (NONJUMP_INSN_P (insn) || CALL_P (insn))
147290075Sobrien    for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
147390075Sobrien      if (REG_NOTE_KIND (note) == REG_LABEL
147490075Sobrien	  /* This could also be a NOTE_INSN_DELETED_LABEL note.  */
1475169689Skan	  && LABEL_P (XEXP (note, 0)))
147690075Sobrien	if (LABEL_NUSES (XEXP (note, 0)) == 0)
147790075Sobrien	  delete_related_insns (XEXP (note, 0));
147890075Sobrien
1479169689Skan  while (prev && (INSN_DELETED_P (prev) || NOTE_P (prev)))
148018334Speter    prev = PREV_INSN (prev);
148118334Speter
148218334Speter  /* If INSN was a label and a dispatch table follows it,
148318334Speter     delete the dispatch table.  The tablejump must have gone already.
148418334Speter     It isn't useful to fall through into a table.  */
148518334Speter
148618334Speter  if (was_code_label
148718334Speter      && NEXT_INSN (insn) != 0
1488169689Skan      && JUMP_P (NEXT_INSN (insn))
148918334Speter      && (GET_CODE (PATTERN (NEXT_INSN (insn))) == ADDR_VEC
149018334Speter	  || GET_CODE (PATTERN (NEXT_INSN (insn))) == ADDR_DIFF_VEC))
149190075Sobrien    next = delete_related_insns (NEXT_INSN (insn));
149218334Speter
149318334Speter  /* If INSN was a label, delete insns following it if now unreachable.  */
149418334Speter
1495169689Skan  if (was_code_label && prev && BARRIER_P (prev))
149618334Speter    {
1497169689Skan      enum rtx_code code;
1498169689Skan      while (next)
149918334Speter	{
1500169689Skan	  code = GET_CODE (next);
150118334Speter	  if (code == NOTE
150218334Speter	      && NOTE_LINE_NUMBER (next) != NOTE_INSN_FUNCTION_END)
150318334Speter	    next = NEXT_INSN (next);
150418334Speter	  /* Keep going past other deleted labels to delete what follows.  */
150518334Speter	  else if (code == CODE_LABEL && INSN_DELETED_P (next))
150618334Speter	    next = NEXT_INSN (next);
1507169689Skan	  else if (code == BARRIER || INSN_P (next))
150818334Speter	    /* Note: if this deletes a jump, it can cause more
150918334Speter	       deletion of unreachable code, after a different label.
151018334Speter	       As long as the value from this recursive call is correct,
151118334Speter	       this invocation functions correctly.  */
151290075Sobrien	    next = delete_related_insns (next);
1513169689Skan	  else
1514169689Skan	    break;
151518334Speter	}
151618334Speter    }
151718334Speter
151818334Speter  return next;
151918334Speter}
152018334Speter
152118334Speter/* Delete a range of insns from FROM to TO, inclusive.
152218334Speter   This is for the sake of peephole optimization, so assume
152318334Speter   that whatever these insns do will still be done by a new
152418334Speter   peephole insn that will replace them.  */
152518334Speter
152618334Spetervoid
1527132718Skandelete_for_peephole (rtx from, rtx to)
152818334Speter{
152990075Sobrien  rtx insn = from;
153018334Speter
153118334Speter  while (1)
153218334Speter    {
153390075Sobrien      rtx next = NEXT_INSN (insn);
153490075Sobrien      rtx prev = PREV_INSN (insn);
153518334Speter
1536169689Skan      if (!NOTE_P (insn))
153718334Speter	{
153818334Speter	  INSN_DELETED_P (insn) = 1;
153918334Speter
154018334Speter	  /* Patch this insn out of the chain.  */
154118334Speter	  /* We don't do this all at once, because we
154218334Speter	     must preserve all NOTEs.  */
154318334Speter	  if (prev)
154418334Speter	    NEXT_INSN (prev) = next;
154518334Speter
154618334Speter	  if (next)
154718334Speter	    PREV_INSN (next) = prev;
154818334Speter	}
154918334Speter
155018334Speter      if (insn == to)
155118334Speter	break;
155218334Speter      insn = next;
155318334Speter    }
155418334Speter
155518334Speter  /* Note that if TO is an unconditional jump
155618334Speter     we *do not* delete the BARRIER that follows,
155718334Speter     since the peephole that replaces this sequence
155818334Speter     is also an unconditional jump in that case.  */
155918334Speter}
156018334Speter
156190075Sobrien/* Throughout LOC, redirect OLABEL to NLABEL.  Treat null OLABEL or
156290075Sobrien   NLABEL as a return.  Accrue modifications into the change group.  */
156318334Speter
156490075Sobrienstatic void
1565132718Skanredirect_exp_1 (rtx *loc, rtx olabel, rtx nlabel, rtx insn)
156618334Speter{
156790075Sobrien  rtx x = *loc;
156890075Sobrien  RTX_CODE code = GET_CODE (x);
156990075Sobrien  int i;
157090075Sobrien  const char *fmt;
157118334Speter
157290075Sobrien  if (code == LABEL_REF)
157390075Sobrien    {
157490075Sobrien      if (XEXP (x, 0) == olabel)
157590075Sobrien	{
157690075Sobrien	  rtx n;
157790075Sobrien	  if (nlabel)
1578169689Skan	    n = gen_rtx_LABEL_REF (Pmode, nlabel);
157990075Sobrien	  else
158090075Sobrien	    n = gen_rtx_RETURN (VOIDmode);
158118334Speter
158290075Sobrien	  validate_change (insn, loc, n, 1);
158390075Sobrien	  return;
158490075Sobrien	}
158590075Sobrien    }
158690075Sobrien  else if (code == RETURN && olabel == 0)
158718334Speter    {
1588169689Skan      if (nlabel)
1589169689Skan	x = gen_rtx_LABEL_REF (Pmode, nlabel);
1590169689Skan      else
1591169689Skan	x = gen_rtx_RETURN (VOIDmode);
159290075Sobrien      if (loc == &PATTERN (insn))
159390075Sobrien	x = gen_rtx_SET (VOIDmode, pc_rtx, x);
159490075Sobrien      validate_change (insn, loc, x, 1);
159590075Sobrien      return;
159690075Sobrien    }
159718334Speter
159890075Sobrien  if (code == SET && nlabel == 0 && SET_DEST (x) == pc_rtx
159990075Sobrien      && GET_CODE (SET_SRC (x)) == LABEL_REF
160090075Sobrien      && XEXP (SET_SRC (x), 0) == olabel)
160190075Sobrien    {
160290075Sobrien      validate_change (insn, loc, gen_rtx_RETURN (VOIDmode), 1);
160390075Sobrien      return;
160418334Speter    }
160518334Speter
160618334Speter  fmt = GET_RTX_FORMAT (code);
160718334Speter  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
160818334Speter    {
160918334Speter      if (fmt[i] == 'e')
161090075Sobrien	redirect_exp_1 (&XEXP (x, i), olabel, nlabel, insn);
161190075Sobrien      else if (fmt[i] == 'E')
161218334Speter	{
161390075Sobrien	  int j;
161418334Speter	  for (j = 0; j < XVECLEN (x, i); j++)
161590075Sobrien	    redirect_exp_1 (&XVECEXP (x, i, j), olabel, nlabel, insn);
161618334Speter	}
161718334Speter    }
161890075Sobrien}
161918334Speter
162090075Sobrien/* Make JUMP go to NLABEL instead of where it jumps now.  Accrue
162190075Sobrien   the modifications into the change group.  Return false if we did
162290075Sobrien   not see how to do that.  */
162390075Sobrien
162490075Sobrienint
1625132718Skanredirect_jump_1 (rtx jump, rtx nlabel)
162690075Sobrien{
162790075Sobrien  int ochanges = num_validated_changes ();
162890075Sobrien  rtx *loc;
162990075Sobrien
163090075Sobrien  if (GET_CODE (PATTERN (jump)) == PARALLEL)
163190075Sobrien    loc = &XVECEXP (PATTERN (jump), 0, 0);
163290075Sobrien  else
163390075Sobrien    loc = &PATTERN (jump);
163490075Sobrien
163590075Sobrien  redirect_exp_1 (loc, JUMP_LABEL (jump), nlabel, jump);
163690075Sobrien  return num_validated_changes () > ochanges;
163790075Sobrien}
163890075Sobrien
163990075Sobrien/* Make JUMP go to NLABEL instead of where it jumps now.  If the old
164090075Sobrien   jump target label is unused as a result, it and the code following
164190075Sobrien   it may be deleted.
164290075Sobrien
164318334Speter   If NLABEL is zero, we are to turn the jump into a (possibly conditional)
164418334Speter   RETURN insn.
164518334Speter
164690075Sobrien   The return value will be 1 if the change was made, 0 if it wasn't
164790075Sobrien   (this can only occur for NLABEL == 0).  */
164818334Speter
164918334Speterint
1650132718Skanredirect_jump (rtx jump, rtx nlabel, int delete_unused)
165118334Speter{
165290075Sobrien  rtx olabel = JUMP_LABEL (jump);
165318334Speter
165418334Speter  if (nlabel == olabel)
165518334Speter    return 1;
165618334Speter
1657169689Skan  if (! redirect_jump_1 (jump, nlabel) || ! apply_change_group ())
165818334Speter    return 0;
165918334Speter
1660169689Skan  redirect_jump_2 (jump, olabel, nlabel, delete_unused, 0);
1661169689Skan  return 1;
1662169689Skan}
1663169689Skan
1664169689Skan/* Fix up JUMP_LABEL and label ref counts after OLABEL has been replaced with
1665169689Skan   NLABEL in JUMP.  If DELETE_UNUSED is non-negative, copy a
1666169689Skan   NOTE_INSN_FUNCTION_END found after OLABEL to the place after NLABEL.
1667169689Skan   If DELETE_UNUSED is positive, delete related insn to OLABEL if its ref
1668169689Skan   count has dropped to zero.  */
1669169689Skanvoid
1670169689Skanredirect_jump_2 (rtx jump, rtx olabel, rtx nlabel, int delete_unused,
1671169689Skan		 int invert)
1672169689Skan{
1673169689Skan  rtx note;
1674169689Skan
167518334Speter  JUMP_LABEL (jump) = nlabel;
167618334Speter  if (nlabel)
167718334Speter    ++LABEL_NUSES (nlabel);
167818334Speter
1679132718Skan  /* Update labels in any REG_EQUAL note.  */
1680132718Skan  if ((note = find_reg_note (jump, REG_EQUAL, NULL_RTX)) != NULL_RTX)
1681132718Skan    {
1682169689Skan      if (!nlabel || (invert && !invert_exp_1 (XEXP (note, 0), jump)))
1683169689Skan	remove_note (jump, note);
1684169689Skan      else
1685132718Skan	{
1686169689Skan	  redirect_exp_1 (&XEXP (note, 0), olabel, nlabel, jump);
1687169689Skan	  confirm_change_group ();
1688132718Skan	}
1689132718Skan    }
1690132718Skan
169190075Sobrien  /* If we're eliding the jump over exception cleanups at the end of a
169290075Sobrien     function, move the function end note so that -Wreturn-type works.  */
169390075Sobrien  if (olabel && nlabel
169490075Sobrien      && NEXT_INSN (olabel)
1695169689Skan      && NOTE_P (NEXT_INSN (olabel))
1696169689Skan      && NOTE_LINE_NUMBER (NEXT_INSN (olabel)) == NOTE_INSN_FUNCTION_END
1697169689Skan      && delete_unused >= 0)
169890075Sobrien    emit_note_after (NOTE_INSN_FUNCTION_END, nlabel);
169918334Speter
1700169689Skan  if (olabel && --LABEL_NUSES (olabel) == 0 && delete_unused > 0
170196263Sobrien      /* Undefined labels will remain outside the insn stream.  */
170296263Sobrien      && INSN_UID (olabel))
170390075Sobrien    delete_related_insns (olabel);
1704169689Skan  if (invert)
1705169689Skan    invert_br_probabilities (jump);
170618334Speter}
170718334Speter
1708169689Skan/* Invert the jump condition X contained in jump insn INSN.  Accrue the
1709169689Skan   modifications into the change group.  Return nonzero for success.  */
1710169689Skanstatic int
1711169689Skaninvert_exp_1 (rtx x, rtx insn)
171218334Speter{
1713169689Skan  RTX_CODE code = GET_CODE (x);
171418334Speter
171590075Sobrien  if (code == IF_THEN_ELSE)
171618334Speter    {
171790075Sobrien      rtx comp = XEXP (x, 0);
171890075Sobrien      rtx tem;
171990075Sobrien      enum rtx_code reversed_code;
172018334Speter
172190075Sobrien      /* We can do this in two ways:  The preferable way, which can only
172290075Sobrien	 be done if this is not an integer comparison, is to reverse
172390075Sobrien	 the comparison code.  Otherwise, swap the THEN-part and ELSE-part
172490075Sobrien	 of the IF_THEN_ELSE.  If we can't do either, fail.  */
172590075Sobrien
172690075Sobrien      reversed_code = reversed_comparison_code (comp, insn);
172790075Sobrien
172890075Sobrien      if (reversed_code != UNKNOWN)
172990075Sobrien	{
173090075Sobrien	  validate_change (insn, &XEXP (x, 0),
173190075Sobrien			   gen_rtx_fmt_ee (reversed_code,
173290075Sobrien					   GET_MODE (comp), XEXP (comp, 0),
173390075Sobrien					   XEXP (comp, 1)),
173490075Sobrien			   1);
1735169689Skan	  return 1;
173690075Sobrien	}
173790075Sobrien
173890075Sobrien      tem = XEXP (x, 1);
173990075Sobrien      validate_change (insn, &XEXP (x, 1), XEXP (x, 2), 1);
174090075Sobrien      validate_change (insn, &XEXP (x, 2), tem, 1);
1741169689Skan      return 1;
174218334Speter    }
174390075Sobrien  else
174490075Sobrien    return 0;
174518334Speter}
174618334Speter
174790075Sobrien/* Invert the condition of the jump JUMP, and make it jump to label
174890075Sobrien   NLABEL instead of where it jumps now.  Accrue changes into the
174990075Sobrien   change group.  Return false if we didn't see how to perform the
175090075Sobrien   inversion and redirection.  */
175118334Speter
175290075Sobrienint
1753132718Skaninvert_jump_1 (rtx jump, rtx nlabel)
175418334Speter{
1755169689Skan  rtx x = pc_set (jump);
175690075Sobrien  int ochanges;
1757169689Skan  int ok;
175818334Speter
175990075Sobrien  ochanges = num_validated_changes ();
1760169689Skan  gcc_assert (x);
1761169689Skan  ok = invert_exp_1 (SET_SRC (x), jump);
1762169689Skan  gcc_assert (ok);
1763169689Skan
176490075Sobrien  if (num_validated_changes () == ochanges)
176590075Sobrien    return 0;
176618334Speter
1767169689Skan  /* redirect_jump_1 will fail of nlabel == olabel, and the current use is
1768169689Skan     in Pmode, so checking this is not merely an optimization.  */
1769169689Skan  return nlabel == JUMP_LABEL (jump) || redirect_jump_1 (jump, nlabel);
177018334Speter}
177118334Speter
177290075Sobrien/* Invert the condition of the jump JUMP, and make it jump to label
177390075Sobrien   NLABEL instead of where it jumps now.  Return true if successful.  */
177418334Speter
177590075Sobrienint
1776132718Skaninvert_jump (rtx jump, rtx nlabel, int delete_unused)
177718334Speter{
1778169689Skan  rtx olabel = JUMP_LABEL (jump);
177918334Speter
1780169689Skan  if (invert_jump_1 (jump, nlabel) && apply_change_group ())
178118334Speter    {
1782169689Skan      redirect_jump_2 (jump, olabel, nlabel, delete_unused, 1);
178390075Sobrien      return 1;
178418334Speter    }
1785169689Skan  cancel_changes (0);
178690075Sobrien  return 0;
178718334Speter}
178890075Sobrien
178918334Speter
179018334Speter/* Like rtx_equal_p except that it considers two REGs as equal
179118334Speter   if they renumber to the same value and considers two commutative
179218334Speter   operations to be the same if the order of the operands has been
1793169689Skan   reversed.  */
179418334Speter
179518334Speterint
1796132718Skanrtx_renumbered_equal_p (rtx x, rtx y)
179718334Speter{
179890075Sobrien  int i;
1799169689Skan  enum rtx_code code = GET_CODE (x);
180090075Sobrien  const char *fmt;
180190075Sobrien
180218334Speter  if (x == y)
180318334Speter    return 1;
180418334Speter
1805169689Skan  if ((code == REG || (code == SUBREG && REG_P (SUBREG_REG (x))))
1806169689Skan      && (REG_P (y) || (GET_CODE (y) == SUBREG
1807169689Skan				  && REG_P (SUBREG_REG (y)))))
180818334Speter    {
180918334Speter      int reg_x = -1, reg_y = -1;
181090075Sobrien      int byte_x = 0, byte_y = 0;
181118334Speter
181218334Speter      if (GET_MODE (x) != GET_MODE (y))
181318334Speter	return 0;
181418334Speter
181518334Speter      /* If we haven't done any renumbering, don't
181618334Speter	 make any assumptions.  */
181718334Speter      if (reg_renumber == 0)
181818334Speter	return rtx_equal_p (x, y);
181918334Speter
182018334Speter      if (code == SUBREG)
182118334Speter	{
182218334Speter	  reg_x = REGNO (SUBREG_REG (x));
182390075Sobrien	  byte_x = SUBREG_BYTE (x);
182418334Speter
182518334Speter	  if (reg_renumber[reg_x] >= 0)
182618334Speter	    {
182790075Sobrien	      reg_x = subreg_regno_offset (reg_renumber[reg_x],
182890075Sobrien					   GET_MODE (SUBREG_REG (x)),
182990075Sobrien					   byte_x,
183090075Sobrien					   GET_MODE (x));
183190075Sobrien	      byte_x = 0;
183218334Speter	    }
183318334Speter	}
183418334Speter      else
183518334Speter	{
183618334Speter	  reg_x = REGNO (x);
183718334Speter	  if (reg_renumber[reg_x] >= 0)
183818334Speter	    reg_x = reg_renumber[reg_x];
183918334Speter	}
184018334Speter
184118334Speter      if (GET_CODE (y) == SUBREG)
184218334Speter	{
184318334Speter	  reg_y = REGNO (SUBREG_REG (y));
184490075Sobrien	  byte_y = SUBREG_BYTE (y);
184518334Speter
184618334Speter	  if (reg_renumber[reg_y] >= 0)
184718334Speter	    {
184890075Sobrien	      reg_y = subreg_regno_offset (reg_renumber[reg_y],
184990075Sobrien					   GET_MODE (SUBREG_REG (y)),
185090075Sobrien					   byte_y,
185190075Sobrien					   GET_MODE (y));
185290075Sobrien	      byte_y = 0;
185318334Speter	    }
185418334Speter	}
185518334Speter      else
185618334Speter	{
185718334Speter	  reg_y = REGNO (y);
185818334Speter	  if (reg_renumber[reg_y] >= 0)
185918334Speter	    reg_y = reg_renumber[reg_y];
186018334Speter	}
186118334Speter
186290075Sobrien      return reg_x >= 0 && reg_x == reg_y && byte_x == byte_y;
186318334Speter    }
186418334Speter
186590075Sobrien  /* Now we have disposed of all the cases
186618334Speter     in which different rtx codes can match.  */
186718334Speter  if (code != GET_CODE (y))
186818334Speter    return 0;
186918334Speter
187018334Speter  switch (code)
187118334Speter    {
187218334Speter    case PC:
187318334Speter    case CC0:
187418334Speter    case ADDR_VEC:
187518334Speter    case ADDR_DIFF_VEC:
1876132718Skan    case CONST_INT:
1877169689Skan    case CONST_DOUBLE:
187818334Speter      return 0;
187918334Speter
188018334Speter    case LABEL_REF:
188118334Speter      /* We can't assume nonlocal labels have their following insns yet.  */
188218334Speter      if (LABEL_REF_NONLOCAL_P (x) || LABEL_REF_NONLOCAL_P (y))
188318334Speter	return XEXP (x, 0) == XEXP (y, 0);
188418334Speter
188518334Speter      /* Two label-refs are equivalent if they point at labels
188618334Speter	 in the same position in the instruction stream.  */
188718334Speter      return (next_real_insn (XEXP (x, 0))
188818334Speter	      == next_real_insn (XEXP (y, 0)));
188918334Speter
189018334Speter    case SYMBOL_REF:
189118334Speter      return XSTR (x, 0) == XSTR (y, 0);
189250397Sobrien
189350397Sobrien    case CODE_LABEL:
189450397Sobrien      /* If we didn't match EQ equality above, they aren't the same.  */
189550397Sobrien      return 0;
189650397Sobrien
189750397Sobrien    default:
189850397Sobrien      break;
189918334Speter    }
190018334Speter
190118334Speter  /* (MULT:SI x y) and (MULT:HI x y) are NOT equivalent.  */
190218334Speter
190318334Speter  if (GET_MODE (x) != GET_MODE (y))
190418334Speter    return 0;
190518334Speter
190618334Speter  /* For commutative operations, the RTX match if the operand match in any
1907169689Skan     order.  Also handle the simple binary and unary cases without a loop.  */
1908169689Skan  if (targetm.commutative_p (x, UNKNOWN))
190918334Speter    return ((rtx_renumbered_equal_p (XEXP (x, 0), XEXP (y, 0))
191018334Speter	     && rtx_renumbered_equal_p (XEXP (x, 1), XEXP (y, 1)))
191118334Speter	    || (rtx_renumbered_equal_p (XEXP (x, 0), XEXP (y, 1))
191218334Speter		&& rtx_renumbered_equal_p (XEXP (x, 1), XEXP (y, 0))));
1913169689Skan  else if (NON_COMMUTATIVE_P (x))
191418334Speter    return (rtx_renumbered_equal_p (XEXP (x, 0), XEXP (y, 0))
191518334Speter	    && rtx_renumbered_equal_p (XEXP (x, 1), XEXP (y, 1)));
1916169689Skan  else if (UNARY_P (x))
191718334Speter    return rtx_renumbered_equal_p (XEXP (x, 0), XEXP (y, 0));
191818334Speter
191918334Speter  /* Compare the elements.  If any pair of corresponding elements
192018334Speter     fail to match, return 0 for the whole things.  */
192118334Speter
192218334Speter  fmt = GET_RTX_FORMAT (code);
192318334Speter  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
192418334Speter    {
192590075Sobrien      int j;
192618334Speter      switch (fmt[i])
192718334Speter	{
192818334Speter	case 'w':
192918334Speter	  if (XWINT (x, i) != XWINT (y, i))
193018334Speter	    return 0;
193118334Speter	  break;
193218334Speter
193318334Speter	case 'i':
193418334Speter	  if (XINT (x, i) != XINT (y, i))
193518334Speter	    return 0;
193618334Speter	  break;
193718334Speter
193890075Sobrien	case 't':
193990075Sobrien	  if (XTREE (x, i) != XTREE (y, i))
194090075Sobrien	    return 0;
194190075Sobrien	  break;
194290075Sobrien
194318334Speter	case 's':
194418334Speter	  if (strcmp (XSTR (x, i), XSTR (y, i)))
194518334Speter	    return 0;
194618334Speter	  break;
194718334Speter
194818334Speter	case 'e':
194918334Speter	  if (! rtx_renumbered_equal_p (XEXP (x, i), XEXP (y, i)))
195018334Speter	    return 0;
195118334Speter	  break;
195218334Speter
195318334Speter	case 'u':
195418334Speter	  if (XEXP (x, i) != XEXP (y, i))
195518334Speter	    return 0;
1956132718Skan	  /* Fall through.  */
195718334Speter	case '0':
195818334Speter	  break;
195918334Speter
196018334Speter	case 'E':
196118334Speter	  if (XVECLEN (x, i) != XVECLEN (y, i))
196218334Speter	    return 0;
196318334Speter	  for (j = XVECLEN (x, i) - 1; j >= 0; j--)
196418334Speter	    if (!rtx_renumbered_equal_p (XVECEXP (x, i, j), XVECEXP (y, i, j)))
196518334Speter	      return 0;
196618334Speter	  break;
196718334Speter
196818334Speter	default:
1969169689Skan	  gcc_unreachable ();
197018334Speter	}
197118334Speter    }
197218334Speter  return 1;
197318334Speter}
197418334Speter
197518334Speter/* If X is a hard register or equivalent to one or a subregister of one,
197618334Speter   return the hard register number.  If X is a pseudo register that was not
197718334Speter   assigned a hard register, return the pseudo register number.  Otherwise,
197818334Speter   return -1.  Any rtx is valid for X.  */
197918334Speter
198018334Speterint
1981132718Skantrue_regnum (rtx x)
198218334Speter{
1983169689Skan  if (REG_P (x))
198418334Speter    {
198518334Speter      if (REGNO (x) >= FIRST_PSEUDO_REGISTER && reg_renumber[REGNO (x)] >= 0)
198618334Speter	return reg_renumber[REGNO (x)];
198718334Speter      return REGNO (x);
198818334Speter    }
198918334Speter  if (GET_CODE (x) == SUBREG)
199018334Speter    {
199118334Speter      int base = true_regnum (SUBREG_REG (x));
1992169689Skan      if (base >= 0
1993169689Skan	  && base < FIRST_PSEUDO_REGISTER
1994169689Skan	  && subreg_offset_representable_p (REGNO (SUBREG_REG (x)),
1995169689Skan					    GET_MODE (SUBREG_REG (x)),
1996169689Skan					    SUBREG_BYTE (x), GET_MODE (x)))
199790075Sobrien	return base + subreg_regno_offset (REGNO (SUBREG_REG (x)),
199890075Sobrien					   GET_MODE (SUBREG_REG (x)),
199990075Sobrien					   SUBREG_BYTE (x), GET_MODE (x));
200018334Speter    }
200118334Speter  return -1;
200218334Speter}
2003104752Skan
2004104752Skan/* Return regno of the register REG and handle subregs too.  */
2005104752Skanunsigned int
2006132718Skanreg_or_subregno (rtx reg)
2007104752Skan{
2008104752Skan  if (GET_CODE (reg) == SUBREG)
2009169689Skan    reg = SUBREG_REG (reg);
2010169689Skan  gcc_assert (REG_P (reg));
2011169689Skan  return REGNO (reg);
2012104752Skan}
2013