118334Speter/* Optimize jump instructions, for GNU compiler. 290075Sobrien Copyright (C) 1987, 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997 3169689Skan 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 4169689Skan Free Software Foundation, Inc. 518334Speter 690075SobrienThis file is part of GCC. 718334Speter 890075SobrienGCC is free software; you can redistribute it and/or modify it under 990075Sobrienthe terms of the GNU General Public License as published by the Free 1090075SobrienSoftware Foundation; either version 2, or (at your option) any later 1190075Sobrienversion. 1218334Speter 1390075SobrienGCC is distributed in the hope that it will be useful, but WITHOUT ANY 1490075SobrienWARRANTY; without even the implied warranty of MERCHANTABILITY or 1590075SobrienFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1690075Sobrienfor more details. 1718334Speter 1818334SpeterYou should have received a copy of the GNU General Public License 1990075Sobrienalong with GCC; see the file COPYING. If not, write to the Free 20169689SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 21169689Skan02110-1301, USA. */ 2218334Speter 2390075Sobrien/* This is the pathetic reminder of old fame of the jump-optimization pass 24169689Skan of the compiler. Now it contains basically a set of utility functions to 2590075Sobrien operate with jumps. 2618334Speter 2718334Speter Each CODE_LABEL has a count of the times it is used 2818334Speter stored in the LABEL_NUSES internal field, and each JUMP_INSN 2918334Speter has one label that it refers to stored in the 3018334Speter JUMP_LABEL internal field. With this we can detect labels that 3118334Speter become unused because of the deletion of all the jumps that 3218334Speter formerly used them. The JUMP_LABEL info is sometimes looked 3318334Speter at by later passes. 3418334Speter 35169689Skan The subroutines redirect_jump and invert_jump are used 3618334Speter from other passes as well. */ 3718334Speter 3818334Speter#include "config.h" 3950397Sobrien#include "system.h" 40132718Skan#include "coretypes.h" 41132718Skan#include "tm.h" 4218334Speter#include "rtl.h" 4390075Sobrien#include "tm_p.h" 4418334Speter#include "flags.h" 4518334Speter#include "hard-reg-set.h" 4618334Speter#include "regs.h" 4718334Speter#include "insn-config.h" 4850397Sobrien#include "insn-attr.h" 4950397Sobrien#include "recog.h" 5090075Sobrien#include "function.h" 5118334Speter#include "expr.h" 5218334Speter#include "real.h" 5350397Sobrien#include "except.h" 54132718Skan#include "diagnostic.h" 5550397Sobrien#include "toplev.h" 5690075Sobrien#include "reload.h" 5790075Sobrien#include "predict.h" 58132718Skan#include "timevar.h" 59169689Skan#include "tree-pass.h" 60169689Skan#include "target.h" 6118334Speter 6218334Speter/* Optimize jump y; x: ... y: jumpif... x? 6318334Speter Don't know if it is worth bothering with. */ 6418334Speter/* Optimize two cases of conditional jump to conditional jump? 6518334Speter This can never delete any instruction or make anything dead, 6618334Speter or even change what is live at any point. 6718334Speter So perhaps let combiner do it. */ 6818334Speter 69132718Skanstatic void init_label_info (rtx); 70132718Skanstatic void mark_all_labels (rtx); 71132718Skanstatic void delete_computation (rtx); 72132718Skanstatic void redirect_exp_1 (rtx *, rtx, rtx, rtx); 73169689Skanstatic int invert_exp_1 (rtx, rtx); 74132718Skanstatic int returnjump_p_1 (rtx *, void *); 75132718Skanstatic void delete_prior_computation (rtx, rtx); 7690075Sobrien 7752284Sobrien/* Alternate entry into the jump optimizer. This entry point only rebuilds 7852284Sobrien the JUMP_LABEL field in jumping insns and REG_LABEL notes in non-jumping 7952284Sobrien instructions. */ 8052284Sobrienvoid 81132718Skanrebuild_jump_labels (rtx f) 8252284Sobrien{ 8390075Sobrien rtx insn; 8418334Speter 85132718Skan timevar_push (TV_REBUILD_JUMP); 86132718Skan init_label_info (f); 8790075Sobrien mark_all_labels (f); 8850397Sobrien 8990075Sobrien /* Keep track of labels used from static data; we don't track them 9090075Sobrien closely enough to delete them here, so make sure their reference 9190075Sobrien count doesn't drop to zero. */ 9218334Speter 9318334Speter for (insn = forced_labels; insn; insn = XEXP (insn, 1)) 94169689Skan if (LABEL_P (XEXP (insn, 0))) 9590075Sobrien LABEL_NUSES (XEXP (insn, 0))++; 96132718Skan timevar_pop (TV_REBUILD_JUMP); 9790075Sobrien} 9890075Sobrien 9990075Sobrien/* Some old code expects exactly one BARRIER as the NEXT_INSN of a 10090075Sobrien non-fallthru insn. This is not generally true, as multiple barriers 10190075Sobrien may have crept in, or the BARRIER may be separated from the last 10290075Sobrien real insn by one or more NOTEs. 10350397Sobrien 10490075Sobrien This simple pass moves barriers and removes duplicates so that the 10590075Sobrien old code is happy. 10690075Sobrien */ 107169689Skanunsigned int 108132718Skancleanup_barriers (void) 10990075Sobrien{ 11090075Sobrien rtx insn, next, prev; 11190075Sobrien for (insn = get_insns (); insn; insn = next) 11218334Speter { 11390075Sobrien next = NEXT_INSN (insn); 114169689Skan if (BARRIER_P (insn)) 11518334Speter { 11690075Sobrien prev = prev_nonnote_insn (insn); 117169689Skan if (BARRIER_P (prev)) 118169689Skan delete_insn (insn); 11990075Sobrien else if (prev != PREV_INSN (insn)) 12090075Sobrien reorder_insns (insn, insn, prev); 12118334Speter } 12218334Speter } 123169689Skan return 0; 12490075Sobrien} 125110611Skan 126169689Skanstruct tree_opt_pass pass_cleanup_barriers = 127110611Skan{ 128169689Skan "barriers", /* name */ 129169689Skan NULL, /* gate */ 130169689Skan cleanup_barriers, /* execute */ 131169689Skan NULL, /* sub */ 132169689Skan NULL, /* next */ 133169689Skan 0, /* static_pass_number */ 134169689Skan 0, /* tv_id */ 135169689Skan 0, /* properties_required */ 136169689Skan 0, /* properties_provided */ 137169689Skan 0, /* properties_destroyed */ 138169689Skan 0, /* todo_flags_start */ 139169689Skan TODO_dump_func, /* todo_flags_finish */ 140169689Skan 0 /* letter */ 141169689Skan}; 142110611Skan 143169689Skanunsigned int 144169689Skanpurge_line_number_notes (void) 14590075Sobrien{ 14690075Sobrien rtx last_note = 0; 14790075Sobrien rtx insn; 14818334Speter /* Delete extraneous line number notes. 14918334Speter Note that two consecutive notes for different lines are not really 15018334Speter extraneous. There should be some indication where that line belonged, 15118334Speter even if it became empty. */ 15218334Speter 153169689Skan for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) 154169689Skan if (NOTE_P (insn)) 15590075Sobrien { 15690075Sobrien if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_FUNCTION_BEG) 15790075Sobrien /* Any previous line note was for the prologue; gdb wants a new 15890075Sobrien note after the prologue even if it is for the same line. */ 15990075Sobrien last_note = NULL_RTX; 16090075Sobrien else if (NOTE_LINE_NUMBER (insn) >= 0) 16190075Sobrien { 16290075Sobrien /* Delete this note if it is identical to previous note. */ 16390075Sobrien if (last_note 164169689Skan#ifdef USE_MAPPED_LOCATION 165169689Skan && NOTE_SOURCE_LOCATION (insn) == NOTE_SOURCE_LOCATION (last_note) 166169689Skan#else 16790075Sobrien && NOTE_SOURCE_FILE (insn) == NOTE_SOURCE_FILE (last_note) 168169689Skan && NOTE_LINE_NUMBER (insn) == NOTE_LINE_NUMBER (last_note) 169169689Skan#endif 170169689Skan) 17190075Sobrien { 17290075Sobrien delete_related_insns (insn); 17390075Sobrien continue; 17490075Sobrien } 17518334Speter 17690075Sobrien last_note = insn; 17790075Sobrien } 17890075Sobrien } 179169689Skan return 0; 18052284Sobrien} 181169689Skan 182169689Skanstruct tree_opt_pass pass_purge_lineno_notes = 183169689Skan{ 184169689Skan "elnotes", /* name */ 185169689Skan NULL, /* gate */ 186169689Skan purge_line_number_notes, /* execute */ 187169689Skan NULL, /* sub */ 188169689Skan NULL, /* next */ 189169689Skan 0, /* static_pass_number */ 190169689Skan 0, /* tv_id */ 191169689Skan 0, /* properties_required */ 192169689Skan 0, /* properties_provided */ 193169689Skan 0, /* properties_destroyed */ 194169689Skan 0, /* todo_flags_start */ 195169689Skan TODO_dump_func, /* todo_flags_finish */ 196169689Skan 0 /* letter */ 197169689Skan}; 198169689Skan 19952284Sobrien 20052284Sobrien/* Initialize LABEL_NUSES and JUMP_LABEL fields. Delete any REG_LABEL 20152284Sobrien notes whose labels don't occur in the insn any more. Returns the 20252284Sobrien largest INSN_UID found. */ 203132718Skanstatic void 204132718Skaninit_label_info (rtx f) 20552284Sobrien{ 20652284Sobrien rtx insn; 20752284Sobrien 20852284Sobrien for (insn = f; insn; insn = NEXT_INSN (insn)) 209169689Skan if (LABEL_P (insn)) 210132718Skan LABEL_NUSES (insn) = (LABEL_PRESERVE_P (insn) != 0); 211169689Skan else if (JUMP_P (insn)) 212132718Skan JUMP_LABEL (insn) = 0; 213169689Skan else if (NONJUMP_INSN_P (insn) || CALL_P (insn)) 214132718Skan { 215132718Skan rtx note, next; 21652284Sobrien 217132718Skan for (note = REG_NOTES (insn); note; note = next) 218132718Skan { 219132718Skan next = XEXP (note, 1); 220132718Skan if (REG_NOTE_KIND (note) == REG_LABEL 221132718Skan && ! reg_mentioned_p (XEXP (note, 0), PATTERN (insn))) 222132718Skan remove_note (insn, note); 223132718Skan } 224132718Skan } 22552284Sobrien} 22652284Sobrien 22752284Sobrien/* Mark the label each jump jumps to. 22890075Sobrien Combine consecutive labels, and count uses of labels. */ 22952284Sobrien 23052284Sobrienstatic void 231132718Skanmark_all_labels (rtx f) 23252284Sobrien{ 23352284Sobrien rtx insn; 23452284Sobrien 23552284Sobrien for (insn = f; insn; insn = NEXT_INSN (insn)) 23690075Sobrien if (INSN_P (insn)) 23752284Sobrien { 23890075Sobrien mark_jump_label (PATTERN (insn), insn, 0); 239169689Skan if (! INSN_DELETED_P (insn) && JUMP_P (insn)) 24090075Sobrien { 24190075Sobrien /* When we know the LABEL_REF contained in a REG used in 24290075Sobrien an indirect jump, we'll have a REG_LABEL note so that 24390075Sobrien flow can tell where it's going. */ 24490075Sobrien if (JUMP_LABEL (insn) == 0) 24552284Sobrien { 24690075Sobrien rtx label_note = find_reg_note (insn, REG_LABEL, NULL_RTX); 24790075Sobrien if (label_note) 24890075Sobrien { 24990075Sobrien /* But a LABEL_REF around the REG_LABEL note, so 25090075Sobrien that we can canonicalize it. */ 251169689Skan rtx label_ref = gen_rtx_LABEL_REF (Pmode, 25290075Sobrien XEXP (label_note, 0)); 25390075Sobrien 25490075Sobrien mark_jump_label (label_ref, insn, 0); 25590075Sobrien XEXP (label_note, 0) = XEXP (label_ref, 0); 25690075Sobrien JUMP_LABEL (insn) = XEXP (label_note, 0); 25790075Sobrien } 25852284Sobrien } 25952284Sobrien } 26052284Sobrien } 26152284Sobrien} 26218334Speter 263169689Skan/* Move all block-beg, block-end and loop-beg notes between START and END out 264169689Skan before START. START and END may be such notes. Returns the values of the 265169689Skan new starting and ending insns, which may be different if the original ones 266169689Skan were such notes. Return true if there were only such notes and no real 267169689Skan instructions. */ 26818334Speter 26990075Sobrienbool 270132718Skansqueeze_notes (rtx* startp, rtx* endp) 27118334Speter{ 27290075Sobrien rtx start = *startp; 27390075Sobrien rtx end = *endp; 27490075Sobrien 27518334Speter rtx insn; 27618334Speter rtx next; 27790075Sobrien rtx last = NULL; 27890075Sobrien rtx past_end = NEXT_INSN (end); 27918334Speter 28090075Sobrien for (insn = start; insn != past_end; insn = next) 28118334Speter { 28218334Speter next = NEXT_INSN (insn); 283169689Skan if (NOTE_P (insn) 28418334Speter && (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END 285169689Skan || NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG)) 28618334Speter { 287169689Skan /* BLOCK_BEG or BLOCK_END notes only exist in the `final' pass. */ 288169689Skan gcc_assert (NOTE_LINE_NUMBER (insn) != NOTE_INSN_BLOCK_BEG 289169689Skan && NOTE_LINE_NUMBER (insn) != NOTE_INSN_BLOCK_END); 290169689Skan 29118334Speter if (insn == start) 29218334Speter start = next; 29318334Speter else 29418334Speter { 29518334Speter rtx prev = PREV_INSN (insn); 29618334Speter PREV_INSN (insn) = PREV_INSN (start); 29718334Speter NEXT_INSN (insn) = start; 29818334Speter NEXT_INSN (PREV_INSN (insn)) = insn; 29918334Speter PREV_INSN (NEXT_INSN (insn)) = insn; 30018334Speter NEXT_INSN (prev) = next; 30118334Speter PREV_INSN (next) = prev; 30218334Speter } 30318334Speter } 30490075Sobrien else 30590075Sobrien last = insn; 30618334Speter } 30718334Speter 30890075Sobrien /* There were no real instructions. */ 30990075Sobrien if (start == past_end) 31090075Sobrien return true; 31118334Speter 31290075Sobrien end = last; 31318334Speter 31490075Sobrien *startp = start; 31590075Sobrien *endp = end; 31690075Sobrien return false; 31718334Speter} 31818334Speter 31918334Speter/* Return the label before INSN, or put a new label there. */ 32018334Speter 32118334Speterrtx 322132718Skanget_label_before (rtx insn) 32318334Speter{ 32418334Speter rtx label; 32518334Speter 32618334Speter /* Find an existing label at this point 32718334Speter or make a new one if there is none. */ 32818334Speter label = prev_nonnote_insn (insn); 32918334Speter 330169689Skan if (label == 0 || !LABEL_P (label)) 33118334Speter { 33218334Speter rtx prev = PREV_INSN (insn); 33318334Speter 33418334Speter label = gen_label_rtx (); 33518334Speter emit_label_after (label, prev); 33618334Speter LABEL_NUSES (label) = 0; 33718334Speter } 33818334Speter return label; 33918334Speter} 34018334Speter 34118334Speter/* Return the label after INSN, or put a new label there. */ 34218334Speter 34318334Speterrtx 344132718Skanget_label_after (rtx insn) 34518334Speter{ 34618334Speter rtx label; 34718334Speter 34818334Speter /* Find an existing label at this point 34918334Speter or make a new one if there is none. */ 35018334Speter label = next_nonnote_insn (insn); 35118334Speter 352169689Skan if (label == 0 || !LABEL_P (label)) 35318334Speter { 35418334Speter label = gen_label_rtx (); 35518334Speter emit_label_after (label, insn); 35618334Speter LABEL_NUSES (label) = 0; 35718334Speter } 35818334Speter return label; 35918334Speter} 36018334Speter 36190075Sobrien/* Given a comparison (CODE ARG0 ARG1), inside an insn, INSN, return a code 36290075Sobrien of reversed comparison if it is possible to do so. Otherwise return UNKNOWN. 36390075Sobrien UNKNOWN may be returned in case we are having CC_MODE compare and we don't 36490075Sobrien know whether it's source is floating point or integer comparison. Machine 36590075Sobrien description should define REVERSIBLE_CC_MODE and REVERSE_CONDITION macros 36690075Sobrien to help this function avoid overhead in these cases. */ 36790075Sobrienenum rtx_code 368132718Skanreversed_comparison_code_parts (enum rtx_code code, rtx arg0, rtx arg1, rtx insn) 36918334Speter{ 37090075Sobrien enum machine_mode mode; 37118334Speter 37290075Sobrien /* If this is not actually a comparison, we can't reverse it. */ 373169689Skan if (GET_RTX_CLASS (code) != RTX_COMPARE 374169689Skan && GET_RTX_CLASS (code) != RTX_COMM_COMPARE) 37590075Sobrien return UNKNOWN; 37618334Speter 37790075Sobrien mode = GET_MODE (arg0); 37890075Sobrien if (mode == VOIDmode) 37990075Sobrien mode = GET_MODE (arg1); 38018334Speter 381169689Skan /* First see if machine description supplies us way to reverse the 382169689Skan comparison. Give it priority over everything else to allow 383169689Skan machine description to do tricks. */ 38490075Sobrien if (GET_MODE_CLASS (mode) == MODE_CC 38590075Sobrien && REVERSIBLE_CC_MODE (mode)) 38618334Speter { 38790075Sobrien#ifdef REVERSE_CONDITION 38890075Sobrien return REVERSE_CONDITION (code, mode); 38990075Sobrien#endif 39090075Sobrien return reverse_condition (code); 39118334Speter } 39218334Speter 39390075Sobrien /* Try a few special cases based on the comparison code. */ 39490075Sobrien switch (code) 39518334Speter { 39690075Sobrien case GEU: 39790075Sobrien case GTU: 39890075Sobrien case LEU: 39990075Sobrien case LTU: 40090075Sobrien case NE: 40190075Sobrien case EQ: 40290075Sobrien /* It is always safe to reverse EQ and NE, even for the floating 403132718Skan point. Similarly the unsigned comparisons are never used for 40490075Sobrien floating point so we can reverse them in the default way. */ 40590075Sobrien return reverse_condition (code); 40690075Sobrien case ORDERED: 40790075Sobrien case UNORDERED: 40890075Sobrien case LTGT: 40990075Sobrien case UNEQ: 41090075Sobrien /* In case we already see unordered comparison, we can be sure to 41190075Sobrien be dealing with floating point so we don't need any more tests. */ 41290075Sobrien return reverse_condition_maybe_unordered (code); 41390075Sobrien case UNLT: 41490075Sobrien case UNLE: 41590075Sobrien case UNGT: 41690075Sobrien case UNGE: 41790075Sobrien /* We don't have safe way to reverse these yet. */ 41890075Sobrien return UNKNOWN; 41990075Sobrien default: 42090075Sobrien break; 42118334Speter } 42218334Speter 423132718Skan if (GET_MODE_CLASS (mode) == MODE_CC || CC0_P (arg0)) 42418334Speter { 42590075Sobrien rtx prev; 42690075Sobrien /* Try to search for the comparison to determine the real mode. 42790075Sobrien This code is expensive, but with sane machine description it 42890075Sobrien will be never used, since REVERSIBLE_CC_MODE will return true 42990075Sobrien in all cases. */ 43090075Sobrien if (! insn) 43190075Sobrien return UNKNOWN; 43218334Speter 43390075Sobrien for (prev = prev_nonnote_insn (insn); 434169689Skan prev != 0 && !LABEL_P (prev); 43590075Sobrien prev = prev_nonnote_insn (prev)) 43690075Sobrien { 43790075Sobrien rtx set = set_of (arg0, prev); 43890075Sobrien if (set && GET_CODE (set) == SET 43990075Sobrien && rtx_equal_p (SET_DEST (set), arg0)) 44090075Sobrien { 44190075Sobrien rtx src = SET_SRC (set); 44252284Sobrien 44390075Sobrien if (GET_CODE (src) == COMPARE) 44490075Sobrien { 44590075Sobrien rtx comparison = src; 44690075Sobrien arg0 = XEXP (src, 0); 44790075Sobrien mode = GET_MODE (arg0); 44890075Sobrien if (mode == VOIDmode) 44990075Sobrien mode = GET_MODE (XEXP (comparison, 1)); 45090075Sobrien break; 45190075Sobrien } 45290075Sobrien /* We can get past reg-reg moves. This may be useful for model 45390075Sobrien of i387 comparisons that first move flag registers around. */ 45490075Sobrien if (REG_P (src)) 45590075Sobrien { 45690075Sobrien arg0 = src; 45790075Sobrien continue; 45890075Sobrien } 45990075Sobrien } 46090075Sobrien /* If register is clobbered in some ununderstandable way, 46190075Sobrien give up. */ 46290075Sobrien if (set) 46390075Sobrien return UNKNOWN; 46490075Sobrien } 46590075Sobrien } 46652284Sobrien 467117395Skan /* Test for an integer condition, or a floating-point comparison 468117395Skan in which NaNs can be ignored. */ 46990075Sobrien if (GET_CODE (arg0) == CONST_INT 47090075Sobrien || (GET_MODE (arg0) != VOIDmode 47190075Sobrien && GET_MODE_CLASS (mode) != MODE_CC 472117395Skan && !HONOR_NANS (mode))) 47390075Sobrien return reverse_condition (code); 47418334Speter 47590075Sobrien return UNKNOWN; 47690075Sobrien} 47718334Speter 478132718Skan/* A wrapper around the previous function to take COMPARISON as rtx 47990075Sobrien expression. This simplifies many callers. */ 48090075Sobrienenum rtx_code 481132718Skanreversed_comparison_code (rtx comparison, rtx insn) 48290075Sobrien{ 483169689Skan if (!COMPARISON_P (comparison)) 48490075Sobrien return UNKNOWN; 48590075Sobrien return reversed_comparison_code_parts (GET_CODE (comparison), 48690075Sobrien XEXP (comparison, 0), 48790075Sobrien XEXP (comparison, 1), insn); 48818334Speter} 489169689Skan 490169689Skan/* Return comparison with reversed code of EXP. 491169689Skan Return NULL_RTX in case we fail to do the reversal. */ 492169689Skanrtx 493169689Skanreversed_comparison (rtx exp, enum machine_mode mode) 494169689Skan{ 495169689Skan enum rtx_code reversed_code = reversed_comparison_code (exp, NULL_RTX); 496169689Skan if (reversed_code == UNKNOWN) 497169689Skan return NULL_RTX; 498169689Skan else 499169689Skan return simplify_gen_relational (reversed_code, mode, VOIDmode, 500169689Skan XEXP (exp, 0), XEXP (exp, 1)); 501169689Skan} 502169689Skan 50390075Sobrien 50490075Sobrien/* Given an rtx-code for a comparison, return the code for the negated 50590075Sobrien comparison. If no such code exists, return UNKNOWN. 50618334Speter 50790075Sobrien WATCH OUT! reverse_condition is not safe to use on a jump that might 50890075Sobrien be acting on the results of an IEEE floating point comparison, because 50990075Sobrien of the special treatment of non-signaling nans in comparisons. 51090075Sobrien Use reversed_comparison_code instead. */ 51118334Speter 51218334Speterenum rtx_code 513132718Skanreverse_condition (enum rtx_code code) 51418334Speter{ 51518334Speter switch (code) 51618334Speter { 51718334Speter case EQ: 51818334Speter return NE; 51918334Speter case NE: 52018334Speter return EQ; 52118334Speter case GT: 52218334Speter return LE; 52318334Speter case GE: 52418334Speter return LT; 52518334Speter case LT: 52618334Speter return GE; 52718334Speter case LE: 52818334Speter return GT; 52918334Speter case GTU: 53018334Speter return LEU; 53118334Speter case GEU: 53218334Speter return LTU; 53318334Speter case LTU: 53418334Speter return GEU; 53518334Speter case LEU: 53618334Speter return GTU; 53790075Sobrien case UNORDERED: 53890075Sobrien return ORDERED; 53990075Sobrien case ORDERED: 54090075Sobrien return UNORDERED; 54118334Speter 54290075Sobrien case UNLT: 54390075Sobrien case UNLE: 54490075Sobrien case UNGT: 54590075Sobrien case UNGE: 54690075Sobrien case UNEQ: 54790075Sobrien case LTGT: 54890075Sobrien return UNKNOWN; 54990075Sobrien 55018334Speter default: 551169689Skan gcc_unreachable (); 55218334Speter } 55318334Speter} 55418334Speter 55590075Sobrien/* Similar, but we're allowed to generate unordered comparisons, which 55690075Sobrien makes it safe for IEEE floating-point. Of course, we have to recognize 55790075Sobrien that the target will support them too... */ 55890075Sobrien 55990075Sobrienenum rtx_code 560132718Skanreverse_condition_maybe_unordered (enum rtx_code code) 56190075Sobrien{ 56290075Sobrien switch (code) 56390075Sobrien { 56490075Sobrien case EQ: 56590075Sobrien return NE; 56690075Sobrien case NE: 56790075Sobrien return EQ; 56890075Sobrien case GT: 56990075Sobrien return UNLE; 57090075Sobrien case GE: 57190075Sobrien return UNLT; 57290075Sobrien case LT: 57390075Sobrien return UNGE; 57490075Sobrien case LE: 57590075Sobrien return UNGT; 57690075Sobrien case LTGT: 57790075Sobrien return UNEQ; 57890075Sobrien case UNORDERED: 57990075Sobrien return ORDERED; 58090075Sobrien case ORDERED: 58190075Sobrien return UNORDERED; 58290075Sobrien case UNLT: 58390075Sobrien return GE; 58490075Sobrien case UNLE: 58590075Sobrien return GT; 58690075Sobrien case UNGT: 58790075Sobrien return LE; 58890075Sobrien case UNGE: 58990075Sobrien return LT; 59090075Sobrien case UNEQ: 59190075Sobrien return LTGT; 59290075Sobrien 59390075Sobrien default: 594169689Skan gcc_unreachable (); 59590075Sobrien } 59690075Sobrien} 59790075Sobrien 59818334Speter/* Similar, but return the code when two operands of a comparison are swapped. 59918334Speter This IS safe for IEEE floating-point. */ 60018334Speter 60118334Speterenum rtx_code 602132718Skanswap_condition (enum rtx_code code) 60318334Speter{ 60418334Speter switch (code) 60518334Speter { 60618334Speter case EQ: 60718334Speter case NE: 60890075Sobrien case UNORDERED: 60990075Sobrien case ORDERED: 61090075Sobrien case UNEQ: 61190075Sobrien case LTGT: 61218334Speter return code; 61318334Speter 61418334Speter case GT: 61518334Speter return LT; 61618334Speter case GE: 61718334Speter return LE; 61818334Speter case LT: 61918334Speter return GT; 62018334Speter case LE: 62118334Speter return GE; 62218334Speter case GTU: 62318334Speter return LTU; 62418334Speter case GEU: 62518334Speter return LEU; 62618334Speter case LTU: 62718334Speter return GTU; 62818334Speter case LEU: 62918334Speter return GEU; 63090075Sobrien case UNLT: 63190075Sobrien return UNGT; 63290075Sobrien case UNLE: 63390075Sobrien return UNGE; 63490075Sobrien case UNGT: 63590075Sobrien return UNLT; 63690075Sobrien case UNGE: 63790075Sobrien return UNLE; 63818334Speter 63918334Speter default: 640169689Skan gcc_unreachable (); 64118334Speter } 64218334Speter} 64318334Speter 64418334Speter/* Given a comparison CODE, return the corresponding unsigned comparison. 64518334Speter If CODE is an equality comparison or already an unsigned comparison, 64618334Speter CODE is returned. */ 64718334Speter 64818334Speterenum rtx_code 649132718Skanunsigned_condition (enum rtx_code code) 65018334Speter{ 65118334Speter switch (code) 65218334Speter { 65318334Speter case EQ: 65418334Speter case NE: 65518334Speter case GTU: 65618334Speter case GEU: 65718334Speter case LTU: 65818334Speter case LEU: 65918334Speter return code; 66018334Speter 66118334Speter case GT: 66218334Speter return GTU; 66318334Speter case GE: 66418334Speter return GEU; 66518334Speter case LT: 66618334Speter return LTU; 66718334Speter case LE: 66818334Speter return LEU; 66918334Speter 67018334Speter default: 671169689Skan gcc_unreachable (); 67218334Speter } 67318334Speter} 67418334Speter 67518334Speter/* Similarly, return the signed version of a comparison. */ 67618334Speter 67718334Speterenum rtx_code 678132718Skansigned_condition (enum rtx_code code) 67918334Speter{ 68018334Speter switch (code) 68118334Speter { 68218334Speter case EQ: 68318334Speter case NE: 68418334Speter case GT: 68518334Speter case GE: 68618334Speter case LT: 68718334Speter case LE: 68818334Speter return code; 68918334Speter 69018334Speter case GTU: 69118334Speter return GT; 69218334Speter case GEU: 69318334Speter return GE; 69418334Speter case LTU: 69518334Speter return LT; 69618334Speter case LEU: 69718334Speter return LE; 69818334Speter 69918334Speter default: 700169689Skan gcc_unreachable (); 70118334Speter } 70218334Speter} 70318334Speter 704117395Skan/* Return nonzero if CODE1 is more strict than CODE2, i.e., if the 70518334Speter truth of CODE1 implies the truth of CODE2. */ 70618334Speter 70718334Speterint 708132718Skancomparison_dominates_p (enum rtx_code code1, enum rtx_code code2) 70918334Speter{ 71090075Sobrien /* UNKNOWN comparison codes can happen as a result of trying to revert 71190075Sobrien comparison codes. 71290075Sobrien They can't match anything, so we have to reject them here. */ 71390075Sobrien if (code1 == UNKNOWN || code2 == UNKNOWN) 71490075Sobrien return 0; 71590075Sobrien 71618334Speter if (code1 == code2) 71718334Speter return 1; 71818334Speter 71918334Speter switch (code1) 72018334Speter { 72190075Sobrien case UNEQ: 72290075Sobrien if (code2 == UNLE || code2 == UNGE) 72390075Sobrien return 1; 72490075Sobrien break; 72590075Sobrien 72618334Speter case EQ: 72790075Sobrien if (code2 == LE || code2 == LEU || code2 == GE || code2 == GEU 72890075Sobrien || code2 == ORDERED) 72918334Speter return 1; 73018334Speter break; 73118334Speter 73290075Sobrien case UNLT: 73390075Sobrien if (code2 == UNLE || code2 == NE) 73490075Sobrien return 1; 73590075Sobrien break; 73690075Sobrien 73718334Speter case LT: 73890075Sobrien if (code2 == LE || code2 == NE || code2 == ORDERED || code2 == LTGT) 73918334Speter return 1; 74018334Speter break; 74118334Speter 74290075Sobrien case UNGT: 74390075Sobrien if (code2 == UNGE || code2 == NE) 74490075Sobrien return 1; 74590075Sobrien break; 74690075Sobrien 74718334Speter case GT: 74890075Sobrien if (code2 == GE || code2 == NE || code2 == ORDERED || code2 == LTGT) 74918334Speter return 1; 75018334Speter break; 75118334Speter 75290075Sobrien case GE: 75390075Sobrien case LE: 75490075Sobrien if (code2 == ORDERED) 75590075Sobrien return 1; 75690075Sobrien break; 75790075Sobrien 75890075Sobrien case LTGT: 75990075Sobrien if (code2 == NE || code2 == ORDERED) 76090075Sobrien return 1; 76190075Sobrien break; 76290075Sobrien 76318334Speter case LTU: 76418334Speter if (code2 == LEU || code2 == NE) 76518334Speter return 1; 76618334Speter break; 76718334Speter 76818334Speter case GTU: 76918334Speter if (code2 == GEU || code2 == NE) 77018334Speter return 1; 77118334Speter break; 77290075Sobrien 77390075Sobrien case UNORDERED: 77490075Sobrien if (code2 == NE || code2 == UNEQ || code2 == UNLE || code2 == UNLT 77590075Sobrien || code2 == UNGE || code2 == UNGT) 77690075Sobrien return 1; 77790075Sobrien break; 77890075Sobrien 77950397Sobrien default: 78050397Sobrien break; 78118334Speter } 78218334Speter 78318334Speter return 0; 78418334Speter} 78518334Speter 78618334Speter/* Return 1 if INSN is an unconditional jump and nothing else. */ 78718334Speter 78818334Speterint 789132718Skansimplejump_p (rtx insn) 79018334Speter{ 791169689Skan return (JUMP_P (insn) 79218334Speter && GET_CODE (PATTERN (insn)) == SET 79318334Speter && GET_CODE (SET_DEST (PATTERN (insn))) == PC 79418334Speter && GET_CODE (SET_SRC (PATTERN (insn))) == LABEL_REF); 79518334Speter} 796117395Skan 79718334Speter/* Return nonzero if INSN is a (possibly) conditional jump 79890075Sobrien and nothing more. 79918334Speter 800169689Skan Use of this function is deprecated, since we need to support combined 80190075Sobrien branch and compare insns. Use any_condjump_p instead whenever possible. */ 80290075Sobrien 80318334Speterint 804132718Skancondjump_p (rtx insn) 80518334Speter{ 80690075Sobrien rtx x = PATTERN (insn); 80790075Sobrien 80890075Sobrien if (GET_CODE (x) != SET 80990075Sobrien || GET_CODE (SET_DEST (x)) != PC) 81018334Speter return 0; 81190075Sobrien 81290075Sobrien x = SET_SRC (x); 81390075Sobrien if (GET_CODE (x) == LABEL_REF) 81418334Speter return 1; 81590075Sobrien else 81690075Sobrien return (GET_CODE (x) == IF_THEN_ELSE 81790075Sobrien && ((GET_CODE (XEXP (x, 2)) == PC 81890075Sobrien && (GET_CODE (XEXP (x, 1)) == LABEL_REF 81990075Sobrien || GET_CODE (XEXP (x, 1)) == RETURN)) 82090075Sobrien || (GET_CODE (XEXP (x, 1)) == PC 82190075Sobrien && (GET_CODE (XEXP (x, 2)) == LABEL_REF 82290075Sobrien || GET_CODE (XEXP (x, 2)) == RETURN)))); 82318334Speter} 82418334Speter 82590075Sobrien/* Return nonzero if INSN is a (possibly) conditional jump inside a 82690075Sobrien PARALLEL. 82718334Speter 82890075Sobrien Use this function is deprecated, since we need to support combined 82990075Sobrien branch and compare insns. Use any_condjump_p instead whenever possible. */ 83090075Sobrien 83118334Speterint 832132718Skancondjump_in_parallel_p (rtx insn) 83318334Speter{ 83490075Sobrien rtx x = PATTERN (insn); 83518334Speter 83618334Speter if (GET_CODE (x) != PARALLEL) 83718334Speter return 0; 83818334Speter else 83918334Speter x = XVECEXP (x, 0, 0); 84018334Speter 84118334Speter if (GET_CODE (x) != SET) 84218334Speter return 0; 84318334Speter if (GET_CODE (SET_DEST (x)) != PC) 84418334Speter return 0; 84518334Speter if (GET_CODE (SET_SRC (x)) == LABEL_REF) 84618334Speter return 1; 84718334Speter if (GET_CODE (SET_SRC (x)) != IF_THEN_ELSE) 84818334Speter return 0; 84918334Speter if (XEXP (SET_SRC (x), 2) == pc_rtx 85018334Speter && (GET_CODE (XEXP (SET_SRC (x), 1)) == LABEL_REF 85118334Speter || GET_CODE (XEXP (SET_SRC (x), 1)) == RETURN)) 85218334Speter return 1; 85318334Speter if (XEXP (SET_SRC (x), 1) == pc_rtx 85418334Speter && (GET_CODE (XEXP (SET_SRC (x), 2)) == LABEL_REF 85518334Speter || GET_CODE (XEXP (SET_SRC (x), 2)) == RETURN)) 85618334Speter return 1; 85718334Speter return 0; 85818334Speter} 85918334Speter 86090075Sobrien/* Return set of PC, otherwise NULL. */ 86190075Sobrien 86290075Sobrienrtx 863132718Skanpc_set (rtx insn) 86490075Sobrien{ 86590075Sobrien rtx pat; 866169689Skan if (!JUMP_P (insn)) 86790075Sobrien return NULL_RTX; 86890075Sobrien pat = PATTERN (insn); 86990075Sobrien 87090075Sobrien /* The set is allowed to appear either as the insn pattern or 87190075Sobrien the first set in a PARALLEL. */ 87290075Sobrien if (GET_CODE (pat) == PARALLEL) 87390075Sobrien pat = XVECEXP (pat, 0, 0); 87490075Sobrien if (GET_CODE (pat) == SET && GET_CODE (SET_DEST (pat)) == PC) 87590075Sobrien return pat; 87690075Sobrien 87790075Sobrien return NULL_RTX; 87890075Sobrien} 87990075Sobrien 88090075Sobrien/* Return true when insn is an unconditional direct jump, 88190075Sobrien possibly bundled inside a PARALLEL. */ 88290075Sobrien 88390075Sobrienint 884132718Skanany_uncondjump_p (rtx insn) 88590075Sobrien{ 88690075Sobrien rtx x = pc_set (insn); 88790075Sobrien if (!x) 88890075Sobrien return 0; 88990075Sobrien if (GET_CODE (SET_SRC (x)) != LABEL_REF) 89090075Sobrien return 0; 891169689Skan if (find_reg_note (insn, REG_NON_LOCAL_GOTO, NULL_RTX)) 892169689Skan return 0; 89390075Sobrien return 1; 89490075Sobrien} 89590075Sobrien 89690075Sobrien/* Return true when insn is a conditional jump. This function works for 89790075Sobrien instructions containing PC sets in PARALLELs. The instruction may have 89890075Sobrien various other effects so before removing the jump you must verify 89990075Sobrien onlyjump_p. 90090075Sobrien 90190075Sobrien Note that unlike condjump_p it returns false for unconditional jumps. */ 90290075Sobrien 90390075Sobrienint 904132718Skanany_condjump_p (rtx insn) 90590075Sobrien{ 90690075Sobrien rtx x = pc_set (insn); 90790075Sobrien enum rtx_code a, b; 90890075Sobrien 90990075Sobrien if (!x) 91090075Sobrien return 0; 91190075Sobrien if (GET_CODE (SET_SRC (x)) != IF_THEN_ELSE) 91290075Sobrien return 0; 91390075Sobrien 91490075Sobrien a = GET_CODE (XEXP (SET_SRC (x), 1)); 91590075Sobrien b = GET_CODE (XEXP (SET_SRC (x), 2)); 91690075Sobrien 91790075Sobrien return ((b == PC && (a == LABEL_REF || a == RETURN)) 91890075Sobrien || (a == PC && (b == LABEL_REF || b == RETURN))); 91990075Sobrien} 92090075Sobrien 92152284Sobrien/* Return the label of a conditional jump. */ 92252284Sobrien 92352284Sobrienrtx 924132718Skancondjump_label (rtx insn) 92552284Sobrien{ 92690075Sobrien rtx x = pc_set (insn); 92752284Sobrien 92890075Sobrien if (!x) 92952284Sobrien return NULL_RTX; 93052284Sobrien x = SET_SRC (x); 93152284Sobrien if (GET_CODE (x) == LABEL_REF) 93252284Sobrien return x; 93352284Sobrien if (GET_CODE (x) != IF_THEN_ELSE) 93452284Sobrien return NULL_RTX; 93552284Sobrien if (XEXP (x, 2) == pc_rtx && GET_CODE (XEXP (x, 1)) == LABEL_REF) 93652284Sobrien return XEXP (x, 1); 93752284Sobrien if (XEXP (x, 1) == pc_rtx && GET_CODE (XEXP (x, 2)) == LABEL_REF) 93852284Sobrien return XEXP (x, 2); 93952284Sobrien return NULL_RTX; 94052284Sobrien} 94152284Sobrien 94252284Sobrien/* Return true if INSN is a (possibly conditional) return insn. */ 94352284Sobrien 94452284Sobrienstatic int 945132718Skanreturnjump_p_1 (rtx *loc, void *data ATTRIBUTE_UNUSED) 94652284Sobrien{ 94752284Sobrien rtx x = *loc; 94890075Sobrien 94990075Sobrien return x && (GET_CODE (x) == RETURN 95090075Sobrien || (GET_CODE (x) == SET && SET_IS_RETURN_P (x))); 95152284Sobrien} 95252284Sobrien 95352284Sobrienint 954132718Skanreturnjump_p (rtx insn) 95552284Sobrien{ 956169689Skan if (!JUMP_P (insn)) 95790075Sobrien return 0; 95852284Sobrien return for_each_rtx (&PATTERN (insn), returnjump_p_1, NULL); 95952284Sobrien} 96052284Sobrien 96190075Sobrien/* Return true if INSN is a jump that only transfers control and 96290075Sobrien nothing more. */ 96390075Sobrien 96490075Sobrienint 965132718Skanonlyjump_p (rtx insn) 96690075Sobrien{ 96790075Sobrien rtx set; 96890075Sobrien 969169689Skan if (!JUMP_P (insn)) 97090075Sobrien return 0; 97190075Sobrien 97290075Sobrien set = single_set (insn); 97390075Sobrien if (set == NULL) 97490075Sobrien return 0; 97590075Sobrien if (GET_CODE (SET_DEST (set)) != PC) 97690075Sobrien return 0; 97790075Sobrien if (side_effects_p (SET_SRC (set))) 97890075Sobrien return 0; 97990075Sobrien 98090075Sobrien return 1; 98190075Sobrien} 98290075Sobrien 98352284Sobrien#ifdef HAVE_cc0 98452284Sobrien 985117395Skan/* Return nonzero if X is an RTX that only sets the condition codes 98690075Sobrien and has no side effects. */ 98790075Sobrien 98890075Sobrienint 989132718Skanonly_sets_cc0_p (rtx x) 99090075Sobrien{ 99190075Sobrien if (! x) 99290075Sobrien return 0; 99390075Sobrien 99490075Sobrien if (INSN_P (x)) 99590075Sobrien x = PATTERN (x); 99690075Sobrien 99790075Sobrien return sets_cc0_p (x) == 1 && ! side_effects_p (x); 99890075Sobrien} 99990075Sobrien 100018334Speter/* Return 1 if X is an RTX that does nothing but set the condition codes 100118334Speter and CLOBBER or USE registers. 100218334Speter Return -1 if X does explicitly set the condition codes, 100318334Speter but also does other things. */ 100418334Speter 100518334Speterint 1006132718Skansets_cc0_p (rtx x) 100718334Speter{ 100890075Sobrien if (! x) 100990075Sobrien return 0; 101090075Sobrien 101190075Sobrien if (INSN_P (x)) 101290075Sobrien x = PATTERN (x); 101390075Sobrien 101418334Speter if (GET_CODE (x) == SET && SET_DEST (x) == cc0_rtx) 101518334Speter return 1; 101618334Speter if (GET_CODE (x) == PARALLEL) 101718334Speter { 101818334Speter int i; 101918334Speter int sets_cc0 = 0; 102018334Speter int other_things = 0; 102118334Speter for (i = XVECLEN (x, 0) - 1; i >= 0; i--) 102218334Speter { 102318334Speter if (GET_CODE (XVECEXP (x, 0, i)) == SET 102418334Speter && SET_DEST (XVECEXP (x, 0, i)) == cc0_rtx) 102518334Speter sets_cc0 = 1; 102618334Speter else if (GET_CODE (XVECEXP (x, 0, i)) == SET) 102718334Speter other_things = 1; 102818334Speter } 102918334Speter return ! sets_cc0 ? 0 : other_things ? -1 : 1; 103018334Speter } 103118334Speter return 0; 103252284Sobrien} 103318334Speter#endif 103418334Speter 103518334Speter/* Follow any unconditional jump at LABEL; 103618334Speter return the ultimate label reached by any such chain of jumps. 1037169689Skan Return null if the chain ultimately leads to a return instruction. 103818334Speter If LABEL is not followed by a jump, return LABEL. 103918334Speter If the chain loops or we can't find end, return LABEL, 104018334Speter since that tells caller to avoid changing the insn. 104118334Speter 1042169689Skan If RELOAD_COMPLETED is 0, we do not chain across a USE or CLOBBER. */ 104318334Speter 104418334Speterrtx 1045132718Skanfollow_jumps (rtx label) 104618334Speter{ 104790075Sobrien rtx insn; 104890075Sobrien rtx next; 104990075Sobrien rtx value = label; 105090075Sobrien int depth; 105118334Speter 105218334Speter for (depth = 0; 105318334Speter (depth < 10 105418334Speter && (insn = next_active_insn (value)) != 0 1055169689Skan && JUMP_P (insn) 105690075Sobrien && ((JUMP_LABEL (insn) != 0 && any_uncondjump_p (insn) 105790075Sobrien && onlyjump_p (insn)) 105850397Sobrien || GET_CODE (PATTERN (insn)) == RETURN) 105918334Speter && (next = NEXT_INSN (insn)) 1060169689Skan && BARRIER_P (next)); 106118334Speter depth++) 106218334Speter { 106318334Speter rtx tem; 1064169689Skan if (!reload_completed && flag_test_coverage) 1065169689Skan { 1066169689Skan /* ??? Optional. Disables some optimizations, but makes 1067169689Skan gcov output more accurate with -O. */ 1068169689Skan for (tem = value; tem != insn; tem = NEXT_INSN (tem)) 1069169689Skan if (NOTE_P (tem) && NOTE_LINE_NUMBER (tem) > 0) 1070169689Skan return value; 1071169689Skan } 107218334Speter 107318334Speter /* If we have found a cycle, make the insn jump to itself. */ 107418334Speter if (JUMP_LABEL (insn) == label) 107518334Speter return label; 107618334Speter 107718334Speter tem = next_active_insn (JUMP_LABEL (insn)); 107818334Speter if (tem && (GET_CODE (PATTERN (tem)) == ADDR_VEC 107918334Speter || GET_CODE (PATTERN (tem)) == ADDR_DIFF_VEC)) 108018334Speter break; 108118334Speter 108218334Speter value = JUMP_LABEL (insn); 108318334Speter } 108418334Speter if (depth == 10) 108518334Speter return label; 108618334Speter return value; 108718334Speter} 108818334Speter 108918334Speter 109018334Speter/* Find all CODE_LABELs referred to in X, and increment their use counts. 109118334Speter If INSN is a JUMP_INSN and there is at least one CODE_LABEL referenced 109218334Speter in INSN, then store one of them in JUMP_LABEL (INSN). 109318334Speter If INSN is an INSN or a CALL_INSN and there is at least one CODE_LABEL 109418334Speter referenced in INSN, add a REG_LABEL note containing that label to INSN. 109518334Speter Also, when there are consecutive labels, canonicalize on the last of them. 109618334Speter 109718334Speter Note that two labels separated by a loop-beginning note 109818334Speter must be kept distinct if we have not yet done loop-optimization, 109918334Speter because the gap between them is where loop-optimize 110018334Speter will want to move invariant code to. CROSS_JUMP tells us 110190075Sobrien that loop-optimization is done with. */ 110218334Speter 110390075Sobrienvoid 1104132718Skanmark_jump_label (rtx x, rtx insn, int in_mem) 110518334Speter{ 110690075Sobrien RTX_CODE code = GET_CODE (x); 110790075Sobrien int i; 110890075Sobrien const char *fmt; 110918334Speter 111018334Speter switch (code) 111118334Speter { 111218334Speter case PC: 111318334Speter case CC0: 111418334Speter case REG: 111518334Speter case CONST_INT: 111618334Speter case CONST_DOUBLE: 111718334Speter case CLOBBER: 111818334Speter case CALL: 111918334Speter return; 112018334Speter 112118334Speter case MEM: 112290075Sobrien in_mem = 1; 112390075Sobrien break; 112490075Sobrien 112590075Sobrien case SYMBOL_REF: 112690075Sobrien if (!in_mem) 112790075Sobrien return; 112890075Sobrien 112918334Speter /* If this is a constant-pool reference, see if it is a label. */ 113090075Sobrien if (CONSTANT_POOL_ADDRESS_P (x)) 113190075Sobrien mark_jump_label (get_pool_constant (x), insn, in_mem); 113218334Speter break; 113318334Speter 113418334Speter case LABEL_REF: 113518334Speter { 113618334Speter rtx label = XEXP (x, 0); 113718334Speter 113890075Sobrien /* Ignore remaining references to unreachable labels that 113990075Sobrien have been deleted. */ 1140169689Skan if (NOTE_P (label) 114190075Sobrien && NOTE_LINE_NUMBER (label) == NOTE_INSN_DELETED_LABEL) 114290075Sobrien break; 114390075Sobrien 1144169689Skan gcc_assert (LABEL_P (label)); 114518334Speter 114618334Speter /* Ignore references to labels of containing functions. */ 114718334Speter if (LABEL_REF_NONLOCAL_P (x)) 114818334Speter break; 114918334Speter 115018334Speter XEXP (x, 0) = label; 115150397Sobrien if (! insn || ! INSN_DELETED_P (insn)) 115250397Sobrien ++LABEL_NUSES (label); 115318334Speter 115418334Speter if (insn) 115518334Speter { 1156169689Skan if (JUMP_P (insn)) 115718334Speter JUMP_LABEL (insn) = label; 115890075Sobrien else 115918334Speter { 116090075Sobrien /* Add a REG_LABEL note for LABEL unless there already 116190075Sobrien is one. All uses of a label, except for labels 116290075Sobrien that are the targets of jumps, must have a 116390075Sobrien REG_LABEL note. */ 116490075Sobrien if (! find_reg_note (insn, REG_LABEL, label)) 116590075Sobrien REG_NOTES (insn) = gen_rtx_INSN_LIST (REG_LABEL, label, 116690075Sobrien REG_NOTES (insn)); 116718334Speter } 116818334Speter } 116918334Speter return; 117018334Speter } 117118334Speter 117218334Speter /* Do walk the labels in a vector, but not the first operand of an 117318334Speter ADDR_DIFF_VEC. Don't set the JUMP_LABEL of a vector. */ 117418334Speter case ADDR_VEC: 117518334Speter case ADDR_DIFF_VEC: 117650397Sobrien if (! INSN_DELETED_P (insn)) 117750397Sobrien { 117850397Sobrien int eltnum = code == ADDR_DIFF_VEC ? 1 : 0; 117918334Speter 118050397Sobrien for (i = 0; i < XVECLEN (x, eltnum); i++) 118190075Sobrien mark_jump_label (XVECEXP (x, eltnum, i), NULL_RTX, in_mem); 118250397Sobrien } 118350397Sobrien return; 118490075Sobrien 118550397Sobrien default: 118650397Sobrien break; 118718334Speter } 118818334Speter 118918334Speter fmt = GET_RTX_FORMAT (code); 119018334Speter for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) 119118334Speter { 119218334Speter if (fmt[i] == 'e') 119390075Sobrien mark_jump_label (XEXP (x, i), insn, in_mem); 119418334Speter else if (fmt[i] == 'E') 119518334Speter { 119690075Sobrien int j; 119718334Speter for (j = 0; j < XVECLEN (x, i); j++) 119890075Sobrien mark_jump_label (XVECEXP (x, i, j), insn, in_mem); 119918334Speter } 120018334Speter } 120118334Speter} 120218334Speter 120318334Speter/* If all INSN does is set the pc, delete it, 120418334Speter and delete the insn that set the condition codes for it 120518334Speter if that's what the previous thing was. */ 120618334Speter 120718334Spetervoid 1208132718Skandelete_jump (rtx insn) 120918334Speter{ 121090075Sobrien rtx set = single_set (insn); 121118334Speter 121218334Speter if (set && GET_CODE (SET_DEST (set)) == PC) 121318334Speter delete_computation (insn); 121418334Speter} 121518334Speter 121690075Sobrien/* Recursively delete prior insns that compute the value (used only by INSN 121790075Sobrien which the caller is deleting) stored in the register mentioned by NOTE 121890075Sobrien which is a REG_DEAD note associated with INSN. */ 121990075Sobrien 122090075Sobrienstatic void 1221132718Skandelete_prior_computation (rtx note, rtx insn) 122290075Sobrien{ 122390075Sobrien rtx our_prev; 122490075Sobrien rtx reg = XEXP (note, 0); 122590075Sobrien 122690075Sobrien for (our_prev = prev_nonnote_insn (insn); 1227169689Skan our_prev && (NONJUMP_INSN_P (our_prev) 1228169689Skan || CALL_P (our_prev)); 122990075Sobrien our_prev = prev_nonnote_insn (our_prev)) 123090075Sobrien { 123190075Sobrien rtx pat = PATTERN (our_prev); 123290075Sobrien 123390075Sobrien /* If we reach a CALL which is not calling a const function 123490075Sobrien or the callee pops the arguments, then give up. */ 1235169689Skan if (CALL_P (our_prev) 123690075Sobrien && (! CONST_OR_PURE_CALL_P (our_prev) 123790075Sobrien || GET_CODE (pat) != SET || GET_CODE (SET_SRC (pat)) != CALL)) 123890075Sobrien break; 123990075Sobrien 124090075Sobrien /* If we reach a SEQUENCE, it is too complex to try to 1241117395Skan do anything with it, so give up. We can be run during 1242117395Skan and after reorg, so SEQUENCE rtl can legitimately show 1243117395Skan up here. */ 124490075Sobrien if (GET_CODE (pat) == SEQUENCE) 124590075Sobrien break; 124690075Sobrien 124790075Sobrien if (GET_CODE (pat) == USE 1248169689Skan && NONJUMP_INSN_P (XEXP (pat, 0))) 124990075Sobrien /* reorg creates USEs that look like this. We leave them 125090075Sobrien alone because reorg needs them for its own purposes. */ 125190075Sobrien break; 125290075Sobrien 125390075Sobrien if (reg_set_p (reg, pat)) 125490075Sobrien { 1255169689Skan if (side_effects_p (pat) && !CALL_P (our_prev)) 125690075Sobrien break; 125790075Sobrien 125890075Sobrien if (GET_CODE (pat) == PARALLEL) 125990075Sobrien { 126090075Sobrien /* If we find a SET of something else, we can't 126190075Sobrien delete the insn. */ 126290075Sobrien 126390075Sobrien int i; 126490075Sobrien 126590075Sobrien for (i = 0; i < XVECLEN (pat, 0); i++) 126690075Sobrien { 126790075Sobrien rtx part = XVECEXP (pat, 0, i); 126890075Sobrien 126990075Sobrien if (GET_CODE (part) == SET 127090075Sobrien && SET_DEST (part) != reg) 127190075Sobrien break; 127290075Sobrien } 127390075Sobrien 127490075Sobrien if (i == XVECLEN (pat, 0)) 127590075Sobrien delete_computation (our_prev); 127690075Sobrien } 127790075Sobrien else if (GET_CODE (pat) == SET 1278169689Skan && REG_P (SET_DEST (pat))) 127990075Sobrien { 128090075Sobrien int dest_regno = REGNO (SET_DEST (pat)); 128190075Sobrien int dest_endregno 128290075Sobrien = (dest_regno 128390075Sobrien + (dest_regno < FIRST_PSEUDO_REGISTER 1284169689Skan ? hard_regno_nregs[dest_regno] 1285169689Skan [GET_MODE (SET_DEST (pat))] : 1)); 128690075Sobrien int regno = REGNO (reg); 128790075Sobrien int endregno 128890075Sobrien = (regno 128990075Sobrien + (regno < FIRST_PSEUDO_REGISTER 1290169689Skan ? hard_regno_nregs[regno][GET_MODE (reg)] : 1)); 129190075Sobrien 129290075Sobrien if (dest_regno >= regno 129390075Sobrien && dest_endregno <= endregno) 129490075Sobrien delete_computation (our_prev); 129590075Sobrien 129690075Sobrien /* We may have a multi-word hard register and some, but not 129790075Sobrien all, of the words of the register are needed in subsequent 129890075Sobrien insns. Write REG_UNUSED notes for those parts that were not 129990075Sobrien needed. */ 130090075Sobrien else if (dest_regno <= regno 130190075Sobrien && dest_endregno >= endregno) 130290075Sobrien { 130390075Sobrien int i; 130490075Sobrien 130590075Sobrien REG_NOTES (our_prev) 130690075Sobrien = gen_rtx_EXPR_LIST (REG_UNUSED, reg, 130790075Sobrien REG_NOTES (our_prev)); 130890075Sobrien 130990075Sobrien for (i = dest_regno; i < dest_endregno; i++) 131090075Sobrien if (! find_regno_note (our_prev, REG_UNUSED, i)) 131190075Sobrien break; 131290075Sobrien 131390075Sobrien if (i == dest_endregno) 131490075Sobrien delete_computation (our_prev); 131590075Sobrien } 131690075Sobrien } 131790075Sobrien 131890075Sobrien break; 131990075Sobrien } 132090075Sobrien 132190075Sobrien /* If PAT references the register that dies here, it is an 132290075Sobrien additional use. Hence any prior SET isn't dead. However, this 132390075Sobrien insn becomes the new place for the REG_DEAD note. */ 132490075Sobrien if (reg_overlap_mentioned_p (reg, pat)) 132590075Sobrien { 132690075Sobrien XEXP (note, 1) = REG_NOTES (our_prev); 132790075Sobrien REG_NOTES (our_prev) = note; 132890075Sobrien break; 132990075Sobrien } 133090075Sobrien } 133190075Sobrien} 133290075Sobrien 133318334Speter/* Delete INSN and recursively delete insns that compute values used only 133418334Speter by INSN. This uses the REG_DEAD notes computed during flow analysis. 133518334Speter If we are running before flow.c, we need do nothing since flow.c will 133618334Speter delete dead code. We also can't know if the registers being used are 133718334Speter dead or not at this point. 133818334Speter 133918334Speter Otherwise, look at all our REG_DEAD notes. If a previous insn does 134018334Speter nothing other than set a register that dies in this insn, we can delete 134118334Speter that insn as well. 134218334Speter 134318334Speter On machines with CC0, if CC0 is used in this insn, we may be able to 134418334Speter delete the insn that set it. */ 134518334Speter 134618334Speterstatic void 1347132718Skandelete_computation (rtx insn) 134818334Speter{ 134918334Speter rtx note, next; 135018334Speter 135118334Speter#ifdef HAVE_cc0 135218334Speter if (reg_referenced_p (cc0_rtx, PATTERN (insn))) 135318334Speter { 135418334Speter rtx prev = prev_nonnote_insn (insn); 135518334Speter /* We assume that at this stage 135618334Speter CC's are always set explicitly 135718334Speter and always immediately before the jump that 135818334Speter will use them. So if the previous insn 135918334Speter exists to set the CC's, delete it 136018334Speter (unless it performs auto-increments, etc.). */ 1361169689Skan if (prev && NONJUMP_INSN_P (prev) 136218334Speter && sets_cc0_p (PATTERN (prev))) 136318334Speter { 136418334Speter if (sets_cc0_p (PATTERN (prev)) > 0 136590075Sobrien && ! side_effects_p (PATTERN (prev))) 136618334Speter delete_computation (prev); 136718334Speter else 136818334Speter /* Otherwise, show that cc0 won't be used. */ 136950397Sobrien REG_NOTES (prev) = gen_rtx_EXPR_LIST (REG_UNUSED, 137050397Sobrien cc0_rtx, REG_NOTES (prev)); 137118334Speter } 137218334Speter } 137318334Speter#endif 137418334Speter 137518334Speter for (note = REG_NOTES (insn); note; note = next) 137618334Speter { 137718334Speter next = XEXP (note, 1); 137818334Speter 137918334Speter if (REG_NOTE_KIND (note) != REG_DEAD 138018334Speter /* Verify that the REG_NOTE is legitimate. */ 1381169689Skan || !REG_P (XEXP (note, 0))) 138218334Speter continue; 138318334Speter 138490075Sobrien delete_prior_computation (note, insn); 138518334Speter } 138618334Speter 138790075Sobrien delete_related_insns (insn); 138818334Speter} 138918334Speter 139090075Sobrien/* Delete insn INSN from the chain of insns and update label ref counts 1391132718Skan and delete insns now unreachable. 139218334Speter 1393132718Skan Returns the first insn after INSN that was not deleted. 139418334Speter 139590075Sobrien Usage of this instruction is deprecated. Use delete_insn instead and 139690075Sobrien subsequent cfg_cleanup pass to delete unreachable code if needed. */ 139790075Sobrien 139818334Speterrtx 1399132718Skandelete_related_insns (rtx insn) 140018334Speter{ 1401169689Skan int was_code_label = (LABEL_P (insn)); 140290075Sobrien rtx note; 140390075Sobrien rtx next = NEXT_INSN (insn), prev = PREV_INSN (insn); 140418334Speter 140518334Speter while (next && INSN_DELETED_P (next)) 140618334Speter next = NEXT_INSN (next); 140718334Speter 140818334Speter /* This insn is already deleted => return first following nondeleted. */ 140918334Speter if (INSN_DELETED_P (insn)) 141018334Speter return next; 141118334Speter 141290075Sobrien delete_insn (insn); 141352284Sobrien 141418334Speter /* If instruction is followed by a barrier, 141518334Speter delete the barrier too. */ 141618334Speter 1417169689Skan if (next != 0 && BARRIER_P (next)) 141890075Sobrien delete_insn (next); 141918334Speter 142018334Speter /* If deleting a jump, decrement the count of the label, 142118334Speter and delete the label if it is now unused. */ 142218334Speter 1423169689Skan if (JUMP_P (insn) && JUMP_LABEL (insn)) 142452284Sobrien { 142552284Sobrien rtx lab = JUMP_LABEL (insn), lab_next; 142618334Speter 142790075Sobrien if (LABEL_NUSES (lab) == 0) 142852284Sobrien { 142952284Sobrien /* This can delete NEXT or PREV, 143052284Sobrien either directly if NEXT is JUMP_LABEL (INSN), 143152284Sobrien or indirectly through more levels of jumps. */ 143290075Sobrien delete_related_insns (lab); 143352284Sobrien 143452284Sobrien /* I feel a little doubtful about this loop, 143552284Sobrien but I see no clean and sure alternative way 143652284Sobrien to find the first insn after INSN that is not now deleted. 143752284Sobrien I hope this works. */ 143852284Sobrien while (next && INSN_DELETED_P (next)) 143952284Sobrien next = NEXT_INSN (next); 144052284Sobrien return next; 144152284Sobrien } 1442132718Skan else if (tablejump_p (insn, NULL, &lab_next)) 144352284Sobrien { 144452284Sobrien /* If we're deleting the tablejump, delete the dispatch table. 144590075Sobrien We may not be able to kill the label immediately preceding 144652284Sobrien just yet, as it might be referenced in code leading up to 144752284Sobrien the tablejump. */ 144890075Sobrien delete_related_insns (lab_next); 144952284Sobrien } 145052284Sobrien } 145152284Sobrien 145218334Speter /* Likewise if we're deleting a dispatch table. */ 145318334Speter 1454169689Skan if (JUMP_P (insn) 145518334Speter && (GET_CODE (PATTERN (insn)) == ADDR_VEC 145618334Speter || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)) 145718334Speter { 145818334Speter rtx pat = PATTERN (insn); 145918334Speter int i, diff_vec_p = GET_CODE (pat) == ADDR_DIFF_VEC; 146018334Speter int len = XVECLEN (pat, diff_vec_p); 146118334Speter 146218334Speter for (i = 0; i < len; i++) 146390075Sobrien if (LABEL_NUSES (XEXP (XVECEXP (pat, diff_vec_p, i), 0)) == 0) 146490075Sobrien delete_related_insns (XEXP (XVECEXP (pat, diff_vec_p, i), 0)); 146518334Speter while (next && INSN_DELETED_P (next)) 146618334Speter next = NEXT_INSN (next); 146718334Speter return next; 146818334Speter } 146918334Speter 147090075Sobrien /* Likewise for an ordinary INSN / CALL_INSN with a REG_LABEL note. */ 1471169689Skan if (NONJUMP_INSN_P (insn) || CALL_P (insn)) 147290075Sobrien for (note = REG_NOTES (insn); note; note = XEXP (note, 1)) 147390075Sobrien if (REG_NOTE_KIND (note) == REG_LABEL 147490075Sobrien /* This could also be a NOTE_INSN_DELETED_LABEL note. */ 1475169689Skan && LABEL_P (XEXP (note, 0))) 147690075Sobrien if (LABEL_NUSES (XEXP (note, 0)) == 0) 147790075Sobrien delete_related_insns (XEXP (note, 0)); 147890075Sobrien 1479169689Skan while (prev && (INSN_DELETED_P (prev) || NOTE_P (prev))) 148018334Speter prev = PREV_INSN (prev); 148118334Speter 148218334Speter /* If INSN was a label and a dispatch table follows it, 148318334Speter delete the dispatch table. The tablejump must have gone already. 148418334Speter It isn't useful to fall through into a table. */ 148518334Speter 148618334Speter if (was_code_label 148718334Speter && NEXT_INSN (insn) != 0 1488169689Skan && JUMP_P (NEXT_INSN (insn)) 148918334Speter && (GET_CODE (PATTERN (NEXT_INSN (insn))) == ADDR_VEC 149018334Speter || GET_CODE (PATTERN (NEXT_INSN (insn))) == ADDR_DIFF_VEC)) 149190075Sobrien next = delete_related_insns (NEXT_INSN (insn)); 149218334Speter 149318334Speter /* If INSN was a label, delete insns following it if now unreachable. */ 149418334Speter 1495169689Skan if (was_code_label && prev && BARRIER_P (prev)) 149618334Speter { 1497169689Skan enum rtx_code code; 1498169689Skan while (next) 149918334Speter { 1500169689Skan code = GET_CODE (next); 150118334Speter if (code == NOTE 150218334Speter && NOTE_LINE_NUMBER (next) != NOTE_INSN_FUNCTION_END) 150318334Speter next = NEXT_INSN (next); 150418334Speter /* Keep going past other deleted labels to delete what follows. */ 150518334Speter else if (code == CODE_LABEL && INSN_DELETED_P (next)) 150618334Speter next = NEXT_INSN (next); 1507169689Skan else if (code == BARRIER || INSN_P (next)) 150818334Speter /* Note: if this deletes a jump, it can cause more 150918334Speter deletion of unreachable code, after a different label. 151018334Speter As long as the value from this recursive call is correct, 151118334Speter this invocation functions correctly. */ 151290075Sobrien next = delete_related_insns (next); 1513169689Skan else 1514169689Skan break; 151518334Speter } 151618334Speter } 151718334Speter 151818334Speter return next; 151918334Speter} 152018334Speter 152118334Speter/* Delete a range of insns from FROM to TO, inclusive. 152218334Speter This is for the sake of peephole optimization, so assume 152318334Speter that whatever these insns do will still be done by a new 152418334Speter peephole insn that will replace them. */ 152518334Speter 152618334Spetervoid 1527132718Skandelete_for_peephole (rtx from, rtx to) 152818334Speter{ 152990075Sobrien rtx insn = from; 153018334Speter 153118334Speter while (1) 153218334Speter { 153390075Sobrien rtx next = NEXT_INSN (insn); 153490075Sobrien rtx prev = PREV_INSN (insn); 153518334Speter 1536169689Skan if (!NOTE_P (insn)) 153718334Speter { 153818334Speter INSN_DELETED_P (insn) = 1; 153918334Speter 154018334Speter /* Patch this insn out of the chain. */ 154118334Speter /* We don't do this all at once, because we 154218334Speter must preserve all NOTEs. */ 154318334Speter if (prev) 154418334Speter NEXT_INSN (prev) = next; 154518334Speter 154618334Speter if (next) 154718334Speter PREV_INSN (next) = prev; 154818334Speter } 154918334Speter 155018334Speter if (insn == to) 155118334Speter break; 155218334Speter insn = next; 155318334Speter } 155418334Speter 155518334Speter /* Note that if TO is an unconditional jump 155618334Speter we *do not* delete the BARRIER that follows, 155718334Speter since the peephole that replaces this sequence 155818334Speter is also an unconditional jump in that case. */ 155918334Speter} 156018334Speter 156190075Sobrien/* Throughout LOC, redirect OLABEL to NLABEL. Treat null OLABEL or 156290075Sobrien NLABEL as a return. Accrue modifications into the change group. */ 156318334Speter 156490075Sobrienstatic void 1565132718Skanredirect_exp_1 (rtx *loc, rtx olabel, rtx nlabel, rtx insn) 156618334Speter{ 156790075Sobrien rtx x = *loc; 156890075Sobrien RTX_CODE code = GET_CODE (x); 156990075Sobrien int i; 157090075Sobrien const char *fmt; 157118334Speter 157290075Sobrien if (code == LABEL_REF) 157390075Sobrien { 157490075Sobrien if (XEXP (x, 0) == olabel) 157590075Sobrien { 157690075Sobrien rtx n; 157790075Sobrien if (nlabel) 1578169689Skan n = gen_rtx_LABEL_REF (Pmode, nlabel); 157990075Sobrien else 158090075Sobrien n = gen_rtx_RETURN (VOIDmode); 158118334Speter 158290075Sobrien validate_change (insn, loc, n, 1); 158390075Sobrien return; 158490075Sobrien } 158590075Sobrien } 158690075Sobrien else if (code == RETURN && olabel == 0) 158718334Speter { 1588169689Skan if (nlabel) 1589169689Skan x = gen_rtx_LABEL_REF (Pmode, nlabel); 1590169689Skan else 1591169689Skan x = gen_rtx_RETURN (VOIDmode); 159290075Sobrien if (loc == &PATTERN (insn)) 159390075Sobrien x = gen_rtx_SET (VOIDmode, pc_rtx, x); 159490075Sobrien validate_change (insn, loc, x, 1); 159590075Sobrien return; 159690075Sobrien } 159718334Speter 159890075Sobrien if (code == SET && nlabel == 0 && SET_DEST (x) == pc_rtx 159990075Sobrien && GET_CODE (SET_SRC (x)) == LABEL_REF 160090075Sobrien && XEXP (SET_SRC (x), 0) == olabel) 160190075Sobrien { 160290075Sobrien validate_change (insn, loc, gen_rtx_RETURN (VOIDmode), 1); 160390075Sobrien return; 160418334Speter } 160518334Speter 160618334Speter fmt = GET_RTX_FORMAT (code); 160718334Speter for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) 160818334Speter { 160918334Speter if (fmt[i] == 'e') 161090075Sobrien redirect_exp_1 (&XEXP (x, i), olabel, nlabel, insn); 161190075Sobrien else if (fmt[i] == 'E') 161218334Speter { 161390075Sobrien int j; 161418334Speter for (j = 0; j < XVECLEN (x, i); j++) 161590075Sobrien redirect_exp_1 (&XVECEXP (x, i, j), olabel, nlabel, insn); 161618334Speter } 161718334Speter } 161890075Sobrien} 161918334Speter 162090075Sobrien/* Make JUMP go to NLABEL instead of where it jumps now. Accrue 162190075Sobrien the modifications into the change group. Return false if we did 162290075Sobrien not see how to do that. */ 162390075Sobrien 162490075Sobrienint 1625132718Skanredirect_jump_1 (rtx jump, rtx nlabel) 162690075Sobrien{ 162790075Sobrien int ochanges = num_validated_changes (); 162890075Sobrien rtx *loc; 162990075Sobrien 163090075Sobrien if (GET_CODE (PATTERN (jump)) == PARALLEL) 163190075Sobrien loc = &XVECEXP (PATTERN (jump), 0, 0); 163290075Sobrien else 163390075Sobrien loc = &PATTERN (jump); 163490075Sobrien 163590075Sobrien redirect_exp_1 (loc, JUMP_LABEL (jump), nlabel, jump); 163690075Sobrien return num_validated_changes () > ochanges; 163790075Sobrien} 163890075Sobrien 163990075Sobrien/* Make JUMP go to NLABEL instead of where it jumps now. If the old 164090075Sobrien jump target label is unused as a result, it and the code following 164190075Sobrien it may be deleted. 164290075Sobrien 164318334Speter If NLABEL is zero, we are to turn the jump into a (possibly conditional) 164418334Speter RETURN insn. 164518334Speter 164690075Sobrien The return value will be 1 if the change was made, 0 if it wasn't 164790075Sobrien (this can only occur for NLABEL == 0). */ 164818334Speter 164918334Speterint 1650132718Skanredirect_jump (rtx jump, rtx nlabel, int delete_unused) 165118334Speter{ 165290075Sobrien rtx olabel = JUMP_LABEL (jump); 165318334Speter 165418334Speter if (nlabel == olabel) 165518334Speter return 1; 165618334Speter 1657169689Skan if (! redirect_jump_1 (jump, nlabel) || ! apply_change_group ()) 165818334Speter return 0; 165918334Speter 1660169689Skan redirect_jump_2 (jump, olabel, nlabel, delete_unused, 0); 1661169689Skan return 1; 1662169689Skan} 1663169689Skan 1664169689Skan/* Fix up JUMP_LABEL and label ref counts after OLABEL has been replaced with 1665169689Skan NLABEL in JUMP. If DELETE_UNUSED is non-negative, copy a 1666169689Skan NOTE_INSN_FUNCTION_END found after OLABEL to the place after NLABEL. 1667169689Skan If DELETE_UNUSED is positive, delete related insn to OLABEL if its ref 1668169689Skan count has dropped to zero. */ 1669169689Skanvoid 1670169689Skanredirect_jump_2 (rtx jump, rtx olabel, rtx nlabel, int delete_unused, 1671169689Skan int invert) 1672169689Skan{ 1673169689Skan rtx note; 1674169689Skan 167518334Speter JUMP_LABEL (jump) = nlabel; 167618334Speter if (nlabel) 167718334Speter ++LABEL_NUSES (nlabel); 167818334Speter 1679132718Skan /* Update labels in any REG_EQUAL note. */ 1680132718Skan if ((note = find_reg_note (jump, REG_EQUAL, NULL_RTX)) != NULL_RTX) 1681132718Skan { 1682169689Skan if (!nlabel || (invert && !invert_exp_1 (XEXP (note, 0), jump))) 1683169689Skan remove_note (jump, note); 1684169689Skan else 1685132718Skan { 1686169689Skan redirect_exp_1 (&XEXP (note, 0), olabel, nlabel, jump); 1687169689Skan confirm_change_group (); 1688132718Skan } 1689132718Skan } 1690132718Skan 169190075Sobrien /* If we're eliding the jump over exception cleanups at the end of a 169290075Sobrien function, move the function end note so that -Wreturn-type works. */ 169390075Sobrien if (olabel && nlabel 169490075Sobrien && NEXT_INSN (olabel) 1695169689Skan && NOTE_P (NEXT_INSN (olabel)) 1696169689Skan && NOTE_LINE_NUMBER (NEXT_INSN (olabel)) == NOTE_INSN_FUNCTION_END 1697169689Skan && delete_unused >= 0) 169890075Sobrien emit_note_after (NOTE_INSN_FUNCTION_END, nlabel); 169918334Speter 1700169689Skan if (olabel && --LABEL_NUSES (olabel) == 0 && delete_unused > 0 170196263Sobrien /* Undefined labels will remain outside the insn stream. */ 170296263Sobrien && INSN_UID (olabel)) 170390075Sobrien delete_related_insns (olabel); 1704169689Skan if (invert) 1705169689Skan invert_br_probabilities (jump); 170618334Speter} 170718334Speter 1708169689Skan/* Invert the jump condition X contained in jump insn INSN. Accrue the 1709169689Skan modifications into the change group. Return nonzero for success. */ 1710169689Skanstatic int 1711169689Skaninvert_exp_1 (rtx x, rtx insn) 171218334Speter{ 1713169689Skan RTX_CODE code = GET_CODE (x); 171418334Speter 171590075Sobrien if (code == IF_THEN_ELSE) 171618334Speter { 171790075Sobrien rtx comp = XEXP (x, 0); 171890075Sobrien rtx tem; 171990075Sobrien enum rtx_code reversed_code; 172018334Speter 172190075Sobrien /* We can do this in two ways: The preferable way, which can only 172290075Sobrien be done if this is not an integer comparison, is to reverse 172390075Sobrien the comparison code. Otherwise, swap the THEN-part and ELSE-part 172490075Sobrien of the IF_THEN_ELSE. If we can't do either, fail. */ 172590075Sobrien 172690075Sobrien reversed_code = reversed_comparison_code (comp, insn); 172790075Sobrien 172890075Sobrien if (reversed_code != UNKNOWN) 172990075Sobrien { 173090075Sobrien validate_change (insn, &XEXP (x, 0), 173190075Sobrien gen_rtx_fmt_ee (reversed_code, 173290075Sobrien GET_MODE (comp), XEXP (comp, 0), 173390075Sobrien XEXP (comp, 1)), 173490075Sobrien 1); 1735169689Skan return 1; 173690075Sobrien } 173790075Sobrien 173890075Sobrien tem = XEXP (x, 1); 173990075Sobrien validate_change (insn, &XEXP (x, 1), XEXP (x, 2), 1); 174090075Sobrien validate_change (insn, &XEXP (x, 2), tem, 1); 1741169689Skan return 1; 174218334Speter } 174390075Sobrien else 174490075Sobrien return 0; 174518334Speter} 174618334Speter 174790075Sobrien/* Invert the condition of the jump JUMP, and make it jump to label 174890075Sobrien NLABEL instead of where it jumps now. Accrue changes into the 174990075Sobrien change group. Return false if we didn't see how to perform the 175090075Sobrien inversion and redirection. */ 175118334Speter 175290075Sobrienint 1753132718Skaninvert_jump_1 (rtx jump, rtx nlabel) 175418334Speter{ 1755169689Skan rtx x = pc_set (jump); 175690075Sobrien int ochanges; 1757169689Skan int ok; 175818334Speter 175990075Sobrien ochanges = num_validated_changes (); 1760169689Skan gcc_assert (x); 1761169689Skan ok = invert_exp_1 (SET_SRC (x), jump); 1762169689Skan gcc_assert (ok); 1763169689Skan 176490075Sobrien if (num_validated_changes () == ochanges) 176590075Sobrien return 0; 176618334Speter 1767169689Skan /* redirect_jump_1 will fail of nlabel == olabel, and the current use is 1768169689Skan in Pmode, so checking this is not merely an optimization. */ 1769169689Skan return nlabel == JUMP_LABEL (jump) || redirect_jump_1 (jump, nlabel); 177018334Speter} 177118334Speter 177290075Sobrien/* Invert the condition of the jump JUMP, and make it jump to label 177390075Sobrien NLABEL instead of where it jumps now. Return true if successful. */ 177418334Speter 177590075Sobrienint 1776132718Skaninvert_jump (rtx jump, rtx nlabel, int delete_unused) 177718334Speter{ 1778169689Skan rtx olabel = JUMP_LABEL (jump); 177918334Speter 1780169689Skan if (invert_jump_1 (jump, nlabel) && apply_change_group ()) 178118334Speter { 1782169689Skan redirect_jump_2 (jump, olabel, nlabel, delete_unused, 1); 178390075Sobrien return 1; 178418334Speter } 1785169689Skan cancel_changes (0); 178690075Sobrien return 0; 178718334Speter} 178890075Sobrien 178918334Speter 179018334Speter/* Like rtx_equal_p except that it considers two REGs as equal 179118334Speter if they renumber to the same value and considers two commutative 179218334Speter operations to be the same if the order of the operands has been 1793169689Skan reversed. */ 179418334Speter 179518334Speterint 1796132718Skanrtx_renumbered_equal_p (rtx x, rtx y) 179718334Speter{ 179890075Sobrien int i; 1799169689Skan enum rtx_code code = GET_CODE (x); 180090075Sobrien const char *fmt; 180190075Sobrien 180218334Speter if (x == y) 180318334Speter return 1; 180418334Speter 1805169689Skan if ((code == REG || (code == SUBREG && REG_P (SUBREG_REG (x)))) 1806169689Skan && (REG_P (y) || (GET_CODE (y) == SUBREG 1807169689Skan && REG_P (SUBREG_REG (y))))) 180818334Speter { 180918334Speter int reg_x = -1, reg_y = -1; 181090075Sobrien int byte_x = 0, byte_y = 0; 181118334Speter 181218334Speter if (GET_MODE (x) != GET_MODE (y)) 181318334Speter return 0; 181418334Speter 181518334Speter /* If we haven't done any renumbering, don't 181618334Speter make any assumptions. */ 181718334Speter if (reg_renumber == 0) 181818334Speter return rtx_equal_p (x, y); 181918334Speter 182018334Speter if (code == SUBREG) 182118334Speter { 182218334Speter reg_x = REGNO (SUBREG_REG (x)); 182390075Sobrien byte_x = SUBREG_BYTE (x); 182418334Speter 182518334Speter if (reg_renumber[reg_x] >= 0) 182618334Speter { 182790075Sobrien reg_x = subreg_regno_offset (reg_renumber[reg_x], 182890075Sobrien GET_MODE (SUBREG_REG (x)), 182990075Sobrien byte_x, 183090075Sobrien GET_MODE (x)); 183190075Sobrien byte_x = 0; 183218334Speter } 183318334Speter } 183418334Speter else 183518334Speter { 183618334Speter reg_x = REGNO (x); 183718334Speter if (reg_renumber[reg_x] >= 0) 183818334Speter reg_x = reg_renumber[reg_x]; 183918334Speter } 184018334Speter 184118334Speter if (GET_CODE (y) == SUBREG) 184218334Speter { 184318334Speter reg_y = REGNO (SUBREG_REG (y)); 184490075Sobrien byte_y = SUBREG_BYTE (y); 184518334Speter 184618334Speter if (reg_renumber[reg_y] >= 0) 184718334Speter { 184890075Sobrien reg_y = subreg_regno_offset (reg_renumber[reg_y], 184990075Sobrien GET_MODE (SUBREG_REG (y)), 185090075Sobrien byte_y, 185190075Sobrien GET_MODE (y)); 185290075Sobrien byte_y = 0; 185318334Speter } 185418334Speter } 185518334Speter else 185618334Speter { 185718334Speter reg_y = REGNO (y); 185818334Speter if (reg_renumber[reg_y] >= 0) 185918334Speter reg_y = reg_renumber[reg_y]; 186018334Speter } 186118334Speter 186290075Sobrien return reg_x >= 0 && reg_x == reg_y && byte_x == byte_y; 186318334Speter } 186418334Speter 186590075Sobrien /* Now we have disposed of all the cases 186618334Speter in which different rtx codes can match. */ 186718334Speter if (code != GET_CODE (y)) 186818334Speter return 0; 186918334Speter 187018334Speter switch (code) 187118334Speter { 187218334Speter case PC: 187318334Speter case CC0: 187418334Speter case ADDR_VEC: 187518334Speter case ADDR_DIFF_VEC: 1876132718Skan case CONST_INT: 1877169689Skan case CONST_DOUBLE: 187818334Speter return 0; 187918334Speter 188018334Speter case LABEL_REF: 188118334Speter /* We can't assume nonlocal labels have their following insns yet. */ 188218334Speter if (LABEL_REF_NONLOCAL_P (x) || LABEL_REF_NONLOCAL_P (y)) 188318334Speter return XEXP (x, 0) == XEXP (y, 0); 188418334Speter 188518334Speter /* Two label-refs are equivalent if they point at labels 188618334Speter in the same position in the instruction stream. */ 188718334Speter return (next_real_insn (XEXP (x, 0)) 188818334Speter == next_real_insn (XEXP (y, 0))); 188918334Speter 189018334Speter case SYMBOL_REF: 189118334Speter return XSTR (x, 0) == XSTR (y, 0); 189250397Sobrien 189350397Sobrien case CODE_LABEL: 189450397Sobrien /* If we didn't match EQ equality above, they aren't the same. */ 189550397Sobrien return 0; 189650397Sobrien 189750397Sobrien default: 189850397Sobrien break; 189918334Speter } 190018334Speter 190118334Speter /* (MULT:SI x y) and (MULT:HI x y) are NOT equivalent. */ 190218334Speter 190318334Speter if (GET_MODE (x) != GET_MODE (y)) 190418334Speter return 0; 190518334Speter 190618334Speter /* For commutative operations, the RTX match if the operand match in any 1907169689Skan order. Also handle the simple binary and unary cases without a loop. */ 1908169689Skan if (targetm.commutative_p (x, UNKNOWN)) 190918334Speter return ((rtx_renumbered_equal_p (XEXP (x, 0), XEXP (y, 0)) 191018334Speter && rtx_renumbered_equal_p (XEXP (x, 1), XEXP (y, 1))) 191118334Speter || (rtx_renumbered_equal_p (XEXP (x, 0), XEXP (y, 1)) 191218334Speter && rtx_renumbered_equal_p (XEXP (x, 1), XEXP (y, 0)))); 1913169689Skan else if (NON_COMMUTATIVE_P (x)) 191418334Speter return (rtx_renumbered_equal_p (XEXP (x, 0), XEXP (y, 0)) 191518334Speter && rtx_renumbered_equal_p (XEXP (x, 1), XEXP (y, 1))); 1916169689Skan else if (UNARY_P (x)) 191718334Speter return rtx_renumbered_equal_p (XEXP (x, 0), XEXP (y, 0)); 191818334Speter 191918334Speter /* Compare the elements. If any pair of corresponding elements 192018334Speter fail to match, return 0 for the whole things. */ 192118334Speter 192218334Speter fmt = GET_RTX_FORMAT (code); 192318334Speter for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) 192418334Speter { 192590075Sobrien int j; 192618334Speter switch (fmt[i]) 192718334Speter { 192818334Speter case 'w': 192918334Speter if (XWINT (x, i) != XWINT (y, i)) 193018334Speter return 0; 193118334Speter break; 193218334Speter 193318334Speter case 'i': 193418334Speter if (XINT (x, i) != XINT (y, i)) 193518334Speter return 0; 193618334Speter break; 193718334Speter 193890075Sobrien case 't': 193990075Sobrien if (XTREE (x, i) != XTREE (y, i)) 194090075Sobrien return 0; 194190075Sobrien break; 194290075Sobrien 194318334Speter case 's': 194418334Speter if (strcmp (XSTR (x, i), XSTR (y, i))) 194518334Speter return 0; 194618334Speter break; 194718334Speter 194818334Speter case 'e': 194918334Speter if (! rtx_renumbered_equal_p (XEXP (x, i), XEXP (y, i))) 195018334Speter return 0; 195118334Speter break; 195218334Speter 195318334Speter case 'u': 195418334Speter if (XEXP (x, i) != XEXP (y, i)) 195518334Speter return 0; 1956132718Skan /* Fall through. */ 195718334Speter case '0': 195818334Speter break; 195918334Speter 196018334Speter case 'E': 196118334Speter if (XVECLEN (x, i) != XVECLEN (y, i)) 196218334Speter return 0; 196318334Speter for (j = XVECLEN (x, i) - 1; j >= 0; j--) 196418334Speter if (!rtx_renumbered_equal_p (XVECEXP (x, i, j), XVECEXP (y, i, j))) 196518334Speter return 0; 196618334Speter break; 196718334Speter 196818334Speter default: 1969169689Skan gcc_unreachable (); 197018334Speter } 197118334Speter } 197218334Speter return 1; 197318334Speter} 197418334Speter 197518334Speter/* If X is a hard register or equivalent to one or a subregister of one, 197618334Speter return the hard register number. If X is a pseudo register that was not 197718334Speter assigned a hard register, return the pseudo register number. Otherwise, 197818334Speter return -1. Any rtx is valid for X. */ 197918334Speter 198018334Speterint 1981132718Skantrue_regnum (rtx x) 198218334Speter{ 1983169689Skan if (REG_P (x)) 198418334Speter { 198518334Speter if (REGNO (x) >= FIRST_PSEUDO_REGISTER && reg_renumber[REGNO (x)] >= 0) 198618334Speter return reg_renumber[REGNO (x)]; 198718334Speter return REGNO (x); 198818334Speter } 198918334Speter if (GET_CODE (x) == SUBREG) 199018334Speter { 199118334Speter int base = true_regnum (SUBREG_REG (x)); 1992169689Skan if (base >= 0 1993169689Skan && base < FIRST_PSEUDO_REGISTER 1994169689Skan && subreg_offset_representable_p (REGNO (SUBREG_REG (x)), 1995169689Skan GET_MODE (SUBREG_REG (x)), 1996169689Skan SUBREG_BYTE (x), GET_MODE (x))) 199790075Sobrien return base + subreg_regno_offset (REGNO (SUBREG_REG (x)), 199890075Sobrien GET_MODE (SUBREG_REG (x)), 199990075Sobrien SUBREG_BYTE (x), GET_MODE (x)); 200018334Speter } 200118334Speter return -1; 200218334Speter} 2003104752Skan 2004104752Skan/* Return regno of the register REG and handle subregs too. */ 2005104752Skanunsigned int 2006132718Skanreg_or_subregno (rtx reg) 2007104752Skan{ 2008104752Skan if (GET_CODE (reg) == SUBREG) 2009169689Skan reg = SUBREG_REG (reg); 2010169689Skan gcc_assert (REG_P (reg)); 2011169689Skan return REGNO (reg); 2012104752Skan} 2013