- set = next_set (regno, set);
- }
-
- /* If no available set was found we've reached the end of the
- (possibly empty) copy chain. */
- if (set == 0)
- break;
-
- gcc_assert (GET_CODE (set->expr) == SET);
-
- src = SET_SRC (set->expr);
-
- /* We know the set is available.
- Now check that SRC is ANTLOC (i.e. none of the source operands
- have changed since the start of the block).
-
- If the source operand changed, we may still use it for the next
- iteration of this loop, but we may not use it for substitutions. */
-
- if (gcse_constant_p (src) || oprs_not_set_p (src, insn))
- set1 = set;
-
- /* If the source of the set is anything except a register, then
- we have reached the end of the copy chain. */
- if (! REG_P (src))
- break;
-
- /* Follow the copy chain, i.e. start another iteration of the loop
- and see if we have an available copy into SRC. */
- regno = REGNO (src);
- }
-
- /* SET1 holds the last set that was available and anticipatable at
- INSN. */
- return set1;
-}
-
-/* Subroutine of cprop_insn that tries to propagate constants into
- JUMP_INSNS. JUMP must be a conditional jump. If SETCC is non-NULL
- it is the instruction that immediately precedes JUMP, and must be a
- single SET of a register. FROM is what we will try to replace,
- SRC is the constant we will try to substitute for it. Returns nonzero
- if a change was made. */
-
-static int
-cprop_jump (basic_block bb, rtx setcc, rtx jump, rtx from, rtx src)
-{
- rtx new_rtx, set_src, note_src;
- rtx set = pc_set (jump);
- rtx note = find_reg_equal_equiv_note (jump);
-
- if (note)
- {
- note_src = XEXP (note, 0);
- if (GET_CODE (note_src) == EXPR_LIST)
- note_src = NULL_RTX;
- }
- else note_src = NULL_RTX;
-
- /* Prefer REG_EQUAL notes except those containing EXPR_LISTs. */
- set_src = note_src ? note_src : SET_SRC (set);
-
- /* First substitute the SETCC condition into the JUMP instruction,
- then substitute that given values into this expanded JUMP. */
- if (setcc != NULL_RTX
- && !modified_between_p (from, setcc, jump)
- && !modified_between_p (src, setcc, jump))
- {
- rtx setcc_src;
- rtx setcc_set = single_set (setcc);
- rtx setcc_note = find_reg_equal_equiv_note (setcc);
- setcc_src = (setcc_note && GET_CODE (XEXP (setcc_note, 0)) != EXPR_LIST)
- ? XEXP (setcc_note, 0) : SET_SRC (setcc_set);
- set_src = simplify_replace_rtx (set_src, SET_DEST (setcc_set),
- setcc_src);
- }
- else
- setcc = NULL_RTX;
-
- new_rtx = simplify_replace_rtx (set_src, from, src);
-
- /* If no simplification can be made, then try the next register. */
- if (rtx_equal_p (new_rtx, SET_SRC (set)))
- return 0;
-
- /* If this is now a no-op delete it, otherwise this must be a valid insn. */
- if (new_rtx == pc_rtx)
- delete_insn (jump);
- else
- {
- /* Ensure the value computed inside the jump insn to be equivalent
- to one computed by setcc. */
- if (setcc && modified_in_p (new_rtx, setcc))
- return 0;
- if (! validate_unshare_change (jump, &SET_SRC (set), new_rtx, 0))
- {
- /* When (some) constants are not valid in a comparison, and there
- are two registers to be replaced by constants before the entire
- comparison can be folded into a constant, we need to keep
- intermediate information in REG_EQUAL notes. For targets with
- separate compare insns, such notes are added by try_replace_reg.
- When we have a combined compare-and-branch instruction, however,
- we need to attach a note to the branch itself to make this
- optimization work. */
-
- if (!rtx_equal_p (new_rtx, note_src))
- set_unique_reg_note (jump, REG_EQUAL, copy_rtx (new_rtx));
- return 0;
- }
-
- /* Remove REG_EQUAL note after simplification. */
- if (note_src)
- remove_note (jump, note);
- }
-
-#ifdef HAVE_cc0
- /* Delete the cc0 setter. */
- if (setcc != NULL && CC0_P (SET_DEST (single_set (setcc))))
- delete_insn (setcc);
-#endif
-
- global_const_prop_count++;
- if (dump_file != NULL)
- {
- fprintf (dump_file,
- "GLOBAL CONST-PROP: Replacing reg %d in jump_insn %d with constant ",
- REGNO (from), INSN_UID (jump));
- print_rtl (dump_file, src);
- fprintf (dump_file, "\n");
- }
- purge_dead_edges (bb);
-
- /* If a conditional jump has been changed into unconditional jump, remove
- the jump and make the edge fallthru - this is always called in
- cfglayout mode. */
- if (new_rtx != pc_rtx && simplejump_p (jump))
- {
- edge e;
- edge_iterator ei;
-
- for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); ei_next (&ei))
- if (e->dest != EXIT_BLOCK_PTR
- && BB_HEAD (e->dest) == JUMP_LABEL (jump))
- {
- e->flags |= EDGE_FALLTHRU;
- break;
- }
- delete_insn (jump);
- }
-
- return 1;
-}
-
-static bool
-constprop_register (rtx insn, rtx from, rtx to)
-{
- rtx sset;
-
- /* Check for reg or cc0 setting instructions followed by
- conditional branch instructions first. */
- if ((sset = single_set (insn)) != NULL
- && NEXT_INSN (insn)
- && any_condjump_p (NEXT_INSN (insn)) && onlyjump_p (NEXT_INSN (insn)))
- {
- rtx dest = SET_DEST (sset);
- if ((REG_P (dest) || CC0_P (dest))
- && cprop_jump (BLOCK_FOR_INSN (insn), insn, NEXT_INSN (insn), from, to))
- return 1;
- }
-
- /* Handle normal insns next. */
- if (NONJUMP_INSN_P (insn)
- && try_replace_reg (from, to, insn))
- return 1;
-
- /* Try to propagate a CONST_INT into a conditional jump.
- We're pretty specific about what we will handle in this
- code, we can extend this as necessary over time.
-
- Right now the insn in question must look like
- (set (pc) (if_then_else ...)) */
- else if (any_condjump_p (insn) && onlyjump_p (insn))
- return cprop_jump (BLOCK_FOR_INSN (insn), NULL, insn, from, to);
- return 0;
-}
-
-/* Perform constant and copy propagation on INSN.
- The result is nonzero if a change was made. */
-
-static int
-cprop_insn (rtx insn)
-{
- struct reg_use *reg_used;
- int changed = 0;
- rtx note;
-
- if (!INSN_P (insn))
- return 0;
-
- reg_use_count = 0;
- note_uses (&PATTERN (insn), find_used_regs, NULL);
-
- note = find_reg_equal_equiv_note (insn);
-
- /* We may win even when propagating constants into notes. */
- if (note)
- find_used_regs (&XEXP (note, 0), NULL);
-
- for (reg_used = ®_use_table[0]; reg_use_count > 0;
- reg_used++, reg_use_count--)
- {
- unsigned int regno = REGNO (reg_used->reg_rtx);
- rtx pat, src;
- struct expr *set;
-
- /* If the register has already been set in this block, there's
- nothing we can do. */
- if (! oprs_not_set_p (reg_used->reg_rtx, insn))
- continue;
-
- /* Find an assignment that sets reg_used and is available
- at the start of the block. */
- set = find_avail_set (regno, insn);
- if (! set)
- continue;
-
- pat = set->expr;
- /* ??? We might be able to handle PARALLELs. Later. */
- gcc_assert (GET_CODE (pat) == SET);
-
- src = SET_SRC (pat);
-
- /* Constant propagation. */
- if (gcse_constant_p (src))
- {
- if (constprop_register (insn, reg_used->reg_rtx, src))
- {
- changed = 1;
- global_const_prop_count++;
- if (dump_file != NULL)
- {
- fprintf (dump_file, "GLOBAL CONST-PROP: Replacing reg %d in ", regno);
- fprintf (dump_file, "insn %d with constant ", INSN_UID (insn));
- print_rtl (dump_file, src);
- fprintf (dump_file, "\n");
- }
- if (INSN_DELETED_P (insn))
- return 1;
- }
- }
- else if (REG_P (src)
- && REGNO (src) >= FIRST_PSEUDO_REGISTER
- && REGNO (src) != regno)
- {
- if (try_replace_reg (reg_used->reg_rtx, src, insn))
- {
- changed = 1;
- global_copy_prop_count++;
- if (dump_file != NULL)
- {
- fprintf (dump_file, "GLOBAL COPY-PROP: Replacing reg %d in insn %d",
- regno, INSN_UID (insn));
- fprintf (dump_file, " with reg %d\n", REGNO (src));
- }
-
- /* The original insn setting reg_used may or may not now be
- deletable. We leave the deletion to flow. */
- /* FIXME: If it turns out that the insn isn't deletable,
- then we may have unnecessarily extended register lifetimes
- and made things worse. */
- }
- }
- }
-
- if (changed && DEBUG_INSN_P (insn))
- return 0;
-
- return changed;
-}
-
-/* Like find_used_regs, but avoid recording uses that appear in
- input-output contexts such as zero_extract or pre_dec. This
- restricts the cases we consider to those for which local cprop
- can legitimately make replacements. */
-
-static void
-local_cprop_find_used_regs (rtx *xptr, void *data)
-{
- rtx x = *xptr;
-
- if (x == 0)
- return;
-
- switch (GET_CODE (x))
- {
- case ZERO_EXTRACT:
- case SIGN_EXTRACT:
- case STRICT_LOW_PART:
- return;
-
- case PRE_DEC:
- case PRE_INC:
- case POST_DEC:
- case POST_INC:
- case PRE_MODIFY:
- case POST_MODIFY:
- /* Can only legitimately appear this early in the context of
- stack pushes for function arguments, but handle all of the
- codes nonetheless. */
- return;
-
- case SUBREG:
- /* Setting a subreg of a register larger than word_mode leaves
- the non-written words unchanged. */
- if (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (x))) > BITS_PER_WORD)
- return;
- break;
-
- default:
- break;
- }
-
- find_used_regs (xptr, data);
-}
-
-/* Try to perform local const/copy propagation on X in INSN. */
-
-static bool
-do_local_cprop (rtx x, rtx insn)
-{
- rtx newreg = NULL, newcnst = NULL;
-
- /* Rule out USE instructions and ASM statements as we don't want to
- change the hard registers mentioned. */
- if (REG_P (x)
- && (REGNO (x) >= FIRST_PSEUDO_REGISTER
- || (GET_CODE (PATTERN (insn)) != USE
- && asm_noperands (PATTERN (insn)) < 0)))
- {
- cselib_val *val = cselib_lookup (x, GET_MODE (x), 0);
- struct elt_loc_list *l;
-
- if (!val)
- return false;
- for (l = val->locs; l; l = l->next)
- {
- rtx this_rtx = l->loc;
- rtx note;
-
- if (gcse_constant_p (this_rtx))
- newcnst = this_rtx;
- if (REG_P (this_rtx) && REGNO (this_rtx) >= FIRST_PSEUDO_REGISTER
- /* Don't copy propagate if it has attached REG_EQUIV note.
- At this point this only function parameters should have
- REG_EQUIV notes and if the argument slot is used somewhere
- explicitly, it means address of parameter has been taken,
- so we should not extend the lifetime of the pseudo. */
- && (!(note = find_reg_note (l->setting_insn, REG_EQUIV, NULL_RTX))
- || ! MEM_P (XEXP (note, 0))))
- newreg = this_rtx;
- }
- if (newcnst && constprop_register (insn, x, newcnst))
- {
- if (dump_file != NULL)
- {
- fprintf (dump_file, "LOCAL CONST-PROP: Replacing reg %d in ",
- REGNO (x));
- fprintf (dump_file, "insn %d with constant ",
- INSN_UID (insn));
- print_rtl (dump_file, newcnst);
- fprintf (dump_file, "\n");
- }
- local_const_prop_count++;
- return true;
- }
- else if (newreg && newreg != x && try_replace_reg (x, newreg, insn))
- {
- if (dump_file != NULL)
- {
- fprintf (dump_file,
- "LOCAL COPY-PROP: Replacing reg %d in insn %d",
- REGNO (x), INSN_UID (insn));
- fprintf (dump_file, " with reg %d\n", REGNO (newreg));
- }
- local_copy_prop_count++;
- return true;
- }
- }
- return false;
-}
-
-/* Do local const/copy propagation (i.e. within each basic block). */
-
-static int
-local_cprop_pass (void)
-{
- basic_block bb;
- rtx insn;
- struct reg_use *reg_used;
- bool changed = false;
-
- cselib_init (false);
- FOR_EACH_BB (bb)
- {
- FOR_BB_INSNS (bb, insn)
- {
- if (INSN_P (insn))
- {
- rtx note = find_reg_equal_equiv_note (insn);
- do
- {
- reg_use_count = 0;
- note_uses (&PATTERN (insn), local_cprop_find_used_regs,
- NULL);
- if (note)
- local_cprop_find_used_regs (&XEXP (note, 0), NULL);
-
- for (reg_used = ®_use_table[0]; reg_use_count > 0;
- reg_used++, reg_use_count--)
- {
- if (do_local_cprop (reg_used->reg_rtx, insn))
- {
- changed = true;
- break;
- }
- }
- if (INSN_DELETED_P (insn))
- break;
- }
- while (reg_use_count);
- }
- cselib_process_insn (insn);
- }
-
- /* Forget everything at the end of a basic block. */
- cselib_clear_table ();
- }
-
- cselib_finish ();
-
- return changed;
-}
-
-/* Similar to get_condition, only the resulting condition must be
- valid at JUMP, instead of at EARLIEST.
-
- This differs from noce_get_condition in ifcvt.c in that we prefer not to
- settle for the condition variable in the jump instruction being integral.
- We prefer to be able to record the value of a user variable, rather than
- the value of a temporary used in a condition. This could be solved by
- recording the value of *every* register scanned by canonicalize_condition,
- but this would require some code reorganization. */
-
-rtx
-fis_get_condition (rtx jump)
-{
- return get_condition (jump, NULL, false, true);
-}
-
-/* Check the comparison COND to see if we can safely form an implicit set from
- it. COND is either an EQ or NE comparison. */
-
-static bool
-implicit_set_cond_p (const_rtx cond)
-{
- const enum machine_mode mode = GET_MODE (XEXP (cond, 0));
- const_rtx cst = XEXP (cond, 1);
-
- /* We can't perform this optimization if either operand might be or might
- contain a signed zero. */
- if (HONOR_SIGNED_ZEROS (mode))
- {
- /* It is sufficient to check if CST is or contains a zero. We must
- handle float, complex, and vector. If any subpart is a zero, then
- the optimization can't be performed. */
- /* ??? The complex and vector checks are not implemented yet. We just
- always return zero for them. */
- if (GET_CODE (cst) == CONST_DOUBLE)
- {
- REAL_VALUE_TYPE d;
- REAL_VALUE_FROM_CONST_DOUBLE (d, cst);
- if (REAL_VALUES_EQUAL (d, dconst0))
- return 0;
- }
- else
- return 0;
- }
-
- return gcse_constant_p (cst);
-}
-
-/* Find the implicit sets of a function. An "implicit set" is a constraint
- on the value of a variable, implied by a conditional jump. For example,
- following "if (x == 2)", the then branch may be optimized as though the
- conditional performed an "explicit set", in this example, "x = 2". This
- function records the set patterns that are implicit at the start of each
- basic block.
-
- FIXME: This would be more effective if critical edges are pre-split. As
- it is now, we can't record implicit sets for blocks that have
- critical successor edges. This results in missed optimizations
- and in more (unnecessary) work in cfgcleanup.c:thread_jump(). */
-
-static void
-find_implicit_sets (void)
-{
- basic_block bb, dest;
- unsigned int count;
- rtx cond, new_rtx;
-
- count = 0;
- FOR_EACH_BB (bb)
- /* Check for more than one successor. */
- if (EDGE_COUNT (bb->succs) > 1)
- {
- cond = fis_get_condition (BB_END (bb));
-
- if (cond
- && (GET_CODE (cond) == EQ || GET_CODE (cond) == NE)
- && REG_P (XEXP (cond, 0))
- && REGNO (XEXP (cond, 0)) >= FIRST_PSEUDO_REGISTER
- && implicit_set_cond_p (cond))
- {
- dest = GET_CODE (cond) == EQ ? BRANCH_EDGE (bb)->dest
- : FALLTHRU_EDGE (bb)->dest;
-
- if (dest
- /* Record nothing for a critical edge. */
- && single_pred_p (dest)
- && dest != EXIT_BLOCK_PTR)
- {
- new_rtx = gen_rtx_SET (VOIDmode, XEXP (cond, 0),
- XEXP (cond, 1));
- implicit_sets[dest->index] = new_rtx;
- if (dump_file)
- {
- fprintf(dump_file, "Implicit set of reg %d in ",
- REGNO (XEXP (cond, 0)));
- fprintf(dump_file, "basic block %d\n", dest->index);
- }
- count++;
- }
- }
- }
-
- if (dump_file)
- fprintf (dump_file, "Found %d implicit sets\n", count);
-}
-
-/* Bypass conditional jumps. */
-
-/* The value of last_basic_block at the beginning of the jump_bypass
- pass. The use of redirect_edge_and_branch_force may introduce new
- basic blocks, but the data flow analysis is only valid for basic
- block indices less than bypass_last_basic_block. */
-
-static int bypass_last_basic_block;
-
-/* Find a set of REGNO to a constant that is available at the end of basic
- block BB. Returns NULL if no such set is found. Based heavily upon
- find_avail_set. */
-
-static struct expr *
-find_bypass_set (int regno, int bb)
-{
- struct expr *result = 0;
-
- for (;;)
- {
- rtx src;
- struct expr *set = lookup_set (regno, &set_hash_table);
-
- while (set)
- {
- if (TEST_BIT (cprop_avout[bb], set->bitmap_index))
- break;
- set = next_set (regno, set);
- }
-
- if (set == 0)
- break;
-
- gcc_assert (GET_CODE (set->expr) == SET);
-
- src = SET_SRC (set->expr);
- if (gcse_constant_p (src))
- result = set;
-
- if (! REG_P (src))
- break;
-
- regno = REGNO (src);
- }
- return result;
-}
-
-
-/* Subroutine of bypass_block that checks whether a pseudo is killed by
- any of the instructions inserted on an edge. Jump bypassing places
- condition code setters on CFG edges using insert_insn_on_edge. This
- function is required to check that our data flow analysis is still
- valid prior to commit_edge_insertions. */
-
-static bool
-reg_killed_on_edge (const_rtx reg, const_edge e)
-{
- rtx insn;
-
- for (insn = e->insns.r; insn; insn = NEXT_INSN (insn))
- if (INSN_P (insn) && reg_set_p (reg, insn))
- return true;
-
- return false;
-}
-
-/* Subroutine of bypass_conditional_jumps that attempts to bypass the given
- basic block BB which has more than one predecessor. If not NULL, SETCC
- is the first instruction of BB, which is immediately followed by JUMP_INSN
- JUMP. Otherwise, SETCC is NULL, and JUMP is the first insn of BB.
- Returns nonzero if a change was made.
-
- During the jump bypassing pass, we may place copies of SETCC instructions
- on CFG edges. The following routine must be careful to pay attention to
- these inserted insns when performing its transformations. */
-
-static int
-bypass_block (basic_block bb, rtx setcc, rtx jump)
-{
- rtx insn, note;
- edge e, edest;
- int i, change;
- int may_be_loop_header;
- unsigned removed_p;
- edge_iterator ei;
-
- insn = (setcc != NULL) ? setcc : jump;
-
- /* Determine set of register uses in INSN. */
- reg_use_count = 0;
- note_uses (&PATTERN (insn), find_used_regs, NULL);
- note = find_reg_equal_equiv_note (insn);
- if (note)
- find_used_regs (&XEXP (note, 0), NULL);
-
- may_be_loop_header = false;
- FOR_EACH_EDGE (e, ei, bb->preds)
- if (e->flags & EDGE_DFS_BACK)
- {
- may_be_loop_header = true;
- break;
- }
-
- change = 0;
- for (ei = ei_start (bb->preds); (e = ei_safe_edge (ei)); )
- {
- removed_p = 0;
-
- if (e->flags & EDGE_COMPLEX)
- {
- ei_next (&ei);
- continue;
- }
-
- /* We can't redirect edges from new basic blocks. */
- if (e->src->index >= bypass_last_basic_block)
- {
- ei_next (&ei);
- continue;
- }
-
- /* The irreducible loops created by redirecting of edges entering the
- loop from outside would decrease effectiveness of some of the following
- optimizations, so prevent this. */
- if (may_be_loop_header
- && !(e->flags & EDGE_DFS_BACK))
- {
- ei_next (&ei);
- continue;
- }
-
- for (i = 0; i < reg_use_count; i++)
- {
- struct reg_use *reg_used = ®_use_table[i];
- unsigned int regno = REGNO (reg_used->reg_rtx);
- basic_block dest, old_dest;
- struct expr *set;
- rtx src, new_rtx;
-
- set = find_bypass_set (regno, e->src->index);
-
- if (! set)
- continue;
-
- /* Check the data flow is valid after edge insertions. */
- if (e->insns.r && reg_killed_on_edge (reg_used->reg_rtx, e))
- continue;
-
- src = SET_SRC (pc_set (jump));
-
- if (setcc != NULL)
- src = simplify_replace_rtx (src,
- SET_DEST (PATTERN (setcc)),
- SET_SRC (PATTERN (setcc)));
-
- new_rtx = simplify_replace_rtx (src, reg_used->reg_rtx,
- SET_SRC (set->expr));
-
- /* Jump bypassing may have already placed instructions on
- edges of the CFG. We can't bypass an outgoing edge that
- has instructions associated with it, as these insns won't
- get executed if the incoming edge is redirected. */
-
- if (new_rtx == pc_rtx)
- {
- edest = FALLTHRU_EDGE (bb);
- dest = edest->insns.r ? NULL : edest->dest;
- }
- else if (GET_CODE (new_rtx) == LABEL_REF)
- {
- dest = BLOCK_FOR_INSN (XEXP (new_rtx, 0));
- /* Don't bypass edges containing instructions. */
- edest = find_edge (bb, dest);
- if (edest && edest->insns.r)
- dest = NULL;
- }
- else
- dest = NULL;
-
- /* Avoid unification of the edge with other edges from original
- branch. We would end up emitting the instruction on "both"
- edges. */
-
- if (dest && setcc && !CC0_P (SET_DEST (PATTERN (setcc)))
- && find_edge (e->src, dest))
- dest = NULL;
-
- old_dest = e->dest;
- if (dest != NULL
- && dest != old_dest
- && dest != EXIT_BLOCK_PTR)
- {
- redirect_edge_and_branch_force (e, dest);
-
- /* Copy the register setter to the redirected edge.
- Don't copy CC0 setters, as CC0 is dead after jump. */
- if (setcc)
- {
- rtx pat = PATTERN (setcc);
- if (!CC0_P (SET_DEST (pat)))
- insert_insn_on_edge (copy_insn (pat), e);
- }
-
- if (dump_file != NULL)
- {
- fprintf (dump_file, "JUMP-BYPASS: Proved reg %d "
- "in jump_insn %d equals constant ",
- regno, INSN_UID (jump));
- print_rtl (dump_file, SET_SRC (set->expr));
- fprintf (dump_file, "\nBypass edge from %d->%d to %d\n",
- e->src->index, old_dest->index, dest->index);
- }
- change = 1;
- removed_p = 1;
- break;
- }
- }
- if (!removed_p)
- ei_next (&ei);
- }
- return change;
-}
-
-/* Find basic blocks with more than one predecessor that only contain a
- single conditional jump. If the result of the comparison is known at
- compile-time from any incoming edge, redirect that edge to the
- appropriate target. Returns nonzero if a change was made.
-
- This function is now mis-named, because we also handle indirect jumps. */
-
-static int
-bypass_conditional_jumps (void)
-{
- basic_block bb;
- int changed;
- rtx setcc;
- rtx insn;
- rtx dest;
-
- /* Note we start at block 1. */
- if (ENTRY_BLOCK_PTR->next_bb == EXIT_BLOCK_PTR)
- return 0;
-
- bypass_last_basic_block = last_basic_block;
- mark_dfs_back_edges ();
-
- changed = 0;
- FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR->next_bb->next_bb,
- EXIT_BLOCK_PTR, next_bb)
- {
- /* Check for more than one predecessor. */
- if (!single_pred_p (bb))
- {
- setcc = NULL_RTX;
- FOR_BB_INSNS (bb, insn)
- if (DEBUG_INSN_P (insn))
- continue;
- else if (NONJUMP_INSN_P (insn))
- {
- if (setcc)
- break;
- if (GET_CODE (PATTERN (insn)) != SET)
- break;
-
- dest = SET_DEST (PATTERN (insn));
- if (REG_P (dest) || CC0_P (dest))
- setcc = insn;
- else
- break;
- }
- else if (JUMP_P (insn))
- {
- if ((any_condjump_p (insn) || computed_jump_p (insn))
- && onlyjump_p (insn))
- changed |= bypass_block (bb, setcc, insn);
- break;
- }
- else if (INSN_P (insn))
- break;
- }
- }
-
- /* If we bypassed any register setting insns, we inserted a
- copy on the redirected edge. These need to be committed. */
- if (changed)
- commit_edge_insertions ();
-
- return changed;
-}
-\f
-/* Compute PRE+LCM working variables. */
-
-/* Local properties of expressions. */
-/* Nonzero for expressions that are transparent in the block. */
-static sbitmap *transp;
-
-/* Nonzero for expressions that are transparent at the end of the block.
- This is only zero for expressions killed by abnormal critical edge
- created by a calls. */
-static sbitmap *transpout;
-
-/* Nonzero for expressions that are computed (available) in the block. */
-static sbitmap *comp;
-
-/* Nonzero for expressions that are locally anticipatable in the block. */
-static sbitmap *antloc;
-
-/* Nonzero for expressions where this block is an optimal computation
- point. */
-static sbitmap *pre_optimal;
-
-/* Nonzero for expressions which are redundant in a particular block. */
-static sbitmap *pre_redundant;
-
-/* Nonzero for expressions which should be inserted on a specific edge. */
-static sbitmap *pre_insert_map;