summaryrefslogtreecommitdiffstats
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 000000000..216fcac72
--- /dev/null
+++ b/meta-oe/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99314.patch
@@ -0,0 +1,433 @@
12010-07-16 Jie Zhang <jie@codesourcery.com>
2
3 Issue #7688
4
5 Backport from mainline:
6
7 gcc/
8 2010-07-12 Jie Zhang <jie@codesourcery.com>
9 * postreload.c (reg_symbol_ref[]): New.
10 (move2add_use_add2_insn): New.
11 (move2add_use_add3_insn): New.
12 (reload_cse_move2add): Handle SYMBOL + OFFSET case.
13 (move2add_note_store): Likewise.
14
15 2010-07-15 Yao Qi <yao@codesourcery.com>
16
17 Merge from Sourcery G++ 4.4:
18
19=== modified file 'gcc/postreload.c'
20--- old/gcc/postreload.c 2010-03-16 10:50:42 +0000
21+++ new/gcc/postreload.c 2010-08-02 16:55:34 +0000
22@@ -1160,17 +1160,19 @@
23 information about register contents we have would be costly, so we
24 use move2add_last_label_luid to note where the label is and then
25 later disable any optimization that would cross it.
26- reg_offset[n] / reg_base_reg[n] / reg_mode[n] are only valid if
27- reg_set_luid[n] is greater than move2add_last_label_luid. */
28+ reg_offset[n] / reg_base_reg[n] / reg_symbol_ref[n] / reg_mode[n]
29+ are only valid if reg_set_luid[n] is greater than
30+ move2add_last_label_luid. */
31 static int reg_set_luid[FIRST_PSEUDO_REGISTER];
32
33 /* If reg_base_reg[n] is negative, register n has been set to
34- reg_offset[n] in mode reg_mode[n] .
35+ reg_offset[n] or reg_symbol_ref[n] + reg_offset[n] in mode reg_mode[n].
36 If reg_base_reg[n] is non-negative, register n has been set to the
37 sum of reg_offset[n] and the value of register reg_base_reg[n]
38 before reg_set_luid[n], calculated in mode reg_mode[n] . */
39 static HOST_WIDE_INT reg_offset[FIRST_PSEUDO_REGISTER];
40 static int reg_base_reg[FIRST_PSEUDO_REGISTER];
41+static rtx reg_symbol_ref[FIRST_PSEUDO_REGISTER];
42 static enum machine_mode reg_mode[FIRST_PSEUDO_REGISTER];
43
44 /* move2add_luid is linearly increased while scanning the instructions
45@@ -1190,6 +1192,151 @@
46 && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (OUTMODE), \
47 GET_MODE_BITSIZE (INMODE))))
48
49+/* This function is called with INSN that sets REG to (SYM + OFF),
50+ while REG is known to already have value (SYM + offset).
51+ This function tries to change INSN into an add instruction
52+ (set (REG) (plus (REG) (OFF - offset))) using the known value.
53+ It also updates the information about REG's known value. */
54+
55+static void
56+move2add_use_add2_insn (rtx reg, rtx sym, rtx off, rtx insn)
57+{
58+ rtx pat = PATTERN (insn);
59+ rtx src = SET_SRC (pat);
60+ int regno = REGNO (reg);
61+ rtx new_src = gen_int_mode (INTVAL (off) - reg_offset[regno],
62+ GET_MODE (reg));
63+ bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (insn));
64+
65+ /* (set (reg) (plus (reg) (const_int 0))) is not canonical;
66+ use (set (reg) (reg)) instead.
67+ We don't delete this insn, nor do we convert it into a
68+ note, to avoid losing register notes or the return
69+ value flag. jump2 already knows how to get rid of
70+ no-op moves. */
71+ if (new_src == const0_rtx)
72+ {
73+ /* If the constants are different, this is a
74+ truncation, that, if turned into (set (reg)
75+ (reg)), would be discarded. Maybe we should
76+ try a truncMN pattern? */
77+ if (INTVAL (off) == reg_offset [regno])
78+ validate_change (insn, &SET_SRC (pat), reg, 0);
79+ }
80+ else if (rtx_cost (new_src, PLUS, speed) < rtx_cost (src, SET, speed)
81+ && have_add2_insn (reg, new_src))
82+ {
83+ rtx tem = gen_rtx_PLUS (GET_MODE (reg), reg, new_src);
84+ validate_change (insn, &SET_SRC (pat), tem, 0);
85+ }
86+ else if (sym == NULL_RTX && GET_MODE (reg) != BImode)
87+ {
88+ enum machine_mode narrow_mode;
89+ for (narrow_mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
90+ narrow_mode != VOIDmode
91+ && narrow_mode != GET_MODE (reg);
92+ narrow_mode = GET_MODE_WIDER_MODE (narrow_mode))
93+ {
94+ if (have_insn_for (STRICT_LOW_PART, narrow_mode)
95+ && ((reg_offset[regno]
96+ & ~GET_MODE_MASK (narrow_mode))
97+ == (INTVAL (off)
98+ & ~GET_MODE_MASK (narrow_mode))))
99+ {
100+ rtx narrow_reg = gen_rtx_REG (narrow_mode,
101+ REGNO (reg));
102+ rtx narrow_src = gen_int_mode (INTVAL (off),
103+ narrow_mode);
104+ rtx new_set =
105+ gen_rtx_SET (VOIDmode,
106+ gen_rtx_STRICT_LOW_PART (VOIDmode,
107+ narrow_reg),
108+ narrow_src);
109+ if (validate_change (insn, &PATTERN (insn),
110+ new_set, 0))
111+ break;
112+ }
113+ }
114+ }
115+ reg_set_luid[regno] = move2add_luid;
116+ reg_base_reg[regno] = -1;
117+ reg_mode[regno] = GET_MODE (reg);
118+ reg_symbol_ref[regno] = sym;
119+ reg_offset[regno] = INTVAL (off);
120+}
121+
122+
123+/* This function is called with INSN that sets REG to (SYM + OFF),
124+ but REG doesn't have known value (SYM + offset). This function
125+ tries to find another register which is known to already have
126+ value (SYM + offset) and change INSN into an add instruction
127+ (set (REG) (plus (the found register) (OFF - offset))) if such
128+ a register is found. It also updates the information about
129+ REG's known value. */
130+
131+static void
132+move2add_use_add3_insn (rtx reg, rtx sym, rtx off, rtx insn)
133+{
134+ rtx pat = PATTERN (insn);
135+ rtx src = SET_SRC (pat);
136+ int regno = REGNO (reg);
137+ int min_cost = INT_MAX;
138+ int min_regno;
139+ bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (insn));
140+ int i;
141+
142+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
143+ if (reg_set_luid[i] > move2add_last_label_luid
144+ && reg_mode[i] == GET_MODE (reg)
145+ && reg_base_reg[i] < 0
146+ && reg_symbol_ref[i] != NULL_RTX
147+ && rtx_equal_p (sym, reg_symbol_ref[i]))
148+ {
149+ rtx new_src = gen_int_mode (INTVAL (off) - reg_offset[i],
150+ GET_MODE (reg));
151+ /* (set (reg) (plus (reg) (const_int 0))) is not canonical;
152+ use (set (reg) (reg)) instead.
153+ We don't delete this insn, nor do we convert it into a
154+ note, to avoid losing register notes or the return
155+ value flag. jump2 already knows how to get rid of
156+ no-op moves. */
157+ if (new_src == const0_rtx)
158+ {
159+ min_cost = 0;
160+ min_regno = i;
161+ break;
162+ }
163+ else
164+ {
165+ int cost = rtx_cost (new_src, PLUS, speed);
166+ if (cost < min_cost)
167+ {
168+ min_cost = cost;
169+ min_regno = i;
170+ }
171+ }
172+ }
173+
174+ if (min_cost < rtx_cost (src, SET, speed))
175+ {
176+ rtx tem;
177+
178+ tem = gen_rtx_REG (GET_MODE (reg), min_regno);
179+ if (i != min_regno)
180+ {
181+ rtx new_src = gen_int_mode (INTVAL (off) - reg_offset[min_regno],
182+ GET_MODE (reg));
183+ tem = gen_rtx_PLUS (GET_MODE (reg), tem, new_src);
184+ }
185+ validate_change (insn, &SET_SRC (pat), tem, 0);
186+ }
187+ reg_set_luid[regno] = move2add_luid;
188+ reg_base_reg[regno] = -1;
189+ reg_mode[regno] = GET_MODE (reg);
190+ reg_symbol_ref[regno] = sym;
191+ reg_offset[regno] = INTVAL (off);
192+}
193+
194 static void
195 reload_cse_move2add (rtx first)
196 {
197@@ -1197,7 +1344,13 @@
198 rtx insn;
199
200 for (i = FIRST_PSEUDO_REGISTER - 1; i >= 0; i--)
201- reg_set_luid[i] = 0;
202+ {
203+ reg_set_luid[i] = 0;
204+ reg_offset[i] = 0;
205+ reg_base_reg[i] = 0;
206+ reg_symbol_ref[i] = NULL_RTX;
207+ reg_mode[i] = VOIDmode;
208+ }
209
210 move2add_last_label_luid = 0;
211 move2add_luid = 2;
212@@ -1245,65 +1398,11 @@
213 (set (STRICT_LOW_PART (REGX)) (CONST_INT B))
214 */
215
216- if (CONST_INT_P (src) && reg_base_reg[regno] < 0)
217+ if (CONST_INT_P (src)
218+ && reg_base_reg[regno] < 0
219+ && reg_symbol_ref[regno] == NULL_RTX)
220 {
221- rtx new_src = gen_int_mode (INTVAL (src) - reg_offset[regno],
222- GET_MODE (reg));
223- bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (insn));
224-
225- /* (set (reg) (plus (reg) (const_int 0))) is not canonical;
226- use (set (reg) (reg)) instead.
227- We don't delete this insn, nor do we convert it into a
228- note, to avoid losing register notes or the return
229- value flag. jump2 already knows how to get rid of
230- no-op moves. */
231- if (new_src == const0_rtx)
232- {
233- /* If the constants are different, this is a
234- truncation, that, if turned into (set (reg)
235- (reg)), would be discarded. Maybe we should
236- try a truncMN pattern? */
237- if (INTVAL (src) == reg_offset [regno])
238- validate_change (insn, &SET_SRC (pat), reg, 0);
239- }
240- else if (rtx_cost (new_src, PLUS, speed) < rtx_cost (src, SET, speed)
241- && have_add2_insn (reg, new_src))
242- {
243- rtx tem = gen_rtx_PLUS (GET_MODE (reg), reg, new_src);
244- validate_change (insn, &SET_SRC (pat), tem, 0);
245- }
246- else if (GET_MODE (reg) != BImode)
247- {
248- enum machine_mode narrow_mode;
249- for (narrow_mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
250- narrow_mode != VOIDmode
251- && narrow_mode != GET_MODE (reg);
252- narrow_mode = GET_MODE_WIDER_MODE (narrow_mode))
253- {
254- if (have_insn_for (STRICT_LOW_PART, narrow_mode)
255- && ((reg_offset[regno]
256- & ~GET_MODE_MASK (narrow_mode))
257- == (INTVAL (src)
258- & ~GET_MODE_MASK (narrow_mode))))
259- {
260- rtx narrow_reg = gen_rtx_REG (narrow_mode,
261- REGNO (reg));
262- rtx narrow_src = gen_int_mode (INTVAL (src),
263- narrow_mode);
264- rtx new_set =
265- gen_rtx_SET (VOIDmode,
266- gen_rtx_STRICT_LOW_PART (VOIDmode,
267- narrow_reg),
268- narrow_src);
269- if (validate_change (insn, &PATTERN (insn),
270- new_set, 0))
271- break;
272- }
273- }
274- }
275- reg_set_luid[regno] = move2add_luid;
276- reg_mode[regno] = GET_MODE (reg);
277- reg_offset[regno] = INTVAL (src);
278+ move2add_use_add2_insn (reg, NULL_RTX, src, insn);
279 continue;
280 }
281
282@@ -1373,6 +1472,51 @@
283 }
284 }
285 }
286+
287+ /* Try to transform
288+ (set (REGX) (CONST (PLUS (SYMBOL_REF) (CONST_INT A))))
289+ ...
290+ (set (REGY) (CONST (PLUS (SYMBOL_REF) (CONST_INT B))))
291+ to
292+ (set (REGX) (CONST (PLUS (SYMBOL_REF) (CONST_INT A))))
293+ ...
294+ (set (REGY) (CONST (PLUS (REGX) (CONST_INT B-A)))) */
295+ if ((GET_CODE (src) == SYMBOL_REF
296+ || (GET_CODE (src) == CONST
297+ && GET_CODE (XEXP (src, 0)) == PLUS
298+ && GET_CODE (XEXP (XEXP (src, 0), 0)) == SYMBOL_REF
299+ && CONST_INT_P (XEXP (XEXP (src, 0), 1))))
300+ && dbg_cnt (cse2_move2add))
301+ {
302+ rtx sym, off;
303+
304+ if (GET_CODE (src) == SYMBOL_REF)
305+ {
306+ sym = src;
307+ off = const0_rtx;
308+ }
309+ else
310+ {
311+ sym = XEXP (XEXP (src, 0), 0);
312+ off = XEXP (XEXP (src, 0), 1);
313+ }
314+
315+ /* If the reg already contains the value which is sum of
316+ sym and some constant value, we can use an add2 insn. */
317+ if (reg_set_luid[regno] > move2add_last_label_luid
318+ && MODES_OK_FOR_MOVE2ADD (GET_MODE (reg), reg_mode[regno])
319+ && reg_base_reg[regno] < 0
320+ && reg_symbol_ref[regno] != NULL_RTX
321+ && rtx_equal_p (sym, reg_symbol_ref[regno]))
322+ move2add_use_add2_insn (reg, sym, off, insn);
323+
324+ /* Otherwise, we have to find a register whose value is sum
325+ of sym and some constant value. */
326+ else
327+ move2add_use_add3_insn (reg, sym, off, insn);
328+
329+ continue;
330+ }
331 }
332
333 for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
334@@ -1386,7 +1530,7 @@
335 reg_set_luid[regno] = 0;
336 }
337 }
338- note_stores (PATTERN (insn), move2add_note_store, NULL);
339+ note_stores (PATTERN (insn), move2add_note_store, insn);
340
341 /* If INSN is a conditional branch, we try to extract an
342 implicit set out of it. */
343@@ -1408,7 +1552,7 @@
344 {
345 rtx implicit_set =
346 gen_rtx_SET (VOIDmode, XEXP (cnd, 0), XEXP (cnd, 1));
347- move2add_note_store (SET_DEST (implicit_set), implicit_set, 0);
348+ move2add_note_store (SET_DEST (implicit_set), implicit_set, insn);
349 }
350 }
351
352@@ -1426,13 +1570,15 @@
353 }
354 }
355
356-/* SET is a SET or CLOBBER that sets DST.
357+/* SET is a SET or CLOBBER that sets DST. DATA is the insn which
358+ contains SET.
359 Update reg_set_luid, reg_offset and reg_base_reg accordingly.
360 Called from reload_cse_move2add via note_stores. */
361
362 static void
363-move2add_note_store (rtx dst, const_rtx set, void *data ATTRIBUTE_UNUSED)
364+move2add_note_store (rtx dst, const_rtx set, void *data)
365 {
366+ rtx insn = (rtx) data;
367 unsigned int regno = 0;
368 unsigned int nregs = 0;
369 unsigned int i;
370@@ -1466,6 +1612,38 @@
371 nregs = hard_regno_nregs[regno][mode];
372
373 if (SCALAR_INT_MODE_P (GET_MODE (dst))
374+ && nregs == 1 && GET_CODE (set) == SET)
375+ {
376+ rtx note, sym = NULL_RTX;
377+ HOST_WIDE_INT off;
378+
379+ note = find_reg_equal_equiv_note (insn);
380+ if (note && GET_CODE (XEXP (note, 0)) == SYMBOL_REF)
381+ {
382+ sym = XEXP (note, 0);
383+ off = 0;
384+ }
385+ else if (note && GET_CODE (XEXP (note, 0)) == CONST
386+ && GET_CODE (XEXP (XEXP (note, 0), 0)) == PLUS
387+ && GET_CODE (XEXP (XEXP (XEXP (note, 0), 0), 0)) == SYMBOL_REF
388+ && CONST_INT_P (XEXP (XEXP (XEXP (note, 0), 0), 1)))
389+ {
390+ sym = XEXP (XEXP (XEXP (note, 0), 0), 0);
391+ off = INTVAL (XEXP (XEXP (XEXP (note, 0), 0), 1));
392+ }
393+
394+ if (sym != NULL_RTX)
395+ {
396+ reg_base_reg[regno] = -1;
397+ reg_symbol_ref[regno] = sym;
398+ reg_offset[regno] = off;
399+ reg_mode[regno] = mode;
400+ reg_set_luid[regno] = move2add_luid;
401+ return;
402+ }
403+ }
404+
405+ if (SCALAR_INT_MODE_P (GET_MODE (dst))
406 && nregs == 1 && GET_CODE (set) == SET
407 && GET_CODE (SET_DEST (set)) != ZERO_EXTRACT
408 && GET_CODE (SET_DEST (set)) != STRICT_LOW_PART)
409@@ -1525,6 +1703,7 @@
410 case CONST_INT:
411 /* Start tracking the register as a constant. */
412 reg_base_reg[regno] = -1;
413+ reg_symbol_ref[regno] = NULL_RTX;
414 reg_offset[regno] = INTVAL (SET_SRC (set));
415 /* We assign the same luid to all registers set to constants. */
416 reg_set_luid[regno] = move2add_last_label_luid + 1;
417@@ -1545,6 +1724,7 @@
418 if (reg_set_luid[base_regno] <= move2add_last_label_luid)
419 {
420 reg_base_reg[base_regno] = base_regno;
421+ reg_symbol_ref[base_regno] = NULL_RTX;
422 reg_offset[base_regno] = 0;
423 reg_set_luid[base_regno] = move2add_luid;
424 reg_mode[base_regno] = mode;
425@@ -1558,6 +1738,7 @@
426 /* Copy base information from our base register. */
427 reg_set_luid[regno] = reg_set_luid[base_regno];
428 reg_base_reg[regno] = reg_base_reg[base_regno];
429+ reg_symbol_ref[regno] = reg_symbol_ref[base_regno];
430
431 /* Compute the sum of the offsets or constants. */
432 reg_offset[regno] = trunc_int_for_mode (offset
433