This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[rtlopt] GCSE global variables removal


Hello,

a patch to remove superfluous usage of global variables in gcse; this
should make their usage more transparent.

The change was approved for rtlopt-branch by Honza, I'm commiting it
there.

Zdenek Dvorak

Changelog:
	* gcse.c (run_jump_opt_after_gcse, can_copy_p, can_copy_init_p,
	current_bb): Removed, now passed locally.
	(expr_hash_table, set_hash_table, cprop_pavloc, cprop_absaltered,
	cprop_avin, cprop_avout, hoist_vbein, hoist_vbeout, hoist_exprs,
	dominators, regvec, st_antloc, num_stores): Removed, now passed
	locally in ...
	(struct pre_global, struct classic_global, struct hoist_global,
	struct store_global, struct cprop_global): New types.
	(rd_kill, rd_gen, reaching_defs, rd_out): Merged to ...
	(struct rd): new type, passed locally.
	(ae_kill, ae_gen, ae_in, ae_out): Merged to ...
	(struct ae): new type, passed locally.
	(reg_set_table, reg_set_table_size): Merged to ...
	(reg_set_table): New.
	(gcse_main, compute_can_copy, alloc_reg_set_mem, free_reg_set_mem,
	record_one_set, oprs_unchanged_p, oprs_anticipatable_p,
	oprs_available_p, hash_scan_set, hash_scan_insn,
	record_last_reg_set_info, record_last_reg_set_info,
	compute_hash_table_work, alloc_rd_mem, free_rd_mem,
	handle_rd_kill_set, compute_kill_rd, compute_rd,
	compute_ae_kill, expr_reaches_here_p_work, expr_reaches_here_p,
	computing_insn, def_reaches_here_p, can_disregard_other_sets,
	handle_avail_expr, classic_gcse, one_classic_gcse_pass,
	alloc_cprop_mem, free_cprop_mem, compute_transp, compute_cprop_data,
	find_used_regs, find_avail_set, cprop_jump, constprop_register,
	constprop_register, cprop_insn, do_local_cprop, local_cprop_pass,
	cprop, one_cprop_pass, find_bypass_set, bypass_block,
	bypass_conditional_jumps, compute_pre_data, pre_expr_reaches_here_p_work,
	pre_expr_reaches_here_p, insert_insn_end_bb, pre_edge_insert,
	pre_insert_copies, pre_delete, pre_gcse, one_pre_gcse_pass,
	compute_transpout, alloc_code_hoist_mem, free_code_hoist_mem,
	compute_code_hoist_vbeinout, compute_code_hoist_data,
	hoist_expr_reaches_here_p, hoist_code, one_code_hoisting_pass,
	trim_ld_motion_mems, reg_set_info, compute_store_table,
	build_store_vectors, insert_store, free_store_memory,
	store_motion): Modified due to removal of global variables.

Index: gcse.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/gcse.c,v
retrieving revision 1.218
diff -c -3 -p -r1.218 gcse.c
*** gcse.c	13 Aug 2002 13:50:22 -0000	1.218
--- gcse.c	19 Sep 2002 20:12:41 -0000
*************** Software Foundation, 59 Temple Place - S
*** 278,292 ****
  /* -dG dump file.  */
  static FILE *gcse_file;
  
- /* Note whether or not we should run jump optimization after gcse.  We
-    want to do this for two cases.
- 
-     * If we changed any jumps via cprop.
- 
-     * If we added any labels via edge splitting.  */
- 
- static int run_jump_opt_after_gcse;
- 
  /* Bitmaps are normally not included in debugging dumps.
     However it's useful to be able to print them from GDB.
     We could create special functions for this, but it's simpler to
--- 278,283 ----
*************** static FILE *debug_stderr;
*** 297,310 ****
  /* An obstack for our working variables.  */
  static struct obstack gcse_obstack;
  
- /* Non-zero for each mode that supports (set (reg) (reg)).
-    This is trivially true for integer and floating point values.
-    It may or may not be true for condition codes.  */
- static char can_copy_p[(int) NUM_MACHINE_MODES];
- 
- /* Non-zero if can_copy_p has been initialized.  */
- static int can_copy_init_p;
- 
  struct reg_use {rtx reg_rtx; };
  
  /* Hash table of expressions.  */
--- 288,293 ----
*************** struct hash_table
*** 378,388 ****
    int set_p;
  };
  
! /* Expression hash table.  */
! static struct hash_table expr_hash_table;
! 
! /* Copy propagation hash table.  */
! static struct hash_table set_hash_table;
  
  /* Mapping of uids to cuids.
     Only real insns get cuids.  */
--- 361,372 ----
    int set_p;
  };
  
! struct reg_avail_info
! {
!   basic_block last_bb;
!   int first_set;
!   int last_set;
! };
  
  /* Mapping of uids to cuids.
     Only real insns get cuids.  */
*************** typedef struct reg_set
*** 443,454 ****
    rtx insn;
  } reg_set;
  
! static reg_set **reg_set_table;
! 
! /* Size of `reg_set_table'.
!    The table starts out at max_gcse_regno + slop, and is enlarged as
!    necessary.  */
! static int reg_set_table_size;
  
  /* Amount to grow `reg_set_table' by when it's full.  */
  #define REG_SET_TABLE_SLOP 100
--- 427,437 ----
    rtx insn;
  } reg_set;
  
! struct reg_set_table
! {
!   reg_set **table;
!   int size;
! } reg_set_table;
  
  /* Amount to grow `reg_set_table' by when it's full.  */
  #define REG_SET_TABLE_SLOP 100
*************** static int copy_prop_count;
*** 527,540 ****
         n_exprs - for available expressions
  
     Thus we view the bitmaps as 2 dimensional arrays.  i.e.
!    rd_kill[block_num][cuid_num]
!    ae_kill[block_num][expr_num]			 */
  
  /* For reaching defs */
! static sbitmap *rd_kill, *rd_gen, *reaching_defs, *rd_out;
  
  /* for available exprs */
! static sbitmap *ae_kill, *ae_gen, *ae_in, *ae_out;
  
  /* Objects of this type are passed around by the null-pointer check
     removal routines.  */
--- 510,667 ----
         n_exprs - for available expressions
  
     Thus we view the bitmaps as 2 dimensional arrays.  i.e.
!    rd.kill[block_num][cuid_num]
!    ae.kill[block_num][expr_num]			 */
  
  /* For reaching defs */
! struct rd
! {
!   sbitmap *kill, *gen, *reaching_defs, *out;
! };
  
  /* for available exprs */
! struct ae
! {
!   sbitmap *kill, *gen, *in, *out;
! };
! 
! /* Global data for PRE.  */
! struct pre_global
! {
!   /* Nonzero for expressions that are transparent in the block.  */
!   sbitmap *transp;
! 
!   /* Nonzero for expressions that are computed (available) in the block.  */
!   sbitmap *comp;
! 
!   /* Nonzero for expressions that are locally anticipatable in the block.  */
!   sbitmap *antloc;
! 
!   /* Nonzero for expressions which should be inserted on a specific edge.  */
!   sbitmap *insert_map;
! 
!   /* Nonzero for expressions which should be deleted in a specific block.  */
!   sbitmap *delete_map;
! 
!   /* Contains the edge_list returned by pre_edge_lcm.  */
!   struct edge_list *edge_list;
! 
!   /* Redundant insns.  */
!   sbitmap redundant_insns;
! 
!   /* Available expressions.  */
!   struct ae ae;
! 
!   /* Expressions hash table.  */
!   struct hash_table expr_hash_table;
! };
! 
! /* Global data for classic gcse.  */
! struct classic_global
! {
!   /* Available expressions.  */
!   struct ae ae;
! 
!   /* Reaching definitions.  */
!   struct rd rd;
! 
!   /* Expression hash table.  */
!   struct hash_table expr_hash_table;	       
! };
! 
! /* Global data for hoisting.  */
! struct hoist_global
! {
!   /* Nonzero for expressions that are transparent in the block.  */
!   sbitmap *transp;
! 
!   /* Nonzero for expressions that are transparent at the end of the block.
!      This is only zero for expressions killed by abnormal critical edge
!      created by a calls.  */
!   sbitmap *transpout;
! 
!   /* Nonzero for expressions that are computed (available) in the block.  */
!   sbitmap *comp;
! 
!   /* Nonzero for expressions that are locally anticipatable in the block.  */
!   sbitmap *antloc;
! 
!   /* Nonzero for expressions which should be inserted on a specific edge.  */
!   sbitmap *insert_map;
! 
!   /* Nonzero for expressions which should be deleted in a specific block.  */
!   sbitmap *delete_map;
! 
!   /* Available expressions.  */
!   struct ae ae;
! 
!   /* Very busy expressions.  */
!   sbitmap *vbein;
!   sbitmap *vbeout;
! 
!   /* Hoistable expressions.  */
!   sbitmap *exprs;
! 
!   /* Dominator bitmaps.  */
!   dominance_info dominators;
! 
!   /* Expressions hash table.  */
!   struct hash_table expr_hash_table;
! };
! 
! /* Global data for store motion.  */
! struct store_global
! {
!   /* This is used to communicate the target bitvector we want to use in the 
!      reg_set_info routine when called via the note_stores mechanism.  */
!   sbitmap * regvec;
! 
!   /* Nonzero for expressions that are transparent in the block.  */
!   sbitmap *transp;
! 
!   /* Used in computing the reverse edge graph bit vectors.  */
!   sbitmap * antloc;
! 
!   /* Global holding the number of store expressions we are dealing with.  */
!   int num_stores;
! 
!   /* Contains the edge_list returned by pre_edge_lcm.  */
!   struct edge_list *edge_list;
! 
!   /* Available expressions.  */
!   struct ae ae;
! 
!   /* Nonzero for expressions which should be inserted on a specific edge.  */
!   sbitmap *insert_map;
! 
!   /* Nonzero for expressions which should be deleted in a specific block.  */
!   sbitmap *delete_map;
! };
! 
! /* Copy/constant propagation global data.  */
! 
! /* Maximum number of register uses in an insn that we handle.  */
! #define MAX_USES 8
! 
! struct cprop_global
! {
!   /* Local properties of assignments.  */
!   sbitmap *pavloc;
!   sbitmap *absaltered;
! 
!   /* Global properties of assignments (computed from the local properties).  */
!   sbitmap *avin;
!   sbitmap *avout;
! 
!   /* Set hash table.  */
!   struct hash_table set_hash_table;
! 
!   /* Table of uses found in an insn.  */
!   struct reg_use reg_use_table[MAX_USES];
! 
!   /* Index into `reg_use_table' while building it.  */
!   int reg_use_count;
! };
  
  /* Objects of this type are passed around by the null-pointer check
     removal routines.  */
*************** struct null_pointer_info
*** 550,556 ****
    sbitmap *nonnull_killed;
  };
  
! static void compute_can_copy	PARAMS ((void));
  static char *gmalloc		PARAMS ((unsigned int));
  static char *grealloc		PARAMS ((char *, unsigned int));
  static char *gcse_alloc		PARAMS ((unsigned long));
--- 677,683 ----
    sbitmap *nonnull_killed;
  };
  
! static void compute_can_copy	PARAMS ((char []));
  static char *gmalloc		PARAMS ((unsigned int));
  static char *grealloc		PARAMS ((char *, unsigned int));
  static char *gcse_alloc		PARAMS ((unsigned long));
