- {
- /* Splitting address givs is useful since it will often allow us
- to eliminate some increment insns for the base giv as
- unnecessary. */
-
- /* If the addr giv is combined with a dest_reg giv, then all
- references to that dest reg will be remapped, which is NOT
- what we want for split addr regs. We always create a new
- register for the split addr giv, just to be safe. */
-
- /* If we have multiple identical address givs within a
- single instruction, then use a single pseudo reg for
- both. This is necessary in case one is a match_dup
- of the other. */
-
- v->const_adjust = 0;
-
- if (v->same_insn)
- {
- v->dest_reg = v->same_insn->dest_reg;
- if (loop_dump_stream)
- fprintf (loop_dump_stream,
- "Sharing address givs in insn %d\n",
- INSN_UID (v->insn));
- }
- /* If multiple address GIVs have been combined with the
- same dest_reg GIV, do not create a new register for
- each. */
- else if (unroll_type != UNROLL_COMPLETELY
- && v->giv_type == DEST_ADDR
- && v->same && v->same->giv_type == DEST_ADDR
- && v->same->unrolled
- /* combine_givs_p may return true for some cases
- where the add and mult values are not equal.
- To share a register here, the values must be
- equal. */
- && rtx_equal_p (v->same->mult_val, v->mult_val)
- && rtx_equal_p (v->same->add_val, v->add_val)
- /* If the memory references have different modes,
- then the address may not be valid and we must
- not share registers. */
- && verify_addresses (v, giv_inc, unroll_number))
- {
- v->dest_reg = v->same->dest_reg;
- v->shared = 1;
- }
- else if (unroll_type != UNROLL_COMPLETELY)
- {
- /* If not completely unrolling the loop, then create a new
- register to hold the split value of the DEST_ADDR giv.
- Emit insn to initialize its value before loop start. */
-
- rtx tem = gen_reg_rtx (v->mode);
- struct induction *same = v->same;
- rtx new_reg = v->new_reg;
- record_base_value (REGNO (tem), v->add_val, 0);
-
- /* If the address giv has a constant in its new_reg value,
- then this constant can be pulled out and put in value,
- instead of being part of the initialization code. */
-
- if (GET_CODE (new_reg) == PLUS
- && GET_CODE (XEXP (new_reg, 1)) == CONST_INT)
- {
- v->dest_reg
- = plus_constant (tem, INTVAL (XEXP (new_reg, 1)));
-
- /* Only succeed if this will give valid addresses.
- Try to validate both the first and the last
- address resulting from loop unrolling, if
- one fails, then can't do const elim here. */
- if (verify_addresses (v, giv_inc, unroll_number))
- {
- /* Save the negative of the eliminated const, so
- that we can calculate the dest_reg's increment
- value later. */
- v->const_adjust = -INTVAL (XEXP (new_reg, 1));
-
- new_reg = XEXP (new_reg, 0);
- if (loop_dump_stream)
- fprintf (loop_dump_stream,
- "Eliminating constant from giv %d\n",
- REGNO (tem));
- }
- else
- v->dest_reg = tem;
- }
- else
- v->dest_reg = tem;
-
- /* If the address hasn't been checked for validity yet, do so
- now, and fail completely if either the first or the last
- unrolled copy of the address is not a valid address
- for the instruction that uses it. */
- if (v->dest_reg == tem
- && ! verify_addresses (v, giv_inc, unroll_number))
- {
- for (v2 = v->next_iv; v2; v2 = v2->next_iv)
- if (v2->same_insn == v)
- v2->same_insn = 0;
-
- if (loop_dump_stream)
- fprintf (loop_dump_stream,
- "Invalid address for giv at insn %d\n",
- INSN_UID (v->insn));
- continue;
- }
-
- v->new_reg = new_reg;
- v->same = same;
-
- /* We set this after the address check, to guarantee that
- the register will be initialized. */
- v->unrolled = 1;
-
- /* To initialize the new register, just move the value of
- new_reg into it. This is not guaranteed to give a valid
- instruction on machines with complex addressing modes.
- If we can't recognize it, then delete it and emit insns
- to calculate the value from scratch. */
- loop_insn_hoist (loop, gen_rtx_SET (VOIDmode, tem,
- copy_rtx (v->new_reg)));
- if (recog_memoized (PREV_INSN (loop->start)) < 0)
- {
- rtx sequence, ret;
-
- /* We can't use bl->initial_value to compute the initial
- value, because the loop may have been preconditioned.
- We must calculate it from NEW_REG. */
- delete_related_insns (PREV_INSN (loop->start));
-
- start_sequence ();
- ret = force_operand (v->new_reg, tem);
- if (ret != tem)
- emit_move_insn (tem, ret);
- sequence = get_insns ();
- end_sequence ();
- loop_insn_hoist (loop, sequence);
-
- if (loop_dump_stream)
- fprintf (loop_dump_stream,
- "Invalid init insn, rewritten.\n");
- }
- }
- else
- {
- v->dest_reg = value;
-
- /* Check the resulting address for validity, and fail
- if the resulting address would be invalid. */
- if (! verify_addresses (v, giv_inc, unroll_number))
- {
- for (v2 = v->next_iv; v2; v2 = v2->next_iv)
- if (v2->same_insn == v)
- v2->same_insn = 0;
-
- if (loop_dump_stream)
- fprintf (loop_dump_stream,
- "Invalid address for giv at insn %d\n",
- INSN_UID (v->insn));
- continue;
- }
- }
-
- /* Store the value of dest_reg into the insn. This sharing
- will not be a problem as this insn will always be copied
- later. */
-
- *v->location = v->dest_reg;
-
- /* If this address giv is combined with a dest reg giv, then
- save the base giv's induction pointer so that we will be
- able to handle this address giv properly. The base giv
- itself does not have to be splittable. */
-
- if (v->same && v->same->giv_type == DEST_REG)
- addr_combined_regs[REGNO (v->same->new_reg)] = v->same;
-
- if (GET_CODE (v->new_reg) == REG)
- {
- /* This giv maybe hasn't been combined with any others.
- Make sure that it's giv is marked as splittable here. */
-
- splittable_regs[REGNO (v->new_reg)] = value;
-
- /* Make it appear to depend upon itself, so that the
- giv will be properly split in the main loop above. */
- if (! v->same)
- {
- v->same = v;
- addr_combined_regs[REGNO (v->new_reg)] = v;
- }
- }
-
- if (loop_dump_stream)
- fprintf (loop_dump_stream, "DEST_ADDR giv being split.\n");
- }