jump.c 48.7 KB
Newer Older
Richard Kenner committed
1
/* Optimize jump instructions, for GNU compiler.
2
   Copyright (C) 1987-2013 Free Software Foundation, Inc.
Richard Kenner committed
3

4
This file is part of GCC.
Richard Kenner committed
5

6 7
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
8
Software Foundation; either version 3, or (at your option) any later
9
version.
Richard Kenner committed
10

11 12 13 14
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
15 16

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

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

   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
30 31
   at by later passes.  For return insns, it contains either a
   RETURN or a SIMPLE_RETURN rtx.
Richard Kenner committed
32

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

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

/* 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.  */

65 66
static void init_label_info (rtx);
static void mark_all_labels (rtx);
67
static void mark_jump_label_1 (rtx, rtx, bool, bool);
68
static void mark_jump_label_asm (rtx, rtx);
69
static void redirect_exp_1 (rtx *, rtx, rtx, rtx);
70
static int invert_exp_1 (rtx, rtx);
71
static int returnjump_p_1 (rtx *, void *);
72

73 74 75
/* Worker for rebuild_jump_labels and rebuild_jump_labels_chain.  */
static void
rebuild_jump_labels_1 (rtx f, bool count_forced)
76
{
77
  rtx insn;
Richard Kenner committed
78

79
  timevar_push (TV_REBUILD_JUMP);
80
  init_label_info (f);
81
  mark_all_labels (f);
Richard Kenner committed
82

83 84 85
  /* 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
86

87 88 89 90
  if (count_forced)
    for (insn = forced_labels; insn; insn = XEXP (insn, 1))
      if (LABEL_P (XEXP (insn, 0)))
	LABEL_NUSES (XEXP (insn, 0))++;
91
  timevar_pop (TV_REBUILD_JUMP);
Jan Hubicka committed
92
}
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111

/* 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).  */
void
rebuild_jump_labels (rtx f)
{
  rebuild_jump_labels_1 (f, true);
}

/* This function is like rebuild_jump_labels, but doesn't run over
   forced_labels.  It can be used on insn chains that aren't the 
   main function chain.  */
void
rebuild_jump_labels_chain (rtx chain)
{
  rebuild_jump_labels_1 (chain, false);
}
Jan Hubicka committed
112

113 114 115 116 117 118 119 120
/* 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.
 */
121
unsigned int
122
cleanup_barriers (void)
123 124 125 126 127
{
  rtx insn, next, prev;
  for (insn = get_insns (); insn; insn = next)
    {
      next = NEXT_INSN (insn);
128
      if (BARRIER_P (insn))
129 130
	{
	  prev = prev_nonnote_insn (insn);
131 132
	  if (!prev)
	    continue;
133
	  if (BARRIER_P (prev))
134
	    delete_insn (insn);
135 136 137 138
	  else if (prev != PREV_INSN (insn))
	    reorder_insns (insn, insn, prev);
	}
    }
139
  return 0;
140
}
Richard Kenner committed
141

142
struct rtl_opt_pass pass_cleanup_barriers =
143
{
144 145
 {
  RTL_PASS,
146
  "barriers",                           /* name */
147
  OPTGROUP_NONE,                        /* optinfo_flags */
148 149 150 151 152
  NULL,                                 /* gate */
  cleanup_barriers,                     /* execute */
  NULL,                                 /* sub */
  NULL,                                 /* next */
  0,                                    /* static_pass_number */
153
  TV_NONE,                              /* tv_id */
154 155 156 157
  0,                                    /* properties_required */
  0,                                    /* properties_provided */
  0,                                    /* properties_destroyed */
  0,                                    /* todo_flags_start */
158
  0                                     /* todo_flags_finish */
159
 }
160 161
};

162

163 164 165 166
/* 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.  */

167
static void
168
init_label_info (rtx f)
169 170 171 172
{
  rtx insn;

  for (insn = f; insn; insn = NEXT_INSN (insn))
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
    {
      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;
190

191 192 193 194 195 196 197 198 199
	  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);
	    }
	}
    }
200 201
}

202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249
/* A subroutine of mark_all_labels.  Trivially propagate a simple label
   load into a jump_insn that uses it.  */

