jump.c 45.1 KB
Newer Older
Richard Kenner committed
1
/* Optimize jump instructions, for GNU compiler.
Jeff Law committed
2
   Copyright (C) 1987, 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997
3
   1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007
4
   Free Software Foundation, Inc.
Richard Kenner committed
5

6
This file is part of GCC.
Richard Kenner committed
7

8 9
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
10
Software Foundation; either version 3, or (at your option) any later
11
version.
Richard Kenner committed
12

13 14 15 16
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.
Richard Kenner committed
17 18

You should have received a copy of the GNU General Public License
19 20
along with GCC; see the file COPYING3.  If not see
<http://www.gnu.org/licenses/>.  */
Richard Kenner committed
21

Jan Hubicka committed
22
/* This is the pathetic reminder of old fame of the jump-optimization pass
23
   of the compiler.  Now it contains basically a set of utility functions to
Jan Hubicka committed
24
   operate with jumps.
Richard Kenner committed
25 26 27 28 29 30 31 32 33

   Each CODE_LABEL has a count of the times it is used
   stored in the LABEL_NUSES internal field, and each JUMP_INSN
   has one label that it refers to stored in the
   JUMP_LABEL internal field.  With this we can detect labels that
   become unused because of the deletion of all the jumps that
   formerly used them.  The JUMP_LABEL info is sometimes looked
   at by later passes.

34
   The subroutines redirect_jump and invert_jump are used
Richard Kenner committed
35 36 37
   from other passes as well.  */

#include "config.h"
38
#include "system.h"
39 40
#include "coretypes.h"
#include "tm.h"
Richard Kenner committed
41
#include "rtl.h"
42
#include "tm_p.h"
Richard Kenner committed
43 44 45 46
#include "flags.h"
#include "hard-reg-set.h"
#include "regs.h"
#include "insn-config.h"
47
#include "insn-attr.h"
48
#include "recog.h"
49
#include "function.h"
50
#include "expr.h"
Richard Kenner committed
51
#include "real.h"
Mike Stump committed
52
#include "except.h"
53
#include "diagnostic.h"
Graham Stott committed
54
#include "toplev.h"
55
#include "reload.h"
Jan Hubicka committed
56
#include "predict.h"
57
#include "timevar.h"
58
#include "tree-pass.h"
59
#include "target.h"
Richard Kenner committed
60 61 62 63 64 65 66 67

/* Optimize jump y; x: ... y: jumpif... x?
   Don't know if it is worth bothering with.  */
/* Optimize two cases of conditional jump to conditional jump?
   This can never delete any instruction or make anything dead,
   or even change what is live at any point.
   So perhaps let combiner do it.  */

68 69
static void init_label_info (rtx);
static void mark_all_labels (rtx);
70
static void mark_jump_label_1 (rtx, rtx, bool, bool);
71
static void redirect_exp_1 (rtx *, rtx, rtx, rtx);
72
static int invert_exp_1 (rtx, rtx);
73
static int returnjump_p_1 (rtx *, void *);
74

75 76 77 78
/* This function rebuilds the JUMP_LABEL field and REG_LABEL_TARGET
   notes in jumping insns and REG_LABEL_OPERAND notes in non-jumping
   instructions and jumping insns that have labels as operands
   (e.g. cbranchsi4).  */
79
void
80
rebuild_jump_labels (rtx f)
81
{
82
  rtx insn;
Richard Kenner committed
83

84
  timevar_push (TV_REBUILD_JUMP);
85
  init_label_info (f);
86
  mark_all_labels (f);
Richard Kenner committed
87

88 89 90
  /* Keep track of labels used from static data; we don't track them
     closely enough to delete them here, so make sure their reference
     count doesn't drop to zero.  */
Richard Kenner committed
91 92

  for (insn = forced_labels; insn; insn = XEXP (insn, 1))
93
    if (LABEL_P (XEXP (insn, 0)))
94
      LABEL_NUSES (XEXP (insn, 0))++;
95
  timevar_pop (TV_REBUILD_JUMP);
Jan Hubicka committed
96 97
}

98 99 100 101 102 103 104 105
/* Some old code expects exactly one BARRIER as the NEXT_INSN of a
   non-fallthru insn.  This is not generally true, as multiple barriers
   may have crept in, or the BARRIER may be separated from the last
   real insn by one or more NOTEs.

   This simple pass moves barriers and removes duplicates so that the
   old code is happy.
 */
106
unsigned int
107
cleanup_barriers (void)
108 109 110 111 112
{
  rtx insn, next, prev;
  for (insn = get_insns (); insn; insn = next)
    {
      next = NEXT_INSN (insn);
113
      if (BARRIER_P (insn))
114 115
	{
	  prev = prev_nonnote_insn (insn);
116
	  if (BARRIER_P (prev))
117
	    delete_insn (insn);
118 119 120 121
	  else if (prev != PREV_INSN (insn))
	    reorder_insns (insn, insn, prev);
	}
    }
122
  return 0;
123
}
Richard Kenner committed
124

125
struct rtl_opt_pass pass_cleanup_barriers =
126
{
127 128
 {
  RTL_PASS,
129
  "barriers",                           /* name */
130 131 132 133 134 135 136 137 138 139
  NULL,                                 /* gate */
  cleanup_barriers,                     /* execute */
  NULL,                                 /* sub */
  NULL,                                 /* next */
  0,                                    /* static_pass_number */
  0,                                    /* tv_id */
  0,                                    /* properties_required */
  0,                                    /* properties_provided */
  0,                                    /* properties_destroyed */
  0,                                    /* todo_flags_start */
140 141
  TODO_dump_func                        /* todo_flags_finish */
 }
142 143
};

144

145 146 147 148
/* Initialize LABEL_NUSES and JUMP_LABEL fields, add REG_LABEL_TARGET
   for remaining targets for JUMP_P.  Delete any REG_LABEL_OPERAND
   notes whose labels don't occur in the insn any more.  */

149
static void
150
init_label_info (rtx f)
151 152 153 154
{
  rtx insn;

  for (insn = f; insn; insn = NEXT_INSN (insn))
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
    {
      if (LABEL_P (insn))
	LABEL_NUSES (insn) = (LABEL_PRESERVE_P (insn) != 0);

      /* REG_LABEL_TARGET notes (including the JUMP_LABEL field) are
	 sticky and not reset here; that way we won't lose association
	 with a label when e.g. the source for a target register
	 disappears out of reach for targets that may use jump-target
	 registers.  Jump transformations are supposed to transform
	 any REG_LABEL_TARGET notes.  The target label reference in a
	 branch may disappear from the branch (and from the
	 instruction before it) for other reasons, like register
	 allocation.  */

      if (INSN_P (insn))
	{
	  rtx note, next;
172

173 174 175 176 177 178 179 180 181
	  for (note = REG_NOTES (insn); note; note = next)
	    {
	      next = XEXP (note, 1);
	      if (REG_NOTE_KIND (note) == REG_LABEL_OPERAND
		  && ! reg_mentioned_p (XEXP (note, 0), PATTERN (insn)))
		remove_note (insn, note);
	    }
	}
    }
182 183 184
}

/* Mark the label each jump jumps to.
Jan Hubicka committed
185
   Combine consecutive labels, and count uses of labels.  */
186 187

