summaryrefslogtreecommitdiffstats
path: root/meta-oe/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99443.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-oe/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99443.patch')
-rw-r--r--meta-oe/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99443.patch873
1 files changed, 873 insertions, 0 deletions
diff --git a/meta-oe/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99443.patch b/meta-oe/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99443.patch
new file mode 100644
index 000000000..802c3816f
--- /dev/null
+++ b/meta-oe/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99443.patch
@@ -0,0 +1,873 @@
12010-11-26 Tom de Vries <tom@codesourcery.com>
2
3 gcc/
4 * gcc/ee.c: New file.
5 * gcc/tree-pass.h (pass_ee): Declare.
6 * gcc/opts.c (decode_options): Set flag_ee at -O2.
7 * gcc/timevar.def (TV_EE): New timevar.
8 * gcc/common.opt (fextension-elimination): New option.
9 * gcc/Makefile.in (ee.o): New rule.
10 * gcc/passes.c (pass_ee): Add it.
11 * gcc/testsuite/gcc.dg/extend-4.c: New test.
12 * gcc/testsuite/gcc.dg/extend-1.c: New test.
13 * gcc/testsuite/gcc.dg/extend-2.c: New test.
14 * gcc/testsuite/gcc.dg/extend-2-64.c: New test.
15 * gcc/testsuite/gcc.dg/extend-3.c: New test.
16
17=== modified file 'gcc/Makefile.in'
18--- old/gcc/Makefile.in 2010-11-16 18:05:53 +0000
19+++ new/gcc/Makefile.in 2010-12-10 15:33:37 +0000
20@@ -1194,6 +1194,7 @@
21 dse.o \
22 dwarf2asm.o \
23 dwarf2out.o \
24+ ee.o \
25 ebitmap.o \
26 emit-rtl.o \
27 et-forest.o \
28@@ -2965,6 +2966,11 @@
29 web.o : web.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
30 hard-reg-set.h $(FLAGS_H) $(BASIC_BLOCK_H) $(FUNCTION_H) output.h $(TOPLEV_H) \
31 $(DF_H) $(OBSTACK_H) $(TIMEVAR_H) $(TREE_PASS_H)
32+ee.o : ee.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
33+ hard-reg-set.h $(FLAGS_H) $(BASIC_BLOCK_H) $(FUNCTION_H) output.h \
34+ $(DF_H) $(TIMEVAR_H) tree-pass.h $(RECOG_H) $(EXPR_H) \
35+ $(REGS_H) $(TREE_H) $(TM_P_H) insn-config.h $(INSN_ATTR_H) $(TOPLEV_H) $(DIAGNOSTIC_CORE_H) \
36+ $(TARGET_H) $(OPTABS_H) insn-codes.h rtlhooks-def.h $(PARAMS_H) $(CGRAPH_H)
37 gcse.o : gcse.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
38 $(REGS_H) hard-reg-set.h $(FLAGS_H) $(REAL_H) insn-config.h $(GGC_H) \
39 $(RECOG_H) $(EXPR_H) $(BASIC_BLOCK_H) $(FUNCTION_H) output.h $(TOPLEV_H) \
40
41=== modified file 'gcc/common.opt'
42--- old/gcc/common.opt 2010-11-04 12:43:52 +0000
43+++ new/gcc/common.opt 2010-12-10 15:33:37 +0000
44@@ -496,6 +496,10 @@
45 Common Report Var(flag_early_inlining) Init(1) Optimization
46 Perform early inlining
47
48+fextension-elimination
49+Common Report Var(flag_ee) Init(0) Optimization
50+Perform extension elimination
51+
52 feliminate-dwarf2-dups
53 Common Report Var(flag_eliminate_dwarf2_dups)
54 Perform DWARF2 duplicate elimination
55
56=== added file 'gcc/ee.c'
57--- old/gcc/ee.c 1970-01-01 00:00:00 +0000
58+++ new/gcc/ee.c 2010-12-10 15:33:37 +0000
59@@ -0,0 +1,662 @@
60+/* Redundant extension elimination
61+ Copyright (C) 2010 Free Software Foundation, Inc.
62+ Contributed by Tom de Vries (tom@codesourcery.com)
63+
64+This file is part of GCC.
65+
66+GCC is free software; you can redistribute it and/or modify it under
67+the terms of the GNU General Public License as published by the Free
68+Software Foundation; either version 3, or (at your option) any later
69+version.
70+
71+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
72+WARRANTY; without even the implied warranty of MERCHANTABILITY or
73+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
74+for more details.
75+
76+You should have received a copy of the GNU General Public License
77+along with GCC; see the file COPYING3. If not see
78+<http://www.gnu.org/licenses/>. */
79+
80+/*
81+
82+ MOTIVATING EXAMPLE
83+
84+ The motivating example for this pass is:
85+
86+ void f(unsigned char *p, short s, int c, int *z)
87+ {
88+ if (c)
89+ *z = 0;
90+ *p ^= (unsigned char)s;
91+ }
92+
93+ For MIPS, compilation results in the following insns.
94+
95+ (set (reg/v:SI 199)
96+ (sign_extend:SI (subreg:HI (reg:SI 200) 2)))
97+
98+ ...
99+
100+ (set (reg:QI 203)
101+ (subreg:QI (reg/v:SI 199) 3))
102+
103+ These insns are the only def and the only use of reg 199, each located in a
104+ different bb.
105+
106+ The sign-extension preserves the lower half of reg 200 and copies them to
107+ reg 199, and the subreg use of reg 199 only reads the least significant byte.
108+ The sign extension is therefore redundant (the extension part, not the copy
109+ part), and can safely be replaced with a regcopy from reg 200 to reg 199.
110+
111+
112+ OTHER SIGN/ZERO EXTENSION ELIMINATION PASSES
113+
114+ There are other passes which eliminate sign/zero-extension: combine and
115+ implicit_zee. Both attempt to eliminate extensions by combining them with
116+ other instructions. The combine pass does this at bb level,
117+ implicit_zee works at inter-bb level.
118+
119+ The combine pass combine an extension with either:
120+ - all uses of the extension, or
121+ - all defs of the operand of the extension.
122+ The implicit_zee pass only implements the latter.
123+
124+ For our motivating example, combine doesn't work since the def and the use of
125+ reg 199 are in a different bb.
126+
127+ Implicit_zee does not work since it only combines an extension with the defs
128+ of its operand.
129+
130+
131+ INTENDED EFFECT
132+
133+ This pass works by removing sign/zero-extensions, or replacing them with
134+ regcopies. The idea there is that the regcopy might be eliminated by a later
135+ pass. In case the regcopy cannot be eliminated, it might at least be cheaper
136+ than the extension.
137+
138+
139+ IMPLEMENTATION
140+
141+ The pass scans twice over all instructions.
142+
143+ The first scan registers all uses of a reg in the biggest_use array. After
144+ that first scan, the biggest_use array contains the size in bits of the
145+ biggest use of each reg.
146+
147+ The second scan finds extensions, determines whether they are redundant based
148+ on the biggest use, and deletes or replaces them.
149+
150+ In case that the src and dest reg of the replacement are not of the same size,
151+ we do not replace with a normal regcopy, but with a truncate or with the copy
152+ of a paradoxical subreg instead.
153+
154+
155+ LIMITATIONS
156+
157+ The scope of the analysis is limited to an extension and its uses. The other
158+ type of analysis (related to the defs of the operand of an extension) is not
159+ done.
160+
161+ Furthermore, we do the analysis of biggest use per reg. So when determining
162+ whether an extension is redundant, we take all uses of a the dest reg into
163+ account, also the ones that are not uses of the extension. This could be
164+ overcome by calculating the def-use chains and using those for analysis
165+ instead.
166+
167+ Finally, during the analysis each insn is looked at in isolation. There is no
168+ propagation of information during the analysis. To overcome this limitation,
169+ a backward iterative bit-level liveness analysis is needed. */
170+
171+
172+#include "config.h"
173+#include "system.h"
174+#include "coretypes.h"
175+#include "tm.h"
176+#include "rtl.h"
177+#include "tree.h"
178+#include "tm_p.h"
179+#include "flags.h"
180+#include "regs.h"
181+#include "hard-reg-set.h"
182+#include "basic-block.h"
183+#include "insn-config.h"
184+#include "function.h"
185+#include "expr.h"
186+#include "insn-attr.h"
187+#include "recog.h"
188+#include "toplev.h"
189+#include "target.h"
190+#include "timevar.h"
191+#include "optabs.h"
192+#include "insn-codes.h"
193+#include "rtlhooks-def.h"
194+#include "output.h"
195+#include "params.h"
196+#include "timevar.h"
197+#include "tree-pass.h"
198+#include "cgraph.h"
199+
200+#define SKIP_REG (-1)
201+
202+/* Array to register the biggest use of a reg, in bits. */
203+
204+static int *biggest_use;
205+
206+/* Forward declaration. */
207+
208+static void note_use (rtx *x, void *data);
209+
210+/* The following two functions are borrowed from trunk/gcc/toplev.c. They can be
211+ removed for a check-in into gcc trunk. */
212+
213+/* Given X, an unsigned number, return the number of least significant bits
214+ that are zero. When X == 0, the result is the word size. */
215+
216+static int
217+ctz_hwi (unsigned HOST_WIDE_INT x)
218+{
219+ return x ? floor_log2 (x & -x) : HOST_BITS_PER_WIDE_INT;
220+}
221+
222+/* Similarly for most significant bits. */
223+
224+static int
225+clz_hwi (unsigned HOST_WIDE_INT x)
226+{
227+ return HOST_BITS_PER_WIDE_INT - 1 - floor_log2(x);
228+}
229+
230+/* Check whether this is a paradoxical subreg. */
231+
232+static bool
233+paradoxical_subreg_p (rtx subreg)
234+{
235+ enum machine_mode subreg_mode, reg_mode;
236+
237+ if (GET_CODE (subreg) != SUBREG)
238+ return false;
239+
240+ subreg_mode = GET_MODE (subreg);
241+ reg_mode = GET_MODE (SUBREG_REG (subreg));
242+
243+ if (GET_MODE_SIZE (subreg_mode) > GET_MODE_SIZE (reg_mode))
244+ return true;
245+
246+ return false;
247+}
248+
249+/* Get the size and reg number of a REG or SUBREG use. */
250+
251+static bool
252+reg_use_p (rtx use, int *size, unsigned int *regno)
253+{
254+ rtx reg;
255+
256+ if (REG_P (use))
257+ {
258+ *regno = REGNO (use);
259+ *size = GET_MODE_BITSIZE (GET_MODE (use));
260+ return true;
261+ }
262+ else if (GET_CODE (use) == SUBREG)
263+ {
264+ reg = SUBREG_REG (use);
265+
266+ if (!REG_P (reg))
267+ return false;
268+
269+ *regno = REGNO (reg);
270+
271+ if (paradoxical_subreg_p (use))
272+ *size = GET_MODE_BITSIZE (GET_MODE (reg));
273+ else
274+ *size = subreg_lsb (use) + GET_MODE_BITSIZE (GET_MODE (use));
275+
276+ return true;
277+ }
278+
279+ return false;
280+}
281+
282+/* Register the use of a reg. */
283+
284+static void
285+register_use (int size, unsigned int regno)
286+{
287+ int *current = &biggest_use[regno];
288+
289+ if (*current == SKIP_REG)
290+ return;
291+
292+ *current = MAX (*current, size);
293+}
294+
295+/* Handle embedded uses. */
296+
297+static void
298+note_embedded_uses (rtx use, rtx pattern)
299+{
300+ const char *format_ptr;
301+ int i, j;
302+
303+ format_ptr = GET_RTX_FORMAT (GET_CODE (use));
304+ for (i = 0; i < GET_RTX_LENGTH (GET_CODE (use)); i++)
305+ if (format_ptr[i] == 'e')
306+ note_use (&XEXP (use, i), pattern);
307+ else if (format_ptr[i] == 'E')
308+ for (j = 0; j < XVECLEN (use, i); j++)
309+ note_use (&XVECEXP (use, i, j), pattern);
310+}
311+
312+/* Get the set that has use as its SRC operand. */
313+
314+static rtx
315+get_set (rtx use, rtx pattern)
316+{
317+ rtx sub;
318+ int i;
319+
320+ if (GET_CODE (pattern) == SET && SET_SRC (pattern) == use)
321+ return pattern;
322+
323+ if (GET_CODE (pattern) == PARALLEL)
324+ for (i = 0; i < XVECLEN (pattern, 0); ++i)
325+ {
326+ sub = XVECEXP (pattern, 0, i);
327+ if (GET_CODE (sub) == SET && SET_SRC (sub) == use)
328+ return sub;
329+ }
330+
331+ return NULL_RTX;
332+}
333+
334+/* Handle a restricted op use. In this context restricted means that a bit in an
335+ operand influences only the same bit or more significant bits in the result.
336+ The bitwise ops are a subclass, but PLUS is one as well. */
337+
338+static void
339+note_restricted_op_use (rtx use, unsigned int nr_operands, rtx pattern)
340+{
341+ unsigned int i, smallest;
342+ int operand_size[2];
343+ int used_size;
344+ unsigned int operand_regno[2];
345+ bool operand_reg[2];
346+ bool operand_ignore[2];
347+ rtx set;
348+
349+ /* Init operand_reg, operand_size, operand_regno and operand_ignore. */
350+ for (i = 0; i < nr_operands; ++i)
351+ {
352+ operand_reg[i] = reg_use_p (XEXP (use, i), &operand_size[i],
353+ &operand_regno[i]);
354+ operand_ignore[i] = false;
355+ }
356+
357+ /* Handle case of reg and-masked with const. */
358+ if (GET_CODE (use) == AND && CONST_INT_P (XEXP (use, 1)) && operand_reg[0])
359+ {
360+ used_size =
361+ HOST_BITS_PER_WIDE_INT - clz_hwi (UINTVAL (XEXP (use, 1)));
362+ operand_size[0] = MIN (operand_size[0], used_size);
363+ }
364+
365+ /* Handle case of reg or-masked with const. */
366+ if (GET_CODE (use) == IOR && CONST_INT_P (XEXP (use, 1)) && operand_reg[0])
367+ {
368+ used_size =
369+ HOST_BITS_PER_WIDE_INT - clz_hwi (~UINTVAL (XEXP (use, 1)));
370+ operand_size[0] = MIN (operand_size[0], used_size);
371+ }
372+
373+ /* Ignore the use of a in 'a = a + b'. */
374+ set = get_set (use, pattern);
375+ if (set != NULL_RTX && REG_P (SET_DEST (set)))
376+ for (i = 0; i < nr_operands; ++i)
377+ operand_ignore[i] = (operand_reg[i]
378+ && (REGNO (SET_DEST (set)) == operand_regno[i]));
379+
380+ /* Handle the case a reg is combined with don't care bits. */
381+ if (nr_operands == 2 && operand_reg[0] && operand_reg[1]
382+ && operand_size[0] != operand_size[1])
383+ {
384+ smallest = operand_size[0] > operand_size[1];
385+
386+ if (paradoxical_subreg_p (XEXP (use, smallest))
387+ && !SUBREG_PROMOTED_VAR_P (XEXP (use, smallest)))
388+ operand_size[1 - smallest] = operand_size[smallest];
389+ }
390+
391+ /* Register the operand use, if necessary. */
392+ for (i = 0; i < nr_operands; ++i)
393+ if (!operand_reg[i])
394+ note_use (&XEXP (use, i), pattern);
395+ else if (!operand_ignore[i])
396+ register_use (operand_size[i], operand_regno[i]);
397+}
398+
399+/* Handle all uses noted by note_uses. */
400+
401+static void
402+note_use (rtx *x, void *data)
403+{
404+ rtx use = *x;
405+ rtx pattern = (rtx)data;
406+ int use_size;
407+ unsigned int use_regno;
408+
409+ switch (GET_CODE (use))
410+ {
411+ case REG:
412+ case SUBREG:
413+ if (!reg_use_p (use, &use_size, &use_regno))
414+ {
415+ note_embedded_uses (use, pattern);
416+ return;
417+ }
418+ register_use (use_size, use_regno);
419+ return;
420+ case IOR:
421+ case AND:
422+ case XOR:
423+ case PLUS:
424+ case MINUS:
425+ note_restricted_op_use (use, 2, pattern);
426+ return;
427+ case NOT:
428+ case NEG:
429+ note_restricted_op_use (use, 1, pattern);
430+ return;
431+ case ASHIFT:
432+ if (!reg_use_p (XEXP (use, 0), &use_size, &use_regno)
433+ || !CONST_INT_P (XEXP (use, 1))
434+ || INTVAL (XEXP (use, 1)) <= 0
435+ || paradoxical_subreg_p (XEXP (use, 0)))
436+ {
437+ note_embedded_uses (use, pattern);
438+ return;
439+ }
440+ register_use (use_size - INTVAL (XEXP (use, 1)), use_regno);
441+ return;
442+ default:
443+ note_embedded_uses (use, pattern);
444+ return;
445+ }
446+}
447+
448+/* Check whether reg is implicitly used. */
449+
450+static bool
451+implicit_use_p (int regno)
452+{
453+#ifdef EPILOGUE_USES
454+ if (EPILOGUE_USES (regno))
455+ return true;
456+#endif
457+
458+#ifdef EH_USES
459+ if (EH_USES (regno))
460+ return true;
461+#endif
462+
463+ return false;
464+}
465+
466+/* Note the uses of argument registers in a call. */
467+
468+static void
469+note_call_uses (rtx insn)
470+{
471+ rtx link, link_expr;
472+
473+ if (!CALL_P (insn))
474+ return;
475+
476+ for (link = CALL_INSN_FUNCTION_USAGE (insn); link; link = XEXP (link, 1))
477+ {
478+ link_expr = XEXP (link, 0);
479+
480+ if (GET_CODE (link_expr) == USE)
481+ note_use (&XEXP (link_expr, 0), link);
482+ }
483+}
484+
485+/* Calculate the biggest use mode for all regs. */
486+
487+static void
488+calculate_biggest_use (void)
489+{
490+ int i;
491+ basic_block bb;
492+ rtx insn;
493+
494+ /* Initialize biggest_use for all regs to 0. If a reg is used implicitly, we
495+ handle that reg conservatively and set it to SKIP_REG instead. */
496+ for (i = 0; i < max_reg_num (); i++)
497+ biggest_use[i] = ((implicit_use_p (i) || HARD_REGISTER_NUM_P (i))
498+ ? SKIP_REG : 0);
499+
500+ /* For all insns, call note_use for each use in insn. */
501+ FOR_EACH_BB (bb)
502+ FOR_BB_INSNS (bb, insn)
503+ {
504+ if (!NONDEBUG_INSN_P (insn))
505+ continue;
506+
507+ note_uses (&PATTERN (insn), note_use, PATTERN (insn));
508+
509+ if (CALL_P (insn))
510+ note_call_uses (insn);
511+ }
512+
513+ /* Dump the biggest uses found. */
514+ if (dump_file)
515+ for (i = 0; i < max_reg_num (); i++)
516+ if (biggest_use[i] > 0)
517+ fprintf (dump_file, "reg %d: size %d\n", i, biggest_use[i]);
518+}
519+
520+/* Check whether this is a sign/zero extension. */
521+
522+static bool
523+extension_p (rtx insn, rtx *dest, rtx *inner, int *preserved_size)
524+{
525+ rtx src, op0;
526+
527+ /* Detect set of reg. */
528+ if (GET_CODE (PATTERN (insn)) != SET)
529+ return false;
530+
531+ src = SET_SRC (PATTERN (insn));
532+ *dest = SET_DEST (PATTERN (insn));
533+
534+ if (!REG_P (*dest))
535+ return false;
536+
537+ /* Detect sign or zero extension. */
538+ if (GET_CODE (src) == ZERO_EXTEND || GET_CODE (src) == SIGN_EXTEND
539+ || (GET_CODE (src) == AND && CONST_INT_P (XEXP (src, 1))))
540+ {
541+ op0 = XEXP (src, 0);
542+
543+ /* Determine amount of least significant bits preserved by operation. */
544+ if (GET_CODE (src) == AND)
545+ *preserved_size = ctz_hwi (~UINTVAL (XEXP (src, 1)));
546+ else
547+ *preserved_size = GET_MODE_BITSIZE (GET_MODE (op0));
548+
549+ if (GET_CODE (op0) == SUBREG)
550+ {
551+ if (subreg_lsb (op0) != 0)
552+ return false;
553+
554+ *inner = SUBREG_REG (op0);
555+ return true;
556+ }
557+ else if (REG_P (op0))
558+ {
559+ *inner = op0;
560+ return true;
561+ }
562+ }
563+
564+ return false;
565+}
566+
567+/* Check whether this is a redundant sign/zero extension. */
568+
569+static bool
570+redundant_extension_p (rtx insn, rtx *dest, rtx *inner)
571+{
572+ int biggest_dest_use;
573+ int preserved_size;
574+
575+ if (!extension_p (insn, dest, inner, &preserved_size))
576+ return false;
577+
578+ if (dump_file)
579+ fprintf (dump_file, "considering extension %u with preserved size %d\n",
580+ INSN_UID (insn), preserved_size);
581+
582+ biggest_dest_use = biggest_use[REGNO (*dest)];
583+
584+ if (biggest_dest_use == SKIP_REG)
585+ return false;
586+
587+ if (preserved_size < biggest_dest_use)
588+ return false;
589+
590+ if (dump_file)
591+ fprintf (dump_file, "found superfluous extension %u\n", INSN_UID (insn));
592+
593+ return true;
594+}
595+
596+/* Try to remove or replace the redundant extension. */
597+
598+static void
599+try_remove_or_replace_extension (rtx insn, rtx dest, rtx inner)
600+{
601+ rtx cp_src, cp_dest, seq, one;
602+
603+ if (GET_MODE_CLASS (GET_MODE (dest)) != GET_MODE_CLASS (GET_MODE (inner)))
604+ return;
605+
606+ /* Check whether replacement is needed. */
607+ if (dest != inner)
608+ {
609+ start_sequence ();
610+
611+ /* Determine the proper replacement operation. */
612+ if (GET_MODE (dest) == GET_MODE (inner))
613+ {
614+ cp_src = inner;
615+ cp_dest = dest;
616+ }
617+ else if (GET_MODE_SIZE (GET_MODE (dest))
618+ > GET_MODE_SIZE (GET_MODE (inner)))
619+ {
620+ emit_clobber (dest);
621+ cp_src = inner;
622+ cp_dest = gen_lowpart_SUBREG (GET_MODE (inner), dest);
623+ }
624+ else
625+ {
626+ cp_src = gen_rtx_TRUNCATE (GET_MODE (dest), inner);
627+ cp_dest = dest;
628+ }
629+
630+ emit_move_insn (cp_dest, cp_src);
631+
632+ seq = get_insns ();
633+ end_sequence ();
634+
635+ /* If the replacement is not supported, bail out. */
636+ for (one = seq; one != NULL_RTX; one = NEXT_INSN (one))
637+ if (recog_memoized (one) < 0 && GET_CODE (PATTERN (one)) != CLOBBER)
638+ return;
639+
640+ /* Insert the replacement. */
641+ emit_insn_before (seq, insn);
642+ }
643+
644+ /* Note replacement/removal in the dump. */
645+ if (dump_file)
646+ {
647+ fprintf (dump_file, "superfluous extension %u ", INSN_UID (insn));
648+ if (dest != inner)
649+ fprintf (dump_file, "replaced by %u\n", INSN_UID (seq));
650+ else
651+ fprintf (dump_file, "removed\n");
652+ }
653+
654+ /* Remove the extension. */
655+ delete_insn (insn);
656+}
657+
658+/* Find redundant extensions and remove or replace them if possible. */
659+
660+static void
661+remove_redundant_extensions (void)
662+{
663+ basic_block bb;
664+ rtx insn, next, dest, inner;
665+
666+ biggest_use = XNEWVEC (int, max_reg_num ());
667+ calculate_biggest_use ();
668+
669+ /* Remove redundant extensions. */
670+ FOR_EACH_BB (bb)
671+ FOR_BB_INSNS_SAFE (bb, insn, next)
672+ {
673+ if (!NONDEBUG_INSN_P (insn))
674+ continue;
675+
676+ if (!redundant_extension_p (insn, &dest, &inner))
677+ continue;
678+
679+ try_remove_or_replace_extension (insn, dest, inner);
680+ }
681+
682+ free (biggest_use);
683+}
684+
685+/* Remove redundant extensions. */
686+
687+static unsigned int
688+rest_of_handle_ee (void)
689+{
690+ remove_redundant_extensions ();
691+ return 0;
692+}
693+
694+/* Run ee pass when flag_ee is set at optimization level > 0. */
695+
696+static bool
697+gate_handle_ee (void)
698+{
699+ return (optimize > 0 && flag_ee);
700+}
701+
702+struct rtl_opt_pass pass_ee =
703+{
704+ {
705+ RTL_PASS,
706+ "ee", /* name */
707+ gate_handle_ee, /* gate */
708+ rest_of_handle_ee, /* execute */
709+ NULL, /* sub */
710+ NULL, /* next */
711+ 0, /* static_pass_number */
712+ TV_EE, /* tv_id */
713+ 0, /* properties_required */
714+ 0, /* properties_provided */
715+ 0, /* properties_destroyed */
716+ 0, /* todo_flags_start */
717+ TODO_ggc_collect |
718+ TODO_dump_func |
719+ TODO_verify_rtl_sharing, /* todo_flags_finish */
720+ }
721+};
722
723=== modified file 'gcc/opts.c'
724--- old/gcc/opts.c 2010-05-17 09:13:28 +0000
725+++ new/gcc/opts.c 2010-12-10 15:33:37 +0000
726@@ -907,6 +907,7 @@
727 flag_tree_switch_conversion = opt2;
728 flag_ipa_cp = opt2;
729 flag_ipa_sra = opt2;
730+ flag_ee = opt2;
731
732 /* Track fields in field-sensitive alias analysis. */
733 set_param_value ("max-fields-for-field-sensitive",
734
735=== modified file 'gcc/passes.c'
736--- old/gcc/passes.c 2010-09-01 13:29:58 +0000
737+++ new/gcc/passes.c 2010-12-10 15:33:37 +0000
738@@ -974,6 +974,7 @@
739 NEXT_PASS (pass_lower_subreg);
740 NEXT_PASS (pass_df_initialize_opt);
741 NEXT_PASS (pass_cse);
742+ NEXT_PASS (pass_ee);
743 NEXT_PASS (pass_rtl_fwprop);
744 NEXT_PASS (pass_rtl_cprop);
745 NEXT_PASS (pass_rtl_pre);
746
747=== added file 'gcc/testsuite/gcc.dg/extend-1.c'
748--- old/gcc/testsuite/gcc.dg/extend-1.c 1970-01-01 00:00:00 +0000
749+++ new/gcc/testsuite/gcc.dg/extend-1.c 2010-12-10 15:33:37 +0000
750@@ -0,0 +1,13 @@
751+/* { dg-do compile } */
752+/* { dg-options "-O2 -fdump-rtl-ee" } */
753+
754+void f(unsigned char * p, short s, int c, int *z)
755+{
756+ if (c)
757+ *z = 0;
758+ *p ^= (unsigned char)s;
759+}
760+
761+/* { dg-final { scan-rtl-dump-times "sign_extend:" 0 "ee" { target mips*-*-* } } } */
762+/* { dg-final { scan-rtl-dump-times "superfluous extension \[0-9\]+ replaced" 1 "ee" { target mips*-*-* } } } */
763+/* { dg-final { cleanup-rtl-dump "ee" } } */
764
765=== added file 'gcc/testsuite/gcc.dg/extend-2-64.c'
766--- old/gcc/testsuite/gcc.dg/extend-2-64.c 1970-01-01 00:00:00 +0000
767+++ new/gcc/testsuite/gcc.dg/extend-2-64.c 2010-12-10 15:33:37 +0000
768@@ -0,0 +1,20 @@
769+/* { dg-do compile } */
770+/* { dg-options "-O2 -fdump-rtl-ee" } */
771+/* { dg-require-effective-target mips64 } */
772+
773+void f(unsigned char * p, short *s, int c)
774+{
775+ short or = 0;
776+ while (c)
777+ {
778+ or = or | s[c];
779+ c --;
780+ }
781+ *p = (unsigned char)or;
782+}
783+
784+/* { dg-final { scan-rtl-dump-times "zero_extend:" 1 "ee" { target mips*-*-* } } } */
785+/* { dg-final { scan-rtl-dump-times "sign_extend:" 0 "ee" { target mips*-*-* } } } */
786+/* { dg-final { scan-rtl-dump-times "superfluous extension \[0-9\]+ replaced" 3 "ee" { target mips*-*-* } } } */
787+/* { dg-final { cleanup-rtl-dump "ee" } } */
788+
789
790=== added file 'gcc/testsuite/gcc.dg/extend-2.c'
791--- old/gcc/testsuite/gcc.dg/extend-2.c 1970-01-01 00:00:00 +0000
792+++ new/gcc/testsuite/gcc.dg/extend-2.c 2010-12-10 15:33:37 +0000
793@@ -0,0 +1,20 @@
794+/* { dg-do compile } */
795+/* { dg-options "-O2 -fdump-rtl-ee" } */
796+/* { dg-require-effective-target ilp32 } */
797+
798+void f(unsigned char * p, short *s, int c)
799+{
800+ short or = 0;
801+ while (c)
802+ {
803+ or = or | s[c];
804+ c --;
805+ }
806+ *p = (unsigned char)or;
807+}
808+
809+/* { dg-final { scan-rtl-dump-times "zero_extend" 0 "ee" { target mips*-*-* } } } */
810+/* { dg-final { scan-rtl-dump-times "sign_extend" 0 "ee" { target mips*-*-* } } } */
811+/* { dg-final { scan-rtl-dump-times "superfluous extension \[0-9\]+ replaced" 2 "ee" { target mips*-*-* } } } */
812+/* { dg-final { cleanup-rtl-dump "ee" } } */
813+
814
815=== added file 'gcc/testsuite/gcc.dg/extend-3.c'
816--- old/gcc/testsuite/gcc.dg/extend-3.c 1970-01-01 00:00:00 +0000
817+++ new/gcc/testsuite/gcc.dg/extend-3.c 2010-12-10 15:33:37 +0000
818@@ -0,0 +1,12 @@
819+/* { dg-do compile } */
820+/* { dg-options "-O2 -fdump-rtl-ee" } */
821+
822+unsigned int f(unsigned char byte)
823+{
824+ return byte << 25;
825+}
826+
827+/* { dg-final { scan-rtl-dump-times "zero_extend:" 0 "ee" { target mips*-*-* } } } */
828+/* { dg-final { scan-rtl-dump "superfluous extension \[0-9\]+ replaced" "ee" { target mips*-*-* } } } */
829+/* { dg-final { cleanup-rtl-dump "ee" } } */
830+
831
832=== added file 'gcc/testsuite/gcc.dg/extend-4.c'
833--- old/gcc/testsuite/gcc.dg/extend-4.c 1970-01-01 00:00:00 +0000
834+++ new/gcc/testsuite/gcc.dg/extend-4.c 2010-12-10 15:33:37 +0000
835@@ -0,0 +1,13 @@
836+/* { dg-do compile } */
837+/* { dg-options "-O2 -fdump-rtl-ee" } */
838+
839+unsigned char f(unsigned int a)
840+{
841+ unsigned int b = a & 0x10ff;
842+ return b;
843+}
844+
845+/* { dg-final { scan-rtl-dump-times "and:" 0 "ee" { target mips*-*-* } } } */
846+/* { dg-final { scan-rtl-dump-times "superfluous extension \[0-9\]+ replaced" 1 "ee" { target mips*-*-* } } } */
847+/* { dg-final { cleanup-rtl-dump "ee" } } */
848+
849
850=== modified file 'gcc/timevar.def'
851--- old/gcc/timevar.def 2009-11-27 12:43:08 +0000
852+++ new/gcc/timevar.def 2010-12-10 15:33:37 +0000
853@@ -162,6 +162,7 @@
854 DEFTIMEVAR (TV_VARCONST , "varconst")
855 DEFTIMEVAR (TV_LOWER_SUBREG , "lower subreg")
856 DEFTIMEVAR (TV_JUMP , "jump")
857+DEFTIMEVAR (TV_EE , "extension elimination")
858 DEFTIMEVAR (TV_FWPROP , "forward prop")
859 DEFTIMEVAR (TV_CSE , "CSE")
860 DEFTIMEVAR (TV_DCE , "dead code elimination")
861
862=== modified file 'gcc/tree-pass.h'
863--- old/gcc/tree-pass.h 2010-09-01 13:29:58 +0000
864+++ new/gcc/tree-pass.h 2010-12-10 15:33:37 +0000
865@@ -468,6 +468,7 @@
866 extern struct rtl_opt_pass pass_initial_value_sets;
867 extern struct rtl_opt_pass pass_unshare_all_rtl;
868 extern struct rtl_opt_pass pass_instantiate_virtual_regs;
869+extern struct rtl_opt_pass pass_ee;
870 extern struct rtl_opt_pass pass_rtl_fwprop;
871 extern struct rtl_opt_pass pass_rtl_fwprop_addr;
872 extern struct rtl_opt_pass pass_jump2;
873