aboutsummaryrefslogtreecommitdiffstats
path: root/toolchain-layer/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99439.patch
diff options
context:
space:
mode:
Diffstat (limited to 'toolchain-layer/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99439.patch')
-rw-r--r--toolchain-layer/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99439.patch1500
1 files changed, 0 insertions, 1500 deletions
diff --git a/toolchain-layer/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99439.patch b/toolchain-layer/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99439.patch
deleted file mode 100644
index cec7f57d47..0000000000
--- a/toolchain-layer/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99439.patch
+++ /dev/null
@@ -1,1500 +0,0 @@
-2010-11-16 Chung-Lin Tang <cltang@codesourcery.com>
-
- 2010-07-21 Richard Henderson <rth@redhat.com>
-
- gcc/
- * config/i386/i386.c (setup_incoming_varargs_64): Emit a simple
- comparison for avoiding xmm register saves. Emit the xmm register
- saves explicitly.
- * config/i386/i386.md (UNSPEC_SSE_PROLOGUE_SAVE): Remove.
- (UNSPEC_SSE_PROLOGUE_SAVE_LOW): Remove.
- (sse_prologue_save, sse_prologue_save_insn1, sse_prologue_save_insn):
- Remove patterns and the associated splitters.
-
- 2010-07-22 Richard Henderson <rth@redhat.com>
-
- gcc/
- PR target/45027
- * config/i386/i386.c (setup_incoming_varargs_64): Force the use
- of V4SFmode for the SSE saves; increase stack alignment if needed.
-
-2010-11-16 Chung-Lin Tang <cltang@codesourcery.com>
-
- Re-merge, backport from mainline:
-
- 2010-07-15 Bernd Schmidt <bernds@codesourcery.com>
-
- gcc/
- * postreload.c (last_label_ruid, first_index_reg, last_index_reg):
- New static variables.
- (reload_combine_recognize_pattern): New static function, broken out
- of reload_combine.
- (reload_combine): Use it. Only initialize first_index_reg and
- last_index_reg once.
-
- 2010-07-17 Bernd Schmidt <bernds@codesourcery.com>
-
- PR target/42235
- gcc/
- * postreload.c (reload_cse_move2add): Return bool, true if anything.
- changed. All callers changed.
- (move2add_use_add2_insn): Likewise.
- (move2add_use_add3_insn): Likewise.
- (reload_cse_regs): If reload_cse_move2add changed anything, rerun
- reload_combine.
- (RELOAD_COMBINE_MAX_USES): Bump to 16.
- (last_jump_ruid): New static variable.
- (struct reg_use): New members CONTAINING_MEM and RUID.
- (reg_state): New members ALL_OFFSETS_MATCH and REAL_STORE_RUID.
- (reload_combine_split_one_ruid, reload_combine_split_ruids,
- reload_combine_purge_insn_uses, reload_combine_closest_single_use
- reload_combine_purge_reg_uses_after_ruid,
- reload_combine_recognize_const_pattern): New static functions.
- (reload_combine_recognize_pattern): Verify that ALL_OFFSETS_MATCH
- is true for our reg and that we have available index regs.
- (reload_combine_note_use): New args RUID and CONTAINING_MEM. All
- callers changed. Use them to initialize fields in struct reg_use.
- (reload_combine): Initialize last_jump_ruid. Be careful when to
- take PREV_INSN of the scanned insn. Update REAL_STORE_RUID fields.
- Call reload_combine_recognize_const_pattern.
- (reload_combine_note_store): Update REAL_STORE_RUID field.
-
- gcc/testsuite/
- * gcc.target/arm/pr42235.c: New test.
-
- 2010-07-19 Bernd Schmidt <bernds@codesourcery.com>
-
- gcc/
- * postreload.c (reload_combine_closest_single_use): Ignore the
- number of uses for DEBUG_INSNs.
- (fixup_debug_insns): New static function.
- (reload_combine_recognize_const_pattern): Use it. Don't let the
- main loop be affected by DEBUG_INSNs.
- Really disallow moving adds past a jump insn.
- (reload_combine_recognize_pattern): Don't update use_ruid here.
- (reload_combine_note_use): Do it here.
- (reload_combine): Use control_flow_insn_p rather than JUMP_P.
-
- 2010-07-20 Bernd Schmidt <bernds@codesourcery.com>
-
- gcc/
- * postreload.c (fixup_debug_insns): Remove arg REGNO. New args
- FROM and TO. All callers changed. Don't look for tracked uses,
- just scan the RTL for DEBUG_INSNs and substitute.
- (reload_combine_recognize_pattern): Call fixup_debug_insns.
- (reload_combine): Ignore DEBUG_INSNs.
-
- 2010-07-22 Bernd Schmidt <bernds@codesourcery.com>
-
- PR bootstrap/44970
- PR middle-end/45009
- gcc/
- * postreload.c: Include "target.h".
- (reload_combine_closest_single_use): Don't take DEBUG_INSNs
- into account.
- (fixup_debug_insns): Don't copy the rtx.
- (reload_combine_recognize_const_pattern): DEBUG_INSNs can't have uses.
- Don't copy when replacing. Call fixup_debug_insns in the case where
- we merged one add with another.
- (reload_combine_recognize_pattern): Fail if there aren't any uses.
- Try harder to determine whether we're picking a valid index register.
- Don't set store_ruid for an insn we're going to scan in the
- next iteration.
- (reload_combine): Remove unused code.
- (reload_combine_note_use): When updating use information for
- an old insn, ignore a use that occurs after store_ruid.
- * Makefile.in (postreload.o): Update dependencies.
-
- 2010-07-27 Bernd Schmidt <bernds@codesourcery.com>
-
- gcc/
- * postreload.c (reload_combine_recognize_const_pattern): Move test
- for limiting the insn movement to the right scope.
-
- 2010-07-27 Bernd Schmidt <bernds@codesourcery.com>
-
- gcc/
- * postreload.c (try_replace_in_use): New static function.
- (reload_combine_recognize_const_pattern): Use it here. Allow
- substituting into a final add insn, and substituting into a memory
- reference in an insn that sets the reg.
-
-=== modified file 'gcc/Makefile.in'
---- old/gcc/Makefile.in 2010-11-11 11:34:59 +0000
-+++ new/gcc/Makefile.in 2010-11-16 18:05:53 +0000
-@@ -3157,7 +3157,7 @@
- $(RTL_H) $(REAL_H) $(FLAGS_H) $(EXPR_H) $(OPTABS_H) reload.h $(REGS_H) \
- hard-reg-set.h insn-config.h $(BASIC_BLOCK_H) $(RECOG_H) output.h \
- $(FUNCTION_H) $(TOPLEV_H) cselib.h $(TM_P_H) $(EXCEPT_H) $(TREE_H) $(MACHMODE_H) \
-- $(OBSTACK_H) $(TIMEVAR_H) $(TREE_PASS_H) $(DF_H) $(DBGCNT_H)
-+ $(OBSTACK_H) $(TARGET_H) $(TIMEVAR_H) $(TREE_PASS_H) $(DF_H) $(DBGCNT_H)
- postreload-gcse.o : postreload-gcse.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TM_H) $(RTL_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h \
- $(RECOG_H) $(EXPR_H) $(BASIC_BLOCK_H) $(FUNCTION_H) output.h $(TOPLEV_H) \
-
-=== modified file 'gcc/config/i386/i386.c'
---- old/gcc/config/i386/i386.c 2010-09-30 20:24:54 +0000
-+++ new/gcc/config/i386/i386.c 2010-11-16 18:05:53 +0000
-@@ -6737,12 +6737,8 @@
- setup_incoming_varargs_64 (CUMULATIVE_ARGS *cum)
- {
- rtx save_area, mem;
-- rtx label;
-- rtx label_ref;
-- rtx tmp_reg;
-- rtx nsse_reg;
- alias_set_type set;
-- int i;
-+ int i, max;
-
- /* GPR size of varargs save area. */
- if (cfun->va_list_gpr_size)
-@@ -6752,7 +6748,7 @@
-
- /* FPR size of varargs save area. We don't need it if we don't pass
- anything in SSE registers. */
-- if (cum->sse_nregs && cfun->va_list_fpr_size)
-+ if (TARGET_SSE && cfun->va_list_fpr_size)
- ix86_varargs_fpr_size = X86_64_SSE_REGPARM_MAX * 16;
- else
- ix86_varargs_fpr_size = 0;
-@@ -6763,10 +6759,11 @@
- save_area = frame_pointer_rtx;
- set = get_varargs_alias_set ();
-
-- for (i = cum->regno;
-- i < X86_64_REGPARM_MAX
-- && i < cum->regno + cfun->va_list_gpr_size / UNITS_PER_WORD;
-- i++)
-+ max = cum->regno + cfun->va_list_gpr_size / UNITS_PER_WORD;
-+ if (max > X86_64_REGPARM_MAX)
-+ max = X86_64_REGPARM_MAX;
-+
-+ for (i = cum->regno; i < max; i++)
- {
- mem = gen_rtx_MEM (Pmode,
- plus_constant (save_area, i * UNITS_PER_WORD));
-@@ -6778,62 +6775,42 @@
-
- if (ix86_varargs_fpr_size)
- {
-- /* Stack must be aligned to 16byte for FP register save area. */
-- if (crtl->stack_alignment_needed < 128)
-- crtl->stack_alignment_needed = 128;
-+ enum machine_mode smode;
-+ rtx label, test;
-
- /* Now emit code to save SSE registers. The AX parameter contains number
-- of SSE parameter registers used to call this function. We use
-- sse_prologue_save insn template that produces computed jump across
-- SSE saves. We need some preparation work to get this working. */
-+ of SSE parameter registers used to call this function, though all we
-+ actually check here is the zero/non-zero status. */
-
- label = gen_label_rtx ();
-- label_ref = gen_rtx_LABEL_REF (Pmode, label);
--
-- /* Compute address to jump to :
-- label - eax*4 + nnamed_sse_arguments*4 Or
-- label - eax*5 + nnamed_sse_arguments*5 for AVX. */
-- tmp_reg = gen_reg_rtx (Pmode);
-- nsse_reg = gen_reg_rtx (Pmode);
-- emit_insn (gen_zero_extendqidi2 (nsse_reg, gen_rtx_REG (QImode, AX_REG)));
-- emit_insn (gen_rtx_SET (VOIDmode, tmp_reg,
-- gen_rtx_MULT (Pmode, nsse_reg,
-- GEN_INT (4))));
--
-- /* vmovaps is one byte longer than movaps. */
-- if (TARGET_AVX)
-- emit_insn (gen_rtx_SET (VOIDmode, tmp_reg,
-- gen_rtx_PLUS (Pmode, tmp_reg,
-- nsse_reg)));
--
-- if (cum->sse_regno)
-- emit_move_insn
-- (nsse_reg,
-- gen_rtx_CONST (DImode,
-- gen_rtx_PLUS (DImode,
-- label_ref,
-- GEN_INT (cum->sse_regno
-- * (TARGET_AVX ? 5 : 4)))));
-- else
-- emit_move_insn (nsse_reg, label_ref);
-- emit_insn (gen_subdi3 (nsse_reg, nsse_reg, tmp_reg));
--
-- /* Compute address of memory block we save into. We always use pointer
-- pointing 127 bytes after first byte to store - this is needed to keep
-- instruction size limited by 4 bytes (5 bytes for AVX) with one
-- byte displacement. */
-- tmp_reg = gen_reg_rtx (Pmode);
-- emit_insn (gen_rtx_SET (VOIDmode, tmp_reg,
-- plus_constant (save_area,
-- ix86_varargs_gpr_size + 127)));
-- mem = gen_rtx_MEM (BLKmode, plus_constant (tmp_reg, -127));
-- MEM_NOTRAP_P (mem) = 1;
-- set_mem_alias_set (mem, set);
-- set_mem_align (mem, BITS_PER_WORD);
--
-- /* And finally do the dirty job! */
-- emit_insn (gen_sse_prologue_save (mem, nsse_reg,
-- GEN_INT (cum->sse_regno), label));
-+ test = gen_rtx_EQ (VOIDmode, gen_rtx_REG (QImode, AX_REG), const0_rtx);
-+ emit_jump_insn (gen_cbranchqi4 (test, XEXP (test, 0), XEXP (test, 1),
-+ label));
-+
-+ /* ??? If !TARGET_SSE_TYPELESS_STORES, would we perform better if
-+ we used movdqa (i.e. TImode) instead? Perhaps even better would
-+ be if we could determine the real mode of the data, via a hook
-+ into pass_stdarg. Ignore all that for now. */
-+ smode = V4SFmode;
-+ if (crtl->stack_alignment_needed < GET_MODE_ALIGNMENT (smode))
-+ crtl->stack_alignment_needed = GET_MODE_ALIGNMENT (smode);
-+
-+ max = cum->sse_regno + cfun->va_list_fpr_size / 16;
-+ if (max > X86_64_SSE_REGPARM_MAX)
-+ max = X86_64_SSE_REGPARM_MAX;
-+
-+ for (i = cum->sse_regno; i < max; ++i)
-+ {
-+ mem = plus_constant (save_area, i * 16 + ix86_varargs_gpr_size);
-+ mem = gen_rtx_MEM (smode, mem);
-+ MEM_NOTRAP_P (mem) = 1;
-+ set_mem_alias_set (mem, set);
-+ set_mem_align (mem, GET_MODE_ALIGNMENT (smode));
-+
-+ emit_move_insn (mem, gen_rtx_REG (smode, SSE_REGNO (i)));
-+ }
-+
-+ emit_label (label);
- }
- }
-
-
-=== modified file 'gcc/config/i386/i386.md'
---- old/gcc/config/i386/i386.md 2010-10-22 04:56:41 +0000
-+++ new/gcc/config/i386/i386.md 2010-11-27 15:24:12 +0000
-@@ -80,7 +80,6 @@
- ; Prologue support
- (UNSPEC_STACK_ALLOC 11)
- (UNSPEC_SET_GOT 12)
-- (UNSPEC_SSE_PROLOGUE_SAVE 13)
- (UNSPEC_REG_SAVE 14)
- (UNSPEC_DEF_CFA 15)
- (UNSPEC_SET_RIP 16)
-@@ -20252,74 +20251,6 @@
- { return ASM_SHORT "0x0b0f"; }
- [(set_attr "length" "2")])
-
--(define_expand "sse_prologue_save"
-- [(parallel [(set (match_operand:BLK 0 "" "")
-- (unspec:BLK [(reg:DI XMM0_REG)
-- (reg:DI XMM1_REG)
-- (reg:DI XMM2_REG)
-- (reg:DI XMM3_REG)
-- (reg:DI XMM4_REG)
-- (reg:DI XMM5_REG)
-- (reg:DI XMM6_REG)
-- (reg:DI XMM7_REG)] UNSPEC_SSE_PROLOGUE_SAVE))
-- (use (match_operand:DI 1 "register_operand" ""))
-- (use (match_operand:DI 2 "immediate_operand" ""))
-- (use (label_ref:DI (match_operand 3 "" "")))])]
-- "TARGET_64BIT"
-- "")
--
--(define_insn "*sse_prologue_save_insn"
-- [(set (mem:BLK (plus:DI (match_operand:DI 0 "register_operand" "R")
-- (match_operand:DI 4 "const_int_operand" "n")))
-- (unspec:BLK [(reg:DI XMM0_REG)
-- (reg:DI XMM1_REG)
-- (reg:DI XMM2_REG)
-- (reg:DI XMM3_REG)
-- (reg:DI XMM4_REG)
-- (reg:DI XMM5_REG)
-- (reg:DI XMM6_REG)
-- (reg:DI XMM7_REG)] UNSPEC_SSE_PROLOGUE_SAVE))
-- (use (match_operand:DI 1 "register_operand" "r"))
-- (use (match_operand:DI 2 "const_int_operand" "i"))
-- (use (label_ref:DI (match_operand 3 "" "X")))]
-- "TARGET_64BIT
-- && INTVAL (operands[4]) + X86_64_SSE_REGPARM_MAX * 16 - 16 < 128
-- && INTVAL (operands[4]) + INTVAL (operands[2]) * 16 >= -128"
--{
-- int i;
-- operands[0] = gen_rtx_MEM (Pmode,
-- gen_rtx_PLUS (Pmode, operands[0], operands[4]));
-- /* VEX instruction with a REX prefix will #UD. */
-- if (TARGET_AVX && GET_CODE (XEXP (operands[0], 0)) != PLUS)
-- gcc_unreachable ();
--
-- output_asm_insn ("jmp\t%A1", operands);
-- for (i = X86_64_SSE_REGPARM_MAX - 1; i >= INTVAL (operands[2]); i--)
-- {
-- operands[4] = adjust_address (operands[0], DImode, i*16);
-- operands[5] = gen_rtx_REG (TImode, SSE_REGNO (i));
-- PUT_MODE (operands[4], TImode);
-- if (GET_CODE (XEXP (operands[0], 0)) != PLUS)
-- output_asm_insn ("rex", operands);
-- output_asm_insn ("%vmovaps\t{%5, %4|%4, %5}", operands);
-- }
-- (*targetm.asm_out.internal_label) (asm_out_file, "L",
-- CODE_LABEL_NUMBER (operands[3]));
-- return "";
--}
-- [(set_attr "type" "other")
-- (set_attr "length_immediate" "0")
-- (set_attr "length_address" "0")
-- (set (attr "length")
-- (if_then_else
-- (eq (symbol_ref "TARGET_AVX") (const_int 0))
-- (const_string "34")
-- (const_string "42")))
-- (set_attr "memory" "store")
-- (set_attr "modrm" "0")
-- (set_attr "prefix" "maybe_vex")
-- (set_attr "mode" "DI")])
--
- (define_expand "prefetch"
- [(prefetch (match_operand 0 "address_operand" "")
- (match_operand:SI 1 "const_int_operand" "")
-
-=== modified file 'gcc/postreload.c'
---- old/gcc/postreload.c 2010-11-08 22:08:43 +0000
-+++ new/gcc/postreload.c 2010-11-16 18:05:53 +0000
-@@ -44,6 +44,7 @@
- #include "toplev.h"
- #include "except.h"
- #include "tree.h"
-+#include "target.h"
- #include "timevar.h"
- #include "tree-pass.h"
- #include "df.h"
-@@ -56,10 +57,10 @@
- static int reload_cse_simplify_operands (rtx, rtx);
-
- static void reload_combine (void);
--static void reload_combine_note_use (rtx *, rtx);
-+static void reload_combine_note_use (rtx *, rtx, int, rtx);
- static void reload_combine_note_store (rtx, const_rtx, void *);
-
--static void reload_cse_move2add (rtx);
-+static bool reload_cse_move2add (rtx);
- static void move2add_note_store (rtx, const_rtx, void *);
-
- /* Call cse / combine like post-reload optimization phases.
-@@ -67,11 +68,16 @@
- void
- reload_cse_regs (rtx first ATTRIBUTE_UNUSED)
- {
-+ bool moves_converted;
- reload_cse_regs_1 (first);
- reload_combine ();
-- reload_cse_move2add (first);
-+ moves_converted = reload_cse_move2add (first);
- if (flag_expensive_optimizations)
-- reload_cse_regs_1 (first);
-+ {
-+ if (moves_converted)
-+ reload_combine ();
-+ reload_cse_regs_1 (first);
-+ }
- }
-
- /* See whether a single set SET is a noop. */
-@@ -660,30 +666,43 @@
-
- /* The maximum number of uses of a register we can keep track of to
- replace them with reg+reg addressing. */
--#define RELOAD_COMBINE_MAX_USES 6
-+#define RELOAD_COMBINE_MAX_USES 16
-
--/* INSN is the insn where a register has been used, and USEP points to the
-- location of the register within the rtl. */
--struct reg_use { rtx insn, *usep; };
-+/* Describes a recorded use of a register. */
-+struct reg_use
-+{
-+ /* The insn where a register has been used. */
-+ rtx insn;
-+ /* Points to the memory reference enclosing the use, if any, NULL_RTX
-+ otherwise. */
-+ rtx containing_mem;
-+ /* Location of the register withing INSN. */
-+ rtx *usep;
-+ /* The reverse uid of the insn. */
-+ int ruid;
-+};
-
- /* If the register is used in some unknown fashion, USE_INDEX is negative.
- If it is dead, USE_INDEX is RELOAD_COMBINE_MAX_USES, and STORE_RUID
-- indicates where it becomes live again.
-+ indicates where it is first set or clobbered.
- Otherwise, USE_INDEX is the index of the last encountered use of the
-- register (which is first among these we have seen since we scan backwards),
-- OFFSET contains the constant offset that is added to the register in
-- all encountered uses, and USE_RUID indicates the first encountered, i.e.
-- last, of these uses.
-+ register (which is first among these we have seen since we scan backwards).
-+ USE_RUID indicates the first encountered, i.e. last, of these uses.
-+ If ALL_OFFSETS_MATCH is true, all encountered uses were inside a PLUS
-+ with a constant offset; OFFSET contains this constant in that case.
- STORE_RUID is always meaningful if we only want to use a value in a
- register in a different place: it denotes the next insn in the insn
-- stream (i.e. the last encountered) that sets or clobbers the register. */
-+ stream (i.e. the last encountered) that sets or clobbers the register.
-+ REAL_STORE_RUID is similar, but clobbers are ignored when updating it. */
- static struct
- {
- struct reg_use reg_use[RELOAD_COMBINE_MAX_USES];
-+ rtx offset;
- int use_index;
-- rtx offset;
- int store_ruid;
-+ int real_store_ruid;
- int use_ruid;
-+ bool all_offsets_match;
- } reg_state[FIRST_PSEUDO_REGISTER];
-
- /* Reverse linear uid. This is increased in reload_combine while scanning
-@@ -691,42 +710,548 @@
- and the store_ruid / use_ruid fields in reg_state. */
- static int reload_combine_ruid;
-
-+/* The RUID of the last label we encountered in reload_combine. */
-+static int last_label_ruid;
-+
-+/* The RUID of the last jump we encountered in reload_combine. */
-+static int last_jump_ruid;
-+
-+/* The register numbers of the first and last index register. A value of
-+ -1 in LAST_INDEX_REG indicates that we've previously computed these
-+ values and found no suitable index registers. */
-+static int first_index_reg = -1;
-+static int last_index_reg;
-+
- #define LABEL_LIVE(LABEL) \
- (label_live[CODE_LABEL_NUMBER (LABEL) - min_labelno])
-
-+/* Subroutine of reload_combine_split_ruids, called to fix up a single
-+ ruid pointed to by *PRUID if it is higher than SPLIT_RUID. */
-+
-+static inline void
-+reload_combine_split_one_ruid (int *pruid, int split_ruid)
-+{
-+ if (*pruid > split_ruid)
-+ (*pruid)++;
-+}
-+
-+/* Called when we insert a new insn in a position we've already passed in
-+ the scan. Examine all our state, increasing all ruids that are higher
-+ than SPLIT_RUID by one in order to make room for a new insn. */
-+
-+static void
-+reload_combine_split_ruids (int split_ruid)
-+{
-+ unsigned i;
-+
-+ reload_combine_split_one_ruid (&reload_combine_ruid, split_ruid);
-+ reload_combine_split_one_ruid (&last_label_ruid, split_ruid);
-+ reload_combine_split_one_ruid (&last_jump_ruid, split_ruid);
-+
-+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-+ {
-+ int j, idx = reg_state[i].use_index;
-+ reload_combine_split_one_ruid (&reg_state[i].use_ruid, split_ruid);
-+ reload_combine_split_one_ruid (&reg_state[i].store_ruid, split_ruid);
-+ reload_combine_split_one_ruid (&reg_state[i].real_store_ruid,
-+ split_ruid);
-+ if (idx < 0)
-+ continue;
-+ for (j = idx; j < RELOAD_COMBINE_MAX_USES; j++)
-+ {
-+ reload_combine_split_one_ruid (&reg_state[i].reg_use[j].ruid,
-+ split_ruid);
-+ }
-+ }
-+}
-+
-+/* Called when we are about to rescan a previously encountered insn with
-+ reload_combine_note_use after modifying some part of it. This clears all
-+ information about uses in that particular insn. */
-+
-+static void
-+reload_combine_purge_insn_uses (rtx insn)
-+{
-+ unsigned i;
-+
-+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-+ {
-+ int j, k, idx = reg_state[i].use_index;
-+ if (idx < 0)
-+ continue;
-+ j = k = RELOAD_COMBINE_MAX_USES;
-+ while (j-- > idx)
-+ {
-+ if (reg_state[i].reg_use[j].insn != insn)
-+ {
-+ k--;
-+ if (k != j)
-+ reg_state[i].reg_use[k] = reg_state[i].reg_use[j];
-+ }
-+ }
-+ reg_state[i].use_index = k;
-+ }
-+}
-+
-+/* Called when we need to forget about all uses of REGNO after an insn
-+ which is identified by RUID. */
-+
-+static void
-+reload_combine_purge_reg_uses_after_ruid (unsigned regno, int ruid)
-+{
-+ int j, k, idx = reg_state[regno].use_index;
-+ if (idx < 0)
-+ return;
-+ j = k = RELOAD_COMBINE_MAX_USES;
-+ while (j-- > idx)
-+ {
-+ if (reg_state[regno].reg_use[j].ruid >= ruid)
-+ {
-+ k--;
-+ if (k != j)
-+ reg_state[regno].reg_use[k] = reg_state[regno].reg_use[j];
-+ }
-+ }
-+ reg_state[regno].use_index = k;
-+}
-+
-+/* Find the use of REGNO with the ruid that is highest among those
-+ lower than RUID_LIMIT, and return it if it is the only use of this
-+ reg in the insn. Return NULL otherwise. */
-+
-+static struct reg_use *
-+reload_combine_closest_single_use (unsigned regno, int ruid_limit)
-+{
-+ int i, best_ruid = 0;
-+ int use_idx = reg_state[regno].use_index;
-+ struct reg_use *retval;
-+
-+ if (use_idx < 0)
-+ return NULL;
-+ retval = NULL;
-+ for (i = use_idx; i < RELOAD_COMBINE_MAX_USES; i++)
-+ {
-+ struct reg_use *use = reg_state[regno].reg_use + i;
-+ int this_ruid = use->ruid;
-+ if (this_ruid >= ruid_limit)
-+ continue;
-+ if (this_ruid > best_ruid)
-+ {
-+ best_ruid = this_ruid;
-+ retval = use;
-+ }
-+ else if (this_ruid == best_ruid)
-+ retval = NULL;
-+ }
-+ if (last_label_ruid >= best_ruid)
-+ return NULL;
-+ return retval;
-+}
-+
-+/* After we've moved an add insn, fix up any debug insns that occur
-+ between the old location of the add and the new location. REG is
-+ the destination register of the add insn; REPLACEMENT is the
-+ SET_SRC of the add. FROM and TO specify the range in which we
-+ should make this change on debug insns. */
-+
-+static void
-+fixup_debug_insns (rtx reg, rtx replacement, rtx from, rtx to)
-+{
-+ rtx insn;
-+ for (insn = from; insn != to; insn = NEXT_INSN (insn))
-+ {
-+ rtx t;
-+
-+ if (!DEBUG_INSN_P (insn))
-+ continue;
-+
-+ t = INSN_VAR_LOCATION_LOC (insn);
-+ t = simplify_replace_rtx (t, reg, replacement);
-+ validate_change (insn, &INSN_VAR_LOCATION_LOC (insn), t, 0);
-+ }
-+}
-+
-+/* Subroutine of reload_combine_recognize_const_pattern. Try to replace REG
-+ with SRC in the insn described by USE, taking costs into account. Return
-+ true if we made the replacement. */
-+
-+static bool
-+try_replace_in_use (struct reg_use *use, rtx reg, rtx src)
-+{
-+ rtx use_insn = use->insn;
-+ rtx mem = use->containing_mem;
-+ bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (use_insn));
-+
-+ if (mem != NULL_RTX)
-+ {
-+ addr_space_t as = MEM_ADDR_SPACE (mem);
-+ rtx oldaddr = XEXP (mem, 0);
-+ rtx newaddr = NULL_RTX;
-+ int old_cost = address_cost (oldaddr, GET_MODE (mem), as, speed);
-+ int new_cost;
-+
-+ newaddr = simplify_replace_rtx (oldaddr, reg, src);
-+ if (memory_address_addr_space_p (GET_MODE (mem), newaddr, as))
-+ {
-+ XEXP (mem, 0) = newaddr;
-+ new_cost = address_cost (newaddr, GET_MODE (mem), as, speed);
-+ XEXP (mem, 0) = oldaddr;
-+ if (new_cost <= old_cost
-+ && validate_change (use_insn,
-+ &XEXP (mem, 0), newaddr, 0))
-+ return true;
-+ }
-+ }
-+ else
-+ {
-+ rtx new_set = single_set (use_insn);
-+ if (new_set
-+ && REG_P (SET_DEST (new_set))
-+ && GET_CODE (SET_SRC (new_set)) == PLUS
-+ && REG_P (XEXP (SET_SRC (new_set), 0))
-+ && CONSTANT_P (XEXP (SET_SRC (new_set), 1)))
-+ {
-+ rtx new_src;
-+ int old_cost = rtx_cost (SET_SRC (new_set), SET, speed);
-+
-+ gcc_assert (rtx_equal_p (XEXP (SET_SRC (new_set), 0), reg));
-+ new_src = simplify_replace_rtx (SET_SRC (new_set), reg, src);
-+
-+ if (rtx_cost (new_src, SET, speed) <= old_cost
-+ && validate_change (use_insn, &SET_SRC (new_set),
-+ new_src, 0))
-+ return true;
-+ }
-+ }
-+ return false;
-+}
-+
-+/* Called by reload_combine when scanning INSN. This function tries to detect
-+ patterns where a constant is added to a register, and the result is used
-+ in an address.
-+ Return true if no further processing is needed on INSN; false if it wasn't
-+ recognized and should be handled normally. */
-+
-+static bool
-+reload_combine_recognize_const_pattern (rtx insn)
-+{
-+ int from_ruid = reload_combine_ruid;
-+ rtx set, pat, reg, src, addreg;
-+ unsigned int regno;
-+ struct reg_use *use;
-+ bool must_move_add;
-+ rtx add_moved_after_insn = NULL_RTX;
-+ int add_moved_after_ruid = 0;
-+ int clobbered_regno = -1;
-+
-+ set = single_set (insn);
-+ if (set == NULL_RTX)
-+ return false;
-+
-+ reg = SET_DEST (set);
-+ src = SET_SRC (set);
-+ if (!REG_P (reg)
-+ || hard_regno_nregs[REGNO (reg)][GET_MODE (reg)] != 1
-+ || GET_MODE (reg) != Pmode
-+ || reg == stack_pointer_rtx)
-+ return false;
-+
-+ regno = REGNO (reg);
-+
-+ /* We look for a REG1 = REG2 + CONSTANT insn, followed by either
-+ uses of REG1 inside an address, or inside another add insn. If
-+ possible and profitable, merge the addition into subsequent
-+ uses. */
-+ if (GET_CODE (src) != PLUS
-+ || !REG_P (XEXP (src, 0))
-+ || !CONSTANT_P (XEXP (src, 1)))
-+ return false;
-+
-+ addreg = XEXP (src, 0);
-+ must_move_add = rtx_equal_p (reg, addreg);
-+
-+ pat = PATTERN (insn);
-+ if (must_move_add && set != pat)
-+ {
-+ /* We have to be careful when moving the add; apart from the
-+ single_set there may also be clobbers. Recognize one special
-+ case, that of one clobber alongside the set (likely a clobber
-+ of the CC register). */
-+ gcc_assert (GET_CODE (PATTERN (insn)) == PARALLEL);
-+ if (XVECLEN (pat, 0) != 2 || XVECEXP (pat, 0, 0) != set
-+ || GET_CODE (XVECEXP (pat, 0, 1)) != CLOBBER
-+ || !REG_P (XEXP (XVECEXP (pat, 0, 1), 0)))
-+ return false;
-+ clobbered_regno = REGNO (XEXP (XVECEXP (pat, 0, 1), 0));
-+ }
-+
-+ do
-+ {
-+ use = reload_combine_closest_single_use (regno, from_ruid);
-+
-+ if (use)
-+ /* Start the search for the next use from here. */
-+ from_ruid = use->ruid;
-+
-+ if (use && GET_MODE (*use->usep) == Pmode)
-+ {
-+ bool delete_add = false;
-+ rtx use_insn = use->insn;
-+ int use_ruid = use->ruid;
-+
-+ /* Avoid moving the add insn past a jump. */
-+ if (must_move_add && use_ruid <= last_jump_ruid)
-+ break;
-+
-+ /* If the add clobbers another hard reg in parallel, don't move
-+ it past a real set of this hard reg. */
-+ if (must_move_add && clobbered_regno >= 0
-+ && reg_state[clobbered_regno].real_store_ruid >= use_ruid)
-+ break;
-+
-+ gcc_assert (reg_state[regno].store_ruid <= use_ruid);
-+ /* Avoid moving a use of ADDREG past a point where it is stored. */
-+ if (reg_state[REGNO (addreg)].store_ruid > use_ruid)
-+ break;
-+
-+ /* We also must not move the addition past an insn that sets
-+ the same register, unless we can combine two add insns. */
-+ if (must_move_add && reg_state[regno].store_ruid == use_ruid)
-+ {
-+ if (use->containing_mem == NULL_RTX)
-+ delete_add = true;
-+ else
-+ break;
-+ }
-+
-+ if (try_replace_in_use (use, reg, src))
-+ {
-+ reload_combine_purge_insn_uses (use_insn);
-+ reload_combine_note_use (&PATTERN (use_insn), use_insn,
-+ use_ruid, NULL_RTX);
-+
-+ if (delete_add)
-+ {
-+ fixup_debug_insns (reg, src, insn, use_insn);
-+ delete_insn (insn);
-+ return true;
-+ }
-+ if (must_move_add)
-+ {
-+ add_moved_after_insn = use_insn;
-+ add_moved_after_ruid = use_ruid;
-+ }
-+ continue;
-+ }
-+ }
-+ /* If we get here, we couldn't handle this use. */
-+ if (must_move_add)
-+ break;
-+ }
-+ while (use);
-+
-+ if (!must_move_add || add_moved_after_insn == NULL_RTX)
-+ /* Process the add normally. */
-+ return false;
-+
-+ fixup_debug_insns (reg, src, insn, add_moved_after_insn);
-+
-+ reorder_insns (insn, insn, add_moved_after_insn);
-+ reload_combine_purge_reg_uses_after_ruid (regno, add_moved_after_ruid);
-+ reload_combine_split_ruids (add_moved_after_ruid - 1);
-+ reload_combine_note_use (&PATTERN (insn), insn,
-+ add_moved_after_ruid, NULL_RTX);
-+ reg_state[regno].store_ruid = add_moved_after_ruid;
-+
-+ return true;
-+}
-+
-+/* Called by reload_combine when scanning INSN. Try to detect a pattern we
-+ can handle and improve. Return true if no further processing is needed on
-+ INSN; false if it wasn't recognized and should be handled normally. */
-+
-+static bool
-+reload_combine_recognize_pattern (rtx insn)
-+{
-+ rtx set, reg, src;
-+ unsigned int regno;
-+
-+ set = single_set (insn);
-+ if (set == NULL_RTX)
-+ return false;
-+
-+ reg = SET_DEST (set);
-+ src = SET_SRC (set);
-+ if (!REG_P (reg)
-+ || hard_regno_nregs[REGNO (reg)][GET_MODE (reg)] != 1)
-+ return false;
-+
-+ regno = REGNO (reg);
-+
-+ /* Look for (set (REGX) (CONST_INT))
-+ (set (REGX) (PLUS (REGX) (REGY)))
-+ ...
-+ ... (MEM (REGX)) ...
-+ and convert it to
-+ (set (REGZ) (CONST_INT))
-+ ...
-+ ... (MEM (PLUS (REGZ) (REGY)))... .
-+
-+ First, check that we have (set (REGX) (PLUS (REGX) (REGY)))
-+ and that we know all uses of REGX before it dies.
-+ Also, explicitly check that REGX != REGY; our life information
-+ does not yet show whether REGY changes in this insn. */
-+
-+ if (GET_CODE (src) == PLUS
-+ && reg_state[regno].all_offsets_match
-+ && last_index_reg != -1
-+ && REG_P (XEXP (src, 1))
-+ && rtx_equal_p (XEXP (src, 0), reg)
-+ && !rtx_equal_p (XEXP (src, 1), reg)
-+ && reg_state[regno].use_index >= 0
-+ && reg_state[regno].use_index < RELOAD_COMBINE_MAX_USES
-+ && last_label_ruid < reg_state[regno].use_ruid)
-+ {
-+ rtx base = XEXP (src, 1);
-+ rtx prev = prev_nonnote_insn (insn);
-+ rtx prev_set = prev ? single_set (prev) : NULL_RTX;
-+ rtx index_reg = NULL_RTX;
-+ rtx reg_sum = NULL_RTX;
-+ int i;
-+
-+ /* Now we need to set INDEX_REG to an index register (denoted as
-+ REGZ in the illustration above) and REG_SUM to the expression
-+ register+register that we want to use to substitute uses of REG
-+ (typically in MEMs) with. First check REG and BASE for being
-+ index registers; we can use them even if they are not dead. */
-+ if (TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS], regno)
-+ || TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS],
-+ REGNO (base)))
-+ {
-+ index_reg = reg;
-+ reg_sum = src;
-+ }
-+ else
-+ {
-+ /* Otherwise, look for a free index register. Since we have
-+ checked above that neither REG nor BASE are index registers,
-+ if we find anything at all, it will be different from these
-+ two registers. */
-+ for (i = first_index_reg; i <= last_index_reg; i++)
-+ {
-+ if (TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS], i)
-+ && reg_state[i].use_index == RELOAD_COMBINE_MAX_USES
-+ && reg_state[i].store_ruid <= reg_state[regno].use_ruid
-+ && (call_used_regs[i] || df_regs_ever_live_p (i))
-+ && (!frame_pointer_needed || i != HARD_FRAME_POINTER_REGNUM)
-+ && !fixed_regs[i] && !global_regs[i]
-+ && hard_regno_nregs[i][GET_MODE (reg)] == 1
-+ && targetm.hard_regno_scratch_ok (i))
-+ {
-+ index_reg = gen_rtx_REG (GET_MODE (reg), i);
-+ reg_sum = gen_rtx_PLUS (GET_MODE (reg), index_reg, base);
-+ break;
-+ }
-+ }
-+ }
-+
-+ /* Check that PREV_SET is indeed (set (REGX) (CONST_INT)) and that
-+ (REGY), i.e. BASE, is not clobbered before the last use we'll
-+ create. */
-+ if (reg_sum
-+ && prev_set
-+ && CONST_INT_P (SET_SRC (prev_set))
-+ && rtx_equal_p (SET_DEST (prev_set), reg)
-+ && (reg_state[REGNO (base)].store_ruid
-+ <= reg_state[regno].use_ruid))
-+ {
-+ /* Change destination register and, if necessary, the constant
-+ value in PREV, the constant loading instruction. */
-+ validate_change (prev, &SET_DEST (prev_set), index_reg, 1);
-+ if (reg_state[regno].offset != const0_rtx)
-+ validate_change (prev,
-+ &SET_SRC (prev_set),
-+ GEN_INT (INTVAL (SET_SRC (prev_set))
-+ + INTVAL (reg_state[regno].offset)),
-+ 1);
-+
-+ /* Now for every use of REG that we have recorded, replace REG
-+ with REG_SUM. */
-+ for (i = reg_state[regno].use_index;
-+ i < RELOAD_COMBINE_MAX_USES; i++)
-+ validate_unshare_change (reg_state[regno].reg_use[i].insn,
-+ reg_state[regno].reg_use[i].usep,
-+ /* Each change must have its own
-+ replacement. */
-+ reg_sum, 1);
-+
-+ if (apply_change_group ())
-+ {
-+ struct reg_use *lowest_ruid = NULL;
-+
-+ /* For every new use of REG_SUM, we have to record the use
-+ of BASE therein, i.e. operand 1. */
-+ for (i = reg_state[regno].use_index;
-+ i < RELOAD_COMBINE_MAX_USES; i++)
-+ {
-+ struct reg_use *use = reg_state[regno].reg_use + i;
-+ reload_combine_note_use (&XEXP (*use->usep, 1), use->insn,
-+ use->ruid, use->containing_mem);
-+ if (lowest_ruid == NULL || use->ruid < lowest_ruid->ruid)
-+ lowest_ruid = use;
-+ }
-+
-+ fixup_debug_insns (reg, reg_sum, insn, lowest_ruid->insn);
-+
-+ /* Delete the reg-reg addition. */
-+ delete_insn (insn);
-+
-+ if (reg_state[regno].offset != const0_rtx)
-+ /* Previous REG_EQUIV / REG_EQUAL notes for PREV
-+ are now invalid. */
-+ remove_reg_equal_equiv_notes (prev);
-+
-+ reg_state[regno].use_index = RELOAD_COMBINE_MAX_USES;
-+ return true;
-+ }
-+ }
-+ }
-+ return false;
-+}
-+
- static void
- reload_combine (void)
- {
-- rtx insn, set;
-- int first_index_reg = -1;
-- int last_index_reg = 0;
-+ rtx insn, prev;
- int i;
- basic_block bb;
- unsigned int r;
-- int last_label_ruid;
- int min_labelno, n_labels;
- HARD_REG_SET ever_live_at_start, *label_live;
-
-- /* If reg+reg can be used in offsetable memory addresses, the main chunk of
-- reload has already used it where appropriate, so there is no use in
-- trying to generate it now. */
-- if (double_reg_address_ok && INDEX_REG_CLASS != NO_REGS)
-- return;
--
- /* To avoid wasting too much time later searching for an index register,
- determine the minimum and maximum index register numbers. */
-- for (r = 0; r < FIRST_PSEUDO_REGISTER; r++)
-- if (TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS], r))
-- {
-- if (first_index_reg == -1)
-- first_index_reg = r;
--
-- last_index_reg = r;
-- }
--
-- /* If no index register is available, we can quit now. */
-- if (first_index_reg == -1)
-- return;
-+ if (INDEX_REG_CLASS == NO_REGS)
-+ last_index_reg = -1;
-+ else if (first_index_reg == -1 && last_index_reg == 0)
-+ {
-+ for (r = 0; r < FIRST_PSEUDO_REGISTER; r++)
-+ if (TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS], r))
-+ {
-+ if (first_index_reg == -1)
-+ first_index_reg = r;
-+
-+ last_index_reg = r;
-+ }
-+
-+ /* If no index register is available, we can quit now. Set LAST_INDEX_REG
-+ to -1 so we'll know to quit early the next time we get here. */
-+ if (first_index_reg == -1)
-+ {
-+ last_index_reg = -1;
-+ return;
-+ }
-+ }
-
- /* Set up LABEL_LIVE and EVER_LIVE_AT_START. The register lifetime
- information is a bit fuzzy immediately after reload, but it's
-@@ -753,20 +1278,23 @@
- }
-
- /* Initialize last_label_ruid, reload_combine_ruid and reg_state. */
-- last_label_ruid = reload_combine_ruid = 0;
-+ last_label_ruid = last_jump_ruid = reload_combine_ruid = 0;
- for (r = 0; r < FIRST_PSEUDO_REGISTER; r++)
- {
-- reg_state[r].store_ruid = reload_combine_ruid;
-+ reg_state[r].store_ruid = 0;
-+ reg_state[r].real_store_ruid = 0;
- if (fixed_regs[r])
- reg_state[r].use_index = -1;
- else
- reg_state[r].use_index = RELOAD_COMBINE_MAX_USES;
- }
-
-- for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
-+ for (insn = get_last_insn (); insn; insn = prev)
- {
- rtx note;
-
-+ prev = PREV_INSN (insn);
-+
- /* We cannot do our optimization across labels. Invalidating all the use
- information we have would be costly, so we just note where the label
- is and then later disable any optimization that would cross it. */
-@@ -777,141 +1305,17 @@
- if (! fixed_regs[r])
- reg_state[r].use_index = RELOAD_COMBINE_MAX_USES;
-
-- if (! INSN_P (insn))
-+ if (! NONDEBUG_INSN_P (insn))
- continue;
-
- reload_combine_ruid++;
-
-- /* Look for (set (REGX) (CONST_INT))
-- (set (REGX) (PLUS (REGX) (REGY)))
-- ...
-- ... (MEM (REGX)) ...
-- and convert it to
-- (set (REGZ) (CONST_INT))
-- ...
-- ... (MEM (PLUS (REGZ) (REGY)))... .
--
-- First, check that we have (set (REGX) (PLUS (REGX) (REGY)))
-- and that we know all uses of REGX before it dies.
-- Also, explicitly check that REGX != REGY; our life information
-- does not yet show whether REGY changes in this insn. */
-- set = single_set (insn);
-- if (set != NULL_RTX
-- && REG_P (SET_DEST (set))
-- && (hard_regno_nregs[REGNO (SET_DEST (set))]
-- [GET_MODE (SET_DEST (set))]
-- == 1)
-- && GET_CODE (SET_SRC (set)) == PLUS
-- && REG_P (XEXP (SET_SRC (set), 1))
-- && rtx_equal_p (XEXP (SET_SRC (set), 0), SET_DEST (set))
-- && !rtx_equal_p (XEXP (SET_SRC (set), 1), SET_DEST (set))
-- && last_label_ruid < reg_state[REGNO (SET_DEST (set))].use_ruid)
-- {
-- rtx reg = SET_DEST (set);
-- rtx plus = SET_SRC (set);
-- rtx base = XEXP (plus, 1);
-- rtx prev = prev_nonnote_nondebug_insn (insn);
-- rtx prev_set = prev ? single_set (prev) : NULL_RTX;
-- unsigned int regno = REGNO (reg);
-- rtx index_reg = NULL_RTX;
-- rtx reg_sum = NULL_RTX;
--
-- /* Now we need to set INDEX_REG to an index register (denoted as
-- REGZ in the illustration above) and REG_SUM to the expression
-- register+register that we want to use to substitute uses of REG
-- (typically in MEMs) with. First check REG and BASE for being
-- index registers; we can use them even if they are not dead. */
-- if (TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS], regno)
-- || TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS],
-- REGNO (base)))
-- {
-- index_reg = reg;
-- reg_sum = plus;
-- }
-- else
-- {
-- /* Otherwise, look for a free index register. Since we have
-- checked above that neither REG nor BASE are index registers,
-- if we find anything at all, it will be different from these
-- two registers. */
-- for (i = first_index_reg; i <= last_index_reg; i++)
-- {
-- if (TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS],
-- i)
-- && reg_state[i].use_index == RELOAD_COMBINE_MAX_USES
-- && reg_state[i].store_ruid <= reg_state[regno].use_ruid
-- && hard_regno_nregs[i][GET_MODE (reg)] == 1)
-- {
-- index_reg = gen_rtx_REG (GET_MODE (reg), i);
-- reg_sum = gen_rtx_PLUS (GET_MODE (reg), index_reg, base);
-- break;
-- }
-- }
-- }
--
-- /* Check that PREV_SET is indeed (set (REGX) (CONST_INT)) and that
-- (REGY), i.e. BASE, is not clobbered before the last use we'll
-- create. */
-- if (reg_sum
-- && prev_set
-- && CONST_INT_P (SET_SRC (prev_set))
-- && rtx_equal_p (SET_DEST (prev_set), reg)
-- && reg_state[regno].use_index >= 0
-- && (reg_state[REGNO (base)].store_ruid
-- <= reg_state[regno].use_ruid))
-- {
-- int i;
--
-- /* Change destination register and, if necessary, the constant
-- value in PREV, the constant loading instruction. */
-- validate_change (prev, &SET_DEST (prev_set), index_reg, 1);
-- if (reg_state[regno].offset != const0_rtx)
-- validate_change (prev,
-- &SET_SRC (prev_set),
-- GEN_INT (INTVAL (SET_SRC (prev_set))
-- + INTVAL (reg_state[regno].offset)),
-- 1);
--
-- /* Now for every use of REG that we have recorded, replace REG
-- with REG_SUM. */
-- for (i = reg_state[regno].use_index;
-- i < RELOAD_COMBINE_MAX_USES; i++)
-- validate_unshare_change (reg_state[regno].reg_use[i].insn,
-- reg_state[regno].reg_use[i].usep,
-- /* Each change must have its own
-- replacement. */
-- reg_sum, 1);
--
-- if (apply_change_group ())
-- {
-- /* For every new use of REG_SUM, we have to record the use
-- of BASE therein, i.e. operand 1. */
-- for (i = reg_state[regno].use_index;
-- i < RELOAD_COMBINE_MAX_USES; i++)
-- reload_combine_note_use
-- (&XEXP (*reg_state[regno].reg_use[i].usep, 1),
-- reg_state[regno].reg_use[i].insn);
--
-- if (reg_state[REGNO (base)].use_ruid
-- > reg_state[regno].use_ruid)
-- reg_state[REGNO (base)].use_ruid
-- = reg_state[regno].use_ruid;
--
-- /* Delete the reg-reg addition. */
-- delete_insn (insn);
--
-- if (reg_state[regno].offset != const0_rtx)
-- /* Previous REG_EQUIV / REG_EQUAL notes for PREV
-- are now invalid. */
-- remove_reg_equal_equiv_notes (prev);
--
-- reg_state[regno].use_index = RELOAD_COMBINE_MAX_USES;
-- reg_state[REGNO (index_reg)].store_ruid
-- = reload_combine_ruid;
-- continue;
-- }
-- }
-- }
-+ if (control_flow_insn_p (insn))
-+ last_jump_ruid = reload_combine_ruid;
-+
-+ if (reload_combine_recognize_const_pattern (insn)
-+ || reload_combine_recognize_pattern (insn))
-+ continue;
-
- note_stores (PATTERN (insn), reload_combine_note_store, NULL);
-
-@@ -967,7 +1371,8 @@
- reg_state[i].use_index = -1;
- }
-
-- reload_combine_note_use (&PATTERN (insn), insn);
-+ reload_combine_note_use (&PATTERN (insn), insn,
-+ reload_combine_ruid, NULL_RTX);
- for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
- {
- if (REG_NOTE_KIND (note) == REG_INC
-@@ -976,6 +1381,7 @@
- int regno = REGNO (XEXP (note, 0));
-
- reg_state[regno].store_ruid = reload_combine_ruid;
-+ reg_state[regno].real_store_ruid = reload_combine_ruid;
- reg_state[regno].use_index = -1;
- }
- }
-@@ -985,8 +1391,8 @@
- }
-
- /* Check if DST is a register or a subreg of a register; if it is,
-- update reg_state[regno].store_ruid and reg_state[regno].use_index
-- accordingly. Called via note_stores from reload_combine. */
-+ update store_ruid, real_store_ruid and use_index in the reg_state
-+ structure accordingly. Called via note_stores from reload_combine. */
-
- static void
- reload_combine_note_store (rtx dst, const_rtx set, void *data ATTRIBUTE_UNUSED)
-@@ -1010,14 +1416,14 @@
- /* note_stores might have stripped a STRICT_LOW_PART, so we have to be
- careful with registers / register parts that are not full words.
- Similarly for ZERO_EXTRACT. */
-- if (GET_CODE (set) != SET
-- || GET_CODE (SET_DEST (set)) == ZERO_EXTRACT
-+ if (GET_CODE (SET_DEST (set)) == ZERO_EXTRACT
- || GET_CODE (SET_DEST (set)) == STRICT_LOW_PART)
- {
- for (i = hard_regno_nregs[regno][mode] - 1 + regno; i >= regno; i--)
- {
- reg_state[i].use_index = -1;
- reg_state[i].store_ruid = reload_combine_ruid;
-+ reg_state[i].real_store_ruid = reload_combine_ruid;
- }
- }
- else
-@@ -1025,6 +1431,8 @@
- for (i = hard_regno_nregs[regno][mode] - 1 + regno; i >= regno; i--)
- {
- reg_state[i].store_ruid = reload_combine_ruid;
-+ if (GET_CODE (set) == SET)
-+ reg_state[i].real_store_ruid = reload_combine_ruid;
- reg_state[i].use_index = RELOAD_COMBINE_MAX_USES;
- }
- }
-@@ -1035,7 +1443,7 @@
- *XP is the pattern of INSN, or a part of it.
- Called from reload_combine, and recursively by itself. */
- static void
--reload_combine_note_use (rtx *xp, rtx insn)
-+reload_combine_note_use (rtx *xp, rtx insn, int ruid, rtx containing_mem)
- {
- rtx x = *xp;
- enum rtx_code code = x->code;
-@@ -1048,7 +1456,7 @@
- case SET:
- if (REG_P (SET_DEST (x)))
- {
-- reload_combine_note_use (&SET_SRC (x), insn);
-+ reload_combine_note_use (&SET_SRC (x), insn, ruid, NULL_RTX);
- return;
- }
- break;
-@@ -1104,6 +1512,11 @@
- return;
- }
-
-+ /* We may be called to update uses in previously seen insns.
-+ Don't add uses beyond the last store we saw. */
-+ if (ruid < reg_state[regno].store_ruid)
-+ return;
-+
- /* If this register is already used in some unknown fashion, we
- can't do anything.
- If we decrement the index from zero to -1, we can't store more
-@@ -1112,29 +1525,34 @@
- if (use_index < 0)
- return;
-
-- if (use_index != RELOAD_COMBINE_MAX_USES - 1)
-- {
-- /* We have found another use for a register that is already
-- used later. Check if the offsets match; if not, mark the
-- register as used in an unknown fashion. */
-- if (! rtx_equal_p (offset, reg_state[regno].offset))
-- {
-- reg_state[regno].use_index = -1;
-- return;
-- }
-- }
-- else
-+ if (use_index == RELOAD_COMBINE_MAX_USES - 1)
- {
- /* This is the first use of this register we have seen since we
- marked it as dead. */
- reg_state[regno].offset = offset;
-- reg_state[regno].use_ruid = reload_combine_ruid;
-- }
-+ reg_state[regno].all_offsets_match = true;
-+ reg_state[regno].use_ruid = ruid;
-+ }
-+ else
-+ {
-+ if (reg_state[regno].use_ruid > ruid)
-+ reg_state[regno].use_ruid = ruid;
-+
-+ if (! rtx_equal_p (offset, reg_state[regno].offset))
-+ reg_state[regno].all_offsets_match = false;
-+ }
-+
- reg_state[regno].reg_use[use_index].insn = insn;
-+ reg_state[regno].reg_use[use_index].ruid = ruid;
-+ reg_state[regno].reg_use[use_index].containing_mem = containing_mem;
- reg_state[regno].reg_use[use_index].usep = xp;
- return;
- }
-
-+ case MEM:
-+ containing_mem = x;
-+ break;
-+
- default:
- break;
- }
-@@ -1144,11 +1562,12 @@
- for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
- {
- if (fmt[i] == 'e')
-- reload_combine_note_use (&XEXP (x, i), insn);
-+ reload_combine_note_use (&XEXP (x, i), insn, ruid, containing_mem);
- else if (fmt[i] == 'E')
- {
- for (j = XVECLEN (x, i) - 1; j >= 0; j--)
-- reload_combine_note_use (&XVECEXP (x, i, j), insn);
-+ reload_combine_note_use (&XVECEXP (x, i, j), insn, ruid,
-+ containing_mem);
- }
- }
- }
-@@ -1196,9 +1615,10 @@
- while REG is known to already have value (SYM + offset).
- This function tries to change INSN into an add instruction
- (set (REG) (plus (REG) (OFF - offset))) using the known value.
-- It also updates the information about REG's known value. */
-+ It also updates the information about REG's known value.
-+ Return true if we made a change. */
-
--static void
-+static bool
- move2add_use_add2_insn (rtx reg, rtx sym, rtx off, rtx insn)
- {
- rtx pat = PATTERN (insn);
-@@ -1207,6 +1627,7 @@
- rtx new_src = gen_int_mode (INTVAL (off) - reg_offset[regno],
- GET_MODE (reg));
- bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (insn));
-+ bool changed = false;
-
- /* (set (reg) (plus (reg) (const_int 0))) is not canonical;
- use (set (reg) (reg)) instead.
-@@ -1221,13 +1642,13 @@
- (reg)), would be discarded. Maybe we should
- try a truncMN pattern? */
- if (INTVAL (off) == reg_offset [regno])
-- validate_change (insn, &SET_SRC (pat), reg, 0);
-+ changed = validate_change (insn, &SET_SRC (pat), reg, 0);
- }
- else if (rtx_cost (new_src, PLUS, speed) < rtx_cost (src, SET, speed)
- && have_add2_insn (reg, new_src))
- {
- rtx tem = gen_rtx_PLUS (GET_MODE (reg), reg, new_src);
-- validate_change (insn, &SET_SRC (pat), tem, 0);
-+ changed = validate_change (insn, &SET_SRC (pat), tem, 0);
- }
- else if (sym == NULL_RTX && GET_MODE (reg) != BImode)
- {
-@@ -1252,8 +1673,9 @@
- gen_rtx_STRICT_LOW_PART (VOIDmode,
- narrow_reg),
- narrow_src);
-- if (validate_change (insn, &PATTERN (insn),
-- new_set, 0))
-+ changed = validate_change (insn, &PATTERN (insn),
-+ new_set, 0);
-+ if (changed)
- break;
- }
- }
-@@ -1263,6 +1685,7 @@
- reg_mode[regno] = GET_MODE (reg);
- reg_symbol_ref[regno] = sym;
- reg_offset[regno] = INTVAL (off);
-+ return changed;
- }
-
-
-@@ -1272,9 +1695,10 @@
- value (SYM + offset) and change INSN into an add instruction
- (set (REG) (plus (the found register) (OFF - offset))) if such
- a register is found. It also updates the information about
-- REG's known value. */
-+ REG's known value.
-+ Return true iff we made a change. */
-
--static void
-+static bool
- move2add_use_add3_insn (rtx reg, rtx sym, rtx off, rtx insn)
- {
- rtx pat = PATTERN (insn);
-@@ -1284,6 +1708,7 @@
- int min_regno;
- bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (insn));
- int i;
-+ bool changed = false;
-
- for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- if (reg_set_luid[i] > move2add_last_label_luid
-@@ -1328,20 +1753,25 @@
- GET_MODE (reg));
- tem = gen_rtx_PLUS (GET_MODE (reg), tem, new_src);
- }
-- validate_change (insn, &SET_SRC (pat), tem, 0);
-+ if (validate_change (insn, &SET_SRC (pat), tem, 0))
-+ changed = true;
- }
- reg_set_luid[regno] = move2add_luid;
- reg_base_reg[regno] = -1;
- reg_mode[regno] = GET_MODE (reg);
- reg_symbol_ref[regno] = sym;
- reg_offset[regno] = INTVAL (off);
-+ return changed;
- }
-
--static void
-+/* Convert move insns with constant inputs to additions if they are cheaper.
-+ Return true if any changes were made. */
-+static bool
- reload_cse_move2add (rtx first)
- {
- int i;
- rtx insn;
-+ bool changed = false;
-
- for (i = FIRST_PSEUDO_REGISTER - 1; i >= 0; i--)
- {
-@@ -1402,7 +1832,7 @@
- && reg_base_reg[regno] < 0
- && reg_symbol_ref[regno] == NULL_RTX)
- {
-- move2add_use_add2_insn (reg, NULL_RTX, src, insn);
-+ changed |= move2add_use_add2_insn (reg, NULL_RTX, src, insn);
- continue;
- }
-
-@@ -1463,6 +1893,7 @@
- }
- if (success)
- delete_insn (insn);
-+ changed |= success;
- insn = next;
- reg_mode[regno] = GET_MODE (reg);
- reg_offset[regno] =
-@@ -1508,12 +1939,12 @@
- && reg_base_reg[regno] < 0
- && reg_symbol_ref[regno] != NULL_RTX
- && rtx_equal_p (sym, reg_symbol_ref[regno]))
-- move2add_use_add2_insn (reg, sym, off, insn);
-+ changed |= move2add_use_add2_insn (reg, sym, off, insn);
-
- /* Otherwise, we have to find a register whose value is sum
- of sym and some constant value. */
- else
-- move2add_use_add3_insn (reg, sym, off, insn);
-+ changed |= move2add_use_add3_insn (reg, sym, off, insn);
-
- continue;
- }
-@@ -1568,6 +1999,7 @@
- }
- }
- }
-+ return changed;
- }
-
- /* SET is a SET or CLOBBER that sets DST. DATA is the insn which
-