static void
188
mark_all_labels (rtx f)
189 190
{
  rtx insn;
191
  rtx prev_nonjump_insn = NULL;
192 193

  for (insn = f; insn; insn = NEXT_INSN (insn))
194
    if (INSN_P (insn))
195
      {
196
	mark_jump_label (PATTERN (insn), insn, 0);
197 198 199 200 201 202 203 204 205 206 207 208

	/* If the previous non-jump insn sets something to a label,
	   something that this jump insn uses, make that label the primary
	   target of this insn if we don't yet have any.  That previous
	   insn must be a single_set and not refer to more than one label.
	   The jump insn must not refer to other labels as jump targets
	   and must be a plain (set (pc) ...), maybe in a parallel, and
	   may refer to the item being set only directly or as one of the
	   arms in an IF_THEN_ELSE.  */
	if (! INSN_DELETED_P (insn)
	    && JUMP_P (insn)
	    && JUMP_LABEL (insn) == NULL)
209
	  {
210 211 212 213 214 215 216 217 218
	    rtx label_note = NULL;
	    rtx pc = pc_set (insn);
	    rtx pc_src = pc != NULL ? SET_SRC (pc) : NULL;

	    if (prev_nonjump_insn != NULL)
	      label_note
		= find_reg_note (prev_nonjump_insn, REG_LABEL_OPERAND, NULL);

	    if (label_note != NULL && pc_src != NULL)
219
	      {
220 221 222 223 224 225 226 227 228 229 230 231 232 233
		rtx label_set = single_set (prev_nonjump_insn);
		rtx label_dest
		  = label_set != NULL ? SET_DEST (label_set) : NULL;

		if (label_set != NULL
		    /* The source must be the direct LABEL_REF, not a
		       PLUS, UNSPEC, IF_THEN_ELSE etc.  */
		    && GET_CODE (SET_SRC (label_set)) == LABEL_REF
		    && (rtx_equal_p (label_dest, pc_src)
			|| (GET_CODE (pc_src) == IF_THEN_ELSE
			    && (rtx_equal_p (label_dest, XEXP (pc_src, 1))
				|| rtx_equal_p (label_dest,
						XEXP (pc_src, 2))))))
				
234
		  {
235 236 237 238 239 240 241 242 243 244
		    /* The CODE_LABEL referred to in the note must be the
		       CODE_LABEL in the LABEL_REF of the "set".  We can
		       conveniently use it for the marker function, which
		       requires a LABEL_REF wrapping.  */
		    gcc_assert (XEXP (label_note, 0)
				== XEXP (SET_SRC (label_set), 0));

		    mark_jump_label_1 (label_set, insn, false, true);
		    gcc_assert (JUMP_LABEL (insn)
				== XEXP (SET_SRC (label_set), 0));
245 246
		  }
	      }
247
	  }
248 249
	else if (! INSN_DELETED_P (insn))
	  prev_nonjump_insn = insn;
250
      }
251 252 253
    else if (LABEL_P (insn))
      prev_nonjump_insn = NULL;

254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277
  /* If we are in cfglayout mode, there may be non-insns between the
     basic blocks.  If those non-insns represent tablejump data, they
     contain label references that we must record.  */
  if (current_ir_type () == IR_RTL_CFGLAYOUT)
    {
      basic_block bb;
      rtx insn;
      FOR_EACH_BB (bb)
	{
	  for (insn = bb->il.rtl->header; insn; insn = NEXT_INSN (insn))
	    if (INSN_P (insn))
	      {
		gcc_assert (JUMP_TABLE_DATA_P (insn));
		mark_jump_label (PATTERN (insn), insn, 0);
	      }

	  for (insn = bb->il.rtl->footer; insn; insn = NEXT_INSN (insn))
	    if (INSN_P (insn))
	      {
		gcc_assert (JUMP_TABLE_DATA_P (insn));
		mark_jump_label (PATTERN (insn), insn, 0);
	      }
	}
    }
278
}
Richard Kenner committed
279

280
/* Given a comparison (CODE ARG0 ARG1), inside an insn, INSN, return a code
281 282 283 284 285 286
   of reversed comparison if it is possible to do so.  Otherwise return UNKNOWN.
   UNKNOWN may be returned in case we are having CC_MODE compare and we don't
   know whether it's source is floating point or integer comparison.  Machine
   description should define REVERSIBLE_CC_MODE and REVERSE_CONDITION macros
   to help this function avoid overhead in these cases.  */
enum rtx_code
287 288
reversed_comparison_code_parts (enum rtx_code code, const_rtx arg0,
				const_rtx arg1, const_rtx insn)
Richard Kenner committed
289
{
290
  enum machine_mode mode;
Richard Kenner committed
291 292

  /* If this is not actually a comparison, we can't reverse it.  */
293 294
  if (GET_RTX_CLASS (code) != RTX_COMPARE
      && GET_RTX_CLASS (code) != RTX_COMM_COMPARE)
295 296 297 298 299 300
    return UNKNOWN;

  mode = GET_MODE (arg0);
  if (mode == VOIDmode)
    mode = GET_MODE (arg1);

301 302 303
  /* First see if machine description supplies us way to reverse the
     comparison.  Give it priority over everything else to allow
     machine description to do tricks.  */
304
  if (GET_MODE_CLASS (mode) == MODE_CC
305 306 307
      && REVERSIBLE_CC_MODE (mode))
    {
#ifdef REVERSE_CONDITION
Kazu Hirata committed
308
      return REVERSE_CONDITION (code, mode);
309
#endif
Kazu Hirata committed
310 311
      return reverse_condition (code);
    }
Richard Kenner committed
312

313
  /* Try a few special cases based on the comparison code.  */
314 315
  switch (code)
    {
Kazu Hirata committed
316 317 318 319 320 321 322
    case GEU:
    case GTU:
    case LEU:
    case LTU:
    case NE:
    case EQ:
      /* It is always safe to reverse EQ and NE, even for the floating
323
	 point.  Similarly the unsigned comparisons are never used for
Kazu Hirata committed
324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340
	 floating point so we can reverse them in the default way.  */
      return reverse_condition (code);
    case ORDERED:
    case UNORDERED:
    case LTGT:
    case UNEQ:
      /* In case we already see unordered comparison, we can be sure to
	 be dealing with floating point so we don't need any more tests.  */
      return reverse_condition_maybe_unordered (code);
    case UNLT:
    case UNLE:
    case UNGT:
    case UNGE:
      /* We don't have safe way to reverse these yet.  */
      return UNKNOWN;
    default:
      break;
341 342
    }

343
  if (GET_MODE_CLASS (mode) == MODE_CC || CC0_P (arg0))
Richard Kenner committed
344
    {
345
      const_rtx prev;
346 347 348 349
      /* Try to search for the comparison to determine the real mode.
         This code is expensive, but with sane machine description it
         will be never used, since REVERSIBLE_CC_MODE will return true
         in all cases.  */
350
      if (! insn)
351
	return UNKNOWN;
Kazu Hirata committed
352

353
      /* These CONST_CAST's are okay because prev_nonnote_insn just
354
	 returns its argument and we assign it to a const_rtx
355
	 variable.  */
356
      for (prev = prev_nonnote_insn (CONST_CAST_RTX(insn));
357
	   prev != 0 && !LABEL_P (prev);
358
	   prev = prev_nonnote_insn (CONST_CAST_RTX(prev)))
359
	{
360
	  const_rtx set = set_of (arg0, prev);
361 362 363 364
	  if (set && GET_CODE (set) == SET
	      && rtx_equal_p (SET_DEST (set), arg0))
	    {
	      rtx src = SET_SRC (set);
Richard Kenner committed
365

366 367 368 369 370 371 372 373 374
	      if (GET_CODE (src) == COMPARE)
		{
		  rtx comparison = src;
		  arg0 = XEXP (src, 0);
		  mode = GET_MODE (arg0);
		  if (mode == VOIDmode)
		    mode = GET_MODE (XEXP (comparison, 1));
		  break;
		}
375
	      /* We can get past reg-reg moves.  This may be useful for model
376 377 378 379 380 381 382 383 384 385 386 387
	         of i387 comparisons that first move flag registers around.  */
	      if (REG_P (src))
		{
		  arg0 = src;
		  continue;
		}
	    }
	  /* If register is clobbered in some ununderstandable way,
	     give up.  */
	  if (set)
	    return UNKNOWN;
	}
Richard Kenner committed
388 389
    }

390 391
  /* Test for an integer condition, or a floating-point comparison
     in which NaNs can be ignored.  */
392 393 394
  if (GET_CODE (arg0) == CONST_INT
      || (GET_MODE (arg0) != VOIDmode
	  && GET_MODE_CLASS (mode) != MODE_CC
395
	  && !HONOR_NANS (mode)))
396 397 398 399 400
    return reverse_condition (code);

  return UNKNOWN;
}

Kazu Hirata committed
401
/* A wrapper around the previous function to take COMPARISON as rtx
402 403
   expression.  This simplifies many callers.  */
enum rtx_code
404
reversed_comparison_code (const_rtx comparison, const_rtx insn)
405
{
406
  if (!COMPARISON_P (comparison))
407 408 409 410 411
    return UNKNOWN;
  return reversed_comparison_code_parts (GET_CODE (comparison),
					 XEXP (comparison, 0),
					 XEXP (comparison, 1), insn);
}
412 413 414 415

/* Return comparison with reversed code of EXP.
   Return NULL_RTX in case we fail to do the reversal.  */
rtx
416
reversed_comparison (const_rtx exp, enum machine_mode mode)
417 418 419 420 421 422 423 424 425
{
  enum rtx_code reversed_code = reversed_comparison_code (exp, NULL_RTX);
  if (reversed_code == UNKNOWN)
    return NULL_RTX;
  else
    return simplify_gen_relational (reversed_code, mode, VOIDmode,
                                    XEXP (exp, 0), XEXP (exp, 1));
}

426

427 428 429 430 431
/* Given an rtx-code for a comparison, return the code for the negated
   comparison.  If no such code exists, return UNKNOWN.

   WATCH OUT!  reverse_condition is not safe to use on a jump that might
   be acting on the results of an IEEE floating point comparison, because
Kazu Hirata committed
432
   of the special treatment of non-signaling nans in comparisons.
433
   Use reversed_comparison_code instead.  */
Richard Kenner committed
434 435

enum rtx_code
436
reverse_condition (enum rtx_code code)
Richard Kenner committed
437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459
{
  switch (code)
    {
    case EQ:
      return NE;
    case NE:
      return EQ;
    case GT:
      return LE;
    case GE:
      return LT;
    case LT:
      return GE;
    case LE:
      return GT;
    case GTU:
      return LEU;
    case GEU:
      return LTU;
    case LTU:
      return GEU;
    case LEU:
      return GTU;
460 461 462 463 464 465 466 467 468 469
    case UNORDERED:
      return ORDERED;
    case ORDERED:
      return UNORDERED;

    case UNLT:
    case UNLE:
    case UNGT:
    case UNGE:
    case UNEQ:
470
    case LTGT:
471
      return UNKNOWN;
Richard Kenner committed
472 473

    default:
474
      gcc_unreachable ();
Richard Kenner committed
475 476 477
    }
}

478 479 480 481 482
/* Similar, but we're allowed to generate unordered comparisons, which
   makes it safe for IEEE floating-point.  Of course, we have to recognize
   that the target will support them too...  */

enum rtx_code
483
reverse_condition_maybe_unordered (enum rtx_code code)
484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516
{
  switch (code)
    {
    case EQ:
      return NE;
    case NE:
      return EQ;
    case GT:
      return UNLE;
    case GE:
      return UNLT;
    case LT:
      return UNGE;
    case LE:
      return UNGT;
    case LTGT:
      return UNEQ;
    case UNORDERED:
      return ORDERED;
    case ORDERED:
      return UNORDERED;
    case UNLT:
      return GE;
    case UNLE:
      return GT;
    case UNGT:
      return LE;
    case UNGE:
      return LT;
    case UNEQ:
      return LTGT;

    default:
517
      gcc_unreachable ();
518 519 520
    }
}

Richard Kenner committed
521 522 523 524
/* Similar, but return the code when two operands of a comparison are swapped.
   This IS safe for IEEE floating-point.  */

enum rtx_code
525
swap_condition (enum rtx_code code)
Richard Kenner committed
526 527 528 529 530
{
  switch (code)
    {
    case EQ:
    case NE:
531 532 533
    case UNORDERED:
    case ORDERED:
    case UNEQ:
534
    case LTGT:
Richard Kenner committed
535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552
      return code;

    case GT:
      return LT;
    case GE:
      return LE;
    case LT:
      return GT;
    case LE:
      return GE;
    case GTU:
      return LTU;
    case GEU:
      return LEU;
    case LTU:
      return GTU;
    case LEU:
      return GEU;
553 554 555 556 557 558 559 560 561
    case UNLT:
      return UNGT;
    case UNLE:
      return UNGE;
    case UNGT:
      return UNLT;
    case UNGE:
      return UNLE;

Richard Kenner committed
562
    default:
563
      gcc_unreachable ();
Richard Kenner committed
564 565 566 567 568 569 570 571
    }
}

/* Given a comparison CODE, return the corresponding unsigned comparison.
   If CODE is an equality comparison or already an unsigned comparison,
   CODE is returned.  */

enum rtx_code
572
unsigned_condition (enum rtx_code code)
Richard Kenner committed
573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593
{
  switch (code)
    {
    case EQ:
    case NE:
    case GTU:
    case GEU:
    case LTU:
    case LEU:
      return code;

    case GT:
      return GTU;
    case GE:
      return GEU;
    case LT:
      return LTU;
    case LE:
      return LEU;

    default:
594
      gcc_unreachable ();
Richard Kenner committed
595 596 597 598 599 600
    }
}

/* Similarly, return the signed version of a comparison.  */

enum rtx_code
601
signed_condition (enum rtx_code code)
Richard Kenner committed
602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622
{
  switch (code)
    {
    case EQ:
    case NE:
    case GT:
    case GE:
    case LT:
    case LE:
      return code;

    case GTU:
      return GT;
    case GEU:
      return GE;
    case LTU:
      return LT;
    case LEU:
      return LE;

    default:
623
      gcc_unreachable ();
Richard Kenner committed
624 625 626
    }
}

627
/* Return nonzero if CODE1 is more strict than CODE2, i.e., if the
Richard Kenner committed
628 629 630
   truth of CODE1 implies the truth of CODE2.  */

int
631
comparison_dominates_p (enum rtx_code code1, enum rtx_code code2)
Richard Kenner committed
632
{
633 634 635 636 637 638
  /* UNKNOWN comparison codes can happen as a result of trying to revert
     comparison codes.
     They can't match anything, so we have to reject them here.  */
  if (code1 == UNKNOWN || code2 == UNKNOWN)
    return 0;

Richard Kenner committed
639 640 641 642 643
  if (code1 == code2)
    return 1;

  switch (code1)
    {
644 645 646 647 648
    case UNEQ:
      if (code2 == UNLE || code2 == UNGE)
	return 1;
      break;

Richard Kenner committed
649
    case EQ:
650 651
      if (code2 == LE || code2 == LEU || code2 == GE || code2 == GEU
	  || code2 == ORDERED)
Richard Kenner committed
652 653 654
	return 1;
      break;

655 656 657 658 659
    case UNLT:
      if (code2 == UNLE || code2 == NE)
	return 1;
      break;

Richard Kenner committed
660
    case LT:
661 662 663 664 665 666
      if (code2 == LE || code2 == NE || code2 == ORDERED || code2 == LTGT)
	return 1;
      break;

    case UNGT:
      if (code2 == UNGE || code2 == NE)
Richard Kenner committed
667 668 669 670
	return 1;
      break;

    case GT:
671
      if (code2 == GE || code2 == NE || code2 == ORDERED || code2 == LTGT)
672 673 674 675 676 677 678 679 680 681 682
	return 1;
      break;

    case GE:
    case LE:
      if (code2 == ORDERED)
	return 1;
      break;

    case LTGT:
      if (code2 == NE || code2 == ORDERED)
Richard Kenner committed
683 684 685 686
	return 1;
      break;

    case LTU:
687
      if (code2 == LEU || code2 == NE)
Richard Kenner committed
688 689 690 691
	return 1;
      break;

    case GTU:
692
      if (code2 == GEU || code2 == NE)
Richard Kenner committed
693 694
	return 1;
      break;
695 696

    case UNORDERED:
697 698
      if (code2 == NE || code2 == UNEQ || code2 == UNLE || code2 == UNLT
	  || code2 == UNGE || code2 == UNGT)
699 700
	return 1;
      break;
Kazu Hirata committed
701

702 703
    default:
      break;
Richard Kenner committed
704 705 706 707 708 709 710 711
    }

  return 0;
}

/* Return 1 if INSN is an unconditional jump and nothing else.  */

int
712
simplejump_p (const_rtx insn)
Richard Kenner committed
713
{
714
  return (JUMP_P (insn)
715 716 717
	  && GET_CODE (PATTERN (insn)) == SET
	  && GET_CODE (SET_DEST (PATTERN (insn))) == PC
	  && GET_CODE (SET_SRC (PATTERN (insn))) == LABEL_REF);
Richard Kenner committed
718 719 720
}

/* Return nonzero if INSN is a (possibly) conditional jump
Kazu Hirata committed
721 722
   and nothing more.

723
   Use of this function is deprecated, since we need to support combined
724
   branch and compare insns.  Use any_condjump_p instead whenever possible.  */
Richard Kenner committed
725 726

