]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/jump.c
Eliminate FOR_EACH_BB macro.
[thirdparty/gcc.git] / gcc / jump.c
CommitLineData
5924de0b 1/* Optimize jump instructions, for GNU compiler.
711789cc 2 Copyright (C) 1987-2013 Free Software Foundation, Inc.
5924de0b 3
f12b58b3 4This file is part of GCC.
5924de0b 5
f12b58b3 6GCC is free software; you can redistribute it and/or modify it under
7the terms of the GNU General Public License as published by the Free
8c4c00c1 8Software Foundation; either version 3, or (at your option) any later
f12b58b3 9version.
5924de0b 10
f12b58b3 11GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12WARRANTY; without even the implied warranty of MERCHANTABILITY or
13FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14for more details.
5924de0b 15
16You should have received a copy of the GNU General Public License
8c4c00c1 17along with GCC; see the file COPYING3. If not see
18<http://www.gnu.org/licenses/>. */
5924de0b 19
fc4eaab7 20/* This is the pathetic reminder of old fame of the jump-optimization pass
d961ae3a 21 of the compiler. Now it contains basically a set of utility functions to
fc4eaab7 22 operate with jumps.
5924de0b 23
24 Each CODE_LABEL has a count of the times it is used
25 stored in the LABEL_NUSES internal field, and each JUMP_INSN
26 has one label that it refers to stored in the
27 JUMP_LABEL internal field. With this we can detect labels that
28 become unused because of the deletion of all the jumps that
29 formerly used them. The JUMP_LABEL info is sometimes looked
9cb2517e 30 at by later passes. For return insns, it contains either a
31 RETURN or a SIMPLE_RETURN rtx.
5924de0b 32
5f3447b0 33 The subroutines redirect_jump and invert_jump are used
5924de0b 34 from other passes as well. */
35
36#include "config.h"
405711de 37#include "system.h"
805e22b2 38#include "coretypes.h"
39#include "tm.h"
5924de0b 40#include "rtl.h"
7953c610 41#include "tm_p.h"
5924de0b 42#include "flags.h"
43#include "hard-reg-set.h"
44#include "regs.h"
5924de0b 45#include "insn-config.h"
fe3b47be 46#include "insn-attr.h"
0dbd1c74 47#include "recog.h"
0a893c29 48#include "function.h"
a79e7523 49#include "basic-block.h"
fa9157fe 50#include "expr.h"
485aaaaf 51#include "except.h"
852f689e 52#include "diagnostic-core.h"
75eb327c 53#include "reload.h"
13488c51 54#include "predict.h"
77fce4cd 55#include "tree-pass.h"
280566a7 56#include "target.h"
5924de0b 57
5924de0b 58/* Optimize jump y; x: ... y: jumpif... x?
59 Don't know if it is worth bothering with. */
60/* Optimize two cases of conditional jump to conditional jump?
61 This can never delete any instruction or make anything dead,
62 or even change what is live at any point.
63 So perhaps let combiner do it. */
64
3ad4992f 65static void init_label_info (rtx);
66static void mark_all_labels (rtx);
19d2fe05 67static void mark_jump_label_1 (rtx, rtx, bool, bool);
78f55ca8 68static void mark_jump_label_asm (rtx, rtx);
3ad4992f 69static void redirect_exp_1 (rtx *, rtx, rtx, rtx);
82880dfd 70static int invert_exp_1 (rtx, rtx);
3ad4992f 71static int returnjump_p_1 (rtx *, void *);
60ecc450 72\f
409e049a 73/* Worker for rebuild_jump_labels and rebuild_jump_labels_chain. */
74static void
75rebuild_jump_labels_1 (rtx f, bool count_forced)
8b946ced 76{
19cb6b50 77 rtx insn;
5924de0b 78
376c21d1 79 timevar_push (TV_REBUILD_JUMP);
805e22b2 80 init_label_info (f);
bf73fcf4 81 mark_all_labels (f);
5924de0b 82
cbd914e1 83 /* Keep track of labels used from static data; we don't track them
84 closely enough to delete them here, so make sure their reference
85 count doesn't drop to zero. */
5924de0b 86
409e049a 87 if (count_forced)
88 for (insn = forced_labels; insn; insn = XEXP (insn, 1))
89 if (LABEL_P (XEXP (insn, 0)))
90 LABEL_NUSES (XEXP (insn, 0))++;
376c21d1 91 timevar_pop (TV_REBUILD_JUMP);
fc4eaab7 92}
409e049a 93
94/* This function rebuilds the JUMP_LABEL field and REG_LABEL_TARGET
95 notes in jumping insns and REG_LABEL_OPERAND notes in non-jumping
96 instructions and jumping insns that have labels as operands
97 (e.g. cbranchsi4). */
98void
99rebuild_jump_labels (rtx f)
100{
101 rebuild_jump_labels_1 (f, true);
102}
103
104/* This function is like rebuild_jump_labels, but doesn't run over
105 forced_labels. It can be used on insn chains that aren't the
106 main function chain. */
107void
108rebuild_jump_labels_chain (rtx chain)
109{
110 rebuild_jump_labels_1 (chain, false);
111}
fc4eaab7 112\f
fb3c15bc 113/* Some old code expects exactly one BARRIER as the NEXT_INSN of a
114 non-fallthru insn. This is not generally true, as multiple barriers
115 may have crept in, or the BARRIER may be separated from the last
116 real insn by one or more NOTEs.
117
118 This simple pass moves barriers and removes duplicates so that the
119 old code is happy.
120 */
5a2fb01f 121static unsigned int
3ad4992f 122cleanup_barriers (void)
fb3c15bc 123{
124 rtx insn, next, prev;
125 for (insn = get_insns (); insn; insn = next)
126 {
127 next = NEXT_INSN (insn);
6d7dc5b9 128 if (BARRIER_P (insn))
fb3c15bc 129 {
130 prev = prev_nonnote_insn (insn);
326fb3fd 131 if (!prev)
132 continue;
6d7dc5b9 133 if (BARRIER_P (prev))
749a971f 134 delete_insn (insn);
fb3c15bc 135 else if (prev != PREV_INSN (insn))
35f3420b 136 reorder_insns_nobb (insn, insn, prev);
fb3c15bc 137 }
138 }
2a1990e9 139 return 0;
fb3c15bc 140}
5924de0b 141
cbe8bda8 142namespace {
143
144const pass_data pass_data_cleanup_barriers =
77fce4cd 145{
cbe8bda8 146 RTL_PASS, /* type */
147 "barriers", /* name */
148 OPTGROUP_NONE, /* optinfo_flags */
149 false, /* has_gate */
150 true, /* has_execute */
151 TV_NONE, /* tv_id */
152 0, /* properties_required */
153 0, /* properties_provided */
154 0, /* properties_destroyed */
155 0, /* todo_flags_start */
156 0, /* todo_flags_finish */
77fce4cd 157};
158
cbe8bda8 159class pass_cleanup_barriers : public rtl_opt_pass
160{
161public:
9af5ce0c 162 pass_cleanup_barriers (gcc::context *ctxt)
163 : rtl_opt_pass (pass_data_cleanup_barriers, ctxt)
cbe8bda8 164 {}
165
166 /* opt_pass methods: */
167 unsigned int execute () { return cleanup_barriers (); }
168
169}; // class pass_cleanup_barriers
170
171} // anon namespace
172
173rtl_opt_pass *
174make_pass_cleanup_barriers (gcc::context *ctxt)
175{
176 return new pass_cleanup_barriers (ctxt);
177}
178
e8d75e01 179\f
19d2fe05 180/* Initialize LABEL_NUSES and JUMP_LABEL fields, add REG_LABEL_TARGET
181 for remaining targets for JUMP_P. Delete any REG_LABEL_OPERAND
182 notes whose labels don't occur in the insn any more. */
183
805e22b2 184static void
3ad4992f 185init_label_info (rtx f)
e8d75e01 186{
e8d75e01 187 rtx insn;
188
c38b28e7 189 for (insn = f; insn; insn = NEXT_INSN (insn))
19d2fe05 190 {
c38b28e7 191 if (LABEL_P (insn))
192 LABEL_NUSES (insn) = (LABEL_PRESERVE_P (insn) != 0);
193
194 /* REG_LABEL_TARGET notes (including the JUMP_LABEL field) are
195 sticky and not reset here; that way we won't lose association
196 with a label when e.g. the source for a target register
197 disappears out of reach for targets that may use jump-target
198 registers. Jump transformations are supposed to transform
199 any REG_LABEL_TARGET notes. The target label reference in a
200 branch may disappear from the branch (and from the
201 instruction before it) for other reasons, like register
202 allocation. */
203
204 if (INSN_P (insn))
19d2fe05 205 {
c38b28e7 206 rtx note, next;
207
208 for (note = REG_NOTES (insn); note; note = next)
209 {
210 next = XEXP (note, 1);
211 if (REG_NOTE_KIND (note) == REG_LABEL_OPERAND
212 && ! reg_mentioned_p (XEXP (note, 0), PATTERN (insn)))
213 remove_note (insn, note);
214 }
19d2fe05 215 }
216 }
e8d75e01 217}
218
58c74e1e 219/* A subroutine of mark_all_labels. Trivially propagate a simple label
220 load into a jump_insn that uses it. */
221
222static void
223maybe_propagate_label_ref (rtx jump_insn, rtx prev_nonjump_insn)
224{
225 rtx label_note, pc, pc_src;
226
227 pc = pc_set (jump_insn);
228 pc_src = pc != NULL ? SET_SRC (pc) : NULL;
229 label_note = find_reg_note (prev_nonjump_insn, REG_LABEL_OPERAND, NULL);
230
231 /* If the previous non-jump insn sets something to a label,
232 something that this jump insn uses, make that label the primary
233 target of this insn if we don't yet have any. That previous
234 insn must be a single_set and not refer to more than one label.
235 The jump insn must not refer to other labels as jump targets
236 and must be a plain (set (pc) ...), maybe in a parallel, and
237 may refer to the item being set only directly or as one of the
238 arms in an IF_THEN_ELSE. */
239
240 if (label_note != NULL && pc_src != NULL)
241 {
242 rtx label_set = single_set (prev_nonjump_insn);
243 rtx label_dest = label_set != NULL ? SET_DEST (label_set) : NULL;
244
245 if (label_set != NULL
246 /* The source must be the direct LABEL_REF, not a
247 PLUS, UNSPEC, IF_THEN_ELSE etc. */
248 && GET_CODE (SET_SRC (label_set)) == LABEL_REF
249 && (rtx_equal_p (label_dest, pc_src)
250 || (GET_CODE (pc_src) == IF_THEN_ELSE
251 && (rtx_equal_p (label_dest, XEXP (pc_src, 1))
252 || rtx_equal_p (label_dest, XEXP (pc_src, 2))))))
253 {
254 /* The CODE_LABEL referred to in the note must be the
255 CODE_LABEL in the LABEL_REF of the "set". We can
256 conveniently use it for the marker function, which
257 requires a LABEL_REF wrapping. */
258 gcc_assert (XEXP (label_note, 0) == XEXP (SET_SRC (label_set), 0));
259
260 mark_jump_label_1 (label_set, jump_insn, false, true);
261
262 gcc_assert (JUMP_LABEL (jump_insn) == XEXP (label_note, 0));
263 }
264 }
265}
266
e8d75e01 267/* Mark the label each jump jumps to.
fc4eaab7 268 Combine consecutive labels, and count uses of labels. */
e8d75e01 269
270static void
3ad4992f 271mark_all_labels (rtx f)
e8d75e01 272{
273 rtx insn;
274
eea7b156 275 if (current_ir_type () == IR_RTL_CFGLAYOUT)
276 {
277 basic_block bb;
fc00614f 278 FOR_EACH_BB_FN (bb, cfun)
eea7b156 279 {
58c74e1e 280 /* In cfglayout mode, we don't bother with trivial next-insn
281 propagation of LABEL_REFs into JUMP_LABEL. This will be
282 handled by other optimizers using better algorithms. */
283 FOR_BB_INSNS (bb, insn)
284 {
285 gcc_assert (! INSN_DELETED_P (insn));
286 if (NONDEBUG_INSN_P (insn))
287 mark_jump_label (PATTERN (insn), insn, 0);
288 }
289
290 /* In cfglayout mode, there may be non-insns between the
291 basic blocks. If those non-insns represent tablejump data,
292 they contain label references that we must record. */
43e94e51 293 for (insn = BB_HEADER (bb); insn; insn = NEXT_INSN (insn))
91f71fa3 294 if (JUMP_TABLE_DATA_P (insn))
295 mark_jump_label (PATTERN (insn), insn, 0);
43e94e51 296 for (insn = BB_FOOTER (bb); insn; insn = NEXT_INSN (insn))
91f71fa3 297 if (JUMP_TABLE_DATA_P (insn))
298 mark_jump_label (PATTERN (insn), insn, 0);
eea7b156 299 }
300 }
58c74e1e 301 else
302 {
303 rtx prev_nonjump_insn = NULL;
304 for (insn = f; insn; insn = NEXT_INSN (insn))
305 {
306 if (INSN_DELETED_P (insn))
307 ;
308 else if (LABEL_P (insn))
309 prev_nonjump_insn = NULL;
91f71fa3 310 else if (JUMP_TABLE_DATA_P (insn))
311 mark_jump_label (PATTERN (insn), insn, 0);
58c74e1e 312 else if (NONDEBUG_INSN_P (insn))
313 {
314 mark_jump_label (PATTERN (insn), insn, 0);
315 if (JUMP_P (insn))
316 {
317 if (JUMP_LABEL (insn) == NULL && prev_nonjump_insn != NULL)
318 maybe_propagate_label_ref (insn, prev_nonjump_insn);
319 }
320 else
321 prev_nonjump_insn = insn;
322 }
323 }
324 }
e8d75e01 325}
5924de0b 326\f
fa8b3d85 327/* Given a comparison (CODE ARG0 ARG1), inside an insn, INSN, return a code
8e98892d 328 of reversed comparison if it is possible to do so. Otherwise return UNKNOWN.
329 UNKNOWN may be returned in case we are having CC_MODE compare and we don't
330 know whether it's source is floating point or integer comparison. Machine
331 description should define REVERSIBLE_CC_MODE and REVERSE_CONDITION macros
332 to help this function avoid overhead in these cases. */
333enum rtx_code
5493cb9a 334reversed_comparison_code_parts (enum rtx_code code, const_rtx arg0,
335 const_rtx arg1, const_rtx insn)
5924de0b 336{
8e98892d 337 enum machine_mode mode;
5924de0b 338
339 /* If this is not actually a comparison, we can't reverse it. */
6720e96c 340 if (GET_RTX_CLASS (code) != RTX_COMPARE
341 && GET_RTX_CLASS (code) != RTX_COMM_COMPARE)
8e98892d 342 return UNKNOWN;
343
344 mode = GET_MODE (arg0);
345 if (mode == VOIDmode)
346 mode = GET_MODE (arg1);
347
3927afe0 348 /* First see if machine description supplies us way to reverse the
349 comparison. Give it priority over everything else to allow
350 machine description to do tricks. */
0ec244e1 351 if (GET_MODE_CLASS (mode) == MODE_CC
8e98892d 352 && REVERSIBLE_CC_MODE (mode))
353 {
354#ifdef REVERSE_CONDITION
85fc0ad1 355 return REVERSE_CONDITION (code, mode);
1084097d 356#else
85fc0ad1 357 return reverse_condition (code);
1084097d 358#endif
85fc0ad1 359 }
5924de0b 360
fa8b3d85 361 /* Try a few special cases based on the comparison code. */
8e98892d 362 switch (code)
363 {
85fc0ad1 364 case GEU:
365 case GTU:
366 case LEU:
367 case LTU:
368 case NE:
369 case EQ:
370 /* It is always safe to reverse EQ and NE, even for the floating
917bbcab 371 point. Similarly the unsigned comparisons are never used for
85fc0ad1 372 floating point so we can reverse them in the default way. */
373 return reverse_condition (code);
374 case ORDERED:
375 case UNORDERED:
376 case LTGT:
377 case UNEQ:
378 /* In case we already see unordered comparison, we can be sure to
379 be dealing with floating point so we don't need any more tests. */
380 return reverse_condition_maybe_unordered (code);
381 case UNLT:
382 case UNLE:
383 case UNGT:
384 case UNGE:
385 /* We don't have safe way to reverse these yet. */
386 return UNKNOWN;
387 default:
388 break;
8e98892d 389 }
390
a4589b78 391 if (GET_MODE_CLASS (mode) == MODE_CC || CC0_P (arg0))
5924de0b 392 {
5493cb9a 393 const_rtx prev;
8e98892d 394 /* Try to search for the comparison to determine the real mode.
395 This code is expensive, but with sane machine description it
396 will be never used, since REVERSIBLE_CC_MODE will return true
397 in all cases. */
111f2389 398 if (! insn)
8e98892d 399 return UNKNOWN;
7113a566 400
ce4469fa 401 /* These CONST_CAST's are okay because prev_nonnote_insn just
5ca94202 402 returns its argument and we assign it to a const_rtx
ce4469fa 403 variable. */
9af5ce0c 404 for (prev = prev_nonnote_insn (CONST_CAST_RTX (insn));
6d7dc5b9 405 prev != 0 && !LABEL_P (prev);
9af5ce0c 406 prev = prev_nonnote_insn (CONST_CAST_RTX (prev)))
8e98892d 407 {
81a410b1 408 const_rtx set = set_of (arg0, prev);
8e98892d 409 if (set && GET_CODE (set) == SET
410 && rtx_equal_p (SET_DEST (set), arg0))
411 {
412 rtx src = SET_SRC (set);
5924de0b 413
8e98892d 414 if (GET_CODE (src) == COMPARE)
415 {
416 rtx comparison = src;
417 arg0 = XEXP (src, 0);
418 mode = GET_MODE (arg0);
419 if (mode == VOIDmode)
420 mode = GET_MODE (XEXP (comparison, 1));
421 break;
422 }
dd5b4b36 423 /* We can get past reg-reg moves. This may be useful for model
8e98892d 424 of i387 comparisons that first move flag registers around. */
425 if (REG_P (src))
426 {
427 arg0 = src;
428 continue;
429 }
430 }
431 /* If register is clobbered in some ununderstandable way,
432 give up. */
433 if (set)
434 return UNKNOWN;
435 }
5924de0b 436 }
437
920d0fb5 438 /* Test for an integer condition, or a floating-point comparison
439 in which NaNs can be ignored. */
971ba038 440 if (CONST_INT_P (arg0)
8e98892d 441 || (GET_MODE (arg0) != VOIDmode
442 && GET_MODE_CLASS (mode) != MODE_CC
920d0fb5 443 && !HONOR_NANS (mode)))
8e98892d 444 return reverse_condition (code);
445
446 return UNKNOWN;
447}
448
df07c3ae 449/* A wrapper around the previous function to take COMPARISON as rtx
8e98892d 450 expression. This simplifies many callers. */
451enum rtx_code
5493cb9a 452reversed_comparison_code (const_rtx comparison, const_rtx insn)
8e98892d 453{
6720e96c 454 if (!COMPARISON_P (comparison))
8e98892d 455 return UNKNOWN;
456 return reversed_comparison_code_parts (GET_CODE (comparison),
457 XEXP (comparison, 0),
458 XEXP (comparison, 1), insn);
459}
0fc1e6fa 460
461/* Return comparison with reversed code of EXP.
462 Return NULL_RTX in case we fail to do the reversal. */
463rtx
5493cb9a 464reversed_comparison (const_rtx exp, enum machine_mode mode)
0fc1e6fa 465{
466 enum rtx_code reversed_code = reversed_comparison_code (exp, NULL_RTX);
467 if (reversed_code == UNKNOWN)
468 return NULL_RTX;
469 else
470 return simplify_gen_relational (reversed_code, mode, VOIDmode,
471 XEXP (exp, 0), XEXP (exp, 1));
472}
473
8e98892d 474\f
a4110d9a 475/* Given an rtx-code for a comparison, return the code for the negated
476 comparison. If no such code exists, return UNKNOWN.
477
478 WATCH OUT! reverse_condition is not safe to use on a jump that might
479 be acting on the results of an IEEE floating point comparison, because
7113a566 480 of the special treatment of non-signaling nans in comparisons.
8e98892d 481 Use reversed_comparison_code instead. */
5924de0b 482
483enum rtx_code
3ad4992f 484reverse_condition (enum rtx_code code)
5924de0b 485{
486 switch (code)
487 {
488 case EQ:
489 return NE;
5924de0b 490 case NE:
491 return EQ;
5924de0b 492 case GT:
493 return LE;
5924de0b 494 case GE:
495 return LT;
5924de0b 496 case LT:
497 return GE;
5924de0b 498 case LE:
499 return GT;
5924de0b 500 case GTU:
501 return LEU;
5924de0b 502 case GEU:
503 return LTU;
5924de0b 504 case LTU:
505 return GEU;
5924de0b 506 case LEU:
507 return GTU;
a4110d9a 508 case UNORDERED:
509 return ORDERED;
510 case ORDERED:
511 return UNORDERED;
512
513 case UNLT:
514 case UNLE:
515 case UNGT:
516 case UNGE:
517 case UNEQ:
79777bad 518 case LTGT:
a4110d9a 519 return UNKNOWN;
5924de0b 520
521 default:
a53ff4c1 522 gcc_unreachable ();
5924de0b 523 }
524}
525
79777bad 526/* Similar, but we're allowed to generate unordered comparisons, which
527 makes it safe for IEEE floating-point. Of course, we have to recognize
528 that the target will support them too... */
529
530enum rtx_code
3ad4992f 531reverse_condition_maybe_unordered (enum rtx_code code)
79777bad 532{
79777bad 533 switch (code)
534 {
535 case EQ:
536 return NE;
537 case NE:
538 return EQ;
539 case GT:
540 return UNLE;
541 case GE:
542 return UNLT;
543 case LT:
544 return UNGE;
545 case LE:
546 return UNGT;
547 case LTGT:
548 return UNEQ;
79777bad 549 case UNORDERED:
550 return ORDERED;
551 case ORDERED:
552 return UNORDERED;
553 case UNLT:
554 return GE;
555 case UNLE:
556 return GT;
557 case UNGT:
558 return LE;
559 case UNGE:
560 return LT;
561 case UNEQ:
562 return LTGT;
563
564 default:
a53ff4c1 565 gcc_unreachable ();
79777bad 566 }
567}
568
5924de0b 569/* Similar, but return the code when two operands of a comparison are swapped.
570 This IS safe for IEEE floating-point. */
571
572enum rtx_code
3ad4992f 573swap_condition (enum rtx_code code)
5924de0b 574{
575 switch (code)
576 {
577 case EQ:
578 case NE:
a4110d9a 579 case UNORDERED:
580 case ORDERED:
581 case UNEQ:
79777bad 582 case LTGT:
5924de0b 583 return code;
584
585 case GT:
586 return LT;
5924de0b 587 case GE:
588 return LE;
5924de0b 589 case LT:
590 return GT;
5924de0b 591 case LE:
592 return GE;
5924de0b 593 case GTU:
594 return LTU;
5924de0b 595 case GEU:
596 return LEU;
5924de0b 597 case LTU:
598 return GTU;
5924de0b 599 case LEU:
600 return GEU;
a4110d9a 601 case UNLT:
602 return UNGT;
603 case UNLE:
604 return UNGE;
605 case UNGT:
606 return UNLT;
607 case UNGE:
608 return UNLE;
609
5924de0b 610 default:
a53ff4c1 611 gcc_unreachable ();
5924de0b 612 }
613}
614
615/* Given a comparison CODE, return the corresponding unsigned comparison.
616 If CODE is an equality comparison or already an unsigned comparison,
617 CODE is returned. */
618
619enum rtx_code
3ad4992f 620unsigned_condition (enum rtx_code code)
5924de0b 621{
622 switch (code)
623 {
624 case EQ:
625 case NE:
626 case GTU:
627 case GEU:
628 case LTU:
629 case LEU:
630 return code;
631
632 case GT:
633 return GTU;
5924de0b 634 case GE:
635 return GEU;
5924de0b 636 case LT:
637 return LTU;
5924de0b 638 case LE:
639 return LEU;
640
641 default:
a53ff4c1 642 gcc_unreachable ();
5924de0b 643 }
644}
645
646/* Similarly, return the signed version of a comparison. */
647
648enum rtx_code
3ad4992f 649signed_condition (enum rtx_code code)
5924de0b 650{
651 switch (code)
652 {
653 case EQ:
654 case NE:
655 case GT:
656 case GE:
657 case LT:
658 case LE:
659 return code;
660
661 case GTU:
662 return GT;
5924de0b 663 case GEU:
664 return GE;
5924de0b 665 case LTU:
666 return LT;
5924de0b 667 case LEU:
668 return LE;
669
670 default:
a53ff4c1 671 gcc_unreachable ();
5924de0b 672 }
673}
674\f
6ef828f9 675/* Return nonzero if CODE1 is more strict than CODE2, i.e., if the
5924de0b 676 truth of CODE1 implies the truth of CODE2. */
677
678int
3ad4992f 679comparison_dominates_p (enum rtx_code code1, enum rtx_code code2)
5924de0b 680{
ca7744c6 681 /* UNKNOWN comparison codes can happen as a result of trying to revert
682 comparison codes.
683 They can't match anything, so we have to reject them here. */
684 if (code1 == UNKNOWN || code2 == UNKNOWN)
685 return 0;
686
5924de0b 687 if (code1 == code2)
688 return 1;
689
690 switch (code1)
691 {
5aa3f5e2 692 case UNEQ:
693 if (code2 == UNLE || code2 == UNGE)
694 return 1;
695 break;
696
5924de0b 697 case EQ:
79777bad 698 if (code2 == LE || code2 == LEU || code2 == GE || code2 == GEU
699 || code2 == ORDERED)
5924de0b 700 return 1;
701 break;
702
5aa3f5e2 703 case UNLT:
704 if (code2 == UNLE || code2 == NE)
705 return 1;
706 break;
707
5924de0b 708 case LT:
5aa3f5e2 709 if (code2 == LE || code2 == NE || code2 == ORDERED || code2 == LTGT)
710 return 1;
711 break;
712
713 case UNGT:
714 if (code2 == UNGE || code2 == NE)
5924de0b 715 return 1;
716 break;
717
718 case GT:
5aa3f5e2 719 if (code2 == GE || code2 == NE || code2 == ORDERED || code2 == LTGT)
79777bad 720 return 1;
721 break;
722
723 case GE:
724 case LE:
725 if (code2 == ORDERED)
726 return 1;
727 break;
728
729 case LTGT:
730 if (code2 == NE || code2 == ORDERED)
5924de0b 731 return 1;
732 break;
733
734 case LTU:
11088b43 735 if (code2 == LEU || code2 == NE)
5924de0b 736 return 1;
737 break;
738
739 case GTU:
11088b43 740 if (code2 == GEU || code2 == NE)
5924de0b 741 return 1;
742 break;
79777bad 743
744 case UNORDERED:
5aa3f5e2 745 if (code2 == NE || code2 == UNEQ || code2 == UNLE || code2 == UNLT
746 || code2 == UNGE || code2 == UNGT)
79777bad 747 return 1;
748 break;
7113a566 749
0dbd1c74 750 default:
751 break;
5924de0b 752 }
753
754 return 0;
755}
756\f
757/* Return 1 if INSN is an unconditional jump and nothing else. */
758
759int
52d07779 760simplejump_p (const_rtx insn)
5924de0b 761{
6d7dc5b9 762 return (JUMP_P (insn)
8d472058 763 && GET_CODE (PATTERN (insn)) == SET
764 && GET_CODE (SET_DEST (PATTERN (insn))) == PC
765 && GET_CODE (SET_SRC (PATTERN (insn))) == LABEL_REF);
5924de0b 766}
767
768/* Return nonzero if INSN is a (possibly) conditional jump
7113a566 769 and nothing more.
770
4885b286 771 Use of this function is deprecated, since we need to support combined
d670e794 772 branch and compare insns. Use any_condjump_p instead whenever possible. */
5924de0b 773
774int
52d07779 775condjump_p (const_rtx insn)
5924de0b 776{
52d07779 777 const_rtx x = PATTERN (insn);
7014838c 778
779 if (GET_CODE (x) != SET
780 || GET_CODE (SET_DEST (x)) != PC)
4fbe8fa7 781 return 0;
7014838c 782
783 x = SET_SRC (x);
784 if (GET_CODE (x) == LABEL_REF)
4fbe8fa7 785 return 1;
7113a566 786 else
787 return (GET_CODE (x) == IF_THEN_ELSE
788 && ((GET_CODE (XEXP (x, 2)) == PC
789 && (GET_CODE (XEXP (x, 1)) == LABEL_REF
9cb2517e 790 || ANY_RETURN_P (XEXP (x, 1))))
7113a566 791 || (GET_CODE (XEXP (x, 1)) == PC
792 && (GET_CODE (XEXP (x, 2)) == LABEL_REF
9cb2517e 793 || ANY_RETURN_P (XEXP (x, 2))))));
4fbe8fa7 794}
795
7014838c 796/* Return nonzero if INSN is a (possibly) conditional jump inside a
3a941ad5 797 PARALLEL.
7113a566 798
d670e794 799 Use this function is deprecated, since we need to support combined
800 branch and compare insns. Use any_condjump_p instead whenever possible. */
4fbe8fa7 801
802int
52d07779 803condjump_in_parallel_p (const_rtx insn)
4fbe8fa7 804{
52d07779 805 const_rtx x = PATTERN (insn);
4fbe8fa7 806
807 if (GET_CODE (x) != PARALLEL)
808 return 0;
809 else
810 x = XVECEXP (x, 0, 0);
811
5924de0b 812 if (GET_CODE (x) != SET)
813 return 0;
814 if (GET_CODE (SET_DEST (x)) != PC)
815 return 0;
816 if (GET_CODE (SET_SRC (x)) == LABEL_REF)
817 return 1;
818 if (GET_CODE (SET_SRC (x)) != IF_THEN_ELSE)
819 return 0;
820 if (XEXP (SET_SRC (x), 2) == pc_rtx
821 && (GET_CODE (XEXP (SET_SRC (x), 1)) == LABEL_REF
9cb2517e 822 || ANY_RETURN_P (XEXP (SET_SRC (x), 1))))
5924de0b 823 return 1;
824 if (XEXP (SET_SRC (x), 1) == pc_rtx
825 && (GET_CODE (XEXP (SET_SRC (x), 2)) == LABEL_REF
9cb2517e 826 || ANY_RETURN_P (XEXP (SET_SRC (x), 2))))
5924de0b 827 return 1;
828 return 0;
829}
830
d670e794 831/* Return set of PC, otherwise NULL. */
832
3a941ad5 833rtx
52d07779 834pc_set (const_rtx insn)
3a941ad5 835{
836 rtx pat;
6d7dc5b9 837 if (!JUMP_P (insn))
d670e794 838 return NULL_RTX;
3a941ad5 839 pat = PATTERN (insn);
d670e794 840
841 /* The set is allowed to appear either as the insn pattern or
842 the first set in a PARALLEL. */
843 if (GET_CODE (pat) == PARALLEL)
844 pat = XVECEXP (pat, 0, 0);
3a941ad5 845 if (GET_CODE (pat) == SET && GET_CODE (SET_DEST (pat)) == PC)
846 return pat;
d670e794 847
848 return NULL_RTX;
3a941ad5 849}
850
d670e794 851/* Return true when insn is an unconditional direct jump,
852 possibly bundled inside a PARALLEL. */
853
3a941ad5 854int
52d07779 855any_uncondjump_p (const_rtx insn)
3a941ad5 856{
52d07779 857 const_rtx x = pc_set (insn);
3a941ad5 858 if (!x)
859 return 0;
860 if (GET_CODE (SET_SRC (x)) != LABEL_REF)
861 return 0;
4ee9c684 862 if (find_reg_note (insn, REG_NON_LOCAL_GOTO, NULL_RTX))
863 return 0;
3a941ad5 864 return 1;
865}
866
d670e794 867/* Return true when insn is a conditional jump. This function works for
3a941ad5 868 instructions containing PC sets in PARALLELs. The instruction may have
869 various other effects so before removing the jump you must verify
9641f63c 870 onlyjump_p.
3a941ad5 871
d670e794 872 Note that unlike condjump_p it returns false for unconditional jumps. */
873
3a941ad5 874int
52d07779 875any_condjump_p (const_rtx insn)
3a941ad5 876{
52d07779 877 const_rtx x = pc_set (insn);
d670e794 878 enum rtx_code a, b;
879
3a941ad5 880 if (!x)
881 return 0;
d670e794 882 if (GET_CODE (SET_SRC (x)) != IF_THEN_ELSE)
883 return 0;
3a941ad5 884
d670e794 885 a = GET_CODE (XEXP (SET_SRC (x), 1));
886 b = GET_CODE (XEXP (SET_SRC (x), 2));
3a941ad5 887
9cb2517e 888 return ((b == PC && (a == LABEL_REF || a == RETURN || a == SIMPLE_RETURN))
889 || (a == PC
890 && (b == LABEL_REF || b == RETURN || b == SIMPLE_RETURN)));
3a941ad5 891}
892
8f7b24f3 893/* Return the label of a conditional jump. */
894
895rtx
5493cb9a 896condjump_label (const_rtx insn)
8f7b24f3 897{
d670e794 898 rtx x = pc_set (insn);
8f7b24f3 899
d670e794 900 if (!x)
8f7b24f3 901 return NULL_RTX;
902 x = SET_SRC (x);
903 if (GET_CODE (x) == LABEL_REF)
904 return x;
905 if (GET_CODE (x) != IF_THEN_ELSE)
906 return NULL_RTX;
907 if (XEXP (x, 2) == pc_rtx && GET_CODE (XEXP (x, 1)) == LABEL_REF)
908 return XEXP (x, 1);
909 if (XEXP (x, 1) == pc_rtx && GET_CODE (XEXP (x, 2)) == LABEL_REF)
910 return XEXP (x, 2);
911 return NULL_RTX;
912}
913
71caadc0 914/* Return true if INSN is a (possibly conditional) return insn. */
915
916static int
3ad4992f 917returnjump_p_1 (rtx *loc, void *data ATTRIBUTE_UNUSED)
71caadc0 918{
919 rtx x = *loc;
c3987c92 920
25e880b1 921 if (x == NULL)
922 return false;
923
924 switch (GET_CODE (x))
925 {
926 case RETURN:
9cb2517e 927 case SIMPLE_RETURN:
25e880b1 928 case EH_RETURN:
929 return true;
930
931 case SET:
932 return SET_IS_RETURN_P (x);
933
934 default:
935 return false;
936 }
71caadc0 937}
938
01e196ce 939/* Return TRUE if INSN is a return jump. */
940
71caadc0 941int
3ad4992f 942returnjump_p (rtx insn)
71caadc0 943{
6d7dc5b9 944 if (!JUMP_P (insn))
cbd914e1 945 return 0;
71caadc0 946 return for_each_rtx (&PATTERN (insn), returnjump_p_1, NULL);
947}
948
25e880b1 949/* Return true if INSN is a (possibly conditional) return insn. */
950
951static int
952eh_returnjump_p_1 (rtx *loc, void *data ATTRIBUTE_UNUSED)
953{
954 return *loc && GET_CODE (*loc) == EH_RETURN;
955}
956
957int
958eh_returnjump_p (rtx insn)
959{
960 if (!JUMP_P (insn))
961 return 0;
962 return for_each_rtx (&PATTERN (insn), eh_returnjump_p_1, NULL);
963}
964
459e9193 965/* Return true if INSN is a jump that only transfers control and
966 nothing more. */
967
968int
52d07779 969onlyjump_p (const_rtx insn)
459e9193 970{
971 rtx set;
972
6d7dc5b9 973 if (!JUMP_P (insn))
459e9193 974 return 0;
975
976 set = single_set (insn);
977 if (set == NULL)
978 return 0;
979 if (GET_CODE (SET_DEST (set)) != PC)
980 return 0;
981 if (side_effects_p (SET_SRC (set)))
982 return 0;
983
984 return 1;
985}
986
4115ac36 987/* Return true iff INSN is a jump and its JUMP_LABEL is a label, not
988 NULL or a return. */
989bool
990jump_to_label_p (rtx insn)
991{
992 return (JUMP_P (insn)
993 && JUMP_LABEL (insn) != NULL && !ANY_RETURN_P (JUMP_LABEL (insn)));
994}
995
9bf8c346 996#ifdef HAVE_cc0
997
6ef828f9 998/* Return nonzero if X is an RTX that only sets the condition codes
2dcd83ba 999 and has no side effects. */
1000
1001int
52d07779 1002only_sets_cc0_p (const_rtx x)
2dcd83ba 1003{
2dcd83ba 1004 if (! x)
1005 return 0;
1006
1007 if (INSN_P (x))
1008 x = PATTERN (x);
1009
1010 return sets_cc0_p (x) == 1 && ! side_effects_p (x);
1011}
1012
5924de0b 1013/* Return 1 if X is an RTX that does nothing but set the condition codes
1014 and CLOBBER or USE registers.
1015 Return -1 if X does explicitly set the condition codes,
1016 but also does other things. */
1017
1018int
52d07779 1019sets_cc0_p (const_rtx x)
5924de0b 1020{
2dcd83ba 1021 if (! x)
1022 return 0;
1023
1024 if (INSN_P (x))
1025 x = PATTERN (x);
1026
5924de0b 1027 if (GET_CODE (x) == SET && SET_DEST (x) == cc0_rtx)
1028 return 1;
1029 if (GET_CODE (x) == PARALLEL)
1030 {
1031 int i;
1032 int sets_cc0 = 0;
1033 int other_things = 0;
1034 for (i = XVECLEN (x, 0) - 1; i >= 0; i--)
1035 {
1036 if (GET_CODE (XVECEXP (x, 0, i)) == SET
1037 && SET_DEST (XVECEXP (x, 0, i)) == cc0_rtx)
1038 sets_cc0 = 1;
1039 else if (GET_CODE (XVECEXP (x, 0, i)) == SET)
1040 other_things = 1;
1041 }
1042 return ! sets_cc0 ? 0 : other_things ? -1 : 1;
1043 }
1044 return 0;
5924de0b 1045}
9bf8c346 1046#endif
5924de0b 1047\f
19d2fe05 1048/* Find all CODE_LABELs referred to in X, and increment their use
1049 counts. If INSN is a JUMP_INSN and there is at least one
1050 CODE_LABEL referenced in INSN as a jump target, then store the last
1051 one in JUMP_LABEL (INSN). For a tablejump, this must be the label
1052 for the ADDR_VEC. Store any other jump targets as REG_LABEL_TARGET
1053 notes. If INSN is an INSN or a CALL_INSN or non-target operands of
1054 a JUMP_INSN, and there is at least one CODE_LABEL referenced in
1055 INSN, add a REG_LABEL_OPERAND note containing that label to INSN.
e0691b9a 1056 For returnjumps, the JUMP_LABEL will also be set as appropriate.
5924de0b 1057
1058 Note that two labels separated by a loop-beginning note
1059 must be kept distinct if we have not yet done loop-optimization,
1060 because the gap between them is where loop-optimize
1061 will want to move invariant code to. CROSS_JUMP tells us
bf73fcf4 1062 that loop-optimization is done with. */
5924de0b 1063
5377f687 1064void
3ad4992f 1065mark_jump_label (rtx x, rtx insn, int in_mem)
19d2fe05 1066{
78f55ca8 1067 rtx asmop = extract_asm_operands (x);
1068 if (asmop)
1069 mark_jump_label_asm (asmop, insn);
1070 else
1071 mark_jump_label_1 (x, insn, in_mem != 0,
1072 (insn != NULL && x == PATTERN (insn) && JUMP_P (insn)));
19d2fe05 1073}
1074
c7684b8e 1075/* Worker function for mark_jump_label. IN_MEM is TRUE when X occurs
19d2fe05 1076 within a (MEM ...). IS_TARGET is TRUE when X is to be treated as a
1077 jump-target; when the JUMP_LABEL field of INSN should be set or a
1078 REG_LABEL_TARGET note should be added, not a REG_LABEL_OPERAND
1079 note. */
1080
1081static void
1082mark_jump_label_1 (rtx x, rtx insn, bool in_mem, bool is_target)
5924de0b 1083{
19cb6b50 1084 RTX_CODE code = GET_CODE (x);
1085 int i;
1086 const char *fmt;
5924de0b 1087
1088 switch (code)
1089 {
1090 case PC:
1091 case CC0:
1092 case REG:
5924de0b 1093 case CLOBBER:
1094 case CALL:
1095 return;
1096
e0691b9a 1097 case RETURN:
31a53363 1098 case SIMPLE_RETURN:
e0691b9a 1099 if (is_target)
1100 {
1101 gcc_assert (JUMP_LABEL (insn) == NULL || JUMP_LABEL (insn) == x);
1102 JUMP_LABEL (insn) = x;
1103 }
1104 return;
1105
d8e0d332 1106 case MEM:
19d2fe05 1107 in_mem = true;
190099a6 1108 break;
1109
76021441 1110 case SEQUENCE:
1111 for (i = 0; i < XVECLEN (x, 0); i++)
1112 mark_jump_label (PATTERN (XVECEXP (x, 0, i)),
1113 XVECEXP (x, 0, i), 0);
1114 return;
1115
190099a6 1116 case SYMBOL_REF:
1117 if (!in_mem)
7113a566 1118 return;
190099a6 1119
d8e0d332 1120 /* If this is a constant-pool reference, see if it is a label. */
190099a6 1121 if (CONSTANT_POOL_ADDRESS_P (x))
19d2fe05 1122 mark_jump_label_1 (get_pool_constant (x), insn, in_mem, is_target);
d8e0d332 1123 break;
1124
19d2fe05 1125 /* Handle operands in the condition of an if-then-else as for a
1126 non-jump insn. */
1127 case IF_THEN_ELSE:
1128 if (!is_target)
1129 break;
1130 mark_jump_label_1 (XEXP (x, 0), insn, in_mem, false);
1131 mark_jump_label_1 (XEXP (x, 1), insn, in_mem, true);
1132 mark_jump_label_1 (XEXP (x, 2), insn, in_mem, true);
1133 return;
1134
5924de0b 1135 case LABEL_REF:
1136 {
b4d3bcce 1137 rtx label = XEXP (x, 0);
b4d3bcce 1138
74b0991d 1139 /* Ignore remaining references to unreachable labels that
1140 have been deleted. */
6d7dc5b9 1141 if (NOTE_P (label)
ad4583d9 1142 && NOTE_KIND (label) == NOTE_INSN_DELETED_LABEL)
74b0991d 1143 break;
1144
a53ff4c1 1145 gcc_assert (LABEL_P (label));
b4d3bcce 1146
f08cae9d 1147 /* Ignore references to labels of containing functions. */
1148 if (LABEL_REF_NONLOCAL_P (x))
1149 break;
b4d3bcce 1150
5924de0b 1151 XEXP (x, 0) = label;
943e16d8 1152 if (! insn || ! INSN_DELETED_P (insn))
1153 ++LABEL_NUSES (label);
b4d3bcce 1154
5924de0b 1155 if (insn)
1156 {
19d2fe05 1157 if (is_target
a8d1dae0 1158 /* Do not change a previous setting of JUMP_LABEL. If the
1159 JUMP_LABEL slot is occupied by a different label,
1160 create a note for this label. */
19d2fe05 1161 && (JUMP_LABEL (insn) == NULL || JUMP_LABEL (insn) == label))
5924de0b 1162 JUMP_LABEL (insn) = label;
ab2237b5 1163 else
e89849bd 1164 {
19d2fe05 1165 enum reg_note kind
1166 = is_target ? REG_LABEL_TARGET : REG_LABEL_OPERAND;
1167
1168 /* Add a REG_LABEL_OPERAND or REG_LABEL_TARGET note
1169 for LABEL unless there already is one. All uses of
1170 a label, except for the primary target of a jump,
1171 must have such a note. */
1172 if (! find_reg_note (insn, kind, label))
a1ddb869 1173 add_reg_note (insn, kind, label);
5924de0b 1174 }
1175 }
1176 return;
1177 }
1178
91f71fa3 1179 /* Do walk the labels in a vector, but not the first operand of an
1180 ADDR_DIFF_VEC. Don't set the JUMP_LABEL of a vector. */
5924de0b 1181 case ADDR_VEC:
1182 case ADDR_DIFF_VEC:
943e16d8 1183 if (! INSN_DELETED_P (insn))
1184 {
1185 int eltnum = code == ADDR_DIFF_VEC ? 1 : 0;
5924de0b 1186
943e16d8 1187 for (i = 0; i < XVECLEN (x, eltnum); i++)
19d2fe05 1188 mark_jump_label_1 (XVECEXP (x, eltnum, i), NULL_RTX, in_mem,
1189 is_target);
943e16d8 1190 }
0dbd1c74 1191 return;
7113a566 1192
0dbd1c74 1193 default:
1194 break;
5924de0b 1195 }
1196
1197 fmt = GET_RTX_FORMAT (code);
19d2fe05 1198
1199 /* The primary target of a tablejump is the label of the ADDR_VEC,
1200 which is canonically mentioned *last* in the insn. To get it
1201 marked as JUMP_LABEL, we iterate over items in reverse order. */
5924de0b 1202 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
1203 {
1204 if (fmt[i] == 'e')
19d2fe05 1205 mark_jump_label_1 (XEXP (x, i), insn, in_mem, is_target);
5924de0b 1206 else if (fmt[i] == 'E')
1207 {
19cb6b50 1208 int j;
19d2fe05 1209
1210 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
1211 mark_jump_label_1 (XVECEXP (x, i, j), insn, in_mem,
1212 is_target);
5924de0b 1213 }
1214 }
1215}
1216
78f55ca8 1217/* Worker function for mark_jump_label. Handle asm insns specially.
1218 In particular, output operands need not be considered so we can
1219 avoid re-scanning the replicated asm_operand. Also, the asm_labels
1220 need to be considered targets. */
1221
1222static void
1223mark_jump_label_asm (rtx asmop, rtx insn)
1224{
1225 int i;
1226
1227 for (i = ASM_OPERANDS_INPUT_LENGTH (asmop) - 1; i >= 0; --i)
1228 mark_jump_label_1 (ASM_OPERANDS_INPUT (asmop, i), insn, false, false);
1229
1230 for (i = ASM_OPERANDS_LABEL_LENGTH (asmop) - 1; i >= 0; --i)
1231 mark_jump_label_1 (ASM_OPERANDS_LABEL (asmop, i), insn, false, true);
1232}
5924de0b 1233\f
e4bf866d 1234/* Delete insn INSN from the chain of insns and update label ref counts
17a74abe 1235 and delete insns now unreachable.
e4bf866d 1236
17a74abe 1237 Returns the first insn after INSN that was not deleted.
5924de0b 1238
e4bf866d 1239 Usage of this instruction is deprecated. Use delete_insn instead and
1240 subsequent cfg_cleanup pass to delete unreachable code if needed. */
5924de0b 1241
1242rtx
3ad4992f 1243delete_related_insns (rtx insn)
5924de0b 1244{
6d7dc5b9 1245 int was_code_label = (LABEL_P (insn));
d3df77e9 1246 rtx note;
e4bf866d 1247 rtx next = NEXT_INSN (insn), prev = PREV_INSN (insn);
5924de0b 1248
1249 while (next && INSN_DELETED_P (next))
1250 next = NEXT_INSN (next);
1251
1252 /* This insn is already deleted => return first following nondeleted. */
1253 if (INSN_DELETED_P (insn))
1254 return next;
1255
e4bf866d 1256 delete_insn (insn);
5924de0b 1257
5924de0b 1258 /* If instruction is followed by a barrier,
1259 delete the barrier too. */
1260
6d7dc5b9 1261 if (next != 0 && BARRIER_P (next))
e4bf866d 1262 delete_insn (next);
5924de0b 1263
ad35ffdc 1264 /* If this is a call, then we have to remove the var tracking note
1265 for the call arguments. */
1266
1267 if (CALL_P (insn)
1268 || (NONJUMP_INSN_P (insn)
1269 && GET_CODE (PATTERN (insn)) == SEQUENCE
1270 && CALL_P (XVECEXP (PATTERN (insn), 0, 0))))
1271 {
d48fddee 1272 rtx p;
ad35ffdc 1273
d48fddee 1274 for (p = next && INSN_DELETED_P (next) ? NEXT_INSN (next) : next;
ad35ffdc 1275 p && NOTE_P (p);
1276 p = NEXT_INSN (p))
1277 if (NOTE_KIND (p) == NOTE_INSN_CALL_ARG_LOCATION)
1278 {
1279 remove_insn (p);
1280 break;
1281 }
1282 }
1283
5924de0b 1284 /* If deleting a jump, decrement the count of the label,
1285 and delete the label if it is now unused. */
1286
4115ac36 1287 if (jump_to_label_p (insn))
1793cd6b 1288 {
1289 rtx lab = JUMP_LABEL (insn), lab_next;
1290
e4bf866d 1291 if (LABEL_NUSES (lab) == 0)
19d2fe05 1292 /* This can delete NEXT or PREV,
1293 either directly if NEXT is JUMP_LABEL (INSN),
1294 or indirectly through more levels of jumps. */
1295 delete_related_insns (lab);
b19beda9 1296 else if (tablejump_p (insn, NULL, &lab_next))
1793cd6b 1297 {
1298 /* If we're deleting the tablejump, delete the dispatch table.
4a82352a 1299 We may not be able to kill the label immediately preceding
1793cd6b 1300 just yet, as it might be referenced in code leading up to
1301 the tablejump. */
e4bf866d 1302 delete_related_insns (lab_next);
1793cd6b 1303 }
1304 }
5924de0b 1305
9c9e0c01 1306 /* Likewise if we're deleting a dispatch table. */
1307
971ba038 1308 if (JUMP_TABLE_DATA_P (insn))
9c9e0c01 1309 {
1310 rtx pat = PATTERN (insn);
1311 int i, diff_vec_p = GET_CODE (pat) == ADDR_DIFF_VEC;
1312 int len = XVECLEN (pat, diff_vec_p);
1313
1314 for (i = 0; i < len; i++)
e4bf866d 1315 if (LABEL_NUSES (XEXP (XVECEXP (pat, diff_vec_p, i), 0)) == 0)
1316 delete_related_insns (XEXP (XVECEXP (pat, diff_vec_p, i), 0));
9c9e0c01 1317 while (next && INSN_DELETED_P (next))
1318 next = NEXT_INSN (next);
1319 return next;
1320 }
1321
19d2fe05 1322 /* Likewise for any JUMP_P / INSN / CALL_INSN with a
1323 REG_LABEL_OPERAND or REG_LABEL_TARGET note. */
1324 if (INSN_P (insn))
d3df77e9 1325 for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
19d2fe05 1326 if ((REG_NOTE_KIND (note) == REG_LABEL_OPERAND
1327 || REG_NOTE_KIND (note) == REG_LABEL_TARGET)
0c97f529 1328 /* This could also be a NOTE_INSN_DELETED_LABEL note. */
6d7dc5b9 1329 && LABEL_P (XEXP (note, 0)))
e4bf866d 1330 if (LABEL_NUSES (XEXP (note, 0)) == 0)
1331 delete_related_insns (XEXP (note, 0));
d3df77e9 1332
6d7dc5b9 1333 while (prev && (INSN_DELETED_P (prev) || NOTE_P (prev)))
5924de0b 1334 prev = PREV_INSN (prev);
1335
1336 /* If INSN was a label and a dispatch table follows it,
1337 delete the dispatch table. The tablejump must have gone already.
1338 It isn't useful to fall through into a table. */
1339
9cdc08c6 1340 if (was_code_label
5924de0b 1341 && NEXT_INSN (insn) != 0
971ba038 1342 && JUMP_TABLE_DATA_P (NEXT_INSN (insn)))
e4bf866d 1343 next = delete_related_insns (NEXT_INSN (insn));
5924de0b 1344
1345 /* If INSN was a label, delete insns following it if now unreachable. */
1346
6d7dc5b9 1347 if (was_code_label && prev && BARRIER_P (prev))
5924de0b 1348 {
6720e96c 1349 enum rtx_code code;
1350 while (next)
5924de0b 1351 {
6720e96c 1352 code = GET_CODE (next);
737251e7 1353 if (code == NOTE)
5924de0b 1354 next = NEXT_INSN (next);
59bee35e 1355 /* Keep going past other deleted labels to delete what follows. */
1356 else if (code == CODE_LABEL && INSN_DELETED_P (next))
1357 next = NEXT_INSN (next);
6720e96c 1358 else if (code == BARRIER || INSN_P (next))
5924de0b 1359 /* Note: if this deletes a jump, it can cause more
1360 deletion of unreachable code, after a different label.
1361 As long as the value from this recursive call is correct,
1362 this invocation functions correctly. */
e4bf866d 1363 next = delete_related_insns (next);
6720e96c 1364 else
1365 break;
5924de0b 1366 }
1367 }
1368
19d2fe05 1369 /* I feel a little doubtful about this loop,
1370 but I see no clean and sure alternative way
1371 to find the first insn after INSN that is not now deleted.
1372 I hope this works. */
1373 while (next && INSN_DELETED_P (next))
1374 next = NEXT_INSN (next);
5924de0b 1375 return next;
1376}
5924de0b 1377\f
1378/* Delete a range of insns from FROM to TO, inclusive.
1379 This is for the sake of peephole optimization, so assume
1380 that whatever these insns do will still be done by a new
1381 peephole insn that will replace them. */
1382
1383void
3ad4992f 1384delete_for_peephole (rtx from, rtx to)
5924de0b 1385{
19cb6b50 1386 rtx insn = from;
5924de0b 1387
1388 while (1)
1389 {
19cb6b50 1390 rtx next = NEXT_INSN (insn);
1391 rtx prev = PREV_INSN (insn);
5924de0b 1392
6d7dc5b9 1393 if (!NOTE_P (insn))
5924de0b 1394 {
1395 INSN_DELETED_P (insn) = 1;
1396
1397 /* Patch this insn out of the chain. */
1398 /* We don't do this all at once, because we
1399 must preserve all NOTEs. */
1400 if (prev)
1401 NEXT_INSN (prev) = next;
1402
1403 if (next)
1404 PREV_INSN (next) = prev;
1405 }
1406
1407 if (insn == to)
1408 break;
1409 insn = next;
1410 }
1411
1412 /* Note that if TO is an unconditional jump
1413 we *do not* delete the BARRIER that follows,
1414 since the peephole that replaces this sequence
1415 is also an unconditional jump in that case. */
1416}
1417\f
4115ac36 1418/* A helper function for redirect_exp_1; examines its input X and returns
1419 either a LABEL_REF around a label, or a RETURN if X was NULL. */
1420static rtx
1421redirect_target (rtx x)
1422{
1423 if (x == NULL_RTX)
1424 return ret_rtx;
1425 if (!ANY_RETURN_P (x))
1426 return gen_rtx_LABEL_REF (Pmode, x);
1427 return x;
1428}
1429
a8b5d014 1430/* Throughout LOC, redirect OLABEL to NLABEL. Treat null OLABEL or
1431 NLABEL as a return. Accrue modifications into the change group. */
5924de0b 1432
a8b5d014 1433static void
3ad4992f 1434redirect_exp_1 (rtx *loc, rtx olabel, rtx nlabel, rtx insn)
5924de0b 1435{
19cb6b50 1436 rtx x = *loc;
1437 RTX_CODE code = GET_CODE (x);
1438 int i;
1439 const char *fmt;
5924de0b 1440
31a53363 1441 if ((code == LABEL_REF && XEXP (x, 0) == olabel)
4115ac36 1442 || x == olabel)
5924de0b 1443 {
4115ac36 1444 x = redirect_target (nlabel);
1445 if (GET_CODE (x) == LABEL_REF && loc == &PATTERN (insn))
1446 x = gen_rtx_SET (VOIDmode, pc_rtx, x);
a8b5d014 1447 validate_change (insn, loc, x, 1);
1448 return;
1449 }
5924de0b 1450
4115ac36 1451 if (code == SET && SET_DEST (x) == pc_rtx
1452 && ANY_RETURN_P (nlabel)
a8b5d014 1453 && GET_CODE (SET_SRC (x)) == LABEL_REF
1454 && XEXP (SET_SRC (x), 0) == olabel)
1455 {
4115ac36 1456 validate_change (insn, loc, nlabel, 1);
a8b5d014 1457 return;
5924de0b 1458 }
1459
3b10edae 1460 if (code == IF_THEN_ELSE)
1461 {
1462 /* Skip the condition of an IF_THEN_ELSE. We only want to
1463 change jump destinations, not eventual label comparisons. */
1464 redirect_exp_1 (&XEXP (x, 1), olabel, nlabel, insn);
1465 redirect_exp_1 (&XEXP (x, 2), olabel, nlabel, insn);
1466 return;
1467 }
1468
5924de0b 1469 fmt = GET_RTX_FORMAT (code);
1470 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
1471 {
1472 if (fmt[i] == 'e')
a8b5d014 1473 redirect_exp_1 (&XEXP (x, i), olabel, nlabel, insn);
1bd8ca86 1474 else if (fmt[i] == 'E')
5924de0b 1475 {
19cb6b50 1476 int j;
5924de0b 1477 for (j = 0; j < XVECLEN (x, i); j++)
a8b5d014 1478 redirect_exp_1 (&XVECEXP (x, i, j), olabel, nlabel, insn);
5924de0b 1479 }
1480 }
a8b5d014 1481}
5924de0b 1482
a8b5d014 1483/* Make JUMP go to NLABEL instead of where it jumps now. Accrue
1484 the modifications into the change group. Return false if we did
1485 not see how to do that. */
1486
1487int
3ad4992f 1488redirect_jump_1 (rtx jump, rtx nlabel)
a8b5d014 1489{
1490 int ochanges = num_validated_changes ();
78f55ca8 1491 rtx *loc, asmop;
ba08b7e7 1492
4115ac36 1493 gcc_assert (nlabel != NULL_RTX);
78f55ca8 1494 asmop = extract_asm_operands (PATTERN (jump));
1495 if (asmop)
1496 {
1497 if (nlabel == NULL)
1498 return 0;
1499 gcc_assert (ASM_OPERANDS_LABEL_LENGTH (asmop) == 1);
1500 loc = &ASM_OPERANDS_LABEL (asmop, 0);
1501 }
1502 else if (GET_CODE (PATTERN (jump)) == PARALLEL)
ba08b7e7 1503 loc = &XVECEXP (PATTERN (jump), 0, 0);
1504 else
1505 loc = &PATTERN (jump);
1506
1507 redirect_exp_1 (loc, JUMP_LABEL (jump), nlabel, jump);
a8b5d014 1508 return num_validated_changes () > ochanges;
1509}
1510
1511/* Make JUMP go to NLABEL instead of where it jumps now. If the old
1512 jump target label is unused as a result, it and the code following
1513 it may be deleted.
5924de0b 1514
4115ac36 1515 Normally, NLABEL will be a label, but it may also be a RETURN rtx;
1516 in that case we are to turn the jump into a (possibly conditional)
1517 return insn.
5924de0b 1518
a8b5d014 1519 The return value will be 1 if the change was made, 0 if it wasn't
4115ac36 1520 (this can only occur when trying to produce return insns). */
5924de0b 1521
1522int
3ad4992f 1523redirect_jump (rtx jump, rtx nlabel, int delete_unused)
5924de0b 1524{
19cb6b50 1525 rtx olabel = JUMP_LABEL (jump);
5924de0b 1526
e1e50552 1527 if (!nlabel)
1528 {
1529 /* If there is no label, we are asked to redirect to the EXIT block.
1530 When before the epilogue is emitted, return/simple_return cannot be
1531 created so we return 0 immediately. After the epilogue is emitted,
1532 we always expect a label, either a non-null label, or a
1533 return/simple_return RTX. */
1534
1535 if (!epilogue_completed)
1536 return 0;
1537 gcc_unreachable ();
1538 }
4115ac36 1539
5924de0b 1540 if (nlabel == olabel)
1541 return 1;
1542
82880dfd 1543 if (! redirect_jump_1 (jump, nlabel) || ! apply_change_group ())
5924de0b 1544 return 0;
1545
82880dfd 1546 redirect_jump_2 (jump, olabel, nlabel, delete_unused, 0);
1547 return 1;
1548}
1549
1550/* Fix up JUMP_LABEL and label ref counts after OLABEL has been replaced with
48e1416a 1551 NLABEL in JUMP.
82880dfd 1552 If DELETE_UNUSED is positive, delete related insn to OLABEL if its ref
1553 count has dropped to zero. */
1554void
1555redirect_jump_2 (rtx jump, rtx olabel, rtx nlabel, int delete_unused,
1556 int invert)
1557{
1558 rtx note;
1559
19d2fe05 1560 gcc_assert (JUMP_LABEL (jump) == olabel);
1561
f2b32076 1562 /* Negative DELETE_UNUSED used to be used to signalize behavior on
737251e7 1563 moving FUNCTION_END note. Just sanity check that no user still worry
1564 about this. */
1565 gcc_assert (delete_unused >= 0);
5924de0b 1566 JUMP_LABEL (jump) = nlabel;
4115ac36 1567 if (!ANY_RETURN_P (nlabel))
5924de0b 1568 ++LABEL_NUSES (nlabel);
1569
1e0703ac 1570 /* Update labels in any REG_EQUAL note. */
1571 if ((note = find_reg_note (jump, REG_EQUAL, NULL_RTX)) != NULL_RTX)
1572 {
4115ac36 1573 if (ANY_RETURN_P (nlabel)
1574 || (invert && !invert_exp_1 (XEXP (note, 0), jump)))
82880dfd 1575 remove_note (jump, note);
1576 else
1e0703ac 1577 {
82880dfd 1578 redirect_exp_1 (&XEXP (note, 0), olabel, nlabel, jump);
1579 confirm_change_group ();
1e0703ac 1580 }
1e0703ac 1581 }
1582
4115ac36 1583 if (!ANY_RETURN_P (olabel)
1584 && --LABEL_NUSES (olabel) == 0 && delete_unused > 0
7f8c3466 1585 /* Undefined labels will remain outside the insn stream. */
1586 && INSN_UID (olabel))
e4bf866d 1587 delete_related_insns (olabel);
82880dfd 1588 if (invert)
1589 invert_br_probabilities (jump);
5924de0b 1590}
1591
82880dfd 1592/* Invert the jump condition X contained in jump insn INSN. Accrue the
1593 modifications into the change group. Return nonzero for success. */
1594static int
1595invert_exp_1 (rtx x, rtx insn)
a8b5d014 1596{
82880dfd 1597 RTX_CODE code = GET_CODE (x);
a8b5d014 1598
1599 if (code == IF_THEN_ELSE)
1600 {
19cb6b50 1601 rtx comp = XEXP (x, 0);
1602 rtx tem;
7da6ea0c 1603 enum rtx_code reversed_code;
a8b5d014 1604
1605 /* We can do this in two ways: The preferable way, which can only
1606 be done if this is not an integer comparison, is to reverse
1607 the comparison code. Otherwise, swap the THEN-part and ELSE-part
1608 of the IF_THEN_ELSE. If we can't do either, fail. */
1609
7da6ea0c 1610 reversed_code = reversed_comparison_code (comp, insn);
1611
1612 if (reversed_code != UNKNOWN)
a8b5d014 1613 {
1614 validate_change (insn, &XEXP (x, 0),
7da6ea0c 1615 gen_rtx_fmt_ee (reversed_code,
a8b5d014 1616 GET_MODE (comp), XEXP (comp, 0),
1617 XEXP (comp, 1)),
1618 1);
82880dfd 1619 return 1;
a8b5d014 1620 }
7113a566 1621
a8b5d014 1622 tem = XEXP (x, 1);
1623 validate_change (insn, &XEXP (x, 1), XEXP (x, 2), 1);
1624 validate_change (insn, &XEXP (x, 2), tem, 1);
82880dfd 1625 return 1;
a8b5d014 1626 }
ba08b7e7 1627 else
a8b5d014 1628 return 0;
a8b5d014 1629}
1630
1631/* Invert the condition of the jump JUMP, and make it jump to label
1632 NLABEL instead of where it jumps now. Accrue changes into the
1633 change group. Return false if we didn't see how to perform the
1634 inversion and redirection. */
1635
1636int
3ad4992f 1637invert_jump_1 (rtx jump, rtx nlabel)
a8b5d014 1638{
82880dfd 1639 rtx x = pc_set (jump);
a8b5d014 1640 int ochanges;
a53ff4c1 1641 int ok;
a8b5d014 1642
1643 ochanges = num_validated_changes ();
78f55ca8 1644 if (x == NULL)
1645 return 0;
a53ff4c1 1646 ok = invert_exp_1 (SET_SRC (x), jump);
1647 gcc_assert (ok);
48e1416a 1648
a8b5d014 1649 if (num_validated_changes () == ochanges)
1650 return 0;
1651
50f46d50 1652 /* redirect_jump_1 will fail of nlabel == olabel, and the current use is
1653 in Pmode, so checking this is not merely an optimization. */
1654 return nlabel == JUMP_LABEL (jump) || redirect_jump_1 (jump, nlabel);
a8b5d014 1655}
1656
1657/* Invert the condition of the jump JUMP, and make it jump to label
1658 NLABEL instead of where it jumps now. Return true if successful. */
1659
1660int
3ad4992f 1661invert_jump (rtx jump, rtx nlabel, int delete_unused)
a8b5d014 1662{
82880dfd 1663 rtx olabel = JUMP_LABEL (jump);
a8b5d014 1664
82880dfd 1665 if (invert_jump_1 (jump, nlabel) && apply_change_group ())
a8b5d014 1666 {
82880dfd 1667 redirect_jump_2 (jump, olabel, nlabel, delete_unused, 1);
a8b5d014 1668 return 1;
1669 }
82880dfd 1670 cancel_changes (0);
a8b5d014 1671 return 0;
1672}
1673
5924de0b 1674\f
1675/* Like rtx_equal_p except that it considers two REGs as equal
6c60c295 1676 if they renumber to the same value and considers two commutative
1677 operations to be the same if the order of the operands has been
280566a7 1678 reversed. */
5924de0b 1679
1680int
a9f1838b 1681rtx_renumbered_equal_p (const_rtx x, const_rtx y)
5924de0b 1682{
19cb6b50 1683 int i;
52d07779 1684 const enum rtx_code code = GET_CODE (x);
19cb6b50 1685 const char *fmt;
7113a566 1686
5924de0b 1687 if (x == y)
1688 return 1;
6c60c295 1689
8ad4c111 1690 if ((code == REG || (code == SUBREG && REG_P (SUBREG_REG (x))))
1691 && (REG_P (y) || (GET_CODE (y) == SUBREG
1692 && REG_P (SUBREG_REG (y)))))
5924de0b 1693 {
6c60c295 1694 int reg_x = -1, reg_y = -1;
701e46d0 1695 int byte_x = 0, byte_y = 0;
9680c846 1696 struct subreg_info info;
5924de0b 1697
1698 if (GET_MODE (x) != GET_MODE (y))
1699 return 0;
1700
1701 /* If we haven't done any renumbering, don't
1702 make any assumptions. */
1703 if (reg_renumber == 0)
1704 return rtx_equal_p (x, y);
1705
1706 if (code == SUBREG)
1707 {
6c60c295 1708 reg_x = REGNO (SUBREG_REG (x));
701e46d0 1709 byte_x = SUBREG_BYTE (x);
6c60c295 1710
1711 if (reg_renumber[reg_x] >= 0)
1712 {
9680c846 1713 subreg_get_info (reg_renumber[reg_x],
1714 GET_MODE (SUBREG_REG (x)), byte_x,
1715 GET_MODE (x), &info);
1716 if (!info.representable_p)
62e42324 1717 return 0;
9680c846 1718 reg_x = info.offset;
701e46d0 1719 byte_x = 0;
6c60c295 1720 }
5924de0b 1721 }
1722 else
1723 {
6c60c295 1724 reg_x = REGNO (x);
1725 if (reg_renumber[reg_x] >= 0)
1726 reg_x = reg_renumber[reg_x];
5924de0b 1727 }
6c60c295 1728
5924de0b 1729 if (GET_CODE (y) == SUBREG)
1730 {
6c60c295 1731 reg_y = REGNO (SUBREG_REG (y));
701e46d0 1732 byte_y = SUBREG_BYTE (y);
6c60c295 1733
1734 if (reg_renumber[reg_y] >= 0)
1735 {
9680c846 1736 subreg_get_info (reg_renumber[reg_y],
1737 GET_MODE (SUBREG_REG (y)), byte_y,
1738 GET_MODE (y), &info);
1739 if (!info.representable_p)
62e42324 1740 return 0;
9680c846 1741 reg_y = info.offset;
701e46d0 1742 byte_y = 0;
6c60c295 1743 }
5924de0b 1744 }
1745 else
1746 {
6c60c295 1747 reg_y = REGNO (y);
1748 if (reg_renumber[reg_y] >= 0)
1749 reg_y = reg_renumber[reg_y];
5924de0b 1750 }
6c60c295 1751
701e46d0 1752 return reg_x >= 0 && reg_x == reg_y && byte_x == byte_y;
5924de0b 1753 }
6c60c295 1754
7113a566 1755 /* Now we have disposed of all the cases
5924de0b 1756 in which different rtx codes can match. */
1757 if (code != GET_CODE (y))
1758 return 0;
6c60c295 1759
5924de0b 1760 switch (code)
1761 {
1762 case PC:
1763 case CC0:
1764 case ADDR_VEC:
1765 case ADDR_DIFF_VEC:
0349edce 1766 CASE_CONST_UNIQUE:
70b1bccd 1767 return 0;
5924de0b 1768
1769 case LABEL_REF:
f08cae9d 1770 /* We can't assume nonlocal labels have their following insns yet. */
1771 if (LABEL_REF_NONLOCAL_P (x) || LABEL_REF_NONLOCAL_P (y))
1772 return XEXP (x, 0) == XEXP (y, 0);
6c60c295 1773
5924de0b 1774 /* Two label-refs are equivalent if they point at labels
1775 in the same position in the instruction stream. */
1776 return (next_real_insn (XEXP (x, 0))
1777 == next_real_insn (XEXP (y, 0)));
1778
1779 case SYMBOL_REF:
1780 return XSTR (x, 0) == XSTR (y, 0);
0dbd1c74 1781
fc41ccae 1782 case CODE_LABEL:
1783 /* If we didn't match EQ equality above, they aren't the same. */
1784 return 0;
1785
0dbd1c74 1786 default:
1787 break;
5924de0b 1788 }
1789
1790 /* (MULT:SI x y) and (MULT:HI x y) are NOT equivalent. */
1791
1792 if (GET_MODE (x) != GET_MODE (y))
1793 return 0;
1794
04ec15fa 1795 /* MEMs referring to different address space are not equivalent. */
bd1a81f7 1796 if (code == MEM && MEM_ADDR_SPACE (x) != MEM_ADDR_SPACE (y))
1797 return 0;
1798
6c60c295 1799 /* For commutative operations, the RTX match if the operand match in any
280566a7 1800 order. Also handle the simple binary and unary cases without a loop. */
1801 if (targetm.commutative_p (x, UNKNOWN))
6c60c295 1802 return ((rtx_renumbered_equal_p (XEXP (x, 0), XEXP (y, 0))
1803 && rtx_renumbered_equal_p (XEXP (x, 1), XEXP (y, 1)))
1804 || (rtx_renumbered_equal_p (XEXP (x, 0), XEXP (y, 1))
1805 && rtx_renumbered_equal_p (XEXP (x, 1), XEXP (y, 0))));
6720e96c 1806 else if (NON_COMMUTATIVE_P (x))
6c60c295 1807 return (rtx_renumbered_equal_p (XEXP (x, 0), XEXP (y, 0))
1808 && rtx_renumbered_equal_p (XEXP (x, 1), XEXP (y, 1)));
6720e96c 1809 else if (UNARY_P (x))
6c60c295 1810 return rtx_renumbered_equal_p (XEXP (x, 0), XEXP (y, 0));
1811
5924de0b 1812 /* Compare the elements. If any pair of corresponding elements
1813 fail to match, return 0 for the whole things. */
1814
1815 fmt = GET_RTX_FORMAT (code);
1816 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
1817 {
19cb6b50 1818 int j;
5924de0b 1819 switch (fmt[i])
1820 {
1bb04728 1821 case 'w':
1822 if (XWINT (x, i) != XWINT (y, i))
1823 return 0;
1824 break;
1825
5924de0b 1826 case 'i':
1827 if (XINT (x, i) != XINT (y, i))
6675c1b7 1828 {
1829 if (((code == ASM_OPERANDS && i == 6)
5169661d 1830 || (code == ASM_INPUT && i == 1)))
6675c1b7 1831 break;
1832 return 0;
1833 }
5924de0b 1834 break;
1835
a0d79d69 1836 case 't':
1837 if (XTREE (x, i) != XTREE (y, i))
1838 return 0;
1839 break;
1840
5924de0b 1841 case 's':
1842 if (strcmp (XSTR (x, i), XSTR (y, i)))
1843 return 0;
1844 break;
1845
1846 case 'e':
1847 if (! rtx_renumbered_equal_p (XEXP (x, i), XEXP (y, i)))
1848 return 0;
1849 break;
1850
1851 case 'u':
1852 if (XEXP (x, i) != XEXP (y, i))
1853 return 0;
b4b174c3 1854 /* Fall through. */
5924de0b 1855 case '0':
1856 break;
1857
1858 case 'E':
1859 if (XVECLEN (x, i) != XVECLEN (y, i))
1860 return 0;
1861 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
1862 if (!rtx_renumbered_equal_p (XVECEXP (x, i, j), XVECEXP (y, i, j)))
1863 return 0;
1864 break;
1865
1866 default:
a53ff4c1 1867 gcc_unreachable ();
5924de0b 1868 }
1869 }
1870 return 1;
1871}
1872\f
1873/* If X is a hard register or equivalent to one or a subregister of one,
1874 return the hard register number. If X is a pseudo register that was not
1875 assigned a hard register, return the pseudo register number. Otherwise,
1876 return -1. Any rtx is valid for X. */
1877
1878int
52d07779 1879true_regnum (const_rtx x)
5924de0b 1880{
8ad4c111 1881 if (REG_P (x))
5924de0b 1882 {
c6a6cdaa 1883 if (REGNO (x) >= FIRST_PSEUDO_REGISTER
1884 && (lra_in_progress || reg_renumber[REGNO (x)] >= 0))
5924de0b 1885 return reg_renumber[REGNO (x)];
1886 return REGNO (x);
1887 }
1888 if (GET_CODE (x) == SUBREG)
1889 {
1890 int base = true_regnum (SUBREG_REG (x));
90489f58 1891 if (base >= 0
9680c846 1892 && base < FIRST_PSEUDO_REGISTER)
1893 {
1894 struct subreg_info info;
1895
c6a6cdaa 1896 subreg_get_info (lra_in_progress
1897 ? (unsigned) base : REGNO (SUBREG_REG (x)),
9680c846 1898 GET_MODE (SUBREG_REG (x)),
1899 SUBREG_BYTE (x), GET_MODE (x), &info);
1900
1901 if (info.representable_p)
1902 return base + info.offset;
1903 }
5924de0b 1904 }
1905 return -1;
1906}
b627bae7 1907
1908/* Return regno of the register REG and handle subregs too. */
1909unsigned int
52d07779 1910reg_or_subregno (const_rtx reg)
b627bae7 1911{
b627bae7 1912 if (GET_CODE (reg) == SUBREG)
a53ff4c1 1913 reg = SUBREG_REG (reg);
1914 gcc_assert (REG_P (reg));
1915 return REGNO (reg);
b627bae7 1916}