static void
maybe_propagate_label_ref (rtx jump_insn, rtx prev_nonjump_insn)
{
  rtx label_note, pc, pc_src;

  pc = pc_set (jump_insn);
  pc_src = pc != NULL ? SET_SRC (pc) : NULL;
  label_note = find_reg_note (prev_nonjump_insn, REG_LABEL_OPERAND, NULL);

  /* 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 (label_note != NULL && pc_src != NULL)
    {
      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))))))
	{
	  /* 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, jump_insn, false, true);

	  gcc_assert (JUMP_LABEL (jump_insn) == XEXP (label_note, 0));
	}
    }
}

250
/* Mark the label each jump jumps to.
Jan Hubicka committed
251
   Combine consecutive labels, and count uses of labels.  */
252 253

static void
254
mark_all_labels (rtx f)
255 256 257
{
  rtx insn;

258 259 260 261 262
  if (current_ir_type () == IR_RTL_CFGLAYOUT)
    {
      basic_block bb;
      FOR_EACH_BB (bb)
	{
263 264 265 266 267 268 269 270 271 272 273 274 275
	  /* In cfglayout mode, we don't bother with trivial next-insn
	     propagation of LABEL_REFs into JUMP_LABEL.  This will be
	     handled by other optimizers using better algorithms.  */
	  FOR_BB_INSNS (bb, insn)
	    {
	      gcc_assert (! INSN_DELETED_P (insn));
	      if (NONDEBUG_INSN_P (insn))
	        mark_jump_label (PATTERN (insn), insn, 0);
	    }

	  /* 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.  */
276
	  for (insn = BB_HEADER (bb); insn; insn = NEXT_INSN (insn))
277 278 279 280 281
	    if (INSN_P (insn))
	      {
		gcc_assert (JUMP_TABLE_DATA_P (insn));
		mark_jump_label (PATTERN (insn), insn, 0);
	      }
282
	  for (insn = BB_FOOTER (bb); insn; insn = NEXT_INSN (insn))
283 284 285 286 287 288 289
	    if (INSN_P (insn))
	      {
		gcc_assert (JUMP_TABLE_DATA_P (insn));
		mark_jump_label (PATTERN (insn), insn, 0);
	      }
	}
    }
290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311
  else
    {
      rtx prev_nonjump_insn = NULL;
      for (insn = f; insn; insn = NEXT_INSN (insn))
	{
	  if (INSN_DELETED_P (insn))
	    ;
	  else if (LABEL_P (insn))
	    prev_nonjump_insn = NULL;
	  else if (NONDEBUG_INSN_P (insn))
	    {
	      mark_jump_label (PATTERN (insn), insn, 0);
	      if (JUMP_P (insn))
		{
		  if (JUMP_LABEL (insn) == NULL && prev_nonjump_insn != NULL)
		    maybe_propagate_label_ref (insn, prev_nonjump_insn);
		}
	      else
		prev_nonjump_insn = insn;
	    }
	}
    }
312
}
Richard Kenner committed
313

314
/* Given a comparison (CODE ARG0 ARG1), inside an insn, INSN, return a code
315 316 317 318 319 320
   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
321 322
reversed_comparison_code_parts (enum rtx_code code, const_rtx arg0,
				const_rtx arg1, const_rtx insn)
Richard Kenner committed
323
{
324
  enum machine_mode mode;
Richard Kenner committed
325 326

  /* If this is not actually a comparison, we can't reverse it.  */
327 328
  if (GET_RTX_CLASS (code) != RTX_COMPARE
      && GET_RTX_CLASS (code) != RTX_COMM_COMPARE)
329 330 331 332 333 334
    return UNKNOWN;

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

335 336 337
  /* 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.  */
338
  if (GET_MODE_CLASS (mode) == MODE_CC
339 340 341
      && REVERSIBLE_CC_MODE (mode))
    {
#ifdef REVERSE_CONDITION
Kazu Hirata committed
342
      return REVERSE_CONDITION (code, mode);
343
#else
Kazu Hirata committed
344
      return reverse_condition (code);
345
#endif
Kazu Hirata committed
346
    }
Richard Kenner committed
347

348
  /* Try a few special cases based on the comparison code.  */
349 350
  switch (code)
    {
Kazu Hirata committed
351 352 353 354 355 356 357
    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
358
	 point.  Similarly the unsigned comparisons are never used for
Kazu Hirata committed
359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375
	 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;
376 377
    }

378
  if (GET_MODE_CLASS (mode) == MODE_CC || CC0_P (arg0))
Richard Kenner committed
379
    {
380
      const_rtx prev;
381 382 383 384
      /* 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.  */
385
      if (! insn)
386
	return UNKNOWN;
Kazu Hirata committed
387

388
      /* These CONST_CAST's are okay because prev_nonnote_insn just
389
	 returns its argument and we assign it to a const_rtx
390
	 variable.  */
391
      for (prev = prev_nonnote_insn (CONST_CAST_RTX(insn));
392
	   prev != 0 && !LABEL_P (prev);
393
	   prev = prev_nonnote_insn (CONST_CAST_RTX(prev)))
394
	{
395
	  const_rtx set = set_of (arg0, prev);
396 397 398 399
	  if (set && GET_CODE (set) == SET
	      && rtx_equal_p (SET_DEST (set), arg0))
	    {
	      rtx src = SET_SRC (set);
Richard Kenner committed
400

401 402 403 404 405 406 407 408 409
	      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;
		}
410
	      /* We can get past reg-reg moves.  This may be useful for model
411 412 413 414 415 416 417 418 419 420 421 422
	         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
423 424
    }

425 426
  /* Test for an integer condition, or a floating-point comparison
     in which NaNs can be ignored.  */
Shujing Zhao committed
427
  if (CONST_INT_P (arg0)
428 429
      || (GET_MODE (arg0) != VOIDmode
	  && GET_MODE_CLASS (mode) != MODE_CC
430
	  && !HONOR_NANS (mode)))
431 432 433 434 435
    return reverse_condition (code);

  return UNKNOWN;
}

Kazu Hirata committed
436
/* A wrapper around the previous function to take COMPARISON as rtx
437 438
   expression.  This simplifies many callers.  */
enum rtx_code
439
reversed_comparison_code (const_rtx comparison, const_rtx insn)
440
{
441
  if (!COMPARISON_P (comparison))
442 443 444 445 446
    return UNKNOWN;
  return reversed_comparison_code_parts (GET_CODE (comparison),
					 XEXP (comparison, 0),
					 XEXP (comparison, 1), insn);
}
447 448 449 450

/* Return comparison with reversed code of EXP.
   Return NULL_RTX in case we fail to do the reversal.  */
rtx
451
reversed_comparison (const_rtx exp, enum machine_mode mode)
452 453 454 455 456 457 458 459 460
{
  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));
}

461

462 463 464 465 466
/* 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
467
   of the special treatment of non-signaling nans in comparisons.
468
   Use reversed_comparison_code instead.  */
Richard Kenner committed
469 470

enum rtx_code
471
reverse_condition (enum rtx_code code)
Richard Kenner committed
472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494
{
  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;
495 496 497 498 499 500 501 502 503 504
    case UNORDERED:
      return ORDERED;
    case ORDERED:
      return UNORDERED;

    case UNLT:
    case UNLE:
    case UNGT:
    case UNGE:
    case UNEQ:
505
    case LTGT:
506
      return UNKNOWN;
Richard Kenner committed
507 508

    default:
509
      gcc_unreachable ();
Richard Kenner committed
510 511 512
    }
}

513 514 515 516 517
/* 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
518
reverse_condition_maybe_unordered (enum rtx_code code)
519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551
{
  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:
552
      gcc_unreachable ();
553 554 555
    }
}

Richard Kenner committed
556 557 558 559
/* Similar, but return the code when two operands of a comparison are swapped.
   This IS safe for IEEE floating-point.  */

enum rtx_code
560
swap_condition (enum rtx_code code)
Richard Kenner committed
561 562 563 564 565
{
  switch (code)
    {
    case EQ:
    case NE:
566 567 568
    case UNORDERED:
    case ORDERED:
    case UNEQ:
569
    case LTGT:
Richard Kenner committed
570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587
      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;
588 589 590 591 592 593 594 595 596
    case UNLT:
      return UNGT;
    case UNLE:
      return UNGE;
    case UNGT:
      return UNLT;
    case UNGE:
      return UNLE;

Richard Kenner committed
597
    default:
598
      gcc_unreachable ();
Richard Kenner committed
599 600 601 602 603 604 605 606
    }
}