int
727
condjump_p (const_rtx insn)
Richard Kenner committed
728
{
729
  const_rtx x = PATTERN (insn);
Jeff Law committed
730 731 732

  if (GET_CODE (x) != SET
      || GET_CODE (SET_DEST (x)) != PC)
Richard Kenner committed
733
    return 0;
Jeff Law committed
734 735 736

  x = SET_SRC (x);
  if (GET_CODE (x) == LABEL_REF)
737
    return 1;
Kazu Hirata committed
738 739 740 741 742 743 744 745
  else
    return (GET_CODE (x) == IF_THEN_ELSE
	    && ((GET_CODE (XEXP (x, 2)) == PC
		 && (GET_CODE (XEXP (x, 1)) == LABEL_REF
		     || GET_CODE (XEXP (x, 1)) == RETURN))
		|| (GET_CODE (XEXP (x, 1)) == PC
		    && (GET_CODE (XEXP (x, 2)) == LABEL_REF
			|| GET_CODE (XEXP (x, 2)) == RETURN))));
746 747
}

Jeff Law committed
748
/* Return nonzero if INSN is a (possibly) conditional jump inside a
749
   PARALLEL.
Kazu Hirata committed
750

751 752
   Use this function is deprecated, since we need to support combined
   branch and compare insns.  Use any_condjump_p instead whenever possible.  */
753 754

int
755
condjump_in_parallel_p (const_rtx insn)
756
{
757
  const_rtx x = PATTERN (insn);
758 759 760 761 762 763 764 765 766 767 768 769 770 771 772

  if (GET_CODE (x) != PARALLEL)
    return 0;
  else
    x = XVECEXP (x, 0, 0);

  if (GET_CODE (x) != SET)
    return 0;
  if (GET_CODE (SET_DEST (x)) != PC)
    return 0;
  if (GET_CODE (SET_SRC (x)) == LABEL_REF)
    return 1;
  if (GET_CODE (SET_SRC (x)) != IF_THEN_ELSE)
    return 0;
  if (XEXP (SET_SRC (x), 2) == pc_rtx
Richard Kenner committed
773 774 775 776 777 778 779 780 781 782
      && (GET_CODE (XEXP (SET_SRC (x), 1)) == LABEL_REF
	  || GET_CODE (XEXP (SET_SRC (x), 1)) == RETURN))
    return 1;
  if (XEXP (SET_SRC (x), 1) == pc_rtx
      && (GET_CODE (XEXP (SET_SRC (x), 2)) == LABEL_REF
	  || GET_CODE (XEXP (SET_SRC (x), 2)) == RETURN))
    return 1;
  return 0;
}

783 784
/* Return set of PC, otherwise NULL.  */

785
rtx
786
pc_set (const_rtx insn)
787 788
{
  rtx pat;
789
  if (!JUMP_P (insn))
790
    return NULL_RTX;
791
  pat = PATTERN (insn);
792 793 794 795 796

  /* The set is allowed to appear either as the insn pattern or
     the first set in a PARALLEL.  */
  if (GET_CODE (pat) == PARALLEL)
    pat = XVECEXP (pat, 0, 0);
797 798
  if (GET_CODE (pat) == SET && GET_CODE (SET_DEST (pat)) == PC)
    return pat;
799 800

  return NULL_RTX;
801 802
}

803 804 805
/* Return true when insn is an unconditional direct jump,
   possibly bundled inside a PARALLEL.  */

806
int
807
any_uncondjump_p (const_rtx insn)
808
{
809
  const_rtx x = pc_set (insn);
810 811 812 813
  if (!x)
    return 0;
  if (GET_CODE (SET_SRC (x)) != LABEL_REF)
    return 0;
814 815
  if (find_reg_note (insn, REG_NON_LOCAL_GOTO, NULL_RTX))
    return 0;
816 817 818
  return 1;
}

819
/* Return true when insn is a conditional jump.  This function works for
820 821
   instructions containing PC sets in PARALLELs.  The instruction may have
   various other effects so before removing the jump you must verify
822
   onlyjump_p.
823

824 825
   Note that unlike condjump_p it returns false for unconditional jumps.  */

826
int
827
any_condjump_p (const_rtx insn)
828
{
829
  const_rtx x = pc_set (insn);
830 831
  enum rtx_code a, b;

832 833
  if (!x)
    return 0;
834 835
  if (GET_CODE (SET_SRC (x)) != IF_THEN_ELSE)
    return 0;
836

837 838
  a = GET_CODE (XEXP (SET_SRC (x), 1));
  b = GET_CODE (XEXP (SET_SRC (x), 2));
839

840
  return ((b == PC && (a == LABEL_REF || a == RETURN))
Kazu Hirata committed
841
	  || (a == PC && (b == LABEL_REF || b == RETURN)));
842 843
}

844 845 846
/* Return the label of a conditional jump.  */

rtx
847
condjump_label (const_rtx insn)
848
{
849
  rtx x = pc_set (insn);
850

851
  if (!x)
852 853 854 855 856 857 858 859 860 861 862 863 864
    return NULL_RTX;
  x = SET_SRC (x);
  if (GET_CODE (x) == LABEL_REF)
    return x;
  if (GET_CODE (x) != IF_THEN_ELSE)
    return NULL_RTX;
  if (XEXP (x, 2) == pc_rtx && GET_CODE (XEXP (x, 1)) == LABEL_REF)
    return XEXP (x, 1);
  if (XEXP (x, 1) == pc_rtx && GET_CODE (XEXP (x, 2)) == LABEL_REF)
    return XEXP (x, 2);
  return NULL_RTX;
}

865 866 867
/* Return true if INSN is a (possibly conditional) return insn.  */

static int
868
returnjump_p_1 (rtx *loc, void *data ATTRIBUTE_UNUSED)
869 870
{
  rtx x = *loc;
871 872 873

  return x && (GET_CODE (x) == RETURN
	       || (GET_CODE (x) == SET && SET_IS_RETURN_P (x)));
874 875 876
}

int
877
returnjump_p (rtx insn)
878
{
879
  if (!JUMP_P (insn))
880
    return 0;
881 882 883
  return for_each_rtx (&PATTERN (insn), returnjump_p_1, NULL);
}

884 885 886 887
/* Return true if INSN is a jump that only transfers control and
   nothing more.  */

int
888
onlyjump_p (const_rtx insn)
889 890 891
{
  rtx set;

892
  if (!JUMP_P (insn))
893 894 895 896 897 898 899 900 901 902 903 904 905
    return 0;

  set = single_set (insn);
  if (set == NULL)
    return 0;
  if (GET_CODE (SET_DEST (set)) != PC)
    return 0;
  if (side_effects_p (SET_SRC (set)))
    return 0;

  return 1;
}

906 907
#ifdef HAVE_cc0

908
/* Return nonzero if X is an RTX that only sets the condition codes
909 910 911
   and has no side effects.  */

int
912
only_sets_cc0_p (const_rtx x)
913 914 915 916 917 918 919 920 921 922
{
  if (! x)
    return 0;

  if (INSN_P (x))
    x = PATTERN (x);

  return sets_cc0_p (x) == 1 && ! side_effects_p (x);
}

Richard Kenner committed
923 924 925 926 927 928
/* Return 1 if X is an RTX that does nothing but set the condition codes
   and CLOBBER or USE registers.
   Return -1 if X does explicitly set the condition codes,
   but also does other things.  */

int
929
sets_cc0_p (const_rtx x)
Richard Kenner committed
930
{
931 932 933 934 935 936
  if (! x)
    return 0;

  if (INSN_P (x))
    x = PATTERN (x);

Richard Kenner committed
937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955
  if (GET_CODE (x) == SET && SET_DEST (x) == cc0_rtx)
    return 1;
  if (GET_CODE (x) == PARALLEL)
    {
      int i;
      int sets_cc0 = 0;
      int other_things = 0;
      for (i = XVECLEN (x, 0) - 1; i >= 0; i--)
	{
	  if (GET_CODE (XVECEXP (x, 0, i)) == SET
	      && SET_DEST (XVECEXP (x, 0, i)) == cc0_rtx)
	    sets_cc0 = 1;
	  else if (GET_CODE (XVECEXP (x, 0, i)) == SET)
	    other_things = 1;
	}
      return ! sets_cc0 ? 0 : other_things ? -1 : 1;
    }
  return 0;
}
956
#endif
Richard Kenner committed
957

