From: J"orn Rennecke Date: Fri, 12 Feb 1999 13:12:48 +0000 (+0000) Subject: reload.c (find_reloads_subreg_address): New function, broken out of find_reloads_toplev. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=22505ad8f35c50ee96e5a642ea54e2de39ea2e52;p=gcc.git reload.c (find_reloads_subreg_address): New function, broken out of find_reloads_toplev. * reload.c (find_reloads_subreg_address): New function, broken out of find_reloads_toplev. (find_reloads_toplev, find_reloads_address_1): Use it. From-SVN: r25169 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2a8e93845b8..b88e8f84b9c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +Fri Feb 12 21:09:51 1999 J"orn Rennecke + + * reload.c (find_reloads_subreg_address): New function, broken out of + find_reloads_toplev. + (find_reloads_toplev, find_reloads_address_1): Use it. + Fri Feb 12 13:20:52 1999 Jeffrey A Law (law@cygnus.com) * h8300.md (zero_extendhisi2 H8/300 variant): Correctly handle diff --git a/gcc/reload.c b/gcc/reload.c index 9959942f8c5..19c7efeacec 100644 --- a/gcc/reload.c +++ b/gcc/reload.c @@ -338,6 +338,8 @@ static int find_reloads_address_1 PROTO((enum machine_mode, rtx, int, rtx *, static void find_reloads_address_part PROTO((rtx, rtx *, enum reg_class, enum machine_mode, int, enum reload_type, int)); +static rtx find_reloads_subreg_address PROTO((rtx, int, int, enum reload_type, + int, rtx)); static int find_inc_amount PROTO((rtx, rtx)); static int loc_mentioned_in_p PROTO((rtx *, rtx)); @@ -4483,34 +4485,8 @@ find_reloads_toplev (x, opnum, type, ind_levels, is_set_dest, insn) XEXP (reg_equiv_mem[regno], 0)) || ! offsettable_memref_p (reg_equiv_mem[regno]) || num_not_at_initial_offset)))) - { - int offset = SUBREG_WORD (x) * UNITS_PER_WORD; - /* We must rerun eliminate_regs, in case the elimination - offsets have changed. */ - rtx addr = XEXP (eliminate_regs (reg_equiv_memory_loc[regno], 0, - NULL_RTX), - 0); - if (BYTES_BIG_ENDIAN) - { - int size; - size = GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))); - offset += MIN (size, UNITS_PER_WORD); - size = GET_MODE_SIZE (GET_MODE (x)); - offset -= MIN (size, UNITS_PER_WORD); - } - addr = plus_constant (addr, offset); - x = gen_rtx_MEM (GET_MODE (x), addr); - RTX_UNCHANGING_P (x) = RTX_UNCHANGING_P (regno_reg_rtx[regno]); - find_reloads_address (GET_MODE (x), &x, - XEXP (x, 0), - &XEXP (x, 0), opnum, type, ind_levels, insn); - /* If this is not a toplevel operand, find_reloads doesn't see this - substitution. We have to emit a USE of the pseudo so that - delete_output_reload can see it. */ - if (replace_reloads && recog_operand[opnum] != x) - emit_insn_before (gen_rtx_USE (VOIDmode, SUBREG_REG (x)), insn); - } - + x = find_reloads_subreg_address (x, 1, opnum, type, ind_levels, + insn); } for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) @@ -5519,6 +5495,8 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn) if (CLASS_MAX_NREGS (class, GET_MODE (SUBREG_REG (x))) > reg_class_size[class]) { + x = find_reloads_subreg_address (x, 0, opnum, type, + ind_levels, insn); push_reload (x, NULL_RTX, loc, NULL_PTR, class, GET_MODE (x), VOIDmode, 0, 0, opnum, type); return 1; @@ -5615,6 +5593,85 @@ find_reloads_address_part (x, loc, class, mode, opnum, type, ind_levels) mode, VOIDmode, 0, 0, opnum, type); } +/* X, a subreg of a pseudo, is a part of an address that needs to be + reloaded. + + If the pseudo is equivalent to a memory location that cannot be directly + addressed, make the necessary address reloads. + + If address reloads have been necessary, or if the address is changed + by register elimination, return the rtx of the memory location; + otherwise, return X. + + If FORCE_REPLACE is nonzero, unconditionally replace the subreg with the + memory location. + + OPNUM and TYPE identify the purpose of the reload. + + IND_LEVELS says how many levels of indirect addressing are + supported at this point in the address. + + INSN, if nonzero, is the insn in which we do the reload. It is used + to determine where to put USEs for pseudos that we have to replace with + stack slots. */ + +static rtx +find_reloads_subreg_address (x, force_replace, opnum, type, + ind_levels, insn) + rtx x; + int force_replace; + int opnum; + enum reload_type type; + int ind_levels; + rtx insn; +{ + int regno = REGNO (SUBREG_REG (x)); + + if (reg_equiv_memory_loc[regno]) + { + /* If the address is not directly addressable, or if the address is not + offsettable, then it must be replaced. */ + if (! force_replace + && (reg_equiv_address[regno] + || ! offsettable_memref_p (reg_equiv_mem[regno]))) + force_replace = 1; + + if (force_replace || num_not_at_initial_offset) + { + rtx tem = make_memloc (SUBREG_REG (x), regno); + + /* If the address changes because of register elimination, then + it must be replaced. */ + if (force_replace + || ! rtx_equal_p (tem, reg_equiv_mem[regno])) + { + int offset = SUBREG_WORD (x) * UNITS_PER_WORD; + + if (BYTES_BIG_ENDIAN) + { + int size; + + size = GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))); + offset += MIN (size, UNITS_PER_WORD); + size = GET_MODE_SIZE (GET_MODE (x)); + offset -= MIN (size, UNITS_PER_WORD); + } + XEXP (tem, 0) = plus_constant (XEXP (tem, 0), offset); + PUT_MODE (tem, GET_MODE (x)); + x = tem; + find_reloads_address (GET_MODE (x), &x, XEXP (x, 0), &XEXP (x, 0), + opnum, ADDR_TYPE (type), ind_levels, insn); + /* If this is not a toplevel operand, find_reloads doesn't see + this substitution. We have to emit a USE of the pseudo so + that delete_output_reload can see it. */ + if (replace_reloads && recog_operand[opnum] != x) + emit_insn_before (gen_rtx_USE (VOIDmode, SUBREG_REG (x)), insn); + } + } + } + return x; +} + /* Substitute into the current INSN the registers into which we have reloaded the things that need reloading. The array `replacements' says contains the locations of all pointers that must be changed