/* 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
607
unsigned_condition (enum rtx_code code)
Richard Kenner committed
608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628
{
  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:
629
      gcc_unreachable ();
Richard Kenner committed
630 631 632 633 634 635
    }
}

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

enum rtx_code
636
signed_condition (enum rtx_code code)
Richard Kenner committed
637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657
{
  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:
658
      gcc_unreachable ();
Richard Kenner committed
659 660 661
    }
}

662
/* Return nonzero if CODE1 is more strict than CODE2, i.e., if the
Richard Kenner committed
663 664 665
   truth of CODE1 implies the truth of CODE2.  */

int
666
comparison_dominates_p (enum rtx_code code1, enum rtx_code code2)
Richard Kenner committed
667
{
668 669 670 671 672 673
  /* 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
674 675 676 677 678
  if (code1 == code2)
    return 1;

  switch (code1)
    {
679 680 681 682 683
    case UNEQ:
      if (code2 == UNLE || code2 == UNGE)
	return 1;
      break;

Richard Kenner committed
684
    case EQ:
685 686
      if (code2 == LE || code2 == LEU || code2 == GE || code2 == GEU
	  || code2 == ORDERED)
Richard Kenner committed
687 688 689
	return 1;
      break;

690 691 692 693 694
    case UNLT:
      if (code2 == UNLE || code2 == NE)
	return 1;
      break;

Richard Kenner committed
695
    case LT:
696 697 698 699 700 701
      if (code2 == LE || code2 == NE || code2 == ORDERED || code2 == LTGT)
	return 1;
      break;

    case UNGT:
      if (code2 == UNGE || code2 == NE)
Richard Kenner committed
702 703 704 705
	return 1;
      break;

    case GT:
706
      if (code2 == GE || code2 == NE || code2 == ORDERED || code2 == LTGT)
707 708 709 710 711 712 713 714 715 716 717
	return 1;
      break;

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

    case LTGT:
      if (code2 == NE || code2 == ORDERED)
Richard Kenner committed
718 719 720 721
	return 1;
      break;

    case LTU:
722
      if (code2 == LEU || code2 == NE)
Richard Kenner committed
723 724 725 726
	return 1;
      break;

    case GTU:
727
      if (code2 == GEU || code2 == NE)
Richard Kenner committed
728 729
	return 1;
      break;
730 731

    case UNORDERED:
732 733
      if (code2 == NE || code2 == UNEQ || code2 == UNLE || code2 == UNLT
	  || code2 == UNGE || code2 == UNGT)
734 735
	return 1;
      break;
Kazu Hirata committed
736

737 738
    default:
      break;
Richard Kenner committed
739 740 741 742 743 744 745 746
    }

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

int
747
simplejump_p (const_rtx insn)
Richard Kenner committed
748
{
749
  return (JUMP_P (insn)
750 751 752
	  && GET_CODE (PATTERN (insn)) == SET
	  && GET_CODE (SET_DEST (PATTERN (insn))) == PC
	  && GET_CODE (SET_SRC (PATTERN (insn))) == LABEL_REF);
Richard Kenner committed
753 754 755
}

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

758
   Use of this function is deprecated, since we need to support combined
759
   branch and compare insns.  Use any_condjump_p instead whenever possible.  */
Richard Kenner committed
760 761

int
762
condjump_p (const_rtx insn)
Richard Kenner committed
763
{
764
  const_rtx x = PATTERN (insn);
Jeff Law committed
765 766 767

  if (GET_CODE (x) != SET
      || GET_CODE (SET_DEST (x)) != PC)
Richard Kenner committed
768
    return 0;
Jeff Law committed
769 770 771

  x = SET_SRC (x);
  if (GET_CODE (x) == LABEL_REF)
772
    return 1;
Kazu Hirata committed
773 774 775 776
  else
    return (GET_CODE (x) == IF_THEN_ELSE
	    && ((GET_CODE (XEXP (x, 2)) == PC
		 && (GET_CODE (XEXP (x, 1)) == LABEL_REF
777
		     || ANY_RETURN_P (XEXP (x, 1))))
Kazu Hirata committed
778 779
		|| (GET_CODE (XEXP (x, 1)) == PC
		    && (GET_CODE (XEXP (x, 2)) == LABEL_REF
780
			|| ANY_RETURN_P (XEXP (x, 2))))));
781 782
}

Jeff Law committed
783
/* Return nonzero if INSN is a (possibly) conditional jump inside a
784
   PARALLEL.
Kazu Hirata committed
785

786 787
   Use this function is deprecated, since we need to support combined
   branch and compare insns.  Use any_condjump_p instead whenever possible.  */
788 789

int
790
condjump_in_parallel_p (const_rtx insn)
791
{
792
  const_rtx x = PATTERN (insn);
793 794 795 796 797 798 799 800 801 802 803 804 805 806 807

  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
808
      && (GET_CODE (XEXP (SET_SRC (x), 1)) == LABEL_REF
809
	  || ANY_RETURN_P (XEXP (SET_SRC (x), 1))))
Richard Kenner committed
810 811 812
    return 1;
  if (XEXP (SET_SRC (x), 1) == pc_rtx
      && (GET_CODE (XEXP (SET_SRC (x), 2)) == LABEL_REF
813
	  || ANY_RETURN_P (XEXP (SET_SRC (x), 2))))
Richard Kenner committed
814 815 816 817
    return 1;
  return 0;
}

818 819
/* Return set of PC, otherwise NULL.  */