958 959 960 961 962 963 964 965
/* Find all CODE_LABELs referred to in X, and increment their use
   counts.  If INSN is a JUMP_INSN and there is at least one
   CODE_LABEL referenced in INSN as a jump target, then store the last
   one in JUMP_LABEL (INSN).  For a tablejump, this must be the label
   for the ADDR_VEC.  Store any other jump targets as REG_LABEL_TARGET
   notes.  If INSN is an INSN or a CALL_INSN or non-target operands of
   a JUMP_INSN, and there is at least one CODE_LABEL referenced in
   INSN, add a REG_LABEL_OPERAND note containing that label to INSN.
Richard Kenner committed
966 967 968 969 970

   Note that two labels separated by a loop-beginning note
   must be kept distinct if we have not yet done loop-optimization,
   because the gap between them is where loop-optimize
   will want to move invariant code to.  CROSS_JUMP tells us
971
   that loop-optimization is done with.  */
Richard Kenner committed
972

973
void
974
mark_jump_label (rtx x, rtx insn, int in_mem)
Richard Kenner committed
975
{
976 977 978 979
  mark_jump_label_1 (x, insn, in_mem != 0,
		     (insn != NULL && x == PATTERN (insn) && JUMP_P (insn)));
}

980
/* Worker function for mark_jump_label.  IN_MEM is TRUE when X occurs
981 982 983 984 985 986 987 988
   within a (MEM ...).  IS_TARGET is TRUE when X is to be treated as a
   jump-target; when the JUMP_LABEL field of INSN should be set or a
   REG_LABEL_TARGET note should be added, not a REG_LABEL_OPERAND
   note.  */

static void
mark_jump_label_1 (rtx x, rtx insn, bool in_mem, bool is_target)
{
989 990 991
  RTX_CODE code = GET_CODE (x);
  int i;
  const char *fmt;
Richard Kenner committed
992 993 994 995 996 997 998 999 1000 1001 1002 1003

  switch (code)
    {
    case PC:
    case CC0:
    case REG:
    case CONST_INT:
    case CONST_DOUBLE:
    case CLOBBER:
    case CALL:
      return;

1004
    case MEM:
1005
      in_mem = true;
1006 1007
      break;

1008 1009 1010 1011 1012 1013
    case SEQUENCE:
      for (i = 0; i < XVECLEN (x, 0); i++)
	mark_jump_label (PATTERN (XVECEXP (x, 0, i)),
			 XVECEXP (x, 0, i), 0);
      return;

1014 1015
    case SYMBOL_REF:
      if (!in_mem)
Kazu Hirata committed
1016
	return;
1017

1018
      /* If this is a constant-pool reference, see if it is a label.  */
1019
      if (CONSTANT_POOL_ADDRESS_P (x))
1020
	mark_jump_label_1 (get_pool_constant (x), insn, in_mem, is_target);
1021 1022
      break;

1023 1024 1025 1026 1027 1028 1029 1030 1031 1032
      /* Handle operands in the condition of an if-then-else as for a
	 non-jump insn.  */
    case IF_THEN_ELSE:
      if (!is_target)
	break;
      mark_jump_label_1 (XEXP (x, 0), insn, in_mem, false);
      mark_jump_label_1 (XEXP (x, 1), insn, in_mem, true);
      mark_jump_label_1 (XEXP (x, 2), insn, in_mem, true);
      return;

Richard Kenner committed
1033 1034
    case LABEL_REF:
      {
1035 1036
	rtx label = XEXP (x, 0);

1037 1038
	/* Ignore remaining references to unreachable labels that
	   have been deleted.  */
1039
	if (NOTE_P (label)
1040
	    && NOTE_KIND (label) == NOTE_INSN_DELETED_LABEL)
1041 1042
	  break;

1043
	gcc_assert (LABEL_P (label));
1044

Richard Stallman committed
1045 1046 1047
	/* Ignore references to labels of containing functions.  */
	if (LABEL_REF_NONLOCAL_P (x))
	  break;
1048

Richard Kenner committed
1049
	XEXP (x, 0) = label;
1050 1051
	if (! insn || ! INSN_DELETED_P (insn))
	  ++LABEL_NUSES (label);
1052

Richard Kenner committed
1053 1054
	if (insn)
	  {
1055
	    if (is_target
1056 1057 1058
		/* Do not change a previous setting of JUMP_LABEL.  If the
		   JUMP_LABEL slot is occupied by a different label,
		   create a note for this label.  */
1059
		&& (JUMP_LABEL (insn) == NULL || JUMP_LABEL (insn) == label))
Richard Kenner committed
1060
	      JUMP_LABEL (insn) = label;
1061
	    else
1062
	      {
1063 1064 1065 1066 1067 1068 1069 1070
		enum reg_note kind
		  = is_target ? REG_LABEL_TARGET : REG_LABEL_OPERAND;

		/* Add a REG_LABEL_OPERAND or REG_LABEL_TARGET note
		   for LABEL unless there already is one.  All uses of
		   a label, except for the primary target of a jump,
		   must have such a note.  */
		if (! find_reg_note (insn, kind, label))
1071
		  add_reg_note (insn, kind, label);
Richard Kenner committed
1072 1073 1074 1075 1076 1077 1078 1079 1080
	      }
	  }
	return;
      }

  /* Do walk the labels in a vector, but not the first operand of an
     ADDR_DIFF_VEC.  Don't set the JUMP_LABEL of a vector.  */
    case ADDR_VEC:
    case ADDR_DIFF_VEC:
1081 1082 1083
      if (! INSN_DELETED_P (insn))
	{
	  int eltnum = code == ADDR_DIFF_VEC ? 1 : 0;
Richard Kenner committed
1084

1085
	  for (i = 0; i < XVECLEN (x, eltnum); i++)
1086 1087
	    mark_jump_label_1 (XVECEXP (x, eltnum, i), NULL_RTX, in_mem,
			       is_target);
1088
	}
1089
      return;
Kazu Hirata committed
1090

1091 1092
    default:
      break;
Richard Kenner committed
1093 1094 1095
    }

  fmt = GET_RTX_FORMAT (code);
1096 1097 1098 1099

  /* The primary target of a tablejump is the label of the ADDR_VEC,
     which is canonically mentioned *last* in the insn.  To get it
     marked as JUMP_LABEL, we iterate over items in reverse order.  */
Richard Kenner committed
1100 1101 1102
  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
    {
      if (fmt[i] == 'e')
1103
	mark_jump_label_1 (XEXP (x, i), insn, in_mem, is_target);
Richard Kenner committed
1104 1105
      else if (fmt[i] == 'E')
	{
1106
	  int j;
1107 1108 1109 1110

	  for (j = XVECLEN (x, i) - 1; j >= 0; j--)
	    mark_jump_label_1 (XVECEXP (x, i, j), insn, in_mem,
			       is_target);
Richard Kenner committed
1111 1112 1113 1114 1115
	}
    }
}


1116
/* Delete insn INSN from the chain of insns and update label ref counts
1117
   and delete insns now unreachable.
1118

1119
   Returns the first insn after INSN that was not deleted.
Richard Kenner committed
1120

1121 1122
   Usage of this instruction is deprecated.  Use delete_insn instead and
   subsequent cfg_cleanup pass to delete unreachable code if needed.  */
Richard Kenner committed
1123 1124

