-/* Record a conflict between register REGNO
- and everything currently live.
- REGNO must not be a pseudo reg that was allocated
- by local_alloc; such numbers must be translated through
- reg_renumber before calling here. */
-
-static void
-record_one_conflict (regno)
- int regno;
-{
- int j;
-
- if (regno < FIRST_PSEUDO_REGISTER)
- /* When a hard register becomes live,
- record conflicts with live pseudo regs. */
- EXECUTE_IF_SET_IN_ALLOCNO_SET (allocnos_live, j,
- {
- SET_HARD_REG_BIT (allocno[j].hard_reg_conflicts, regno);
- });
- else
- /* When a pseudo-register becomes live,
- record conflicts first with hard regs,
- then with other pseudo regs. */
- {
- int ialloc = reg_allocno[regno];
- int ialloc_prod = ialloc * allocno_row_words;
-
- IOR_HARD_REG_SET (allocno[ialloc].hard_reg_conflicts, hard_regs_live);
- for (j = allocno_row_words - 1; j >= 0; j--)
- {
-#if 0
- int k;
- for (k = 0; k < n_no_conflict_pairs; k++)
- if (! ((j == no_conflict_pairs[k].allocno1
- && ialloc == no_conflict_pairs[k].allocno2)
- ||
- (j == no_conflict_pairs[k].allocno2
- && ialloc == no_conflict_pairs[k].allocno1)))
-#endif /* 0 */
- conflicts[ialloc_prod + j] |= allocnos_live[j];
- }
- }
-}
-
-/* Record all allocnos currently live as conflicting
- with all hard regs currently live.
-
- ALLOCNO_VEC is a vector of LEN allocnos, all allocnos that
- are currently live. Their bits are also flagged in allocnos_live. */
-
-static void
-record_conflicts (allocno_vec, len)
- int *allocno_vec;
- int len;
-{
- while (--len >= 0)
- IOR_HARD_REG_SET (allocno[allocno_vec[len]].hard_reg_conflicts,
- hard_regs_live);
-}
-
-/* If CONFLICTP (i, j) is true, make sure CONFLICTP (j, i) is also true. */
-static void
-mirror_conflicts ()
-{
- int i, j;
- int rw = allocno_row_words;
- int rwb = rw * INT_BITS;
- INT_TYPE *p = conflicts;
- INT_TYPE *q0 = conflicts, *q1, *q2;
- unsigned INT_TYPE mask;
-
- for (i = max_allocno - 1, mask = 1; i >= 0; i--, mask <<= 1)
- {
- if (! mask)
- {
- mask = 1;
- q0++;
- }
- for (j = allocno_row_words - 1, q1 = q0; j >= 0; j--, q1 += rwb)
- {
- unsigned INT_TYPE word;
-
- for (word = (unsigned INT_TYPE) *p++, q2 = q1; word;
- word >>= 1, q2 += rw)
- {
- if (word & 1)
- *q2 |= mask;
- }
- }
- }
-}
-\f
-/* Handle the case where REG is set by the insn being scanned,
- during the forward scan to accumulate conflicts.
- Store a 1 in regs_live or allocnos_live for this register, record how many
- consecutive hardware registers it actually needs,
- and record a conflict with all other registers already live.
-
- Note that even if REG does not remain alive after this insn,
- we must mark it here as live, to ensure a conflict between
- REG and any other regs set in this insn that really do live.
- This is because those other regs could be considered after this.
-
- REG might actually be something other than a register;
- if so, we do nothing.
-
- SETTER is 0 if this register was modified by an auto-increment (i.e.,
- a REG_INC note was found for it). */
-
-static void
-mark_reg_store (reg, setter, data)
- rtx reg, setter;
- void *data ATTRIBUTE_UNUSED;
-{
- int regno;
-
- if (GET_CODE (reg) == SUBREG)
- reg = SUBREG_REG (reg);
-
- if (GET_CODE (reg) != REG)
- return;
-
- regs_set[n_regs_set++] = reg;
-
- if (setter && GET_CODE (setter) != CLOBBER)
- set_preference (reg, SET_SRC (setter));
-
- regno = REGNO (reg);
-
- /* Either this is one of the max_allocno pseudo regs not allocated,
- or it is or has a hardware reg. First handle the pseudo-regs. */
- if (regno >= FIRST_PSEUDO_REGISTER)
- {
- if (reg_allocno[regno] >= 0)
- {
- SET_ALLOCNO_LIVE (reg_allocno[regno]);
- record_one_conflict (regno);
- }
- }
-
- if (reg_renumber[regno] >= 0)
- regno = reg_renumber[regno];
-
- /* Handle hardware regs (and pseudos allocated to hard regs). */
- if (regno < FIRST_PSEUDO_REGISTER && ! fixed_regs[regno])
- {
- int last = regno + HARD_REGNO_NREGS (regno, GET_MODE (reg));
- while (regno < last)
- {
- record_one_conflict (regno);
- SET_HARD_REG_BIT (hard_regs_live, regno);
- regno++;
- }
- }
-}
-\f
-/* Like mark_reg_set except notice just CLOBBERs; ignore SETs. */
-
-static void
-mark_reg_clobber (reg, setter, data)
- rtx reg, setter;
- void *data ATTRIBUTE_UNUSED;
-{
- if (GET_CODE (setter) == CLOBBER)
- mark_reg_store (reg, setter, data);
-}
-
-/* Record that REG has conflicts with all the regs currently live.
- Do not mark REG itself as live. */
-
-static void
-mark_reg_conflicts (reg)
- rtx reg;
-{
- int regno;
-
- if (GET_CODE (reg) == SUBREG)
- reg = SUBREG_REG (reg);
-
- if (GET_CODE (reg) != REG)
- return;
-
- regno = REGNO (reg);
-
- /* Either this is one of the max_allocno pseudo regs not allocated,
- or it is or has a hardware reg. First handle the pseudo-regs. */
- if (regno >= FIRST_PSEUDO_REGISTER)
- {
- if (reg_allocno[regno] >= 0)
- record_one_conflict (regno);
- }
-
- if (reg_renumber[regno] >= 0)
- regno = reg_renumber[regno];
-
- /* Handle hardware regs (and pseudos allocated to hard regs). */
- if (regno < FIRST_PSEUDO_REGISTER && ! fixed_regs[regno])
- {
- int last = regno + HARD_REGNO_NREGS (regno, GET_MODE (reg));
- while (regno < last)
- {
- record_one_conflict (regno);
- regno++;
- }
- }
-}
-\f
-/* Mark REG as being dead (following the insn being scanned now).
- Store a 0 in regs_live or allocnos_live for this register. */
-
-static void
-mark_reg_death (reg)
- rtx reg;
-{
- int regno = REGNO (reg);
-
- /* Either this is one of the max_allocno pseudo regs not allocated,
- or it is a hardware reg. First handle the pseudo-regs. */
- if (regno >= FIRST_PSEUDO_REGISTER)
- {
- if (reg_allocno[regno] >= 0)
- CLEAR_ALLOCNO_LIVE (reg_allocno[regno]);
- }
-
- /* For pseudo reg, see if it has been assigned a hardware reg. */
- if (reg_renumber[regno] >= 0)
- regno = reg_renumber[regno];
-
- /* Handle hardware regs (and pseudos allocated to hard regs). */
- if (regno < FIRST_PSEUDO_REGISTER && ! fixed_regs[regno])
- {
- /* Pseudo regs already assigned hardware regs are treated
- almost the same as explicit hardware regs. */
- int last = regno + HARD_REGNO_NREGS (regno, GET_MODE (reg));
- while (regno < last)
- {
- CLEAR_HARD_REG_BIT (hard_regs_live, regno);
- regno++;
- }
- }
-}
-
-/* Mark hard reg REGNO as currently live, assuming machine mode MODE
- for the value stored in it. MODE determines how many consecutive
- registers are actually in use. Do not record conflicts;
- it is assumed that the caller will do that. */
-
-static void
-mark_reg_live_nc (regno, mode)
- int regno;
- enum machine_mode mode;
-{
- int last = regno + HARD_REGNO_NREGS (regno, mode);
- while (regno < last)
- {
- SET_HARD_REG_BIT (hard_regs_live, regno);
- regno++;
- }
-}
-\f
-/* Try to set a preference for an allocno to a hard register.
- We are passed DEST and SRC which are the operands of a SET. It is known
- that SRC is a register. If SRC or the first operand of SRC is a register,
- try to set a preference. If one of the two is a hard register and the other
- is a pseudo-register, mark the preference.
-
- Note that we are not as aggressive as local-alloc in trying to tie a
- pseudo-register to a hard register. */
-
-static void
-set_preference (dest, src)
- rtx dest, src;
-{
- unsigned int src_regno, dest_regno;
- /* Amount to add to the hard regno for SRC, or subtract from that for DEST,
- to compensate for subregs in SRC or DEST. */
- int offset = 0;
- unsigned int i;
- int copy = 1;
-
- if (GET_RTX_FORMAT (GET_CODE (src))[0] == 'e')
- src = XEXP (src, 0), copy = 0;
-
- /* Get the reg number for both SRC and DEST.
- If neither is a reg, give up. */
-
- if (GET_CODE (src) == REG)
- src_regno = REGNO (src);
- else if (GET_CODE (src) == SUBREG && GET_CODE (SUBREG_REG (src)) == REG)
- {
- src_regno = REGNO (SUBREG_REG (src));
-
- if (REGNO (SUBREG_REG (src)) < FIRST_PSEUDO_REGISTER)
- offset += subreg_regno_offset (REGNO (SUBREG_REG (src)),
- GET_MODE (SUBREG_REG (src)),
- SUBREG_BYTE (src),
- GET_MODE (src));
- else
- offset += (SUBREG_BYTE (src)
- / REGMODE_NATURAL_SIZE (GET_MODE (src)));
- }
- else
- return;
-
- if (GET_CODE (dest) == REG)
- dest_regno = REGNO (dest);
- else if (GET_CODE (dest) == SUBREG && GET_CODE (SUBREG_REG (dest)) == REG)
- {
- dest_regno = REGNO (SUBREG_REG (dest));
-
- if (REGNO (SUBREG_REG (dest)) < FIRST_PSEUDO_REGISTER)
- offset -= subreg_regno_offset (REGNO (SUBREG_REG (dest)),
- GET_MODE (SUBREG_REG (dest)),
- SUBREG_BYTE (dest),
- GET_MODE (dest));
- else
- offset -= (SUBREG_BYTE (dest)
- / REGMODE_NATURAL_SIZE (GET_MODE (dest)));
- }
- else
- return;
-
- /* Convert either or both to hard reg numbers. */
-
- if (reg_renumber[src_regno] >= 0)
- src_regno = reg_renumber[src_regno];
-
- if (reg_renumber[dest_regno] >= 0)
- dest_regno = reg_renumber[dest_regno];
-
- /* Now if one is a hard reg and the other is a global pseudo
- then give the other a preference. */
-
- if (dest_regno < FIRST_PSEUDO_REGISTER && src_regno >= FIRST_PSEUDO_REGISTER
- && reg_allocno[src_regno] >= 0)
- {
- dest_regno -= offset;
- if (dest_regno < FIRST_PSEUDO_REGISTER)
- {
- if (copy)
- SET_REGBIT (hard_reg_copy_preferences,
- reg_allocno[src_regno], dest_regno);
-
- SET_REGBIT (hard_reg_preferences,
- reg_allocno[src_regno], dest_regno);
- for (i = dest_regno;
- i < dest_regno + HARD_REGNO_NREGS (dest_regno, GET_MODE (dest));
- i++)
- SET_REGBIT (hard_reg_full_preferences, reg_allocno[src_regno], i);
- }
- }
-
- if (src_regno < FIRST_PSEUDO_REGISTER && dest_regno >= FIRST_PSEUDO_REGISTER
- && reg_allocno[dest_regno] >= 0)
- {
- src_regno += offset;
- if (src_regno < FIRST_PSEUDO_REGISTER)
- {
- if (copy)
- SET_REGBIT (hard_reg_copy_preferences,
- reg_allocno[dest_regno], src_regno);
-
- SET_REGBIT (hard_reg_preferences,
- reg_allocno[dest_regno], src_regno);
- for (i = src_regno;
- i < src_regno + HARD_REGNO_NREGS (src_regno, GET_MODE (src));
- i++)
- SET_REGBIT (hard_reg_full_preferences, reg_allocno[dest_regno], i);
- }
- }
-}
-\f