820
rtx
821
pc_set (const_rtx insn)
822 823
{
  rtx pat;
824
  if (!JUMP_P (insn))
825
    return NULL_RTX;
826
  pat = PATTERN (insn);
827 828 829 830 831

  /* 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);
832 833
  if (GET_CODE (pat) == SET && GET_CODE (SET_DEST (pat)) == PC)
    return pat;
834 835

  return NULL_RTX;
836 837
}

838 839 840
/* Return true when insn is an unconditional direct jump,
   possibly bundled inside a PARALLEL.  */

841
int
842
any_uncondjump_p (const_rtx insn)
843
{
844
  const_rtx x = pc_set (insn);
845 846 847 848
  if (!x)
    return 0;
  if (GET_CODE (SET_SRC (x)) != LABEL_REF)
    return 0;
849 850
  if (find_reg_note (insn, REG_NON_LOCAL_GOTO, NULL_RTX))
    return 0;
851 852 853
  return 1;
}

854
/* Return true when insn is a conditional jump.  This function works for
855 856
   instructions containing PC sets in PARALLELs.  The instruction may have
   various other effects so before removing the jump you must verify
857
   onlyjump_p.
858

859 860
   Note that unlike condjump_p it returns false for unconditional jumps.  */

861
int
862
any_condjump_p (const_rtx insn)
863
{
864
  const_rtx x = pc_set (insn);
865 866
  enum rtx_code a, b;

867 868
  if (!x)
    return 0;
869 870
  if (GET_CODE (SET_SRC (x)) != IF_THEN_ELSE)
    return 0;
871

872 873
  a = GET_CODE (XEXP (SET_SRC (x), 1));
  b = GET_CODE (XEXP (SET_SRC (x), 2));
874

875 876 877
  return ((b == PC && (a == LABEL_REF || a == RETURN || a == SIMPLE_RETURN))
	  || (a == PC
	      && (b == LABEL_REF || b == RETURN || b == SIMPLE_RETURN)));
878 879
}

880 881 882
/* Return the label of a conditional jump.  */

rtx
883
condjump_label (const_rtx insn)
884
{
885
  rtx x = pc_set (insn);
886

887
  if (!x)
888 889 890 891 892 893 894 895 896 897 898 899 900
    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;
}

901 902 903
/* Return true if INSN is a (possibly conditional) return insn.  */

static int
904
returnjump_p_1 (rtx *loc, void *data ATTRIBUTE_UNUSED)
905 906
{
  rtx x = *loc;
907

908 909 910 911 912 913
  if (x == NULL)
    return false;

  switch (GET_CODE (x))
    {
    case RETURN:
914
    case SIMPLE_RETURN:
915 916 917 918 919 920 921 922 923
    case EH_RETURN:
      return true;

    case SET:
      return SET_IS_RETURN_P (x);

    default:
      return false;
    }
924 925
}

926 927
/* Return TRUE if INSN is a return jump.  */

928
int
929
returnjump_p (rtx insn)
930
{
931
  if (!JUMP_P (insn))
932
    return 0;
933 934 935
  return for_each_rtx (&PATTERN (insn), returnjump_p_1, NULL);
}

936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951
/* Return true if INSN is a (possibly conditional) return insn.  */

static int
eh_returnjump_p_1 (rtx *loc, void *data ATTRIBUTE_UNUSED)
{
  return *loc && GET_CODE (*loc) == EH_RETURN;
}

int
eh_returnjump_p (rtx insn)
{
  if (!JUMP_P (insn))
    return 0;
  return for_each_rtx (&PATTERN (insn), eh_returnjump_p_1, NULL);
}

952 953 954 955
/* Return true if INSN is a jump that only transfers control and
   nothing more.  */

int
956
onlyjump_p (const_rtx insn)
957 958 959
{
  rtx set;

960
  if (!JUMP_P (insn))
961 962 963 964 965 966 967 968 969 970 971 972 973
    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;
}

974 975 976 977 978 979 980 981 982
/* Return true iff INSN is a jump and its JUMP_LABEL is a label, not
   NULL or a return.  */
bool
jump_to_label_p (rtx insn)
{
  return (JUMP_P (insn)
	  && JUMP_LABEL (insn) != NULL && !ANY_RETURN_P (JUMP_LABEL (insn)));
}

983 984
#ifdef HAVE_cc0

985
/* Return nonzero if X is an RTX that only sets the condition codes
986 987 988
   and has no side effects.  */

int
989
only_sets_cc0_p (const_rtx x)
990 991 992 993 994 995 996 997 998 999
{
  if (! x)
    return 0;

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

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

Richard Kenner committed
1000 1001 1002 1003 1004 1005
/* 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
1006
sets_cc0_p (const_rtx x)
Richard Kenner committed
1007
{
1008 1009 1010 1011 1012 1013
  if (! x)
    return 0;

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

Richard Kenner committed
1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032
  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;
}
1033
#endif
Richard Kenner committed
1034

1035 1036 1037 1038 1039 1040 1041 1042
/* 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.
1043
   For returnjumps, the JUMP_LABEL will also be set as appropriate.
Richard Kenner committed
1044 1045 1046 1047 1048

   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
1049
   that loop-optimization is done with.  */
Richard Kenner committed
1050

1051
void
1052
mark_jump_label (rtx x, rtx insn, int in_mem)
Richard Kenner committed
1053
{
1054 1055 1056 1057 1058 1059
  rtx asmop = extract_asm_operands (x);
  if (asmop)
    mark_jump_label_asm (asmop, insn);
  else
    mark_jump_label_1 (x, insn, in_mem != 0,
		       (insn != NULL && x == PATTERN (insn) && JUMP_P (insn)));
1060 1061
}

1062
/* Worker function for mark_jump_label.  IN_MEM is TRUE when X occurs
1063 1064 1065 1066 1067 1068 1069 1070
   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)
{
1071 1072 1073
  RTX_CODE code = GET_CODE (x);
  int i;
  const char *fmt;
Richard Kenner committed
1074 1075 1076 1077 1078 1079 1080 1081 1082 1083

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

1084
    case RETURN:
1085
    case SIMPLE_RETURN:
1086 1087 1088 1089 1090 1091 1092
      if (is_target)
	{
	  gcc_assert (JUMP_LABEL (insn) == NULL || JUMP_LABEL (insn) == x);
	  JUMP_LABEL (insn) = x;
	}
      return;

1093
    case MEM:
1094
      in_mem = true;
1095 1096
      break;

1097 1098 1099 1100 1101 1102
    case SEQUENCE:
      for (i = 0; i < XVECLEN (x, 0); i++)
	mark_jump_label (PATTERN (XVECEXP (x, 0, i)),
			 XVECEXP (x, 0, i), 0);
      return;

1103 1104
    case SYMBOL_REF:
      if (!in_mem)
Kazu Hirata committed
1105
	return;
1106

1107
      /* If this is a constant-pool reference, see if it is a label.  */
1108
      if (CONSTANT_POOL_ADDRESS_P (x))
1109
	mark_jump_label_1 (get_pool_constant (x), insn, in_mem, is_target);
1110 1111
      break;

1112 1113 1114 1115 1116 1117 1118 1119 1120 1121
      /* 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
1122 1123
    case LABEL_REF:
      {
1124 1125
	rtx label = XEXP (x, 0);

1126 1127
	/* Ignore remaining references to unreachable labels that
	   have been deleted.  */
1128
	if (NOTE_P (label)
1129
	    && NOTE_KIND (label) == NOTE_INSN_DELETED_LABEL)
1130 1131
	  break;

1132
	gcc_assert (LABEL_P (label));
1133

Richard Stallman committed
1134 1135 1136
	/* Ignore references to labels of containing functions.  */
	if (LABEL_REF_NONLOCAL_P (x))
	  break;
1137

Richard Kenner committed
1138
	XEXP (x, 0) = label;
1139 1140
	if (! insn || ! INSN_DELETED_P (insn))
	  ++LABEL_NUSES (label);
1141

Richard Kenner committed
1142 1143
	if (insn)
	  {
1144
	    if (is_target
1145 1146 1147
		/* 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.  */
1148
		&& (JUMP_LABEL (insn) == NULL || JUMP_LABEL (insn) == label))
Richard Kenner committed
1149
	      JUMP_LABEL (insn) = label;
1150
	    else
1151
	      {
1152 1153 1154 1155 1156 1157 1158 1159
		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))
1160
		  add_reg_note (insn, kind, label);
Richard Kenner committed
1161 1162 1163 1164 1165 1166 1167 1168 1169
	      }
	  }
	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:
