aboutsummaryrefslogtreecommitdiffstats
path: root/meta-oe/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99314.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-oe/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99314.patch')
-rw-r--r--meta-oe/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99314.patch433
1 files changed, 433 insertions, 0 deletions
diff --git a/meta-oe/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99314.patch b/meta-oe/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99314.patch
new file mode 100644
index 0000000000..216fcac723
--- /dev/null
+++ b/meta-oe/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99314.patch
@@ -0,0 +1,433 @@
+2010-07-16 Jie Zhang <jie@codesourcery.com>
+
+ Issue #7688
+
+ Backport from mainline:
+
+ gcc/
+ 2010-07-12 Jie Zhang <jie@codesourcery.com>
+ * postreload.c (reg_symbol_ref[]): New.
+ (move2add_use_add2_insn): New.
+ (move2add_use_add3_insn): New.
+ (reload_cse_move2add): Handle SYMBOL + OFFSET case.
+ (move2add_note_store): Likewise.
+
+ 2010-07-15 Yao Qi <yao@codesourcery.com>
+
+ Merge from Sourcery G++ 4.4:
+
+=== modified file 'gcc/postreload.c'
+--- old/gcc/postreload.c 2010-03-16 10:50:42 +0000
++++ new/gcc/postreload.c 2010-08-02 16:55:34 +0000
+@@ -1160,17 +1160,19 @@
+ information about register contents we have would be costly, so we
+ use move2add_last_label_luid to note where the label is and then
+ later disable any optimization that would cross it.
+- reg_offset[n] / reg_base_reg[n] / reg_mode[n] are only valid if
+- reg_set_luid[n] is greater than move2add_last_label_luid. */
++ reg_offset[n] / reg_base_reg[n] / reg_symbol_ref[n] / reg_mode[n]
++ are only valid if reg_set_luid[n] is greater than
++ move2add_last_label_luid. */
+ static int reg_set_luid[FIRST_PSEUDO_REGISTER];
+
+ /* If reg_base_reg[n] is negative, register n has been set to
+- reg_offset[n] in mode reg_mode[n] .
++ reg_offset[n] or reg_symbol_ref[n] + reg_offset[n] in mode reg_mode[n].
+ If reg_base_reg[n] is non-negative, register n has been set to the
+ sum of reg_offset[n] and the value of register reg_base_reg[n]
+ before reg_set_luid[n], calculated in mode reg_mode[n] . */
+ static HOST_WIDE_INT reg_offset[FIRST_PSEUDO_REGISTER];
+ static int reg_base_reg[FIRST_PSEUDO_REGISTER];
++static rtx reg_symbol_ref[FIRST_PSEUDO_REGISTER];
+ static enum machine_mode reg_mode[FIRST_PSEUDO_REGISTER];
+
+ /* move2add_luid is linearly increased while scanning the instructions
+@@ -1190,6 +1192,151 @@
+ && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (OUTMODE), \
+ GET_MODE_BITSIZE (INMODE))))
+
++/* This function is called with INSN that sets REG to (SYM + OFF),
++ 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. */
++
++static void
++move2add_use_add2_insn (rtx reg, rtx sym, rtx off, rtx insn)
++{
++ rtx pat = PATTERN (insn);
++ rtx src = SET_SRC (pat);
++ int regno = REGNO (reg);
++ 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));
++
++ /* (set (reg) (plus (reg) (const_int 0))) is not canonical;
++ use (set (reg) (reg)) instead.
++ We don't delete this insn, nor do we convert it into a
++ note, to avoid losing register notes or the return
++ value flag. jump2 already knows how to get rid of
++ no-op moves. */
++ if (new_src == const0_rtx)
++ {
++ /* If the constants are different, this is a
++ truncation, that, if turned into (set (reg)
++ (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);
++ }
++ 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);
++ }
++ else if (sym == NULL_RTX && GET_MODE (reg) != BImode)
++ {
++ enum machine_mode narrow_mode;
++ for (narrow_mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
++ narrow_mode != VOIDmode
++ && narrow_mode != GET_MODE (reg);
++ narrow_mode = GET_MODE_WIDER_MODE (narrow_mode))
++ {
++ if (have_insn_for (STRICT_LOW_PART, narrow_mode)
++ && ((reg_offset[regno]
++ & ~GET_MODE_MASK (narrow_mode))
++ == (INTVAL (off)
++ & ~GET_MODE_MASK (narrow_mode))))
++ {
++ rtx narrow_reg = gen_rtx_REG (narrow_mode,
++ REGNO (reg));
++ rtx narrow_src = gen_int_mode (INTVAL (off),
++ narrow_mode);
++ rtx new_set =
++ gen_rtx_SET (VOIDmode,
++ gen_rtx_STRICT_LOW_PART (VOIDmode,
++ narrow_reg),
++ narrow_src);
++ if (validate_change (insn, &PATTERN (insn),
++ new_set, 0))
++ break;
++ }
++ }
++ }
++ 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);
++}
++
++
++/* This function is called with INSN that sets REG to (SYM + OFF),
++ but REG doesn't have known value (SYM + offset). This function
++ tries to find another register which is known to already have
++ 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. */
++
++static void
++move2add_use_add3_insn (rtx reg, rtx sym, rtx off, rtx insn)
++{
++ rtx pat = PATTERN (insn);
++ rtx src = SET_SRC (pat);
++ int regno = REGNO (reg);
++ int min_cost = INT_MAX;
++ int min_regno;
++ bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (insn));
++ int i;
++
++ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
++ if (reg_set_luid[i] > move2add_last_label_luid
++ && reg_mode[i] == GET_MODE (reg)
++ && reg_base_reg[i] < 0
++ && reg_symbol_ref[i] != NULL_RTX
++ && rtx_equal_p (sym, reg_symbol_ref[i]))
++ {
++ rtx new_src = gen_int_mode (INTVAL (off) - reg_offset[i],
++ GET_MODE (reg));
++ /* (set (reg) (plus (reg) (const_int 0))) is not canonical;
++ use (set (reg) (reg)) instead.
++ We don't delete this insn, nor do we convert it into a
++ note, to avoid losing register notes or the return
++ value flag. jump2 already knows how to get rid of
++ no-op moves. */
++ if (new_src == const0_rtx)
++ {
++ min_cost = 0;
++ min_regno = i;
++ break;
++ }
++ else
++ {
++ int cost = rtx_cost (new_src, PLUS, speed);
++ if (cost < min_cost)
++ {
++ min_cost = cost;
++ min_regno = i;
++ }
++ }
++ }
++
++ if (min_cost < rtx_cost (src, SET, speed))
++ {
++ rtx tem;
++
++ tem = gen_rtx_REG (GET_MODE (reg), min_regno);
++ if (i != min_regno)
++ {
++ rtx new_src = gen_int_mode (INTVAL (off) - reg_offset[min_regno],
++ GET_MODE (reg));
++ tem = gen_rtx_PLUS (GET_MODE (reg), tem, new_src);
++ }
++ validate_change (insn, &SET_SRC (pat), tem, 0);
++ }
++ 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);
++}
++
+ static void
+ reload_cse_move2add (rtx first)
+ {
+@@ -1197,7 +1344,13 @@
+ rtx insn;
+
+ for (i = FIRST_PSEUDO_REGISTER - 1; i >= 0; i--)
+- reg_set_luid[i] = 0;
++ {
++ reg_set_luid[i] = 0;
++ reg_offset[i] = 0;
++ reg_base_reg[i] = 0;
++ reg_symbol_ref[i] = NULL_RTX;
++ reg_mode[i] = VOIDmode;
++ }
+
+ move2add_last_label_luid = 0;
+ move2add_luid = 2;
+@@ -1245,65 +1398,11 @@
+ (set (STRICT_LOW_PART (REGX)) (CONST_INT B))
+ */
+
+- if (CONST_INT_P (src) && reg_base_reg[regno] < 0)
++ if (CONST_INT_P (src)
++ && reg_base_reg[regno] < 0
++ && reg_symbol_ref[regno] == NULL_RTX)
+ {
+- rtx new_src = gen_int_mode (INTVAL (src) - reg_offset[regno],
+- GET_MODE (reg));
+- bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (insn));
+-
+- /* (set (reg) (plus (reg) (const_int 0))) is not canonical;
+- use (set (reg) (reg)) instead.
+- We don't delete this insn, nor do we convert it into a
+- note, to avoid losing register notes or the return
+- value flag. jump2 already knows how to get rid of
+- no-op moves. */
+- if (new_src == const0_rtx)
+- {
+- /* If the constants are different, this is a
+- truncation, that, if turned into (set (reg)
+- (reg)), would be discarded. Maybe we should
+- try a truncMN pattern? */
+- if (INTVAL (src) == reg_offset [regno])
+- 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);
+- }
+- else if (GET_MODE (reg) != BImode)
+- {
+- enum machine_mode narrow_mode;
+- for (narrow_mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
+- narrow_mode != VOIDmode
+- && narrow_mode != GET_MODE (reg);
+- narrow_mode = GET_MODE_WIDER_MODE (narrow_mode))
+- {
+- if (have_insn_for (STRICT_LOW_PART, narrow_mode)
+- && ((reg_offset[regno]
+- & ~GET_MODE_MASK (narrow_mode))
+- == (INTVAL (src)
+- & ~GET_MODE_MASK (narrow_mode))))
+- {
+- rtx narrow_reg = gen_rtx_REG (narrow_mode,
+- REGNO (reg));
+- rtx narrow_src = gen_int_mode (INTVAL (src),
+- narrow_mode);
+- rtx new_set =
+- gen_rtx_SET (VOIDmode,
+- gen_rtx_STRICT_LOW_PART (VOIDmode,
+- narrow_reg),
+- narrow_src);
+- if (validate_change (insn, &PATTERN (insn),
+- new_set, 0))
+- break;
+- }
+- }
+- }
+- reg_set_luid[regno] = move2add_luid;
+- reg_mode[regno] = GET_MODE (reg);
+- reg_offset[regno] = INTVAL (src);
++ move2add_use_add2_insn (reg, NULL_RTX, src, insn);
+ continue;
+ }
+
+@@ -1373,6 +1472,51 @@
+ }
+ }
+ }
++
++ /* Try to transform
++ (set (REGX) (CONST (PLUS (SYMBOL_REF) (CONST_INT A))))
++ ...
++ (set (REGY) (CONST (PLUS (SYMBOL_REF) (CONST_INT B))))
++ to
++ (set (REGX) (CONST (PLUS (SYMBOL_REF) (CONST_INT A))))
++ ...
++ (set (REGY) (CONST (PLUS (REGX) (CONST_INT B-A)))) */
++ if ((GET_CODE (src) == SYMBOL_REF
++ || (GET_CODE (src) == CONST
++ && GET_CODE (XEXP (src, 0)) == PLUS
++ && GET_CODE (XEXP (XEXP (src, 0), 0)) == SYMBOL_REF
++ && CONST_INT_P (XEXP (XEXP (src, 0), 1))))
++ && dbg_cnt (cse2_move2add))
++ {
++ rtx sym, off;
++
++ if (GET_CODE (src) == SYMBOL_REF)
++ {
++ sym = src;
++ off = const0_rtx;
++ }
++ else
++ {
++ sym = XEXP (XEXP (src, 0), 0);
++ off = XEXP (XEXP (src, 0), 1);
++ }
++
++ /* If the reg already contains the value which is sum of
++ sym and some constant value, we can use an add2 insn. */
++ if (reg_set_luid[regno] > move2add_last_label_luid
++ && MODES_OK_FOR_MOVE2ADD (GET_MODE (reg), reg_mode[regno])
++ && 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);
++
++ /* 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);
++
++ continue;
++ }
+ }
+
+ for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
+@@ -1386,7 +1530,7 @@
+ reg_set_luid[regno] = 0;
+ }
+ }
+- note_stores (PATTERN (insn), move2add_note_store, NULL);
++ note_stores (PATTERN (insn), move2add_note_store, insn);
+
+ /* If INSN is a conditional branch, we try to extract an
+ implicit set out of it. */
+@@ -1408,7 +1552,7 @@
+ {
+ rtx implicit_set =
+ gen_rtx_SET (VOIDmode, XEXP (cnd, 0), XEXP (cnd, 1));
+- move2add_note_store (SET_DEST (implicit_set), implicit_set, 0);
++ move2add_note_store (SET_DEST (implicit_set), implicit_set, insn);
+ }
+ }
+
+@@ -1426,13 +1570,15 @@
+ }
+ }
+
+-/* SET is a SET or CLOBBER that sets DST.
++/* SET is a SET or CLOBBER that sets DST. DATA is the insn which
++ contains SET.
+ Update reg_set_luid, reg_offset and reg_base_reg accordingly.
+ Called from reload_cse_move2add via note_stores. */
+
+ static void
+-move2add_note_store (rtx dst, const_rtx set, void *data ATTRIBUTE_UNUSED)
++move2add_note_store (rtx dst, const_rtx set, void *data)
+ {
++ rtx insn = (rtx) data;
+ unsigned int regno = 0;
+ unsigned int nregs = 0;
+ unsigned int i;
+@@ -1466,6 +1612,38 @@
+ nregs = hard_regno_nregs[regno][mode];
+
+ if (SCALAR_INT_MODE_P (GET_MODE (dst))
++ && nregs == 1 && GET_CODE (set) == SET)
++ {
++ rtx note, sym = NULL_RTX;
++ HOST_WIDE_INT off;
++
++ note = find_reg_equal_equiv_note (insn);
++ if (note && GET_CODE (XEXP (note, 0)) == SYMBOL_REF)
++ {
++ sym = XEXP (note, 0);
++ off = 0;
++ }
++ else if (note && GET_CODE (XEXP (note, 0)) == CONST
++ && GET_CODE (XEXP (XEXP (note, 0), 0)) == PLUS
++ && GET_CODE (XEXP (XEXP (XEXP (note, 0), 0), 0)) == SYMBOL_REF
++ && CONST_INT_P (XEXP (XEXP (XEXP (note, 0), 0), 1)))
++ {
++ sym = XEXP (XEXP (XEXP (note, 0), 0), 0);
++ off = INTVAL (XEXP (XEXP (XEXP (note, 0), 0), 1));
++ }
++
++ if (sym != NULL_RTX)
++ {
++ reg_base_reg[regno] = -1;
++ reg_symbol_ref[regno] = sym;
++ reg_offset[regno] = off;
++ reg_mode[regno] = mode;
++ reg_set_luid[regno] = move2add_luid;
++ return;
++ }
++ }
++
++ if (SCALAR_INT_MODE_P (GET_MODE (dst))
+ && nregs == 1 && GET_CODE (set) == SET
+ && GET_CODE (SET_DEST (set)) != ZERO_EXTRACT
+ && GET_CODE (SET_DEST (set)) != STRICT_LOW_PART)
+@@ -1525,6 +1703,7 @@
+ case CONST_INT:
+ /* Start tracking the register as a constant. */
+ reg_base_reg[regno] = -1;
++ reg_symbol_ref[regno] = NULL_RTX;
+ reg_offset[regno] = INTVAL (SET_SRC (set));
+ /* We assign the same luid to all registers set to constants. */
+ reg_set_luid[regno] = move2add_last_label_luid + 1;
+@@ -1545,6 +1724,7 @@
+ if (reg_set_luid[base_regno] <= move2add_last_label_luid)
+ {
+ reg_base_reg[base_regno] = base_regno;
++ reg_symbol_ref[base_regno] = NULL_RTX;
+ reg_offset[base_regno] = 0;
+ reg_set_luid[base_regno] = move2add_luid;
+ reg_mode[base_regno] = mode;
+@@ -1558,6 +1738,7 @@
+ /* Copy base information from our base register. */
+ reg_set_luid[regno] = reg_set_luid[base_regno];
+ reg_base_reg[regno] = reg_base_reg[base_regno];
++ reg_symbol_ref[regno] = reg_symbol_ref[base_regno];
+
+ /* Compute the sum of the offsets or constants. */
+ reg_offset[regno] = trunc_int_for_mode (offset
+