rtlopt merge part 8 - webizer pass
Jan Hubicka
jh@suse.cz
Fri Feb 7 12:19:00 GMT 2003
Hi,
this patch contains updated version of the web construction pass. It's primary
motivation has been to write something more generic to split induction
variables after loop unrolling.
In that case seuqence
a[reg]=x
reg++;
a[reg]=x
reg++;
a[reg]=x
reg++;
Is split into
a[reg]=x
reg2=reg+1;
a[reg2]=xl
reg3=reg2+1;
a[reg3]=xl
That is cleaned up by our CSE pass. The pass is generic and should improve
register allocation, alias analysis, stupid register allocation and other
optimizations passes as well. It's overall effect is speedup from 402 to 405
on SpecINT, but it is higher on hammer. It's major drawback is the regalloc
unability to reconstruct 2-address isntrucitons so I uess that on 3 address
machines it will work better.
========================================================================
164.gzip 1400 303 462* 1400 308 455*
175.vpr 1400 470 298* 1400 472 297*
176.gcc 1100 292 376* 1100 298 369*
181.mcf 1800 810 222* 1800 809 223*
186.crafty 1000 188 531* 1000 189 530*
197.parser 1800 489 368* 1800 487 369*
252.eon 1300 220 591* 1300 218 597*
253.perlbmk 1800 321 560* 1800 310 580*
254.gap 1100 266 413* 1100 262 420*
255.vortex 1900 387 491* 1900 386 492*
256.bzip2 1500 423 355* 1500 416 361*
300.twolf 3000 894 335* 3000 880 341*
Est. SPECint_base2000 402
Est. SPECint2000 405
HARDWARE
--------
Hardware Vendor: AMD
Model Name: Athlon 1.133 Ghz Box
CPU: AMD Athlon(tm) Processor
CPU MHz: 1133.380
FPU: Integrated
CPU(s) enabled: 1
CPU(s) orderable: 1
Parallel: No
Primary Cache: 64KBI + 64KBD on chip
Secondary Cache: 256 KB
L3 Cache: N/A
Other Cache: N/A
Memory: 512 MB
Disk Subsystem: 1x IBM DTLA 307030 30GB EIDE Disk
Other Hardware: Ethernet
SOFTWARE
--------
Operating System: SuSE Linux 8.0 (i386)
Compiler: GCC CVS
File System: Linux/reiserfs
System State: Multi-User
NOTES
-----
Base flags: -O3 -funroll-loops
Compiler: mainline
Peak flags: -O3 -funroll-loops
Compiler: mainline+web construction
Run with profile directed optimizations for both base and peak
(first pass has -fprofile-arcs, second has -fbranch-probabilities)
To compile and execute eon correctly the following extra flags
are used for compilation: -ffast-math -fwritable-strings.
It has about 1% copilation time cost. At the moment I am enabling it at -O3
becuase of the debug info problems, but in future I would like to see it
enabled at -O2 once var tracking is in and possibly elliminated by SSA/deSSA
done after unrolling, but that seems to be more far from now.
* Makefile.in (web.o): New.
* web.c: New file.
* rtl.h (web_main): Declare.
* timervar.def (TV_WEB): New.
* toplev.c (dump_file_index, dump_file_info): Add DFI_web.
(flag_web): New static variable.
(lang_independent_ptions): Add "web".
(rest_of_compilation): Call web_main.
(parse_options_and_default_flags): Add flag_web.
* invoke.texi (-fweb): Document.
* df.c (read_modify_subreg): Fix.
Index: Makefile.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Makefile.in,v
retrieving revision 1.988
diff -c -3 -p -r1.988 Makefile.in
*** Makefile.in 6 Feb 2003 01:47:53 -0000 1.988
--- Makefile.in 7 Feb 2003 12:11:04 -0000
*************** OBJS = alias.o bb-reorder.o bitmap.o bui
*** 785,791 ****
sibcall.o simplify-rtx.o ssa.o ssa-ccp.o ssa-dce.o stmt.o \
stor-layout.o stringpool.o timevar.o toplev.o tracer.o tree.o tree-dump.o \
tree-inline.o unroll.o varasm.o varray.o version.o vmsdbgout.o xcoffout.o \
! alloc-pool.o et-forest.o \
$(GGC) $(out_object_file) $(EXTRA_OBJS) $(host_hook_obj)
BACKEND = main.o libbackend.a
--- 785,791 ----
sibcall.o simplify-rtx.o ssa.o ssa-ccp.o ssa-dce.o stmt.o \
stor-layout.o stringpool.o timevar.o toplev.o tracer.o tree.o tree-dump.o \
tree-inline.o unroll.o varasm.o varray.o version.o vmsdbgout.o xcoffout.o \
! alloc-pool.o et-forest.o web.o \
$(GGC) $(out_object_file) $(EXTRA_OBJS) $(host_hook_obj)
BACKEND = main.o libbackend.a
*************** cse.o : cse.c $(CONFIG_H) $(SYSTEM_H) co
*** 1537,1542 ****
--- 1537,1545 ----
hard-reg-set.h flags.h real.h insn-config.h $(RECOG_H) $(EXPR_H) toplev.h \
output.h function.h $(BASIC_BLOCK_H) $(GGC_H) $(TM_P_H) $(TIMEVAR_H) \
except.h $(TARGET_H)
+ web.o : web.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(RTL_H) $(REGS_H) hard-reg-set.h \
+ flags.h real.h insn-config.h ggc.h $(RECOG_H) $(EXPR_H) $(BASIC_BLOCK_H) \
+ function.h output.h toplev.h $(TM_P_H) $(PARAMS_H)
gcse.o : gcse.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(REGS_H) \
hard-reg-set.h flags.h real.h insn-config.h ggc.h $(RECOG_H) $(EXPR_H) \
$(BASIC_BLOCK_H) function.h output.h toplev.h $(TM_P_H) $(PARAMS_H) except.h gt-gcse.h
Index: df.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/df.c,v
retrieving revision 1.46
diff -c -3 -p -r1.46 df.c
*** df.c 31 Jan 2003 23:34:12 -0000 1.46
--- df.c 7 Feb 2003 12:11:05 -0000
*************** read_modify_subreg_p (x)
*** 894,900 ****
isize = GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)));
osize = GET_MODE_SIZE (GET_MODE (x));
if (isize <= osize)
! return true;
if (isize <= UNITS_PER_WORD)
return false;
if (osize > UNITS_PER_WORD)
--- 894,900 ----
isize = GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)));
osize = GET_MODE_SIZE (GET_MODE (x));
if (isize <= osize)
! return false;
if (isize <= UNITS_PER_WORD)
return false;
if (osize > UNITS_PER_WORD)
Index: rtl.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/rtl.h,v
retrieving revision 1.383
diff -c -3 -p -r1.383 rtl.h
*** rtl.h 5 Feb 2003 00:56:40 -0000 1.383
--- rtl.h 7 Feb 2003 12:11:05 -0000
*************** extern rtx remove_death PARAMS ((unsig
*** 2035,2040 ****
--- 2035,2042 ----
extern void dump_combine_stats PARAMS ((FILE *));
extern void dump_combine_total_stats PARAMS ((FILE *));
#endif
+ /* In web.c */
+ extern void web_main PARAMS ((void));
/* In sched.c. */
#ifdef BUFSIZ
Index: timevar.def
===================================================================
RCS file: /cvs/gcc/gcc/gcc/timevar.def,v
retrieving revision 1.17
diff -c -3 -p -r1.17 timevar.def
*** timevar.def 27 Jan 2003 02:22:21 -0000 1.17
--- timevar.def 7 Feb 2003 12:11:05 -0000
*************** DEFTIMEVAR (TV_GCSE , "
*** 63,68 ****
--- 63,69 ----
DEFTIMEVAR (TV_LOOP , "loop analysis")
DEFTIMEVAR (TV_BYPASS , "bypass jumps")
DEFTIMEVAR (TV_TRACER , "tracer")
+ DEFTIMEVAR (TV_WEB , "web")
DEFTIMEVAR (TV_CSE2 , "CSE 2")
DEFTIMEVAR (TV_BRANCH_PROB , "branch prediction")
DEFTIMEVAR (TV_FLOW , "flow analysis")
Index: toplev.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/toplev.c,v
retrieving revision 1.705
diff -c -3 -p -r1.705 toplev.c
*** toplev.c 6 Feb 2003 01:47:55 -0000 1.705
--- toplev.c 7 Feb 2003 12:11:05 -0000
*************** enum dump_file_index
*** 239,244 ****
--- 239,245 ----
DFI_bp,
DFI_ce1,
DFI_tracer,
+ DFI_web,
DFI_cse2,
DFI_life,
DFI_combine,
*************** static struct dump_file_info dump_file[D
*** 289,294 ****
--- 290,296 ----
{ "bp", 'b', 1, 0, 0 },
{ "ce1", 'C', 1, 0, 0 },
{ "tracer", 'T', 1, 0, 0 },
+ { "web", 'Z', 0, 0, 0 },
{ "cse2", 't', 1, 0, 0 },
{ "life", 'f', 1, 0, 0 }, /* Yes, duplicate enable switch. */
{ "combine", 'c', 1, 0, 0 },
*************** int flag_complex_divide_method = 0;
*** 611,616 ****
--- 613,622 ----
int flag_syntax_only = 0;
+ /* Nonzero means performs web construction pass. */
+
+ static int flag_web;
+
/* Nonzero means perform loop optimizer. */
static int flag_loop_optimize;
*************** static const lang_independent_options f_
*** 1033,1038 ****
--- 1046,1053 ----
N_("Return 'short' aggregates in registers") },
{"delayed-branch", &flag_delayed_branch, 1,
N_("Attempt to fill delay slots of branch instructions") },
+ {"web", &flag_web, 1,
+ N_("Construct webs and split unrelated uses of single variable") },
{"gcse", &flag_gcse, 1,
N_("Perform the global common subexpression elimination") },
{"gcse-lm", &flag_gcse_lm, 1,
*************** rest_of_compilation (decl)
*** 3000,3005 ****
--- 3019,3037 ----
close_dump_file (DFI_cfg, print_rtl_with_bb, insns);
+ if (flag_web)
+ {
+ open_dump_file (DFI_web, decl);
+ timevar_push (TV_WEB);
+ web_main ();
+ delete_trivially_dead_insns (get_insns (), max_reg_num ());
+ cleanup_cfg (CLEANUP_EXPENSIVE);
+
+ timevar_pop (TV_WEB);
+ close_dump_file (DFI_web, print_rtl_with_bb, get_insns ());
+ reg_scan (get_insns (), max_reg_num (), 0);
+ }
+
/* Do branch profiling and static profile estimation passes. */
if (optimize > 0 || cfun->arc_profile || flag_branch_probabilities)
{
*************** parse_options_and_default_flags (argc, a
*** 4884,4889 ****
--- 4931,4937 ----
{
flag_inline_functions = 1;
flag_rename_registers = 1;
+ flag_web = 1;
}
if (optimize < 2 || optimize_size)
Index: web.c
===================================================================
RCS file: web.c
diff -N web.c
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- web.c 7 Feb 2003 12:11:05 -0000
***************
*** 0 ****
--- 1,323 ----
+ /* Web construction code for GNU compiler.
+ Contributed by Jan Hubicka
+ Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 2, or (at your option) any later
+ version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+ /* Simple optimization pass that splits indepdendent uses of each pseudo
+ increasing effectivity of other optimizations. The optimization can
+ serve as an example of the use of dataflow module.
+
+ We don't split registers with REG_USERVAR set unless -fmessy-debugging is
+ used, because debug information about such split variables is almost
+ useless.
+
+ TODO
+ - Add code to keep debugging up-to-date after splitting of user variable
+ pseudos. This can be done by remembering all the pseudos used for the
+ variable and use life analysis information before reload to determing
+ wich one of the possible choices is alive and in case more are live,
+ choose one with latest definition.
+
+ Some other optimization passes will benefit from the infrastructure
+ too.
+
+ - We may use profile information and ignore infrequent use for purposes
+ of web unifying inserting the compensation code later to implement full
+ induction variable expansion for loops (currently we expand only if
+ induction is dead afterwards, that is often the case anyway). */
+
+ #include "config.h"
+ #include "system.h"
+ #include "coretypes.h"
+ #include "tm.h"
+ #include "toplev.h"
+
+ #include "rtl.h"
+ #include "hard-reg-set.h"
+ #include "flags.h"
+ #include "basic-block.h"
+ #include "output.h"
+ #include "df.h"
+ #include "function.h"
+
+
+ /* This entry is allocated for each reference in the insn stream. */
+ struct web_entry
+ {
+ /* pointer to the parent in the union/find tree. */
+ struct web_entry *pred;
+ /* Newly assigned register to the entry. Set only for roots. */
+ rtx reg;
+ };
+
+ static struct web_entry *unionfind_root PARAMS ((struct web_entry *));
+ static void unionfind_union PARAMS ((struct web_entry *,
+ struct web_entry *));
+ static void union_defs PARAMS ((struct df *, struct ref *,
+ struct web_entry *,
+ struct web_entry *));
+ static rtx entry_register PARAMS ((struct web_entry *,
+ struct ref *, char *, char *));
+ static void replace_ref PARAMS ((struct ref *, rtx));
+ static int mark_addressof PARAMS ((rtx *, void *));
+
+ /* Find the root of unionfind tree (the representatnt of set). */
+
+ static struct web_entry *
+ unionfind_root (element)
+ struct web_entry *element;
+ {
+ struct web_entry *element1 = element, *element2;
+
+ while (element->pred)
+ element = element->pred;
+ while (element1->pred)
+ {
+ element2 = element1->pred;
+ element1->pred = element;
+ element1 = element2;
+ }
+ return element;
+ }
+
+ /* Union sets. */
+
+ static void
+ unionfind_union (first, second)
+ struct web_entry *first, *second;
+ {
+ first = unionfind_root (first);
+ second = unionfind_root (second);
+ if (first == second)
+ return;
+ second->pred = first;
+ }
+
+ /* For each use, all possible defs reaching it must come in same register,
+ union them. */
+
+ static void
+ union_defs (df, use, def_entry, use_entry)
+ struct df *df;
+ struct ref *use;
+ struct web_entry *def_entry;
+ struct web_entry *use_entry;
+ {
+ rtx insn = DF_REF_INSN (use);
+ struct df_link *link = DF_REF_CHAIN (use);
+ struct df_link *use_link = DF_INSN_USES (df, insn);
+ struct df_link *def_link = DF_INSN_DEFS (df, insn);
+ rtx set = single_set (insn);
+
+ /* Some instructions may use match_dup for it's operands. In case the
+ operands are dead, we will assign them different pseudos creating
+ invalid instruction, so union all uses of the same operands for each
+ insn. */
+
+ while (use_link)
+ {
+ if (use != use_link->ref
+ && DF_REF_REAL_REG (use) == DF_REF_REAL_REG (use_link->ref))
+ unionfind_union (use_entry + DF_REF_ID (use),
+ use_entry + DF_REF_ID (use_link->ref));
+ use_link = use_link->next;
+ }
+
+ /* Recognize trivial noop moves and attempt to keep them noop.
+ While most of noop moves should be removed we still keep some at
+ libcall boundaries and such. */
+
+ if (set
+ && SET_SRC (set) == DF_REF_REG (use)
+ && SET_SRC (set) == SET_DEST (set))
+ {
+ while (def_link)
+ {
+ if (DF_REF_REAL_REG (use) == DF_REF_REAL_REG (def_link->ref))
+ unionfind_union (use_entry + DF_REF_ID (use),
+ def_entry + DF_REF_ID (def_link->ref));
+ def_link = def_link->next;
+ }
+ }
+ while (link)
+ {
+ unionfind_union (use_entry + DF_REF_ID (use),
+ def_entry + DF_REF_ID (link->ref));
+ link = link->next;
+ }
+
+ /* An READ_WRITE use require the corresponding def to be in the same
+ register. Find it and union. */
+ if (use->flags & DF_REF_READ_WRITE)
+ {
+ struct df_link *link = DF_INSN_DEFS (df, DF_REF_INSN (use));
+
+ while (DF_REF_REAL_REG (link->ref) != DF_REF_REAL_REG (use))
+ link = link->next;
+
+ unionfind_union (use_entry + DF_REF_ID (use),
+ def_entry + DF_REF_ID (link->ref));
+ }
+ }
+
+ /* Find corresponding register for given entry. */
+
+ static rtx
+ entry_register (entry, ref, used, use_addressof)
+ struct web_entry *entry;
+ struct ref *ref;
+ char *used;
+ char *use_addressof;
+ {
+ struct web_entry *root;
+ rtx reg, newreg;
+
+ /* Find corresponding web and see if it has been visited. */
+
+ root = unionfind_root (entry);
+ if (root->reg)
+ return root->reg;
+
+ /* We are seeing this web first time, do the assignment. */
+
+ reg = DF_REF_REAL_REG (ref);
+
+ /* In case the original register is already assigned, generate new one. */
+ if (!used[REGNO (reg)])
+ newreg = reg, used[REGNO (reg)] = 1;
+ else if (REG_USERVAR_P (reg) && 0/*&& !flag_messy_debugging*/)
+ {
+ newreg = reg;
+ if (rtl_dump_file)
+ fprintf (rtl_dump_file,
+ "New web forced to keep reg=%i (user variable)\n",
+ REGNO (reg));
+ }
+ else if (use_addressof [REGNO (reg)])
+ {
+ newreg = reg;
+ if (rtl_dump_file)
+ fprintf (rtl_dump_file,
+ "New web forced to keep reg=%i (address taken)\n",
+ REGNO (reg));
+ }
+ else
+ {
+ newreg = gen_reg_rtx (GET_MODE (reg));
+ REG_USERVAR_P (newreg) = REG_USERVAR_P (reg);
+ REG_POINTER (newreg) = REG_POINTER (reg);
+ REG_LOOP_TEST_P (newreg) = REG_LOOP_TEST_P (reg);
+ RTX_UNCHANGING_P (newreg) = RTX_UNCHANGING_P (reg);
+ REG_ATTRS (newreg) = REG_ATTRS (reg);
+ if (rtl_dump_file)
+ fprintf (rtl_dump_file, "Web oldreg=%i newreg=%i\n", REGNO (reg),
+ REGNO (newreg));
+ }
+
+ root->reg = newreg;
+ return newreg;
+ }
+
+ /* Replace the reference by REG. */
+
+ static void
+ replace_ref (ref, reg)
+ struct ref *ref;
+ rtx reg;
+ {
+ rtx oldreg = DF_REF_REAL_REG (ref);
+ rtx *loc = DF_REF_REAL_LOC (ref);
+
+ if (oldreg == reg)
+ return;
+ if (rtl_dump_file)
+ fprintf (rtl_dump_file, "Updating insn %i (%i->%i)\n",
+ INSN_UID (DF_REF_INSN (ref)), REGNO (oldreg), REGNO (reg));
+ *loc = reg;
+ }
+
+ /* Mark each pseudo, whose address is taken. */
+
+ static int
+ mark_addressof (rtl, data)
+ rtx *rtl;
+ void *data;
+ {
+ if (!*rtl)
+ return 0;
+ if (GET_CODE (*rtl) == ADDRESSOF
+ && REG_P (XEXP (*rtl, 0)))
+ ((char *)data)[REGNO (XEXP (*rtl, 0))] = 1;
+ return 0;
+ }
+
+ /* Main entry point. */
+
+ void
+ web_main ()
+ {
+ struct df *df;
+ struct web_entry *def_entry;
+ struct web_entry *use_entry;
+ unsigned int i;
+ int max = max_reg_num ();
+ char *used;
+ char *use_addressof;
+ rtx insn;
+
+ df = df_init ();
+ df_analyse (df, 0, DF_UD_CHAIN | DF_EQUIV_NOTES);
+
+ def_entry =
+ (struct web_entry *) xcalloc (df->n_defs, sizeof (struct web_entry));
+ use_entry =
+ (struct web_entry *) xcalloc (df->n_uses, sizeof (struct web_entry));
+ used = (char *) xcalloc (max, sizeof (char));
+ use_addressof = (char *) xcalloc (max, sizeof (char));
+
+ if (rtl_dump_file)
+ df_dump (df, DF_UD_CHAIN | DF_DU_CHAIN, rtl_dump_file);
+
+ /* Produce the web. */
+ for (i = 0; i < df->n_uses; i++)
+ union_defs (df, df->uses[i], def_entry, use_entry);
+
+ /* We can not safely rename registers whose address is taken. */
+ for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+ if (INSN_P (insn))
+ for_each_rtx (&PATTERN (insn), mark_addressof, use_addressof);
+
+ /* Update the instruction stream, allocating new registers for split pseudos
+ in progress. */
+ for (i = 0; i < df->n_uses; i++)
+ replace_ref (df->uses[i], entry_register (use_entry + i, df->uses[i],
+ used, use_addressof));
+ for (i = 0; i < df->n_defs; i++)
+ replace_ref (df->defs[i], entry_register (def_entry + i, df->defs[i],
+ used, use_addressof));
+
+ /* Dataflow information is corrupt here, but it can be easy to update it
+ by creating new entries for new registers and update or calilng
+ df_insns_modify. */
+ free (def_entry);
+ free (use_entry);
+ free (used);
+ free (use_addressof);
+ df_finish (df);
+ }
Index: doc/invoke.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/invoke.texi,v
retrieving revision 1.234
diff -c -3 -p -r1.234 invoke.texi
*** doc/invoke.texi 4 Feb 2003 01:27:46 -0000 1.234
--- doc/invoke.texi 7 Feb 2003 12:11:07 -0000
*************** in the following sections.
*** 287,295 ****
-frerun-cse-after-loop -frerun-loop-opt @gol
-fschedule-insns -fschedule-insns2 @gol
-fno-sched-interblock -fno-sched-spec -fsched-spec-load @gol
-fsched-spec-load-dangerous -fsignaling-nans @gol
-fsingle-precision-constant -fssa -fssa-ccp -fssa-dce @gol
-fstrength-reduce -fstrict-aliasing -ftracer -fthread-jumps @gol
! -funroll-all-loops -funroll-loops @gol
--param @var{name}=@var{value}
-O -O0 -O1 -O2 -O3 -Os}
--- 287,297 ----
-frerun-cse-after-loop -frerun-loop-opt @gol
-fschedule-insns -fschedule-insns2 @gol
-fno-sched-interblock -fno-sched-spec -fsched-spec-load @gol
-fsched-spec-load-dangerous -fsignaling-nans @gol
-fsingle-precision-constant -fssa -fssa-ccp -fssa-dce @gol
-fstrength-reduce -fstrict-aliasing -ftracer -fthread-jumps @gol
! -funroll-all-loops -funroll-loops -fweb @gol
--param @var{name}=@var{value}
-O -O0 -O1 -O2 -O3 -Os}
*************** with @samp{r}.
*** 3239,3244 ****
--- 3240,3248 ----
@item y
@opindex dy
Dump debugging information during parsing, to standard error.
+ @item Z
+ @opindex dZ
+ Dump after web construction pass, to @file{@var{file}.10.web}.
@end table
@item -fdump-unnumbered
*************** of registers left over after register al
*** 4094,4099 ****
--- 4122,4136 ----
will most benefit processors with lots of registers. It can, however,
make debugging impossible, since variables will no longer stay in
a ``home register''.
+
+ @item -fweb
+ @opindex fweb
+ Constructs webs as commonly used for register allocation purposes and assign
+ each web individual pseudo register. This allows our register allocation pass
+ to operate on pseudos directly, but also strengthens several other optimization
+ passes, such as CSE, loop optimizer and trivial dead code remover. It can,
+ however, make debugging impossible, since variables will no longer stay in a
+ ``home register''.
Enabled at levels @option{-O3}.
More information about the Gcc-patches
mailing list