X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Freload1.c;h=3eb20b02ff80bedb030ac556938c06babf153aae;hb=4c77974444cb8aad3524031282d4190346a6d0b5;hp=717489f3216c216612261e94abf991282f0123df;hpb=695ea1b4840c3fb18503754e29e1be6928d74482;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/reload1.c b/gcc/reload1.c index 717489f3216..3eb20b02ff8 100644 --- a/gcc/reload1.c +++ b/gcc/reload1.c @@ -1,6 +1,6 @@ /* Reload pseudo regs into hard regs for insns that require hard regs. Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. This file is part of GCC. @@ -77,10 +77,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA reload needs, spilling, assigning reload registers to use for fixing up each insn, and generating the new insns to copy values into the reload registers. */ - -#ifndef LOCAL_REGNO -#define LOCAL_REGNO(REGNO) 0 -#endif /* During reload_as_needed, element N contains a REG rtx for the hard reg into which reg N has been reloaded (perhaps for a previous insn). */ @@ -106,6 +102,10 @@ rtx *reg_equiv_constant; is transferred to either reg_equiv_address or reg_equiv_mem. */ rtx *reg_equiv_memory_loc; +/* We allocate reg_equiv_memory_loc inside a varray so that the garbage + collector can keep track of what is inside. */ +varray_type reg_equiv_memory_loc_varray; + /* Element N is the address of stack slot to which pseudo reg N is equivalent. This is used when the address is not valid as a memory address (because its displacement is too big for the machine.) */ @@ -142,6 +142,11 @@ static HARD_REG_SET reg_reloaded_valid; This is only valid if reg_reloaded_contents is set and valid. */ static HARD_REG_SET reg_reloaded_dead; +/* Indicate whether the register's current value is one that is not + safe to retain across a call, even for registers that are normally + call-saved. */ +static HARD_REG_SET reg_reloaded_call_part_clobbered; + /* Number of spill-regs so far; number of valid elements of spill_regs. */ static int n_spills; @@ -401,6 +406,7 @@ static int reload_reg_free_for_value_p (int, int, int, enum reload_type, rtx, rtx, int, int); static int free_for_value_p (int, enum machine_mode, int, enum reload_type, rtx, rtx, int, int); +static int function_invariant_p (rtx); static int reload_reg_reaches_end_p (unsigned int, int, enum reload_type); static int allocate_reload_reg (struct insn_chain *, int, int); static int conflicts_with_override (rtx); @@ -415,6 +421,7 @@ static void emit_output_reload_insns (struct insn_chain *, struct reload *, int); static void do_input_reload (struct insn_chain *, struct reload *, int); static void do_output_reload (struct insn_chain *, struct reload *, int); +static bool inherit_piecemeal_p (int, int); static void emit_reload_insns (struct insn_chain *); static void delete_output_reload (rtx, int, int); static void delete_address_reloads (rtx, rtx); @@ -479,6 +486,7 @@ init_reload (void) INIT_REG_SET (&spilled_pseudos); INIT_REG_SET (&pseudos_counted); + VARRAY_RTX_INIT (reg_equiv_memory_loc_varray, 0, "reg_equiv_memory_loc"); } /* List of insn chains that are currently unused. */ @@ -533,7 +541,7 @@ compute_use_by_pseudos (HARD_REG_SET *to, regset from) } else { - nregs = HARD_REGNO_NREGS (r, PSEUDO_REGNO_MODE (regno)); + nregs = hard_regno_nregs[r][PSEUDO_REGNO_MODE (regno)]; while (nregs-- > 0) SET_HARD_REG_BIT (*to, r + nregs); } @@ -576,7 +584,7 @@ replace_pseudos_in (rtx *loc, enum machine_mode mem_mode, rtx usage) *loc = reg_equiv_mem[regno]; else if (reg_equiv_address[regno]) *loc = gen_rtx_MEM (GET_MODE (x), reg_equiv_address[regno]); - else if (GET_CODE (regno_reg_rtx[regno]) != REG + else if (!REG_P (regno_reg_rtx[regno]) || REGNO (regno_reg_rtx[regno]) != regno) *loc = regno_reg_rtx[regno]; else @@ -673,6 +681,17 @@ reload (rtx first, int global) if (! call_used_regs[i] && ! fixed_regs[i] && ! LOCAL_REGNO (i)) regs_ever_live[i] = 1; +#ifdef NON_SAVING_SETJMP + /* A function that calls setjmp should save and restore all the + call-saved registers on a system where longjmp clobbers them. */ + if (NON_SAVING_SETJMP && current_function_calls_setjmp) + { + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) + if (! call_used_regs[i]) + regs_ever_live[i] = 1; + } +#endif + /* Find all the pseudo registers that didn't get hard regs but do have known equivalent constants or memory slots. These include parameters (known equivalent to parameter slots) @@ -695,12 +714,9 @@ reload (rtx first, int global) CLEAR_HARD_REG_SET (bad_spill_regs_global); - /* Look for REG_EQUIV notes; record what each pseudo is equivalent to. - Also find all paradoxical subregs and find largest such for each pseudo. - On machines with small register classes, record hard registers that - are used for user variables. These can never be used for spills. - Also look for a "constant" REG_SETJMP. This means that all - caller-saved registers must be marked live. */ + /* Look for REG_EQUIV notes; record what each pseudo is equivalent + to. Also find all paradoxical subregs and find largest such for + each pseudo. */ num_eliminable_invariants = 0; for (insn = first; insn; insn = NEXT_INSN (insn)) @@ -714,26 +730,17 @@ reload (rtx first, int global) && GET_MODE (insn) != VOIDmode) PUT_MODE (insn, VOIDmode); - if (GET_CODE (insn) == CALL_INSN - && find_reg_note (insn, REG_SETJMP, NULL)) - for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) - if (! call_used_regs[i]) - regs_ever_live[i] = 1; - - if (set != 0 && GET_CODE (SET_DEST (set)) == REG) + if (set != 0 && REG_P (SET_DEST (set))) { rtx note = find_reg_note (insn, REG_EQUIV, NULL_RTX); if (note -#ifdef LEGITIMATE_PIC_OPERAND_P && (! function_invariant_p (XEXP (note, 0)) || ! flag_pic /* A function invariant is often CONSTANT_P but may include a register. We promise to only pass CONSTANT_P objects to LEGITIMATE_PIC_OPERAND_P. */ || (CONSTANT_P (XEXP (note, 0)) - && LEGITIMATE_PIC_OPERAND_P (XEXP (note, 0)))) -#endif - ) + && LEGITIMATE_PIC_OPERAND_P (XEXP (note, 0))))) { rtx x = XEXP (note, 0); i = REGNO (SET_DEST (set)); @@ -783,7 +790,7 @@ reload (rtx first, int global) and the MEM is not SET_SRC, the equivalencing insn is one with the MEM as a SET_DEST and it occurs later. So don't mark this insn now. */ - if (GET_CODE (x) != MEM + if (!MEM_P (x) || rtx_equal_p (SET_SRC (set), x)) reg_equiv_init[i] = gen_rtx_INSN_LIST (VOIDmode, insn, reg_equiv_init[i]); @@ -793,8 +800,8 @@ reload (rtx first, int global) /* If this insn is setting a MEM from a register equivalent to it, this is the equivalencing insn. */ - else if (set && GET_CODE (SET_DEST (set)) == MEM - && GET_CODE (SET_SRC (set)) == REG + else if (set && MEM_P (SET_DEST (set)) + && REG_P (SET_SRC (set)) && reg_equiv_memory_loc[REGNO (SET_SRC (set))] && rtx_equal_p (SET_DEST (set), reg_equiv_memory_loc[REGNO (SET_SRC (set))])) @@ -832,8 +839,7 @@ reload (rtx first, int global) main reload loop in the most common case where register elimination cannot be done. */ for (insn = first; insn && num_eliminable; insn = NEXT_INSN (insn)) - if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN - || GET_CODE (insn) == CALL_INSN) + if (INSN_P (insn)) note_stores (PATTERN (insn), mark_not_eliminable, NULL); maybe_fix_stack_asms (); @@ -846,9 +852,22 @@ reload (rtx first, int global) /* Spill any hard regs that we know we can't eliminate. */ CLEAR_HARD_REG_SET (used_spill_regs); - for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMINABLE_REGS]; ep++) - if (! ep->can_eliminate) - spill_hard_reg (ep->from, 1); + /* There can be multiple ways to eliminate a register; + they should be listed adjacently. + Elimination for any register fails only if all possible ways fail. */ + for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMINABLE_REGS]; ) + { + int from = ep->from; + int can_eliminate = 0; + do + { + can_eliminate |= ep->can_eliminate; + ep++; + } + while (ep < ®_eliminate[NUM_ELIMINABLE_REGS] && ep->from == from); + if (! can_eliminate) + spill_hard_reg (from, 1); + } #if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM if (frame_pointer_needed) @@ -915,10 +934,10 @@ reload (rtx first, int global) XEXP (x, 0))) reg_equiv_mem[i] = x, reg_equiv_address[i] = 0; else if (CONSTANT_P (XEXP (x, 0)) - || (GET_CODE (XEXP (x, 0)) == REG + || (REG_P (XEXP (x, 0)) && REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER) || (GET_CODE (XEXP (x, 0)) == PLUS - && GET_CODE (XEXP (XEXP (x, 0), 0)) == REG + && REG_P (XEXP (XEXP (x, 0), 0)) && (REGNO (XEXP (XEXP (x, 0), 0)) < FIRST_PSEUDO_REGISTER) && CONSTANT_P (XEXP (XEXP (x, 0), 1)))) @@ -1030,17 +1049,13 @@ reload (rtx first, int global) if an insn has a variable address, gets a REG_EH_REGION note added to it, and then gets converted into an load from a constant address. */ - if (GET_CODE (equiv_insn) == NOTE + if (NOTE_P (equiv_insn) || can_throw_internal (equiv_insn)) ; else if (reg_set_p (regno_reg_rtx[i], PATTERN (equiv_insn))) delete_dead_insn (equiv_insn); else - { - PUT_CODE (equiv_insn, NOTE); - NOTE_SOURCE_FILE (equiv_insn) = 0; - NOTE_LINE_NUMBER (equiv_insn) = NOTE_INSN_DELETED; - } + SET_INSN_DELETED (equiv_insn); } } } @@ -1143,7 +1158,7 @@ reload (rtx first, int global) { rtx *pnote; - if (GET_CODE (insn) == CALL_INSN) + if (CALL_P (insn)) replace_pseudos_in (& CALL_INSN_FUNCTION_USAGE (insn), VOIDmode, CALL_INSN_FUNCTION_USAGE (insn)); @@ -1152,12 +1167,12 @@ reload (rtx first, int global) && (GET_MODE (insn) == QImode || find_reg_note (insn, REG_EQUAL, NULL_RTX))) || (GET_CODE (PATTERN (insn)) == CLOBBER - && (GET_CODE (XEXP (PATTERN (insn), 0)) != MEM + && (!MEM_P (XEXP (PATTERN (insn), 0)) || GET_MODE (XEXP (PATTERN (insn), 0)) != BLKmode || (GET_CODE (XEXP (XEXP (PATTERN (insn), 0), 0)) != SCRATCH && XEXP (XEXP (PATTERN (insn), 0), 0) != stack_pointer_rtx)) - && (GET_CODE (XEXP (PATTERN (insn), 0)) != REG + && (!REG_P (XEXP (PATTERN (insn), 0)) || ! REG_FUNCTION_VALUE_P (XEXP (PATTERN (insn), 0))))) { delete_insn (insn); @@ -1218,8 +1233,7 @@ reload (rtx first, int global) if (reg_equiv_constant) free (reg_equiv_constant); reg_equiv_constant = 0; - if (reg_equiv_memory_loc) - free (reg_equiv_memory_loc); + VARRAY_GROW (reg_equiv_memory_loc_varray, 0); reg_equiv_memory_loc = 0; if (offsets_known_at) @@ -1249,6 +1263,14 @@ reload (rtx first, int global) by this, so unshare everything here. */ unshare_all_rtl_again (first); +#ifdef STACK_BOUNDARY + /* init_emit has set the alignment of the hard frame pointer + to STACK_BOUNDARY. It is very likely no longer valid if + the hard frame pointer was used for register allocation. */ + if (!frame_pointer_needed) + REGNO_POINTER_ALIGN (HARD_FRAME_POINTER_REGNUM) = BITS_PER_UNIT; +#endif + return failure; } @@ -1410,7 +1432,7 @@ calculate_needs_all_insns (int global) include REG_LABEL), we need to see what effects this has on the known offsets at labels. */ - if (GET_CODE (insn) == CODE_LABEL || GET_CODE (insn) == JUMP_INSN + if (LABEL_P (insn) || JUMP_P (insn) || (INSN_P (insn) && REG_NOTES (insn) != 0)) set_label_offsets (insn, insn, 0); @@ -1424,7 +1446,7 @@ calculate_needs_all_insns (int global) rtx set = single_set (insn); /* Skip insns that only set an equivalence. */ - if (set && GET_CODE (SET_DEST (set)) == REG + if (set && REG_P (SET_DEST (set)) && reg_renumber[REGNO (SET_DEST (set))] < 0 && reg_equiv_constant[REGNO (SET_DEST (set))]) continue; @@ -1449,7 +1471,7 @@ calculate_needs_all_insns (int global) rtx set = single_set (insn); if (set && SET_SRC (set) == SET_DEST (set) - && GET_CODE (SET_SRC (set)) == REG + && REG_P (SET_SRC (set)) && REGNO (SET_SRC (set)) >= FIRST_PSEUDO_REGISTER) { delete_insn (insn); @@ -1560,7 +1582,7 @@ count_pseudo (int reg) spill_add_cost[r] += freq; - nregs = HARD_REGNO_NREGS (r, PSEUDO_REGNO_MODE (reg)); + nregs = hard_regno_nregs[r][PSEUDO_REGNO_MODE (reg)]; while (nregs-- > 0) spill_cost[r + nregs] += freq; } @@ -1622,7 +1644,7 @@ static void count_spilled_pseudo (int spilled, int spilled_nregs, int reg) { int r = reg_renumber[reg]; - int nregs = HARD_REGNO_NREGS (r, PSEUDO_REGNO_MODE (reg)); + int nregs = hard_regno_nregs[r][PSEUDO_REGNO_MODE (reg)]; if (REGNO_REG_SET_P (&spilled_pseudos, reg) || spilled + spilled_nregs <= r || r + nregs <= spilled) @@ -1673,7 +1695,7 @@ find_reg (struct insn_chain *chain, int order) { int this_cost = spill_cost[regno]; int ok = 1; - unsigned int this_nregs = HARD_REGNO_NREGS (regno, rl->mode); + unsigned int this_nregs = hard_regno_nregs[regno][rl->mode]; for (j = 1; j < this_nregs; j++) { @@ -1684,9 +1706,9 @@ find_reg (struct insn_chain *chain, int order) } if (! ok) continue; - if (rl->in && GET_CODE (rl->in) == REG && REGNO (rl->in) == regno) + if (rl->in && REG_P (rl->in) && REGNO (rl->in) == regno) this_cost--; - if (rl->out && GET_CODE (rl->out) == REG && REGNO (rl->out) == regno) + if (rl->out && REG_P (rl->out) && REGNO (rl->out) == regno) this_cost--; if (this_cost < best_cost /* Among registers with equal cost, prefer caller-saved ones, or @@ -1709,10 +1731,10 @@ find_reg (struct insn_chain *chain, int order) if (best_reg == -1) return 0; - if (rtl_dump_file) - fprintf (rtl_dump_file, "Using reg %d for reload %d\n", best_reg, rnum); + if (dump_file) + fprintf (dump_file, "Using reg %d for reload %d\n", best_reg, rnum); - rl->nregs = HARD_REGNO_NREGS (best_reg, rl->mode); + rl->nregs = hard_regno_nregs[best_reg][rl->mode]; rl->regno = best_reg; EXECUTE_IF_SET_IN_REG_SET @@ -1760,7 +1782,7 @@ find_reload_regs (struct insn_chain *chain) int regno = REGNO (chain->rld[i].reg_rtx); chain->rld[i].regno = regno; chain->rld[i].nregs - = HARD_REGNO_NREGS (regno, GET_MODE (chain->rld[i].reg_rtx)); + = hard_regno_nregs[regno][GET_MODE (chain->rld[i].reg_rtx)]; } else chain->rld[i].regno = -1; @@ -1772,8 +1794,8 @@ find_reload_regs (struct insn_chain *chain) CLEAR_HARD_REG_SET (used_spill_regs_local); - if (rtl_dump_file) - fprintf (rtl_dump_file, "Spilling for insn %d.\n", INSN_UID (chain->insn)); + if (dump_file) + fprintf (dump_file, "Spilling for insn %d.\n", INSN_UID (chain->insn)); qsort (reload_order, n_reloads, sizeof (short), reload_reg_class_lower); @@ -1875,15 +1897,13 @@ delete_dead_insn (rtx insn) /* If the previous insn sets a register that dies in our insn, delete it too. */ if (prev && GET_CODE (PATTERN (prev)) == SET - && (prev_dest = SET_DEST (PATTERN (prev)), GET_CODE (prev_dest) == REG) + && (prev_dest = SET_DEST (PATTERN (prev)), REG_P (prev_dest)) && reg_mentioned_p (prev_dest, PATTERN (insn)) && find_regno_note (insn, REG_DEAD, REGNO (prev_dest)) && ! side_effects_p (SET_SRC (PATTERN (prev)))) delete_dead_insn (prev); - PUT_CODE (insn, NOTE); - NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED; - NOTE_SOURCE_FILE (insn) = 0; + SET_INSN_DELETED (insn); } /* Modify the home of pseudo-reg I. @@ -1904,7 +1924,7 @@ alter_reg (int i, int from_reg) /* If the reg got changed to a MEM at rtl-generation time, ignore it. */ - if (GET_CODE (regno_reg_rtx[i]) != REG) + if (!REG_P (regno_reg_rtx[i])) return; /* Modify the reg-rtx to contain the new hard reg @@ -2025,7 +2045,7 @@ alter_reg (int i, int from_reg) any copies of it, since otherwise when the stack slot is reused, nonoverlapping_memrefs_p might think they cannot overlap. */ - if (decl && GET_CODE (decl) == REG && REGNO (decl) == (unsigned) i) + if (decl && REG_P (decl) && REGNO (decl) == (unsigned) i) { if (from_reg != -1 && spill_stack_slot[from_reg] == x) x = copy_rtx (x); @@ -2050,7 +2070,7 @@ mark_home_live (int regno) i = reg_renumber[regno]; if (i < 0) return; - lim = i + HARD_REGNO_NREGS (i, PSEUDO_REGNO_MODE (regno)); + lim = i + hard_regno_nregs[i][PSEUDO_REGNO_MODE (regno)]; while (i < lim) regs_ever_live[i++] = 1; } @@ -2106,7 +2126,7 @@ set_label_offsets (rtx x, rtx insn, int initial_p) else if (x == insn && (tem = prev_nonnote_insn (insn)) != 0 - && GET_CODE (tem) == BARRIER) + && BARRIER_P (tem)) set_offsets_for_label (insn); else /* If neither of the above cases is true, compare each offset @@ -2258,15 +2278,6 @@ eliminate_regs (rtx x, enum machine_mode mem_mode, rtx insn) case RETURN: return x; - case ADDRESSOF: - /* This is only for the benefit of the debugging backends, which call - eliminate_regs on DECL_RTL; any ADDRESSOFs in the actual insns are - removed after CSE. */ - new = eliminate_regs (XEXP (x, 0), 0, insn); - if (GET_CODE (new) == MEM) - return XEXP (new, 0); - return x; - case REG: regno = REGNO (x); @@ -2295,7 +2306,7 @@ eliminate_regs (rtx x, enum machine_mode mem_mode, rtx insn) and require special code to handle code a reloaded PLUS operand. Also consider backends where the flags register is clobbered by a - MINUS, but we can emit a PLUS that does not clobber flags (ia32, + MINUS, but we can emit a PLUS that does not clobber flags (IA-32, lea instruction comes to mind). If we try to reload a MINUS, we may kill the flags register that was holding a useful value. @@ -2304,7 +2315,7 @@ eliminate_regs (rtx x, enum machine_mode mem_mode, rtx insn) case PLUS: /* If this is the sum of an eliminable register and a constant, rework the sum. */ - if (GET_CODE (XEXP (x, 0)) == REG + if (REG_P (XEXP (x, 0)) && REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER && CONSTANT_P (XEXP (x, 1))) { @@ -2353,13 +2364,13 @@ eliminate_regs (rtx x, enum machine_mode mem_mode, rtx insn) didn't get a hard register but has a reg_equiv_constant, we must replace the constant here since it may no longer be in the position of any operand. */ - if (GET_CODE (new0) == PLUS && GET_CODE (new1) == REG + if (GET_CODE (new0) == PLUS && REG_P (new1) && REGNO (new1) >= FIRST_PSEUDO_REGISTER && reg_renumber[REGNO (new1)] < 0 && reg_equiv_constant != 0 && reg_equiv_constant[REGNO (new1)] != 0) new1 = reg_equiv_constant[REGNO (new1)]; - else if (GET_CODE (new1) == PLUS && GET_CODE (new0) == REG + else if (GET_CODE (new1) == PLUS && REG_P (new0) && REGNO (new0) >= FIRST_PSEUDO_REGISTER && reg_renumber[REGNO (new0)] < 0 && reg_equiv_constant[REGNO (new0)] != 0) @@ -2384,7 +2395,7 @@ eliminate_regs (rtx x, enum machine_mode mem_mode, rtx insn) so that we have (plus (mult ..) ..). This is needed in order to keep load-address insns valid. This case is pathological. We ignore the possibility of overflow here. */ - if (GET_CODE (XEXP (x, 0)) == REG + if (REG_P (XEXP (x, 0)) && REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER && GET_CODE (XEXP (x, 1)) == CONST_INT) for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMINABLE_REGS]; @@ -2489,7 +2500,7 @@ eliminate_regs (rtx x, enum machine_mode mem_mode, rtx insn) pseudo didn't get a hard reg, we must replace this with the eliminated version of the memory location because push_reload may do the replacement in certain circumstances. */ - if (GET_CODE (SUBREG_REG (x)) == REG + if (REG_P (SUBREG_REG (x)) && (GET_MODE_SIZE (GET_MODE (x)) <= GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))) && reg_equiv_memory_loc != 0 @@ -2505,7 +2516,7 @@ eliminate_regs (rtx x, enum machine_mode mem_mode, rtx insn) int x_size = GET_MODE_SIZE (GET_MODE (x)); int new_size = GET_MODE_SIZE (GET_MODE (new)); - if (GET_CODE (new) == MEM + if (MEM_P (new) && ((x_size < new_size #ifdef WORD_REGISTER_OPERATIONS /* On these machines, combine can create rtl of the form @@ -2529,12 +2540,6 @@ eliminate_regs (rtx x, enum machine_mode mem_mode, rtx insn) return x; case MEM: - /* This is only for the benefit of the debugging backends, which call - eliminate_regs on DECL_RTL; any ADDRESSOFs in the actual insns are - removed after CSE. */ - if (GET_CODE (XEXP (x, 0)) == ADDRESSOF) - return eliminate_regs (XEXP (XEXP (x, 0), 0), 0, insn); - /* Our only special processing is to pass the mode of the MEM to our recursive call and copy the flags. While we are here, handle this case more efficiently. */ @@ -2633,9 +2638,6 @@ elimination_effects (rtx x, enum machine_mode mem_mode) case RETURN: return; - case ADDRESSOF: - abort (); - case REG: regno = REGNO (x); @@ -2708,7 +2710,7 @@ elimination_effects (rtx x, enum machine_mode mem_mode) return; case SUBREG: - if (GET_CODE (SUBREG_REG (x)) == REG + if (REG_P (SUBREG_REG (x)) && (GET_MODE_SIZE (GET_MODE (x)) <= GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))) && reg_equiv_memory_loc != 0 @@ -2742,7 +2744,7 @@ elimination_effects (rtx x, enum machine_mode mem_mode) case SET: /* Check for setting a register that we know about. */ - if (GET_CODE (SET_DEST (x)) == REG) + if (REG_P (SET_DEST (x))) { /* See if this is setting the replacement register for an elimination. @@ -2778,9 +2780,6 @@ elimination_effects (rtx x, enum machine_mode mem_mode) return; case MEM: - if (GET_CODE (XEXP (x, 0)) == ADDRESSOF) - abort (); - /* Our only special processing is to pass the mode of the MEM to our recursive call. */ elimination_effects (XEXP (x, 0), GET_MODE (x)); @@ -2822,7 +2821,7 @@ check_eliminable_occurrences (rtx x) struct elim_table *ep; for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMINABLE_REGS]; ep++) - if (ep->from_rtx == x && ep->can_eliminate) + if (ep->from_rtx == x) ep->can_eliminate = 0; return; } @@ -2867,6 +2866,7 @@ eliminate_regs_in_insn (rtx insn, int replace) rtx substed_operand[MAX_RECOG_OPERANDS]; rtx orig_operand[MAX_RECOG_OPERANDS]; struct elim_table *ep; + rtx plus_src; if (! insn_is_asm && icode < 0) { @@ -2879,7 +2879,7 @@ eliminate_regs_in_insn (rtx insn, int replace) abort (); } - if (old_set != 0 && GET_CODE (SET_DEST (old_set)) == REG + if (old_set != 0 && REG_P (SET_DEST (old_set)) && REGNO (SET_DEST (old_set)) < FIRST_PSEUDO_REGISTER) { /* Check for setting an eliminable register. */ @@ -2970,17 +2970,40 @@ eliminate_regs_in_insn (rtx insn, int replace) } /* We allow one special case which happens to work on all machines we - currently support: a single set with the source being a PLUS of an - eliminable register and a constant. */ - if (old_set - && GET_CODE (SET_DEST (old_set)) == REG - && GET_CODE (SET_SRC (old_set)) == PLUS - && GET_CODE (XEXP (SET_SRC (old_set), 0)) == REG - && GET_CODE (XEXP (SET_SRC (old_set), 1)) == CONST_INT - && REGNO (XEXP (SET_SRC (old_set), 0)) < FIRST_PSEUDO_REGISTER) + currently support: a single set with the source or a REG_EQUAL + note being a PLUS of an eliminable register and a constant. */ + plus_src = 0; + if (old_set && REG_P (SET_DEST (old_set))) { - rtx reg = XEXP (SET_SRC (old_set), 0); - HOST_WIDE_INT offset = INTVAL (XEXP (SET_SRC (old_set), 1)); + /* First see if the source is of the form (plus (reg) CST). */ + if (GET_CODE (SET_SRC (old_set)) == PLUS + && REG_P (XEXP (SET_SRC (old_set), 0)) + && GET_CODE (XEXP (SET_SRC (old_set), 1)) == CONST_INT + && REGNO (XEXP (SET_SRC (old_set), 0)) < FIRST_PSEUDO_REGISTER) + plus_src = SET_SRC (old_set); + else if (REG_P (SET_SRC (old_set))) + { + /* Otherwise, see if we have a REG_EQUAL note of the form + (plus (reg) CST). */ + rtx links; + for (links = REG_NOTES (insn); links; links = XEXP (links, 1)) + { + if (REG_NOTE_KIND (links) == REG_EQUAL + && GET_CODE (XEXP (links, 0)) == PLUS + && REG_P (XEXP (XEXP (links, 0), 0)) + && GET_CODE (XEXP (XEXP (links, 0), 1)) == CONST_INT + && REGNO (XEXP (XEXP (links, 0), 0)) < FIRST_PSEUDO_REGISTER) + { + plus_src = XEXP (links, 0); + break; + } + } + } + } + if (plus_src) + { + rtx reg = XEXP (plus_src, 0); + HOST_WIDE_INT offset = INTVAL (XEXP (plus_src, 1)); for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMINABLE_REGS]; ep++) if (ep->from_rtx == reg && ep->can_eliminate) @@ -3010,7 +3033,12 @@ eliminate_regs_in_insn (rtx insn, int replace) if (INSN_CODE (insn) < 0) abort (); } - else + /* If we have a nonzero offset, and the source is already + a simple REG, the following transformation would + increase the cost of the insn by replacing a simple REG + with (plus (reg sp) CST). So try only when plus_src + comes from old_set proper, not REG_NOTES. */ + else if (SET_SRC (old_set) == plus_src) { new_body = old_body; if (! replace) @@ -3025,6 +3053,9 @@ eliminate_regs_in_insn (rtx insn, int replace) XEXP (SET_SRC (old_set), 0) = ep->to_rtx; XEXP (SET_SRC (old_set), 1) = GEN_INT (offset); } + else + break; + val = 1; /* This can't have an effect on elimination offsets, so skip right to the end. */ @@ -3048,7 +3079,7 @@ eliminate_regs_in_insn (rtx insn, int replace) { /* Check for setting a register that we know about. */ if (recog_data.operand_type[i] != OP_IN - && GET_CODE (orig_operand[i]) == REG) + && REG_P (orig_operand[i])) { /* If we are assigning to a register that can be eliminated, it must be as part of a PARALLEL, since the code above handles @@ -3056,7 +3087,7 @@ eliminate_regs_in_insn (rtx insn, int replace) eliminate this reg. */ for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMINABLE_REGS]; ep++) - if (ep->from_rtx == orig_operand[i] && ep->can_eliminate) + if (ep->from_rtx == orig_operand[i]) ep->can_eliminate = 0; } @@ -3071,8 +3102,8 @@ eliminate_regs_in_insn (rtx insn, int replace) /* If an output operand changed from a REG to a MEM and INSN is an insn, write a CLOBBER insn. */ if (recog_data.operand_type[i] != OP_IN - && GET_CODE (orig_operand[i]) == REG - && GET_CODE (substed_operand[i]) == MEM + && REG_P (orig_operand[i]) + && MEM_P (substed_operand[i]) && replace) emit_insn_after (gen_rtx_CLOBBER (VOIDmode, orig_operand[i]), insn); @@ -3126,16 +3157,16 @@ eliminate_regs_in_insn (rtx insn, int replace) thing always? */ if (! insn_is_asm && old_set != 0 - && ((GET_CODE (SET_SRC (old_set)) == REG + && ((REG_P (SET_SRC (old_set)) && (GET_CODE (new_body) != SET - || GET_CODE (SET_SRC (new_body)) != REG)) + || !REG_P (SET_SRC (new_body)))) /* If this was a load from or store to memory, compare the MEM in recog_data.operand to the one in the insn. If they are not equal, then rerecognize the insn. */ || (old_set != 0 - && ((GET_CODE (SET_SRC (old_set)) == MEM + && ((MEM_P (SET_SRC (old_set)) && SET_SRC (old_set) != recog_data.operand[1]) - || (GET_CODE (SET_DEST (old_set)) == MEM + || (MEM_P (SET_DEST (old_set)) && SET_DEST (old_set) != recog_data.operand[0]))) /* If this was an add insn before, rerecognize. */ || GET_CODE (SET_SRC (old_set)) == PLUS)) @@ -3436,7 +3467,6 @@ init_elim_table (void) /* Does this function require a frame pointer? */ frame_pointer_needed = (! flag_omit_frame_pointer -#ifdef EXIT_IGNORE_STACK /* ?? If EXIT_IGNORE_STACK is set, we will not save and restore sp for alloca. So we can't eliminate the frame pointer in that case. At some point, @@ -3444,7 +3474,6 @@ init_elim_table (void) sp-adjusting insns for this case. */ || (current_function_calls_alloca && EXIT_IGNORE_STACK) -#endif || FRAME_POINTER_REQUIRED); num_eliminable = 0; @@ -3467,8 +3496,8 @@ init_elim_table (void) #endif /* Count the number of eliminable registers and build the FROM and TO - REG rtx's. Note that code in gen_rtx will cause, e.g., - gen_rtx (REG, Pmode, STACK_POINTER_REGNUM) to equal stack_pointer_rtx. + REG rtx's. Note that code in gen_rtx_REG will cause, e.g., + gen_rtx_REG (Pmode, STACK_POINTER_REGNUM) to equal stack_pointer_rtx. We depend on this. */ for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMINABLE_REGS]; ep++) { @@ -3506,8 +3535,8 @@ spill_hard_reg (unsigned int regno, int cant_eliminate) if (reg_renumber[i] >= 0 && (unsigned int) reg_renumber[i] <= regno && ((unsigned int) reg_renumber[i] - + HARD_REGNO_NREGS ((unsigned int) reg_renumber[i], - PSEUDO_REGNO_MODE (i)) + + hard_regno_nregs[(unsigned int) reg_renumber[i]] + [PSEUDO_REGNO_MODE (i)] > regno)) SET_REGNO_REG_SET (&spilled_pseudos, i); } @@ -3658,12 +3687,12 @@ finish_spills (int global) alter_reg (i, reg_old_renumber[i]); reg_old_renumber[i] = regno; - if (rtl_dump_file) + if (dump_file) { if (regno == -1) - fprintf (rtl_dump_file, " Register %d now on stack.\n\n", i); + fprintf (dump_file, " Register %d now on stack.\n\n", i); else - fprintf (rtl_dump_file, " Register %d now in %d.\n\n", + fprintf (dump_file, " Register %d now in %d.\n\n", i, reg_renumber[i]); } } @@ -3671,9 +3700,7 @@ finish_spills (int global) return something_changed; } -/* Find all paradoxical subregs within X and update reg_max_ref_width. - Also mark any hard registers used to store user variables as - forbidden from being used for spill registers. */ +/* Find all paradoxical subregs within X and update reg_max_ref_width. */ static void scan_paradoxical_subregs (rtx x) @@ -3685,13 +3712,6 @@ scan_paradoxical_subregs (rtx x) switch (code) { case REG: -#if 0 - if (SMALL_REGISTER_CLASSES && REGNO (x) < FIRST_PSEUDO_REGISTER - && REG_USERVAR_P (x)) - SET_HARD_REG_BIT (bad_spill_regs_global, REGNO (x)); -#endif - return; - case CONST_INT: case CONST: case SYMBOL_REF: @@ -3705,7 +3725,7 @@ scan_paradoxical_subregs (rtx x) return; case SUBREG: - if (GET_CODE (SUBREG_REG (x)) == REG + if (REG_P (SUBREG_REG (x)) && GET_MODE_SIZE (GET_MODE (x)) > GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))) reg_max_ref_width[REGNO (SUBREG_REG (x))] = GET_MODE_SIZE (GET_MODE (x)); @@ -3752,6 +3772,7 @@ reload_as_needed (int live_known) reg_last_reload_reg = xcalloc (max_regno, sizeof (rtx)); reg_has_output_reload = xmalloc (max_regno); CLEAR_HARD_REG_SET (reg_reloaded_valid); + CLEAR_HARD_REG_SET (reg_reloaded_call_part_clobbered); set_initial_elim_offsets (); @@ -3763,7 +3784,7 @@ reload_as_needed (int live_known) /* If we pass a label, copy the offsets from the label information into the current offsets of each elimination. */ - if (GET_CODE (insn) == CODE_LABEL) + if (LABEL_P (insn)) set_offsets_for_label (insn); else if (INSN_P (insn)) @@ -3775,7 +3796,7 @@ reload_as_needed (int live_known) if ((GET_CODE (PATTERN (insn)) == USE || GET_CODE (PATTERN (insn)) == CLOBBER) - && GET_CODE (XEXP (PATTERN (insn), 0)) == MEM) + && MEM_P (XEXP (PATTERN (insn), 0))) XEXP (XEXP (PATTERN (insn), 0), 0) = eliminate_regs (XEXP (XEXP (PATTERN (insn), 0), 0), GET_MODE (XEXP (PATTERN (insn), 0)), @@ -3786,7 +3807,7 @@ reload_as_needed (int live_known) if ((num_eliminable || num_eliminable_invariants) && chain->need_elim) { eliminate_regs_in_insn (insn, 1); - if (GET_CODE (insn) == NOTE) + if (NOTE_P (insn)) { update_eliminable_offsets (); continue; @@ -3876,7 +3897,7 @@ reload_as_needed (int live_known) /* There may have been CLOBBER insns placed after INSN. So scan between INSN and NEXT and use them to forget old reloads. */ for (x = NEXT_INSN (insn); x != old_next; x = NEXT_INSN (x)) - if (GET_CODE (x) == INSN && GET_CODE (PATTERN (x)) == CLOBBER) + if (NONJUMP_INSN_P (x) && GET_CODE (PATTERN (x)) == CLOBBER) note_stores (PATTERN (x), forget_old_reloads_1, NULL); #ifdef AUTO_INC_DEC @@ -3921,8 +3942,9 @@ reload_as_needed (int live_known) if (n == 1) { n = validate_replace_rtx (reload_reg, - gen_rtx (code, mode, - reload_reg), + gen_rtx_fmt_e (code, + mode, + reload_reg), p); /* We must also verify that the constraints @@ -3937,8 +3959,9 @@ reload_as_needed (int live_known) undo the replacement. */ if (!n) { - validate_replace_rtx (gen_rtx (code, mode, - reload_reg), + validate_replace_rtx (gen_rtx_fmt_e (code, + mode, + reload_reg), reload_reg, p); break; } @@ -3995,13 +4018,17 @@ reload_as_needed (int live_known) #endif } /* A reload reg's contents are unknown after a label. */ - if (GET_CODE (insn) == CODE_LABEL) + if (LABEL_P (insn)) CLEAR_HARD_REG_SET (reg_reloaded_valid); /* Don't assume a reload reg is still good after a call insn - if it is a call-used reg. */ - else if (GET_CODE (insn) == CALL_INSN) + if it is a call-used reg, or if it contains a value that will + be partially clobbered by the call. */ + else if (CALL_P (insn)) + { AND_COMPL_HARD_REG_SET (reg_reloaded_valid, call_used_reg_set); + AND_COMPL_HARD_REG_SET (reg_reloaded_valid, reg_reloaded_call_part_clobbered); + } } /* Clean up. */ @@ -4033,7 +4060,7 @@ forget_old_reloads_1 (rtx x, rtx ignored ATTRIBUTE_UNUSED, x = SUBREG_REG (x); } - if (GET_CODE (x) != REG) + if (!REG_P (x)) return; regno = REGNO (x); @@ -4044,7 +4071,7 @@ forget_old_reloads_1 (rtx x, rtx ignored ATTRIBUTE_UNUSED, { unsigned int i; - nr = HARD_REGNO_NREGS (regno, GET_MODE (x)); + nr = hard_regno_nregs[regno][GET_MODE (x)]; /* Storing into a spilled-reg invalidates its contents. This can happen if a block-local pseudo is allocated to that reg and it wasn't spilled because this block's total need is 0. @@ -4056,6 +4083,7 @@ forget_old_reloads_1 (rtx x, rtx ignored ATTRIBUTE_UNUSED, || ! TEST_HARD_REG_BIT (reg_is_output_reload, regno + i)) { CLEAR_HARD_REG_BIT (reg_reloaded_valid, regno + i); + CLEAR_HARD_REG_BIT (reg_reloaded_call_part_clobbered, regno + i); spill_reg_store[regno + i] = 0; } } @@ -4117,7 +4145,7 @@ static void mark_reload_reg_in_use (unsigned int regno, int opnum, enum reload_type type, enum machine_mode mode) { - unsigned int nregs = HARD_REGNO_NREGS (regno, mode); + unsigned int nregs = hard_regno_nregs[regno][mode]; unsigned int i; for (i = regno; i < nregs + regno; i++) @@ -4179,7 +4207,7 @@ static void clear_reload_reg_in_use (unsigned int regno, int opnum, enum reload_type type, enum machine_mode mode) { - unsigned int nregs = HARD_REGNO_NREGS (regno, mode); + unsigned int nregs = hard_regno_nregs[regno][mode]; unsigned int start_regno, end_regno, r; int i; /* A complication is that for some reload types, inheritance might @@ -4263,7 +4291,7 @@ clear_reload_reg_in_use (unsigned int regno, int opnum, unsigned int conflict_start = true_regnum (rld[i].reg_rtx); unsigned int conflict_end = (conflict_start - + HARD_REGNO_NREGS (conflict_start, rld[i].mode)); + + hard_regno_nregs[conflict_start][rld[i].mode]); /* If there is an overlap with the first to-be-freed register, adjust the interval start. */ @@ -4300,6 +4328,7 @@ reload_reg_free_p (unsigned int regno, int opnum, enum reload_type type) /* In use for anything means we can't use it for RELOAD_OTHER. */ if (TEST_HARD_REG_BIT (reload_reg_used_in_other_addr, regno) || TEST_HARD_REG_BIT (reload_reg_used_in_op_addr, regno) + || TEST_HARD_REG_BIT (reload_reg_used_in_op_addr_reload, regno) || TEST_HARD_REG_BIT (reload_reg_used_in_insn, regno)) return 0; @@ -4478,6 +4507,7 @@ reload_reg_reaches_end_p (unsigned int regno, int opnum, enum reload_type type) return 0; return (! TEST_HARD_REG_BIT (reload_reg_used_in_op_addr, regno) + && ! TEST_HARD_REG_BIT (reload_reg_used_in_op_addr_reload, regno) && ! TEST_HARD_REG_BIT (reload_reg_used_in_insn, regno) && ! TEST_HARD_REG_BIT (reload_reg_used, regno)); @@ -4754,9 +4784,9 @@ reload_reg_free_for_value_p (int start_regno, int regno, int opnum, for (i = 0; i < n_reloads; i++) { rtx reg = rld[i].reg_rtx; - if (reg && GET_CODE (reg) == REG + if (reg && REG_P (reg) && ((unsigned) regno - true_regnum (reg) - <= HARD_REGNO_NREGS (REGNO (reg), GET_MODE (reg)) - (unsigned) 1) + <= hard_regno_nregs[REGNO (reg)][GET_MODE (reg)] - (unsigned) 1) && i != reloadnum) { rtx other_input = rld[i].in; @@ -4912,7 +4942,7 @@ free_for_value_p (int regno, enum machine_mode mode, int opnum, enum reload_type type, rtx value, rtx out, int reloadnum, int ignore_address_reloads) { - int nregs = HARD_REGNO_NREGS (regno, mode); + int nregs = hard_regno_nregs[regno][mode]; while (nregs-- > 0) if (! reload_reg_free_for_value_p (regno, regno + nregs, opnum, type, value, out, reloadnum, @@ -4921,6 +4951,27 @@ free_for_value_p (int regno, enum machine_mode mode, int opnum, return 1; } +/* Return nonzero if the rtx X is invariant over the current function. */ +/* ??? Actually, the places where we use this expect exactly what + * is tested here, and not everything that is function invariant. In + * particular, the frame pointer and arg pointer are special cased; + * pic_offset_table_rtx is not, and this will cause aborts when we + * go to spill these things to memory. */ + +static int +function_invariant_p (rtx x) +{ + if (CONSTANT_P (x)) + return 1; + if (x == frame_pointer_rtx || x == arg_pointer_rtx) + return 1; + if (GET_CODE (x) == PLUS + && (XEXP (x, 0) == frame_pointer_rtx || XEXP (x, 0) == arg_pointer_rtx) + && CONSTANT_P (XEXP (x, 1))) + return 1; + return 0; +} + /* Determine whether the reload reg X overlaps any rtx'es used for overriding inheritance. Return nonzero if so. */ @@ -5085,7 +5136,7 @@ allocate_reload_reg (struct insn_chain *chain ATTRIBUTE_UNUSED, int r, && ! TEST_HARD_REG_BIT (reload_reg_used_for_inherit, regnum)))) { - int nr = HARD_REGNO_NREGS (regnum, rld[r].mode); + int nr = hard_regno_nregs[regnum][rld[r].mode]; /* Avoid the problem where spilling a GENERAL_OR_FP_REG (on 68000) got us two FP regs. If NR is 1, we would reject both of them. */ @@ -5278,7 +5329,7 @@ choose_reload_regs (struct insn_chain *chain) if (rld[r].in != 0 && rld[r].reg_rtx != 0 && (rtx_equal_p (rld[r].in, rld[r].reg_rtx) || (rtx_equal_p (rld[r].out, rld[r].reg_rtx) - && GET_CODE (rld[r].in) != MEM + && !MEM_P (rld[r].in) && true_regnum (rld[r].in) < FIRST_PSEUDO_REGISTER))) continue; @@ -5320,18 +5371,18 @@ choose_reload_regs (struct insn_chain *chain) if (rld[r].in == 0) ; - else if (GET_CODE (rld[r].in) == REG) + else if (REG_P (rld[r].in)) { regno = REGNO (rld[r].in); mode = GET_MODE (rld[r].in); } - else if (GET_CODE (rld[r].in_reg) == REG) + else if (REG_P (rld[r].in_reg)) { regno = REGNO (rld[r].in_reg); mode = GET_MODE (rld[r].in_reg); } else if (GET_CODE (rld[r].in_reg) == SUBREG - && GET_CODE (SUBREG_REG (rld[r].in_reg)) == REG) + && REG_P (SUBREG_REG (rld[r].in_reg))) { byte = SUBREG_BYTE (rld[r].in_reg); regno = REGNO (SUBREG_REG (rld[r].in_reg)); @@ -5344,7 +5395,7 @@ choose_reload_regs (struct insn_chain *chain) || GET_CODE (rld[r].in_reg) == PRE_DEC || GET_CODE (rld[r].in_reg) == POST_INC || GET_CODE (rld[r].in_reg) == POST_DEC) - && GET_CODE (XEXP (rld[r].in_reg, 0)) == REG) + && REG_P (XEXP (rld[r].in_reg, 0))) { regno = REGNO (XEXP (rld[r].in_reg, 0)); mode = GET_MODE (XEXP (rld[r].in_reg, 0)); @@ -5356,7 +5407,7 @@ choose_reload_regs (struct insn_chain *chain) Also, it takes much more hair to keep track of all the things that can invalidate an inherited reload of part of a pseudoreg. */ else if (GET_CODE (rld[r].in) == SUBREG - && GET_CODE (SUBREG_REG (rld[r].in)) == REG) + && REG_P (SUBREG_REG (rld[r].in))) regno = subreg_regno (rld[r].in); #endif @@ -5418,7 +5469,7 @@ choose_reload_regs (struct insn_chain *chain) { /* If a group is needed, verify that all the subsequent registers still have their values intact. */ - int nr = HARD_REGNO_NREGS (i, rld[r].mode); + int nr = hard_regno_nregs[i][rld[r].mode]; int k; for (k = 1; k < nr; k++) @@ -5515,8 +5566,8 @@ choose_reload_regs (struct insn_chain *chain) && rld[r].out == 0 && (CONSTANT_P (rld[r].in) || GET_CODE (rld[r].in) == PLUS - || GET_CODE (rld[r].in) == REG - || GET_CODE (rld[r].in) == MEM) + || REG_P (rld[r].in) + || MEM_P (rld[r].in)) && (rld[r].nregs == max_group_size || ! reg_classes_intersect_p (rld[r].class, group_class))) search_equiv = rld[r].in; @@ -5541,7 +5592,7 @@ choose_reload_regs (struct insn_chain *chain) if (equiv != 0) { - if (GET_CODE (equiv) == REG) + if (REG_P (equiv)) regno = REGNO (equiv); else if (GET_CODE (equiv) == SUBREG) { @@ -5651,7 +5702,7 @@ choose_reload_regs (struct insn_chain *chain) && (regno != HARD_FRAME_POINTER_REGNUM || !frame_pointer_needed)) { - int nr = HARD_REGNO_NREGS (regno, rld[r].mode); + int nr = hard_regno_nregs[regno][rld[r].mode]; int k; rld[r].reg_rtx = equiv; reload_inherited[r] = 1; @@ -5790,7 +5841,7 @@ choose_reload_regs (struct insn_chain *chain) if (reload_inherited[r] && rld[r].reg_rtx) check_reg = rld[r].reg_rtx; else if (reload_override_in[r] - && (GET_CODE (reload_override_in[r]) == REG + && (REG_P (reload_override_in[r]) || GET_CODE (reload_override_in[r]) == SUBREG)) check_reg = reload_override_in[r]; else @@ -5859,21 +5910,21 @@ choose_reload_regs (struct insn_chain *chain) /* I is nonneg if this reload uses a register. If rld[r].reg_rtx is 0, this is an optional reload that we opted to ignore. */ - if (rld[r].out_reg != 0 && GET_CODE (rld[r].out_reg) == REG + if (rld[r].out_reg != 0 && REG_P (rld[r].out_reg) && rld[r].reg_rtx != 0) { int nregno = REGNO (rld[r].out_reg); int nr = 1; if (nregno < FIRST_PSEUDO_REGISTER) - nr = HARD_REGNO_NREGS (nregno, rld[r].mode); + nr = hard_regno_nregs[nregno][rld[r].mode]; while (--nr >= 0) reg_has_output_reload[nregno + nr] = 1; if (i >= 0) { - nr = HARD_REGNO_NREGS (i, rld[r].mode); + nr = hard_regno_nregs[i][rld[r].mode]; while (--nr >= 0) SET_HARD_REG_BIT (reg_is_output_reload, i + nr); } @@ -6129,8 +6180,8 @@ emit_input_reload_insns (struct insn_chain *chain, struct reload *rl, because we will use this equiv reg right away. */ if (oldequiv == 0 && optimize - && (GET_CODE (old) == MEM - || (GET_CODE (old) == REG + && (MEM_P (old) + || (REG_P (old) && REGNO (old) >= FIRST_PSEUDO_REGISTER && reg_renumber[REGNO (old)] < 0))) oldequiv = find_equiv_reg (old, insn, ALL_REGS, -1, NULL, 0, mode); @@ -6175,14 +6226,14 @@ emit_input_reload_insns (struct insn_chain *chain, struct reload *rl, find the pseudo in RELOAD_IN_REG. */ if (oldequiv == 0 && reload_override_in[j] - && GET_CODE (rl->in_reg) == REG) + && REG_P (rl->in_reg)) { oldequiv = old; old = rl->in_reg; } if (oldequiv == 0) oldequiv = old; - else if (GET_CODE (oldequiv) == REG) + else if (REG_P (oldequiv)) oldequiv_reg = oldequiv; else if (GET_CODE (oldequiv) == SUBREG) oldequiv_reg = SUBREG_REG (oldequiv); @@ -6191,10 +6242,10 @@ emit_input_reload_insns (struct insn_chain *chain, struct reload *rl, with an output-reload, see if we can prove there was actually no need to store the old value in it. */ - if (optimize && GET_CODE (oldequiv) == REG + if (optimize && REG_P (oldequiv) && REGNO (oldequiv) < FIRST_PSEUDO_REGISTER && spill_reg_store[REGNO (oldequiv)] - && GET_CODE (old) == REG + && REG_P (old) && (dead_or_set_p (insn, spill_reg_stored_to[REGNO (oldequiv)]) || rtx_equal_p (spill_reg_stored_to[REGNO (oldequiv)], rl->out_reg))) @@ -6264,10 +6315,10 @@ emit_input_reload_insns (struct insn_chain *chain, struct reload *rl, old = XEXP (rl->in_reg, 0); - if (optimize && GET_CODE (oldequiv) == REG + if (optimize && REG_P (oldequiv) && REGNO (oldequiv) < FIRST_PSEUDO_REGISTER && spill_reg_store[REGNO (oldequiv)] - && GET_CODE (old) == REG + && REG_P (old) && (dead_or_set_p (insn, spill_reg_stored_to[REGNO (oldequiv)]) || rtx_equal_p (spill_reg_stored_to[REGNO (oldequiv)], @@ -6286,7 +6337,7 @@ emit_input_reload_insns (struct insn_chain *chain, struct reload *rl, insn, see if we can get rid of that pseudo-register entirely by redirecting the previous insn into our reload register. */ - else if (optimize && GET_CODE (old) == REG + else if (optimize && REG_P (old) && REGNO (old) >= FIRST_PSEUDO_REGISTER && dead_or_set_p (insn, old) /* This is unsafe if some other reload @@ -6296,10 +6347,10 @@ emit_input_reload_insns (struct insn_chain *chain, struct reload *rl, rl->when_needed, old, rl->out, j, 0)) { rtx temp = PREV_INSN (insn); - while (temp && GET_CODE (temp) == NOTE) + while (temp && NOTE_P (temp)) temp = PREV_INSN (temp); if (temp - && GET_CODE (temp) == INSN + && NONJUMP_INSN_P (temp) && GET_CODE (PATTERN (temp)) == SET && SET_DEST (PATTERN (temp)) == old /* Make sure we can access insn_operand_constraint. */ @@ -6320,7 +6371,7 @@ emit_input_reload_insns (struct insn_chain *chain, struct reload *rl, a reload register, and its spill_reg_store entry will contain the previous destination. This is now invalid. */ - if (GET_CODE (SET_SRC (PATTERN (temp))) == REG + if (REG_P (SET_SRC (PATTERN (temp))) && REGNO (SET_SRC (PATTERN (temp))) < FIRST_PSEUDO_REGISTER) { spill_reg_store[REGNO (SET_SRC (PATTERN (temp)))] = 0; @@ -6383,7 +6434,7 @@ emit_input_reload_insns (struct insn_chain *chain, struct reload *rl, tmp = oldequiv; if (GET_CODE (tmp) == SUBREG) tmp = SUBREG_REG (tmp); - if (GET_CODE (tmp) == REG + if (REG_P (tmp) && REGNO (tmp) >= FIRST_PSEUDO_REGISTER && (reg_equiv_memory_loc[REGNO (tmp)] != 0 || reg_equiv_constant[REGNO (tmp)] != 0)) @@ -6399,7 +6450,7 @@ emit_input_reload_insns (struct insn_chain *chain, struct reload *rl, tmp = old; if (GET_CODE (tmp) == SUBREG) tmp = SUBREG_REG (tmp); - if (GET_CODE (tmp) == REG + if (REG_P (tmp) && REGNO (tmp) >= FIRST_PSEUDO_REGISTER && (reg_equiv_memory_loc[REGNO (tmp)] != 0 || reg_equiv_constant[REGNO (tmp)] != 0)) @@ -6509,12 +6560,12 @@ emit_input_reload_insns (struct insn_chain *chain, struct reload *rl, { rtx real_oldequiv = oldequiv; - if ((GET_CODE (oldequiv) == REG + if ((REG_P (oldequiv) && REGNO (oldequiv) >= FIRST_PSEUDO_REGISTER && (reg_equiv_memory_loc[REGNO (oldequiv)] != 0 || reg_equiv_constant[REGNO (oldequiv)] != 0)) || (GET_CODE (oldequiv) == SUBREG - && GET_CODE (SUBREG_REG (oldequiv)) == REG + && REG_P (SUBREG_REG (oldequiv)) && (REGNO (SUBREG_REG (oldequiv)) >= FIRST_PSEUDO_REGISTER) && ((reg_equiv_memory_loc @@ -6589,7 +6640,7 @@ emit_output_reload_insns (struct insn_chain *chain, struct reload *rl, { rtx real_old = old; - if (GET_CODE (old) == REG && REGNO (old) >= FIRST_PSEUDO_REGISTER + if (REG_P (old) && REGNO (old) >= FIRST_PSEUDO_REGISTER && reg_equiv_mem[REGNO (old)] != 0) real_old = reg_equiv_mem[REGNO (old)]; @@ -6667,7 +6718,7 @@ emit_output_reload_insns (struct insn_chain *chain, struct reload *rl, /* Don't output the last reload if OLD is not the dest of INSN and is in the src and is clobbered by INSN. */ if (! flag_expensive_optimizations - || GET_CODE (old) != REG + || !REG_P (old) || !(set = single_set (insn)) || rtx_equal_p (old, SET_DEST (set)) || !reg_mentioned_p (old, SET_SRC (set)) @@ -6761,7 +6812,7 @@ static void do_input_reload (struct insn_chain *chain, struct reload *rl, int j) { rtx insn = chain->insn; - rtx old = (rl->in && GET_CODE (rl->in) == MEM + rtx old = (rl->in && MEM_P (rl->in) ? rl->in_reg : rl->in); if (old != 0 @@ -6776,8 +6827,8 @@ do_input_reload (struct insn_chain *chain, struct reload *rl, int j) e.g. inheriting a SImode output reload for (mem:HI (plus:SI (reg:SI 14 fp) (const_int 10))) */ if (optimize && reload_inherited[j] && rl->in - && GET_CODE (rl->in) == MEM - && GET_CODE (rl->in_reg) == MEM + && MEM_P (rl->in) + && MEM_P (rl->in_reg) && reload_spill_index[j] >= 0 && TEST_HARD_REG_BIT (reg_reloaded_valid, reload_spill_index[j])) rl->in = regno_reg_rtx[reg_reloaded_contents[reload_spill_index[j]]]; @@ -6789,7 +6840,7 @@ do_input_reload (struct insn_chain *chain, struct reload *rl, int j) if (optimize && (reload_inherited[j] || reload_override_in[j]) && rl->reg_rtx - && GET_CODE (rl->reg_rtx) == REG + && REG_P (rl->reg_rtx) && spill_reg_store[REGNO (rl->reg_rtx)] != 0 #if 0 /* There doesn't seem to be any reason to restrict this to pseudos @@ -6824,7 +6875,7 @@ do_output_reload (struct insn_chain *chain, struct reload *rl, int j) if (pseudo && optimize - && GET_CODE (pseudo) == REG + && REG_P (pseudo) && ! rtx_equal_p (rl->in_reg, pseudo) && REGNO (pseudo) >= FIRST_PSEUDO_REGISTER && reg_last_reload_reg[REGNO (pseudo)]) @@ -6851,7 +6902,7 @@ do_output_reload (struct insn_chain *chain, struct reload *rl, int j) /* An output operand that dies right away does need a reload, but need not be copied from it. Show the new location in the REG_UNUSED note. */ - if ((GET_CODE (old) == REG || GET_CODE (old) == SCRATCH) + if ((REG_P (old) || GET_CODE (old) == SCRATCH) && (note = find_reg_note (insn, REG_UNUSED, old)) != 0) { XEXP (note, 0) = rl->reg_rtx; @@ -6859,7 +6910,7 @@ do_output_reload (struct insn_chain *chain, struct reload *rl, int j) } /* Likewise for a SUBREG of an operand that dies. */ else if (GET_CODE (old) == SUBREG - && GET_CODE (SUBREG_REG (old)) == REG + && REG_P (SUBREG_REG (old)) && 0 != (note = find_reg_note (insn, REG_UNUSED, SUBREG_REG (old)))) { @@ -6873,12 +6924,33 @@ do_output_reload (struct insn_chain *chain, struct reload *rl, int j) return; /* If is a JUMP_INSN, we can't support output reloads yet. */ - if (GET_CODE (insn) == JUMP_INSN) + if (JUMP_P (insn)) abort (); emit_output_reload_insns (chain, rld + j, j); } +/* Reload number R reloads from or to a group of hard registers starting at + register REGNO. Return true if it can be treated for inheritance purposes + like a group of reloads, each one reloading a single hard register. + The caller has already checked that the spill register and REGNO use + the same number of registers to store the reload value. */ + +static bool +inherit_piecemeal_p (int r ATTRIBUTE_UNUSED, int regno ATTRIBUTE_UNUSED) +{ +#ifdef CANNOT_CHANGE_MODE_CLASS + return (!REG_CANNOT_CHANGE_MODE_P (reload_spill_index[r], + GET_MODE (rld[r].reg_rtx), + reg_raw_mode[reload_spill_index[r]]) + && !REG_CANNOT_CHANGE_MODE_P (regno, + GET_MODE (rld[r].reg_rtx), + reg_raw_mode[regno])); +#else + return true; +#endif +} + /* Output insns to reload values in and out of the chosen reload regs. */ static void @@ -6902,10 +6974,10 @@ emit_reload_insns (struct insn_chain *chain) other_operand_reload_insns = 0; /* Dump reloads into the dump file. */ - if (rtl_dump_file) + if (dump_file) { - fprintf (rtl_dump_file, "\nReloads for insn # %d\n", INSN_UID (insn)); - debug_reload_to_stream (rtl_dump_file); + fprintf (dump_file, "\nReloads for insn # %d\n", INSN_UID (insn)); + debug_reload_to_stream (dump_file); } /* Now output the instructions to copy the data into and out of the @@ -6947,25 +7019,25 @@ emit_reload_insns (struct insn_chain *chain) reloads for the operand. The RELOAD_OTHER output reloads are output in descending order by reload number. */ - emit_insn_before (other_input_address_reload_insns, insn); - emit_insn_before (other_input_reload_insns, insn); + emit_insn_before_sameloc (other_input_address_reload_insns, insn); + emit_insn_before_sameloc (other_input_reload_insns, insn); for (j = 0; j < reload_n_operands; j++) { - emit_insn_before (inpaddr_address_reload_insns[j], insn); - emit_insn_before (input_address_reload_insns[j], insn); - emit_insn_before (input_reload_insns[j], insn); + emit_insn_before_sameloc (inpaddr_address_reload_insns[j], insn); + emit_insn_before_sameloc (input_address_reload_insns[j], insn); + emit_insn_before_sameloc (input_reload_insns[j], insn); } - emit_insn_before (other_operand_reload_insns, insn); - emit_insn_before (operand_reload_insns, insn); + emit_insn_before_sameloc (other_operand_reload_insns, insn); + emit_insn_before_sameloc (operand_reload_insns, insn); for (j = 0; j < reload_n_operands; j++) { - rtx x = emit_insn_after (outaddr_address_reload_insns[j], insn); - x = emit_insn_after (output_address_reload_insns[j], x); - x = emit_insn_after (output_reload_insns[j], x); - emit_insn_after (other_output_reload_insns[j], x); + rtx x = emit_insn_after_sameloc (outaddr_address_reload_insns[j], insn); + x = emit_insn_after_sameloc (output_address_reload_insns[j], x); + x = emit_insn_after_sameloc (output_reload_insns[j], x); + emit_insn_after_sameloc (other_output_reload_insns[j], x); } /* For all the spill regs newly reloaded in this instruction, @@ -6992,7 +7064,7 @@ emit_reload_insns (struct insn_chain *chain) if (GET_CODE (reg) == SUBREG) reg = SUBREG_REG (reg); - if (GET_CODE (reg) == REG + if (REG_P (reg) && REGNO (reg) >= FIRST_PSEUDO_REGISTER && ! reg_has_output_reload[REGNO (reg)]) { @@ -7014,7 +7086,7 @@ emit_reload_insns (struct insn_chain *chain) if (i >= 0 && rld[r].reg_rtx != 0) { - int nr = HARD_REGNO_NREGS (i, GET_MODE (rld[r].reg_rtx)); + int nr = hard_regno_nregs[i][GET_MODE (rld[r].reg_rtx)]; int k; int part_reaches_end = 0; int all_reaches_end = 1; @@ -7038,30 +7110,38 @@ emit_reload_insns (struct insn_chain *chain) If consecutive registers are used, clear them all. */ for (k = 0; k < nr; k++) + { CLEAR_HARD_REG_BIT (reg_reloaded_valid, i + k); + CLEAR_HARD_REG_BIT (reg_reloaded_call_part_clobbered, i + k); + } /* Maybe the spill reg contains a copy of reload_out. */ if (rld[r].out != 0 - && (GET_CODE (rld[r].out) == REG + && (REG_P (rld[r].out) #ifdef AUTO_INC_DEC || ! rld[r].out_reg #endif - || GET_CODE (rld[r].out_reg) == REG)) + || REG_P (rld[r].out_reg))) { - rtx out = (GET_CODE (rld[r].out) == REG + rtx out = (REG_P (rld[r].out) ? rld[r].out : rld[r].out_reg ? rld[r].out_reg /* AUTO_INC */ : XEXP (rld[r].in_reg, 0)); int nregno = REGNO (out); int nnr = (nregno >= FIRST_PSEUDO_REGISTER ? 1 - : HARD_REGNO_NREGS (nregno, - GET_MODE (rld[r].reg_rtx))); + : hard_regno_nregs[nregno] + [GET_MODE (rld[r].reg_rtx)]); + bool piecemeal; spill_reg_store[i] = new_spill_reg_store[i]; spill_reg_stored_to[i] = out; reg_last_reload_reg[nregno] = rld[r].reg_rtx; + piecemeal = (nregno < FIRST_PSEUDO_REGISTER + && nr == nnr + && inherit_piecemeal_p (r, nregno)); + /* If NREGNO is a hard register, it may occupy more than one register. If it does, say what is in the rest of the registers assuming that both registers @@ -7071,7 +7151,7 @@ emit_reload_insns (struct insn_chain *chain) if (nregno < FIRST_PSEUDO_REGISTER) for (k = 1; k < nnr; k++) reg_last_reload_reg[nregno + k] - = (nr == nnr + = (piecemeal ? regno_reg_rtx[REGNO (rld[r].reg_rtx) + k] : 0); @@ -7080,11 +7160,13 @@ emit_reload_insns (struct insn_chain *chain) { CLEAR_HARD_REG_BIT (reg_reloaded_dead, i + k); reg_reloaded_contents[i + k] - = (nregno >= FIRST_PSEUDO_REGISTER || nr != nnr + = (nregno >= FIRST_PSEUDO_REGISTER || !piecemeal ? nregno : nregno + k); reg_reloaded_insn[i + k] = insn; SET_HARD_REG_BIT (reg_reloaded_valid, i + k); + if (HARD_REGNO_CALL_PART_CLOBBERED (i + k, GET_MODE (out))) + SET_HARD_REG_BIT (reg_reloaded_call_part_clobbered, i + k); } } @@ -7093,34 +7175,41 @@ emit_reload_insns (struct insn_chain *chain) the register being reloaded. */ else if (rld[r].out_reg == 0 && rld[r].in != 0 - && ((GET_CODE (rld[r].in) == REG + && ((REG_P (rld[r].in) && REGNO (rld[r].in) >= FIRST_PSEUDO_REGISTER && ! reg_has_output_reload[REGNO (rld[r].in)]) - || (GET_CODE (rld[r].in_reg) == REG + || (REG_P (rld[r].in_reg) && ! reg_has_output_reload[REGNO (rld[r].in_reg)])) && ! reg_set_p (rld[r].reg_rtx, PATTERN (insn))) { int nregno; int nnr; + rtx in; + bool piecemeal; - if (GET_CODE (rld[r].in) == REG + if (REG_P (rld[r].in) && REGNO (rld[r].in) >= FIRST_PSEUDO_REGISTER) - nregno = REGNO (rld[r].in); - else if (GET_CODE (rld[r].in_reg) == REG) - nregno = REGNO (rld[r].in_reg); + in = rld[r].in; + else if (REG_P (rld[r].in_reg)) + in = rld[r].in_reg; else - nregno = REGNO (XEXP (rld[r].in_reg, 0)); + in = XEXP (rld[r].in_reg, 0); + nregno = REGNO (in); nnr = (nregno >= FIRST_PSEUDO_REGISTER ? 1 - : HARD_REGNO_NREGS (nregno, - GET_MODE (rld[r].reg_rtx))); + : hard_regno_nregs[nregno] + [GET_MODE (rld[r].reg_rtx)]); reg_last_reload_reg[nregno] = rld[r].reg_rtx; + piecemeal = (nregno < FIRST_PSEUDO_REGISTER + && nr == nnr + && inherit_piecemeal_p (r, nregno)); + if (nregno < FIRST_PSEUDO_REGISTER) for (k = 1; k < nnr; k++) reg_last_reload_reg[nregno + k] - = (nr == nnr + = (piecemeal ? regno_reg_rtx[REGNO (rld[r].reg_rtx) + k] : 0); @@ -7136,11 +7225,13 @@ emit_reload_insns (struct insn_chain *chain) { CLEAR_HARD_REG_BIT (reg_reloaded_dead, i + k); reg_reloaded_contents[i + k] - = (nregno >= FIRST_PSEUDO_REGISTER || nr != nnr + = (nregno >= FIRST_PSEUDO_REGISTER || !piecemeal ? nregno : nregno + k); reg_reloaded_insn[i + k] = insn; SET_HARD_REG_BIT (reg_reloaded_valid, i + k); + if (HARD_REGNO_CALL_PART_CLOBBERED (i + k, GET_MODE (in))) + SET_HARD_REG_BIT (reg_reloaded_call_part_clobbered, i + k); } } } @@ -7166,11 +7257,11 @@ emit_reload_insns (struct insn_chain *chain) But forget_old_reloads_1 won't get to see it, because it thinks only about the original insn. So invalidate it here. */ if (i < 0 && rld[r].out != 0 - && (GET_CODE (rld[r].out) == REG - || (GET_CODE (rld[r].out) == MEM - && GET_CODE (rld[r].out_reg) == REG))) + && (REG_P (rld[r].out) + || (MEM_P (rld[r].out) + && REG_P (rld[r].out_reg)))) { - rtx out = (GET_CODE (rld[r].out) == REG + rtx out = (REG_P (rld[r].out) ? rld[r].out : rld[r].out_reg); int nregno = REGNO (out); if (nregno >= FIRST_PSEUDO_REGISTER) @@ -7207,11 +7298,11 @@ emit_reload_insns (struct insn_chain *chain) } else store_insn = new_spill_reg_store[REGNO (src_reg)]; - if (src_reg && GET_CODE (src_reg) == REG + if (src_reg && REG_P (src_reg) && REGNO (src_reg) < FIRST_PSEUDO_REGISTER) { int src_regno = REGNO (src_reg); - int nr = HARD_REGNO_NREGS (src_regno, rld[r].mode); + int nr = hard_regno_nregs[src_regno][rld[r].mode]; /* The place where to find a death note varies with PRESERVE_DEATH_INFO_REGNO_P . The condition is not necessarily checked exactly in the code that moves @@ -7227,6 +7318,10 @@ emit_reload_insns (struct insn_chain *chain) reg_reloaded_insn[src_regno + nr] = store_insn; CLEAR_HARD_REG_BIT (reg_reloaded_dead, src_regno + nr); SET_HARD_REG_BIT (reg_reloaded_valid, src_regno + nr); + if (HARD_REGNO_CALL_PART_CLOBBERED (src_regno + nr, + GET_MODE (src_reg))) + SET_HARD_REG_BIT (reg_reloaded_call_part_clobbered, + src_regno + nr); SET_HARD_REG_BIT (reg_is_output_reload, src_regno + nr); if (note) SET_HARD_REG_BIT (reg_reloaded_died, src_regno); @@ -7234,11 +7329,15 @@ emit_reload_insns (struct insn_chain *chain) CLEAR_HARD_REG_BIT (reg_reloaded_died, src_regno); } reg_last_reload_reg[nregno] = src_reg; + /* We have to set reg_has_output_reload here, or else + forget_old_reloads_1 will clear reg_last_reload_reg + right away. */ + reg_has_output_reload[nregno] = 1; } } else { - int num_regs = HARD_REGNO_NREGS (nregno, GET_MODE (rld[r].out)); + int num_regs = hard_regno_nregs[nregno][GET_MODE (rld[r].out)]; while (num_regs-- > 0) reg_last_reload_reg[nregno + num_regs] = 0; @@ -7300,13 +7399,13 @@ gen_reload (rtx out, rtx in, int opnum, enum reload_type type) ??? At some point, this whole thing needs to be rethought. */ if (GET_CODE (in) == PLUS - && (GET_CODE (XEXP (in, 0)) == REG + && (REG_P (XEXP (in, 0)) || GET_CODE (XEXP (in, 0)) == SUBREG - || GET_CODE (XEXP (in, 0)) == MEM) - && (GET_CODE (XEXP (in, 1)) == REG + || MEM_P (XEXP (in, 0))) + && (REG_P (XEXP (in, 1)) || GET_CODE (XEXP (in, 1)) == SUBREG || CONSTANT_P (XEXP (in, 1)) - || GET_CODE (XEXP (in, 1)) == MEM)) + || MEM_P (XEXP (in, 1)))) { /* We need to compute the sum of a register or a MEM and another register, constant, or MEM, and put it into the reload @@ -7334,7 +7433,7 @@ gen_reload (rtx out, rtx in, int opnum, enum reload_type type) the case. If the insn would be A = B + A, rearrange it so it will be A = A + B as constrain_operands expects. */ - if (GET_CODE (XEXP (in, 1)) == REG + if (REG_P (XEXP (in, 1)) && REGNO (out) == REGNO (XEXP (in, 1))) tem = op0, op0 = op1, op1 = tem; @@ -7373,8 +7472,8 @@ gen_reload (rtx out, rtx in, int opnum, enum reload_type type) code = (int) add_optab->handlers[(int) GET_MODE (out)].insn_code; - if (CONSTANT_P (op1) || GET_CODE (op1) == MEM || GET_CODE (op1) == SUBREG - || (GET_CODE (op1) == REG + if (CONSTANT_P (op1) || MEM_P (op1) || GET_CODE (op1) == SUBREG + || (REG_P (op1) && REGNO (op1) >= FIRST_PSEUDO_REGISTER) || (code != CODE_FOR_nothing && ! ((*insn_data[code].operand[2].predicate) @@ -7421,9 +7520,9 @@ gen_reload (rtx out, rtx in, int opnum, enum reload_type type) #ifdef SECONDARY_MEMORY_NEEDED /* If we need a memory location to do the move, do it that way. */ - else if ((GET_CODE (in) == REG || GET_CODE (in) == SUBREG) + else if ((REG_P (in) || GET_CODE (in) == SUBREG) && reg_or_subregno (in) < FIRST_PSEUDO_REGISTER - && (GET_CODE (out) == REG || GET_CODE (out) == SUBREG) + && (REG_P (out) || GET_CODE (out) == SUBREG) && reg_or_subregno (out) < FIRST_PSEUDO_REGISTER && SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (reg_or_subregno (in)), REGNO_REG_CLASS (reg_or_subregno (out)), @@ -7444,7 +7543,7 @@ gen_reload (rtx out, rtx in, int opnum, enum reload_type type) #endif /* If IN is a simple operand, use gen_move_insn. */ - else if (GET_RTX_CLASS (GET_CODE (in)) == 'o' || GET_CODE (in) == SUBREG) + else if (OBJECT_P (in) || GET_CODE (in) == SUBREG) emit_insn (gen_move_insn (out, in)); #ifdef HAVE_reload_load_address @@ -7503,7 +7602,7 @@ delete_output_reload (rtx insn, int j, int last_reload_reg) rtx reg2 = rld[k].in; if (! reg2) continue; - if (GET_CODE (reg2) == MEM || reload_override_in[k]) + if (MEM_P (reg2) || reload_override_in[k]) reg2 = rld[k].in_reg; #ifdef AUTO_INC_DEC if (rld[k].out && ! rld[k].out_reg) @@ -7544,14 +7643,14 @@ delete_output_reload (rtx insn, int j, int last_reload_reg) for (i1 = NEXT_INSN (output_reload_insn); i1 != insn; i1 = NEXT_INSN (i1)) { - if (GET_CODE (i1) == CODE_LABEL || GET_CODE (i1) == JUMP_INSN) + if (LABEL_P (i1) || JUMP_P (i1)) return; - if ((GET_CODE (i1) == INSN || GET_CODE (i1) == CALL_INSN) + if ((NONJUMP_INSN_P (i1) || CALL_P (i1)) && reg_mentioned_p (reg, PATTERN (i1))) { /* If this is USE in front of INSN, we only have to check that there are no more references than accounted for by inheritance. */ - while (GET_CODE (i1) == INSN && GET_CODE (PATTERN (i1)) == USE) + while (NONJUMP_INSN_P (i1) && GET_CODE (PATTERN (i1)) == USE) { n_occurrences += rtx_equal_p (reg, XEXP (PATTERN (i1), 0)) != 0; i1 = NEXT_INSN (i1); @@ -7563,7 +7662,7 @@ delete_output_reload (rtx insn, int j, int last_reload_reg) } /* We will be deleting the insn. Remove the spill reg information. */ - for (k = HARD_REGNO_NREGS (last_reload_reg, GET_MODE (reg)); k-- > 0; ) + for (k = hard_regno_nregs[last_reload_reg][GET_MODE (reg)]; k-- > 0; ) { spill_reg_store[last_reload_reg + k] = 0; spill_reg_stored_to[last_reload_reg + k] = 0; @@ -7597,10 +7696,10 @@ delete_output_reload (rtx insn, int j, int last_reload_reg) since if they are the only uses, they are dead. */ if (set != 0 && SET_DEST (set) == reg) continue; - if (GET_CODE (i2) == CODE_LABEL - || GET_CODE (i2) == JUMP_INSN) + if (LABEL_P (i2) + || JUMP_P (i2)) break; - if ((GET_CODE (i2) == INSN || GET_CODE (i2) == CALL_INSN) + if ((NONJUMP_INSN_P (i2) || CALL_P (i2)) && reg_mentioned_p (reg, PATTERN (i2))) { /* Some other ref remains; just delete the output reload we @@ -7622,8 +7721,8 @@ delete_output_reload (rtx insn, int j, int last_reload_reg) delete_address_reloads (i2, insn); delete_insn (i2); } - if (GET_CODE (i2) == CODE_LABEL - || GET_CODE (i2) == JUMP_INSN) + if (LABEL_P (i2) + || JUMP_P (i2)) break; } @@ -7649,7 +7748,7 @@ delete_address_reloads (rtx dead_insn, rtx current_insn) if (set) { rtx dst = SET_DEST (set); - if (GET_CODE (dst) == MEM) + if (MEM_P (dst)) delete_address_reloads_1 (dead_insn, XEXP (dst, 0), current_insn); } /* If we deleted the store from a reloaded post_{in,de}c expression, @@ -7711,7 +7810,7 @@ delete_address_reloads_1 (rtx dead_insn, rtx x, rtx current_insn) code = GET_CODE (prev); if (code == CODE_LABEL || code == JUMP_INSN) return; - if (GET_RTX_CLASS (code) != 'i') + if (!INSN_P (prev)) continue; if (reg_set_p (x, PATTERN (prev))) break; @@ -7725,7 +7824,7 @@ delete_address_reloads_1 (rtx dead_insn, rtx x, rtx current_insn) if (! set) return; dst = SET_DEST (set); - if (GET_CODE (dst) != REG + if (!REG_P (dst) || ! rtx_equal_p (dst, x)) return; if (! reg_set_p (dst, PATTERN (dead_insn))) @@ -7734,7 +7833,7 @@ delete_address_reloads_1 (rtx dead_insn, rtx x, rtx current_insn) it might have been inherited. */ for (i2 = NEXT_INSN (dead_insn); i2; i2 = NEXT_INSN (i2)) { - if (GET_CODE (i2) == CODE_LABEL) + if (LABEL_P (i2)) break; if (! INSN_P (i2)) continue; @@ -7758,7 +7857,7 @@ delete_address_reloads_1 (rtx dead_insn, rtx x, rtx current_insn) } return; } - if (GET_CODE (i2) == JUMP_INSN) + if (JUMP_P (i2)) break; /* If DST is still live at CURRENT_INSN, check if it is used for any reload. Note that even if CURRENT_INSN sets DST, we still @@ -7813,7 +7912,7 @@ inc_for_reload (rtx reloadreg, rtx in, rtx value, int inc_amount) inc/dec operation. If REG_LAST_RELOAD_REG were nonzero, we could inc/dec that register as well (maybe even using it for the source), but I'm not sure it's worth worrying about. */ - if (GET_CODE (incloc) == REG) + if (REG_P (incloc)) reg_last_reload_reg[REGNO (incloc)] = 0; if (GET_CODE (value) == PRE_DEC || GET_CODE (value) == POST_DEC) @@ -7956,22 +8055,23 @@ fixup_abnormal_edges (void) == (EDGE_ABNORMAL | EDGE_EH)) break; } - if (e && GET_CODE (bb->end) != CALL_INSN && !can_throw_internal (bb->end)) + if (e && !CALL_P (BB_END (bb)) + && !can_throw_internal (BB_END (bb))) { - rtx insn = bb->end, stop = NEXT_INSN (bb->end); + rtx insn = BB_END (bb), stop = NEXT_INSN (BB_END (bb)); rtx next; for (e = bb->succ; e; e = e->succ_next) if (e->flags & EDGE_FALLTHRU) break; /* Get past the new insns generated. Allow notes, as the insns may be already deleted. */ - while ((GET_CODE (insn) == INSN || GET_CODE (insn) == NOTE) + while ((NONJUMP_INSN_P (insn) || NOTE_P (insn)) && !can_throw_internal (insn) - && insn != bb->head) + && insn != BB_HEAD (bb)) insn = PREV_INSN (insn); - if (GET_CODE (insn) != CALL_INSN && !can_throw_internal (insn)) + if (!CALL_P (insn) && !can_throw_internal (insn)) abort (); - bb->end = insn; + BB_END (bb) = insn; inserted = true; insn = NEXT_INSN (insn); while (insn && insn != stop)