rtx
1125
delete_related_insns (rtx insn)
Richard Kenner committed
1126
{
1127
  int was_code_label = (LABEL_P (insn));
1128
  rtx note;
1129
  rtx next = NEXT_INSN (insn), prev = PREV_INSN (insn);
Richard Kenner committed
1130 1131 1132 1133 1134 1135 1136 1137

  while (next && INSN_DELETED_P (next))
    next = NEXT_INSN (next);

  /* This insn is already deleted => return first following nondeleted.  */
  if (INSN_DELETED_P (insn))
    return next;

1138
  delete_insn (insn);
Richard Kenner committed
1139 1140 1141 1142

  /* If instruction is followed by a barrier,
     delete the barrier too.  */

1143
  if (next != 0 && BARRIER_P (next))
1144
    delete_insn (next);
Richard Kenner committed
1145 1146 1147 1148

  /* If deleting a jump, decrement the count of the label,
     and delete the label if it is now unused.  */

1149
  if (JUMP_P (insn) && JUMP_LABEL (insn))
1150 1151 1152
    {
      rtx lab = JUMP_LABEL (insn), lab_next;

1153
      if (LABEL_NUSES (lab) == 0)
1154 1155 1156 1157
	/* This can delete NEXT or PREV,
	   either directly if NEXT is JUMP_LABEL (INSN),
	   or indirectly through more levels of jumps.  */
	delete_related_insns (lab);
1158
      else if (tablejump_p (insn, NULL, &lab_next))
1159 1160
	{
	  /* If we're deleting the tablejump, delete the dispatch table.
1161
	     We may not be able to kill the label immediately preceding
1162 1163
	     just yet, as it might be referenced in code leading up to
	     the tablejump.  */
1164
	  delete_related_insns (lab_next);
1165 1166
	}
    }
Richard Kenner committed
1167

1168 1169
  /* Likewise if we're deleting a dispatch table.  */

1170
  if (JUMP_P (insn)
1171 1172 1173 1174 1175 1176 1177 1178
      && (GET_CODE (PATTERN (insn)) == ADDR_VEC
	  || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC))
    {
      rtx pat = PATTERN (insn);
      int i, diff_vec_p = GET_CODE (pat) == ADDR_DIFF_VEC;
      int len = XVECLEN (pat, diff_vec_p);

      for (i = 0; i < len; i++)
1179 1180
	if (LABEL_NUSES (XEXP (XVECEXP (pat, diff_vec_p, i), 0)) == 0)
	  delete_related_insns (XEXP (XVECEXP (pat, diff_vec_p, i), 0));
1181 1182 1183 1184 1185
      while (next && INSN_DELETED_P (next))
	next = NEXT_INSN (next);
      return next;
    }

1186 1187 1188
  /* Likewise for any JUMP_P / INSN / CALL_INSN with a
     REG_LABEL_OPERAND or REG_LABEL_TARGET note.  */
  if (INSN_P (insn))
1189
    for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
1190 1191
      if ((REG_NOTE_KIND (note) == REG_LABEL_OPERAND
	   || REG_NOTE_KIND (note) == REG_LABEL_TARGET)
1192
	  /* This could also be a NOTE_INSN_DELETED_LABEL note.  */
1193
	  && LABEL_P (XEXP (note, 0)))
1194 1195
	if (LABEL_NUSES (XEXP (note, 0)) == 0)
	  delete_related_insns (XEXP (note, 0));
1196

1197
  while (prev && (INSN_DELETED_P (prev) || NOTE_P (prev)))
Richard Kenner committed
1198 1199 1200 1201 1202 1203
    prev = PREV_INSN (prev);

  /* If INSN was a label and a dispatch table follows it,
     delete the dispatch table.  The tablejump must have gone already.
     It isn't useful to fall through into a table.  */

1204
  if (was_code_label
Richard Kenner committed
1205
      && NEXT_INSN (insn) != 0
1206
      && JUMP_P (NEXT_INSN (insn))
Richard Kenner committed
1207 1208
      && (GET_CODE (PATTERN (NEXT_INSN (insn))) == ADDR_VEC
	  || GET_CODE (PATTERN (NEXT_INSN (insn))) == ADDR_DIFF_VEC))
1209
    next = delete_related_insns (NEXT_INSN (insn));
Richard Kenner committed
1210 1211 1212

  /* If INSN was a label, delete insns following it if now unreachable.  */

1213
  if (was_code_label && prev && BARRIER_P (prev))
Richard Kenner committed
1214
    {
1215 1216
      enum rtx_code code;
      while (next)
Richard Kenner committed
1217
	{
1218
	  code = GET_CODE (next);
1219
	  if (code == NOTE)
Richard Kenner committed
1220
	    next = NEXT_INSN (next);
1221 1222 1223
	  /* Keep going past other deleted labels to delete what follows.  */
	  else if (code == CODE_LABEL && INSN_DELETED_P (next))
	    next = NEXT_INSN (next);
1224
	  else if (code == BARRIER || INSN_P (next))
Richard Kenner committed
1225 1226 1227 1228
	    /* Note: if this deletes a jump, it can cause more
	       deletion of unreachable code, after a different label.
	       As long as the value from this recursive call is correct,
	       this invocation functions correctly.  */
1229
	    next = delete_related_insns (next);
1230 1231
	  else
	    break;
Richard Kenner committed
1232 1233 1234
	}
    }

1235 1236 1237 1238 1239 1240
  /* I feel a little doubtful about this loop,
     but I see no clean and sure alternative way
     to find the first insn after INSN that is not now deleted.
     I hope this works.  */
  while (next && INSN_DELETED_P (next))
    next = NEXT_INSN (next);
Richard Kenner committed
1241 1242 1243 1244 1245 1246 1247 1248 1249
  return next;
}

/* Delete a range of insns from FROM to TO, inclusive.
   This is for the sake of peephole optimization, so assume
   that whatever these insns do will still be done by a new
   peephole insn that will replace them.  */

void
1250
delete_for_peephole (rtx from, rtx to)
Richard Kenner committed
1251
{
1252
  rtx insn = from;
Richard Kenner committed
1253 1254 1255

  while (1)
    {
1256 1257
      rtx next = NEXT_INSN (insn);
      rtx prev = PREV_INSN (insn);
Richard Kenner committed
1258

1259
      if (!NOTE_P (insn))
Richard Kenner committed
1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283
	{
	  INSN_DELETED_P (insn) = 1;

	  /* Patch this insn out of the chain.  */
	  /* We don't do this all at once, because we
	     must preserve all NOTEs.  */
	  if (prev)
	    NEXT_INSN (prev) = next;

	  if (next)
	    PREV_INSN (next) = prev;
	}

      if (insn == to)
	break;
      insn = next;
    }

  /* Note that if TO is an unconditional jump
     we *do not* delete the BARRIER that follows,
     since the peephole that replaces this sequence
     is also an unconditional jump in that case.  */
}

1284 1285
/* Throughout LOC, redirect OLABEL to NLABEL.  Treat null OLABEL or
   NLABEL as a return.  Accrue modifications into the change group.  */
Richard Kenner committed
1286

1287
static void
1288
redirect_exp_1 (rtx *loc, rtx olabel, rtx nlabel, rtx insn)
Richard Kenner committed
1289
{
1290 1291 1292 1293
  rtx x = *loc;
  RTX_CODE code = GET_CODE (x);
  int i;
  const char *fmt;
Richard Kenner committed
1294

1295
  if (code == LABEL_REF)
Richard Kenner committed
1296
    {
1297 1298 1299 1300
      if (XEXP (x, 0) == olabel)
	{
	  rtx n;
	  if (nlabel)
1301
	    n = gen_rtx_LABEL_REF (Pmode, nlabel);
1302
	  else
Kazu Hirata committed
1303
	    n = gen_rtx_RETURN (VOIDmode);
Richard Kenner committed
1304

1305 1306 1307 1308 1309 1310
	  validate_change (insn, loc, n, 1);
	  return;
	}
    }
  else if (code == RETURN && olabel == 0)
    {
1311
      if (nlabel)
1312
	x = gen_rtx_LABEL_REF (Pmode, nlabel);
1313 1314
      else
	x = gen_rtx_RETURN (VOIDmode);
1315 1316 1317 1318 1319
      if (loc == &PATTERN (insn))
	x = gen_rtx_SET (VOIDmode, pc_rtx, x);
      validate_change (insn, loc, x, 1);
      return;
    }
Richard Kenner committed
1320

1321 1322 1323 1324 1325 1326
  if (code == SET && nlabel == 0 && SET_DEST (x) == pc_rtx
      && GET_CODE (SET_SRC (x)) == LABEL_REF
      && XEXP (SET_SRC (x), 0) == olabel)
    {
      validate_change (insn, loc, gen_rtx_RETURN (VOIDmode), 1);
      return;
Richard Kenner committed
1327 1328
    }

1329 1330 1331 1332 1333 1334 1335 1336 1337
  if (code == IF_THEN_ELSE)
    {
      /* Skip the condition of an IF_THEN_ELSE.  We only want to
         change jump destinations, not eventual label comparisons.  */
      redirect_exp_1 (&XEXP (x, 1), olabel, nlabel, insn);
      redirect_exp_1 (&XEXP (x, 2), olabel, nlabel, insn);
      return;
    }

Richard Kenner committed
1338 1339 1340 1341
  fmt = GET_RTX_FORMAT (code);
  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
    {
      if (fmt[i] == 'e')
1342
	redirect_exp_1 (&XEXP (x, i), olabel, nlabel, insn);
1343
      else if (fmt[i] == 'E')
Richard Kenner committed
1344
	{
1345
	  int j;
Richard Kenner committed
1346
	  for (j = 0; j < XVECLEN (x, i); j++)
1347
	    redirect_exp_1 (&XVECEXP (x, i, j), olabel, nlabel, insn);
Richard Kenner committed
1348 1349
	}
    }
1350
}
Richard Kenner committed
1351

