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