*************** static int get_bitmap_width     PARAMS (
*** 562,575 ****
  static void record_one_set	PARAMS ((int, rtx));
  static void record_set_info	PARAMS ((rtx, rtx, void *));
  static void compute_sets	PARAMS ((rtx));
! static void hash_scan_insn	PARAMS ((rtx, struct hash_table *, int));
! static void hash_scan_set	PARAMS ((rtx, rtx, struct hash_table *));
  static void hash_scan_clobber	PARAMS ((rtx, rtx, struct hash_table *));
  static void hash_scan_call	PARAMS ((rtx, rtx, struct hash_table *));
  static int want_to_gcse_p	PARAMS ((rtx));
! static int oprs_unchanged_p	PARAMS ((rtx, rtx, int));
! static int oprs_anticipatable_p PARAMS ((rtx, rtx));
! static int oprs_available_p	PARAMS ((rtx, rtx));
  static void insert_expr_in_table PARAMS ((rtx, enum machine_mode, rtx,
  					  int, int, struct hash_table *));
  static void insert_set_in_table PARAMS ((rtx, rtx, struct hash_table *));
--- 689,704 ----
  static void record_one_set	PARAMS ((int, rtx));
  static void record_set_info	PARAMS ((rtx, rtx, void *));
  static void compute_sets	PARAMS ((rtx));
! static void hash_scan_insn	PARAMS ((rtx, struct hash_table *,
! 					int, basic_block, struct reg_avail_info *));
! static void hash_scan_set	PARAMS ((rtx, rtx, struct hash_table *,
! 					basic_block, struct reg_avail_info *));
  static void hash_scan_clobber	PARAMS ((rtx, rtx, struct hash_table *));
  static void hash_scan_call	PARAMS ((rtx, rtx, struct hash_table *));
  static int want_to_gcse_p	PARAMS ((rtx));
! static int oprs_unchanged_p	PARAMS ((rtx, rtx, int, basic_block, struct reg_avail_info *));
! static int oprs_anticipatable_p PARAMS ((rtx, rtx, basic_block, struct reg_avail_info *));
! static int oprs_available_p	PARAMS ((rtx, rtx, basic_block, struct reg_avail_info *));
  static void insert_expr_in_table PARAMS ((rtx, enum machine_mode, rtx,
  					  int, int, struct hash_table *));
  static void insert_set_in_table PARAMS ((rtx, rtx, struct hash_table *));
*************** static unsigned int hash_expr_1 PARAMS (
*** 578,584 ****
  static unsigned int hash_string_1 PARAMS ((const char *));
  static unsigned int hash_set	PARAMS ((int, int));
  static int expr_equiv_p	        PARAMS ((rtx, rtx));
! static void record_last_reg_set_info PARAMS ((rtx, int));
  static void record_last_mem_set_info PARAMS ((rtx));
  static void record_last_set_info PARAMS ((rtx, rtx, void *));
  static void compute_hash_table	PARAMS ((struct hash_table *));
--- 707,713 ----
  static unsigned int hash_string_1 PARAMS ((const char *));
  static unsigned int hash_set	PARAMS ((int, int));
  static int expr_equiv_p	        PARAMS ((rtx, rtx));
! static void record_last_reg_set_info PARAMS ((rtx, int, basic_block, struct reg_avail_info *));
  static void record_last_mem_set_info PARAMS ((rtx));
  static void record_last_set_info PARAMS ((rtx, rtx, void *));
  static void compute_hash_table	PARAMS ((struct hash_table *));
*************** static void mark_call		PARAMS ((rtx));
*** 596,670 ****
  static void mark_set		PARAMS ((rtx, rtx));
  static void mark_clobber	PARAMS ((rtx, rtx));
  static void mark_oprs_set	PARAMS ((rtx));
! static void alloc_cprop_mem	PARAMS ((int, int));
! static void free_cprop_mem	PARAMS ((void));
  static void compute_transp	PARAMS ((rtx, int, sbitmap *, int));
! static void compute_transpout	PARAMS ((void));
  static void compute_local_properties PARAMS ((sbitmap *, sbitmap *, sbitmap *,
! 					      struct hash_table *));
! static void compute_cprop_data	PARAMS ((void));
  static void find_used_regs	PARAMS ((rtx *, void *));
  static int try_replace_reg	PARAMS ((rtx, rtx, rtx));
! static struct expr *find_avail_set PARAMS ((int, rtx));
! static int cprop_jump		PARAMS ((basic_block, rtx, rtx, rtx, rtx));
  static void mems_conflict_for_gcse_p PARAMS ((rtx, rtx, void *));
  static int load_killed_in_block_p    PARAMS ((basic_block, int, rtx, int));
  static void canon_list_insert        PARAMS ((rtx, rtx, void *));
! static int cprop_insn		PARAMS ((rtx, int));
! static int cprop		PARAMS ((int));
! static int one_cprop_pass	PARAMS ((int, int));
! static bool constprop_register	PARAMS ((rtx, rtx, rtx, int));
! static struct expr *find_bypass_set PARAMS ((int, int));
! static int bypass_block		    PARAMS ((basic_block, rtx, rtx));
! static int bypass_conditional_jumps PARAMS ((void));
! static void alloc_pre_mem	PARAMS ((int, int));
! static void free_pre_mem	PARAMS ((void));
! static void compute_pre_data	PARAMS ((void));
  static int pre_expr_reaches_here_p PARAMS ((basic_block, struct expr *,
! 					    basic_block));
! static void insert_insn_end_bb	PARAMS ((struct expr *, basic_block, int));
  static void pre_insert_copy_insn PARAMS ((struct expr *, rtx));
! static void pre_insert_copies	PARAMS ((void));
! static int pre_delete		PARAMS ((void));
! static int pre_gcse		PARAMS ((void));
  static int one_pre_gcse_pass	PARAMS ((int));
  static void add_label_notes	PARAMS ((rtx, rtx));
! static void alloc_code_hoist_mem PARAMS ((int, int));
! static void free_code_hoist_mem	PARAMS ((void));
! static void compute_code_hoist_vbeinout	PARAMS ((void));
! static void compute_code_hoist_data PARAMS ((void));
  static int hoist_expr_reaches_here_p PARAMS ((basic_block, int, basic_block,
! 					      char *));
! static void hoist_code		PARAMS ((void));
  static int one_code_hoisting_pass PARAMS ((void));
! static void alloc_rd_mem	PARAMS ((int, int));
! static void free_rd_mem		PARAMS ((void));
! static void handle_rd_kill_set	PARAMS ((rtx, int, basic_block));
! static void compute_kill_rd	PARAMS ((void));
! static void compute_rd		PARAMS ((void));
! static void alloc_avail_expr_mem PARAMS ((int, int));
! static void free_avail_expr_mem PARAMS ((void));
! static void compute_ae_gen	PARAMS ((struct hash_table *));
  static int expr_killed_p	PARAMS ((rtx, basic_block));
! static void compute_ae_kill	PARAMS ((sbitmap *, sbitmap *, struct hash_table *));
  static int expr_reaches_here_p	PARAMS ((struct occr *, struct expr *,
! 					 basic_block, int));
! static rtx computing_insn	PARAMS ((struct expr *, rtx));
! static int def_reaches_here_p	PARAMS ((rtx, rtx));
! static int can_disregard_other_sets PARAMS ((struct reg_set **, rtx, int));
! static int handle_avail_expr	PARAMS ((rtx, struct expr *));
! static int classic_gcse		PARAMS ((void));
  static int one_classic_gcse_pass PARAMS ((int));
  static void invalidate_nonnull_info PARAMS ((rtx, rtx, void *));
  static int delete_null_pointer_checks_1 PARAMS ((unsigned int *,
  						  sbitmap *, sbitmap *,
  						  struct null_pointer_info *));
  static rtx process_insert_insn	PARAMS ((struct expr *));
! static int pre_edge_insert	PARAMS ((struct edge_list *, struct expr **));
  static int expr_reaches_here_p_work PARAMS ((struct occr *, struct expr *,
! 					     basic_block, int, char *));
  static int pre_expr_reaches_here_p_work	PARAMS ((basic_block, struct expr *,
! 						 basic_block, char *));
  static struct ls_expr * ldst_entry 	PARAMS ((rtx));
  static void free_ldst_entry 		PARAMS ((struct ls_expr *));
  static void free_ldst_mems		PARAMS ((void));
--- 725,804 ----
  static void mark_set		PARAMS ((rtx, rtx));
  static void mark_clobber	PARAMS ((rtx, rtx));
  static void mark_oprs_set	PARAMS ((rtx));
! static void alloc_cprop_mem	PARAMS ((int, struct cprop_global *));
! static void free_cprop_mem	PARAMS ((struct cprop_global *));
  static void compute_transp	PARAMS ((rtx, int, sbitmap *, int));
! static void compute_transpout	PARAMS ((struct hoist_global *));
  static void compute_local_properties PARAMS ((sbitmap *, sbitmap *, sbitmap *,
!  					      struct hash_table *));
! static void compute_cprop_data	PARAMS ((struct cprop_global *));
  static void find_used_regs	PARAMS ((rtx *, void *));
  static int try_replace_reg	PARAMS ((rtx, rtx, rtx));
! static struct expr *find_avail_set PARAMS ((int, rtx, struct cprop_global *));
! static int cprop_jump		PARAMS ((basic_block, rtx, rtx, rtx, rtx, int *));
  static void mems_conflict_for_gcse_p PARAMS ((rtx, rtx, void *));
  static int load_killed_in_block_p    PARAMS ((basic_block, int, rtx, int));
  static void canon_list_insert        PARAMS ((rtx, rtx, void *));
! static int cprop_insn		PARAMS ((rtx, int, struct cprop_global *, int *));
! static int cprop		PARAMS ((int, struct cprop_global *, int *));
! static int one_cprop_pass	PARAMS ((int, int, int *));
! static bool constprop_register	PARAMS ((rtx, rtx, rtx, int, int *));
! static struct expr *find_bypass_set PARAMS ((int, int, struct cprop_global *));
! static int bypass_block		    PARAMS ((basic_block, rtx, rtx, struct cprop_global *));
! static int bypass_conditional_jumps PARAMS ((struct cprop_global *));
! static void alloc_pre_mem	PARAMS ((int, struct pre_global *));
! static void free_pre_mem	PARAMS ((struct pre_global *));
! static void compute_pre_data	PARAMS ((struct pre_global *));
  static int pre_expr_reaches_here_p PARAMS ((basic_block, struct expr *,
!  					    basic_block, struct pre_global *));
! static void insert_insn_end_bb	PARAMS ((struct expr *, basic_block, int,
! 					sbitmap *, sbitmap *));
  static void pre_insert_copy_insn PARAMS ((struct expr *, rtx));
! static void pre_insert_copies	PARAMS ((struct pre_global *));
! static int pre_delete		PARAMS ((struct pre_global *));
! static int pre_gcse		PARAMS ((struct pre_global *));
  static int one_pre_gcse_pass	PARAMS ((int));
  static void add_label_notes	PARAMS ((rtx, rtx));
! static void alloc_code_hoist_mem PARAMS ((int, struct hoist_global *));
! static void free_code_hoist_mem	PARAMS ((struct hoist_global *));
! static void compute_code_hoist_vbeinout	PARAMS (( struct hoist_global *));
! static void compute_code_hoist_data PARAMS (( struct hoist_global *));
  static int hoist_expr_reaches_here_p PARAMS ((basic_block, int, basic_block,
!  					      char *, struct hoist_global *));
! static void hoist_code		PARAMS ((struct hoist_global *));
  static int one_code_hoisting_pass PARAMS ((void));
! static void alloc_rd_mem	PARAMS ((int, int, struct rd *));
! static void free_rd_mem		PARAMS ((struct rd *));
! static void handle_rd_kill_set	PARAMS ((rtx, int, basic_block, struct rd *));
! static void compute_kill_rd	PARAMS ((struct rd *));
! static void compute_rd		PARAMS ((struct rd *));
! static void alloc_avail_expr_mem PARAMS ((int, int, struct ae *));
! static void free_avail_expr_mem PARAMS ((struct ae *));
! static void compute_ae_gen	PARAMS ((struct ae *, struct hash_table *));
  static int expr_killed_p	PARAMS ((rtx, basic_block));
! static void compute_ae_kill	PARAMS ((struct ae *, struct hash_table *));
  static int expr_reaches_here_p	PARAMS ((struct occr *, struct expr *,
! 					 basic_block, int, struct ae *));
! static rtx computing_insn	PARAMS ((struct expr *, rtx, struct ae *));
! static int def_reaches_here_p	PARAMS ((rtx, rtx, struct rd *));
! static int can_disregard_other_sets PARAMS ((struct reg_set **, rtx, int,
! 					    struct rd *));
! static int handle_avail_expr	PARAMS ((rtx, struct expr *,
! 					struct ae *, struct rd *));
! static int classic_gcse		PARAMS ((struct classic_global *));
  static int one_classic_gcse_pass PARAMS ((int));
  static void invalidate_nonnull_info PARAMS ((rtx, rtx, void *));
  static int delete_null_pointer_checks_1 PARAMS ((unsigned int *,
  						  sbitmap *, sbitmap *,
  						  struct null_pointer_info *));
  static rtx process_insert_insn	PARAMS ((struct expr *));
! static int pre_edge_insert	PARAMS ((struct expr **, struct pre_global *));
  static int expr_reaches_here_p_work PARAMS ((struct occr *, struct expr *,
! 					     basic_block, int, char *,
! 					     struct ae *));
  static int pre_expr_reaches_here_p_work	PARAMS ((basic_block, struct expr *,
! 						 basic_block, char *,
! 						 struct pre_global *));
  static struct ls_expr * ldst_entry 	PARAMS ((rtx));
  static void free_ldst_entry 		PARAMS ((struct ls_expr *));
  static void free_ldst_mems		PARAMS ((void));
*************** static inline struct ls_expr * next_ls_e
*** 676,707 ****
  static int simple_mem			PARAMS ((rtx));
  static void invalidate_any_buried_refs	PARAMS ((rtx));
  static void compute_ld_motion_mems	PARAMS ((void));
! static void trim_ld_motion_mems		PARAMS ((void));
  static void update_ld_motion_stores	PARAMS ((struct expr *));
  static void reg_set_info		PARAMS ((rtx, rtx, void *));
  static int store_ops_ok			PARAMS ((rtx, basic_block));
  static void find_moveable_store		PARAMS ((rtx));
! static int compute_store_table		PARAMS ((void));
  static int load_kills_store		PARAMS ((rtx, rtx));
  static int find_loads			PARAMS ((rtx, rtx));
  static int store_killed_in_insn		PARAMS ((rtx, rtx));
  static int store_killed_after		PARAMS ((rtx, rtx, basic_block));
  static int store_killed_before		PARAMS ((rtx, rtx, basic_block));
! static void build_store_vectors		PARAMS ((void));
  static void insert_insn_start_bb	PARAMS ((rtx, basic_block));
! static int insert_store			PARAMS ((struct ls_expr *, edge));
  static void replace_store_insn		PARAMS ((rtx, rtx, basic_block));
  static void delete_store		PARAMS ((struct ls_expr *,
  						 basic_block));
! static void free_store_memory		PARAMS ((void));
  static void store_motion		PARAMS ((void));
  static void free_insn_expr_list_list	PARAMS ((rtx *));
  static void clear_modify_mem_tables	PARAMS ((void));
  static void free_modify_mem_tables	PARAMS ((void));
  static rtx gcse_emit_move_after		PARAMS ((rtx, rtx, rtx));
! static bool do_local_cprop		PARAMS ((rtx, rtx, int, rtx*));
  static bool adjust_libcall_notes	PARAMS ((rtx, rtx, rtx, rtx*));
! static void local_cprop_pass		PARAMS ((int));
  
  /* Entry point for global common subexpression elimination.
     F is the first instruction in the function.  */
--- 810,842 ----
  static int simple_mem			PARAMS ((rtx));
  static void invalidate_any_buried_refs	PARAMS ((rtx));
  static void compute_ld_motion_mems	PARAMS ((void));
! static void trim_ld_motion_mems		PARAMS ((struct pre_global *));
  static void update_ld_motion_stores	PARAMS ((struct expr *));
  static void reg_set_info		PARAMS ((rtx, rtx, void *));
  static int store_ops_ok			PARAMS ((rtx, basic_block));
  static void find_moveable_store		PARAMS ((rtx));
! static int compute_store_table		PARAMS ((struct store_global *));
  static int load_kills_store		PARAMS ((rtx, rtx));
  static int find_loads			PARAMS ((rtx, rtx));
  static int store_killed_in_insn		PARAMS ((rtx, rtx));
  static int store_killed_after		PARAMS ((rtx, rtx, basic_block));
  static int store_killed_before		PARAMS ((rtx, rtx, basic_block));
! static void build_store_vectors		PARAMS ((struct store_global *));
  static void insert_insn_start_bb	PARAMS ((rtx, basic_block));
! static int insert_store			PARAMS ((struct ls_expr *, edge,
! 						struct store_global *));
  static void replace_store_insn		PARAMS ((rtx, rtx, basic_block));
  static void delete_store		PARAMS ((struct ls_expr *,
  						 basic_block));
! static void free_store_memory		PARAMS ((struct store_global *));
  static void store_motion		PARAMS ((void));
  static void free_insn_expr_list_list	PARAMS ((rtx *));
  static void clear_modify_mem_tables	PARAMS ((void));
  static void free_modify_mem_tables	PARAMS ((void));
  static rtx gcse_emit_move_after		PARAMS ((rtx, rtx, rtx));
! static bool do_local_cprop		PARAMS ((rtx, rtx, int, int *, rtx *));
  static bool adjust_libcall_notes	PARAMS ((rtx, rtx, rtx, rtx*));
! static void local_cprop_pass		PARAMS ((int, int *, struct cprop_global *));
  
  /* Entry point for global common subexpression elimination.
     F is the first instruction in the function.  */
*************** gcse_main (f, file)
*** 723,728 ****
--- 858,872 ----
       need the original basic block count so that we can properly deallocate
       arrays sized on the number of basic blocks originally in the cfg.  */
    int orig_bb_count;
+ 
+   /* Note whether or not we should run jump optimization after gcse.  We
+      want to do this for two cases.
+ 
+       * If we changed any jumps via cprop.
+ 
+       * If we added any labels via edge splitting.  */
+   int run_jump_opt_after_gcse;
+ 
    /* We do not construct an accurate cfg in functions which call
       setjmp, so just punt to be safe.  */
    if (current_function_calls_setjmp)
*************** gcse_main (f, file)
*** 776,788 ****
        return 0;
      }
  
-   /* See what modes support reg/reg copy operations.  */
-   if (! can_copy_init_p)
-     {
-       compute_can_copy ();
-       can_copy_init_p = 1;
-     }
- 
    gcc_obstack_init (&gcse_obstack);
    bytes_used = 0;
  
--- 920,925 ----
*************** gcse_main (f, file)
*** 822,828 ****
  
        /* Don't allow constant propagation to modify jumps
  	 during this pass.  */
!       changed = one_cprop_pass (pass + 1, 0);
  
        if (optimize_size)
  	changed |= one_classic_gcse_pass (pass + 1);
--- 959,965 ----
  
        /* Don't allow constant propagation to modify jumps
  	 during this pass.  */
!       changed = one_cprop_pass (pass + 1, 0, &run_jump_opt_after_gcse);
  
        if (optimize_size)
  	changed |= one_classic_gcse_pass (pass + 1);
*************** gcse_main (f, file)
*** 890,896 ****
    max_gcse_regno = max_reg_num ();
    alloc_gcse_mem (f);
    /* This time, go ahead and allow cprop to alter jumps.  */
!   one_cprop_pass (pass + 1, 1);
    free_gcse_mem ();
  
    if (file)
--- 1027,1033 ----
    max_gcse_regno = max_reg_num ();
    alloc_gcse_mem (f);
    /* This time, go ahead and allow cprop to alter jumps.  */
!   one_cprop_pass (pass + 1, 1, &run_jump_opt_after_gcse);
    free_gcse_mem ();
  
    if (file)
*************** gcse_main (f, file)
*** 919,925 ****
  /* Compute which modes support reg/reg copy operations.  */
  
  static void
! compute_can_copy ()
  {
    int i;
  #ifndef AVOID_CCMODE_COPIES
--- 1056,1063 ----
  /* Compute which modes support reg/reg copy operations.  */
  
  static void
! compute_can_copy (can_copy_p)
!      char can_copy_p[];
  {
    int i;
  #ifndef AVOID_CCMODE_COPIES
*************** alloc_reg_set_mem (n_regs)
*** 1200,1209 ****
  {
    unsigned int n;
  
!   reg_set_table_size = n_regs + REG_SET_TABLE_SLOP;
!   n = reg_set_table_size * sizeof (struct reg_set *);
!   reg_set_table = (struct reg_set **) gmalloc (n);
!   memset ((char *) reg_set_table, 0, n);
  
    gcc_obstack_init (&reg_set_obstack);
  }
--- 1338,1347 ----
  {
    unsigned int n;
  
!   reg_set_table.size = n_regs + REG_SET_TABLE_SLOP;
!   n = reg_set_table.size * sizeof (struct reg_set *);
!   reg_set_table.table = (struct reg_set **) gmalloc (n);
!   memset ((char *) reg_set_table.table, 0, n);
  
    gcc_obstack_init (&reg_set_obstack);
  }
*************** alloc_reg_set_mem (n_regs)
*** 1211,1217 ****
  static void
  free_reg_set_mem ()
  {
!   free (reg_set_table);
    obstack_free (&reg_set_obstack, NULL);
  }
  
--- 1349,1355 ----
  static void
  free_reg_set_mem ()
  {
!   free (reg_set_table.table);
    obstack_free (&reg_set_obstack, NULL);
  }
  
*************** record_one_set (regno, insn)
*** 1226,1249 ****
    struct reg_set *new_reg_info;
  
    /* If the table isn't big enough, enlarge it.  */
!   if (regno >= reg_set_table_size)
      {
        int new_size = regno + REG_SET_TABLE_SLOP;
  
!       reg_set_table
! 	= (struct reg_set **) grealloc ((char *) reg_set_table,
  					new_size * sizeof (struct reg_set *));
!       memset ((char *) (reg_set_table + reg_set_table_size), 0,
! 	      (new_size - reg_set_table_size) * sizeof (struct reg_set *));
!       reg_set_table_size = new_size;
      }
  
    new_reg_info = (struct reg_set *) obstack_alloc (&reg_set_obstack,
  						   sizeof (struct reg_set));
    bytes_used += sizeof (struct reg_set);
    new_reg_info->insn = insn;
!   new_reg_info->next = reg_set_table[regno];
!   reg_set_table[regno] = new_reg_info;
  }
  
  /* Called from compute_sets via note_stores to handle one SET or CLOBBER in
--- 1364,1387 ----
    struct reg_set *new_reg_info;
  
    /* If the table isn't big enough, enlarge it.  */
!   if (regno >= reg_set_table.size)
      {
        int new_size = regno + REG_SET_TABLE_SLOP;
  
!       reg_set_table.table
! 	= (struct reg_set **) grealloc ((char *) reg_set_table.table,
  					new_size * sizeof (struct reg_set *));
!       memset ((char *) (reg_set_table.table + reg_set_table.size), 0,
! 	      (new_size - reg_set_table.size) * sizeof (struct reg_set *));
!       reg_set_table.size = new_size;
      }
  
    new_reg_info = (struct reg_set *) obstack_alloc (&reg_set_obstack,
  						   sizeof (struct reg_set));
    bytes_used += sizeof (struct reg_set);
    new_reg_info->insn = insn;
!   new_reg_info->next = reg_set_table.table[regno];
!   reg_set_table.table[regno] = new_reg_info;
  }
  
  /* Called from compute_sets via note_stores to handle one SET or CLOBBER in
*************** compute_sets (f)
*** 1279,1295 ****
  
  /* Hash table support.  */
  
- struct reg_avail_info
- {
-   basic_block last_bb;
-   int first_set;
-   int last_set;
- };
- 
- static struct reg_avail_info *reg_avail_info;
- static basic_block current_bb;
- 
- 
  /* See whether X, the source of a set, is something we want to consider for
     GCSE.  */
  
--- 1417,1422 ----
*************** want_to_gcse_p (x)
*** 1346,1354 ****
     or from INSN to the end of INSN's basic block (if AVAIL_P != 0).  */
  
  static int
! oprs_unchanged_p (x, insn, avail_p)
       rtx x, insn;
       int avail_p;
  {
    int i, j;
    enum rtx_code code;
--- 1473,1483 ----
     or from INSN to the end of INSN's basic block (if AVAIL_P != 0).  */
  
  static int
! oprs_unchanged_p (x, insn, avail_p, current_bb, reg_avail_info)
       rtx x, insn;
       int avail_p;
+      basic_block current_bb;
+      struct reg_avail_info *reg_avail_info;
  {
    int i, j;
    enum rtx_code code;
*************** oprs_unchanged_p (x, insn, avail_p)
*** 1377,1383 ****
  				  x, avail_p))
  	return 0;
        else
! 	return oprs_unchanged_p (XEXP (x, 0), insn, avail_p);
  
      case PRE_DEC:
      case PRE_INC:
--- 1506,1512 ----
  				  x, avail_p))
  	return 0;
        else
! 	return oprs_unchanged_p (XEXP (x, 0), insn, avail_p, current_bb, reg_avail_info);
  
      case PRE_DEC:
      case PRE_INC:
*************** oprs_unchanged_p (x, insn, avail_p)
*** 1411,1424 ****
  	     level, change it into iteration.  This function is called enough
  	     to be worth it.  */
  	  if (i == 0)
! 	    return oprs_unchanged_p (XEXP (x, i), insn, avail_p);
  
! 	  else if (! oprs_unchanged_p (XEXP (x, i), insn, avail_p))
  	    return 0;
  	}
        else if (fmt[i] == 'E')
  	for (j = 0; j < XVECLEN (x, i); j++)
! 	  if (! oprs_unchanged_p (XVECEXP (x, i, j), insn, avail_p))
  	    return 0;
      }
  
--- 1540,1553 ----
  	     level, change it into iteration.  This function is called enough
  	     to be worth it.  */
  	  if (i == 0)
! 	    return oprs_unchanged_p (XEXP (x, i), insn, avail_p, current_bb, reg_avail_info);
  
! 	  else if (! oprs_unchanged_p (XEXP (x, i), insn, avail_p, current_bb, reg_avail_info))
  	    return 0;
  	}
        else if (fmt[i] == 'E')
  	for (j = 0; j < XVECLEN (x, i); j++)
! 	  if (! oprs_unchanged_p (XVECEXP (x, i, j), insn, avail_p, current_bb, reg_avail_info))
  	    return 0;
      }
  
*************** load_killed_in_block_p (bb, uid_limit, x
*** 1528,1547 ****
     the start of INSN's basic block up to but not including INSN.  */
  
  static int
! oprs_anticipatable_p (x, insn)
       rtx x, insn;
  {
!   return oprs_unchanged_p (x, insn, 0);
  }
  
  /* Return non-zero if the operands of expression X are unchanged from
     INSN to the end of INSN's basic block.  */
  
  static int
! oprs_available_p (x, insn)
       rtx x, insn;
  {
!   return oprs_unchanged_p (x, insn, 1);
  }
  
  /* Hash expression X.
--- 1657,1680 ----
     the start of INSN's basic block up to but not including INSN.  */
  
  static int
! oprs_anticipatable_p (x, insn, current_bb, reg_avail_info)
       rtx x, insn;
+      basic_block current_bb;
+      struct reg_avail_info *reg_avail_info;
  {
!   return oprs_unchanged_p (x, insn, 0, current_bb, reg_avail_info);
  }
  
  /* Return non-zero if the operands of expression X are unchanged from
     INSN to the end of INSN's basic block.  */
  
  static int
! oprs_available_p (x, insn, current_bb, reg_avail_info)
       rtx x, insn;
+      basic_block current_bb;
+      struct reg_avail_info *reg_avail_info;
  {
!   return oprs_unchanged_p (x, insn, 1, current_bb, reg_avail_info);
  }
  
  /* Hash expression X.
*************** insert_set_in_table (x, insn, table)
*** 2156,2169 ****
     expression one).  */
  
  static void
! hash_scan_set (pat, insn, table)
       rtx pat, insn;
       struct hash_table *table;
  {
    rtx src = SET_SRC (pat);
    rtx dest = SET_DEST (pat);
    rtx note;
  
    if (GET_CODE (src) == CALL)
      hash_scan_call (src, insn, table);
  
--- 2289,2319 ----
     expression one).  */
  
  static void
! hash_scan_set (pat, insn, table, current_bb, reg_avail_info)
       rtx pat, insn;
       struct hash_table *table;
+      basic_block current_bb;
+      struct reg_avail_info *reg_avail_info;
  {
+   /* Non-zero for each mode that supports (set (reg) (reg)).
+      This is trivially true for integer and floating point values.
+      It may or may not be true for condition codes.  */
+   static char can_copy_p[(int) NUM_MACHINE_MODES];
+ 
+   /* Non-zero if can_copy_p has been initialized.  */
+   static int can_copy_init_p;
+ 
    rtx src = SET_SRC (pat);
    rtx dest = SET_DEST (pat);
    rtx note;
  
+   /* See what modes support reg/reg copy operations.  */
+   if (! can_copy_init_p)
+     {
+       compute_can_copy (can_copy_p);
+       can_copy_init_p = 1;
+     }
+ 
    if (GET_CODE (src) == CALL)
      hash_scan_call (src, insn, table);
  
*************** hash_scan_set (pat, insn, table)
*** 2202,2216 ****
  	  /* An expression is not anticipatable if its operands are
  	     modified before this insn or if this is not the only SET in
  	     this insn.  */
! 	  int antic_p = oprs_anticipatable_p (src, insn) && single_set (insn);
  	  /* An expression is not available if its operands are
  	     subsequently modified, including this insn.  It's also not
  	     available if this is a branch, because we can't insert
  	     a set after the branch.  */
! 	  int avail_p = (oprs_available_p (src, insn)
  			 && ! JUMP_P (insn));
  
! 	  insert_expr_in_table (src, GET_MODE (dest), insn, antic_p, avail_p, table);
  	}
  
        /* Record sets for constant/copy propagation.  */
--- 2352,2367 ----
  	  /* An expression is not anticipatable if its operands are
  	     modified before this insn or if this is not the only SET in
  	     this insn.  */
! 	  int antic_p = oprs_anticipatable_p (src, insn, current_bb, reg_avail_info) && single_set (insn);
  	  /* An expression is not available if its operands are
  	     subsequently modified, including this insn.  It's also not
  	     available if this is a branch, because we can't insert
  	     a set after the branch.  */
! 	  int avail_p = (oprs_available_p (src, insn, current_bb, reg_avail_info)
  			 && ! JUMP_P (insn));
  
! 	  insert_expr_in_table (src, GET_MODE (dest), insn, antic_p, avail_p,
! 				table);
  	}
  
        /* Record sets for constant/copy propagation.  */
*************** hash_scan_set (pat, insn, table)
*** 2226,2232 ****
  		  oprs_available_p searches from INSN on.  */
  	       && (insn == BLOCK_END (BLOCK_NUM (insn))
  		   || ((tmp = next_nonnote_insn (insn)) != NULL_RTX
! 		       && oprs_available_p (pat, tmp))))
  	insert_set_in_table (pat, insn, table);
      }
  }
--- 2377,2383 ----
  		  oprs_available_p searches from INSN on.  */
  	       && (insn == BLOCK_END (BLOCK_NUM (insn))
  		   || ((tmp = next_nonnote_insn (insn)) != NULL_RTX
! 		       && oprs_available_p (pat, tmp, current_bb, reg_avail_info))))
  	insert_set_in_table (pat, insn, table);
      }
  }
