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