📄 reload1.c
字号:
gen_rtx (REG, Pmode, FRAME_POINTER_REGNUM), gen_rtx (REG, Pmode, i)); /* This way, we make sure that reg+reg is an offsettable address. */ tem = plus_constant (tem, 4); if (memory_address_p (QImode, tem)) { double_reg_address_ok = 1; break; } } /* Initialize obstack for our rtl allocation. */ gcc_obstack_init (&reload_obstack); reload_firstobj = (char *) obstack_alloc (&reload_obstack, 0);#ifdef HAVE_SECONDARY_RELOADS /* Initialize the optabs for doing special input and output reloads. */ for (i = 0; i < NUM_MACHINE_MODES; i++) reload_in_optab[i] = reload_out_optab[i] = CODE_FOR_nothing;#ifdef HAVE_reload_inqi if (HAVE_reload_inqi) reload_in_optab[(int) QImode] = CODE_FOR_reload_inqi;#endif#ifdef HAVE_reload_inhi if (HAVE_reload_inhi) reload_in_optab[(int) HImode] = CODE_FOR_reload_inhi;#endif#ifdef HAVE_reload_insi if (HAVE_reload_insi) reload_in_optab[(int) SImode] = CODE_FOR_reload_insi;#endif#ifdef HAVE_reload_indi if (HAVE_reload_indi) reload_in_optab[(int) DImode] = CODE_FOR_reload_indi;#endif#ifdef HAVE_reload_inti if (HAVE_reload_inti) reload_in_optab[(int) TImode] = CODE_FOR_reload_inti;#endif#ifdef HAVE_reload_insf if (HAVE_reload_insf) reload_in_optab[(int) SFmode] = CODE_FOR_reload_insf;#endif#ifdef HAVE_reload_indf if (HAVE_reload_indf) reload_in_optab[(int) DFmode] = CODE_FOR_reload_indf;#endif#ifdef HAVE_reload_inxf if (HAVE_reload_inxf) reload_in_optab[(int) XFmode] = CODE_FOR_reload_inxf;#endif#ifdef HAVE_reload_intf if (HAVE_reload_intf) reload_in_optab[(int) TFmode] = CODE_FOR_reload_intf;#endif#ifdef HAVE_reload_outqi if (HAVE_reload_outqi) reload_out_optab[(int) QImode] = CODE_FOR_reload_outqi;#endif#ifdef HAVE_reload_outhi if (HAVE_reload_outhi) reload_out_optab[(int) HImode] = CODE_FOR_reload_outhi;#endif#ifdef HAVE_reload_outsi if (HAVE_reload_outsi) reload_out_optab[(int) SImode] = CODE_FOR_reload_outsi;#endif#ifdef HAVE_reload_outdi if (HAVE_reload_outdi) reload_out_optab[(int) DImode] = CODE_FOR_reload_outdi;#endif#ifdef HAVE_reload_outti if (HAVE_reload_outti) reload_out_optab[(int) TImode] = CODE_FOR_reload_outti;#endif#ifdef HAVE_reload_outsf if (HAVE_reload_outsf) reload_out_optab[(int) SFmode] = CODE_FOR_reload_outsf;#endif#ifdef HAVE_reload_outdf if (HAVE_reload_outdf) reload_out_optab[(int) DFmode] = CODE_FOR_reload_outdf;#endif#ifdef HAVE_reload_outxf if (HAVE_reload_outxf) reload_out_optab[(int) XFmode] = CODE_FOR_reload_outxf;#endif#ifdef HAVE_reload_outtf if (HAVE_reload_outtf) reload_out_optab[(int) TFmode] = CODE_FOR_reload_outtf;#endif#endif /* HAVE_SECONDARY_RELOADS */}/* Main entry point for the reload pass, and only entry point in this file. FIRST is the first insn of the function being compiled. GLOBAL nonzero means we were called from global_alloc and should attempt to reallocate any pseudoregs that we displace from hard regs we will use for reloads. If GLOBAL is zero, we do not have enough information to do that, so any pseudo reg that is spilled must go to the stack. DUMPFILE is the global-reg debugging dump file stream, or 0. If it is nonzero, messages are written to it to describe which registers are seized as reload regs, which pseudo regs are spilled from them, and where the pseudo regs are reallocated to. Return value is nonzero if reload failed and we must not do any more for this function. */intreload (first, global, dumpfile) rtx first; int global; FILE *dumpfile;{ register int class; register int i; register rtx insn; register struct elim_table *ep; int something_changed; int something_needs_reloads; int something_needs_elimination; int new_basic_block_needs; enum reg_class caller_save_spill_class = NO_REGS; int caller_save_group_size = 1; /* Nonzero means we couldn't get enough spill regs. */ int failure = 0; /* The basic block number currently being processed for INSN. */ int this_block; /* Make sure even insns with volatile mem refs are recognizable. */ init_recog (); /* Enable find_equiv_reg to distinguish insns made by reload. */ reload_first_uid = get_max_uid (); for (i = 0; i < N_REG_CLASSES; i++) basic_block_needs[i] = 0;#ifdef SECONDARY_MEMORY_NEEDED /* Initialize the secondary memory table. */ clear_secondary_mem ();#endif /* Remember which hard regs appear explicitly before we merge into `regs_ever_live' the ones in which pseudo regs have been allocated. */ bcopy (regs_ever_live, regs_explicitly_used, sizeof regs_ever_live); /* We don't have a stack slot for any spill reg yet. */ bzero (spill_stack_slot, sizeof spill_stack_slot); bzero (spill_stack_slot_width, sizeof spill_stack_slot_width); /* Initialize the save area information for caller-save, in case some are needed. */ init_save_areas (); /* Compute which hard registers are now in use as homes for pseudo registers. This is done here rather than (eg) in global_alloc because this point is reached even if not optimizing. */ for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++) mark_home_live (i); /* Make sure that the last insn in the chain is not something that needs reloading. */ emit_note (NULL_PTR, NOTE_INSN_DELETED); /* 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) and cse'd or loop-moved constant memory addresses. Record constant equivalents in reg_equiv_constant so they will be substituted by find_reloads. Record memory equivalents in reg_mem_equiv so they can be substituted eventually by altering the REG-rtx's. */ reg_equiv_constant = (rtx *) alloca (max_regno * sizeof (rtx)); bzero (reg_equiv_constant, max_regno * sizeof (rtx)); reg_equiv_memory_loc = (rtx *) alloca (max_regno * sizeof (rtx)); bzero (reg_equiv_memory_loc, max_regno * sizeof (rtx)); reg_equiv_mem = (rtx *) alloca (max_regno * sizeof (rtx)); bzero (reg_equiv_mem, max_regno * sizeof (rtx)); reg_equiv_init = (rtx *) alloca (max_regno * sizeof (rtx)); bzero (reg_equiv_init, max_regno * sizeof (rtx)); reg_equiv_address = (rtx *) alloca (max_regno * sizeof (rtx)); bzero (reg_equiv_address, max_regno * sizeof (rtx)); reg_max_ref_width = (int *) alloca (max_regno * sizeof (int)); bzero (reg_max_ref_width, max_regno * sizeof (int)); /* Look for REG_EQUIV notes; record what each pseudo is equivalent to. Also find all paradoxical subregs and find largest such for each pseudo. */ for (insn = first; insn; insn = NEXT_INSN (insn)) { rtx set = single_set (insn); if (set != 0 && GET_CODE (SET_DEST (set)) == REG) { rtx note = find_reg_note (insn, REG_EQUIV, NULL_RTX); if (note#ifdef LEGITIMATE_PIC_OPERAND_P && (! CONSTANT_P (XEXP (note, 0)) || ! flag_pic || LEGITIMATE_PIC_OPERAND_P (XEXP (note, 0)))#endif ) { rtx x = XEXP (note, 0); i = REGNO (SET_DEST (set)); if (i > LAST_VIRTUAL_REGISTER) { if (GET_CODE (x) == MEM) reg_equiv_memory_loc[i] = x; else if (CONSTANT_P (x)) { if (LEGITIMATE_CONSTANT_P (x)) reg_equiv_constant[i] = x; else reg_equiv_memory_loc[i] = force_const_mem (GET_MODE (SET_DEST (set)), x); } else continue; /* If this register is being made equivalent to a MEM 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 || rtx_equal_p (SET_SRC (set), x)) reg_equiv_init[i] = insn; } } } /* 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 && reg_equiv_memory_loc[REGNO (SET_SRC (set))] && rtx_equal_p (SET_DEST (set), reg_equiv_memory_loc[REGNO (SET_SRC (set))])) reg_equiv_init[REGNO (SET_SRC (set))] = insn; if (GET_RTX_CLASS (GET_CODE (insn)) == 'i') scan_paradoxical_subregs (PATTERN (insn)); } /* 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, we should improve this by emitting the sp-adjusting insns for this case. */ || (current_function_calls_alloca && EXIT_IGNORE_STACK)#endif || FRAME_POINTER_REQUIRED); num_eliminable = 0; /* Initialize the table of registers to eliminate. The way we do this depends on how the eliminable registers were defined. */#ifdef ELIMINABLE_REGS for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMINABLE_REGS]; ep++) { ep->can_eliminate = ep->can_eliminate_previous = (CAN_ELIMINATE (ep->from, ep->to) && (ep->from != FRAME_POINTER_REGNUM || ! frame_pointer_needed)); }#else reg_eliminate[0].can_eliminate = reg_eliminate[0].can_eliminate_previous = ! frame_pointer_needed;#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. We depend on this. */ for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMINABLE_REGS]; ep++) { num_eliminable += ep->can_eliminate; ep->from_rtx = gen_rtx (REG, Pmode, ep->from); ep->to_rtx = gen_rtx (REG, Pmode, ep->to); } num_labels = max_label_num () - get_first_label_num (); /* Allocate the tables used to store offset information at labels. */ offsets_known_at = (char *) alloca (num_labels); offsets_at = (int (*)[NUM_ELIMINABLE_REGS]) alloca (num_labels * NUM_ELIMINABLE_REGS * sizeof (int)); offsets_known_at -= get_first_label_num (); offsets_at -= get_first_label_num (); /* Alter each pseudo-reg rtx to contain its hard reg number. Assign stack slots to the pseudos that lack hard regs or equivalents. Do not touch virtual registers. */ for (i = LAST_VIRTUAL_REGISTER + 1; i < max_regno; i++) alter_reg (i, -1); /* Round size of stack frame to BIGGEST_ALIGNMENT. This must be done here because the stack size may be a part of the offset computation for register elimination. */ assign_stack_local (BLKmode, 0, 0); /* If we have some registers we think can be eliminated, scan all insns to see if there is an insn that sets one of these registers to something other than itself plus a constant. If so, the register cannot be eliminated. Doing this scan here eliminates an extra pass through the 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) note_stores (PATTERN (insn), mark_not_eliminable);#ifndef REGISTER_CONSTRAINTS /* If all the pseudo regs have hard regs, except for those that are never referenced, we know that no reloads are needed. */ /* But that is not true if there are register constraints, since in that case some pseudos might be in the wrong kind of hard reg. */ for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++) if (reg_renumber[i] == -1 && reg_n_refs[i] != 0) break; if (i == max_regno && num_eliminable == 0 && ! caller_save_needed) return;#endif /* Compute the order of preference for hard registers to spill. Store them by decreasing preference in potential_reload_regs. */ order_regs_for_reload (); /* So far, no hard regs have been spilled. */ n_spills = 0; for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) spill_reg_order[i] = -1; /* On most machines, we can't use any register explicitly used in the rtl as a spill register. But on some, we have to. Those will have taken care to keep the life of hard regs as short as possible. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -