1 /* Optimize jump instructions, for GNU compiler.
2 Copyright (C) 1987-2018 Free Software Foundation, Inc.
4 This file is part of GCC.
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 3, or (at your option) any later
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3. If not see
18 <http://www.gnu.org/licenses/>. */
20 /* This is the pathetic reminder of old fame of the jump-optimization pass
21 of the compiler. Now it contains basically a set of utility functions to
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
30 at by later passes. For return insns, it contains either a
31 RETURN or a SIMPLE_RETURN rtx.
33 The subroutines redirect_jump and invert_jump are used
34 from other passes as well. */
38 #include "coretypes.h"
44 #include "tree-pass.h"
47 #include "insn-config.h"
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. */
61 static void init_label_info (rtx_insn
*);
62 static void mark_all_labels (rtx_insn
*);
63 static void mark_jump_label_1 (rtx
, rtx_insn
*, bool, bool);
64 static void mark_jump_label_asm (rtx
, rtx_insn
*);
65 static void redirect_exp_1 (rtx
*, rtx
, rtx
, rtx_insn
*);
66 static int invert_exp_1 (rtx
, rtx_insn
*);
68 /* Worker for rebuild_jump_labels and rebuild_jump_labels_chain. */
70 rebuild_jump_labels_1 (rtx_insn
*f
, bool count_forced
)
72 timevar_push (TV_REBUILD_JUMP
);
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. */
84 FOR_EACH_VEC_SAFE_ELT (forced_labels
, i
, insn
)
88 timevar_pop (TV_REBUILD_JUMP
);
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
96 rebuild_jump_labels (rtx_insn
*f
)
98 rebuild_jump_labels_1 (f
, true);
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. */
105 rebuild_jump_labels_chain (rtx_insn
*chain
)
107 rebuild_jump_labels_1 (chain
, false);
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.
115 This simple pass moves barriers and removes duplicates so that the
119 cleanup_barriers (void)
122 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
124 if (BARRIER_P (insn
))
126 rtx_insn
*prev
= prev_nonnote_nondebug_insn (insn
);
132 /* Make sure we do not split a call and its corresponding
133 CALL_ARG_LOCATION note. */
134 rtx_insn
*next
= NEXT_INSN (prev
);
137 && NOTE_KIND (next
) == NOTE_INSN_CALL_ARG_LOCATION
)
141 if (BARRIER_P (prev
))
143 else if (prev
!= PREV_INSN (insn
))
145 basic_block bb
= BLOCK_FOR_INSN (prev
);
146 rtx_insn
*end
= PREV_INSN (insn
);
147 reorder_insns_nobb (insn
, insn
, prev
);
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
161 prev
= NEXT_INSN (prev
);
162 if (prev
!= insn
&& BLOCK_FOR_INSN (prev
) == bb
)
163 BLOCK_FOR_INSN (prev
) = NULL
;
175 const pass_data pass_data_cleanup_barriers
=
178 "barriers", /* name */
179 OPTGROUP_NONE
, /* optinfo_flags */
181 0, /* properties_required */
182 0, /* properties_provided */
183 0, /* properties_destroyed */
184 0, /* todo_flags_start */
185 0, /* todo_flags_finish */
188 class pass_cleanup_barriers
: public rtl_opt_pass
191 pass_cleanup_barriers (gcc::context
*ctxt
)
192 : rtl_opt_pass (pass_data_cleanup_barriers
, ctxt
)
195 /* opt_pass methods: */
196 virtual unsigned int execute (function
*) { return cleanup_barriers (); }
198 }; // class pass_cleanup_barriers
203 make_pass_cleanup_barriers (gcc::context
*ctxt
)
205 return new pass_cleanup_barriers (ctxt
);
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. */
214 init_label_info (rtx_insn
*f
)
218 for (insn
= f
; insn
; insn
= NEXT_INSN (insn
))
221 LABEL_NUSES (insn
) = (LABEL_PRESERVE_P (insn
) != 0);
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
237 for (note
= REG_NOTES (insn
); note
; note
= next
)
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
);
248 /* A subroutine of mark_all_labels. Trivially propagate a simple label
249 load into a jump_insn that uses it. */
252 maybe_propagate_label_ref (rtx_insn
*jump_insn
, rtx_insn
*prev_nonjump_insn
)
254 rtx label_note
, pc
, pc_src
;
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
);
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. */
269 if (label_note
!= NULL
&& pc_src
!= NULL
)
271 rtx label_set
= single_set (prev_nonjump_insn
);
272 rtx label_dest
= label_set
!= NULL
? SET_DEST (label_set
) : NULL
;
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))))))
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. */
287 gcc_assert (XEXP (label_note
, 0) == label_ref_label (SET_SRC (label_set
)));
289 mark_jump_label_1 (label_set
, jump_insn
, false, true);
291 gcc_assert (JUMP_LABEL (jump_insn
) == XEXP (label_note
, 0));
296 /* Mark the label each jump jumps to.
297 Combine consecutive labels, and count uses of labels. */
300 mark_all_labels (rtx_insn
*f
)
304 if (current_ir_type () == IR_RTL_CFGLAYOUT
)
307 FOR_EACH_BB_FN (bb
, cfun
)
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
)
314 gcc_assert (! insn
->deleted ());
315 if (NONDEBUG_INSN_P (insn
))
316 mark_jump_label (PATTERN (insn
), insn
, 0);
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. */
322 for (insn
= BB_HEADER (bb
); insn
; insn
= NEXT_INSN (insn
))
323 if (JUMP_TABLE_DATA_P (insn
))
324 mark_jump_label (PATTERN (insn
), insn
, 0);
325 for (insn
= BB_FOOTER (bb
); insn
; insn
= NEXT_INSN (insn
))
326 if (JUMP_TABLE_DATA_P (insn
))
327 mark_jump_label (PATTERN (insn
), insn
, 0);
332 rtx_insn
*prev_nonjump_insn
= NULL
;
333 for (insn
= f
; insn
; insn
= NEXT_INSN (insn
))
335 if (insn
->deleted ())
337 else if (LABEL_P (insn
))
338 prev_nonjump_insn
= NULL
;
339 else if (JUMP_TABLE_DATA_P (insn
))
340 mark_jump_label (PATTERN (insn
), insn
, 0);
341 else if (NONDEBUG_INSN_P (insn
))
343 mark_jump_label (PATTERN (insn
), insn
, 0);
346 if (JUMP_LABEL (insn
) == NULL
&& prev_nonjump_insn
!= NULL
)
347 maybe_propagate_label_ref (insn
, prev_nonjump_insn
);
350 prev_nonjump_insn
= insn
;
356 /* Given a comparison (CODE ARG0 ARG1), inside an insn, INSN, return a code
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. */
363 reversed_comparison_code_parts (enum rtx_code code
, const_rtx arg0
,
364 const_rtx arg1
, const rtx_insn
*insn
)
368 /* If this is not actually a comparison, we can't reverse it. */
369 if (GET_RTX_CLASS (code
) != RTX_COMPARE
370 && GET_RTX_CLASS (code
) != RTX_COMM_COMPARE
)
373 mode
= GET_MODE (arg0
);
374 if (mode
== VOIDmode
)
375 mode
= GET_MODE (arg1
);
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. */
380 if (GET_MODE_CLASS (mode
) == MODE_CC
381 && REVERSIBLE_CC_MODE (mode
))
382 return REVERSE_CONDITION (code
, mode
);
384 /* Try a few special cases based on the comparison code. */
393 /* It is always safe to reverse EQ and NE, even for the floating
394 point. Similarly the unsigned comparisons are never used for
395 floating point so we can reverse them in the default way. */
396 return reverse_condition (code
);
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
);
408 /* We don't have safe way to reverse these yet. */
414 if (GET_MODE_CLASS (mode
) == MODE_CC
|| CC0_P (arg0
))
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
423 /* These CONST_CAST's are okay because prev_nonnote_insn just
424 returns its argument and we assign it to a const_rtx
426 for (rtx_insn
*prev
= prev_nonnote_insn (const_cast<rtx_insn
*> (insn
));
427 prev
!= 0 && !LABEL_P (prev
);
428 prev
= prev_nonnote_insn (prev
))
430 const_rtx set
= set_of (arg0
, prev
);
431 if (set
&& GET_CODE (set
) == SET
432 && rtx_equal_p (SET_DEST (set
), arg0
))
434 rtx src
= SET_SRC (set
);
436 if (GET_CODE (src
) == COMPARE
)
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));
445 /* We can get past reg-reg moves. This may be useful for model
446 of i387 comparisons that first move flag registers around. */
453 /* If register is clobbered in some ununderstandable way,
460 /* Test for an integer condition, or a floating-point comparison
461 in which NaNs can be ignored. */
462 if (CONST_INT_P (arg0
)
463 || (GET_MODE (arg0
) != VOIDmode
464 && GET_MODE_CLASS (mode
) != MODE_CC
465 && !HONOR_NANS (mode
)))
466 return reverse_condition (code
);
471 /* A wrapper around the previous function to take COMPARISON as rtx
472 expression. This simplifies many callers. */
474 reversed_comparison_code (const_rtx comparison
, const rtx_insn
*insn
)
476 if (!COMPARISON_P (comparison
))
478 return reversed_comparison_code_parts (GET_CODE (comparison
),
479 XEXP (comparison
, 0),
480 XEXP (comparison
, 1), insn
);
483 /* Return comparison with reversed code of EXP.
484 Return NULL_RTX in case we fail to do the reversal. */
486 reversed_comparison (const_rtx exp
, machine_mode mode
)
488 enum rtx_code reversed_code
= reversed_comparison_code (exp
, NULL
);
489 if (reversed_code
== UNKNOWN
)
492 return simplify_gen_relational (reversed_code
, mode
, VOIDmode
,
493 XEXP (exp
, 0), XEXP (exp
, 1));
497 /* Given an rtx-code for a comparison, return the code for the negated
498 comparison. If no such code exists, return UNKNOWN.
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
502 of the special treatment of non-signaling nans in comparisons.
503 Use reversed_comparison_code instead. */
506 reverse_condition (enum rtx_code code
)
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... */
553 reverse_condition_maybe_unordered (enum rtx_code code
)
591 /* Similar, but return the code when two operands of a comparison are swapped.
592 This IS safe for IEEE floating-point. */
595 swap_condition (enum rtx_code code
)
637 /* Given a comparison CODE, return the corresponding unsigned comparison.
638 If CODE is an equality comparison or already an unsigned comparison,
642 unsigned_condition (enum rtx_code code
)
668 /* Similarly, return the signed version of a comparison. */
671 signed_condition (enum rtx_code code
)
697 /* Return nonzero if CODE1 is more strict than CODE2, i.e., if the
698 truth of CODE1 implies the truth of CODE2. */
701 comparison_dominates_p (enum rtx_code code1
, enum rtx_code code2
)
703 /* UNKNOWN comparison codes can happen as a result of trying to revert
705 They can't match anything, so we have to reject them here. */
706 if (code1
== UNKNOWN
|| code2
== UNKNOWN
)
715 if (code2
== UNLE
|| code2
== UNGE
)
720 if (code2
== LE
|| code2
== LEU
|| code2
== GE
|| code2
== GEU
726 if (code2
== UNLE
|| code2
== NE
)
731 if (code2
== LE
|| code2
== NE
|| code2
== ORDERED
|| code2
== LTGT
)
736 if (code2
== UNGE
|| code2
== NE
)
741 if (code2
== GE
|| code2
== NE
|| code2
== ORDERED
|| code2
== LTGT
)
747 if (code2
== ORDERED
)
752 if (code2
== NE
|| code2
== ORDERED
)
757 if (code2
== LEU
|| code2
== NE
)
762 if (code2
== GEU
|| code2
== NE
)
767 if (code2
== NE
|| code2
== UNEQ
|| code2
== UNLE
|| code2
== UNLT
768 || code2
== UNGE
|| code2
== UNGT
)
779 /* Return 1 if INSN is an unconditional jump and nothing else. */
782 simplejump_p (const rtx_insn
*insn
)
784 return (JUMP_P (insn
)
785 && GET_CODE (PATTERN (insn
)) == SET
786 && GET_CODE (SET_DEST (PATTERN (insn
))) == PC
787 && GET_CODE (SET_SRC (PATTERN (insn
))) == LABEL_REF
);
790 /* Return nonzero if INSN is a (possibly) conditional jump
793 Use of this function is deprecated, since we need to support combined
794 branch and compare insns. Use any_condjump_p instead whenever possible. */
797 condjump_p (const rtx_insn
*insn
)
799 const_rtx x
= PATTERN (insn
);
801 if (GET_CODE (x
) != SET
802 || GET_CODE (SET_DEST (x
)) != PC
)
806 if (GET_CODE (x
) == LABEL_REF
)
809 return (GET_CODE (x
) == IF_THEN_ELSE
810 && ((GET_CODE (XEXP (x
, 2)) == PC
811 && (GET_CODE (XEXP (x
, 1)) == LABEL_REF
812 || ANY_RETURN_P (XEXP (x
, 1))))
813 || (GET_CODE (XEXP (x
, 1)) == PC
814 && (GET_CODE (XEXP (x
, 2)) == LABEL_REF
815 || ANY_RETURN_P (XEXP (x
, 2))))));
818 /* Return nonzero if INSN is a (possibly) conditional jump inside a
821 Use this function is deprecated, since we need to support combined
822 branch and compare insns. Use any_condjump_p instead whenever possible. */
825 condjump_in_parallel_p (const rtx_insn
*insn
)
827 const_rtx x
= PATTERN (insn
);
829 if (GET_CODE (x
) != PARALLEL
)
832 x
= XVECEXP (x
, 0, 0);
834 if (GET_CODE (x
) != SET
)
836 if (GET_CODE (SET_DEST (x
)) != PC
)
838 if (GET_CODE (SET_SRC (x
)) == LABEL_REF
)
840 if (GET_CODE (SET_SRC (x
)) != IF_THEN_ELSE
)
842 if (XEXP (SET_SRC (x
), 2) == pc_rtx
843 && (GET_CODE (XEXP (SET_SRC (x
), 1)) == LABEL_REF
844 || ANY_RETURN_P (XEXP (SET_SRC (x
), 1))))
846 if (XEXP (SET_SRC (x
), 1) == pc_rtx
847 && (GET_CODE (XEXP (SET_SRC (x
), 2)) == LABEL_REF
848 || ANY_RETURN_P (XEXP (SET_SRC (x
), 2))))
853 /* Return set of PC, otherwise NULL. */
856 pc_set (const rtx_insn
*insn
)
861 pat
= PATTERN (insn
);
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);
867 if (GET_CODE (pat
) == SET
&& GET_CODE (SET_DEST (pat
)) == PC
)
873 /* Return true when insn is an unconditional direct jump,
874 possibly bundled inside a PARALLEL. */
877 any_uncondjump_p (const rtx_insn
*insn
)
879 const_rtx x
= pc_set (insn
);
882 if (GET_CODE (SET_SRC (x
)) != LABEL_REF
)
884 if (find_reg_note (insn
, REG_NON_LOCAL_GOTO
, NULL_RTX
))
889 /* Return true when insn is a conditional jump. This function works for
890 instructions containing PC sets in PARALLELs. The instruction may have
891 various other effects so before removing the jump you must verify
894 Note that unlike condjump_p it returns false for unconditional jumps. */
897 any_condjump_p (const rtx_insn
*insn
)
899 const_rtx x
= pc_set (insn
);
904 if (GET_CODE (SET_SRC (x
)) != IF_THEN_ELSE
)
907 a
= GET_CODE (XEXP (SET_SRC (x
), 1));
908 b
= GET_CODE (XEXP (SET_SRC (x
), 2));
910 return ((b
== PC
&& (a
== LABEL_REF
|| a
== RETURN
|| a
== SIMPLE_RETURN
))
912 && (b
== LABEL_REF
|| b
== RETURN
|| b
== SIMPLE_RETURN
)));
915 /* Return the label of a conditional jump. */
918 condjump_label (const rtx_insn
*insn
)
920 rtx x
= pc_set (insn
);
925 if (GET_CODE (x
) == LABEL_REF
)
927 if (GET_CODE (x
) != IF_THEN_ELSE
)
929 if (XEXP (x
, 2) == pc_rtx
&& GET_CODE (XEXP (x
, 1)) == LABEL_REF
)
931 if (XEXP (x
, 1) == pc_rtx
&& GET_CODE (XEXP (x
, 2)) == LABEL_REF
)
936 /* Return TRUE if INSN is a return jump. */
939 returnjump_p (const rtx_insn
*insn
)
943 subrtx_iterator::array_type array
;
944 FOR_EACH_SUBRTX (iter
, array
, PATTERN (insn
), NONCONST
)
947 switch (GET_CODE (x
))
955 if (SET_IS_RETURN_P (x
))
967 /* Return true if INSN is a (possibly conditional) return insn. */
970 eh_returnjump_p (rtx_insn
*insn
)
974 subrtx_iterator::array_type array
;
975 FOR_EACH_SUBRTX (iter
, array
, PATTERN (insn
), NONCONST
)
976 if (GET_CODE (*iter
) == EH_RETURN
)
982 /* Return true if INSN is a jump that only transfers control and
986 onlyjump_p (const rtx_insn
*insn
)
993 set
= single_set (insn
);
996 if (GET_CODE (SET_DEST (set
)) != PC
)
998 if (side_effects_p (SET_SRC (set
)))
1004 /* Return true iff INSN is a jump and its JUMP_LABEL is a label, not
1005 NULL or a return. */
1007 jump_to_label_p (const rtx_insn
*insn
)
1009 return (JUMP_P (insn
)
1010 && JUMP_LABEL (insn
) != NULL
&& !ANY_RETURN_P (JUMP_LABEL (insn
)));
1013 /* Return nonzero if X is an RTX that only sets the condition codes
1014 and has no side effects. */
1017 only_sets_cc0_p (const_rtx x
)
1025 return sets_cc0_p (x
) == 1 && ! side_effects_p (x
);
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. */
1034 sets_cc0_p (const_rtx x
)
1042 if (GET_CODE (x
) == SET
&& SET_DEST (x
) == cc0_rtx
)
1044 if (GET_CODE (x
) == PARALLEL
)
1048 int other_things
= 0;
1049 for (i
= XVECLEN (x
, 0) - 1; i
>= 0; i
--)
1051 if (GET_CODE (XVECEXP (x
, 0, i
)) == SET
1052 && SET_DEST (XVECEXP (x
, 0, i
)) == cc0_rtx
)
1054 else if (GET_CODE (XVECEXP (x
, 0, i
)) == SET
)
1057 return ! sets_cc0
? 0 : other_things
? -1 : 1;
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.
1070 For returnjumps, the JUMP_LABEL will also be set as appropriate.
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
1076 that loop-optimization is done with. */
1079 mark_jump_label (rtx x
, rtx_insn
*insn
, int in_mem
)
1081 rtx asmop
= extract_asm_operands (x
);
1083 mark_jump_label_asm (asmop
, insn
);
1085 mark_jump_label_1 (x
, insn
, in_mem
!= 0,
1086 (insn
!= NULL
&& x
== PATTERN (insn
) && JUMP_P (insn
)));
1089 /* Worker function for mark_jump_label. IN_MEM is TRUE when X occurs
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
1096 mark_jump_label_1 (rtx x
, rtx_insn
*insn
, bool in_mem
, bool is_target
)
1098 RTX_CODE code
= GET_CODE (x
);
1115 gcc_assert (JUMP_LABEL (insn
) == NULL
|| JUMP_LABEL (insn
) == x
);
1116 JUMP_LABEL (insn
) = x
;
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
)),
1137 /* If this is a constant-pool reference, see if it is a label. */
1138 if (CONSTANT_POOL_ADDRESS_P (x
))
1139 mark_jump_label_1 (get_pool_constant (x
), insn
, in_mem
, is_target
);
1142 /* Handle operands in the condition of an if-then-else as for a
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);
1154 rtx_insn
*label
= label_ref_label (x
);
1156 /* Ignore remaining references to unreachable labels that
1157 have been deleted. */
1159 && NOTE_KIND (label
) == NOTE_INSN_DELETED_LABEL
)
1162 gcc_assert (LABEL_P (label
));
1164 /* Ignore references to labels of containing functions. */
1165 if (LABEL_REF_NONLOCAL_P (x
))
1168 set_label_ref_label (x
, label
);
1169 if (! insn
|| ! insn
->deleted ())
1170 ++LABEL_NUSES (label
);
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. */
1178 && (JUMP_LABEL (insn
) == NULL
|| JUMP_LABEL (insn
) == label
))
1179 JUMP_LABEL (insn
) = label
;
1183 = is_target
? REG_LABEL_TARGET
: REG_LABEL_OPERAND
;
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
))
1190 add_reg_note (insn
, kind
, label
);
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. */
1200 if (! insn
->deleted ())
1202 int eltnum
= code
== ADDR_DIFF_VEC
? 1 : 0;
1204 for (i
= 0; i
< XVECLEN (x
, eltnum
); i
++)
1205 mark_jump_label_1 (XVECEXP (x
, eltnum
, i
), NULL
, in_mem
,
1214 fmt
= GET_RTX_FORMAT (code
);
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. */
1219 for (i
= GET_RTX_LENGTH (code
) - 1; i
>= 0; i
--)
1222 mark_jump_label_1 (XEXP (x
, i
), insn
, in_mem
, is_target
);
1223 else if (fmt
[i
] == 'E')
1227 for (j
= XVECLEN (x
, i
) - 1; j
>= 0; j
--)
1228 mark_jump_label_1 (XVECEXP (x
, i
, j
), insn
, in_mem
,
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. */
1240 mark_jump_label_asm (rtx asmop
, rtx_insn
*insn
)
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);
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);
1251 /* Delete insn INSN from the chain of insns and update label ref counts
1252 and delete insns now unreachable.
1254 Returns the first insn after INSN that was not deleted.
1256 Usage of this instruction is deprecated. Use delete_insn instead and
1257 subsequent cfg_cleanup pass to delete unreachable code if needed. */
1260 delete_related_insns (rtx uncast_insn
)
1262 rtx_insn
*insn
= as_a
<rtx_insn
*> (uncast_insn
);
1263 int was_code_label
= (LABEL_P (insn
));
1265 rtx_insn
*next
= NEXT_INSN (insn
), *prev
= PREV_INSN (insn
);
1267 while (next
&& next
->deleted ())
1268 next
= NEXT_INSN (next
);
1270 /* This insn is already deleted => return first following nondeleted. */
1271 if (insn
->deleted ())
1276 /* If instruction is followed by a barrier,
1277 delete the barrier too. */
1279 if (next
!= 0 && BARRIER_P (next
))
1282 /* If this is a call, then we have to remove the var tracking note
1283 for the call arguments. */
1286 || (NONJUMP_INSN_P (insn
)
1287 && GET_CODE (PATTERN (insn
)) == SEQUENCE
1288 && CALL_P (XVECEXP (PATTERN (insn
), 0, 0))))
1292 for (p
= next
&& next
->deleted () ? NEXT_INSN (next
) : next
;
1295 if (NOTE_KIND (p
) == NOTE_INSN_CALL_ARG_LOCATION
)
1302 /* If deleting a jump, decrement the count of the label,
1303 and delete the label if it is now unused. */
1305 if (jump_to_label_p (insn
))
1307 rtx lab
= JUMP_LABEL (insn
);
1308 rtx_jump_table_data
*lab_next
;
1310 if (LABEL_NUSES (lab
) == 0)
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
);
1315 else if (tablejump_p (insn
, NULL
, &lab_next
))
1317 /* If we're deleting the tablejump, delete the dispatch table.
1318 We may not be able to kill the label immediately preceding
1319 just yet, as it might be referenced in code leading up to
1321 delete_related_insns (lab_next
);
1325 /* Likewise if we're deleting a dispatch table. */
1327 if (rtx_jump_table_data
*table
= dyn_cast
<rtx_jump_table_data
*> (insn
))
1329 rtvec labels
= table
->get_labels ();
1331 int len
= GET_NUM_ELEM (labels
);
1333 for (i
= 0; i
< len
; i
++)
1334 if (LABEL_NUSES (XEXP (RTVEC_ELT (labels
, i
), 0)) == 0)
1335 delete_related_insns (XEXP (RTVEC_ELT (labels
, i
), 0));
1336 while (next
&& next
->deleted ())
1337 next
= NEXT_INSN (next
);
1341 /* Likewise for any JUMP_P / INSN / CALL_INSN with a
1342 REG_LABEL_OPERAND or REG_LABEL_TARGET note. */
1344 for (note
= REG_NOTES (insn
); note
; note
= XEXP (note
, 1))
1345 if ((REG_NOTE_KIND (note
) == REG_LABEL_OPERAND
1346 || REG_NOTE_KIND (note
) == REG_LABEL_TARGET
)
1347 /* This could also be a NOTE_INSN_DELETED_LABEL note. */
1348 && LABEL_P (XEXP (note
, 0)))
1349 if (LABEL_NUSES (XEXP (note
, 0)) == 0)
1350 delete_related_insns (XEXP (note
, 0));
1352 while (prev
&& (prev
->deleted () || NOTE_P (prev
)))
1353 prev
= PREV_INSN (prev
);
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. */
1360 && NEXT_INSN (insn
) != 0
1361 && JUMP_TABLE_DATA_P (NEXT_INSN (insn
)))
1362 next
= delete_related_insns (NEXT_INSN (insn
));
1364 /* If INSN was a label, delete insns following it if now unreachable. */
1366 if (was_code_label
&& prev
&& BARRIER_P (prev
))
1371 code
= GET_CODE (next
);
1373 next
= NEXT_INSN (next
);
1374 /* Keep going past other deleted labels to delete what follows. */
1375 else if (code
== CODE_LABEL
&& next
->deleted ())
1376 next
= NEXT_INSN (next
);
1377 /* Keep the (use (insn))s created by dbr_schedule, which needs
1378 them in order to track liveness relative to a previous
1380 else if (INSN_P (next
)
1381 && GET_CODE (PATTERN (next
)) == USE
1382 && INSN_P (XEXP (PATTERN (next
), 0)))
1383 next
= NEXT_INSN (next
);
1384 else if (code
== BARRIER
|| INSN_P (next
))
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. */
1389 next
= delete_related_insns (next
);
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. */
1399 while (next
&& next
->deleted ())
1400 next
= NEXT_INSN (next
);
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. */
1410 delete_for_peephole (rtx_insn
*from
, rtx_insn
*to
)
1412 rtx_insn
*insn
= from
;
1416 rtx_insn
*next
= NEXT_INSN (insn
);
1417 rtx_insn
*prev
= PREV_INSN (insn
);
1421 insn
->set_deleted();
1423 /* Patch this insn out of the chain. */
1424 /* We don't do this all at once, because we
1425 must preserve all NOTEs. */
1427 SET_NEXT_INSN (prev
) = next
;
1430 SET_PREV_INSN (next
) = prev
;
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. */
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. */
1447 redirect_target (rtx x
)
1451 if (!ANY_RETURN_P (x
))
1452 return gen_rtx_LABEL_REF (Pmode
, x
);
1456 /* Throughout LOC, redirect OLABEL to NLABEL. Treat null OLABEL or
1457 NLABEL as a return. Accrue modifications into the change group. */
1460 redirect_exp_1 (rtx
*loc
, rtx olabel
, rtx nlabel
, rtx_insn
*insn
)
1463 RTX_CODE code
= GET_CODE (x
);
1467 if ((code
== LABEL_REF
&& label_ref_label (x
) == olabel
)
1470 x
= redirect_target (nlabel
);
1471 if (GET_CODE (x
) == LABEL_REF
&& loc
== &PATTERN (insn
))
1472 x
= gen_rtx_SET (pc_rtx
, x
);
1473 validate_change (insn
, loc
, x
, 1);
1477 if (code
== SET
&& SET_DEST (x
) == pc_rtx
1478 && ANY_RETURN_P (nlabel
)
1479 && GET_CODE (SET_SRC (x
)) == LABEL_REF
1480 && label_ref_label (SET_SRC (x
)) == olabel
)
1482 validate_change (insn
, loc
, nlabel
, 1);
1486 if (code
== IF_THEN_ELSE
)
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
);
1495 fmt
= GET_RTX_FORMAT (code
);
1496 for (i
= GET_RTX_LENGTH (code
) - 1; i
>= 0; i
--)
1499 redirect_exp_1 (&XEXP (x
, i
), olabel
, nlabel
, insn
);
1500 else if (fmt
[i
] == 'E')
1503 for (j
= 0; j
< XVECLEN (x
, i
); j
++)
1504 redirect_exp_1 (&XVECEXP (x
, i
, j
), olabel
, nlabel
, insn
);
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. */
1514 redirect_jump_1 (rtx_insn
*jump
, rtx nlabel
)
1516 int ochanges
= num_validated_changes ();
1519 gcc_assert (nlabel
!= NULL_RTX
);
1520 asmop
= extract_asm_operands (PATTERN (jump
));
1525 gcc_assert (ASM_OPERANDS_LABEL_LENGTH (asmop
) == 1);
1526 loc
= &ASM_OPERANDS_LABEL (asmop
, 0);
1528 else if (GET_CODE (PATTERN (jump
)) == PARALLEL
)
1529 loc
= &XVECEXP (PATTERN (jump
), 0, 0);
1531 loc
= &PATTERN (jump
);
1533 redirect_exp_1 (loc
, JUMP_LABEL (jump
), nlabel
, jump
);
1534 return num_validated_changes () > ochanges
;
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
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)
1545 The return value will be 1 if the change was made, 0 if it wasn't
1546 (this can only occur when trying to produce return insns). */
1549 redirect_jump (rtx_jump_insn
*jump
, rtx nlabel
, int delete_unused
)
1551 rtx olabel
= jump
->jump_label ();
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. */
1561 if (!epilogue_completed
)
1566 if (nlabel
== olabel
)
1569 if (! redirect_jump_1 (jump
, nlabel
) || ! apply_change_group ())
1572 redirect_jump_2 (jump
, olabel
, nlabel
, delete_unused
, 0);
1576 /* Fix up JUMP_LABEL and label ref counts after OLABEL has been replaced with
1578 If DELETE_UNUSED is positive, delete related insn to OLABEL if its ref
1579 count has dropped to zero. */
1581 redirect_jump_2 (rtx_jump_insn
*jump
, rtx olabel
, rtx nlabel
, int delete_unused
,
1586 gcc_assert (JUMP_LABEL (jump
) == olabel
);
1588 /* Negative DELETE_UNUSED used to be used to signalize behavior on
1589 moving FUNCTION_END note. Just sanity check that no user still worry
1591 gcc_assert (delete_unused
>= 0);
1592 JUMP_LABEL (jump
) = nlabel
;
1593 if (!ANY_RETURN_P (nlabel
))
1594 ++LABEL_NUSES (nlabel
);
1596 /* Update labels in any REG_EQUAL note. */
1597 if ((note
= find_reg_note (jump
, REG_EQUAL
, NULL_RTX
)) != NULL_RTX
)
1599 if (ANY_RETURN_P (nlabel
)
1600 || (invert
&& !invert_exp_1 (XEXP (note
, 0), jump
)))
1601 remove_note (jump
, note
);
1604 redirect_exp_1 (&XEXP (note
, 0), olabel
, nlabel
, jump
);
1605 confirm_change_group ();
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
))
1613 CROSSING_JUMP_P (jump
) = 0;
1615 if (!ANY_RETURN_P (olabel
)
1616 && --LABEL_NUSES (olabel
) == 0 && delete_unused
> 0
1617 /* Undefined labels will remain outside the insn stream. */
1618 && INSN_UID (olabel
))
1619 delete_related_insns (olabel
);
1621 invert_br_probabilities (jump
);
1624 /* Invert the jump condition X contained in jump insn INSN. Accrue the
1625 modifications into the change group. Return nonzero for success. */
1627 invert_exp_1 (rtx x
, rtx_insn
*insn
)
1629 RTX_CODE code
= GET_CODE (x
);
1631 if (code
== IF_THEN_ELSE
)
1633 rtx comp
= XEXP (x
, 0);
1635 enum rtx_code reversed_code
;
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. */
1642 reversed_code
= reversed_comparison_code (comp
, insn
);
1644 if (reversed_code
!= UNKNOWN
)
1646 validate_change (insn
, &XEXP (x
, 0),
1647 gen_rtx_fmt_ee (reversed_code
,
1648 GET_MODE (comp
), XEXP (comp
, 0),
1655 validate_change (insn
, &XEXP (x
, 1), XEXP (x
, 2), 1);
1656 validate_change (insn
, &XEXP (x
, 2), tem
, 1);
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. */
1669 invert_jump_1 (rtx_jump_insn
*jump
, rtx nlabel
)
1671 rtx x
= pc_set (jump
);
1675 ochanges
= num_validated_changes ();
1678 ok
= invert_exp_1 (SET_SRC (x
), jump
);
1681 if (num_validated_changes () == ochanges
)
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
);
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. */
1693 invert_jump (rtx_jump_insn
*jump
, rtx nlabel
, int delete_unused
)
1695 rtx olabel
= JUMP_LABEL (jump
);
1697 if (invert_jump_1 (jump
, nlabel
) && apply_change_group ())
1699 redirect_jump_2 (jump
, olabel
, nlabel
, delete_unused
, 1);
1707 /* Like rtx_equal_p except that it considers two REGs as equal
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
1713 rtx_renumbered_equal_p (const_rtx x
, const_rtx y
)
1716 const enum rtx_code code
= GET_CODE (x
);
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
)))))
1726 int reg_x
= -1, reg_y
= -1;
1727 poly_int64 byte_x
= 0, byte_y
= 0;
1728 struct subreg_info info
;
1730 if (GET_MODE (x
) != GET_MODE (y
))
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
);
1740 reg_x
= REGNO (SUBREG_REG (x
));
1741 byte_x
= SUBREG_BYTE (x
);
1743 if (reg_renumber
[reg_x
] >= 0)
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
)
1750 reg_x
= info
.offset
;
1757 if (reg_renumber
[reg_x
] >= 0)
1758 reg_x
= reg_renumber
[reg_x
];
1761 if (GET_CODE (y
) == SUBREG
)
1763 reg_y
= REGNO (SUBREG_REG (y
));
1764 byte_y
= SUBREG_BYTE (y
);
1766 if (reg_renumber
[reg_y
] >= 0)
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
)
1773 reg_y
= info
.offset
;
1780 if (reg_renumber
[reg_y
] >= 0)
1781 reg_y
= reg_renumber
[reg_y
];
1784 return reg_x
>= 0 && reg_x
== reg_y
&& known_eq (byte_x
, byte_y
);
1787 /* Now we have disposed of all the cases
1788 in which different rtx codes can match. */
1789 if (code
!= GET_CODE (y
))
1802 /* We can't assume nonlocal labels have their following insns yet. */
1803 if (LABEL_REF_NONLOCAL_P (x
) || LABEL_REF_NONLOCAL_P (y
))
1804 return label_ref_label (x
) == label_ref_label (y
);
1806 /* Two label-refs are equivalent if they point at labels
1807 in the same position in the instruction stream. */
1810 rtx_insn
*xi
= next_nonnote_nondebug_insn (label_ref_label (x
));
1811 rtx_insn
*yi
= next_nonnote_nondebug_insn (label_ref_label (y
));
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
);
1820 return XSTR (x
, 0) == XSTR (y
, 0);
1823 /* If we didn't match EQ equality above, they aren't the same. */
1830 /* (MULT:SI x y) and (MULT:HI x y) are NOT equivalent. */
1832 if (GET_MODE (x
) != GET_MODE (y
))
1835 /* MEMs referring to different address space are not equivalent. */
1836 if (code
== MEM
&& MEM_ADDR_SPACE (x
) != MEM_ADDR_SPACE (y
))
1839 /* For commutative operations, the RTX match if the operand match in any
1840 order. Also handle the simple binary and unary cases without a loop. */
1841 if (targetm
.commutative_p (x
, UNKNOWN
))
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))));
1846 else if (NON_COMMUTATIVE_P (x
))
1847 return (rtx_renumbered_equal_p (XEXP (x
, 0), XEXP (y
, 0))
1848 && rtx_renumbered_equal_p (XEXP (x
, 1), XEXP (y
, 1)));
1849 else if (UNARY_P (x
))
1850 return rtx_renumbered_equal_p (XEXP (x
, 0), XEXP (y
, 0));
1852 /* Compare the elements. If any pair of corresponding elements
1853 fail to match, return 0 for the whole things. */
1855 fmt
= GET_RTX_FORMAT (code
);
1856 for (i
= GET_RTX_LENGTH (code
) - 1; i
>= 0; i
--)
1862 if (XWINT (x
, i
) != XWINT (y
, i
))
1867 if (XINT (x
, i
) != XINT (y
, i
))
1869 if (((code
== ASM_OPERANDS
&& i
== 6)
1870 || (code
== ASM_INPUT
&& i
== 1)))
1877 if (maybe_ne (SUBREG_BYTE (x
), SUBREG_BYTE (y
)))
1882 if (XTREE (x
, i
) != XTREE (y
, i
))
1887 if (strcmp (XSTR (x
, i
), XSTR (y
, i
)))
1892 if (! rtx_renumbered_equal_p (XEXP (x
, i
), XEXP (y
, i
)))
1897 if (XEXP (x
, i
) != XEXP (y
, i
))
1904 if (XVECLEN (x
, i
) != XVECLEN (y
, i
))
1906 for (j
= XVECLEN (x
, i
) - 1; j
>= 0; j
--)
1907 if (!rtx_renumbered_equal_p (XVECEXP (x
, i
, j
), XVECEXP (y
, i
, j
)))
1918 /* If X is a hard register or equivalent to one or a subregister of one,
1919 return the hard register number. If X is a pseudo register that was not
1920 assigned a hard register, return the pseudo register number. Otherwise,
1921 return -1. Any rtx is valid for X. */
1924 true_regnum (const_rtx x
)
1928 if (REGNO (x
) >= FIRST_PSEUDO_REGISTER
1929 && (lra_in_progress
|| reg_renumber
[REGNO (x
)] >= 0))
1930 return reg_renumber
[REGNO (x
)];
1933 if (GET_CODE (x
) == SUBREG
)
1935 int base
= true_regnum (SUBREG_REG (x
));
1937 && base
< FIRST_PSEUDO_REGISTER
)
1939 struct subreg_info info
;
1941 subreg_get_info (lra_in_progress
1942 ? (unsigned) base
: REGNO (SUBREG_REG (x
)),
1943 GET_MODE (SUBREG_REG (x
)),
1944 SUBREG_BYTE (x
), GET_MODE (x
), &info
);
1946 if (info
.representable_p
)
1947 return base
+ info
.offset
;
1953 /* Return regno of the register REG and handle subregs too. */
1955 reg_or_subregno (const_rtx reg
)
1957 if (GET_CODE (reg
) == SUBREG
)
1958 reg
= SUBREG_REG (reg
);
1959 gcc_assert (REG_P (reg
));