>> On Fri, Nov 09, 2001 at 08:54:27AM -0800, Andrew Macleod wrote: >> > I couldn't find a decent/logical place to put the 2 routines >> > that are currently in toplev.c... suggestions? >> >> life.c?
OK, I can create it. >> >> I also think you'll get better results if you place the >> initialization in the same block as the sets. Make sure >> to update the LOG_LINKS if you run this after regular >> life analysis. Well, we can kinda do that, but we need to use more infrastructure. We'd have to make sure that the first use we've found isn't also fed by some other definition, ie its in a loop. So we can't always insert it in that block, but we could insert it at the end of a block which dominates it. I took the cheap method of inserting it right at the beginning. Its doesn't come into play often, and I was hoping since its a set of 0, that any inefficiencies might be taken care of by another optimization. I suppose we could go build and use dominators at -O3 and get the set closer... What we really need to know is exactly what sets feed the use. If the block with the first use dominates all other sets, then we could insert the set right in front of the insn. Otherwise we'd have to set it at the end of the block which dominates the first use and all the other sets. Anyway, thats the logic I used to insert it at the beginning. Should I change that? Or is this sufficient for now? >> > We can use the flag to selectivly turn on the optimization just >> > for the targets we care about. >> >> As I demonstrated, I think _all_ targets will likely want this. Ok, I'll simply remove the flag. Here's the patch as it stands now: * Makefile.in (OBJS, life.o): Add life.c object and dependancies. * rtl.h (initialize_uninitialized_subregs): New prototype. * toplev.c (rest_of_compilation): Call initialize_uninitialized_subregs when optimization is on. * life.c (find_regno_partial, initialize_uninitialized_subregs): New file and functions. Index: gcc/Makefile.in =================================================================== RCS file: /cvs/gcc/egcs/gcc/Makefile.in,v retrieving revision 1.757 diff -c -p -r1.757 Makefile.in *** Makefile.in 2001/10/21 16:29:12 1.757 --- Makefile.in 2001/11/14 19:45:33 *************** C_OBJS = c-parse.o c-lang.o $(C_AND_OBJC *** 733,755 **** # Language-independent object files. ! OBJS = \ ! alias.o bb-reorder.o bitmap.o builtins.o caller-save.o calls.o \ ! combine.o conflict.o convert.o cse.o cselib.o dbxout.o debug.o \ ! dependence.o df.o diagnostic.o doloop.o dominance.o dwarf2asm.o \ ! dwarf2out.o dwarfout.o emit-rtl.o except.o explow.o expmed.o expr.o \ ! final.o flow.o fold-const.o function.o gcse.o genrtl.o ggc-common.o \ ! global.o graph.o haifa-sched.o hash.o hashtable.o ifcvt.o \ ! insn-attrtab.o insn-emit.o insn-extract.o insn-opinit.o insn-output.o \ ! insn-peep.o insn-recog.o integrate.o intl.o jump.o lcm.o lists.o \ ! local-alloc.o loop.o mbchar.o optabs.o params.o predict.o print-rtl.o \ ! print-tree.o profile.o real.o recog.o reg-stack.o regclass.o regmove.o \ ! regrename.o reload.o reload1.o reorg.o resource.o rtl.o rtlanal.o \ ! rtl-error.o sbitmap.o sched-deps.o sched-ebb.o sched-rgn.o sched-vis.o \ ! sdbout.o sibcall.o simplify-rtx.o splay-tree.o ssa.o ssa-ccp.o \ ! ssa-dce.o stmt.o stor-layout.o stringpool.o timevar.o toplev.o tree.o \ ! unroll.o varasm.o varray.o version.o xcoffout.o cfg.o cfganal.o \ ! cfgbuild.o cfgcleanup.o cfgloop.o cfgrtl.o tree-inline.o langhooks.o \ $(GGC) $(out_object_file) $(EXTRA_OBJS) BACKEND = main.o libbackend.a --- 733,755 ---- # Language-independent object files. ! OBJS = \ ! alias.o bb-reorder.o bitmap.o builtins.o caller-save.o calls.o \ ! combine.o conflict.o convert.o cse.o cselib.o dbxout.o debug.o \ ! dependence.o df.o diagnostic.o doloop.o dominance.o dwarf2asm.o \ ! dwarf2out.o dwarfout.o emit-rtl.o except.o explow.o expmed.o expr.o \ ! final.o flow.o fold-const.o function.o gcse.o genrtl.o ggc-common.o \ ! global.o graph.o haifa-sched.o hash.o hashtable.o ifcvt.o \ ! insn-attrtab.o insn-emit.o insn-extract.o insn-opinit.o insn-output.o \ ! insn-peep.o insn-recog.o integrate.o intl.o jump.o lcm.o life.o lists.o \ ! local-alloc.o loop.o mbchar.o optabs.o params.o predict.o print-rtl.o \ ! print-tree.o profile.o real.o recog.o reg-stack.o regclass.o regmove.o \ ! regrename.o reload.o reload1.o reorg.o resource.o rtl.o rtlanal.o \ ! rtl-error.o sbitmap.o sched-deps.o sched-ebb.o sched-rgn.o sched-vis.o \ ! sdbout.o sibcall.o simplify-rtx.o splay-tree.o ssa.o ssa-ccp.o \ ! ssa-dce.o stmt.o stor-layout.o stringpool.o timevar.o toplev.o tree.o \ ! unroll.o varasm.o varray.o version.o xcoffout.o cfg.o cfganal.o \ ! cfgbuild.o cfgcleanup.o cfgloop.o cfgrtl.o tree-inline.o langhooks.o \ $(GGC) $(out_object_file) $(EXTRA_OBJS) BACKEND = main.o libbackend.a *************** regrename.o : regrename.c $(CONFIG_H) $( *** 1593,1598 **** --- 1593,1600 ---- ifcvt.o : ifcvt.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(REGS_H) toplev.h \ flags.h insn-config.h function.h $(RECOG_H) $(BASIC_BLOCK_H) $(EXPR_H) \ output.h $(TM_P_H) + life.o : life.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) hard-reg-set.h \ + $(BASIC_BLOCK_H) bitmap.h $(REGS_H) $(EXPR_H) dependence.o : dependence.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) \ $(C_COMMON_H) flags.h varray.h $(EXPR_H) params.o : params.c $(CONFIG_H) $(SYSTEM_H) $(PARAMS_H) toplev.h Index: gcc/rtl.h =================================================================== RCS file: /cvs/gcc/egcs/gcc/rtl.h,v retrieving revision 1.309 diff -c -p -r1.309 rtl.h *** rtl.h 2001/10/25 12:55:16 1.309 --- rtl.h 2001/11/14 19:45:45 *************** extern void print_rtl_with_bb PARAMS (( *** 1898,1903 **** --- 1898,1906 ---- extern void dump_flow_info PARAMS ((FILE *)); #endif + /* In life.c */ + extern int initialize_uninitialized_subregs PARAMS ((void)); + /* In expmed.c */ extern void init_expmed PARAMS ((void)); extern void expand_inc PARAMS ((rtx, rtx)); Index: gcc/toplev.c =================================================================== RCS file: /cvs/gcc/egcs/gcc/toplev.c,v retrieving revision 1.525 diff -c -p -r1.525 toplev.c *** toplev.c 2001/10/23 13:34:23 1.525 --- toplev.c 2001/11/14 19:45:54 *************** rest_of_compilation (decl) *** 3280,3285 **** --- 3280,3296 ---- setjmp_args_warning (); } + if (optimize) + { + if (initialize_uninitialized_subregs ()) + { + /* Insns were inserted, so things might look a bit different. */ + insns = get_insns(); + life_analysis (insns, rtl_dump_file, + (PROP_LOG_LINKS | PROP_REG_INFO)); + } + } + close_dump_file (DFI_life, print_rtl_with_bb, insns); ggc_collect (); *** life.c Thu Nov 15 10:07:00 2001 --- gcc/life.c Wed Nov 14 12:11:23 2001 *************** *** 0 **** --- 1,140 ---- + /* Top level of GNU C compiler + Copyright (C) 2001 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. */ + + /* This contains various routines used by register lifetime analysis and + manipulation. */ + + #include "config.h" + #include "system.h" + #include "rtl.h" + #include "hard-reg-set.h" + #include "basic-block.h" + #include "bitmap.h" + #include "regs.h" + #include "expr.h" + + static int find_regno_partial PARAMS ((rtx *, void *)); + + /* This structure is used to pass parameters to an from the + the function find_regno_partial(). It is used to pass in the + register number we are looking, as well as to return any rtx + we find. */ + + typedef struct { + unsigned regno_to_find; + rtx retval; + } find_regno_partial_param; + + + /* Find the rtx for the reg numbers specified in 'data' if it is + part of an expression which only uses part of the register. Return + it in the structure passed in. */ + static int + find_regno_partial (ptr, data) + rtx *ptr; + void *data; + { + find_regno_partial_param *param = (find_regno_partial_param *)data; + unsigned reg = param->regno_to_find; + param->retval = NULL_RTX; + + if (*ptr == NULL_RTX) + return 0; + + switch (GET_CODE (*ptr)) + { + case ZERO_EXTRACT: + case SIGN_EXTRACT: + case STRICT_LOW_PART: + if (GET_CODE (XEXP (*ptr, 0)) == REG && REGNO (XEXP (*ptr, 0)) == reg) + { + param->retval = *ptr; + return 1; + } + break; + + case SUBREG: + if (GET_CODE (SUBREG_REG (*ptr)) == REG + && REGNO (SUBREG_REG (*ptr)) == reg) + { + param->retval = *ptr; + return 1; + } + break; + } + + return 0; + } + + /* Process all immediate successors of the entry block looking for pseudo + registers which are live on entry. Find all of those whose first + instance is a partial register reference of some kind, and initialize + them to 0 after the entry block. This will prevent bit sets within + registers whose value is unknown, and may contain some kind of sticky + bits we don't want. */ + + int + initialize_uninitialized_subregs () + { + rtx insn; + edge e; + int reg, did_something = 0; + find_regno_partial_param param; + + for (e = ENTRY_BLOCK_PTR->succ; e; e = e->succ_next) + { + basic_block bb = e->dest; + regset map = bb->global_live_at_start; + EXECUTE_IF_SET_IN_REG_SET (map, + FIRST_PSEUDO_REGISTER, reg, + { + int uid = REGNO_FIRST_UID (reg); + rtx i; + + /* Find an insn which mentions the register we are looking for. + Its preferable to have an instance of the register's rtl since + there may be various flags set which we need to duplicate. + If we can't find it, its probably an automatic whose initial + value doesnt matter, or hopefully something we dont care about. */ + for (i = get_insns (); i && INSN_UID (i) != uid; i = NEXT_INSN (i)) + ; + if (i != NULL_RTX) + { + /* Found the insn, now get the REG rtx, if we can. */ + param.regno_to_find = reg; + for_each_rtx (&i, find_regno_partial, ¶m); + if (param.retval != NULL_RTX) + { + insn = gen_move_insn (param.retval, + CONST0_RTX (GET_MODE (param.retval))); + insert_insn_on_edge (insn, e); + did_something = 1; + } + } + }); + } + + if (did_something) + commit_edge_insertions (); + return did_something; + } + + +