1170 1171 1172
      if (! INSN_DELETED_P (insn))
	{
	  int eltnum = code == ADDR_DIFF_VEC ? 1 : 0;
Richard Kenner committed
1173

1174
	  for (i = 0; i < XVECLEN (x, eltnum); i++)
1175 1176
	    mark_jump_label_1 (XVECEXP (x, eltnum, i), NULL_RTX, in_mem,
			       is_target);
1177
	}
1178
      return;
Kazu Hirata committed
1179

1180 1181
    default:
      break;
Richard Kenner committed
1182 1183 1184
    }

  fmt = GET_RTX_FORMAT (code);
1185 1186 1187 1188

  /* 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
1189 1190 1191
  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
    {
      if (fmt[i] == 'e')
1192
	mark_jump_label_1 (XEXP (x, i), insn, in_mem, is_target);
Richard Kenner committed
1193 1194
      else if (fmt[i] == 'E')
	{
1195
	  int j;
1196 1197 1198 1199

	  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
1200 1201 1202 1203
	}
    }
}

1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219
/* Worker function for mark_jump_label.  Handle asm insns specially.
   In particular, output operands need not be considered so we can
   avoid re-scanning the replicated asm_operand.  Also, the asm_labels
   need to be considered targets.  */

static void
mark_jump_label_asm (rtx asmop, rtx insn)
{
  int i;

  for (i = ASM_OPERANDS_INPUT_LENGTH (asmop) - 1; i >= 0; --i)
    mark_jump_label_1 (ASM_OPERANDS_INPUT (asmop, i), insn, false, false);

  for (i = ASM_OPERANDS_LABEL_LENGTH (asmop) - 1; i >= 0; --i)
    mark_jump_label_1 (ASM_OPERANDS_LABEL (asmop, i), insn, false, true);
}
Richard Kenner committed
1220

1221
/* Delete insn INSN from the chain of insns and update label ref counts
1222
   and delete insns now unreachable.
1223

1224
   Returns the first insn after INSN that was not deleted.
Richard Kenner committed
1225

1226 1227
   Usage of this instruction is deprecated.  Use delete_insn instead and
   subsequent cfg_cleanup pass to delete unreachable code if needed.  */
Richard Kenner committed
1228 1229

rtx
1230
delete_related_insns (rtx insn)
Richard Kenner committed
1231
{
1232
  int was_code_label = (LABEL_P (insn));
1233
  rtx note;
1234
  rtx next = NEXT_INSN (insn), prev = PREV_INSN (insn);
Richard Kenner committed
1235 1236 1237 1238 1239 1240 1241 1242

  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;

1243
  delete_insn (insn);
Richard Kenner committed
1244 1245 1246 1247

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

1248
  if (next != 0 && BARRIER_P (next))
1249
    delete_insn (next);
Richard Kenner committed
1250

1251 1252 1253 1254 1255 1256 1257 1258
  /* If this is a call, then we have to remove the var tracking note
     for the call arguments.  */

  if (CALL_P (insn)
      || (NONJUMP_INSN_P (insn)
	  && GET_CODE (PATTERN (insn)) == SEQUENCE
	  && CALL_P (XVECEXP (PATTERN (insn), 0, 0))))
    {
1259
      rtx p;
1260

1261
      for (p = next && INSN_DELETED_P (next) ? NEXT_INSN (next) : next;
1262 1263 1264 1265 1266 1267 1268 1269 1270
	   p && NOTE_P (p);
	   p = NEXT_INSN (p))
	if (NOTE_KIND (p) == NOTE_INSN_CALL_ARG_LOCATION)
	  {
	    remove_insn (p);
	    break;
	  }
    }

Richard Kenner committed
1271 1272 1273
  /* If deleting a jump, decrement the count of the label,
     and delete the label if it is now unused.  */

1274
  if (jump_to_label_p (insn))
1275 1276 1277
    {
      rtx lab = JUMP_LABEL (insn), lab_next;

1278
      if (LABEL_NUSES (lab) == 0)
1279 1280 1281 1282
	/* 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);
1283
      else if (tablejump_p (insn, NULL, &lab_next))
1284 1285
	{
	  /* If we're deleting the tablejump, delete the dispatch table.
1286
	     We may not be able to kill the label immediately preceding
1287 1288
	     just yet, as it might be referenced in code leading up to
	     the tablejump.  */
1289
	  delete_related_insns (lab_next);
1290 1291
	}
    }
Richard Kenner committed
1292

1293 1294
  /* Likewise if we're deleting a dispatch table.  */

Shujing Zhao committed
1295
  if (JUMP_TABLE_DATA_P (insn))
1296 1297 1298 1299 1300 1301
    {
      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++)
1302 1303
	if (LABEL_NUSES (XEXP (XVECEXP (pat, diff_vec_p, i), 0)) == 0)
	  delete_related_insns (XEXP (XVECEXP (pat, diff_vec_p, i), 0));