*************** hash_scan_call (x, insn, table)
*** 2261,2270 ****
     not record any expressions.  */
  
  static void
! hash_scan_insn (insn, table, in_libcall_block)
       rtx insn;
       struct hash_table *table;
       int in_libcall_block;
  {
    rtx pat = PATTERN (insn);
    int i;
--- 2412,2423 ----
     not record any expressions.  */
  
  static void
! hash_scan_insn (insn, table, in_libcall_block, current_bb, reg_avail_info)
       rtx insn;
       struct hash_table *table;
       int in_libcall_block;
+      basic_block current_bb;
+      struct reg_avail_info *reg_avail_info;
  {
    rtx pat = PATTERN (insn);
    int i;
*************** hash_scan_insn (insn, table, in_libcall_
*** 2276,2289 ****
       what's been modified.  */
  
    if (GET_CODE (pat) == SET)
!     hash_scan_set (pat, insn, table);
    else if (GET_CODE (pat) == PARALLEL)
      for (i = 0; i < XVECLEN (pat, 0); i++)
        {
  	rtx x = XVECEXP (pat, 0, i);
  
  	if (GET_CODE (x) == SET)
! 	  hash_scan_set (x, insn, table);
  	else if (GET_CODE (x) == CLOBBER)
  	  hash_scan_clobber (x, insn, table);
  	else if (GET_CODE (x) == CALL)
--- 2429,2442 ----
       what's been modified.  */
  
    if (GET_CODE (pat) == SET)
!     hash_scan_set (pat, insn, table, current_bb, reg_avail_info);
    else if (GET_CODE (pat) == PARALLEL)
      for (i = 0; i < XVECLEN (pat, 0); i++)
        {
  	rtx x = XVECEXP (pat, 0, i);
  
  	if (GET_CODE (x) == SET)
! 	  hash_scan_set (x, insn, table, current_bb, reg_avail_info);
  	else if (GET_CODE (x) == CLOBBER)
  	  hash_scan_clobber (x, insn, table);
  	else if (GET_CODE (x) == CALL)
*************** dump_hash_table (file, name, table)
*** 2353,2361 ****
     and is used to compute "transparency".  */
  
  static void
! record_last_reg_set_info (insn, regno)
       rtx insn;
       int regno;
  {
    struct reg_avail_info *info = &reg_avail_info[regno];
    int cuid = INSN_CUID (insn);
--- 2506,2516 ----
     and is used to compute "transparency".  */
  
  static void
! record_last_reg_set_info (insn, regno, current_bb, reg_avail_info)
       rtx insn;
       int regno;
+      basic_block current_bb;
+      struct reg_avail_info *reg_avail_info;
  {
    struct reg_avail_info *info = &reg_avail_info[regno];
    int cuid = INSN_CUID (insn);
*************** record_last_mem_set_info (insn)
*** 2440,2445 ****
--- 2595,2602 ----
     SET or CLOBBER in an insn.  DATA is really the instruction in which
     the SET is taking place.  */
  
+ static basic_block rlsi_current_bb;
+ static struct reg_avail_info *rlsi_reg_avail_info;
  static void
  record_last_set_info (dest, setter, data)
       rtx dest, setter ATTRIBUTE_UNUSED;
*************** record_last_set_info (dest, setter, data
*** 2451,2457 ****
      dest = SUBREG_REG (dest);
  
    if (GET_CODE (dest) == REG)
!     record_last_reg_set_info (last_set_insn, REGNO (dest));
    else if (GET_CODE (dest) == MEM
  	   /* Ignore pushes, they clobber nothing.  */
  	   && ! push_operand (dest, GET_MODE (dest)))
--- 2608,2614 ----
      dest = SUBREG_REG (dest);
  
    if (GET_CODE (dest) == REG)
!     record_last_reg_set_info (last_set_insn, REGNO (dest), rlsi_current_bb, rlsi_reg_avail_info);
    else if (GET_CODE (dest) == MEM
  	   /* Ignore pushes, they clobber nothing.  */
  	   && ! push_operand (dest, GET_MODE (dest)))
*************** compute_hash_table_work (table)
*** 2480,2485 ****
--- 2637,2644 ----
       struct hash_table *table;
  {
    unsigned int i;
+   basic_block current_bb;
+   struct reg_avail_info *reg_avail_info;
  
    /* While we compute the hash table we also compute a bit array of which
       registers are set in which blocks.
*************** compute_hash_table_work (table)
*** 2526,2536 ****
  	      for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
  		if (clobbers_all
  		    || TEST_HARD_REG_BIT (regs_invalidated_by_call, regno))
! 		  record_last_reg_set_info (insn, regno);
  
  	      mark_call (insn);
  	    }
  
  	  note_stores (PATTERN (insn), record_last_set_info, insn);
  	}
  
--- 2685,2697 ----
  	      for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
  		if (clobbers_all
  		    || TEST_HARD_REG_BIT (regs_invalidated_by_call, regno))
! 		  record_last_reg_set_info (insn, regno, current_bb, reg_avail_info);
  
  	      mark_call (insn);
  	    }
  
+ 	  rlsi_current_bb = current_bb;
+ 	  rlsi_reg_avail_info = reg_avail_info;
  	  note_stores (PATTERN (insn), record_last_set_info, insn);
  	}
  
*************** compute_hash_table_work (table)
*** 2545,2551 ****
  	      in_libcall_block = 1;
  	    else if (table->set_p && find_reg_note (insn, REG_RETVAL, NULL_RTX))
  	      in_libcall_block = 0;
! 	    hash_scan_insn (insn, table, in_libcall_block);
  	    if (!table->set_p && find_reg_note (insn, REG_RETVAL, NULL_RTX))
  	      in_libcall_block = 0;
  	  }
--- 2706,2712 ----
  	      in_libcall_block = 1;
  	    else if (table->set_p && find_reg_note (insn, REG_RETVAL, NULL_RTX))
  	      in_libcall_block = 0;
! 	    hash_scan_insn (insn, table, in_libcall_block, current_bb, reg_avail_info);
  	    if (!table->set_p && find_reg_note (insn, REG_RETVAL, NULL_RTX))
  	      in_libcall_block = 0;
  	  }
*************** mark_oprs_set (insn)
*** 2892,2943 ****
  /* Allocate reaching def variables.  */
  
  static void
! alloc_rd_mem (n_blocks, n_insns)
       int n_blocks, n_insns;
  {
!   rd_kill = (sbitmap *) sbitmap_vector_alloc (n_blocks, n_insns);
!   sbitmap_vector_zero (rd_kill, n_blocks);
  
!   rd_gen = (sbitmap *) sbitmap_vector_alloc (n_blocks, n_insns);
!   sbitmap_vector_zero (rd_gen, n_blocks);
  
!   reaching_defs = (sbitmap *) sbitmap_vector_alloc (n_blocks, n_insns);
!   sbitmap_vector_zero (reaching_defs, n_blocks);
  
!   rd_out = (sbitmap *) sbitmap_vector_alloc (n_blocks, n_insns);
!   sbitmap_vector_zero (rd_out, n_blocks);
  }
  
  /* Free reaching def variables.  */
  
  static void
! free_rd_mem ()
  {
!   sbitmap_vector_free (rd_kill);
!   sbitmap_vector_free (rd_gen);
!   sbitmap_vector_free (reaching_defs);
!   sbitmap_vector_free (rd_out);
  }
  
  /* Add INSN to the kills of BB.  REGNO, set in BB, is killed by INSN.  */
  
  static void
! handle_rd_kill_set (insn, regno, bb)
       rtx insn;
       int regno;
       basic_block bb;
  {
    struct reg_set *this_reg;
  
!   for (this_reg = reg_set_table[regno]; this_reg; this_reg = this_reg ->next)
      if (BLOCK_NUM (this_reg->insn) != BLOCK_NUM (insn))
!       SET_BIT (rd_kill[bb->index], INSN_CUID (this_reg->insn));
  }
  
  /* Compute the set of kill's for reaching definitions.  */
  
  static void
! compute_kill_rd ()
  {
    int cuid;
    unsigned int regno;
--- 3053,3108 ----
  /* Allocate reaching def variables.  */
  
  static void
! alloc_rd_mem (n_blocks, n_insns, rd)
       int n_blocks, n_insns;
+      struct rd *rd;
  {
!   rd->kill = (sbitmap *) sbitmap_vector_alloc (n_blocks, n_insns);
!   sbitmap_vector_zero (rd->kill, n_blocks);
  
!   rd->gen = (sbitmap *) sbitmap_vector_alloc (n_blocks, n_insns);
!   sbitmap_vector_zero (rd->gen, n_blocks);
  
!   rd->reaching_defs = (sbitmap *) sbitmap_vector_alloc (n_blocks, n_insns);
!   sbitmap_vector_zero (rd->reaching_defs, n_blocks);
  
!   rd->out = (sbitmap *) sbitmap_vector_alloc (n_blocks, n_insns);
!   sbitmap_vector_zero (rd->out, n_blocks);
  }
  
  /* Free reaching def variables.  */
  
  static void
! free_rd_mem (rd)
!      struct rd *rd;
  {
!   sbitmap_vector_free (rd->kill);
!   sbitmap_vector_free (rd->gen);
!   sbitmap_vector_free (rd->reaching_defs);
!   sbitmap_vector_free (rd->out);
  }
  
  /* Add INSN to the kills of BB.  REGNO, set in BB, is killed by INSN.  */
  
  static void
! handle_rd_kill_set (insn, regno, bb, rd)
       rtx insn;
       int regno;
       basic_block bb;
+      struct rd *rd;
  {
    struct reg_set *this_reg;
  
!   for (this_reg = reg_set_table.table[regno]; this_reg; this_reg = this_reg ->next)
      if (BLOCK_NUM (this_reg->insn) != BLOCK_NUM (insn))
!       SET_BIT (rd->kill[bb->index], INSN_CUID (this_reg->insn));
  }
  
  /* Compute the set of kill's for reaching definitions.  */
  
  static void
! compute_kill_rd (rd)
!      struct rd *rd;
  {
    int cuid;
    unsigned int regno;
*************** compute_kill_rd ()
*** 2954,2960 ****
  	   Set the bit in `kill' corresponding to that insn.  */
    FOR_EACH_BB (bb)
      for (cuid = 0; cuid < max_cuid; cuid++)
!       if (TEST_BIT (rd_gen[bb->index], cuid))
  	{
  	  rtx insn = CUID_INSN (cuid);
  	  rtx pat = PATTERN (insn);
--- 3119,3125 ----
  	   Set the bit in `kill' corresponding to that insn.  */
    FOR_EACH_BB (bb)
      for (cuid = 0; cuid < max_cuid; cuid++)
!       if (TEST_BIT (rd->gen[bb->index], cuid))
  	{
  	  rtx insn = CUID_INSN (cuid);
  	  rtx pat = PATTERN (insn);
*************** compute_kill_rd ()
*** 2963,2969 ****
  	    {
  	      for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
  		if (TEST_HARD_REG_BIT (regs_invalidated_by_call, regno))
! 		  handle_rd_kill_set (insn, regno, bb);
  	    }
  
  	  if (GET_CODE (pat) == PARALLEL)
--- 3128,3134 ----
  	    {
  	      for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
  		if (TEST_HARD_REG_BIT (regs_invalidated_by_call, regno))
! 		  handle_rd_kill_set (insn, regno, bb, rd);
  	    }
  
  	  if (GET_CODE (pat) == PARALLEL)
*************** compute_kill_rd ()
*** 2976,2988 ****
  		      && GET_CODE (XEXP (XVECEXP (pat, 0, i), 0)) == REG)
  		    handle_rd_kill_set (insn,
  					REGNO (XEXP (XVECEXP (pat, 0, i), 0)),
! 					bb);
  		}
  	    }
  	  else if (GET_CODE (pat) == SET && GET_CODE (SET_DEST (pat)) == REG)
  	    /* Each setting of this register outside of this block
  	       must be marked in the set of kills in this block.  */
! 	    handle_rd_kill_set (insn, REGNO (SET_DEST (pat)), bb);
  	}
  }
  
--- 3141,3153 ----
  		      && GET_CODE (XEXP (XVECEXP (pat, 0, i), 0)) == REG)
  		    handle_rd_kill_set (insn,
  					REGNO (XEXP (XVECEXP (pat, 0, i), 0)),
! 					bb, rd);
  		}
  	    }
  	  else if (GET_CODE (pat) == SET && GET_CODE (SET_DEST (pat)) == REG)
  	    /* Each setting of this register outside of this block
  	       must be marked in the set of kills in this block.  */
! 	    handle_rd_kill_set (insn, REGNO (SET_DEST (pat)), bb, rd);
  	}
  }
  
*************** compute_kill_rd ()
*** 2992,3004 ****
     expressions but applied to the gens and kills of reaching definitions.  */
  
  static void
! compute_rd ()
  {
    int changed, passes;
    basic_block bb;
  
    FOR_EACH_BB (bb)
!     sbitmap_copy (rd_out[bb->index] /*dst*/, rd_gen[bb->index] /*src*/);
  
    passes = 0;
    changed = 1;
--- 3157,3170 ----
     expressions but applied to the gens and kills of reaching definitions.  */
  
  static void
! compute_rd (rd)
!      struct rd *rd;
  {
    int changed, passes;
    basic_block bb;
  
    FOR_EACH_BB (bb)
!     sbitmap_copy (rd->out[bb->index] /*dst*/, rd->gen[bb->index] /*src*/);
  
    passes = 0;
    changed = 1;
*************** compute_rd ()
*** 3007,3015 ****
        changed = 0;
        FOR_EACH_BB (bb)
  	{
! 	  sbitmap_union_of_preds (reaching_defs[bb->index], rd_out, bb->index);
! 	  changed |= sbitmap_union_of_diff_cg (rd_out[bb->index], rd_gen[bb->index],
! 					       reaching_defs[bb->index], rd_kill[bb->index]);
  	}
        passes++;
      }
--- 3173,3181 ----
        changed = 0;
        FOR_EACH_BB (bb)
  	{
! 	  sbitmap_union_of_preds (rd->reaching_defs[bb->index], rd->out, bb->index);
! 	  changed |= sbitmap_union_of_diff_cg (rd->out[bb->index], rd->gen[bb->index],
! 					       rd->reaching_defs[bb->index], rd->kill[bb->index]);
  	}
        passes++;
      }
*************** compute_rd ()
*** 3023,3071 ****
  /* Allocate memory for available expression computation.  */
  
  static void
! alloc_avail_expr_mem (n_blocks, n_exprs)
       int n_blocks, n_exprs;
  {
!   ae_kill = (sbitmap *) sbitmap_vector_alloc (n_blocks, n_exprs);
!   sbitmap_vector_zero (ae_kill, n_blocks);
  
!   ae_gen = (sbitmap *) sbitmap_vector_alloc (n_blocks, n_exprs);
!   sbitmap_vector_zero (ae_gen, n_blocks);
  
!   ae_in = (sbitmap *) sbitmap_vector_alloc (n_blocks, n_exprs);
!   sbitmap_vector_zero (ae_in, n_blocks);
  
!   ae_out = (sbitmap *) sbitmap_vector_alloc (n_blocks, n_exprs);
!   sbitmap_vector_zero (ae_out, n_blocks);
  }
  
  static void
! free_avail_expr_mem ()
  {
!   sbitmap_vector_free (ae_kill);
!   sbitmap_vector_free (ae_gen);
!   sbitmap_vector_free (ae_in);
!   sbitmap_vector_free (ae_out);
  }
  
  /* Compute the set of available expressions generated in each basic block.  */
  
  static void
! compute_ae_gen (expr_hash_table)
       struct hash_table *expr_hash_table;
  {
    unsigned int i;
    struct expr *expr;
    struct occr *occr;
  
!   /* For each recorded occurrence of each expression, set ae_gen[bb][expr].
       This is all we have to do because an expression is not recorded if it
       is not available, and the only expressions we want to work with are the
       ones that are recorded.  */
    for (i = 0; i < expr_hash_table->size; i++)
      for (expr = expr_hash_table->table[i]; expr != 0; expr = expr->next_same_hash)
        for (occr = expr->avail_occr; occr != 0; occr = occr->next)
! 	SET_BIT (ae_gen[BLOCK_NUM (occr->insn)], expr->bitmap_index);
  }
  
  /* Return non-zero if expression X is killed in BB.  */
--- 3189,3240 ----
  /* Allocate memory for available expression computation.  */
  
  static void
! alloc_avail_expr_mem (n_blocks, n_exprs, ae)
       int n_blocks, n_exprs;
+      struct ae *ae;
  {
!   ae->kill = (sbitmap *) sbitmap_vector_alloc (n_blocks, n_exprs);
!   sbitmap_vector_zero (ae->kill, n_blocks);
  
!   ae->gen = (sbitmap *) sbitmap_vector_alloc (n_blocks, n_exprs);
!   sbitmap_vector_zero (ae->gen, n_blocks);
  
!   ae->in = (sbitmap *) sbitmap_vector_alloc (n_blocks, n_exprs);
!   sbitmap_vector_zero (ae->in, n_blocks);
  
!   ae->out = (sbitmap *) sbitmap_vector_alloc (n_blocks, n_exprs);
!   sbitmap_vector_zero (ae->out, n_blocks);
  }
  
  static void
! free_avail_expr_mem (ae)
!      struct ae *ae;
  {
!   sbitmap_vector_free (ae->kill);
!   sbitmap_vector_free (ae->gen);
!   sbitmap_vector_free (ae->in);
!   sbitmap_vector_free (ae->out);
  }
  
  /* Compute the set of available expressions generated in each basic block.  */
  
  static void
! compute_ae_gen (ae, expr_hash_table)
!      struct ae *ae;
       struct hash_table *expr_hash_table;
  {
    unsigned int i;
    struct expr *expr;
    struct occr *occr;
  
!   /* For each recorded occurrence of each expression, set ae->gen[bb][expr].
       This is all we have to do because an expression is not recorded if it
       is not available, and the only expressions we want to work with are the
       ones that are recorded.  */
    for (i = 0; i < expr_hash_table->size; i++)
      for (expr = expr_hash_table->table[i]; expr != 0; expr = expr->next_same_hash)
        for (occr = expr->avail_occr; occr != 0; occr = occr->next)
! 	SET_BIT (ae->gen[BLOCK_NUM (occr->insn)], expr->bitmap_index);
  }
  
  /* Return non-zero if expression X is killed in BB.  */
*************** expr_killed_p (x, bb)
*** 3134,3141 ****
  /* Compute the set of available expressions killed in each basic block.  */
  
  static void
! compute_ae_kill (ae_gen, ae_kill, expr_hash_table)
!      sbitmap *ae_gen, *ae_kill;
       struct hash_table *expr_hash_table;
  {
    basic_block bb;
--- 3303,3310 ----
  /* Compute the set of available expressions killed in each basic block.  */
  
  static void
! compute_ae_kill (ae, expr_hash_table)
!      struct ae *ae;
       struct hash_table *expr_hash_table;
  {
    basic_block bb;
*************** compute_ae_kill (ae_gen, ae_kill, expr_h
*** 3147,3157 ****
        for (expr = expr_hash_table->table[i]; expr; expr = expr->next_same_hash)
  	{
  	  /* Skip EXPR if generated in this block.  */
! 	  if (TEST_BIT (ae_gen[bb->index], expr->bitmap_index))
  	    continue;
  
  	  if (expr_killed_p (expr->expr, bb))
! 	    SET_BIT (ae_kill[bb->index], expr->bitmap_index);
  	}
  }
  
--- 3316,3326 ----
        for (expr = expr_hash_table->table[i]; expr; expr = expr->next_same_hash)
  	{
  	  /* Skip EXPR if generated in this block.  */
! 	  if (TEST_BIT (ae->gen[bb->index], expr->bitmap_index))
  	    continue;
  
  	  if (expr_killed_p (expr->expr, bb))
! 	    SET_BIT (ae->kill[bb->index], expr->bitmap_index);
  	}
  }
  
*************** compute_ae_kill (ae_gen, ae_kill, expr_h
*** 3174,3185 ****
     the closest such expression.  */
  
  static int
! expr_reaches_here_p_work (occr, expr, bb, check_self_loop, visited)
       struct occr *occr;
       struct expr *expr;
       basic_block bb;
       int check_self_loop;
       char *visited;
  {
    edge pred;
  
--- 3343,3355 ----
     the closest such expression.  */
  
  static int
! expr_reaches_here_p_work (occr, expr, bb, check_self_loop, visited, ae)
       struct occr *occr;
       struct expr *expr;
       basic_block bb;
       int check_self_loop;
       char *visited;
+      struct ae *ae;
  {
    edge pred;
  
*************** expr_reaches_here_p_work (occr, expr, bb
*** 3194,3200 ****
  	{
  	  /* BB loops on itself.  */
  	  if (check_self_loop
! 	      && TEST_BIT (ae_gen[pred_bb->index], expr->bitmap_index)
  	      && BLOCK_NUM (occr->insn) == pred_bb->index)
  	    return 1;
  
--- 3364,3370 ----
  	{
  	  /* BB loops on itself.  */
  	  if (check_self_loop
! 	      && TEST_BIT (ae->gen[pred_bb->index], expr->bitmap_index)
  	      && BLOCK_NUM (occr->insn) == pred_bb->index)
  	    return 1;
  
*************** expr_reaches_here_p_work (occr, expr, bb
*** 3202,3212 ****
  	}
  
        /* Ignore this predecessor if it kills the expression.  */
!       else if (TEST_BIT (ae_kill[pred_bb->index], expr->bitmap_index))
  	visited[pred_bb->index] = 1;
  
        /* Does this predecessor generate this expression?  */
!       else if (TEST_BIT (ae_gen[pred_bb->index], expr->bitmap_index))
  	{
  	  /* Is this the occurrence we're looking for?
  	     Note that there's only one generating occurrence per block
--- 3372,3382 ----
  	}
  
        /* Ignore this predecessor if it kills the expression.  */
!       else if (TEST_BIT (ae->kill[pred_bb->index], expr->bitmap_index))
  	visited[pred_bb->index] = 1;
  
        /* Does this predecessor generate this expression?  */
!       else if (TEST_BIT (ae->gen[pred_bb->index], expr->bitmap_index))
  	{
  	  /* Is this the occurrence we're looking for?
  	     Note that there's only one generating occurrence per block
*************** expr_reaches_here_p_work (occr, expr, bb
*** 3222,3228 ****
  	{
  	  visited[pred_bb->index] = 1;
  	  if (expr_reaches_here_p_work (occr, expr, pred_bb, check_self_loop,
! 	      visited))
  
  	    return 1;
  	}
--- 3392,3398 ----
  	{
  	  visited[pred_bb->index] = 1;
  	  if (expr_reaches_here_p_work (occr, expr, pred_bb, check_self_loop,
! 	      visited, ae))
  
  	    return 1;
  	}
*************** expr_reaches_here_p_work (occr, expr, bb
*** 3236,3251 ****
     memory allocated for that function is returned.  */
  
  static int
! expr_reaches_here_p (occr, expr, bb, check_self_loop)
       struct occr *occr;
       struct expr *expr;
       basic_block bb;
       int check_self_loop;
  {
    int rval;
    char *visited = (char *) xcalloc (last_basic_block, 1);
  
!   rval = expr_reaches_here_p_work (occr, expr, bb, check_self_loop, visited);
  
    free (visited);
    return rval;
--- 3406,3422 ----
     memory allocated for that function is returned.  */
  
  static int
! expr_reaches_here_p (occr, expr, bb, check_self_loop, ae)
       struct occr *occr;
       struct expr *expr;
       basic_block bb;
       int check_self_loop;
+      struct ae *ae;
  {
    int rval;
    char *visited = (char *) xcalloc (last_basic_block, 1);
  
!   rval = expr_reaches_here_p_work (occr, expr, bb, check_self_loop, visited, ae);
  
    free (visited);
    return rval;
*************** expr_reaches_here_p (occr, expr, bb, che
*** 3257,3265 ****
     Called only by handle_avail_expr.  */
  
  static rtx
! computing_insn (expr, insn)
       struct expr *expr;
       rtx insn;
  {
    basic_block bb = BLOCK_FOR_INSN (insn);
  
--- 3428,3437 ----
     Called only by handle_avail_expr.  */
  
  static rtx
! computing_insn (expr, insn, ae)
       struct expr *expr;
       rtx insn;
+      struct ae *ae;
  {
    basic_block bb = BLOCK_FOR_INSN (insn);
  
*************** computing_insn (expr, insn)
*** 3292,3298 ****
  		 is generated later in the block [and thus there's a loop].
  		 We let the normal cse pass handle the other cases.  */
  	      if (INSN_CUID (insn) < INSN_CUID (occr->insn)
! 		  && expr_reaches_here_p (occr, expr, bb, 1))
  		{
  		  can_reach++;
  		  if (can_reach > 1)
--- 3464,3470 ----
  		 is generated later in the block [and thus there's a loop].
  		 We let the normal cse pass handle the other cases.  */
  	      if (INSN_CUID (insn) < INSN_CUID (occr->insn)
! 		  && expr_reaches_here_p (occr, expr, bb, 1, ae))
  		{
  		  can_reach++;
  		  if (can_reach > 1)
*************** computing_insn (expr, insn)
*** 3301,3307 ****
  		  insn_computes_expr = occr->insn;
  		}
  	    }
! 	  else if (expr_reaches_here_p (occr, expr, bb, 0))
  	    {
  	      can_reach++;
  	      if (can_reach > 1)
--- 3473,3479 ----
  		  insn_computes_expr = occr->insn;
  		}
  	    }
! 	  else if (expr_reaches_here_p (occr, expr, bb, 0, ae))
  	    {
  	      can_reach++;
  	      if (can_reach > 1)
*************** computing_insn (expr, insn)
*** 3322,3333 ****
     Only called by can_disregard_other_sets.  */
  
  static int
! def_reaches_here_p (insn, def_insn)
       rtx insn, def_insn;
  {
    rtx reg;
  
!   if (TEST_BIT (reaching_defs[BLOCK_NUM (insn)], INSN_CUID (def_insn)))
      return 1;
  
    if (BLOCK_NUM (insn) == BLOCK_NUM (def_insn))
--- 3494,3506 ----
     Only called by can_disregard_other_sets.  */
  
  static int
! def_reaches_here_p (insn, def_insn, rd)
       rtx insn, def_insn;
+      struct rd *rd;
  {
    rtx reg;
  
!   if (TEST_BIT (rd->reaching_defs[BLOCK_NUM (insn)], INSN_CUID (def_insn)))
      return 1;
  
    if (BLOCK_NUM (insn) == BLOCK_NUM (def_insn))
*************** def_reaches_here_p (insn, def_insn)
*** 3359,3374 ****
     always safe to return zero.  */
  
  static int
! can_disregard_other_sets (addr_this_reg, insn, for_combine)
       struct reg_set **addr_this_reg;
       rtx insn;
       int for_combine;
  {
    int number_of_reaching_defs = 0;
    struct reg_set *this_reg;
  
    for (this_reg = *addr_this_reg; this_reg != 0; this_reg = this_reg->next)
!     if (def_reaches_here_p (insn, this_reg->insn))
        {
  	number_of_reaching_defs++;
  	/* Ignore parallels for now.  */
--- 3532,3548 ----
     always safe to return zero.  */
  
  static int
! can_disregard_other_sets (addr_this_reg, insn, for_combine, rd)
       struct reg_set **addr_this_reg;
       rtx insn;
       int for_combine;
+      struct rd *rd;
  {
    int number_of_reaching_defs = 0;
    struct reg_set *this_reg;
  
    for (this_reg = *addr_this_reg; this_reg != 0; this_reg = this_reg->next)
!     if (def_reaches_here_p (insn, this_reg->insn, rd))
        {
  	number_of_reaching_defs++;
  	/* Ignore parallels for now.  */
*************** can_disregard_other_sets (addr_this_reg,
*** 3407,3415 ****
     The result is non-zero if any changes were made.  */
  
  static int
! handle_avail_expr (insn, expr)
       rtx insn;
       struct expr *expr;
  {
    rtx pat, insn_computes_expr, expr_set;
    rtx to;
--- 3581,3591 ----
     The result is non-zero if any changes were made.  */
  
  static int
! handle_avail_expr (insn, expr, ae, rd)
       rtx insn;
       struct expr *expr;
+      struct ae *ae;
+      struct rd *rd;
  {
    rtx pat, insn_computes_expr, expr_set;
    rtx to;
*************** handle_avail_expr (insn, expr)
*** 3419,3425 ****
  
    /* We only handle the case where one computation of the expression
       reaches this instruction.  */
!   insn_computes_expr = computing_insn (expr, insn);
    if (insn_computes_expr == NULL)
      return 0;
    expr_set = single_set (insn_computes_expr);
--- 3595,3601 ----
  
    /* We only handle the case where one computation of the expression
       reaches this instruction.  */
!   insn_computes_expr = computing_insn (expr, insn, ae);
    if (insn_computes_expr == NULL)
      return 0;
    expr_set = single_set (insn_computes_expr);
*************** handle_avail_expr (insn, expr)
*** 3444,3452 ****
        if (regnum_for_replacing >= max_gcse_regno
  	  /* If the register the expression is computed into is set only once,
  	     or only one set reaches this insn, we can use it.  */
! 	  || (((this_reg = reg_set_table[regnum_for_replacing]),
  	       this_reg->next == NULL)
! 	      || can_disregard_other_sets (&this_reg, insn, 0)))
  	{
  	  use_src = 1;
  	  found_setting = 1;
--- 3620,3628 ----
        if (regnum_for_replacing >= max_gcse_regno
  	  /* If the register the expression is computed into is set only once,
  	     or only one set reaches this insn, we can use it.  */
! 	  || (((this_reg = reg_set_table.table[regnum_for_replacing]),
  	       this_reg->next == NULL)
! 	      || can_disregard_other_sets (&this_reg, insn, 0, rd)))
  	{
  	  use_src = 1;
  	  found_setting = 1;
*************** handle_avail_expr (insn, expr)
*** 3462,3473 ****
        if (regnum_for_replacing >= max_gcse_regno)
  	abort ();
  
!       this_reg = reg_set_table[regnum_for_replacing];
  
        /* If the register the expression is computed into is set only once,
  	 or only one set reaches this insn, use it.  */
        if (this_reg->next == NULL
! 	  || can_disregard_other_sets (&this_reg, insn, 0))
  	found_setting = 1;
      }
  
--- 3638,3649 ----
        if (regnum_for_replacing >= max_gcse_regno)
  	abort ();
  
!       this_reg = reg_set_table.table[regnum_for_replacing];
  
        /* If the register the expression is computed into is set only once,
  	 or only one set reaches this insn, use it.  */
        if (this_reg->next == NULL
! 	  || can_disregard_other_sets (&this_reg, insn, 0, rd))
  	found_setting = 1;
      }
  
*************** handle_avail_expr (insn, expr)
*** 3565,3571 ****
     The result is non-zero if a change was made.  */
  
  static int
! classic_gcse ()
  {
    int changed;
    rtx insn;
--- 3741,3748 ----
     The result is non-zero if a change was made.  */
  
  static int
! classic_gcse (classic_data)
!      struct classic_global *classic_data;
  {
    int changed;
    rtx insn;
*************** classic_gcse ()
*** 3599,3612 ****
  
  	      if (want_to_gcse_p (src)
  		  /* Is the expression recorded?  */
! 		  && ((expr = lookup_expr (src, &expr_hash_table)) != NULL)
  		  /* Is the expression available [at the start of the
  		     block]?  */
! 		  && TEST_BIT (ae_in[bb->index], expr->bitmap_index)
  		  /* Are the operands unchanged since the start of the
  		     block?  */
  		  && oprs_not_set_p (src, insn))
! 		changed |= handle_avail_expr (insn, expr);
  	    }
  
  	  /* Keep track of everything modified by this insn.  */
--- 3776,3790 ----
  
  	      if (want_to_gcse_p (src)
  		  /* Is the expression recorded?  */
! 		  && ((expr = lookup_expr (src, &classic_data->expr_hash_table)) != NULL)
  		  /* Is the expression available [at the start of the
  		     block]?  */
! 		  && TEST_BIT (classic_data->ae.in[bb->index], expr->bitmap_index)
  		  /* Are the operands unchanged since the start of the
  		     block?  */
  		  && oprs_not_set_p (src, insn))
! 		changed |= handle_avail_expr (insn, expr,
! 				&classic_data->ae, &classic_data->rd);
  	    }
  
  	  /* Keep track of everything modified by this insn.  */
*************** one_classic_gcse_pass (pass)
*** 3628,3657 ****
       int pass;
  {
    int changed = 0;
  
    gcse_subst_count = 0;
    gcse_create_count = 0;
  
!   alloc_hash_table (max_cuid, &expr_hash_table, 0);
!   alloc_rd_mem (last_basic_block, max_cuid);
!   compute_hash_table (&expr_hash_table);
    if (gcse_file)
!     dump_hash_table (gcse_file, "Expression", &expr_hash_table);
  
!   if (expr_hash_table.n_elems > 0)
      {
!       compute_kill_rd ();
!       compute_rd ();
!       alloc_avail_expr_mem (last_basic_block, expr_hash_table.n_elems);
!       compute_ae_gen (&expr_hash_table);
!       compute_ae_kill (ae_gen, ae_kill, &expr_hash_table);
!       compute_available (ae_gen, ae_kill, ae_out, ae_in);
!       changed = classic_gcse ();
!       free_avail_expr_mem ();
      }
  
!   free_rd_mem ();
!   free_hash_table (&expr_hash_table);
  
    if (gcse_file)
      {
--- 3806,3836 ----
       int pass;
  {
    int changed = 0;
+   struct classic_global classic_data;
  
    gcse_subst_count = 0;
    gcse_create_count = 0;
  
!   alloc_hash_table (max_cuid, &classic_data.expr_hash_table, 0);
!   alloc_rd_mem (last_basic_block, max_cuid, &classic_data.rd);
!   compute_hash_table (&classic_data.expr_hash_table);
    if (gcse_file)
!     dump_hash_table (gcse_file, "Expression", &classic_data.expr_hash_table);
  
!   if (classic_data.expr_hash_table.n_elems > 0)
      {
!       compute_kill_rd (&classic_data.rd);
!       compute_rd (&classic_data.rd);
!       alloc_avail_expr_mem (last_basic_block, classic_data.expr_hash_table.n_elems, &classic_data.ae);
!       compute_ae_gen (&classic_data.ae, &classic_data.expr_hash_table);
!       compute_ae_kill (&classic_data.ae, &classic_data.expr_hash_table);
!       compute_available (classic_data.ae.gen, classic_data.ae.kill, classic_data.ae.out, classic_data.ae.in);
!       changed = classic_gcse (&classic_data);
!       free_avail_expr_mem (&classic_data.ae);
      }
  
!   free_rd_mem (&classic_data.rd);
!   free_hash_table (&classic_data.expr_hash_table);
  
    if (gcse_file)
      {
*************** one_classic_gcse_pass (pass)
*** 3664,3702 ****
    return changed;
  }
  
- /* Compute copy/constant propagation working variables.  */
- 
- /* Local properties of assignments.  */
- static sbitmap *cprop_pavloc;
- static sbitmap *cprop_absaltered;
- 
- /* Global properties of assignments (computed from the local properties).  */
- static sbitmap *cprop_avin;
- static sbitmap *cprop_avout;
- 
  /* Allocate vars used for copy/const propagation.  N_BLOCKS is the number of
     basic blocks.  N_SETS is the number of sets.  */
  
  static void
! alloc_cprop_mem (n_blocks, n_sets)
!      int n_blocks, n_sets;
  {
!   cprop_pavloc = sbitmap_vector_alloc (n_blocks, n_sets);
!   cprop_absaltered = sbitmap_vector_alloc (n_blocks, n_sets);
  
!   cprop_avin = sbitmap_vector_alloc (n_blocks, n_sets);
!   cprop_avout = sbitmap_vector_alloc (n_blocks, n_sets);
  }
  
  /* Free vars used by copy/const propagation.  */
  
  static void
! free_cprop_mem ()
  {
!   sbitmap_vector_free (cprop_pavloc);
!   sbitmap_vector_free (cprop_absaltered);
!   sbitmap_vector_free (cprop_avin);
!   sbitmap_vector_free (cprop_avout);
  }
  
  /* For each block, compute whether X is transparent.  X is either an
--- 3843,3873 ----
    return changed;
  }
  
  /* Allocate vars used for copy/const propagation.  N_BLOCKS is the number of
     basic blocks.  N_SETS is the number of sets.  */
  
  static void
! alloc_cprop_mem (n_blocks, cprop_data)
!      int n_blocks;
!      struct cprop_global *cprop_data;
  {
!   cprop_data->pavloc = sbitmap_vector_alloc (n_blocks, cprop_data->set_hash_table.n_elems);
!   cprop_data->absaltered = sbitmap_vector_alloc (n_blocks, cprop_data->set_hash_table.n_elems);
  
!   cprop_data->avin = sbitmap_vector_alloc (n_blocks, cprop_data->set_hash_table.n_elems);
!   cprop_data->avout = sbitmap_vector_alloc (n_blocks, cprop_data->set_hash_table.n_elems);
  }
  
  /* Free vars used by copy/const propagation.  */
  
  static void
! free_cprop_mem (cprop_data)
!      struct cprop_global *cprop_data;
  {
!   sbitmap_vector_free (cprop_data->pavloc);
!   sbitmap_vector_free (cprop_data->absaltered);
!   sbitmap_vector_free (cprop_data->avin);
!   sbitmap_vector_free (cprop_data->avout);
  }
  
  /* For each block, compute whether X is transparent.  X is either an
*************** compute_transp (x, indx, bmap, set_p)
*** 3739,3745 ****
  	    }
  	  else
  	    {
! 	      for (r = reg_set_table[REGNO (x)]; r != NULL; r = r->next)
  		SET_BIT (bmap[BLOCK_NUM (r->insn)], indx);
  	    }
  	}
--- 3910,3916 ----
  	    }
  	  else
  	    {
! 	      for (r = reg_set_table.table[REGNO (x)]; r != NULL; r = r->next)
  		SET_BIT (bmap[BLOCK_NUM (r->insn)], indx);
  	    }
  	}
*************** compute_transp (x, indx, bmap, set_p)
*** 3753,3759 ****
  	    }
  	  else
  	    {
! 	      for (r = reg_set_table[REGNO (x)]; r != NULL; r = r->next)
  		RESET_BIT (bmap[BLOCK_NUM (r->insn)], indx);
  	    }
  	}
--- 3924,3930 ----
  	    }
  	  else
  	    {
! 	      for (r = reg_set_table.table[REGNO (x)]; r != NULL; r = r->next)
  		RESET_BIT (bmap[BLOCK_NUM (r->insn)], indx);
  	    }
  	}
*************** compute_transp (x, indx, bmap, set_p)
*** 3841,3865 ****
     propagation.  */
  
  static void
! compute_cprop_data ()
  {
!   compute_local_properties (cprop_absaltered, cprop_pavloc, NULL, &set_hash_table);
!   compute_available (cprop_pavloc, cprop_absaltered,
! 		     cprop_avout, cprop_avin);
  }
  
  /* Copy/constant propagation.  */
  
- /* Maximum number of register uses in an insn that we handle.  */
- #define MAX_USES 8
- 
- /* Table of uses found in an insn.
-    Allocated statically to avoid alloc/free complexity and overhead.  */
- static struct reg_use reg_use_table[MAX_USES];
- 
- /* Index into `reg_use_table' while building it.  */
- static int reg_use_count;
- 
  /* Set up a list of register numbers used in INSN.  The found uses are stored
     in `reg_use_table'.  `reg_use_count' is initialized to zero before entry,
     and contains the number of uses in the table upon exit.
--- 4012,4027 ----
     propagation.  */
  
  static void
! compute_cprop_data (cprop_data)
!      struct cprop_global *cprop_data;
  {
!   compute_local_properties (cprop_data->absaltered, cprop_data->pavloc, NULL, &cprop_data->set_hash_table);
!   compute_available (cprop_data->pavloc, cprop_data->absaltered,
! 		     cprop_data->avout, cprop_data->avin);
  }
  
  /* Copy/constant propagation.  */
  
  /* Set up a list of register numbers used in INSN.  The found uses are stored
     in `reg_use_table'.  `reg_use_count' is initialized to zero before entry,
     and contains the number of uses in the table upon exit.
*************** static int reg_use_count;
*** 3870,3881 ****
  static void
  find_used_regs (xptr, data)
       rtx *xptr;
!      void *data ATTRIBUTE_UNUSED;
  {
    int i, j;
    enum rtx_code code;
    const char *fmt;
    rtx x = *xptr;
  
    /* repeat is used to turn tail-recursion into iteration since GCC
       can't do it when there's no return value.  */
--- 4032,4044 ----
  static void
  find_used_regs (xptr, data)
       rtx *xptr;
!      void *data;
  {
    int i, j;
    enum rtx_code code;
    const char *fmt;
    rtx x = *xptr;
+   struct cprop_global *cprop_data = (struct cprop_global *) data;
  
    /* repeat is used to turn tail-recursion into iteration since GCC
       can't do it when there's no return value.  */
*************** find_used_regs (xptr, data)
*** 3886,3896 ****
    code = GET_CODE (x);
    if (REG_P (x))
      {
!       if (reg_use_count == MAX_USES)
  	return;
  
!       reg_use_table[reg_use_count].reg_rtx = x;
!       reg_use_count++;
      }
  
    /* Recursively scan the operands of this expression.  */
--- 4049,4059 ----
    code = GET_CODE (x);
    if (REG_P (x))
      {
!       if (cprop_data->reg_use_count == MAX_USES)
  	return;
  
!       cprop_data->reg_use_table[cprop_data->reg_use_count].reg_rtx = x;
!       cprop_data->reg_use_count++;
      }
  
    /* Recursively scan the operands of this expression.  */
*************** try_replace_reg (from, to, insn)
*** 3968,3976 ****
     NULL no such set is found.  */
  
  static struct expr *
! find_avail_set (regno, insn)
       int regno;
       rtx insn;
  {
    /* SET1 contains the last set found that can be returned to the caller for
       use in a substitution.  */
--- 4131,4140 ----
     NULL no such set is found.  */
  
  static struct expr *
! find_avail_set (regno, insn, cprop_data)
       int regno;
       rtx insn;
+      struct cprop_global *cprop_data;
  {
    /* SET1 contains the last set found that can be returned to the caller for
       use in a substitution.  */
*************** find_avail_set (regno, insn)
*** 3988,4000 ****
    while (1)
      {
        rtx src;
!       struct expr *set = lookup_set (regno, NULL_RTX, &set_hash_table);
  
        /* Find a set that is available at the start of the block
  	 which contains INSN.  */
        while (set)
  	{
! 	  if (TEST_BIT (cprop_avin[BLOCK_NUM (insn)], set->bitmap_index))
  	    break;
  	  set = next_set (regno, set);
  	}
--- 4152,4164 ----
    while (1)
      {
        rtx src;
!       struct expr *set = lookup_set (regno, NULL_RTX, &cprop_data->set_hash_table);
  
        /* Find a set that is available at the start of the block
  	 which contains INSN.  */
        while (set)
  	{
! 	  if (TEST_BIT (cprop_data->avin[BLOCK_NUM (insn)], set->bitmap_index))
  	    break;
  	  set = next_set (regno, set);
  	}
*************** find_avail_set (regno, insn)
*** 4042,4053 ****
     if a change was made.  */
  
  static int
! cprop_jump (bb, setcc, jump, from, src)
       basic_block bb;
       rtx setcc;
       rtx jump;
       rtx from;
       rtx src;
  {
    rtx new, new_set;
    rtx set = pc_set (jump);
--- 4206,4218 ----
     if a change was made.  */
  
  static int
! cprop_jump (bb, setcc, jump, from, src, run_jump_opt_after_gcse)
       basic_block bb;
       rtx setcc;
       rtx jump;
       rtx from;
       rtx src;
+      int *run_jump_opt_after_gcse;
  {
    rtx new, new_set;
    rtx set = pc_set (jump);
*************** cprop_jump (bb, setcc, jump, from, src)
*** 4092,4098 ****
      delete_insn (setcc);
  #endif
  
!   run_jump_opt_after_gcse = 1;
  
    const_prop_count++;
    if (gcse_file != NULL)
--- 4257,4263 ----
      delete_insn (setcc);
  #endif
  
!   *run_jump_opt_after_gcse = 1;
  
    const_prop_count++;
    if (gcse_file != NULL)
*************** cprop_jump (bb, setcc, jump, from, src)
*** 4109,4119 ****
  }
  
  static bool
! constprop_register (insn, from, to, alter_jumps)
       rtx insn;
       rtx from;
       rtx to;
       int alter_jumps;
  {
    rtx sset;
  
--- 4274,4285 ----
  }
  
  static bool
! constprop_register (insn, from, to, alter_jumps, run_jump_opt_after_gcse)
       rtx insn;
       rtx from;
       rtx to;
       int alter_jumps;
+      int *run_jump_opt_after_gcse;
  {
    rtx sset;
  
*************** constprop_register (insn, from, to, alte
*** 4125,4131 ****
      {
        rtx dest = SET_DEST (sset);
        if ((REG_P (dest) || CC0_P (dest))
! 	  && cprop_jump (BLOCK_FOR_INSN (insn), insn, NEXT_INSN (insn), from, to))
  	return 1;
      }
  
--- 4291,4298 ----
      {
        rtx dest = SET_DEST (sset);
        if ((REG_P (dest) || CC0_P (dest))
! 	  && cprop_jump (BLOCK_FOR_INSN (insn), insn, NEXT_INSN (insn), from, to,
! 			 run_jump_opt_after_gcse))
  	return 1;
      }
  
*************** constprop_register (insn, from, to, alte
*** 4141,4147 ****
       Right now the insn in question must look like
       (set (pc) (if_then_else ...))  */
    else if (alter_jumps && any_condjump_p (insn) && onlyjump_p (insn))
!     return cprop_jump (BLOCK_FOR_INSN (insn), NULL, insn, from, to);
    return 0;
  }
  
--- 4308,4315 ----
       Right now the insn in question must look like
       (set (pc) (if_then_else ...))  */
    else if (alter_jumps && any_condjump_p (insn) && onlyjump_p (insn))
!     return cprop_jump (BLOCK_FOR_INSN (insn), NULL, insn, from, to,
! 		       run_jump_opt_after_gcse);
    return 0;
  }
  
*************** constprop_register (insn, from, to, alte
*** 4149,4157 ****
     The result is non-zero if a change was made.  */
  
  static int
! cprop_insn (insn, alter_jumps)
       rtx insn;
       int alter_jumps;
  {
    struct reg_use *reg_used;
    int changed = 0;
--- 4317,4327 ----
     The result is non-zero if a change was made.  */
  
  static int
! cprop_insn (insn, alter_jumps, cprop_data, run_jump_opt_after_gcse)
       rtx insn;
       int alter_jumps;
+      struct cprop_global *cprop_data;
+      int *run_jump_opt_after_gcse;
  {
    struct reg_use *reg_used;
    int changed = 0;
*************** cprop_insn (insn, alter_jumps)
*** 4160,4176 ****
    if (!INSN_P (insn))
      return 0;
  
!   reg_use_count = 0;
!   note_uses (&PATTERN (insn), find_used_regs, NULL);
  
    note = find_reg_equal_equiv_note (insn);
  
    /* We may win even when propagating constants into notes.  */
    if (note)
!     find_used_regs (&XEXP (note, 0), NULL);
  
!   for (reg_used = &reg_use_table[0]; reg_use_count > 0;
!        reg_used++, reg_use_count--)
      {
        unsigned int regno = REGNO (reg_used->reg_rtx);
        rtx pat, src;
--- 4330,4346 ----
    if (!INSN_P (insn))
      return 0;
  
!   cprop_data->reg_use_count = 0;
!   note_uses (&PATTERN (insn), find_used_regs, cprop_data);
  
    note = find_reg_equal_equiv_note (insn);
  
    /* We may win even when propagating constants into notes.  */
    if (note)
!     find_used_regs (&XEXP (note, 0), cprop_data);
  
!   for (reg_used = &cprop_data->reg_use_table[0]; cprop_data->reg_use_count > 0;
!        reg_used++, cprop_data->reg_use_count--)
      {
        unsigned int regno = REGNO (reg_used->reg_rtx);
        rtx pat, src;
*************** cprop_insn (insn, alter_jumps)
*** 4188,4194 ****
  
        /* Find an assignment that sets reg_used and is available
  	 at the start of the block.  */
!       set = find_avail_set (regno, insn);
        if (! set)
  	continue;
  
--- 4358,4364 ----
  
        /* Find an assignment that sets reg_used and is available
  	 at the start of the block.  */
!       set = find_avail_set (regno, insn, cprop_data);
        if (! set)
  	continue;
  
*************** cprop_insn (insn, alter_jumps)
*** 4202,4208 ****
        /* Constant propagation.  */
        if (CONSTANT_P (src))
  	{
!           if (constprop_register (insn, reg_used->reg_rtx, src, alter_jumps))
  	    {
  	      changed = 1;
  	      const_prop_count++;
--- 4372,4378 ----
        /* Constant propagation.  */
        if (CONSTANT_P (src))
  	{
!           if (constprop_register (insn, reg_used->reg_rtx, src, alter_jumps, run_jump_opt_after_gcse))
  	    {
  	      changed = 1;
  	      const_prop_count++;
*************** cprop_insn (insn, alter_jumps)
*** 4245,4254 ****
  /* LIBCALL_SP is a zero-terminated array of insns at the end of a libcall;
     their REG_EQUAL notes need updating.  */
  static bool
! do_local_cprop (x, insn, alter_jumps, libcall_sp)
       rtx x;
       rtx insn;
       int alter_jumps;
       rtx *libcall_sp;
  {
    rtx newreg = NULL, newcnst = NULL;
--- 4415,4425 ----
  /* LIBCALL_SP is a zero-terminated array of insns at the end of a libcall;
     their REG_EQUAL notes need updating.  */
  static bool
! do_local_cprop (x, insn, alter_jumps, run_jump_opt_after_gcse, libcall_sp)
       rtx x;
       rtx insn;
       int alter_jumps;
+      int *run_jump_opt_after_gcse;
       rtx *libcall_sp;
  {
    rtx newreg = NULL, newcnst = NULL;
*************** do_local_cprop (x, insn, alter_jumps, li
*** 4280,4286 ****
  		  || GET_CODE (XEXP (note, 0)) != MEM))
  	    newreg = this_rtx;
  	}
!       if (newcnst && constprop_register (insn, x, newcnst, alter_jumps))
  	{
  	  /* If we find a case where we can't fix the retval REG_EQUAL notes
  	     match the new register, we either have to abandom this replacement
--- 4451,4457 ----
  		  || GET_CODE (XEXP (note, 0)) != MEM))
  	    newreg = this_rtx;
  	}
!       if (newcnst && constprop_register (insn, x, newcnst, alter_jumps, run_jump_opt_after_gcse))
  	{
  	  /* If we find a case where we can't fix the retval REG_EQUAL notes
  	     match the new register, we either have to abandom this replacement
*************** adjust_libcall_notes (oldreg, newval, in
*** 4360,4367 ****
  #define MAX_NESTED_LIBCALLS 9
  
  static void
! local_cprop_pass (alter_jumps)
       int alter_jumps;
  {
    rtx insn;
    struct reg_use *reg_used;
--- 4531,4540 ----
  #define MAX_NESTED_LIBCALLS 9
  
  static void
! local_cprop_pass (alter_jumps, run_jump_opt_after_gcse, cprop_data)
       int alter_jumps;
+      int *run_jump_opt_after_gcse;
+      struct cprop_global *cprop_data;
  {
    rtx insn;
    struct reg_use *reg_used;
*************** local_cprop_pass (alter_jumps)
*** 4388,4405 ****
  	  note = find_reg_equal_equiv_note (insn);
  	  do
  	    {
! 	      reg_use_count = 0;
! 	      note_uses (&PATTERN (insn), find_used_regs, NULL);
  	      if (note)
! 		find_used_regs (&XEXP (note, 0), NULL);
  
! 	      for (reg_used = &reg_use_table[0]; reg_use_count > 0;
! 		   reg_used++, reg_use_count--)
  		if (do_local_cprop (reg_used->reg_rtx, insn, alter_jumps,
! 		    libcall_sp))
  		  break;
  	    }
! 	  while (reg_use_count);
  	}
        cselib_process_insn (insn);
      }
--- 4561,4578 ----
  	  note = find_reg_equal_equiv_note (insn);
  	  do
  	    {
! 	      cprop_data->reg_use_count = 0;
! 	      note_uses (&PATTERN (insn), find_used_regs, cprop_data);
  	      if (note)
! 		find_used_regs (&XEXP (note, 0), cprop_data);
  
! 	      for (reg_used = &cprop_data->reg_use_table[0]; cprop_data->reg_use_count > 0;
! 		   reg_used++, cprop_data->reg_use_count--)
  		if (do_local_cprop (reg_used->reg_rtx, insn, alter_jumps,
! 			run_jump_opt_after_gcse, libcall_sp))
  		  break;
  	    }
! 	  while (cprop_data->reg_use_count);
  	}
        cselib_process_insn (insn);
      }
*************** local_cprop_pass (alter_jumps)
*** 4410,4417 ****
     non-zero if a change was made.  */
  
  static int
! cprop (alter_jumps)
       int alter_jumps;
  {
    int changed;
    basic_block bb;
--- 4583,4592 ----
     non-zero if a change was made.  */
  
  static int
! cprop (alter_jumps, cprop_data, run_jump_opt_after_gcse)
       int alter_jumps;
+      struct cprop_global *cprop_data;
+      int *run_jump_opt_after_gcse;
  {
    int changed;
    basic_block bb;
*************** cprop (alter_jumps)
*** 4437,4443 ****
  	   insn = NEXT_INSN (insn))
  	if (INSN_P (insn))
  	  {
! 	    changed |= cprop_insn (insn, alter_jumps);
  
  	    /* Keep track of everything modified by this insn.  */
  	    /* ??? Need to be careful w.r.t. mods done to INSN.  Don't
--- 4612,4618 ----
  	   insn = NEXT_INSN (insn))
  	if (INSN_P (insn))
  	  {
! 	    changed |= cprop_insn (insn, alter_jumps, cprop_data, run_jump_opt_after_gcse);
  
  	    /* Keep track of everything modified by this insn.  */
  	    /* ??? Need to be careful w.r.t. mods done to INSN.  Don't
*************** cprop (alter_jumps)
*** 4458,4489 ****
     PASS is the pass count.  */
  
  static int
! one_cprop_pass (pass, alter_jumps)
       int pass;
       int alter_jumps;
  {
    int changed = 0;
  
    const_prop_count = 0;
    copy_prop_count = 0;
  
!   local_cprop_pass (alter_jumps);
  
!   alloc_hash_table (max_cuid, &set_hash_table, 1);
!   compute_hash_table (&set_hash_table);
    if (gcse_file)
!     dump_hash_table (gcse_file, "SET", &set_hash_table);
!   if (set_hash_table.n_elems > 0)
      {
!       alloc_cprop_mem (last_basic_block, set_hash_table.n_elems);
!       compute_cprop_data ();
!       changed = cprop (alter_jumps);
        if (alter_jumps)
! 	changed |= bypass_conditional_jumps ();
!       free_cprop_mem ();
      }
  
!   free_hash_table (&set_hash_table);
  
    if (gcse_file)
      {
--- 4633,4666 ----
     PASS is the pass count.  */
  
  static int
! one_cprop_pass (pass, alter_jumps, run_jump_opt_after_gcse)
       int pass;
       int alter_jumps;
+      int *run_jump_opt_after_gcse;
  {
    int changed = 0;
+   struct cprop_global cprop_data;
  
    const_prop_count = 0;
    copy_prop_count = 0;
  
!   local_cprop_pass (alter_jumps, run_jump_opt_after_gcse, &cprop_data);
  
!   alloc_hash_table (max_cuid, &cprop_data.set_hash_table, 1);
!   compute_hash_table (&cprop_data.set_hash_table);
    if (gcse_file)
!     dump_hash_table (gcse_file, "SET", &cprop_data.set_hash_table);
!   if (cprop_data.set_hash_table.n_elems > 0)
      {
!       alloc_cprop_mem (last_basic_block, &cprop_data);
!       compute_cprop_data (&cprop_data);
!       changed = cprop (alter_jumps, &cprop_data, run_jump_opt_after_gcse);
        if (alter_jumps)
! 	changed |= bypass_conditional_jumps (&cprop_data);
!       free_cprop_mem (&cprop_data);
      }
  
!   free_hash_table (&cprop_data.set_hash_table);
  
    if (gcse_file)
      {
*************** one_cprop_pass (pass, alter_jumps)
*** 4503,4522 ****
     find_avail_set.  */
  
  static struct expr *
! find_bypass_set (regno, bb)
       int regno;
       int bb;
  {
    struct expr *result = 0;
  
    for (;;)
      {
        rtx src;
!       struct expr *set = lookup_set (regno, NULL_RTX, &set_hash_table);
  
        while (set)
  	{
! 	  if (TEST_BIT (cprop_avout[bb], set->bitmap_index))
  	    break;
  	  set = next_set (regno, set);
  	}
--- 4680,4700 ----
     find_avail_set.  */
  
  static struct expr *
! find_bypass_set (regno, bb, cprop_data)
       int regno;
       int bb;
+      struct cprop_global *cprop_data;
  {
    struct expr *result = 0;
  
    for (;;)
      {
        rtx src;
!       struct expr *set = lookup_set (regno, NULL_RTX, &cprop_data->set_hash_table);
  
        while (set)
  	{
! 	  if (TEST_BIT (cprop_data->avout[bb], set->bitmap_index))
  	    break;
  	  set = next_set (regno, set);
  	}
*************** find_bypass_set (regno, bb)
*** 4547,4555 ****
     Returns nonzero if a change was made.  */
  
  static int
! bypass_block (bb, setcc, jump)
       basic_block bb;
       rtx setcc, jump;
  {
    rtx insn, note;
    edge e, enext;
--- 4725,4734 ----
     Returns nonzero if a change was made.  */
  
  static int
! bypass_block (bb, setcc, jump, cprop_data)
       basic_block bb;
       rtx setcc, jump;
+      struct cprop_global *cprop_data;
  {
    rtx insn, note;
    edge e, enext;
*************** bypass_block (bb, setcc, jump)
*** 4558,4576 ****
    insn = (setcc != NULL) ? setcc : jump;
  
    /* Determine set of register uses in INSN.  */
!   reg_use_count = 0;
!   note_uses (&PATTERN (insn), find_used_regs, NULL);
    note = find_reg_equal_equiv_note (insn);
    if (note)
!     find_used_regs (&XEXP (note, 0), NULL);
  
    change = 0;
    for (e = bb->pred; e; e = enext)
      {
        enext = e->pred_next;
!       for (i = 0; i < reg_use_count; i++)
  	{
! 	  struct reg_use *reg_used = &reg_use_table[i];
  	  unsigned int regno = REGNO (reg_used->reg_rtx);
  	  basic_block dest, old_dest;
  	  struct expr *set;
--- 4737,4755 ----
    insn = (setcc != NULL) ? setcc : jump;
  
    /* Determine set of register uses in INSN.  */
!   cprop_data->reg_use_count = 0;
!   note_uses (&PATTERN (insn), find_used_regs, cprop_data);
    note = find_reg_equal_equiv_note (insn);
    if (note)
!     find_used_regs (&XEXP (note, 0), cprop_data);
  
    change = 0;
    for (e = bb->pred; e; e = enext)
      {
        enext = e->pred_next;
!       for (i = 0; i < cprop_data->reg_use_count; i++)
  	{
! 	  struct reg_use *reg_used = &cprop_data->reg_use_table[i];
  	  unsigned int regno = REGNO (reg_used->reg_rtx);
  	  basic_block dest, old_dest;
  	  struct expr *set;
*************** bypass_block (bb, setcc, jump)
*** 4579,4585 ****
  	  if (regno >= max_gcse_regno)
  	    continue;
  
! 	  set = find_bypass_set (regno, e->src->index);
  
  	  if (! set)
  	    continue;
--- 4758,4764 ----
  	  if (regno >= max_gcse_regno)
  	    continue;
  
!           set = find_bypass_set (regno, e->src->index, cprop_data);
  
  	  if (! set)
  	    continue;
*************** bypass_block (bb, setcc, jump)
*** 4638,4644 ****
     appropriate target.  Returns nonzero if a change was made.  */
  
  static int
! bypass_conditional_jumps ()
  {
    basic_block bb;
    int changed;
--- 4817,4824 ----
     appropriate target.  Returns nonzero if a change was made.  */
  
  static int
! bypass_conditional_jumps (cprop_data)
!      struct cprop_global *cprop_data;
  {
    basic_block bb;
    int changed;
*************** bypass_conditional_jumps ()
*** 4677,4683 ****
  	    else if (GET_CODE (insn) == JUMP_INSN)
  	      {
  		if (any_condjump_p (insn) && onlyjump_p (insn))
! 		  changed |= bypass_block (bb, setcc, insn);
  		break;
  	      }
  	    else if (INSN_P (insn))
--- 4857,4863 ----
  	    else if (GET_CODE (insn) == JUMP_INSN)
  	      {
  		if (any_condjump_p (insn) && onlyjump_p (insn))
! 		  changed |= bypass_block (bb, setcc, insn, cprop_data);
  		break;
  	      }
  	    else if (INSN_P (insn))
*************** bypass_conditional_jumps ()
*** 4695,4807 ****
  
  /* Compute PRE+LCM working variables.  */
  
- /* Local properties of expressions.  */
- /* Nonzero for expressions that are transparent in the block.  */
- static sbitmap *transp;
- 
- /* Nonzero for expressions that are transparent at the end of the block.
-    This is only zero for expressions killed by abnormal critical edge
-    created by a calls.  */
- static sbitmap *transpout;
- 
- /* Nonzero for expressions that are computed (available) in the block.  */
- static sbitmap *comp;
- 
- /* Nonzero for expressions that are locally anticipatable in the block.  */
- static sbitmap *antloc;
- 
- /* Nonzero for expressions where this block is an optimal computation
-    point.  */
- static sbitmap *pre_optimal;
- 
- /* Nonzero for expressions which are redundant in a particular block.  */
- static sbitmap *pre_redundant;
- 
- /* Nonzero for expressions which should be inserted on a specific edge.  */
- static sbitmap *pre_insert_map;
- 
- /* Nonzero for expressions which should be deleted in a specific block.  */
- static sbitmap *pre_delete_map;
- 
- /* Contains the edge_list returned by pre_edge_lcm.  */
- static struct edge_list *edge_list;
- 
- /* Redundant insns.  */
- static sbitmap pre_redundant_insns;
- 
  /* Allocate vars used for PRE analysis.  */
  
  static void
! alloc_pre_mem (n_blocks, n_exprs)
!      int n_blocks, n_exprs;
! {
!   transp = sbitmap_vector_alloc (n_blocks, n_exprs);
!   comp = sbitmap_vector_alloc (n_blocks, n_exprs);
!   antloc = sbitmap_vector_alloc (n_blocks, n_exprs);
! 
!   pre_optimal = NULL;
!   pre_redundant = NULL;
!   pre_insert_map = NULL;
!   pre_delete_map = NULL;
!   ae_in = NULL;
!   ae_out = NULL;
!   ae_kill = sbitmap_vector_alloc (n_blocks, n_exprs);
  
!   /* pre_insert and pre_delete are allocated later.  */
  }
  
  /* Free vars used for PRE analysis.  */
  
  static void
! free_pre_mem ()
  {
!   sbitmap_vector_free (transp);
!   sbitmap_vector_free (comp);
  
    /* ANTLOC and AE_KILL are freed just after pre_lcm finishes.  */
  
!   if (pre_optimal)
!     sbitmap_vector_free (pre_optimal);
!   if (pre_redundant)
!     sbitmap_vector_free (pre_redundant);
!   if (pre_insert_map)
!     sbitmap_vector_free (pre_insert_map);
!   if (pre_delete_map)
!     sbitmap_vector_free (pre_delete_map);
!   if (ae_in)
!     sbitmap_vector_free (ae_in);
!   if (ae_out)
!     sbitmap_vector_free (ae_out);
! 
!   transp = comp = NULL;
!   pre_optimal = pre_redundant = pre_insert_map = pre_delete_map = NULL;
!   ae_in = ae_out = NULL;
  }
  
  /* Top level routine to do the dataflow analysis needed by PRE.  */
  
  static void
! compute_pre_data ()
  {
    sbitmap trapping_expr;
    basic_block bb;
    unsigned int ui;
  
!   compute_local_properties (transp, comp, antloc, &expr_hash_table);
!   sbitmap_vector_zero (ae_kill, last_basic_block);
  
    /* Collect expressions which might trap.  */
!   trapping_expr = sbitmap_alloc (expr_hash_table.n_elems);
    sbitmap_zero (trapping_expr);
!   for (ui = 0; ui < expr_hash_table.size; ui++)
      {
        struct expr *e;
!       for (e = expr_hash_table.table[ui]; e != NULL; e = e->next_same_hash)
  	if (may_trap_p (e->expr))
  	  SET_BIT (trapping_expr, e->bitmap_index);
      }
  
!   /* Compute ae_kill for each basic block using:
  
       ~(TRANSP | COMP)
  
--- 4875,4950 ----
  
  /* Compute PRE+LCM working variables.  */
  
  /* Allocate vars used for PRE analysis.  */
  
  static void
! alloc_pre_mem (n_blocks, pre_data)
!      int n_blocks;
!      struct pre_global *pre_data;
! {
!   pre_data->transp = sbitmap_vector_alloc (n_blocks, pre_data->expr_hash_table.n_elems);
!   pre_data->comp = sbitmap_vector_alloc (n_blocks, pre_data->expr_hash_table.n_elems);
!   pre_data->antloc = sbitmap_vector_alloc (n_blocks, pre_data->expr_hash_table.n_elems);
! 
!   pre_data->insert_map = NULL;
!   pre_data->delete_map = NULL;
!   pre_data->ae.in = NULL;
!   pre_data->ae.out = NULL;
!   pre_data->ae.kill = sbitmap_vector_alloc (n_blocks, pre_data->expr_hash_table.n_elems);
  
!   /* pre_insert_map and pre_delete_map are allocated later.  */
  }
  
  /* Free vars used for PRE analysis.  */
  
  static void
! free_pre_mem (pre_data)
!      struct pre_global *pre_data;
  {
!   sbitmap_vector_free (pre_data->transp);
!   sbitmap_vector_free (pre_data->comp);
  
    /* ANTLOC and AE_KILL are freed just after pre_lcm finishes.  */
  
!   if (pre_data->insert_map)
!     sbitmap_vector_free (pre_data->insert_map);
!   if (pre_data->delete_map)
!     sbitmap_vector_free (pre_data->delete_map);
!   if (pre_data->ae.in)
!     sbitmap_vector_free (pre_data->ae.in);
!   if (pre_data->ae.out)
!     sbitmap_vector_free (pre_data->ae.out);
! 
!   pre_data->transp = pre_data->comp = NULL;
!   pre_data->insert_map = pre_data->delete_map = NULL;
!   pre_data->ae.in = pre_data->ae.out = NULL;
  }
  
  /* Top level routine to do the dataflow analysis needed by PRE.  */
  
  static void
! compute_pre_data (pre_data)
!      struct pre_global *pre_data;
  {
    sbitmap trapping_expr;
    basic_block bb;
    unsigned int ui;
  
!   compute_local_properties (pre_data->transp, pre_data->comp, pre_data->antloc, &pre_data->expr_hash_table);
!   sbitmap_vector_zero (pre_data->ae.kill, last_basic_block);
  
    /* Collect expressions which might trap.  */
!   trapping_expr = sbitmap_alloc (pre_data->expr_hash_table.n_elems);
    sbitmap_zero (trapping_expr);
!   for (ui = 0; ui < pre_data->expr_hash_table.size; ui++)
      {
        struct expr *e;
!       for (e = pre_data->expr_hash_table.table[ui]; e != NULL; e = e->next_same_hash)
  	if (may_trap_p (e->expr))
  	  SET_BIT (trapping_expr, e->bitmap_index);
      }
  
!   /* Compute ae.kill for each basic block using:
  
       ~(TRANSP | COMP)
  
*************** compute_pre_data ()
*** 4818,4838 ****
        for (e = bb->pred; e ; e = e->pred_next)
  	if (e->flags & EDGE_ABNORMAL)
  	  {
! 	    sbitmap_difference (antloc[bb->index], antloc[bb->index], trapping_expr);
! 	    sbitmap_difference (transp[bb->index], transp[bb->index], trapping_expr);
  	    break;
  	  }
  
!       sbitmap_a_or_b (ae_kill[bb->index], transp[bb->index], comp[bb->index]);
!       sbitmap_not (ae_kill[bb->index], ae_kill[bb->index]);
      }
  
!   edge_list = pre_edge_lcm (gcse_file, expr_hash_table.n_elems, transp, comp, antloc,
! 			    ae_kill, &pre_insert_map, &pre_delete_map);
!   sbitmap_vector_free (antloc);
!   antloc = NULL;
!   sbitmap_vector_free (ae_kill);
!   ae_kill = NULL;
    sbitmap_free (trapping_expr);
  }
  
--- 4961,4986 ----
        for (e = bb->pred; e ; e = e->pred_next)
  	if (e->flags & EDGE_ABNORMAL)
  	  {
! 	    sbitmap_difference (pre_data->antloc[bb->index],
! 				pre_data->antloc[bb->index], trapping_expr);
! 	    sbitmap_difference (pre_data->transp[bb->index],
! 				pre_data->transp[bb->index], trapping_expr);
  	    break;
  	  }
  
!       sbitmap_a_or_b (pre_data->ae.kill[bb->index], pre_data->transp[bb->index],
! 		      pre_data->comp[bb->index]);
!       sbitmap_not (pre_data->ae.kill[bb->index], pre_data->ae.kill[bb->index]);
      }
  
!   pre_data->edge_list = pre_edge_lcm (gcse_file, pre_data->expr_hash_table.n_elems,
! 				pre_data->transp, pre_data->comp, pre_data->antloc,
! 				pre_data->ae.kill,
! 				&pre_data->insert_map, &pre_data->delete_map);
!   sbitmap_vector_free (pre_data->antloc);
!   pre_data->antloc = NULL;
!   sbitmap_vector_free (pre_data->ae.kill);
!   pre_data->ae.kill = NULL; 
    sbitmap_free (trapping_expr);
  }
  
*************** compute_pre_data ()
*** 4852,4862 ****
     the closest such expression.  */
  
  static int
! pre_expr_reaches_here_p_work (occr_bb, expr, bb, visited)
       basic_block occr_bb;
       struct expr *expr;
       basic_block bb;
       char *visited;
  {
    edge pred;
  
--- 5000,5011 ----
     the closest such expression.  */
  
  static int
! pre_expr_reaches_here_p_work (occr_bb, expr, bb, visited, pre_data)
       basic_block occr_bb;
       struct expr *expr;
       basic_block bb;
       char *visited;
+      struct pre_global *pre_data;
  {
    edge pred;
  
*************** pre_expr_reaches_here_p_work (occr_bb, e
*** 4870,4876 ****
  	;/* Nothing to do.  */
  
        /* Does this predecessor generate this expression?  */
!       else if (TEST_BIT (comp[pred_bb->index], expr->bitmap_index))
  	{
  	  /* Is this the occurrence we're looking for?
  	     Note that there's only one generating occurrence per block
--- 5019,5025 ----
  	;/* Nothing to do.  */
  
        /* Does this predecessor generate this expression?  */
!       else if (TEST_BIT (pre_data->comp[pred_bb->index], expr->bitmap_index))
  	{
  	  /* Is this the occurrence we're looking for?
  	     Note that there's only one generating occurrence per block
*************** pre_expr_reaches_here_p_work (occr_bb, e
*** 4881,4894 ****
  	  visited[pred_bb->index] = 1;
  	}
        /* Ignore this predecessor if it kills the expression.  */
!       else if (! TEST_BIT (transp[pred_bb->index], expr->bitmap_index))
  	visited[pred_bb->index] = 1;
  
        /* Neither gen nor kill.  */
        else
  	{
  	  visited[pred_bb->index] = 1;
! 	  if (pre_expr_reaches_here_p_work (occr_bb, expr, pred_bb, visited))
  	    return 1;
  	}
      }
--- 5030,5043 ----
  	  visited[pred_bb->index] = 1;
  	}
        /* Ignore this predecessor if it kills the expression.  */
!       else if (! TEST_BIT (pre_data->transp[pred_bb->index], expr->bitmap_index))
  	visited[pred_bb->index] = 1;
  
        /* Neither gen nor kill.  */
        else
  	{
  	  visited[pred_bb->index] = 1;
! 	  if (pre_expr_reaches_here_p_work (occr_bb, expr, pred_bb, visited, pre_data))
  	    return 1;
  	}
      }
*************** pre_expr_reaches_here_p_work (occr_bb, e
*** 4901,4915 ****
     memory allocated for that function is returned.  */
  
  static int
! pre_expr_reaches_here_p (occr_bb, expr, bb)
       basic_block occr_bb;
       struct expr *expr;
       basic_block bb;
  {
    int rval;
    char *visited = (char *) xcalloc (last_basic_block, 1);
  
!   rval = pre_expr_reaches_here_p_work (occr_bb, expr, bb, visited);
  
    free (visited);
    return rval;
--- 5050,5065 ----
     memory allocated for that function is returned.  */
  
  static int
! pre_expr_reaches_here_p (occr_bb, expr, bb, pre_data)
       basic_block occr_bb;
       struct expr *expr;
       basic_block bb;
+      struct pre_global *pre_data;
  {
    int rval;
    char *visited = (char *) xcalloc (last_basic_block, 1);
  
!   rval = pre_expr_reaches_here_p_work (occr_bb, expr, bb, visited, pre_data);
  
    free (visited);
    return rval;
*************** process_insert_insn (expr)
*** 4956,4965 ****
     no sense for code hoisting.  */
  
  static void
! insert_insn_end_bb (expr, bb, pre)
       struct expr *expr;
       basic_block bb;
       int pre;
  {
    rtx insn = bb->end;
    rtx new_insn;
--- 5106,5117 ----
     no sense for code hoisting.  */
  
  static void
! insert_insn_end_bb (expr, bb, pre, antloc, transp)
       struct expr *expr;
       basic_block bb;
       int pre;
+      sbitmap *antloc;
+      sbitmap *transp;
  {
    rtx insn = bb->end;
    rtx new_insn;
*************** insert_insn_end_bb (expr, bb, pre)
*** 5088,5096 ****
     the expressions fully redundant.  */
  
  static int
! pre_edge_insert (edge_list, index_map)
!      struct edge_list *edge_list;
       struct expr **index_map;
  {
    int e, i, j, num_edges, set_size, did_insert = 0;
    sbitmap *inserted;
--- 5240,5248 ----
     the expressions fully redundant.  */
  
  static int
! pre_edge_insert (index_map, pre_data)
       struct expr **index_map;
+      struct pre_global *pre_data;
  {
    int e, i, j, num_edges, set_size, did_insert = 0;
    sbitmap *inserted;
*************** pre_edge_insert (edge_list, index_map)
*** 5098,5118 ****
    /* Where PRE_INSERT_MAP is nonzero, we add the expression on that edge
       if it reaches any of the deleted expressions.  */
  
!   set_size = pre_insert_map[0]->size;
!   num_edges = NUM_EDGES (edge_list);
!   inserted = sbitmap_vector_alloc (num_edges, expr_hash_table.n_elems);
    sbitmap_vector_zero (inserted, num_edges);
  
    for (e = 0; e < num_edges; e++)
      {
        int indx;
!       basic_block bb = INDEX_EDGE_PRED_BB (edge_list, e);
  
        for (i = indx = 0; i < set_size; i++, indx += SBITMAP_ELT_BITS)
  	{
! 	  SBITMAP_ELT_TYPE insert = pre_insert_map[e]->elms[i];
  
! 	  for (j = indx; insert && j < (int) expr_hash_table.n_elems; j++, insert >>= 1)
  	    if ((insert & 1) != 0 && index_map[j]->reaching_reg != NULL_RTX)
  	      {
  		struct expr *expr = index_map[j];
--- 5250,5270 ----
    /* Where PRE_INSERT_MAP is nonzero, we add the expression on that edge
       if it reaches any of the deleted expressions.  */
  
!   set_size = pre_data->insert_map[0]->size;
!   num_edges = NUM_EDGES (pre_data->edge_list);
!   inserted = sbitmap_vector_alloc (num_edges, pre_data->expr_hash_table.n_elems);
    sbitmap_vector_zero (inserted, num_edges);
  
    for (e = 0; e < num_edges; e++)
      {
        int indx;
!       basic_block bb = INDEX_EDGE_PRED_BB (pre_data->edge_list, e);
  
        for (i = indx = 0; i < set_size; i++, indx += SBITMAP_ELT_BITS)
  	{
! 	  SBITMAP_ELT_TYPE insert = pre_data->insert_map[e]->elms[i];
  
! 	  for (j = indx; insert && j < (int) pre_data->expr_hash_table.n_elems; j++, insert >>= 1)
  	    if ((insert & 1) != 0 && index_map[j]->reaching_reg != NULL_RTX)
  	      {
  		struct expr *expr = index_map[j];
*************** pre_edge_insert (edge_list, index_map)
*** 5129,5135 ****
  		    if (!TEST_BIT (inserted[e], j))
  		      {
  			rtx insn;
! 			edge eg = INDEX_EDGE (edge_list, e);
  
  			/* We can't insert anything on an abnormal and
  			   critical edge, so we insert the insn at the end of
--- 5281,5287 ----
  		    if (!TEST_BIT (inserted[e], j))
  		      {
  			rtx insn;
! 			edge eg = INDEX_EDGE (pre_data->edge_list, e);
  
  			/* We can't insert anything on an abnormal and
  			   critical edge, so we insert the insn at the end of
*************** pre_edge_insert (edge_list, index_map)
*** 5139,5145 ****
  			   now.  */
  
  			if ((eg->flags & EDGE_ABNORMAL) == EDGE_ABNORMAL)
! 			  insert_insn_end_bb (index_map[j], bb, 0);
  			else
  			  {
  			    insn = process_insert_insn (index_map[j]);
--- 5291,5298 ----
  			   now.  */
  
  			if ((eg->flags & EDGE_ABNORMAL) == EDGE_ABNORMAL)
! 			  insert_insn_end_bb (index_map[j], bb, 0,
! 					pre_data->antloc, pre_data->transp);
  			else
  			  {
  			    insn = process_insert_insn (index_map[j]);
*************** pre_edge_insert (edge_list, index_map)
*** 5150,5156 ****
  			  {
  			    fprintf (gcse_file, "PRE/HOIST: edge (%d,%d), ",
  				     bb->index,
! 				     INDEX_EDGE_SUCC_BB (edge_list, e)->index);
  			    fprintf (gcse_file, "copy expression %d\n",
  				     expr->bitmap_index);
  			  }
--- 5303,5310 ----
  			  {
  			    fprintf (gcse_file, "PRE/HOIST: edge (%d,%d), ",
  				     bb->index,
! 				     INDEX_EDGE_SUCC_BB (pre_data->edge_list,
! 							 e)->index);
  			    fprintf (gcse_file, "copy expression %d\n",
  				     expr->bitmap_index);
  			  }
*************** pre_insert_copy_insn (expr, insn)
*** 5204,5210 ****
     to `reaching_reg'.  */
  
  static void
! pre_insert_copies ()
  {
    unsigned int i;
    struct expr *expr;
--- 5358,5365 ----
     to `reaching_reg'.  */
  
  static void
! pre_insert_copies (pre_data)
!      struct pre_global *pre_data;
  {
    unsigned int i;
    struct expr *expr;
*************** pre_insert_copies ()
*** 5217,5224 ****
       ??? The current algorithm is rather brute force.
       Need to do some profiling.  */
  
!   for (i = 0; i < expr_hash_table.size; i++)
!     for (expr = expr_hash_table.table[i]; expr != NULL; expr = expr->next_same_hash)
        {
  	/* If the basic block isn't reachable, PPOUT will be TRUE.  However,
  	   we don't want to insert a copy here because the expression may not
--- 5372,5379 ----
       ??? The current algorithm is rather brute force.
       Need to do some profiling.  */
  
!   for (i = 0; i < pre_data->expr_hash_table.size; i++)
!     for (expr = pre_data->expr_hash_table.table[i]; expr != NULL; expr = expr->next_same_hash)
        {
  	/* If the basic block isn't reachable, PPOUT will be TRUE.  However,
  	   we don't want to insert a copy here because the expression may not
*************** pre_insert_copies ()
*** 5242,5254 ****
  		  continue;
  
  		/* Don't handle this one if it's a redundant one.  */
! 		if (TEST_BIT (pre_redundant_insns, INSN_CUID (insn)))
  		  continue;
  
  		/* Or if the expression doesn't reach the deleted one.  */
  		if (! pre_expr_reaches_here_p (BLOCK_FOR_INSN (avail->insn),
  					       expr,
! 					       BLOCK_FOR_INSN (occr->insn)))
  		  continue;
  
  		/* Copy the result of avail to reaching_reg.  */
--- 5397,5410 ----
  		  continue;
  
  		/* Don't handle this one if it's a redundant one.  */
! 		if (TEST_BIT (pre_data->redundant_insns, INSN_CUID (insn)))
  		  continue;
  
  		/* Or if the expression doesn't reach the deleted one.  */
  		if (! pre_expr_reaches_here_p (BLOCK_FOR_INSN (avail->insn),
  					       expr,
! 					       BLOCK_FOR_INSN (occr->insn),
! 					       pre_data))
  		  continue;
  
  		/* Copy the result of avail to reaching_reg.  */
*************** gcse_emit_move_after (src, dest, insn)
*** 5297,5303 ****
     Returns non-zero if a change is made.  */
  
  static int
! pre_delete ()
  {
    unsigned int i;
    int changed;
--- 5453,5460 ----
     Returns non-zero if a change is made.  */
  
  static int
! pre_delete (pre_data)
!      struct pre_global *pre_data;
  {
    unsigned int i;
    int changed;
*************** pre_delete ()
*** 5305,5312 ****
    struct occr *occr;
  
    changed = 0;
!   for (i = 0; i < expr_hash_table.size; i++)
!     for (expr = expr_hash_table.table[i]; expr != NULL; expr = expr->next_same_hash)
        {
  	int indx = expr->bitmap_index;
  
--- 5462,5469 ----
    struct occr *occr;
  
    changed = 0;
!   for (i = 0; i < pre_data->expr_hash_table.size; i++)
!     for (expr = pre_data->expr_hash_table.table[i]; expr != NULL; expr = expr->next_same_hash)
        {
  	int indx = expr->bitmap_index;
  
*************** pre_delete ()
*** 5319,5325 ****
  	    rtx set;
  	    basic_block bb = BLOCK_FOR_INSN (insn);
  
! 	    if (TEST_BIT (pre_delete_map[bb->index], indx))
  	      {
  		set = single_set (insn);
  		if (! set)
--- 5476,5482 ----
  	    rtx set;
  	    basic_block bb = BLOCK_FOR_INSN (insn);
  
! 	    if (TEST_BIT (pre_data->delete_map[bb->index], indx))
  	      {
  		set = single_set (insn);
  		if (! set)
*************** pre_delete ()
*** 5335,5341 ****
  		gcse_emit_move_after (expr->reaching_reg, SET_DEST (set), insn);
  		delete_insn (insn);
  		occr->deleted_p = 1;
! 		SET_BIT (pre_redundant_insns, INSN_CUID (insn));
  		changed = 1;
  		gcse_subst_count++;
  
--- 5492,5498 ----
  		gcse_emit_move_after (expr->reaching_reg, SET_DEST (set), insn);
  		delete_insn (insn);
  		occr->deleted_p = 1;
! 		SET_BIT (pre_data->redundant_insns, INSN_CUID (insn));
  		changed = 1;
  		gcse_subst_count++;
  
*************** pre_delete ()
*** 5375,5381 ****
     redundancies.  */
  
  static int
! pre_gcse ()
  {
    unsigned int i;
    int did_insert, changed;
--- 5532,5539 ----
     redundancies.  */
  
  static int
! pre_gcse (pre_data)
!      struct pre_global *pre_data;
  {
    unsigned int i;
    int did_insert, changed;
*************** pre_gcse ()
*** 5385,5411 ****
    /* Compute a mapping from expression number (`bitmap_index') to
       hash table entry.  */
  
!   index_map = (struct expr **) xcalloc (expr_hash_table.n_elems, sizeof (struct expr *));
!   for (i = 0; i < expr_hash_table.size; i++)
!     for (expr = expr_hash_table.table[i]; expr != NULL; expr = expr->next_same_hash)
        index_map[expr->bitmap_index] = expr;
  
    /* Reset bitmap used to track which insns are redundant.  */
!   pre_redundant_insns = sbitmap_alloc (max_cuid);
!   sbitmap_zero (pre_redundant_insns);
  
    /* Delete the redundant insns first so that
       - we know what register to use for the new insns and for the other
         ones with reaching expressions
       - we know which insns are redundant when we go to create copies  */
  
!   changed = pre_delete ();
! 
!   did_insert = pre_edge_insert (edge_list, index_map);
  
    /* In other places with reaching expressions, copy the expression to the
       specially allocated pseudo-reg that reaches the redundant expr.  */
!   pre_insert_copies ();
    if (did_insert)
      {
        commit_edge_insertions ();
--- 5543,5569 ----
    /* Compute a mapping from expression number (`bitmap_index') to
       hash table entry.  */
  
!   index_map = (struct expr **) xcalloc (pre_data->expr_hash_table.n_elems, sizeof (struct expr *));
!   for (i = 0; i < pre_data->expr_hash_table.size; i++)
!     for (expr = pre_data->expr_hash_table.table[i]; expr != NULL; expr = expr->next_same_hash)
        index_map[expr->bitmap_index] = expr;
  
    /* Reset bitmap used to track which insns are redundant.  */
!   pre_data->redundant_insns = sbitmap_alloc (max_cuid);
!   sbitmap_zero (pre_data->redundant_insns);
  
    /* Delete the redundant insns first so that
       - we know what register to use for the new insns and for the other
         ones with reaching expressions
       - we know which insns are redundant when we go to create copies  */
  
!   changed = pre_delete (pre_data);
!   
!   did_insert = pre_edge_insert (index_map, pre_data);
  
    /* In other places with reaching expressions, copy the expression to the
       specially allocated pseudo-reg that reaches the redundant expr.  */
!   pre_insert_copies (pre_data);
    if (did_insert)
      {
        commit_edge_insertions ();
*************** pre_gcse ()
*** 5413,5419 ****
      }
  
    free (index_map);
!   sbitmap_free (pre_redundant_insns);
    return changed;
  }
  
--- 5571,5577 ----
      }
  
    free (index_map);
!   sbitmap_free (pre_data->redundant_insns);
    return changed;
  }
  
*************** one_pre_gcse_pass (pass)
*** 5426,5457 ****
       int pass;
  {
    int changed = 0;
  
    gcse_subst_count = 0;
    gcse_create_count = 0;
  
!   alloc_hash_table (max_cuid, &expr_hash_table, 0);
    add_noreturn_fake_exit_edges ();
    if (flag_gcse_lm)
      compute_ld_motion_mems ();
  
!   compute_hash_table (&expr_hash_table);
!   trim_ld_motion_mems ();
    if (gcse_file)
!     dump_hash_table (gcse_file, "Expression", &expr_hash_table);
  
!   if (expr_hash_table.n_elems > 0)
      {
!       alloc_pre_mem (last_basic_block, expr_hash_table.n_elems);
!       compute_pre_data ();
!       changed |= pre_gcse ();
!       free_edge_list (edge_list);
!       free_pre_mem ();
      }
  
    free_ldst_mems ();
    remove_fake_edges ();
!   free_hash_table (&expr_hash_table);
  
    if (gcse_file)
      {
--- 5584,5616 ----
       int pass;
  {
    int changed = 0;
+   struct pre_global pre_data;
  
    gcse_subst_count = 0;
    gcse_create_count = 0;
  
!   alloc_hash_table (max_cuid, &pre_data.expr_hash_table, 0);
    add_noreturn_fake_exit_edges ();
    if (flag_gcse_lm)
      compute_ld_motion_mems ();
  
!   compute_hash_table (&pre_data.expr_hash_table);
!   trim_ld_motion_mems (&pre_data);
    if (gcse_file)
!     dump_hash_table (gcse_file, "Expression", &pre_data.expr_hash_table);
  
!   if (pre_data.expr_hash_table.n_elems > 0)
      {
!       alloc_pre_mem (last_basic_block, &pre_data);
!       compute_pre_data (&pre_data);
!       changed |= pre_gcse (&pre_data);
!       free_edge_list (pre_data.edge_list);
!       free_pre_mem (&pre_data);
      }
  
    free_ldst_mems ();
    remove_fake_edges ();
!   free_hash_table (&pre_data.expr_hash_table);
  
    if (gcse_file)
      {
*************** add_label_notes (x, insn)
*** 5524,5536 ****
     EH table sizes, this may not be worthwhile.  */
  
  static void
! compute_transpout ()
  {
    basic_block bb;
    unsigned int i;
    struct expr *expr;
  
!   sbitmap_vector_ones (transpout, last_basic_block);
  
    FOR_EACH_BB (bb)
      {
--- 5683,5696 ----
     EH table sizes, this may not be worthwhile.  */
  
  static void
! compute_transpout (hoist_data)
!      struct hoist_global *hoist_data;
  {
    basic_block bb;
    unsigned int i;
    struct expr *expr;
  
!   sbitmap_vector_ones (hoist_data->transpout, last_basic_block);
  
    FOR_EACH_BB (bb)
      {
*************** compute_transpout ()
*** 5540,5547 ****
        if (GET_CODE (bb->end) != CALL_INSN)
  	continue;
  
!       for (i = 0; i < expr_hash_table.size; i++)
! 	for (expr = expr_hash_table.table[i]; expr ; expr = expr->next_same_hash)
  	  if (GET_CODE (expr->expr) == MEM)
  	    {
  	      if (GET_CODE (XEXP (expr->expr, 0)) == SYMBOL_REF
--- 5700,5707 ----
        if (GET_CODE (bb->end) != CALL_INSN)
  	continue;
  
!       for (i = 0; i < hoist_data->expr_hash_table.size; i++)
! 	for (expr = hoist_data->expr_hash_table.table[i]; expr ; expr = expr->next_same_hash)
  	  if (GET_CODE (expr->expr) == MEM)
  	    {
  	      if (GET_CODE (XEXP (expr->expr, 0)) == SYMBOL_REF
*************** compute_transpout ()
*** 5551,5557 ****
  	      /* ??? Optimally, we would use interprocedural alias
  		 analysis to determine if this mem is actually killed
  		 by this call.  */
! 	      RESET_BIT (transpout[bb->index], expr->bitmap_index);
  	    }
      }
  }
--- 5711,5717 ----
  	      /* ??? Optimally, we would use interprocedural alias
  		 analysis to determine if this mem is actually killed
  		 by this call.  */
! 	      RESET_BIT (hoist_data->transpout[bb->index], expr->bitmap_index);
  	    }
      }
  }
*************** delete_null_pointer_checks (f)
*** 5863,5878 ****
  
  /* Code Hoisting variables and subroutines.  */
  
- /* Very busy expressions.  */
- static sbitmap *hoist_vbein;
- static sbitmap *hoist_vbeout;
- 
- /* Hoistable expressions.  */
- static sbitmap *hoist_exprs;
- 
- /* Dominator bitmaps.  */
- dominance_info dominators;
- 
  /* ??? We could compute post dominators and run this algorithm in
     reverse to perform tail merging, doing so would probably be
     more effective than the tail merging code in jump.c.
--- 6023,6028 ----
*************** dominance_info dominators;
*** 5883,5916 ****
  /* Allocate vars used for code hoisting analysis.  */
  
  static void
! alloc_code_hoist_mem (n_blocks, n_exprs)
!      int n_blocks, n_exprs;
! {
!   antloc = sbitmap_vector_alloc (n_blocks, n_exprs);
!   transp = sbitmap_vector_alloc (n_blocks, n_exprs);
!   comp = sbitmap_vector_alloc (n_blocks, n_exprs);
! 
!   hoist_vbein = sbitmap_vector_alloc (n_blocks, n_exprs);
!   hoist_vbeout = sbitmap_vector_alloc (n_blocks, n_exprs);
!   hoist_exprs = sbitmap_vector_alloc (n_blocks, n_exprs);
!   transpout = sbitmap_vector_alloc (n_blocks, n_exprs);
  }
  
  /* Free vars used for code hoisting analysis.  */
  
  static void
! free_code_hoist_mem ()
  {
!   sbitmap_vector_free (antloc);
!   sbitmap_vector_free (transp);
!   sbitmap_vector_free (comp);
! 
!   sbitmap_vector_free (hoist_vbein);
!   sbitmap_vector_free (hoist_vbeout);
!   sbitmap_vector_free (hoist_exprs);
!   sbitmap_vector_free (transpout);
  
!   free_dominance_info (dominators);
  }
  
  /* Compute the very busy expressions at entry/exit from each block.
--- 6033,6068 ----
  /* Allocate vars used for code hoisting analysis.  */
  
  static void
! alloc_code_hoist_mem (n_blocks, hoist_data)
!      int n_blocks;
!      struct hoist_global *hoist_data;
! {
!   hoist_data->antloc = sbitmap_vector_alloc (n_blocks, hoist_data->expr_hash_table.n_elems);
!   hoist_data->transp = sbitmap_vector_alloc (n_blocks, hoist_data->expr_hash_table.n_elems);
!   hoist_data->comp = sbitmap_vector_alloc (n_blocks, hoist_data->expr_hash_table.n_elems);
! 
!   hoist_data->vbein = sbitmap_vector_alloc (n_blocks, hoist_data->expr_hash_table.n_elems);
!   hoist_data->vbeout = sbitmap_vector_alloc (n_blocks, hoist_data->expr_hash_table.n_elems);
!   hoist_data->exprs = sbitmap_vector_alloc (n_blocks, hoist_data->expr_hash_table.n_elems);
!   hoist_data->transpout = sbitmap_vector_alloc (n_blocks, hoist_data->expr_hash_table.n_elems);
  }
  
  /* Free vars used for code hoisting analysis.  */
  
  static void
! free_code_hoist_mem (hoist_data)
!      struct hoist_global *hoist_data;
  {
!   sbitmap_vector_free (hoist_data->antloc);
!   sbitmap_vector_free (hoist_data->transp);
!   sbitmap_vector_free (hoist_data->comp);
! 
!   sbitmap_vector_free (hoist_data->vbein);
!   sbitmap_vector_free (hoist_data->vbeout);
!   sbitmap_vector_free (hoist_data->exprs);
!   sbitmap_vector_free (hoist_data->transpout);
  
!   free_dominance_info (hoist_data->dominators);
  }
  
  /* Compute the very busy expressions at entry/exit from each block.
*************** free_code_hoist_mem ()
*** 5919,5931 ****
     compute the expression.  */
  
  static void
! compute_code_hoist_vbeinout ()
  {
    int changed, passes;
    basic_block bb;
  
!   sbitmap_vector_zero (hoist_vbeout, last_basic_block);
!   sbitmap_vector_zero (hoist_vbein, last_basic_block);
  
    passes = 0;
    changed = 1;
--- 6071,6084 ----
     compute the expression.  */
  
  static void
! compute_code_hoist_vbeinout (hoist_data)
!      struct hoist_global *hoist_data;
  {
    int changed, passes;
    basic_block bb;
  
!   sbitmap_vector_zero (hoist_data->vbeout, last_basic_block);
!   sbitmap_vector_zero (hoist_data->vbein, last_basic_block);
  
    passes = 0;
    changed = 1;
*************** compute_code_hoist_vbeinout ()
*** 5938,5947 ****
  	 the convergence.  */
        FOR_EACH_BB_REVERSE (bb)
  	{
! 	  changed |= sbitmap_a_or_b_and_c_cg (hoist_vbein[bb->index], antloc[bb->index],
! 					      hoist_vbeout[bb->index], transp[bb->index]);
  	  if (bb->next_bb != EXIT_BLOCK_PTR)
! 	    sbitmap_intersection_of_succs (hoist_vbeout[bb->index], hoist_vbein, bb->index);
  	}
  
        passes++;
--- 6091,6103 ----
  	 the convergence.  */
        FOR_EACH_BB_REVERSE (bb)
  	{
! 	  changed |= sbitmap_a_or_b_and_c_cg (hoist_data->vbein[bb->index],
! 	  				      hoist_data->antloc[bb->index],
! 					      hoist_data->vbeout[bb->index],
! 					      hoist_data->transp[bb->index]);
  	  if (bb->next_bb != EXIT_BLOCK_PTR)
! 	    sbitmap_intersection_of_succs (hoist_data->vbeout[bb->index],
! 	    				   hoist_data->vbein, bb->index);
  	}
  
        passes++;
*************** compute_code_hoist_vbeinout ()
*** 5954,5965 ****
  /* Top level routine to do the dataflow analysis needed by code hoisting.  */
  
  static void
! compute_code_hoist_data ()
  {
!   compute_local_properties (transp, comp, antloc, &expr_hash_table);
!   compute_transpout ();
!   compute_code_hoist_vbeinout ();
!   dominators = calculate_dominance_info (CDI_DOMINATORS);
    if (gcse_file)
      fprintf (gcse_file, "\n");
  }
--- 6110,6122 ----
  /* Top level routine to do the dataflow analysis needed by code hoisting.  */
  
  static void
! compute_code_hoist_data (hoist_data)
!      struct hoist_global *hoist_data;
  {
!   compute_local_properties (hoist_data->transp, hoist_data->comp, hoist_data->antloc, &hoist_data->expr_hash_table);
!   compute_transpout (hoist_data);
!   compute_code_hoist_vbeinout (hoist_data);
!   hoist_data->dominators = calculate_dominance_info (CDI_DOMINATORS);
    if (gcse_file)
      fprintf (gcse_file, "\n");
  }
*************** compute_code_hoist_data ()
*** 5978,5988 ****
     paths.  */
  
  static int
! hoist_expr_reaches_here_p (expr_bb, expr_index, bb, visited)
       basic_block expr_bb;
       int expr_index;
       basic_block bb;
       char *visited;
  {
    edge pred;
    int visited_allocated_locally = 0;
--- 6135,6146 ----
     paths.  */
  
  static int
! hoist_expr_reaches_here_p (expr_bb, expr_index, bb, visited, hoist_data)
       basic_block expr_bb;
       int expr_index;
       basic_block bb;
       char *visited;
+      struct hoist_global *hoist_data;
  {
    edge pred;
    int visited_allocated_locally = 0;
*************** hoist_expr_reaches_here_p (expr_bb, expr
*** 6006,6014 ****
  	continue;
  
        /* Does this predecessor generate this expression?  */
!       else if (TEST_BIT (comp[pred_bb->index], expr_index))
  	break;
!       else if (! TEST_BIT (transp[pred_bb->index], expr_index))
  	break;
  
        /* Not killed.  */
--- 6164,6172 ----
  	continue;
  
        /* Does this predecessor generate this expression?  */
!       else if (TEST_BIT (hoist_data->comp[pred_bb->index], expr_index))
  	break;
!       else if (! TEST_BIT (hoist_data->transp[pred_bb->index], expr_index))
  	break;
  
        /* Not killed.  */
*************** hoist_expr_reaches_here_p (expr_bb, expr
*** 6016,6022 ****
  	{
  	  visited[pred_bb->index] = 1;
  	  if (! hoist_expr_reaches_here_p (expr_bb, expr_index,
! 					   pred_bb, visited))
  	    break;
  	}
      }
--- 6174,6180 ----
  	{
  	  visited[pred_bb->index] = 1;
  	  if (! hoist_expr_reaches_here_p (expr_bb, expr_index,
! 					   pred_bb, visited, hoist_data))
  	    break;
  	}
      }
*************** hoist_expr_reaches_here_p (expr_bb, expr
*** 6029,6035 ****
  /* Actually perform code hoisting.  */
  
  static void
! hoist_code ()
  {
    basic_block bb, dominated;
    basic_block *domby;
--- 6187,6194 ----
  /* Actually perform code hoisting.  */
  
  static void
! hoist_code (hoist_data)
!      struct hoist_global *hoist_data;
  {
    basic_block bb, dominated;
    basic_block *domby;
*************** hoist_code ()
*** 6038,6051 ****
    struct expr **index_map;
    struct expr *expr;
  
!   sbitmap_vector_zero (hoist_exprs, last_basic_block);
  
    /* Compute a mapping from expression number (`bitmap_index') to
       hash table entry.  */
  
!   index_map = (struct expr **) xcalloc (expr_hash_table.n_elems, sizeof (struct expr *));
!   for (i = 0; i < expr_hash_table.size; i++)
!     for (expr = expr_hash_table.table[i]; expr != NULL; expr = expr->next_same_hash)
        index_map[expr->bitmap_index] = expr;
  
    /* Walk over each basic block looking for potentially hoistable
--- 6197,6210 ----
    struct expr **index_map;
    struct expr *expr;
  
!   sbitmap_vector_zero (hoist_data->exprs, last_basic_block);
  
    /* Compute a mapping from expression number (`bitmap_index') to
       hash table entry.  */
  
!   index_map = (struct expr **) xcalloc (hoist_data->expr_hash_table.n_elems, sizeof (struct expr *));
!   for (i = 0; i < hoist_data->expr_hash_table.size; i++)
!     for (expr = hoist_data->expr_hash_table.table[i]; expr != NULL; expr = expr->next_same_hash)
        index_map[expr->bitmap_index] = expr;
  
    /* Walk over each basic block looking for potentially hoistable
*************** hoist_code ()
*** 6055,6069 ****
        int found = 0;
        int insn_inserted_p;
  
!       domby_len = get_dominated_by (dominators, bb, &domby);
        /* Examine each expression that is very busy at the exit of this
  	 block.  These are the potentially hoistable expressions.  */
!       for (i = 0; i < hoist_vbeout[bb->index]->n_bits; i++)
  	{
  	  int hoistable = 0;
  
! 	  if (TEST_BIT (hoist_vbeout[bb->index], i)
! 	      && TEST_BIT (transpout[bb->index], i))
  	    {
  	      /* We've found a potentially hoistable expression, now
  		 we look at every block BB dominates to see if it
--- 6214,6228 ----
        int found = 0;
        int insn_inserted_p;
  
!       domby_len = get_dominated_by (hoist_data->dominators, bb, &domby);
        /* Examine each expression that is very busy at the exit of this
  	 block.  These are the potentially hoistable expressions.  */
!       for (i = 0; i < hoist_data->vbeout[bb->index]->n_bits; i++)
  	{
  	  int hoistable = 0;
  
! 	  if (TEST_BIT (hoist_data->vbeout[bb->index], i) &&
! 	      TEST_BIT (hoist_data->transpout[bb->index], i))
  	    {
  	      /* We've found a potentially hoistable expression, now
  		 we look at every block BB dominates to see if it
*************** hoist_code ()
*** 6077,6083 ****
  		  /* We've found a dominated block, now see if it computes
  		     the busy expression and whether or not moving that
  		     expression to the "beginning" of that block is safe.  */
! 		  if (!TEST_BIT (antloc[dominated->index], i))
  		    continue;
  
  		  /* Note if the expression would reach the dominated block
--- 6236,6242 ----
  		  /* We've found a dominated block, now see if it computes
  		     the busy expression and whether or not moving that
  		     expression to the "beginning" of that block is safe.  */
! 		  if (!TEST_BIT (hoist_data->antloc[dominated->index], i))
  		    continue;
  
  		  /* Note if the expression would reach the dominated block
*************** hoist_code ()
*** 6085,6091 ****
  
  		     Keep track of how many times this expression is hoistable
  		     from a dominated block into BB.  */
! 		  if (hoist_expr_reaches_here_p (bb, i, dominated, NULL))
  		    hoistable++;
  		}
  
--- 6244,6250 ----
  
  		     Keep track of how many times this expression is hoistable
  		     from a dominated block into BB.  */
! 		  if (hoist_expr_reaches_here_p (bb, i, dominated, NULL, hoist_data))
  		    hoistable++;
  		}
  
*************** hoist_code ()
*** 6101,6107 ****
  		 to nullify any benefit we get from code hoisting.  */
  	      if (hoistable > 1)
  		{
! 		  SET_BIT (hoist_exprs[bb->index], i);
  		  found = 1;
  		}
  	    }
--- 6260,6266 ----
  		 to nullify any benefit we get from code hoisting.  */
  	      if (hoistable > 1)
  		{
! 		  SET_BIT (hoist_data->exprs[bb->index], i);
  		  found = 1;
  		}
  	    }
*************** hoist_code ()
*** 6114,6127 ****
  	}
  
        /* Loop over all the hoistable expressions.  */
!       for (i = 0; i < hoist_exprs[bb->index]->n_bits; i++)
  	{
  	  /* We want to insert the expression into BB only once, so
  	     note when we've inserted it.  */
  	  insn_inserted_p = 0;
  
  	  /* These tests should be the same as the tests above.  */
! 	  if (TEST_BIT (hoist_vbeout[bb->index], i))
  	    {
  	      /* We've found a potentially hoistable expression, now
  		 we look at every block BB dominates to see if it
--- 6273,6286 ----
  	}
  
        /* Loop over all the hoistable expressions.  */
!       for (i = 0; i < hoist_data->exprs[bb->index]->n_bits; i++)
  	{
  	  /* We want to insert the expression into BB only once, so
  	     note when we've inserted it.  */
  	  insn_inserted_p = 0;
  
  	  /* These tests should be the same as the tests above.  */
! 	  if (TEST_BIT (hoist_data->vbeout[bb->index], i))
  	    {
  	      /* We've found a potentially hoistable expression, now
  		 we look at every block BB dominates to see if it
*************** hoist_code ()
*** 6136,6142 ****
  		  /* We've found a dominated block, now see if it computes
  		     the busy expression and whether or not moving that
  		     expression to the "beginning" of that block is safe.  */
! 		  if (!TEST_BIT (antloc[dominated->index], i))
  		    continue;
  
  		  /* The expression is computed in the dominated block and
--- 6295,6301 ----
  		  /* We've found a dominated block, now see if it computes
  		     the busy expression and whether or not moving that
  		     expression to the "beginning" of that block is safe.  */
! 		  if (!TEST_BIT (hoist_data->antloc[dominated->index], i))
  		    continue;
  
  		  /* The expression is computed in the dominated block and
*************** hoist_code ()
*** 6144,6150 ****
  		     dominated block.  Now we have to determine if the
  		     expression would reach the dominated block if it was
  		     placed at the end of BB.  */
! 		  if (hoist_expr_reaches_here_p (bb, i, dominated, NULL))
  		    {
  		      struct expr *expr = index_map[i];
  		      struct occr *occr = expr->antic_occr;
--- 6303,6309 ----
  		     dominated block.  Now we have to determine if the
  		     expression would reach the dominated block if it was
  		     placed at the end of BB.  */
! 		  if (hoist_expr_reaches_here_p (bb, i, dominated, NULL, hoist_data))
  		    {
  		      struct expr *expr = index_map[i];
  		      struct occr *occr = expr->antic_occr;
*************** hoist_code ()
*** 6177,6183 ****
  		      occr->deleted_p = 1;
  		      if (!insn_inserted_p)
  			{
! 			  insert_insn_end_bb (index_map[i], bb, 0);
  			  insn_inserted_p = 1;
  			}
  		    }
--- 6336,6343 ----
  		      occr->deleted_p = 1;
  		      if (!insn_inserted_p)
  			{
! 			  insert_insn_end_bb (index_map[i], bb, 0,
! 				hoist_data->antloc, hoist_data->transp);
  			  insn_inserted_p = 1;
  			}
  		    }
*************** static int
*** 6198,6218 ****
  one_code_hoisting_pass ()
  {
    int changed = 0;
  
!   alloc_hash_table (max_cuid, &expr_hash_table, 0);
!   compute_hash_table (&expr_hash_table);
    if (gcse_file)
!     dump_hash_table (gcse_file, "Code Hosting Expressions", &expr_hash_table);
  
!   if (expr_hash_table.n_elems > 0)
      {
!       alloc_code_hoist_mem (last_basic_block, expr_hash_table.n_elems);
!       compute_code_hoist_data ();
!       hoist_code ();
!       free_code_hoist_mem ();
      }
  
!   free_hash_table (&expr_hash_table);
  
    return changed;
  }
--- 6358,6379 ----
  one_code_hoisting_pass ()
  {
    int changed = 0;
+   struct hoist_global hoist_data;
  
!   alloc_hash_table (max_cuid, &hoist_data.expr_hash_table, 0);
!   compute_hash_table (&hoist_data.expr_hash_table);
    if (gcse_file)
!     dump_hash_table (gcse_file, "Code Hosting Expressions", &hoist_data.expr_hash_table);
  
!   if (hoist_data.expr_hash_table.n_elems > 0)
      {
!       alloc_code_hoist_mem (last_basic_block, &hoist_data);
!       compute_code_hoist_data (&hoist_data);
!       hoist_code (&hoist_data);
!       free_code_hoist_mem (&hoist_data);
      }
  
!   free_hash_table (&hoist_data.expr_hash_table);
  
    return changed;
  }
*************** compute_ld_motion_mems ()
*** 6515,6521 ****
     expression list for pre gcse.  */
  
  static void
! trim_ld_motion_mems ()
  {
    struct ls_expr * last = NULL;
    struct ls_expr * ptr = first_ls_expr ();
--- 6676,6683 ----
     expression list for pre gcse.  */
  
  static void
! trim_ld_motion_mems (pre_data)
!      struct pre_global *pre_data;
  {
    struct ls_expr * last = NULL;
    struct ls_expr * ptr = first_ls_expr ();
*************** trim_ld_motion_mems ()
*** 6532,6540 ****
  
  	  del = 1;
  	  /* Delete if we cannot find this mem in the expression list.  */
! 	  for (i = 0; i < expr_hash_table.size && del; i++)
  	    {
! 	      for (expr = expr_hash_table.table[i];
  		   expr != NULL;
  		   expr = expr->next_same_hash)
  		if (expr_equiv_p (expr->expr, ptr->pattern))
--- 6694,6702 ----
  
  	  del = 1;
  	  /* Delete if we cannot find this mem in the expression list.  */
! 	  for (i = 0; i < pre_data->expr_hash_table.size && del; i++)
  	    {
! 	      for (expr = pre_data->expr_hash_table.table[i]; 
  		   expr != NULL;
  		   expr = expr->next_same_hash)
  		if (expr_equiv_p (expr->expr, ptr->pattern))
*************** update_ld_motion_stores (expr)
*** 6634,6661 ****
  
  /* Store motion code.  */
  
- /* This is used to communicate the target bitvector we want to use in the
-    reg_set_info routine when called via the note_stores mechanism.  */
- static sbitmap * regvec;
- 
- /* Used in computing the reverse edge graph bit vectors.  */
- static sbitmap * st_antloc;
- 
- /* Global holding the number of store expressions we are dealing with.  */
- static int num_stores;
- 
  /* Checks to set if we need to mark a register set. Called from note_stores.  */
  
  static void
  reg_set_info (dest, setter, data)
       rtx dest, setter ATTRIBUTE_UNUSED;
!      void * data ATTRIBUTE_UNUSED;
  {
    if (GET_CODE (dest) == SUBREG)
      dest = SUBREG_REG (dest);
  
    if (GET_CODE (dest) == REG)
!     SET_BIT (*regvec, REGNO (dest));
  }
  
  /* Return non-zero if the register operands of expression X are killed
--- 6796,6814 ----
  
  /* Store motion code.  */
  
  /* Checks to set if we need to mark a register set. Called from note_stores.  */
  
  static void
  reg_set_info (dest, setter, data)
       rtx dest, setter ATTRIBUTE_UNUSED;
!      void * data;
  {
+   struct store_global *store_data = (struct store_global *) data;
    if (GET_CODE (dest) == SUBREG)
      dest = SUBREG_REG (dest);
  
    if (GET_CODE (dest) == REG)
!     SET_BIT (*store_data->regvec, REGNO (dest));
  }
  
  /* Return non-zero if the register operands of expression X are killed
*************** find_moveable_store (insn)
*** 6779,6785 ****
     other way by looking at the flowgraph in reverse.  */
  
  static int
! compute_store_table ()
  {
    int ret;
    basic_block bb;
--- 6932,6939 ----
     other way by looking at the flowgraph in reverse.  */
  
  static int
! compute_store_table (store_data)
!      struct store_global *store_data;
  {
    int ret;
    basic_block bb;
*************** compute_store_table ()
*** 6796,6802 ****
    /* Find all the stores we care about.  */
    FOR_EACH_BB (bb)
      {
!       regvec = & (reg_set_in_block[bb->index]);
        for (insn = bb->end;
  	   insn && insn != PREV_INSN (bb->end);
  	   insn = PREV_INSN (insn))
--- 6950,6956 ----
    /* Find all the stores we care about.  */
    FOR_EACH_BB (bb)
      {
!       store_data->regvec = & (reg_set_in_block[bb->index]);
        for (insn = bb->end;
  	   insn && insn != PREV_INSN (bb->end);
  	   insn = PREV_INSN (insn))
*************** compute_store_table ()
*** 6821,6827 ****
  	    }
  
  	  pat = PATTERN (insn);
! 	  note_stores (pat, reg_set_info, NULL);
  
  	  /* Now that we've marked regs, look for stores.  */
  	  if (GET_CODE (pat) == SET)
--- 6975,6981 ----
  	    }
  
  	  pat = PATTERN (insn);
! 	  note_stores (pat, reg_set_info, store_data);
  
  	  /* Now that we've marked regs, look for stores.  */
  	  if (GET_CODE (pat) == SET)
*************** store_killed_before (x, insn, bb)
*** 6981,6987 ****
     determine which ones are not killed by aliasing, and generate
     the appropriate vectors for gen and killed.  */
  static void
! build_store_vectors ()
  {
    basic_block bb, b;
    rtx insn, st;
--- 7135,7142 ----
     determine which ones are not killed by aliasing, and generate
     the appropriate vectors for gen and killed.  */
  static void
! build_store_vectors (store_data)
!      struct store_global *store_data;
  {
    basic_block bb, b;
    rtx insn, st;
*************** build_store_vectors ()
*** 6989,6999 ****
  
    /* Build the gen_vector. This is any store in the table which is not killed
       by aliasing later in its block.  */
!   ae_gen = (sbitmap *) sbitmap_vector_alloc (last_basic_block, num_stores);
!   sbitmap_vector_zero (ae_gen, last_basic_block);
! 
!   st_antloc = (sbitmap *) sbitmap_vector_alloc (last_basic_block, num_stores);
!   sbitmap_vector_zero (st_antloc, last_basic_block);
  
    for (ptr = first_ls_expr (); ptr != NULL; ptr = next_ls_expr (ptr))
      {
--- 7144,7156 ----
  
    /* Build the gen_vector. This is any store in the table which is not killed
       by aliasing later in its block.  */
!   store_data->ae.gen = (sbitmap *) sbitmap_vector_alloc (last_basic_block,
! 					store_data->num_stores);
!   sbitmap_vector_zero (store_data->ae.gen, last_basic_block);
! 
!   store_data->antloc = (sbitmap *) sbitmap_vector_alloc (last_basic_block,
! 					store_data->num_stores);
!   sbitmap_vector_zero (store_data->antloc, last_basic_block);
  
    for (ptr = first_ls_expr (); ptr != NULL; ptr = next_ls_expr (ptr))
      {
*************** build_store_vectors ()
*** 7014,7020 ****
  		 the block), and replace it with this one). We'll copy the
  		 old SRC expression to an unused register in case there
  		 are any side effects.  */
! 	      if (TEST_BIT (ae_gen[bb->index], ptr->index))
  		{
  		  /* Find previous store.  */
  		  rtx st;
--- 7171,7177 ----
  		 the block), and replace it with this one). We'll copy the
  		 old SRC expression to an unused register in case there
  		 are any side effects.  */
! 	      if (TEST_BIT (store_data->ae.gen[bb->index], ptr->index))
  		{
  		  /* Find previous store.  */
  		  rtx st;
*************** build_store_vectors ()
*** 7031,7044 ****
  		      continue;
  		    }
  		}
! 	      SET_BIT (ae_gen[bb->index], ptr->index);
  	      AVAIL_STORE_LIST (ptr) = alloc_INSN_LIST (insn,
  							AVAIL_STORE_LIST (ptr));
  	    }
  
  	  if (!store_killed_before (ptr->pattern, insn, bb))
  	    {
! 	      SET_BIT (st_antloc[BLOCK_NUM (insn)], ptr->index);
  	      ANTIC_STORE_LIST (ptr) = alloc_INSN_LIST (insn,
  							ANTIC_STORE_LIST (ptr));
  	    }
--- 7188,7201 ----
  		      continue;
  		    }
  		}
! 	      SET_BIT (store_data->ae.gen[bb->index], ptr->index);
  	      AVAIL_STORE_LIST (ptr) = alloc_INSN_LIST (insn,
  							AVAIL_STORE_LIST (ptr));
  	    }
  
  	  if (!store_killed_before (ptr->pattern, insn, bb))
  	    {
! 	      SET_BIT (store_data->antloc[BLOCK_NUM (insn)], ptr->index);
  	      ANTIC_STORE_LIST (ptr) = alloc_INSN_LIST (insn,
  							ANTIC_STORE_LIST (ptr));
  	    }
*************** build_store_vectors ()
*** 7048,7058 ****
        free_INSN_LIST_list (&store_list);
      }
  
!   ae_kill = (sbitmap *) sbitmap_vector_alloc (last_basic_block, num_stores);
!   sbitmap_vector_zero (ae_kill, last_basic_block);
  
!   transp = (sbitmap *) sbitmap_vector_alloc (last_basic_block, num_stores);
!   sbitmap_vector_zero (transp, last_basic_block);
  
    for (ptr = first_ls_expr (); ptr != NULL; ptr = next_ls_expr (ptr))
      FOR_EACH_BB (b)
--- 7205,7215 ----
        free_INSN_LIST_list (&store_list);
      }
  
!   store_data->ae.kill = (sbitmap *) sbitmap_vector_alloc (last_basic_block, store_data->num_stores);
!   sbitmap_vector_zero (store_data->ae.kill, last_basic_block);
  
!   store_data->transp = (sbitmap *) sbitmap_vector_alloc (last_basic_block, store_data->num_stores);
!   sbitmap_vector_zero (store_data->transp, last_basic_block);
  
    for (ptr = first_ls_expr (); ptr != NULL; ptr = next_ls_expr (ptr))
      FOR_EACH_BB (b)
*************** build_store_vectors ()
*** 7075,7084 ****
  	      If we always kill it in this case, we'll sometimes do
  	      uneccessary work, but it shouldn't actually hurt anything.
  	    if (!TEST_BIT (ae_gen[b], ptr->index)).  */
! 	    SET_BIT (ae_kill[b->index], ptr->index);
  	  }
  	else
! 	  SET_BIT (transp[b->index], ptr->index);
        }
  
    /* Any block with no exits calls some non-returning function, so
--- 7232,7241 ----
  	      If we always kill it in this case, we'll sometimes do
  	      uneccessary work, but it shouldn't actually hurt anything.
  	    if (!TEST_BIT (ae_gen[b], ptr->index)).  */
! 	    SET_BIT (store_data->ae.kill[b->index], ptr->index);
  	  }
  	else
! 	  SET_BIT (store_data->transp[b->index], ptr->index);
        }
  
    /* Any block with no exits calls some non-returning function, so
*************** build_store_vectors ()
*** 7089,7098 ****
      {
        fprintf (gcse_file, "ST_avail and ST_antic (shown under loads..)\n");
        print_ldst_list (gcse_file);
!       dump_sbitmap_vector (gcse_file, "st_antloc", "", st_antloc, last_basic_block);
!       dump_sbitmap_vector (gcse_file, "st_kill", "", ae_kill, last_basic_block);
!       dump_sbitmap_vector (gcse_file, "Transpt", "", transp, last_basic_block);
!       dump_sbitmap_vector (gcse_file, "st_avloc", "", ae_gen, last_basic_block);
      }
  }
  
--- 7246,7255 ----
      {
        fprintf (gcse_file, "ST_avail and ST_antic (shown under loads..)\n");
        print_ldst_list (gcse_file);
!       dump_sbitmap_vector (gcse_file, "st_antloc", "", store_data->antloc, last_basic_block);
!       dump_sbitmap_vector (gcse_file, "st_kill", "", store_data->ae.kill, last_basic_block);
!       dump_sbitmap_vector (gcse_file, "Transpt", "", store_data->transp, last_basic_block);
!       dump_sbitmap_vector (gcse_file, "st_avloc", "", store_data->ae.gen, last_basic_block);
      }
  }
  
*************** insert_insn_start_bb (insn, bb)
*** 7135,7143 ****
     if an edge insertion was performed.  */
  
  static int
! insert_store (expr, e)
       struct ls_expr * expr;
       edge e;
  {
    rtx reg, insn;
    basic_block bb;
--- 7292,7301 ----
     if an edge insertion was performed.  */
  
  static int
! insert_store (expr, e, store_data)
       struct ls_expr * expr;
       edge e;
+      struct store_global *store_data;
  {
    rtx reg, insn;
    basic_block bb;
*************** insert_store (expr, e)
*** 7157,7166 ****
    bb = e->dest;
    for (tmp = e->dest->pred; tmp ; tmp = tmp->pred_next)
      {
!       int index = EDGE_INDEX (edge_list, tmp->src, tmp->dest);
        if (index == EDGE_INDEX_NO_EDGE)
  	abort ();
!       if (! TEST_BIT (pre_insert_map[index], expr->index))
  	break;
      }
  
--- 7315,7324 ----
    bb = e->dest;
    for (tmp = e->dest->pred; tmp ; tmp = tmp->pred_next)
      {
!       int index = EDGE_INDEX (store_data->edge_list, tmp->src, tmp->dest);
        if (index == EDGE_INDEX_NO_EDGE)
  	abort ();
!       if (! TEST_BIT (store_data->insert_map[index], expr->index))
  	break;
      }
  
*************** insert_store (expr, e)
*** 7170,7177 ****
      {
        for (tmp = e->dest->pred; tmp ; tmp = tmp->pred_next)
  	{
! 	  int index = EDGE_INDEX (edge_list, tmp->src, tmp->dest);
! 	  RESET_BIT (pre_insert_map[index], expr->index);
  	}
        insert_insn_start_bb (insn, bb);
        return 0;
--- 7328,7335 ----
      {
        for (tmp = e->dest->pred; tmp ; tmp = tmp->pred_next)
  	{
! 	  int index = EDGE_INDEX (store_data->edge_list, tmp->src, tmp->dest);
! 	  RESET_BIT (store_data->insert_map[index], expr->index);
  	}
        insert_insn_start_bb (insn, bb);
        return 0;
*************** delete_store (expr, bb)
*** 7258,7284 ****
  /* Free memory used by store motion.  */
  
  static void
! free_store_memory ()
  {
    free_ldst_mems ();
  
!   if (ae_gen)
!     sbitmap_vector_free (ae_gen);
!   if (ae_kill)
!     sbitmap_vector_free (ae_kill);
!   if (transp)
!     sbitmap_vector_free (transp);
!   if (st_antloc)
!     sbitmap_vector_free (st_antloc);
!   if (pre_insert_map)
!     sbitmap_vector_free (pre_insert_map);
!   if (pre_delete_map)
!     sbitmap_vector_free (pre_delete_map);
    if (reg_set_in_block)
      sbitmap_vector_free (reg_set_in_block);
! 
!   ae_gen = ae_kill = transp = st_antloc = NULL;
!   pre_insert_map = pre_delete_map = reg_set_in_block = NULL;
  }
  
  /* Perform store motion. Much like gcse, except we move expressions the
--- 7416,7445 ----
  /* Free memory used by store motion.  */
  
  static void
! free_store_memory (store_data)
!      struct store_global *store_data;
  {
    free_ldst_mems ();
  
!   if (store_data->ae.gen)
!     sbitmap_vector_free (store_data->ae.gen);
!   if (store_data->ae.kill)
!     sbitmap_vector_free (store_data->ae.kill);
!   if (store_data->transp)
!     sbitmap_vector_free (store_data->transp);
!   if (store_data->antloc)
!     sbitmap_vector_free (store_data->antloc);
!   if (store_data->insert_map)
!     sbitmap_vector_free (store_data->insert_map);
!   if (store_data->delete_map)
!     sbitmap_vector_free (store_data->delete_map);
    if (reg_set_in_block)
      sbitmap_vector_free (reg_set_in_block);
!   
!   store_data->ae.gen = store_data->ae.kill =
!     store_data->transp = store_data->antloc = NULL;
!   store_data->insert_map = store_data->delete_map =
!     reg_set_in_block = NULL;
  }
  
  /* Perform store motion. Much like gcse, except we move expressions the
*************** store_motion ()
*** 7291,7296 ****
--- 7452,7458 ----
    int x;
    struct ls_expr * ptr;
    int update_flow = 0;
+   struct store_global store_data;
  
    if (gcse_file)
      {
*************** store_motion ()
*** 7298,7309 ****
        print_rtl (gcse_file, get_insns ());
      }
  
- 
    init_alias_analysis ();
  
    /* Find all the stores that are live to the end of their block.  */
!   num_stores = compute_store_table ();
!   if (num_stores == 0)
      {
        sbitmap_vector_free (reg_set_in_block);
        end_alias_analysis ();
--- 7460,7470 ----
        print_rtl (gcse_file, get_insns ());
      }
  
    init_alias_analysis ();
  
    /* Find all the stores that are live to the end of their block.  */
!   store_data.num_stores = compute_store_table (&store_data);
!   if (store_data.num_stores == 0)
      {
        sbitmap_vector_free (reg_set_in_block);
        end_alias_analysis ();
*************** store_motion ()
*** 7312,7340 ****
  
    /* Now compute whats actually available to move.  */
    add_noreturn_fake_exit_edges ();
!   build_store_vectors ();
  
!   edge_list = pre_edge_rev_lcm (gcse_file, num_stores, transp, ae_gen,
! 				st_antloc, ae_kill, &pre_insert_map,
! 				&pre_delete_map);
  
    /* Now we want to insert the new stores which are going to be needed.  */
    for (ptr = first_ls_expr (); ptr != NULL; ptr = next_ls_expr (ptr))
      {
        FOR_EACH_BB (bb)
! 	if (TEST_BIT (pre_delete_map[bb->index], ptr->index))
  	  delete_store (ptr, bb);
  
!       for (x = 0; x < NUM_EDGES (edge_list); x++)
! 	if (TEST_BIT (pre_insert_map[x], ptr->index))
! 	  update_flow |= insert_store (ptr, INDEX_EDGE (edge_list, x));
      }
  
    if (update_flow)
      commit_edge_insertions ();
  
!   free_store_memory ();
!   free_edge_list (edge_list);
    remove_fake_edges ();
    end_alias_analysis ();
  }
--- 7473,7503 ----
  
    /* Now compute whats actually available to move.  */
    add_noreturn_fake_exit_edges ();
!   build_store_vectors (&store_data);
  
!   store_data.edge_list = pre_edge_rev_lcm (gcse_file, store_data.num_stores,
! 				store_data.transp, store_data.ae.gen, 
! 				store_data.antloc, store_data.ae.kill,
! 				&store_data.insert_map, &store_data.delete_map);
  
    /* Now we want to insert the new stores which are going to be needed.  */
    for (ptr = first_ls_expr (); ptr != NULL; ptr = next_ls_expr (ptr))
      {
        FOR_EACH_BB (bb)
! 	if (TEST_BIT (store_data.delete_map[bb->index], ptr->index))
  	  delete_store (ptr, bb);
  
!       for (x = 0; x < NUM_EDGES (store_data.edge_list); x++)
! 	if (TEST_BIT (store_data.insert_map[x], ptr->index))
! 	  update_flow |= insert_store (ptr, INDEX_EDGE (store_data.edge_list, x),
! 				       &store_data);
      }
  
    if (update_flow)
      commit_edge_insertions ();
  
!   free_store_memory (&store_data);
!   free_edge_list (store_data.edge_list);
    remove_fake_edges ();
    end_alias_analysis ();
  }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]