- /* It is unsafe to move the set.
-
- This code used to consider it OK to move a set of a variable
- which was not created by the user and not used in an exit test.
- That behavior is incorrect and was removed. */
- ;
- else if ((tem = loop_invariant_p (loop, src))
- && (dependencies == 0
- || (tem2 = loop_invariant_p (loop, dependencies)) != 0)
- && (regs->array[REGNO (SET_DEST (set))].set_in_loop == 1
- || (tem1
- = consec_sets_invariant_p
- (loop, SET_DEST (set),
- regs->array[REGNO (SET_DEST (set))].set_in_loop,
- p)))
- /* If the insn can cause a trap (such as divide by zero),
- can't move it unless it's guaranteed to be executed
- once loop is entered. Even a function call might
- prevent the trap insn from being reached
- (since it might exit!) */
- && ! ((maybe_never || call_passed)
- && may_trap_p (src)))
- {
- struct movable *m;
- int regno = REGNO (SET_DEST (set));
-
- /* A potential lossage is where we have a case where two insns
- can be combined as long as they are both in the loop, but
- we move one of them outside the loop. For large loops,
- this can lose. The most common case of this is the address
- of a function being called.
-
- Therefore, if this register is marked as being used exactly
- once if we are in a loop with calls (a "large loop"), see if
- we can replace the usage of this register with the source
- of this SET. If we can, delete this insn.
-
- Don't do this if P has a REG_RETVAL note or if we have
- SMALL_REGISTER_CLASSES and SET_SRC is a hard register. */
-
- if (loop_info->has_call
- && regs->array[regno].single_usage != 0
- && regs->array[regno].single_usage != const0_rtx
- && REGNO_FIRST_UID (regno) == INSN_UID (p)
- && (REGNO_LAST_UID (regno)
- == INSN_UID (regs->array[regno].single_usage))
- && regs->array[regno].set_in_loop == 1
- && GET_CODE (SET_SRC (set)) != ASM_OPERANDS
- && ! side_effects_p (SET_SRC (set))
- && ! find_reg_note (p, REG_RETVAL, NULL_RTX)
- && (! SMALL_REGISTER_CLASSES
- || (! (GET_CODE (SET_SRC (set)) == REG
- && REGNO (SET_SRC (set)) < FIRST_PSEUDO_REGISTER)))
- /* This test is not redundant; SET_SRC (set) might be
- a call-clobbered register and the life of REGNO
- might span a call. */
- && ! modified_between_p (SET_SRC (set), p,
- regs->array[regno].single_usage)
- && no_labels_between_p (p, regs->array[regno].single_usage)
- && validate_replace_rtx (SET_DEST (set), SET_SRC (set),
- regs->array[regno].single_usage))
- {
- /* Replace any usage in a REG_EQUAL note. Must copy the
- new source, so that we don't get rtx sharing between the
- SET_SOURCE and REG_NOTES of insn p. */
- REG_NOTES (regs->array[regno].single_usage)
- = replace_rtx (REG_NOTES (regs->array[regno].single_usage),
- SET_DEST (set), copy_rtx (SET_SRC (set)));
-
- delete_insn (p);
- for (i = 0; i < LOOP_REGNO_NREGS (regno, SET_DEST (set)); i++)
- regs->array[regno+i].set_in_loop = 0;
- continue;
- }
-
- m = (struct movable *) xmalloc (sizeof (struct movable));
- m->next = 0;
- m->insn = p;
- m->set_src = src;
- m->dependencies = dependencies;
- m->set_dest = SET_DEST (set);
- m->force = 0;
- m->consec = regs->array[REGNO (SET_DEST (set))].set_in_loop - 1;
- m->done = 0;
- m->forces = 0;
- m->partial = 0;
- m->move_insn = move_insn;
- m->move_insn_first = 0;
- m->is_equiv = (find_reg_note (p, REG_EQUIV, NULL_RTX) != 0);
- m->savemode = VOIDmode;
- m->regno = regno;
- /* Set M->cond if either loop_invariant_p
- or consec_sets_invariant_p returned 2
- (only conditionally invariant). */
- m->cond = ((tem | tem1 | tem2) > 1);
- m->global = LOOP_REG_GLOBAL_P (loop, regno);
- m->match = 0;
- m->lifetime = LOOP_REG_LIFETIME (loop, regno);
- m->savings = regs->array[regno].n_times_set;
- if (find_reg_note (p, REG_RETVAL, NULL_RTX))
- m->savings += libcall_benefit (p);
- for (i = 0; i < LOOP_REGNO_NREGS (regno, SET_DEST (set)); i++)
- regs->array[regno+i].set_in_loop = move_insn ? -2 : -1;
- /* Add M to the end of the chain MOVABLES. */
- loop_movables_add (movables, m);
-
- if (m->consec > 0)
+ /* It is unsafe to move the set. However, it may be OK to
+ move the source into a new pseudo, and substitute a
+ reg-to-reg copy for the original insn.
+
+ This code used to consider it OK to move a set of a variable
+ which was not created by the user and not used in an exit
+ test.
+ That behavior is incorrect and was removed. */
+ insert_temp = 1;
+
+ /* Don't try to optimize a MODE_CC set with a constant
+ source. It probably will be combined with a conditional
+ jump. */
+ if (GET_MODE_CLASS (GET_MODE (SET_DEST (set))) == MODE_CC
+ && CONSTANT_P (src))
+ ;
+ /* Don't try to optimize a register that was made
+ by loop-optimization for an inner loop.
+ We don't know its life-span, so we can't compute
+ the benefit. */
+ else if (REGNO (SET_DEST (set)) >= max_reg_before_loop)
+ ;
+ /* Don't move the source and add a reg-to-reg copy:
+ - with -Os (this certainly increases size),
+ - if the mode doesn't support copy operations (obviously),
+ - if the source is already a reg (the motion will gain nothing),
+ - if the source is a legitimate constant (likewise). */
+ else if (insert_temp
+ && (optimize_size
+ || ! can_copy_p (GET_MODE (SET_SRC (set)))
+ || GET_CODE (SET_SRC (set)) == REG
+ || (CONSTANT_P (SET_SRC (set))
+ && LEGITIMATE_CONSTANT_P (SET_SRC (set)))))
+ ;
+ else if ((tem = loop_invariant_p (loop, src))
+ && (dependencies == 0
+ || (tem2
+ = loop_invariant_p (loop, dependencies)) != 0)
+ && (regs->array[REGNO (SET_DEST (set))].set_in_loop == 1
+ || (tem1
+ = consec_sets_invariant_p
+ (loop, SET_DEST (set),
+ regs->array[REGNO (SET_DEST (set))].set_in_loop,
+ p)))
+ /* If the insn can cause a trap (such as divide by zero),
+ can't move it unless it's guaranteed to be executed
+ once loop is entered. Even a function call might
+ prevent the trap insn from being reached
+ (since it might exit!) */
+ && ! ((maybe_never || call_passed)
+ && may_trap_p (src)))