1304 1305 1306 1307 1308
      while (next && INSN_DELETED_P (next))
	next = NEXT_INSN (next);
      return next;
    }

1309 1310 1311
  /* Likewise for any JUMP_P / INSN / CALL_INSN with a
     REG_LABEL_OPERAND or REG_LABEL_TARGET note.  */
  if (INSN_P (insn))
1312
    for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
1313 1314
      if ((REG_NOTE_KIND (note) == REG_LABEL_OPERAND
	   || REG_NOTE_KIND (note) == REG_LABEL_TARGET)
1315
	  /* This could also be a NOTE_INSN_DELETED_LABEL note.  */
1316
	  && LABEL_P (XEXP (note, 0)))
1317 1318
	if (LABEL_NUSES (XEXP (note, 0)) == 0)
	  delete_related_insns (XEXP (note, 0));
1319

1320
  while (prev && (INSN_DELETED_P (prev) || NOTE_P (prev)))
Richard Kenner committed
1321 1322 1323 1324 1325 1326
    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.  */

1327
  if (was_code_label
Richard Kenner committed
1328
      && NEXT_INSN (insn) != 0
Shujing Zhao committed
1329
      && JUMP_TABLE_DATA_P (NEXT_INSN (insn)))
1330
    next = delete_related_insns (NEXT_INSN (insn));
Richard Kenner committed
1331 1332 1333

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

1334
  if (was_code_label && prev && BARRIER_P (prev))
Richard Kenner committed
1335
    {
1336 1337
      enum rtx_code code;
      while (next)
Richard Kenner committed
1338
	{
1339
	  code = GET_CODE (next);
1340
	  if (code == NOTE)
Richard Kenner committed
1341
	    next = NEXT_INSN (next);
1342 1343 1344
	  /* Keep going past other deleted labels to delete what follows.  */
	  else if (code == CODE_LABEL && INSN_DELETED_P (next))
	    next = NEXT_INSN (next);
1345
	  else if (code == BARRIER || INSN_P (next))
Richard Kenner committed
1346 1347 1348 1349
	    /* 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.  */
1350
	    next = delete_related_insns (next);
1351 1352
	  else
	    break;
Richard Kenner committed
1353 1354 1355
	}
    }

1356 1357 1358 1359 1360 1361
  /* 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
1362 1363 1364 1365 1366 1367 1368 1369 1370
  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
1371
delete_for_peephole (rtx from, rtx to)
Richard Kenner committed
1372
{
1373
  rtx insn = from;
Richard Kenner committed
1374 1375 1376

  while (1)
    {
1377 1378
      rtx next = NEXT_INSN (insn);
      rtx prev = PREV_INSN (insn);
Richard Kenner committed
1379

1380
      if (!NOTE_P (insn))
Richard Kenner committed
1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404
	{
	  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.  */
}

1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416
/* A helper function for redirect_exp_1; examines its input X and returns
   either a LABEL_REF around a label, or a RETURN if X was NULL.  */
static rtx
redirect_target (rtx x)
{
  if (x == NULL_RTX)
    return ret_rtx;
  if (!ANY_RETURN_P (x))
    return gen_rtx_LABEL_REF (Pmode, x);
  return x;
}

1417 1418
/* Throughout LOC, redirect OLABEL to NLABEL.  Treat null OLABEL or
   NLABEL as a return.  Accrue modifications into the change group.  */
Richard Kenner committed
1419

1420
static void
1421
redirect_exp_1 (rtx *loc, rtx olabel, rtx nlabel, rtx insn)
Richard Kenner committed
1422
{
1423 1424 1425 1426
  rtx x = *loc;
  RTX_CODE code = GET_CODE (x);
  int i;
  const char *fmt;
Richard Kenner committed
1427

1428
  if ((code == LABEL_REF && XEXP (x, 0) == olabel)
1429
      || x == olabel)
Richard Kenner committed
1430
    {
1431 1432 1433
      x = redirect_target (nlabel);
      if (GET_CODE (x) == LABEL_REF && loc == &PATTERN (insn))
 	x = gen_rtx_SET (VOIDmode, pc_rtx, x);
1434 1435 1436
      validate_change (insn, loc, x, 1);
      return;
    }
Richard Kenner committed
1437

1438 1439
  if (code == SET && SET_DEST (x) == pc_rtx
      && ANY_RETURN_P (nlabel)
1440 1441 1442
      && GET_CODE (SET_SRC (x)) == LABEL_REF
      && XEXP (SET_SRC (x), 0) == olabel)
    {
1443
      validate_change (insn, loc, nlabel, 1);
1444
      return;
Richard Kenner committed
1445 1446
    }

1447 1448 1449 1450 1451 1452 1453 1454 1455
  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
1456 1457 1458 1459
  fmt = GET_RTX_FORMAT (code);
  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
    {
      if (fmt[i] == 'e')
1460
	redirect_exp_1 (&XEXP (x, i), olabel, nlabel, insn);
1461
      else if (fmt[i] == 'E')
Richard Kenner committed
1462
	{
1463
	  int j;
Richard Kenner committed
1464
	  for (j = 0; j < XVECLEN (x, i); j++)
1465
	    redirect_exp_1 (&XVECEXP (x, i, j), olabel, nlabel, insn);
Richard Kenner committed
1466 1467
	}
    }
1468
}
Richard Kenner committed
1469

1470 1471 1472 1473 1474
/* 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
1475
redirect_jump_1 (rtx jump, rtx nlabel)
1476 1477
{
  int ochanges = num_validated_changes ();
1478
  rtx *loc, asmop;
Jan Hubicka committed
1479

1480
  gcc_assert (nlabel != NULL_RTX);
1481 1482 1483 1484 1485 1486 1487 1488 1489
  asmop = extract_asm_operands (PATTERN (jump));
  if (asmop)
    {
      if (nlabel == NULL)
	return 0;
      gcc_assert (ASM_OPERANDS_LABEL_LENGTH (asmop) == 1);
      loc = &ASM_OPERANDS_LABEL (asmop, 0);
    }
  else if (GET_CODE (PATTERN (jump)) == PARALLEL)
Jan Hubicka committed
1490 1491 1492 1493 1494
    loc = &XVECEXP (PATTERN (jump), 0, 0);
  else
    loc = &PATTERN (jump);

  redirect_exp_1 (loc, JUMP_LABEL (jump), nlabel, jump);
1495 1496 1497 1498 1499 1500
  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
1501

1502 1503 1504
   Normally, NLABEL will be a label, but it may also be a RETURN rtx;
   in that case we are to turn the jump into a (possibly conditional)
   return insn.
Richard Kenner committed
1505

1506
   The return value will be 1 if the change was made, 0 if it wasn't
1507
   (this can only occur when trying to produce return insns).  */