1352 1353 1354 1355 1356
/* Make JUMP go to NLABEL instead of where it jumps now.  Accrue
   the modifications into the change group.  Return false if we did
   not see how to do that.  */

int
1357
redirect_jump_1 (rtx jump, rtx nlabel)
1358 1359
{
  int ochanges = num_validated_changes ();
Jan Hubicka committed
1360 1361 1362 1363 1364 1365 1366 1367
  rtx *loc;

  if (GET_CODE (PATTERN (jump)) == PARALLEL)
    loc = &XVECEXP (PATTERN (jump), 0, 0);
  else
    loc = &PATTERN (jump);

  redirect_exp_1 (loc, JUMP_LABEL (jump), nlabel, jump);
1368 1369 1370 1371 1372 1373
  return num_validated_changes () > ochanges;
}

/* Make JUMP go to NLABEL instead of where it jumps now.  If the old
   jump target label is unused as a result, it and the code following
   it may be deleted.
Richard Kenner committed
1374 1375 1376 1377

   If NLABEL is zero, we are to turn the jump into a (possibly conditional)
   RETURN insn.

1378 1379
   The return value will be 1 if the change was made, 0 if it wasn't
   (this can only occur for NLABEL == 0).  */
Richard Kenner committed
1380 1381

int
1382
redirect_jump (rtx jump, rtx nlabel, int delete_unused)
Richard Kenner committed
1383
{
1384
  rtx olabel = JUMP_LABEL (jump);
Richard Kenner committed
1385 1386 1387 1388

  if (nlabel == olabel)
    return 1;

1389
  if (! redirect_jump_1 (jump, nlabel) || ! apply_change_group ())
Richard Kenner committed
1390 1391
    return 0;

1392 1393 1394 1395 1396
  redirect_jump_2 (jump, olabel, nlabel, delete_unused, 0);
  return 1;
}

/* Fix up JUMP_LABEL and label ref counts after OLABEL has been replaced with
1397
   NLABEL in JUMP.  
1398 1399 1400 1401 1402 1403 1404 1405
   If DELETE_UNUSED is positive, delete related insn to OLABEL if its ref
   count has dropped to zero.  */
void
redirect_jump_2 (rtx jump, rtx olabel, rtx nlabel, int delete_unused,
		 int invert)
{
  rtx note;

1406 1407
  gcc_assert (JUMP_LABEL (jump) == olabel);

1408
  /* Negative DELETE_UNUSED used to be used to signalize behavior on
1409 1410 1411
     moving FUNCTION_END note.  Just sanity check that no user still worry
     about this.  */
  gcc_assert (delete_unused >= 0);
Richard Kenner committed
1412 1413 1414 1415
  JUMP_LABEL (jump) = nlabel;
  if (nlabel)
    ++LABEL_NUSES (nlabel);

1416 1417 1418
  /* Update labels in any REG_EQUAL note.  */
  if ((note = find_reg_note (jump, REG_EQUAL, NULL_RTX)) != NULL_RTX)
    {
1419 1420 1421
      if (!nlabel || (invert && !invert_exp_1 (XEXP (note, 0), jump)))
	remove_note (jump, note);
      else
1422
	{
1423 1424
	  redirect_exp_1 (&XEXP (note, 0), olabel, nlabel, jump);
	  confirm_change_group ();
1425 1426 1427
	}
    }

1428
  if (olabel && --LABEL_NUSES (olabel) == 0 && delete_unused > 0
1429 1430
      /* Undefined labels will remain outside the insn stream.  */
      && INSN_UID (olabel))
1431
    delete_related_insns (olabel);
1432 1433
  if (invert)
    invert_br_probabilities (jump);
Richard Kenner committed
1434 1435
}

1436 1437 1438 1439
/* Invert the jump condition X contained in jump insn INSN.  Accrue the
   modifications into the change group.  Return nonzero for success.  */
static int
invert_exp_1 (rtx x, rtx insn)
1440
{
1441
  RTX_CODE code = GET_CODE (x);
1442 1443 1444

  if (code == IF_THEN_ELSE)
    {
1445 1446
      rtx comp = XEXP (x, 0);
      rtx tem;
1447
      enum rtx_code reversed_code;
1448 1449 1450 1451 1452 1453

      /* We can do this in two ways:  The preferable way, which can only
	 be done if this is not an integer comparison, is to reverse
	 the comparison code.  Otherwise, swap the THEN-part and ELSE-part
	 of the IF_THEN_ELSE.  If we can't do either, fail.  */

1454 1455 1456
      reversed_code = reversed_comparison_code (comp, insn);

      if (reversed_code != UNKNOWN)
1457 1458
	{
	  validate_change (insn, &XEXP (x, 0),
1459
			   gen_rtx_fmt_ee (reversed_code,
1460 1461 1462
					   GET_MODE (comp), XEXP (comp, 0),
					   XEXP (comp, 1)),
			   1);
1463
	  return 1;
1464
	}
Kazu Hirata committed
1465

1466 1467 1468
      tem = XEXP (x, 1);
      validate_change (insn, &XEXP (x, 1), XEXP (x, 2), 1);
      validate_change (insn, &XEXP (x, 2), tem, 1);
1469
      return 1;
1470
    }
Jan Hubicka committed
1471
  else
1472 1473 1474 1475 1476 1477 1478 1479 1480
    return 0;
}

/* Invert the condition of the jump JUMP, and make it jump to label
   NLABEL instead of where it jumps now.  Accrue changes into the
   change group.  Return false if we didn't see how to perform the
   inversion and redirection.  */

int
1481
invert_jump_1 (rtx jump, rtx nlabel)
1482
{
1483
  rtx x = pc_set (jump);
1484
  int ochanges;
1485
  int ok;
1486 1487

  ochanges = num_validated_changes ();
1488 1489 1490 1491
  gcc_assert (x);
  ok = invert_exp_1 (SET_SRC (x), jump);
  gcc_assert (ok);
  
1492 1493 1494
  if (num_validated_changes () == ochanges)
    return 0;

1495 1496 1497
  /* redirect_jump_1 will fail of nlabel == olabel, and the current use is
     in Pmode, so checking this is not merely an optimization.  */
  return nlabel == JUMP_LABEL (jump) || redirect_jump_1 (jump, nlabel);
1498 1499 1500 1501 1502 1503
}

/* Invert the condition of the jump JUMP, and make it jump to label
   NLABEL instead of where it jumps now.  Return true if successful.  */

int
1504
invert_jump (rtx jump, rtx nlabel, int delete_unused)
1505
{
1506
  rtx olabel = JUMP_LABEL (jump);
1507

1508
  if (invert_jump_1 (jump, nlabel) && apply_change_group ())
1509
    {
1510
      redirect_jump_2 (jump, olabel, nlabel, delete_unused, 1);
1511 1512
      return 1;
    }
1513
  cancel_changes (0);
1514 1515 1516
  return 0;
}

Richard Kenner committed
1517 1518

/* Like rtx_equal_p except that it considers two REGs as equal
1519 1520
   if they renumber to the same value and considers two commutative
   operations to be the same if the order of the operands has been
1521
   reversed.  */
Richard Kenner committed
1522 1523

