diff options
Diffstat (limited to 'gcc/combine.c')
-rw-r--r-- | gcc/combine.c | 264 |
1 files changed, 30 insertions, 234 deletions
diff --git a/gcc/combine.c b/gcc/combine.c index 62bf4ae..6476812 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -33,12 +33,6 @@ along with GCC; see the file COPYING3. If not see small number of quadruplets of insns A, B, C and D for which there's high likelihood of success. - LOG_LINKS does not have links for use of the CC0. They don't - need to, because the insn that sets the CC0 is always immediately - before the insn that tests it. So we always regard a branch - insn as having a logical link to the preceding insn. The same is true - for an insn explicitly using CC0. - We check (with modified_between_p) to avoid combining in such a way as to move a computation to a place where its value would be different. @@ -64,16 +58,7 @@ along with GCC; see the file COPYING3. If not see To simplify substitution, we combine only when the earlier insn(s) consist of only a single assignment. To simplify updating afterward, - we never combine when a subroutine call appears in the middle. - - Since we do not represent assignments to CC0 explicitly except when that - is all an insn does, there is no LOG_LINKS entry in an insn that uses - the condition code for the insn that set the condition code. - Fortunately, these two insns must be consecutive. - Therefore, every JUMP_INSN is taken to have an implicit logical link - to the preceding insn. This is not quite right, since non-jumps can - also use the condition code; but in practice such insns would not - combine anyway. */ + we never combine when a subroutine call appears in the middle. */ #include "config.h" #include "system.h" @@ -549,8 +534,8 @@ combine_split_insns (rtx pattern, rtx_insn *insn) } /* This is used by find_single_use to locate an rtx in LOC that - contains exactly one use of DEST, which is typically either a REG - or CC0. It returns a pointer to the innermost rtx expression + contains exactly one use of DEST, which is typically a REG. + It returns a pointer to the innermost rtx expression containing DEST. Appearances of DEST that are being used to totally replace it are not counted. */ @@ -574,12 +559,11 @@ find_single_use_1 (rtx dest, rtx *loc) return 0; case SET: - /* If the destination is anything other than CC0, PC, a REG or a SUBREG + /* If the destination is anything other than PC, a REG or a SUBREG of a REG that occupies all of the REG, the insn uses DEST if it is mentioned in the destination or the source. Otherwise, we need just check the source. */ - if (GET_CODE (SET_DEST (x)) != CC0 - && GET_CODE (SET_DEST (x)) != PC + if (GET_CODE (SET_DEST (x)) != PC && !REG_P (SET_DEST (x)) && ! (GET_CODE (SET_DEST (x)) == SUBREG && REG_P (SUBREG_REG (SET_DEST (x))) @@ -649,9 +633,6 @@ find_single_use_1 (rtx dest, rtx *loc) If PLOC is nonzero, *PLOC is set to the insn containing the single use. - If DEST is cc0_rtx, we look only at the next insn. In that case, we don't - care about REG_DEAD notes or LOG_LINKS. - Otherwise, we find the single use by finding an insn that has a LOG_LINKS pointing at INSN and has a REG_DEAD note for DEST. If DEST is only referenced once in that insn, we know that it must be the first @@ -665,19 +646,6 @@ find_single_use (rtx dest, rtx_insn *insn, rtx_insn **ploc) rtx *result; struct insn_link *link; - if (dest == cc0_rtx) - { - next = NEXT_INSN (insn); - if (next == 0 - || (!NONJUMP_INSN_P (next) && !JUMP_P (next))) - return 0; - - result = find_single_use_1 (dest, &PATTERN (next)); - if (result && ploc) - *ploc = next; - return result; - } - if (!REG_P (dest)) return 0; @@ -1128,9 +1096,7 @@ create_log_links (void) /* Walk the LOG_LINKS of insn B to see if we find a reference to A. Return true if we found a LOG_LINK that proves that A feeds B. This only works if there are no instructions between A and B which could have a link - depending on A, since in that case we would not record a link for B. - We also check the implicit dependency created by a cc0 setter/user - pair. */ + depending on A, since in that case we would not record a link for B. */ static bool insn_a_feeds_b (rtx_insn *a, rtx_insn *b) @@ -1139,8 +1105,6 @@ insn_a_feeds_b (rtx_insn *a, rtx_insn *b) FOR_EACH_LOG_LINK (links, b) if (links->insn == a) return true; - if (HAVE_cc0 && sets_cc0_p (a)) - return true; return false; } @@ -1153,7 +1117,6 @@ static int combine_instructions (rtx_insn *f, unsigned int nregs) { rtx_insn *insn, *next; - rtx_insn *prev; struct insn_link *links, *nextlinks; rtx_insn *first; basic_block last_bb; @@ -1330,69 +1293,6 @@ combine_instructions (rtx_insn *f, unsigned int nregs) } } - /* Try to combine a jump insn that uses CC0 - with a preceding insn that sets CC0, and maybe with its - logical predecessor as well. - This is how we make decrement-and-branch insns. - We need this special code because data flow connections - via CC0 do not get entered in LOG_LINKS. */ - - if (HAVE_cc0 - && JUMP_P (insn) - && (prev = prev_nonnote_insn (insn)) != 0 - && NONJUMP_INSN_P (prev) - && sets_cc0_p (PATTERN (prev))) - { - if ((next = try_combine (insn, prev, NULL, NULL, - &new_direct_jump_p, - last_combined_insn)) != 0) - goto retry; - - FOR_EACH_LOG_LINK (nextlinks, prev) - if ((next = try_combine (insn, prev, nextlinks->insn, - NULL, &new_direct_jump_p, - last_combined_insn)) != 0) - goto retry; - } - - /* Do the same for an insn that explicitly references CC0. */ - if (HAVE_cc0 && NONJUMP_INSN_P (insn) - && (prev = prev_nonnote_insn (insn)) != 0 - && NONJUMP_INSN_P (prev) - && sets_cc0_p (PATTERN (prev)) - && GET_CODE (PATTERN (insn)) == SET - && reg_mentioned_p (cc0_rtx, SET_SRC (PATTERN (insn)))) - { - if ((next = try_combine (insn, prev, NULL, NULL, - &new_direct_jump_p, - last_combined_insn)) != 0) - goto retry; - - FOR_EACH_LOG_LINK (nextlinks, prev) - if ((next = try_combine (insn, prev, nextlinks->insn, - NULL, &new_direct_jump_p, - last_combined_insn)) != 0) - goto retry; - } - - /* Finally, see if any of the insns that this insn links to - explicitly references CC0. If so, try this insn, that insn, - and its predecessor if it sets CC0. */ - if (HAVE_cc0) - { - FOR_EACH_LOG_LINK (links, insn) - if (NONJUMP_INSN_P (links->insn) - && GET_CODE (PATTERN (links->insn)) == SET - && reg_mentioned_p (cc0_rtx, SET_SRC (PATTERN (links->insn))) - && (prev = prev_nonnote_insn (links->insn)) != 0 - && NONJUMP_INSN_P (prev) - && sets_cc0_p (PATTERN (prev)) - && (next = try_combine (insn, links->insn, - prev, NULL, &new_direct_jump_p, - last_combined_insn)) != 0) - goto retry; - } - /* Try combining an insn with two different insns whose results it uses. */ if (max_combine >= 3) @@ -1853,7 +1753,7 @@ can_combine_p (rtx_insn *insn, rtx_insn *i3, rtx_insn *pred ATTRIBUTE_UNUSED, else if (next_active_insn (insn) != i3) all_adjacent = false; - /* Can combine only if previous insn is a SET of a REG, a SUBREG or CC0. + /* Can combine only if previous insn is a SET of a REG or a SUBREG, or a PARALLEL consisting of such a SET and CLOBBERs. If INSN has CLOBBER parallel parts, ignore them for our processing. @@ -2032,7 +1932,7 @@ can_combine_p (rtx_insn *insn, rtx_insn *i3, rtx_insn *pred ATTRIBUTE_UNUSED, || (DF_INSN_LUID (insn) < last_call_luid && ! CONSTANT_P (src))) return 0; - /* DEST must either be a REG or CC0. */ + /* DEST must be a REG. */ if (REG_P (dest)) { /* If register alignment is being enforced for multi-word items in all @@ -2059,7 +1959,7 @@ can_combine_p (rtx_insn *insn, rtx_insn *i3, rtx_insn *pred ATTRIBUTE_UNUSED, GET_MODE (src))))) return 0; } - else if (GET_CODE (dest) != CC0) + else return 0; @@ -2139,23 +2039,6 @@ can_combine_p (rtx_insn *insn, rtx_insn *i3, rtx_insn *pred ATTRIBUTE_UNUSED, || reg_overlap_mentioned_p (XEXP (link, 0), PATTERN (i3)))) return 0; - /* Don't combine an insn that follows a CC0-setting insn. - An insn that uses CC0 must not be separated from the one that sets it. - We do, however, allow I2 to follow a CC0-setting insn if that insn - is passed as I1; in that case it will be deleted also. - We also allow combining in this case if all the insns are adjacent - because that would leave the two CC0 insns adjacent as well. - It would be more logical to test whether CC0 occurs inside I1 or I2, - but that would be much slower, and this ought to be equivalent. */ - - if (HAVE_cc0) - { - p = prev_nonnote_insn (insn); - if (p && p != pred && NONJUMP_INSN_P (p) && sets_cc0_p (PATTERN (p)) - && ! all_adjacent) - return 0; - } - /* If we get here, we have passed all the tests and the combination is to be allowed. */ @@ -2988,7 +2871,7 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0, This undoes a previous combination and allows us to match a branch-and- decrement insn. */ - if (!HAVE_cc0 && i1 == 0 + if (i1 == 0 && is_parallel_of_n_reg_sets (PATTERN (i2), 2) && (GET_MODE_CLASS (GET_MODE (SET_DEST (XVECEXP (PATTERN (i2), 0, 0)))) == MODE_CC) @@ -3020,7 +2903,7 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0, /* If I2 is a PARALLEL of two SETs of REGs (and perhaps some CLOBBERs), make those two SETs separate I1 and I2 insns, and make an I0 that is the original I1. */ - if (!HAVE_cc0 && i0 == 0 + if (i0 == 0 && is_parallel_of_n_reg_sets (PATTERN (i2), 2) && can_split_parallel_of_n_reg_sets (i2, 2) && !reg_used_between_p (SET_DEST (XVECEXP (PATTERN (i2), 0, 0)), i2, i3) @@ -3228,7 +3111,7 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0, subst_insn = i3; - /* Many machines that don't use CC0 have insns that can both perform an + /* Many machines have insns that can both perform an arithmetic operation and set the condition code. These operations will be represented as a PARALLEL with the first element of the vector being a COMPARE of an arithmetic operation with the constant zero. @@ -3239,7 +3122,7 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0, needed, and make the PARALLEL by just replacing I2DEST in I3SRC with I2SRC. Later we will make the PARALLEL that contains I2. */ - if (!HAVE_cc0 && i1 == 0 && added_sets_2 && GET_CODE (PATTERN (i3)) == SET + if (i1 == 0 && added_sets_2 && GET_CODE (PATTERN (i3)) == SET && GET_CODE (SET_SRC (PATTERN (i3))) == COMPARE && CONST_INT_P (XEXP (SET_SRC (PATTERN (i3)), 1)) && rtx_equal_p (XEXP (SET_SRC (PATTERN (i3)), 0), i2dest)) @@ -3779,7 +3662,6 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0, are set between I2 and I3. */ if (insn_code_number < 0 && (split = find_split_point (&newpat, i3, false)) != 0 - && (!HAVE_cc0 || REG_P (i2dest)) /* We need I2DEST in the proper mode. If it is a hard register or the only use of a pseudo, we can change its mode. Make sure we don't change a hard register to have a mode that @@ -3966,7 +3848,7 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0, eliminate the copy. We cannot do this if the destination of the first assignment is a - condition code register or cc0. We eliminate this case by making sure + condition code register. We eliminate this case by making sure the SET_DEST and SET_SRC have the same mode. We cannot do this if the destination of the second assignment is @@ -4060,8 +3942,7 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0, rtx set0 = XVECEXP (newpat, 0, 0); rtx set1 = XVECEXP (newpat, 0, 1); - /* Normally, it doesn't matter which of the two is done first, - but the one that references cc0 can't be the second, and + /* Normally, it doesn't matter which of the two is done first, but one which uses any regs/memory set in between i2 and i3 can't be first. The PARALLEL might also have been pre-existing in i3, so we need to make sure that we won't wrongly hoist a SET to i2 @@ -4074,7 +3955,6 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0, && find_reg_note (i2, REG_DEAD, SUBREG_REG (SET_DEST (set1)))) && !modified_between_p (SET_DEST (set1), i2, i3) - && (!HAVE_cc0 || !reg_referenced_p (cc0_rtx, set0)) /* If I3 is a jump, ensure that set0 is a jump so that we do not create invalid RTL. */ && (!JUMP_P (i3) || SET_DEST (set0) == pc_rtx) @@ -4090,7 +3970,6 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0, && find_reg_note (i2, REG_DEAD, SUBREG_REG (SET_DEST (set0)))) && !modified_between_p (SET_DEST (set0), i2, i3) - && (!HAVE_cc0 || !reg_referenced_p (cc0_rtx, set1)) /* If I3 is a jump, ensure that set1 is a jump so that we do not create invalid RTL. */ && (!JUMP_P (i3) || SET_DEST (set1) == pc_rtx) @@ -4158,19 +4037,6 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0, } } - /* If I2 is the CC0 setter and I3 is the CC0 user then check whether - they are adjacent to each other or not. */ - if (HAVE_cc0) - { - rtx_insn *p = prev_nonnote_insn (i3); - if (p && p != i2 && NONJUMP_INSN_P (p) && newi2pat - && sets_cc0_p (newi2pat)) - { - undo_all (); - return 0; - } - } - /* Only allow this combination if insn_cost reports that the replacement instructions are cheaper than the originals. */ if (!combine_validate_cost (i0, i1, i2, i3, newpat, newi2pat, other_pat)) @@ -5061,19 +4927,6 @@ find_split_point (rtx *loc, rtx_insn *insn, bool set_src) break; case SET: - /* If SET_DEST is CC0 and SET_SRC is not an operand, a COMPARE, or a - ZERO_EXTRACT, the most likely reason why this doesn't match is that - we need to put the operand into a register. So split at that - point. */ - - if (SET_DEST (x) == cc0_rtx - && GET_CODE (SET_SRC (x)) != COMPARE - && GET_CODE (SET_SRC (x)) != ZERO_EXTRACT - && !OBJECT_P (SET_SRC (x)) - && ! (GET_CODE (SET_SRC (x)) == SUBREG - && OBJECT_P (SUBREG_REG (SET_SRC (x))))) - return &SET_SRC (x); - /* See if we can split SET_SRC as it stands. */ split = find_split_point (&SET_SRC (x), insn, true); if (split && split != &SET_SRC (x)) @@ -5485,9 +5338,7 @@ subst (rtx x, rtx from, rtx to, int in_dest, int in_cond, int unique_copy) { rtx dest = SET_DEST (XVECEXP (x, 0, i)); - if (!REG_P (dest) - && GET_CODE (dest) != CC0 - && GET_CODE (dest) != PC) + if (!REG_P (dest) && GET_CODE (dest) != PC) { new_rtx = subst (dest, from, to, 0, 0, unique_copy); @@ -5505,13 +5356,12 @@ subst (rtx x, rtx from, rtx to, int in_dest, int in_cond, int unique_copy) len = GET_RTX_LENGTH (code); fmt = GET_RTX_FORMAT (code); - /* We don't need to process a SET_DEST that is a register, CC0, - or PC, so set up to skip this common case. All other cases - where we want to suppress replacing something inside a - SET_SRC are handled via the IN_DEST operand. */ + /* We don't need to process a SET_DEST that is a register or PC, so + set up to skip this common case. All other cases where we want + to suppress replacing something inside a SET_SRC are handled via + the IN_DEST operand. */ if (code == SET && (REG_P (SET_DEST (x)) - || GET_CODE (SET_DEST (x)) == CC0 || GET_CODE (SET_DEST (x)) == PC)) fmt = "ie"; @@ -5581,22 +5431,17 @@ subst (rtx x, rtx from, rtx to, int in_dest, int in_cond, int unique_copy) from in the outside mode, and that may be invalid if it is an fp reg copied in integer mode. - We allow two exceptions to this: It is valid if + We allow an exception to this: It is valid if it is inside another SUBREG and the mode of that SUBREG and the mode of the inside of TO is - tieable and it is valid if X is a SET that copies - FROM to CC0. */ + tieable. */ if (GET_CODE (to) == SUBREG && !targetm.modes_tieable_p (GET_MODE (to), GET_MODE (SUBREG_REG (to))) && ! (code == SUBREG && (targetm.modes_tieable_p - (GET_MODE (x), GET_MODE (SUBREG_REG (to))))) - && (!HAVE_cc0 - || (! (code == SET - && i == 1 - && XEXP (x, 0) == cc0_rtx)))) + (GET_MODE (x), GET_MODE (SUBREG_REG (to)))))) return gen_rtx_CLOBBER (VOIDmode, const0_rtx); if (code == SUBREG @@ -6219,8 +6064,7 @@ combine_simplify_rtx (rtx x, machine_mode op0_mode, int in_dest, /* If the first operand is a condition code, we can't do anything with it. */ if (GET_CODE (XEXP (x, 0)) == COMPARE - || (GET_MODE_CLASS (GET_MODE (XEXP (x, 0))) != MODE_CC - && ! CC0_P (XEXP (x, 0)))) + || GET_MODE_CLASS (GET_MODE (XEXP (x, 0))) != MODE_CC) { rtx op0 = XEXP (x, 0); rtx op1 = XEXP (x, 1); @@ -6833,12 +6677,9 @@ simplify_set (rtx x) SUBST (SET_SRC (x), src); } - /* If we are setting CC0 or if the source is a COMPARE, look for the use of - the comparison result and try to simplify it unless we already have used - undobuf.other_insn. */ - if ((GET_MODE_CLASS (mode) == MODE_CC - || GET_CODE (src) == COMPARE - || CC0_P (dest)) + /* If the source is a COMPARE, look for the use of the comparison result + and try to simplify it unless we already have used undobuf.other_insn. */ + if ((GET_MODE_CLASS (mode) == MODE_CC || GET_CODE (src) == COMPARE) && (cc_use = find_single_use (dest, subst_insn, &other_insn)) != 0 && (undobuf.other_insn == 0 || other_insn == undobuf.other_insn) && COMPARISON_P (*cc_use) @@ -6915,7 +6756,7 @@ simplify_set (rtx x) a hard register, just build new versions with the proper mode. If it is a pseudo, we lose unless it is only time we set the pseudo, in which case we can safely change its mode. */ - if (!HAVE_cc0 && compare_mode != GET_MODE (dest)) + if (compare_mode != GET_MODE (dest)) { if (can_change_dest_mode (dest, 0, compare_mode)) { @@ -7039,24 +6880,6 @@ simplify_set (rtx x) src = SET_SRC (x), dest = SET_DEST (x); } - /* If we have (set (cc0) (subreg ...)), we try to remove the subreg - in SRC. */ - if (dest == cc0_rtx - && partial_subreg_p (src) - && subreg_lowpart_p (src)) - { - rtx inner = SUBREG_REG (src); - machine_mode inner_mode = GET_MODE (inner); - - /* Here we make sure that we don't have a sign bit on. */ - if (val_signbit_known_clear_p (GET_MODE (src), - nonzero_bits (inner, inner_mode))) - { - SUBST (SET_SRC (x), inner); - src = SET_SRC (x); - } - } - /* If we have (set FOO (subreg:M (mem:N BAR) 0)) with M wider than N, this would require a paradoxical subreg. Replace the subreg with a zero_extend to avoid the reload that would otherwise be required. @@ -12250,7 +12073,6 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1) /* We can't do anything if OP0 is a condition code value, rather than an actual data value. */ if (const_op != 0 - || CC0_P (XEXP (op0, 0)) || GET_MODE_CLASS (GET_MODE (XEXP (op0, 0))) == MODE_CC) break; @@ -13935,9 +13757,6 @@ mark_used_regs_combine (rtx x) case ADDR_VEC: case ADDR_DIFF_VEC: case ASM_INPUT: - /* CC0 must die in the insn after it is set, so we don't need to take - special note of it here. */ - case CC0: return; case CLOBBER: @@ -14615,7 +14434,6 @@ distribute_notes (rtx notes, rtx_insn *from_insn, rtx_insn *i3, rtx_insn *i2, { rtx set = single_set (tem_insn); rtx inner_dest = 0; - rtx_insn *cc0_setter = NULL; if (set != 0) for (inner_dest = SET_DEST (set); @@ -14628,17 +14446,12 @@ distribute_notes (rtx notes, rtx_insn *from_insn, rtx_insn *i3, rtx_insn *i2, /* Verify that it was the set, and not a clobber that modified the register. - CC0 targets must be careful to maintain setter/user - pairs. If we cannot delete the setter due to side + If we cannot delete the setter due to side effects, mark the user with an UNUSED note instead of deleting it. */ if (set != 0 && ! side_effects_p (SET_SRC (set)) - && rtx_equal_p (XEXP (note, 0), inner_dest) - && (!HAVE_cc0 - || (! reg_mentioned_p (cc0_rtx, SET_SRC (set)) - || ((cc0_setter = prev_cc0_setter (tem_insn)) != NULL - && sets_cc0_p (PATTERN (cc0_setter)) > 0)))) + && rtx_equal_p (XEXP (note, 0), inner_dest)) { /* Move the notes and links of TEM_INSN elsewhere. This might delete other dead insns recursively. @@ -14661,23 +14474,6 @@ distribute_notes (rtx notes, rtx_insn *from_insn, rtx_insn *i3, rtx_insn *i2, SET_INSN_DELETED (tem_insn); if (tem_insn == i2) i2 = NULL; - - /* Delete the setter too. */ - if (cc0_setter) - { - PATTERN (cc0_setter) = pc_rtx; - old_notes = REG_NOTES (cc0_setter); - REG_NOTES (cc0_setter) = NULL; - - distribute_notes (old_notes, cc0_setter, - cc0_setter, NULL, - NULL_RTX, NULL_RTX, NULL_RTX); - distribute_links (LOG_LINKS (cc0_setter)); - - SET_INSN_DELETED (cc0_setter); - if (cc0_setter == i2) - i2 = NULL; - } } else { |