Richard Kenner committed
1508 1509

int
1510
redirect_jump (rtx jump, rtx nlabel, int delete_unused)
Richard Kenner committed
1511
{
1512
  rtx olabel = JUMP_LABEL (jump);
Richard Kenner committed
1513

1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525
  if (!nlabel)
    {
      /* If there is no label, we are asked to redirect to the EXIT block.
	 When before the epilogue is emitted, return/simple_return cannot be
	 created so we return 0 immediately.  After the epilogue is emitted,
	 we always expect a label, either a non-null label, or a
	 return/simple_return RTX.  */

      if (!epilogue_completed)
	return 0;
      gcc_unreachable ();
    }
1526

Richard Kenner committed
1527 1528 1529
  if (nlabel == olabel)
    return 1;

1530
  if (! redirect_jump_1 (jump, nlabel) || ! apply_change_group ())
Richard Kenner committed
1531 1532
    return 0;

1533 1534 1535 1536 1537
  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
H.J. Lu committed
1538
   NLABEL in JUMP.
1539 1540 1541 1542 1543 1544 1545 1546
   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;

1547 1548
  gcc_assert (JUMP_LABEL (jump) == olabel);

1549
  /* Negative DELETE_UNUSED used to be used to signalize behavior on
1550 1551 1552
     moving FUNCTION_END note.  Just sanity check that no user still worry
     about this.  */
  gcc_assert (delete_unused >= 0);
Richard Kenner committed
1553
  JUMP_LABEL (jump) = nlabel;
1554
  if (!ANY_RETURN_P (nlabel))
Richard Kenner committed
1555 1556
    ++LABEL_NUSES (nlabel);

1557 1558 1559
  /* Update labels in any REG_EQUAL note.  */
  if ((note = find_reg_note (jump, REG_EQUAL, NULL_RTX)) != NULL_RTX)
    {
1560 1561
      if (ANY_RETURN_P (nlabel)
	  || (invert && !invert_exp_1 (XEXP (note, 0), jump)))
1562 1563
	remove_note (jump, note);
      else
1564
	{
1565 1566
	  redirect_exp_1 (&XEXP (note, 0), olabel, nlabel, jump);
	  confirm_change_group ();
1567 1568 1569
	}
    }

1570 1571
  if (!ANY_RETURN_P (olabel)
      && --LABEL_NUSES (olabel) == 0 && delete_unused > 0
1572 1573
      /* Undefined labels will remain outside the insn stream.  */
      && INSN_UID (olabel))
1574
    delete_related_insns (olabel);
1575 1576
  if (invert)
    invert_br_probabilities (jump);
Richard Kenner committed
1577 1578
}

1579 1580 1581 1582
/* 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)
1583
{
1584
  RTX_CODE code = GET_CODE (x);
1585 1586 1587

  if (code == IF_THEN_ELSE)
    {
1588 1589
      rtx comp = XEXP (x, 0);
      rtx tem;
1590
      enum rtx_code reversed_code;
1591 1592 1593 1594 1595 1596

      /* 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.  */

1597 1598 1599
      reversed_code = reversed_comparison_code (comp, insn);

      if (reversed_code != UNKNOWN)
1600 1601
	{
	  validate_change (insn, &XEXP (x, 0),
1602
			   gen_rtx_fmt_ee (reversed_code,
1603 1604 1605
					   GET_MODE (comp), XEXP (comp, 0),
					   XEXP (comp, 1)),
			   1);
1606
	  return 1;
1607
	}
Kazu Hirata committed
1608

1609 1610 1611
      tem = XEXP (x, 1);
      validate_change (insn, &XEXP (x, 1), XEXP (x, 2), 1);
      validate_change (insn, &XEXP (x, 2), tem, 1);
1612
      return 1;
1613
    }
Jan Hubicka committed
1614
  else
1615 1616 1617 1618 1619 1620 1621 1622 1623
    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