int
1524
rtx_renumbered_equal_p (const_rtx x, const_rtx y)
Richard Kenner committed
1525
{
1526
  int i;
1527
  const enum rtx_code code = GET_CODE (x);
1528
  const char *fmt;
Kazu Hirata committed
1529

Richard Kenner committed
1530 1531
  if (x == y)
    return 1;
1532

1533 1534 1535
  if ((code == REG || (code == SUBREG && REG_P (SUBREG_REG (x))))
      && (REG_P (y) || (GET_CODE (y) == SUBREG
				  && REG_P (SUBREG_REG (y)))))
Richard Kenner committed
1536
    {
1537
      int reg_x = -1, reg_y = -1;
1538
      int byte_x = 0, byte_y = 0;
Richard Kenner committed
1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549

      if (GET_MODE (x) != GET_MODE (y))
	return 0;

      /* If we haven't done any renumbering, don't
	 make any assumptions.  */
      if (reg_renumber == 0)
	return rtx_equal_p (x, y);

      if (code == SUBREG)
	{
1550
	  reg_x = REGNO (SUBREG_REG (x));
1551
	  byte_x = SUBREG_BYTE (x);
1552 1553 1554

	  if (reg_renumber[reg_x] >= 0)
	    {
1555 1556 1557 1558 1559
	      if (!subreg_offset_representable_p (reg_renumber[reg_x],
						  GET_MODE (SUBREG_REG (x)),
						  byte_x,
						  GET_MODE (x)))
		return 0;
1560 1561 1562 1563 1564
	      reg_x = subreg_regno_offset (reg_renumber[reg_x],
					   GET_MODE (SUBREG_REG (x)),
					   byte_x,
					   GET_MODE (x));
	      byte_x = 0;
1565
	    }
1566 1567 1568 1569 1570
	  else if (!subreg_offset_representable_p (reg_x,
						   GET_MODE (SUBREG_REG (x)),
						   byte_x,
						   GET_MODE (x)))
	    return 0;
Richard Kenner committed
1571 1572 1573
	}
      else
	{
1574 1575 1576
	  reg_x = REGNO (x);
	  if (reg_renumber[reg_x] >= 0)
	    reg_x = reg_renumber[reg_x];
Richard Kenner committed
1577
	}
1578

Richard Kenner committed
1579 1580
      if (GET_CODE (y) == SUBREG)
	{
1581
	  reg_y = REGNO (SUBREG_REG (y));
1582
	  byte_y = SUBREG_BYTE (y);
1583 1584 1585

	  if (reg_renumber[reg_y] >= 0)
	    {
1586 1587 1588 1589 1590
	      if (!subreg_offset_representable_p (reg_renumber[reg_y],
						  GET_MODE (SUBREG_REG (y)),
						  byte_y,
						  GET_MODE (y)))
		return 0;
1591 1592 1593 1594 1595
	      reg_y = subreg_regno_offset (reg_renumber[reg_y],
					   GET_MODE (SUBREG_REG (y)),
					   byte_y,
					   GET_MODE (y));
	      byte_y = 0;
1596
	    }
1597 1598 1599 1600 1601
	  else if (!subreg_offset_representable_p (reg_y,
						   GET_MODE (SUBREG_REG (y)),
						   byte_y,
						   GET_MODE (y)))
	    return 0;
Richard Kenner committed
1602 1603 1604
	}
      else
	{
1605 1606 1607
	  reg_y = REGNO (y);
	  if (reg_renumber[reg_y] >= 0)
	    reg_y = reg_renumber[reg_y];
Richard Kenner committed
1608
	}
1609

1610
      return reg_x >= 0 && reg_x == reg_y && byte_x == byte_y;
Richard Kenner committed
1611
    }
1612

Kazu Hirata committed
1613
  /* Now we have disposed of all the cases
Richard Kenner committed
1614 1615 1616
     in which different rtx codes can match.  */
  if (code != GET_CODE (y))
    return 0;
1617

Richard Kenner committed
1618 1619 1620 1621 1622 1623 1624
  switch (code)
    {
    case PC:
    case CC0:
    case ADDR_VEC:
    case ADDR_DIFF_VEC:
    case CONST_INT:
1625
    case CONST_DOUBLE:
1626
      return 0;
Richard Kenner committed
1627 1628

    case LABEL_REF:
Richard Stallman committed
1629 1630 1631
      /* We can't assume nonlocal labels have their following insns yet.  */
      if (LABEL_REF_NONLOCAL_P (x) || LABEL_REF_NONLOCAL_P (y))
	return XEXP (x, 0) == XEXP (y, 0);
1632

Richard Kenner committed
1633 1634 1635 1636 1637 1638 1639
      /* Two label-refs are equivalent if they point at labels
	 in the same position in the instruction stream.  */
      return (next_real_insn (XEXP (x, 0))
	      == next_real_insn (XEXP (y, 0)));

    case SYMBOL_REF:
      return XSTR (x, 0) == XSTR (y, 0);
1640

1641 1642 1643 1644
    case CODE_LABEL:
      /* If we didn't match EQ equality above, they aren't the same.  */
      return 0;

1645 1646
    default:
      break;
Richard Kenner committed
1647 1648 1649 1650 1651 1652 1653
    }

  /* (MULT:SI x y) and (MULT:HI x y) are NOT equivalent.  */

  if (GET_MODE (x) != GET_MODE (y))
    return 0;

1654
  /* For commutative operations, the RTX match if the operand match in any
1655 1656
     order.  Also handle the simple binary and unary cases without a loop.  */
  if (targetm.commutative_p (x, UNKNOWN))
1657 1658 1659 1660
    return ((rtx_renumbered_equal_p (XEXP (x, 0), XEXP (y, 0))
	     && rtx_renumbered_equal_p (XEXP (x, 1), XEXP (y, 1)))
	    || (rtx_renumbered_equal_p (XEXP (x, 0), XEXP (y, 1))
		&& rtx_renumbered_equal_p (XEXP (x, 1), XEXP (y, 0))));
1661
  else if (NON_COMMUTATIVE_P (x))
1662 1663
    return (rtx_renumbered_equal_p (XEXP (x, 0), XEXP (y, 0))
	    && rtx_renumbered_equal_p (XEXP (x, 1), XEXP (y, 1)));
1664
  else if (UNARY_P (x))
1665 1666
    return rtx_renumbered_equal_p (XEXP (x, 0), XEXP (y, 0));

Richard Kenner committed
1667 1668 1669 1670 1671 1672
  /* Compare the elements.  If any pair of corresponding elements
     fail to match, return 0 for the whole things.  */

  fmt = GET_RTX_FORMAT (code);
  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
    {
1673
      int j;
Richard Kenner committed
1674 1675
      switch (fmt[i])
	{
1676 1677 1678 1679 1680
	case 'w':
	  if (XWINT (x, i) != XWINT (y, i))
	    return 0;
	  break;

Richard Kenner committed
1681 1682 1683 1684 1685
	case 'i':
	  if (XINT (x, i) != XINT (y, i))
	    return 0;
	  break;

1686 1687 1688 1689 1690
	case 't':
	  if (XTREE (x, i) != XTREE (y, i))
	    return 0;
	  break;

Richard Kenner committed
1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703
	case 's':
	  if (strcmp (XSTR (x, i), XSTR (y, i)))
	    return 0;
	  break;

	case 'e':
	  if (! rtx_renumbered_equal_p (XEXP (x, i), XEXP (y, i)))
	    return 0;
	  break;

	case 'u':
	  if (XEXP (x, i) != XEXP (y, i))
	    return 0;
1704
	  /* Fall through.  */
Richard Kenner committed
1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716
	case '0':
	  break;

	case 'E':
	  if (XVECLEN (x, i) != XVECLEN (y, i))
	    return 0;
	  for (j = XVECLEN (x, i) - 1; j >= 0; j--)
	    if (!rtx_renumbered_equal_p (XVECEXP (x, i, j), XVECEXP (y, i, j)))
	      return 0;
	  break;

	default:
1717
	  gcc_unreachable ();
Richard Kenner committed
1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728
	}
    }
  return 1;
}

/* If X is a hard register or equivalent to one or a subregister of one,
   return the hard register number.  If X is a pseudo register that was not
   assigned a hard register, return the pseudo register number.  Otherwise,
   return -1.  Any rtx is valid for X.  */

int
1729
true_regnum (const_rtx x)
Richard Kenner committed
1730
{
1731
  if (REG_P (x))
Richard Kenner committed
1732 1733 1734 1735 1736 1737 1738 1739
    {
      if (REGNO (x) >= FIRST_PSEUDO_REGISTER && reg_renumber[REGNO (x)] >= 0)
	return reg_renumber[REGNO (x)];
      return REGNO (x);
    }
  if (GET_CODE (x) == SUBREG)
    {
      int base = true_regnum (SUBREG_REG (x));
1740 1741 1742 1743 1744
      if (base >= 0
	  && base < FIRST_PSEUDO_REGISTER
	  && subreg_offset_representable_p (REGNO (SUBREG_REG (x)),
					    GET_MODE (SUBREG_REG (x)),
					    SUBREG_BYTE (x), GET_MODE (x)))
1745 1746 1747
	return base + subreg_regno_offset (REGNO (SUBREG_REG (x)),
					   GET_MODE (SUBREG_REG (x)),
					   SUBREG_BYTE (x), GET_MODE (x));
Richard Kenner committed
1748 1749 1750
    }
  return -1;
}
1751 1752 1753

/* Return regno of the register REG and handle subregs too.  */
unsigned int
1754
reg_or_subregno (const_rtx reg)
1755 1756
{
  if (GET_CODE (reg) == SUBREG)
1757 1758 1759
    reg = SUBREG_REG (reg);
  gcc_assert (REG_P (reg));
  return REGNO (reg);
1760
}