1624
invert_jump_1 (rtx jump, rtx nlabel)
1625
{
1626
  rtx x = pc_set (jump);
1627
  int ochanges;
1628
  int ok;
1629 1630

  ochanges = num_validated_changes ();
1631 1632
  if (x == NULL)
    return 0;
1633 1634
  ok = invert_exp_1 (SET_SRC (x), jump);
  gcc_assert (ok);
H.J. Lu committed
1635

1636 1637 1638
  if (num_validated_changes () == ochanges)
    return 0;

1639 1640 1641
  /* 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);
1642 1643 1644 1645 1646 1647
}

/* 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
1648
invert_jump (rtx jump, rtx nlabel, int delete_unused)
1649
{
1650
  rtx olabel = JUMP_LABEL (jump);
1651

1652
  if (invert_jump_1 (jump, nlabel) && apply_change_group ())
1653
    {
1654
      redirect_jump_2 (jump, olabel, nlabel, delete_unused, 1);
1655 1656
      return 1;
    }
1657
  cancel_changes (0);
1658 1659 1660
  return 0;
}

Richard Kenner committed
1661 1662

/* Like rtx_equal_p except that it considers two REGs as equal
1663 1664
   if they renumber to the same value and considers two commutative
   operations to be the same if the order of the operands has been
1665
   reversed.  */
Richard Kenner committed
1666 1667

int
1668
rtx_renumbered_equal_p (const_rtx x, const_rtx y)
Richard Kenner committed
1669
{
1670
  int i;
1671
  const enum rtx_code code = GET_CODE (x);
1672
  const char *fmt;
Kazu Hirata committed
1673

Richard Kenner committed
1674 1675
  if (x == y)
    return 1;
1676

1677 1678 1679
  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
1680
    {
1681
      int reg_x = -1, reg_y = -1;
1682
      int byte_x = 0, byte_y = 0;
1683
      struct subreg_info info;
Richard Kenner committed
1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694

      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)
	{
1695
	  reg_x = REGNO (SUBREG_REG (x));
1696
	  byte_x = SUBREG_BYTE (x);
1697 1698 1699

	  if (reg_renumber[reg_x] >= 0)
	    {
1700 1701 1702 1703
	      subreg_get_info (reg_renumber[reg_x],
			       GET_MODE (SUBREG_REG (x)), byte_x,
			       GET_MODE (x), &info);
	      if (!info.representable_p)
1704
		return 0;
1705
	      reg_x = info.offset;
1706
	      byte_x = 0;
1707
	    }
Richard Kenner committed
1708 1709 1710
	}
      else
	{
1711 1712 1713
	  reg_x = REGNO (x);
	  if (reg_renumber[reg_x] >= 0)
	    reg_x = reg_renumber[reg_x];
Richard Kenner committed
1714
	}
1715

Richard Kenner committed
1716 1717
      if (GET_CODE (y) == SUBREG)
	{
1718
	  reg_y = REGNO (SUBREG_REG (y));
1719
	  byte_y = SUBREG_BYTE (y);
1720 1721 1722

	  if (reg_renumber[reg_y] >= 0)
	    {
1723 1724 1725 1726
	      subreg_get_info (reg_renumber[reg_y],
			       GET_MODE (SUBREG_REG (y)), byte_y,
			       GET_MODE (y), &info);
	      if (!info.representable_p)
1727
		return 0;
1728
	      reg_y = info.offset;
1729
	      byte_y = 0;
1730
	    }
Richard Kenner committed
1731 1732 1733
	}
      else
	{
1734 1735 1736
	  reg_y = REGNO (y);
	  if (reg_renumber[reg_y] >= 0)
	    reg_y = reg_renumber[reg_y];
Richard Kenner committed
1737
	}
1738

1739
      return reg_x >= 0 && reg_x == reg_y && byte_x == byte_y;
Richard Kenner committed
1740
    }
1741

Kazu Hirata committed
1742
  /* Now we have disposed of all the cases
Richard Kenner committed
1743 1744 1745
     in which different rtx codes can match.  */
  if (code != GET_CODE (y))
    return 0;
1746

Richard Kenner committed
1747 1748 1749 1750 1751 1752
  switch (code)
    {
    case PC:
    case CC0:
    case ADDR_VEC:
    case ADDR_DIFF_VEC:
1753
    CASE_CONST_UNIQUE:
1754
      return 0;
Richard Kenner committed
1755 1756

    case LABEL_REF:
Richard Stallman committed
1757 1758 1759
      /* 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);
1760

Richard Kenner committed
1761 1762 1763 1764 1765 1766 1767
      /* 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);
1768

1769 1770 1771 1772
    case CODE_LABEL:
      /* If we didn't match EQ equality above, they aren't the same.  */
      return 0;

1773 1774
    default:
      break;
Richard Kenner committed
1775 1776 1777 1778 1779 1780 1781
    }

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

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

1782
  /* MEMs referring to different address space are not equivalent.  */
1783 1784 1785
  if (code == MEM && MEM_ADDR_SPACE (x) != MEM_ADDR_SPACE (y))
    return 0;

1786
  /* For commutative operations, the RTX match if the operand match in any
1787 1788
     order.  Also handle the simple binary and unary cases without a loop.  */
  if (targetm.commutative_p (x, UNKNOWN))
1789 1790 1791 1792
    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))));
1793
  else if (NON_COMMUTATIVE_P (x))
1794 1795
    return (rtx_renumbered_equal_p (XEXP (x, 0), XEXP (y, 0))
	    && rtx_renumbered_equal_p (XEXP (x, 1), XEXP (y, 1)));
1796
  else if (UNARY_P (x))
1797 1798
    return rtx_renumbered_equal_p (XEXP (x, 0), XEXP (y, 0));

Richard Kenner committed
1799 1800 1801 1802 1803 1804
  /* 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--)
    {
1805
      int j;
Richard Kenner committed
1806 1807
      switch (fmt[i])
	{
1808 1809 1810 1811 1812
	case 'w':
	  if (XWINT (x, i) != XWINT (y, i))
	    return 0;
	  break;

Richard Kenner committed
1813 1814
	case 'i':
	  if (XINT (x, i) != XINT (y, i))
1815 1816
	    {
	      if (((code == ASM_OPERANDS && i == 6)
1817
		   || (code == ASM_INPUT && i == 1)))
1818 1819 1820
		break;
	      return 0;
	    }
Richard Kenner committed
1821 1822
	  break;

1823 1824 1825 1826 1827
	case 't':
	  if (XTREE (x, i) != XTREE (y, i))
	    return 0;
	  break;

Richard Kenner committed
1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840
	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;
1841
	  /* Fall through.  */
Richard Kenner committed
1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853
	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:
1854
	  gcc_unreachable ();
Richard Kenner committed
1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865
	}
    }
  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
1866
true_regnum (const_rtx x)
Richard Kenner committed
1867
{
1868
  if (REG_P (x))
Richard Kenner committed
1869
    {
1870 1871
      if (REGNO (x) >= FIRST_PSEUDO_REGISTER
	  && (lra_in_progress || reg_renumber[REGNO (x)] >= 0))
Richard Kenner committed
1872 1873 1874 1875 1876 1877
	return reg_renumber[REGNO (x)];
      return REGNO (x);
    }
  if (GET_CODE (x) == SUBREG)
    {
      int base = true_regnum (SUBREG_REG (x));
1878
      if (base >= 0
1879 1880 1881 1882
	  && base < FIRST_PSEUDO_REGISTER)
	{
	  struct subreg_info info;

1883 1884
	  subreg_get_info (lra_in_progress
			   ? (unsigned) base : REGNO (SUBREG_REG (x)),
1885 1886 1887 1888 1889 1890
			   GET_MODE (SUBREG_REG (x)),
			   SUBREG_BYTE (x), GET_MODE (x), &info);

	  if (info.representable_p)
	    return base + info.offset;
	}
Richard Kenner committed
1891 1892 1893
    }
  return -1;
}
1894 1895 1896

/* Return regno of the register REG and handle subregs too.  */
unsigned int
1897
reg_or_subregno (const_rtx reg)
1898 1899
{
  if (GET_CODE (reg) == SUBREG)
1900 1901 1902
    reg = SUBREG_REG (reg);
  gcc_assert (REG_P (reg));
  return REGNO (reg);
1903
}